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/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,
|
|
@@ -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,
|
|
@@ -13632,6 +13646,131 @@ function unsubscribeAll(unsubscribers) {
|
|
|
13632
13646
|
return [];
|
|
13633
13647
|
}
|
|
13634
13648
|
|
|
13649
|
+
// src/instrumentation/core/channel-definitions.ts
|
|
13650
|
+
function channel(spec) {
|
|
13651
|
+
return spec;
|
|
13652
|
+
}
|
|
13653
|
+
function defineChannels(pkg, channels, options) {
|
|
13654
|
+
const { instrumentationName } = options;
|
|
13655
|
+
return Object.fromEntries(
|
|
13656
|
+
Object.entries(channels).map(([key, spec]) => {
|
|
13657
|
+
const fullChannelName = `orchestrion:${pkg}:${spec.channelName}`;
|
|
13658
|
+
if (spec.kind === "async") {
|
|
13659
|
+
const asyncSpec = spec;
|
|
13660
|
+
const tracingChannel2 = () => isomorph_default.newTracingChannel(
|
|
13661
|
+
fullChannelName
|
|
13662
|
+
);
|
|
13663
|
+
const intercept2 = (interceptor) => {
|
|
13664
|
+
const hook = tracingChannel2();
|
|
13665
|
+
return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
|
|
13666
|
+
};
|
|
13667
|
+
};
|
|
13668
|
+
return [
|
|
13669
|
+
key,
|
|
13670
|
+
{
|
|
13671
|
+
...asyncSpec,
|
|
13672
|
+
instrumentationName,
|
|
13673
|
+
intercept: intercept2,
|
|
13674
|
+
invoke: (target, thisArg, args, additional) => {
|
|
13675
|
+
const hook = tracingChannel2();
|
|
13676
|
+
return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
|
|
13677
|
+
},
|
|
13678
|
+
tracingChannel: tracingChannel2,
|
|
13679
|
+
tracePromise: (fn, context) => tracingChannel2().tracePromise(
|
|
13680
|
+
fn,
|
|
13681
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
13682
|
+
context
|
|
13683
|
+
)
|
|
13684
|
+
}
|
|
13685
|
+
];
|
|
13686
|
+
}
|
|
13687
|
+
const syncSpec = spec;
|
|
13688
|
+
const tracingChannel = () => isomorph_default.newTracingChannel(
|
|
13689
|
+
fullChannelName
|
|
13690
|
+
);
|
|
13691
|
+
const intercept = (interceptor) => {
|
|
13692
|
+
const hook = tracingChannel();
|
|
13693
|
+
return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
|
|
13694
|
+
};
|
|
13695
|
+
};
|
|
13696
|
+
return [
|
|
13697
|
+
key,
|
|
13698
|
+
{
|
|
13699
|
+
...syncSpec,
|
|
13700
|
+
instrumentationName,
|
|
13701
|
+
intercept,
|
|
13702
|
+
invoke: (target, thisArg, args, additional) => {
|
|
13703
|
+
const hook = tracingChannel();
|
|
13704
|
+
return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
|
|
13705
|
+
},
|
|
13706
|
+
tracingChannel,
|
|
13707
|
+
traceSync: (fn, context) => tracingChannel().traceSync(
|
|
13708
|
+
fn,
|
|
13709
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
13710
|
+
context
|
|
13711
|
+
)
|
|
13712
|
+
}
|
|
13713
|
+
];
|
|
13714
|
+
})
|
|
13715
|
+
);
|
|
13716
|
+
}
|
|
13717
|
+
|
|
13718
|
+
// src/instrumentation/plugins/openai-channels.ts
|
|
13719
|
+
var openAIChannels = defineChannels(
|
|
13720
|
+
"openai",
|
|
13721
|
+
{
|
|
13722
|
+
filesCreateTraced: channel({
|
|
13723
|
+
channelName: "files.create-traced",
|
|
13724
|
+
kind: "async"
|
|
13725
|
+
}),
|
|
13726
|
+
batchesRetrieveTraced: channel({
|
|
13727
|
+
channelName: "batches.retrieve-traced",
|
|
13728
|
+
kind: "async"
|
|
13729
|
+
}),
|
|
13730
|
+
batchesCompleteTrace: channel({
|
|
13731
|
+
channelName: "batches.complete-trace",
|
|
13732
|
+
kind: "async"
|
|
13733
|
+
}),
|
|
13734
|
+
chatCompletionsCreate: channel({
|
|
13735
|
+
channelName: "chat.completions.create",
|
|
13736
|
+
kind: "async"
|
|
13737
|
+
}),
|
|
13738
|
+
embeddingsCreate: channel({
|
|
13739
|
+
channelName: "embeddings.create",
|
|
13740
|
+
kind: "async"
|
|
13741
|
+
}),
|
|
13742
|
+
betaChatCompletionsParse: channel({
|
|
13743
|
+
channelName: "beta.chat.completions.parse",
|
|
13744
|
+
kind: "async"
|
|
13745
|
+
}),
|
|
13746
|
+
betaChatCompletionsStream: channel({
|
|
13747
|
+
channelName: "beta.chat.completions.stream",
|
|
13748
|
+
kind: "sync-stream"
|
|
13749
|
+
}),
|
|
13750
|
+
moderationsCreate: channel({
|
|
13751
|
+
channelName: "moderations.create",
|
|
13752
|
+
kind: "async"
|
|
13753
|
+
}),
|
|
13754
|
+
responsesCreate: channel({
|
|
13755
|
+
channelName: "responses.create",
|
|
13756
|
+
kind: "async"
|
|
13757
|
+
}),
|
|
13758
|
+
responsesStream: channel({
|
|
13759
|
+
channelName: "responses.stream",
|
|
13760
|
+
kind: "sync-stream"
|
|
13761
|
+
}),
|
|
13762
|
+
responsesParse: channel({
|
|
13763
|
+
channelName: "responses.parse",
|
|
13764
|
+
kind: "async"
|
|
13765
|
+
}),
|
|
13766
|
+
responsesCompact: channel({
|
|
13767
|
+
channelName: "responses.compact",
|
|
13768
|
+
kind: "async"
|
|
13769
|
+
})
|
|
13770
|
+
},
|
|
13771
|
+
{ instrumentationName: INSTRUMENTATION_NAMES.OPENAI }
|
|
13772
|
+
);
|
|
13773
|
+
|
|
13635
13774
|
// src/wrappers/attachment-utils.ts
|
|
13636
13775
|
function getExtensionFromMediaType(mediaType) {
|
|
13637
13776
|
const extensionMap = {
|
|
@@ -13807,118 +13946,91 @@ function processInputAttachments(input) {
|
|
|
13807
13946
|
return processNode(input);
|
|
13808
13947
|
}
|
|
13809
13948
|
|
|
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
|
-
];
|
|
13949
|
+
// src/instrumentation/plugins/openai-span-data.ts
|
|
13950
|
+
var OPENAI_METADATA_KEYS = [
|
|
13951
|
+
"model",
|
|
13952
|
+
"temperature",
|
|
13953
|
+
"top_p",
|
|
13954
|
+
"max_tokens",
|
|
13955
|
+
"frequency_penalty",
|
|
13956
|
+
"presence_penalty",
|
|
13957
|
+
"stop",
|
|
13958
|
+
"response_format",
|
|
13959
|
+
"tools",
|
|
13960
|
+
"tool_choice",
|
|
13961
|
+
"parallel_tool_calls",
|
|
13962
|
+
"max_tool_calls"
|
|
13963
|
+
];
|
|
13964
|
+
function batchMetadata(params) {
|
|
13965
|
+
const metadata = { provider: "openai" };
|
|
13966
|
+
for (const key of OPENAI_METADATA_KEYS) {
|
|
13967
|
+
try {
|
|
13968
|
+
const value = Reflect.get(params, key);
|
|
13969
|
+
if (value !== void 0) {
|
|
13970
|
+
metadata[key] = value;
|
|
13847
13971
|
}
|
|
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
|
-
|
|
13972
|
+
} catch {
|
|
13973
|
+
}
|
|
13974
|
+
}
|
|
13975
|
+
return metadata;
|
|
13976
|
+
}
|
|
13977
|
+
function extractOpenAIBatchInput(endpoint, params) {
|
|
13978
|
+
const input = endpoint === "/v1/chat/completions" ? params.messages : params.input;
|
|
13979
|
+
return {
|
|
13980
|
+
input: processInputAttachments(input),
|
|
13981
|
+
metadata: batchMetadata(params)
|
|
13982
|
+
};
|
|
13983
|
+
}
|
|
13984
|
+
function extractOpenAIChatInput(params) {
|
|
13985
|
+
const { messages, ...metadata } = params;
|
|
13986
|
+
return {
|
|
13987
|
+
input: processInputAttachments(messages),
|
|
13988
|
+
metadata: { ...metadata, provider: "openai" }
|
|
13989
|
+
};
|
|
13990
|
+
}
|
|
13991
|
+
function extractOpenAIResponsesInput(params) {
|
|
13992
|
+
const { input, ...metadata } = params;
|
|
13993
|
+
return {
|
|
13994
|
+
input: processInputAttachments(input),
|
|
13995
|
+
metadata: { ...metadata, provider: "openai" }
|
|
13996
|
+
};
|
|
13997
|
+
}
|
|
13998
|
+
function extractOpenAIResponsesMetadata(result) {
|
|
13999
|
+
if (!result) {
|
|
14000
|
+
return void 0;
|
|
14001
|
+
}
|
|
14002
|
+
const { output: _output, usage: _usage, ...metadata } = result;
|
|
14003
|
+
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
14004
|
+
}
|
|
14005
|
+
function processImagesInOutput(output) {
|
|
14006
|
+
if (Array.isArray(output)) {
|
|
14007
|
+
return output.map(processImagesInOutput);
|
|
14008
|
+
}
|
|
14009
|
+
if (isObject(output) && output.type === "image_generation_call" && typeof output.result === "string" && output.result) {
|
|
14010
|
+
const fileExtension = output.output_format || "png";
|
|
14011
|
+
const contentType = `image/${fileExtension}`;
|
|
14012
|
+
const baseFilename = typeof output.revised_prompt === "string" ? output.revised_prompt.slice(0, 50).replace(/[^a-zA-Z0-9]/g, "_") : "generated_image";
|
|
14013
|
+
let binaryString;
|
|
14014
|
+
try {
|
|
14015
|
+
binaryString = atob(output.result);
|
|
14016
|
+
} catch {
|
|
14017
|
+
return output;
|
|
14018
|
+
}
|
|
14019
|
+
const bytes = new Uint8Array(binaryString.length);
|
|
14020
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
14021
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
14022
|
+
}
|
|
14023
|
+
return {
|
|
14024
|
+
...output,
|
|
14025
|
+
result: new Attachment({
|
|
14026
|
+
data: new Blob([bytes], { type: contentType }),
|
|
14027
|
+
filename: `${baseFilename}.${fileExtension}`,
|
|
14028
|
+
contentType
|
|
14029
|
+
})
|
|
14030
|
+
};
|
|
14031
|
+
}
|
|
14032
|
+
return output;
|
|
13877
14033
|
}
|
|
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
14034
|
|
|
13923
14035
|
// src/openai-utils.ts
|
|
13924
14036
|
var BRAINTRUST_CACHED_STREAM_METRIC = "__braintrust_cached_metric";
|
|
@@ -13975,23 +14087,573 @@ function getCachedMetricFromHeaders(headers) {
|
|
|
13975
14087
|
return parseCachedHeader(headers.get(LEGACY_CACHED_HEADER));
|
|
13976
14088
|
}
|
|
13977
14089
|
|
|
14090
|
+
// src/instrumentation/plugins/openai-batch-instrumentation.ts
|
|
14091
|
+
var SUPPORTED_ENDPOINTS = /* @__PURE__ */ new Set(["/v1/chat/completions", "/v1/responses"]);
|
|
14092
|
+
var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
|
|
14093
|
+
"completed",
|
|
14094
|
+
"failed",
|
|
14095
|
+
"expired",
|
|
14096
|
+
"cancelled"
|
|
14097
|
+
]);
|
|
14098
|
+
var pendingBatchTraces = /* @__PURE__ */ new Map();
|
|
14099
|
+
function read(value, key) {
|
|
14100
|
+
if (!isObject(value)) {
|
|
14101
|
+
return void 0;
|
|
14102
|
+
}
|
|
14103
|
+
try {
|
|
14104
|
+
return Reflect.get(value, key);
|
|
14105
|
+
} catch {
|
|
14106
|
+
return void 0;
|
|
14107
|
+
}
|
|
14108
|
+
}
|
|
14109
|
+
function isBatchRecordIterable(value) {
|
|
14110
|
+
if (value === null || typeof value !== "object" && typeof value !== "function") {
|
|
14111
|
+
return false;
|
|
14112
|
+
}
|
|
14113
|
+
return typeof read(value, Symbol.iterator) === "function" || typeof read(value, Symbol.asyncIterator) === "function";
|
|
14114
|
+
}
|
|
14115
|
+
function validCustomId(value) {
|
|
14116
|
+
return typeof value === "string" && value.length > 0 && value.length <= 64;
|
|
14117
|
+
}
|
|
14118
|
+
function logBatchInstrumentationError(context, error) {
|
|
14119
|
+
debugLogger.debug(`OpenAI Batch instrumentation ${context}:`, error);
|
|
14120
|
+
}
|
|
14121
|
+
async function exportParent(parent) {
|
|
14122
|
+
if ("toStr" in parent && typeof parent.toStr === "function") {
|
|
14123
|
+
return parent.toStr();
|
|
14124
|
+
}
|
|
14125
|
+
if ("export" in parent && typeof parent.export === "function") {
|
|
14126
|
+
return await parent.export();
|
|
14127
|
+
}
|
|
14128
|
+
return void 0;
|
|
14129
|
+
}
|
|
14130
|
+
async function deterministicDigest(namespace, ...parts) {
|
|
14131
|
+
const encoded = new TextEncoder().encode(
|
|
14132
|
+
[namespace, ...parts].map((part) => `${part.length}:${part}`).join("\0")
|
|
14133
|
+
);
|
|
14134
|
+
return new Uint8Array(
|
|
14135
|
+
await globalThis.crypto.subtle.digest("SHA-256", encoded)
|
|
14136
|
+
);
|
|
14137
|
+
}
|
|
14138
|
+
function digestHex(bytes, length) {
|
|
14139
|
+
return Array.from(bytes.slice(0, length)).map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
14140
|
+
}
|
|
14141
|
+
function digestUuid(bytes) {
|
|
14142
|
+
const hex = digestHex(bytes, 16);
|
|
14143
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
14144
|
+
}
|
|
14145
|
+
async function batchSpanIds(inputFileId) {
|
|
14146
|
+
const [row, span, root] = await Promise.all([
|
|
14147
|
+
deterministicDigest("openai:batch:row", inputFileId),
|
|
14148
|
+
deterministicDigest("openai:batch:span", inputFileId),
|
|
14149
|
+
deterministicDigest("openai:batch:root", inputFileId)
|
|
14150
|
+
]);
|
|
14151
|
+
return {
|
|
14152
|
+
rowId: digestUuid(row),
|
|
14153
|
+
spanId: digestHex(span, 8),
|
|
14154
|
+
rootSpanId: digestHex(root, 16)
|
|
14155
|
+
};
|
|
14156
|
+
}
|
|
14157
|
+
async function childSpanIds(inputFileId, customId) {
|
|
14158
|
+
const [row, span] = await Promise.all([
|
|
14159
|
+
deterministicDigest("openai:batch:child:row", inputFileId, customId),
|
|
14160
|
+
deterministicDigest("openai:batch:child:span", inputFileId, customId)
|
|
14161
|
+
]);
|
|
14162
|
+
return { rowId: digestUuid(row), spanId: digestHex(span, 8) };
|
|
14163
|
+
}
|
|
14164
|
+
async function startBatchSpan(context) {
|
|
14165
|
+
const ids = await batchSpanIds(context.inputFileId);
|
|
14166
|
+
const parent = SpanComponentsV4.fromStr(context.parent);
|
|
14167
|
+
const hasParentSpan = Boolean(
|
|
14168
|
+
parent.data.row_id && parent.data.span_id && parent.data.root_span_id
|
|
14169
|
+
);
|
|
14170
|
+
return withCurrent(
|
|
14171
|
+
NOOP_SPAN,
|
|
14172
|
+
() => _internalStartSpanWithInitialMergeAndParentSpanIds(
|
|
14173
|
+
withSpanInstrumentationName(
|
|
14174
|
+
{
|
|
14175
|
+
name: "openai.batch",
|
|
14176
|
+
type: "task" /* TASK */,
|
|
14177
|
+
parent: context.parent,
|
|
14178
|
+
...!hasParentSpan ? {
|
|
14179
|
+
parentSpanIds: {
|
|
14180
|
+
parentSpanIds: [],
|
|
14181
|
+
rootSpanId: ids.rootSpanId
|
|
14182
|
+
}
|
|
14183
|
+
} : {},
|
|
14184
|
+
spanId: ids.spanId,
|
|
14185
|
+
startTime: context.taskStartTime,
|
|
14186
|
+
event: {
|
|
14187
|
+
id: ids.rowId,
|
|
14188
|
+
metadata: {
|
|
14189
|
+
endpoint: context.endpoint,
|
|
14190
|
+
input_file_id: context.inputFileId,
|
|
14191
|
+
provider: "openai"
|
|
14192
|
+
}
|
|
14193
|
+
}
|
|
14194
|
+
},
|
|
14195
|
+
INSTRUMENTATION_NAMES.OPENAI
|
|
14196
|
+
)
|
|
14197
|
+
)
|
|
14198
|
+
);
|
|
14199
|
+
}
|
|
14200
|
+
async function startBatchChild(context, taskParent, input) {
|
|
14201
|
+
const ids = await childSpanIds(context.inputFileId, input.customId);
|
|
14202
|
+
return withCurrent(
|
|
14203
|
+
NOOP_SPAN,
|
|
14204
|
+
() => _internalStartSpanWithInitialMerge(
|
|
14205
|
+
withSpanInstrumentationName(
|
|
14206
|
+
{
|
|
14207
|
+
name: context.endpoint === "/v1/chat/completions" ? "Chat Completion" : "openai.responses.create",
|
|
14208
|
+
type: "llm" /* LLM */,
|
|
14209
|
+
parent: taskParent,
|
|
14210
|
+
spanId: ids.spanId,
|
|
14211
|
+
startTime: context.childStartTime,
|
|
14212
|
+
event: {
|
|
14213
|
+
id: ids.rowId,
|
|
14214
|
+
...input.spanData?.input !== void 0 ? { input: input.spanData.input } : {},
|
|
14215
|
+
metadata: {
|
|
14216
|
+
...input.spanData?.metadata,
|
|
14217
|
+
custom_id: input.customId,
|
|
14218
|
+
provider: "openai"
|
|
14219
|
+
}
|
|
14220
|
+
}
|
|
14221
|
+
},
|
|
14222
|
+
INSTRUMENTATION_NAMES.OPENAI
|
|
14223
|
+
)
|
|
14224
|
+
)
|
|
14225
|
+
);
|
|
14226
|
+
}
|
|
14227
|
+
async function* jsonlRecords(file, onIssue = () => {
|
|
14228
|
+
}) {
|
|
14229
|
+
const resolvedFile = await file;
|
|
14230
|
+
if (typeof resolvedFile === "string") {
|
|
14231
|
+
for (const line of resolvedFile.split("\n")) {
|
|
14232
|
+
if (!line.trim()) {
|
|
14233
|
+
continue;
|
|
14234
|
+
}
|
|
14235
|
+
try {
|
|
14236
|
+
yield JSON.parse(line.replace(/\r$/, ""));
|
|
14237
|
+
} catch (error) {
|
|
14238
|
+
logBatchInstrumentationError("skipped malformed JSONL", error);
|
|
14239
|
+
onIssue(new Error("OpenAI Batch file contains malformed JSONL"));
|
|
14240
|
+
}
|
|
14241
|
+
}
|
|
14242
|
+
return;
|
|
14243
|
+
}
|
|
14244
|
+
const body = read(resolvedFile, "body");
|
|
14245
|
+
const getReader = read(body, "getReader");
|
|
14246
|
+
if (isObject(body) && typeof getReader === "function") {
|
|
14247
|
+
let reader;
|
|
14248
|
+
try {
|
|
14249
|
+
reader = Reflect.apply(getReader, body, []);
|
|
14250
|
+
const decoder2 = new TextDecoder();
|
|
14251
|
+
let pending = "";
|
|
14252
|
+
while (true) {
|
|
14253
|
+
const readChunk = read(reader, "read");
|
|
14254
|
+
if (typeof readChunk !== "function") {
|
|
14255
|
+
throw new Error("Response body stream has no read method");
|
|
14256
|
+
}
|
|
14257
|
+
const chunk = await Reflect.apply(readChunk, reader, []);
|
|
14258
|
+
if (!isObject(chunk)) {
|
|
14259
|
+
throw new Error("Response body stream returned an invalid chunk");
|
|
14260
|
+
}
|
|
14261
|
+
if (chunk.done === true) {
|
|
14262
|
+
pending += decoder2.decode();
|
|
14263
|
+
break;
|
|
14264
|
+
}
|
|
14265
|
+
if (!(chunk.value instanceof Uint8Array)) {
|
|
14266
|
+
throw new Error("Response body stream returned a non-byte chunk");
|
|
14267
|
+
}
|
|
14268
|
+
pending += decoder2.decode(chunk.value, { stream: true });
|
|
14269
|
+
let newline = pending.indexOf("\n");
|
|
14270
|
+
while (newline !== -1) {
|
|
14271
|
+
const line = pending.slice(0, newline).replace(/\r$/, "");
|
|
14272
|
+
pending = pending.slice(newline + 1);
|
|
14273
|
+
if (line.trim()) {
|
|
14274
|
+
try {
|
|
14275
|
+
yield JSON.parse(line);
|
|
14276
|
+
} catch (error) {
|
|
14277
|
+
logBatchInstrumentationError("skipped malformed JSONL", error);
|
|
14278
|
+
onIssue(new Error("OpenAI Batch file contains malformed JSONL"));
|
|
14279
|
+
}
|
|
14280
|
+
}
|
|
14281
|
+
newline = pending.indexOf("\n");
|
|
14282
|
+
}
|
|
14283
|
+
}
|
|
14284
|
+
if (pending.trim()) {
|
|
14285
|
+
try {
|
|
14286
|
+
yield JSON.parse(pending.replace(/\r$/, ""));
|
|
14287
|
+
} catch (error) {
|
|
14288
|
+
logBatchInstrumentationError("skipped malformed JSONL", error);
|
|
14289
|
+
onIssue(new Error("OpenAI Batch file contains malformed JSONL"));
|
|
14290
|
+
}
|
|
14291
|
+
}
|
|
14292
|
+
} catch (error) {
|
|
14293
|
+
logBatchInstrumentationError("could not read JSONL response body", error);
|
|
14294
|
+
onIssue(new Error("OpenAI Batch response body could not be read"));
|
|
14295
|
+
} finally {
|
|
14296
|
+
const releaseLock = read(reader, "releaseLock");
|
|
14297
|
+
if (typeof releaseLock === "function") {
|
|
14298
|
+
try {
|
|
14299
|
+
Reflect.apply(releaseLock, reader, []);
|
|
14300
|
+
} catch (error) {
|
|
14301
|
+
logBatchInstrumentationError(
|
|
14302
|
+
"could not release stream reader",
|
|
14303
|
+
error
|
|
14304
|
+
);
|
|
14305
|
+
}
|
|
14306
|
+
}
|
|
14307
|
+
}
|
|
14308
|
+
return;
|
|
14309
|
+
}
|
|
14310
|
+
if (isBatchRecordIterable(resolvedFile)) {
|
|
14311
|
+
for await (const record of resolvedFile) {
|
|
14312
|
+
yield record;
|
|
14313
|
+
}
|
|
14314
|
+
return;
|
|
14315
|
+
}
|
|
14316
|
+
logBatchInstrumentationError("skipped invalid JSONL source", resolvedFile);
|
|
14317
|
+
onIssue(new Error("OpenAI Batch file source is invalid"));
|
|
14318
|
+
}
|
|
14319
|
+
async function readBatchInputs(file) {
|
|
14320
|
+
const inputs = /* @__PURE__ */ new Map();
|
|
14321
|
+
const issues = [];
|
|
14322
|
+
let endpoint;
|
|
14323
|
+
try {
|
|
14324
|
+
for await (const value of jsonlRecords(
|
|
14325
|
+
file,
|
|
14326
|
+
(issue) => issues.push(issue)
|
|
14327
|
+
)) {
|
|
14328
|
+
const customId = read(value, "custom_id");
|
|
14329
|
+
const url = read(value, "url");
|
|
14330
|
+
const body = read(value, "body");
|
|
14331
|
+
if (!validCustomId(customId) || inputs.has(customId) || read(value, "method") !== "POST" || typeof url !== "string" || !SUPPORTED_ENDPOINTS.has(url) || endpoint !== void 0 && endpoint !== url || !isObject(body)) {
|
|
14332
|
+
issues.push(new Error("OpenAI Batch input contains an invalid record"));
|
|
14333
|
+
continue;
|
|
14334
|
+
}
|
|
14335
|
+
endpoint = url;
|
|
14336
|
+
let spanData;
|
|
14337
|
+
try {
|
|
14338
|
+
spanData = extractOpenAIBatchInput(url, body);
|
|
14339
|
+
} catch (error) {
|
|
14340
|
+
logBatchInstrumentationError("could not extract batch input", error);
|
|
14341
|
+
}
|
|
14342
|
+
inputs.set(customId, { customId, spanData });
|
|
14343
|
+
}
|
|
14344
|
+
} catch (error) {
|
|
14345
|
+
logBatchInstrumentationError("could not process input file", error);
|
|
14346
|
+
issues.push(new Error("OpenAI Batch input file could not be processed"));
|
|
14347
|
+
}
|
|
14348
|
+
if (!endpoint || inputs.size === 0) {
|
|
14349
|
+
issues.push(new Error("OpenAI Batch input contains no supported records"));
|
|
14350
|
+
}
|
|
14351
|
+
return { endpoint, inputs, issues };
|
|
14352
|
+
}
|
|
14353
|
+
async function writePendingSpans(trace, endTime) {
|
|
14354
|
+
const task = await startBatchSpan(trace.context);
|
|
14355
|
+
const taskParent = await task.export();
|
|
14356
|
+
for (const input of trace.inputs.values()) {
|
|
14357
|
+
try {
|
|
14358
|
+
const child = await startBatchChild(trace.context, taskParent, input);
|
|
14359
|
+
if (endTime !== void 0) {
|
|
14360
|
+
child.end({ endTime });
|
|
14361
|
+
}
|
|
14362
|
+
} catch (error) {
|
|
14363
|
+
logBatchInstrumentationError("could not write batch request span", error);
|
|
14364
|
+
}
|
|
14365
|
+
}
|
|
14366
|
+
if (endTime !== void 0) {
|
|
14367
|
+
if (trace.status && trace.status !== "completed") {
|
|
14368
|
+
task.log({ error: new Error(`OpenAI Batch ${trace.status}`) });
|
|
14369
|
+
}
|
|
14370
|
+
task.end({ endTime });
|
|
14371
|
+
}
|
|
14372
|
+
}
|
|
14373
|
+
var interceptOpenAIFilesCreateTraced = async (target, thisArg, args) => {
|
|
14374
|
+
const startTime = getCurrentUnixTimestamp();
|
|
14375
|
+
const inputPromise = readBatchInputs(args[0].inputFileContent);
|
|
14376
|
+
const parentPromise = exportParent(args[0].parent);
|
|
14377
|
+
const file = await Reflect.apply(target, thisArg, args);
|
|
14378
|
+
try {
|
|
14379
|
+
const inputFileId = read(file, "id");
|
|
14380
|
+
const [inputData, exportedParent2] = await Promise.all([
|
|
14381
|
+
inputPromise,
|
|
14382
|
+
parentPromise
|
|
14383
|
+
]);
|
|
14384
|
+
if (typeof inputFileId !== "string" || !exportedParent2 || !inputData.endpoint || inputData.issues.length > 0) {
|
|
14385
|
+
if (inputData.issues[0]) {
|
|
14386
|
+
logBatchInstrumentationError(
|
|
14387
|
+
"skipped invalid input file",
|
|
14388
|
+
inputData.issues[0]
|
|
14389
|
+
);
|
|
14390
|
+
}
|
|
14391
|
+
return file;
|
|
14392
|
+
}
|
|
14393
|
+
const trace = {
|
|
14394
|
+
context: {
|
|
14395
|
+
inputFileId,
|
|
14396
|
+
endpoint: inputData.endpoint,
|
|
14397
|
+
parent: exportedParent2,
|
|
14398
|
+
taskStartTime: startTime,
|
|
14399
|
+
childStartTime: startTime
|
|
14400
|
+
},
|
|
14401
|
+
inputs: inputData.inputs
|
|
14402
|
+
};
|
|
14403
|
+
pendingBatchTraces.set(inputFileId, trace);
|
|
14404
|
+
await writePendingSpans(trace);
|
|
14405
|
+
} catch (error) {
|
|
14406
|
+
logBatchInstrumentationError("could not start batch spans", error);
|
|
14407
|
+
}
|
|
14408
|
+
return file;
|
|
14409
|
+
};
|
|
14410
|
+
function validTimestamp(value) {
|
|
14411
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0;
|
|
14412
|
+
}
|
|
14413
|
+
function terminalEndTime(batch, startTime) {
|
|
14414
|
+
let timestamp;
|
|
14415
|
+
switch (batch.status) {
|
|
14416
|
+
case "completed":
|
|
14417
|
+
timestamp = batch.completed_at;
|
|
14418
|
+
break;
|
|
14419
|
+
case "failed":
|
|
14420
|
+
timestamp = batch.failed_at;
|
|
14421
|
+
break;
|
|
14422
|
+
case "expired":
|
|
14423
|
+
timestamp = batch.expired_at;
|
|
14424
|
+
break;
|
|
14425
|
+
default:
|
|
14426
|
+
timestamp = batch.cancelled_at;
|
|
14427
|
+
}
|
|
14428
|
+
return validTimestamp(timestamp) ? Math.max(timestamp, startTime) : Math.max(getCurrentUnixTimestamp(), startTime);
|
|
14429
|
+
}
|
|
14430
|
+
async function updateBatchTimestamps(batch) {
|
|
14431
|
+
const trace = pendingBatchTraces.get(batch.input_file_id);
|
|
14432
|
+
if (!trace || trace.context.endpoint !== batch.endpoint) {
|
|
14433
|
+
return;
|
|
14434
|
+
}
|
|
14435
|
+
if (validTimestamp(batch.created_at)) {
|
|
14436
|
+
trace.context.taskStartTime = batch.created_at;
|
|
14437
|
+
}
|
|
14438
|
+
trace.context.childStartTime = validTimestamp(batch.in_progress_at) ? Math.max(batch.in_progress_at, trace.context.taskStartTime) : trace.context.taskStartTime;
|
|
14439
|
+
trace.status = batch.status;
|
|
14440
|
+
if (TERMINAL_STATUSES.has(batch.status)) {
|
|
14441
|
+
trace.endTime = terminalEndTime(batch, trace.context.childStartTime);
|
|
14442
|
+
}
|
|
14443
|
+
await writePendingSpans(trace, trace.endTime);
|
|
14444
|
+
}
|
|
14445
|
+
var interceptOpenAIBatchesRetrieveTraced = (target, thisArg, args) => Promise.resolve(Reflect.apply(target, thisArg, args)).then(async (batch) => {
|
|
14446
|
+
try {
|
|
14447
|
+
await updateBatchTimestamps(batch);
|
|
14448
|
+
} catch (error) {
|
|
14449
|
+
logBatchInstrumentationError("could not update batch timestamps", error);
|
|
14450
|
+
}
|
|
14451
|
+
return batch;
|
|
14452
|
+
});
|
|
14453
|
+
function errorFromResult(result) {
|
|
14454
|
+
const error = read(result.value, "error");
|
|
14455
|
+
if (isObject(error)) {
|
|
14456
|
+
const message = read(error, "message");
|
|
14457
|
+
return new Error(
|
|
14458
|
+
typeof message === "string" ? message : "OpenAI Batch request failed"
|
|
14459
|
+
);
|
|
14460
|
+
}
|
|
14461
|
+
const response = read(result.value, "response");
|
|
14462
|
+
const statusCode = read(response, "status_code");
|
|
14463
|
+
if (result.source === "error" || typeof statusCode === "number" && (statusCode < 200 || statusCode >= 300)) {
|
|
14464
|
+
const message = read(read(read(response, "body"), "error"), "message");
|
|
14465
|
+
return new Error(
|
|
14466
|
+
typeof message === "string" ? message : "OpenAI Batch request failed"
|
|
14467
|
+
);
|
|
14468
|
+
}
|
|
14469
|
+
return void 0;
|
|
14470
|
+
}
|
|
14471
|
+
async function completeBatchResult(context, taskParent, endTime, input, result) {
|
|
14472
|
+
const child = await startBatchChild(context, taskParent, input);
|
|
14473
|
+
try {
|
|
14474
|
+
const resultError = errorFromResult(result);
|
|
14475
|
+
const responseBody = read(read(result.value, "response"), "body");
|
|
14476
|
+
if (resultError) {
|
|
14477
|
+
child.log({ error: resultError });
|
|
14478
|
+
} else if (isObject(responseBody)) {
|
|
14479
|
+
const model = read(responseBody, "model");
|
|
14480
|
+
child.log({
|
|
14481
|
+
output: context.endpoint === "/v1/chat/completions" ? read(responseBody, "choices") : processImagesInOutput(read(responseBody, "output")),
|
|
14482
|
+
...typeof model === "string" ? { metadata: { model } } : {},
|
|
14483
|
+
metrics: parseMetricsFromUsage(read(responseBody, "usage"))
|
|
14484
|
+
});
|
|
14485
|
+
} else {
|
|
14486
|
+
child.log({ error: new Error("OpenAI Batch response body is missing") });
|
|
14487
|
+
}
|
|
14488
|
+
} catch (error) {
|
|
14489
|
+
child.log({ error });
|
|
14490
|
+
} finally {
|
|
14491
|
+
child.end({ endTime });
|
|
14492
|
+
}
|
|
14493
|
+
}
|
|
14494
|
+
async function completeResultFile({
|
|
14495
|
+
context,
|
|
14496
|
+
endTime,
|
|
14497
|
+
file,
|
|
14498
|
+
inputs,
|
|
14499
|
+
issues,
|
|
14500
|
+
seen,
|
|
14501
|
+
source,
|
|
14502
|
+
taskParent
|
|
14503
|
+
}) {
|
|
14504
|
+
if (file === void 0) {
|
|
14505
|
+
return;
|
|
14506
|
+
}
|
|
14507
|
+
for await (const value of jsonlRecords(file, (issue) => issues.push(issue))) {
|
|
14508
|
+
const customId = read(value, "custom_id");
|
|
14509
|
+
if (!validCustomId(customId) || !isObject(value)) {
|
|
14510
|
+
issues.push(
|
|
14511
|
+
new Error("OpenAI Batch result is missing a valid custom_id")
|
|
14512
|
+
);
|
|
14513
|
+
continue;
|
|
14514
|
+
}
|
|
14515
|
+
if (seen.has(customId)) {
|
|
14516
|
+
issues.push(new Error("OpenAI Batch result contains a duplicate"));
|
|
14517
|
+
continue;
|
|
14518
|
+
}
|
|
14519
|
+
const input = inputs.get(customId);
|
|
14520
|
+
if (!input) {
|
|
14521
|
+
issues.push(
|
|
14522
|
+
new Error("OpenAI Batch result does not match an input record")
|
|
14523
|
+
);
|
|
14524
|
+
continue;
|
|
14525
|
+
}
|
|
14526
|
+
seen.add(customId);
|
|
14527
|
+
await completeBatchResult(context, taskParent, endTime, input, {
|
|
14528
|
+
value,
|
|
14529
|
+
source
|
|
14530
|
+
});
|
|
14531
|
+
}
|
|
14532
|
+
}
|
|
14533
|
+
function sameInputs(first, second) {
|
|
14534
|
+
return first.size === second.size && [...first.keys()].every((customId) => second.has(customId));
|
|
14535
|
+
}
|
|
14536
|
+
async function contextForCompletion(inputFileId, inputData) {
|
|
14537
|
+
if (!inputData.endpoint || inputData.issues.length > 0) {
|
|
14538
|
+
return void 0;
|
|
14539
|
+
}
|
|
14540
|
+
const existing = pendingBatchTraces.get(inputFileId);
|
|
14541
|
+
if (existing) {
|
|
14542
|
+
if (existing.context.endpoint !== inputData.endpoint || !sameInputs(existing.inputs, inputData.inputs)) {
|
|
14543
|
+
return void 0;
|
|
14544
|
+
}
|
|
14545
|
+
return { ...existing, inputs: inputData.inputs };
|
|
14546
|
+
}
|
|
14547
|
+
const parent = await exportParent(getSpanParentObject());
|
|
14548
|
+
if (!parent) {
|
|
14549
|
+
return void 0;
|
|
14550
|
+
}
|
|
14551
|
+
const startTime = getCurrentUnixTimestamp();
|
|
14552
|
+
return {
|
|
14553
|
+
context: {
|
|
14554
|
+
inputFileId,
|
|
14555
|
+
endpoint: inputData.endpoint,
|
|
14556
|
+
parent,
|
|
14557
|
+
taskStartTime: startTime,
|
|
14558
|
+
childStartTime: startTime
|
|
14559
|
+
},
|
|
14560
|
+
inputs: inputData.inputs
|
|
14561
|
+
};
|
|
14562
|
+
}
|
|
14563
|
+
async function completeBatch(args) {
|
|
14564
|
+
const inputData = await readBatchInputs(args.inputFileContent);
|
|
14565
|
+
const trace = await contextForCompletion(args.inputFileId, inputData);
|
|
14566
|
+
if (!trace) {
|
|
14567
|
+
logBatchInstrumentationError(
|
|
14568
|
+
"left batch spans pending",
|
|
14569
|
+
inputData.issues[0] ?? new Error("OpenAI Batch input does not match")
|
|
14570
|
+
);
|
|
14571
|
+
return;
|
|
14572
|
+
}
|
|
14573
|
+
const endTime = trace.endTime ?? getCurrentUnixTimestamp();
|
|
14574
|
+
const task = await startBatchSpan(trace.context);
|
|
14575
|
+
const taskParent = await task.export();
|
|
14576
|
+
const issues = [];
|
|
14577
|
+
const seen = /* @__PURE__ */ new Set();
|
|
14578
|
+
await Promise.all([
|
|
14579
|
+
completeResultFile({
|
|
14580
|
+
context: trace.context,
|
|
14581
|
+
endTime,
|
|
14582
|
+
file: args.outputFileContent,
|
|
14583
|
+
inputs: trace.inputs,
|
|
14584
|
+
issues,
|
|
14585
|
+
seen,
|
|
14586
|
+
source: "output",
|
|
14587
|
+
taskParent
|
|
14588
|
+
}),
|
|
14589
|
+
completeResultFile({
|
|
14590
|
+
context: trace.context,
|
|
14591
|
+
endTime,
|
|
14592
|
+
file: args.errorFileContent,
|
|
14593
|
+
inputs: trace.inputs,
|
|
14594
|
+
issues,
|
|
14595
|
+
seen,
|
|
14596
|
+
source: "error",
|
|
14597
|
+
taskParent
|
|
14598
|
+
})
|
|
14599
|
+
]);
|
|
14600
|
+
if (issues.length > 0) {
|
|
14601
|
+
logBatchInstrumentationError("left batch spans pending", issues[0]);
|
|
14602
|
+
return;
|
|
14603
|
+
}
|
|
14604
|
+
const missing = [...trace.inputs.values()].filter(
|
|
14605
|
+
({ customId }) => !seen.has(customId)
|
|
14606
|
+
);
|
|
14607
|
+
if (!trace.status || trace.status === "completed") {
|
|
14608
|
+
if (missing.length > 0) {
|
|
14609
|
+
logBatchInstrumentationError(
|
|
14610
|
+
"left batch spans pending",
|
|
14611
|
+
new Error("OpenAI Batch result files are incomplete")
|
|
14612
|
+
);
|
|
14613
|
+
return;
|
|
14614
|
+
}
|
|
14615
|
+
} else {
|
|
14616
|
+
for (const input of missing) {
|
|
14617
|
+
const child = await startBatchChild(trace.context, taskParent, input);
|
|
14618
|
+
child.log({ error: new Error(`OpenAI Batch ${trace.status}`) });
|
|
14619
|
+
child.end({ endTime });
|
|
14620
|
+
}
|
|
14621
|
+
task.log({ error: new Error(`OpenAI Batch ${trace.status}`) });
|
|
14622
|
+
}
|
|
14623
|
+
task.end({ endTime });
|
|
14624
|
+
pendingBatchTraces.delete(args.inputFileId);
|
|
14625
|
+
}
|
|
14626
|
+
var interceptOpenAIBatchTraceComplete = (target, thisArg, args) => Promise.resolve(Reflect.apply(target, thisArg, args)).then(async (result) => {
|
|
14627
|
+
try {
|
|
14628
|
+
await completeBatch(args[0]);
|
|
14629
|
+
} catch (error) {
|
|
14630
|
+
logBatchInstrumentationError("could not complete batch", error);
|
|
14631
|
+
}
|
|
14632
|
+
return result;
|
|
14633
|
+
});
|
|
14634
|
+
|
|
13978
14635
|
// src/instrumentation/plugins/openai-plugin.ts
|
|
13979
14636
|
var OpenAIPlugin = class extends BasePlugin {
|
|
13980
14637
|
constructor() {
|
|
13981
14638
|
super();
|
|
13982
14639
|
}
|
|
13983
14640
|
onEnable() {
|
|
14641
|
+
this.unsubscribers.push(
|
|
14642
|
+
openAIChannels.filesCreateTraced.intercept(
|
|
14643
|
+
interceptOpenAIFilesCreateTraced
|
|
14644
|
+
),
|
|
14645
|
+
openAIChannels.batchesRetrieveTraced.intercept(
|
|
14646
|
+
interceptOpenAIBatchesRetrieveTraced
|
|
14647
|
+
),
|
|
14648
|
+
openAIChannels.batchesCompleteTrace.intercept(
|
|
14649
|
+
interceptOpenAIBatchTraceComplete
|
|
14650
|
+
)
|
|
14651
|
+
);
|
|
13984
14652
|
this.unsubscribers.push(
|
|
13985
14653
|
traceStreamingChannel(openAIChannels.chatCompletionsCreate, {
|
|
13986
14654
|
name: "Chat Completion",
|
|
13987
14655
|
type: "llm" /* LLM */,
|
|
13988
|
-
extractInput: ([params]) =>
|
|
13989
|
-
const { messages, ...metadata } = params;
|
|
13990
|
-
return {
|
|
13991
|
-
input: processInputAttachments(messages),
|
|
13992
|
-
metadata: { ...metadata, provider: "openai" }
|
|
13993
|
-
};
|
|
13994
|
-
},
|
|
14656
|
+
extractInput: ([params]) => extractOpenAIChatInput(params),
|
|
13995
14657
|
extractOutput: (result) => {
|
|
13996
14658
|
return result?.choices;
|
|
13997
14659
|
},
|
|
@@ -14037,13 +14699,7 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
14037
14699
|
traceStreamingChannel(openAIChannels.betaChatCompletionsParse, {
|
|
14038
14700
|
name: "Chat Completion",
|
|
14039
14701
|
type: "llm" /* LLM */,
|
|
14040
|
-
extractInput: ([params]) =>
|
|
14041
|
-
const { messages, ...metadata } = params;
|
|
14042
|
-
return {
|
|
14043
|
-
input: processInputAttachments(messages),
|
|
14044
|
-
metadata: { ...metadata, provider: "openai" }
|
|
14045
|
-
};
|
|
14046
|
-
},
|
|
14702
|
+
extractInput: ([params]) => extractOpenAIChatInput(params),
|
|
14047
14703
|
extractOutput: (result) => {
|
|
14048
14704
|
return result?.choices;
|
|
14049
14705
|
},
|
|
@@ -14065,13 +14721,7 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
14065
14721
|
traceSyncStreamChannel(openAIChannels.betaChatCompletionsStream, {
|
|
14066
14722
|
name: "Chat Completion",
|
|
14067
14723
|
type: "llm" /* LLM */,
|
|
14068
|
-
extractInput: ([params]) =>
|
|
14069
|
-
const { messages, ...metadata } = params;
|
|
14070
|
-
return {
|
|
14071
|
-
input: processInputAttachments(messages),
|
|
14072
|
-
metadata: { ...metadata, provider: "openai" }
|
|
14073
|
-
};
|
|
14074
|
-
}
|
|
14724
|
+
extractInput: ([params]) => extractOpenAIChatInput(params)
|
|
14075
14725
|
})
|
|
14076
14726
|
);
|
|
14077
14727
|
this.unsubscribers.push(
|
|
@@ -14101,23 +14751,11 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
14101
14751
|
traceStreamingChannel(openAIChannels.responsesCreate, {
|
|
14102
14752
|
name: "openai.responses.create",
|
|
14103
14753
|
type: "llm" /* LLM */,
|
|
14104
|
-
extractInput: ([params]) =>
|
|
14105
|
-
const { input, ...metadata } = params;
|
|
14106
|
-
return {
|
|
14107
|
-
input: processInputAttachments(input),
|
|
14108
|
-
metadata: { ...metadata, provider: "openai" }
|
|
14109
|
-
};
|
|
14110
|
-
},
|
|
14754
|
+
extractInput: ([params]) => extractOpenAIResponsesInput(params),
|
|
14111
14755
|
extractOutput: (result) => {
|
|
14112
14756
|
return processImagesInOutput(result?.output);
|
|
14113
14757
|
},
|
|
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
|
-
},
|
|
14758
|
+
extractMetadata: (result) => extractOpenAIResponsesMetadata(result),
|
|
14121
14759
|
extractMetrics: (result, startTime, endEvent) => {
|
|
14122
14760
|
const metrics = withCachedMetric(
|
|
14123
14761
|
parseMetricsFromUsage(result?.usage),
|
|
@@ -14136,13 +14774,7 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
14136
14774
|
traceSyncStreamChannel(openAIChannels.responsesStream, {
|
|
14137
14775
|
name: "openai.responses.create",
|
|
14138
14776
|
type: "llm" /* LLM */,
|
|
14139
|
-
extractInput: ([params]) =>
|
|
14140
|
-
const { input, ...metadata } = params;
|
|
14141
|
-
return {
|
|
14142
|
-
input: processInputAttachments(input),
|
|
14143
|
-
metadata: { ...metadata, provider: "openai" }
|
|
14144
|
-
};
|
|
14145
|
-
},
|
|
14777
|
+
extractInput: ([params]) => extractOpenAIResponsesInput(params),
|
|
14146
14778
|
extractFromEvent: (event) => {
|
|
14147
14779
|
if (event.type !== "response.completed" || !event.response) {
|
|
14148
14780
|
return {};
|
|
@@ -14165,23 +14797,11 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
14165
14797
|
traceStreamingChannel(openAIChannels.responsesParse, {
|
|
14166
14798
|
name: "openai.responses.parse",
|
|
14167
14799
|
type: "llm" /* LLM */,
|
|
14168
|
-
extractInput: ([params]) =>
|
|
14169
|
-
const { input, ...metadata } = params;
|
|
14170
|
-
return {
|
|
14171
|
-
input: processInputAttachments(input),
|
|
14172
|
-
metadata: { ...metadata, provider: "openai" }
|
|
14173
|
-
};
|
|
14174
|
-
},
|
|
14800
|
+
extractInput: ([params]) => extractOpenAIResponsesInput(params),
|
|
14175
14801
|
extractOutput: (result) => {
|
|
14176
14802
|
return processImagesInOutput(result?.output);
|
|
14177
14803
|
},
|
|
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
|
-
},
|
|
14804
|
+
extractMetadata: (result) => extractOpenAIResponsesMetadata(result),
|
|
14185
14805
|
extractMetrics: (result, startTime, endEvent) => {
|
|
14186
14806
|
const metrics = withCachedMetric(
|
|
14187
14807
|
parseMetricsFromUsage(result?.usage),
|
|
@@ -14200,23 +14820,11 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
14200
14820
|
traceAsyncChannel(openAIChannels.responsesCompact, {
|
|
14201
14821
|
name: "openai.responses.compact",
|
|
14202
14822
|
type: "llm" /* LLM */,
|
|
14203
|
-
extractInput: ([params]) =>
|
|
14204
|
-
const { input, ...metadata } = params;
|
|
14205
|
-
return {
|
|
14206
|
-
input: processInputAttachments(input),
|
|
14207
|
-
metadata: { ...metadata, provider: "openai" }
|
|
14208
|
-
};
|
|
14209
|
-
},
|
|
14823
|
+
extractInput: ([params]) => extractOpenAIResponsesInput(params),
|
|
14210
14824
|
extractOutput: (result) => {
|
|
14211
14825
|
return processImagesInOutput(result?.output);
|
|
14212
14826
|
},
|
|
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
|
-
},
|
|
14827
|
+
extractMetadata: (result) => extractOpenAIResponsesMetadata(result),
|
|
14220
14828
|
extractMetrics: (result, startTime, endEvent) => {
|
|
14221
14829
|
const metrics = withCachedMetric(
|
|
14222
14830
|
parseMetricsFromUsage(result?.usage),
|
|
@@ -14272,35 +14880,6 @@ function withCachedMetric(metrics, result, endEvent) {
|
|
|
14272
14880
|
cached
|
|
14273
14881
|
};
|
|
14274
14882
|
}
|
|
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
14883
|
function mergeLogprobTokens(existing, incoming) {
|
|
14305
14884
|
if (incoming === void 0) {
|
|
14306
14885
|
return existing;
|
|
@@ -19457,6 +20036,12 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
|
|
|
19457
20036
|
if (!activeEntry) {
|
|
19458
20037
|
return result;
|
|
19459
20038
|
}
|
|
20039
|
+
const executionOptions = args[1];
|
|
20040
|
+
const toolCallId = isObject(executionOptions) ? executionOptions.toolCallId : void 0;
|
|
20041
|
+
const toolInput = {
|
|
20042
|
+
input: serializeToolExecutionInput(args),
|
|
20043
|
+
...typeof toolCallId === "string" ? { metadata: { toolCallId } } : {}
|
|
20044
|
+
};
|
|
19460
20045
|
if (isAsyncGenerator(result)) {
|
|
19461
20046
|
return (async function* () {
|
|
19462
20047
|
const span = activeEntry.parentSpan.startSpan(
|
|
@@ -19470,7 +20055,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
|
|
|
19470
20055
|
INSTRUMENTATION_NAMES.AI_SDK
|
|
19471
20056
|
)
|
|
19472
20057
|
);
|
|
19473
|
-
span.log(
|
|
20058
|
+
span.log(toolInput);
|
|
19474
20059
|
try {
|
|
19475
20060
|
let lastValue;
|
|
19476
20061
|
for await (const value of result) {
|
|
@@ -19488,7 +20073,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
|
|
|
19488
20073
|
}
|
|
19489
20074
|
return activeEntry.parentSpan.traced(
|
|
19490
20075
|
async (span) => {
|
|
19491
|
-
span.log(
|
|
20076
|
+
span.log(toolInput);
|
|
19492
20077
|
const awaitedResult = await result;
|
|
19493
20078
|
span.log({ output: awaitedResult });
|
|
19494
20079
|
return awaitedResult;
|
|
@@ -33610,14 +34195,17 @@ function getMetricsFromResponse(response) {
|
|
|
33610
34195
|
if (!isRecord(usageMetadata)) {
|
|
33611
34196
|
continue;
|
|
33612
34197
|
}
|
|
33613
|
-
const inputTokenDetails = usageMetadata.input_token_details;
|
|
34198
|
+
const inputTokenDetails = isRecord(usageMetadata.input_token_details) ? usageMetadata.input_token_details : {};
|
|
33614
34199
|
const outputTokenDetails = usageMetadata.output_token_details;
|
|
33615
34200
|
return normalizeTokenMetrics({
|
|
33616
34201
|
total_tokens: usageMetadata.total_tokens,
|
|
33617
34202
|
prompt_tokens: usageMetadata.input_tokens,
|
|
33618
34203
|
completion_tokens: usageMetadata.output_tokens,
|
|
33619
|
-
|
|
33620
|
-
|
|
34204
|
+
// Prefer TTL-specific cache writes over the aggregate when available.
|
|
34205
|
+
prompt_cache_creation_tokens: inputTokenDetails.ephemeral_5m_input_tokens == null && inputTokenDetails.ephemeral_1h_input_tokens == null ? inputTokenDetails.cache_creation : void 0,
|
|
34206
|
+
prompt_cache_creation_5m_tokens: inputTokenDetails.ephemeral_5m_input_tokens,
|
|
34207
|
+
prompt_cache_creation_1h_tokens: inputTokenDetails.ephemeral_1h_input_tokens,
|
|
34208
|
+
prompt_cached_tokens: inputTokenDetails.cache_read,
|
|
33621
34209
|
completion_reasoning_tokens: isRecord(outputTokenDetails) ? outputTokenDetails.reasoning : void 0
|
|
33622
34210
|
});
|
|
33623
34211
|
}
|
|
@@ -34333,7 +34921,7 @@ function extractSession(event) {
|
|
|
34333
34921
|
return isObject(candidate) && typeof candidate.prompt === "function" ? candidate : void 0;
|
|
34334
34922
|
}
|
|
34335
34923
|
function isPiAgent(value) {
|
|
34336
|
-
return isObject(value) && typeof value.streamFn === "function" && typeof value.subscribe === "function";
|
|
34924
|
+
return isObject(value) && (typeof value.streamFunction === "function" || typeof value.streamFn === "function") && typeof value.subscribe === "function";
|
|
34337
34925
|
}
|
|
34338
34926
|
function promptContextStore() {
|
|
34339
34927
|
piPromptContextStore ??= isomorph_default.newAsyncLocalStorage();
|
|
@@ -34343,17 +34931,21 @@ function currentPiPromptState() {
|
|
|
34343
34931
|
return promptContextStore().getStore();
|
|
34344
34932
|
}
|
|
34345
34933
|
function installPiAgentInstrumentation(agent) {
|
|
34934
|
+
const property = typeof agent.streamFunction === "function" ? "streamFunction" : "streamFn";
|
|
34935
|
+
const streamFunction = agent[property];
|
|
34346
34936
|
const existing = piAgentPatchStates.get(agent);
|
|
34347
|
-
if (!existing ||
|
|
34937
|
+
if (streamFunction && (!existing || existing.property !== property || streamFunction !== existing.wrappedStreamFunction)) {
|
|
34348
34938
|
const patchState = {
|
|
34349
|
-
|
|
34350
|
-
|
|
34939
|
+
originalStreamFunction: streamFunction,
|
|
34940
|
+
property,
|
|
34941
|
+
wrappedStreamFunction: streamFunction
|
|
34351
34942
|
};
|
|
34352
|
-
patchState.
|
|
34943
|
+
patchState.wrappedStreamFunction = makeInstrumentedStreamFunction(
|
|
34353
34944
|
agent,
|
|
34354
|
-
patchState.
|
|
34945
|
+
patchState.originalStreamFunction,
|
|
34946
|
+
property
|
|
34355
34947
|
);
|
|
34356
|
-
agent
|
|
34948
|
+
agent[property] = patchState.wrappedStreamFunction;
|
|
34357
34949
|
piAgentPatchStates.set(agent, patchState);
|
|
34358
34950
|
}
|
|
34359
34951
|
if (piAgentEventSubscriptions.has(agent)) {
|
|
@@ -34378,15 +34970,21 @@ function installPiAgentInstrumentation(agent) {
|
|
|
34378
34970
|
logInstrumentationError4("Pi Coding Agent event subscription", error);
|
|
34379
34971
|
}
|
|
34380
34972
|
}
|
|
34381
|
-
function
|
|
34382
|
-
return async function
|
|
34383
|
-
const invokeOriginal = () => Reflect.apply(
|
|
34973
|
+
function makeInstrumentedStreamFunction(agent, originalStreamFunction, property) {
|
|
34974
|
+
return async function instrumentedPiStreamFunction(model, context, options) {
|
|
34975
|
+
const invokeOriginal = () => Reflect.apply(originalStreamFunction, this, [model, context, options]);
|
|
34384
34976
|
const state = currentPiPromptState();
|
|
34385
34977
|
if (!state || state.agent !== agent || state.finalized) {
|
|
34386
34978
|
return invokeOriginal();
|
|
34387
34979
|
}
|
|
34388
34980
|
wrapPiToolExecutors(context.tools);
|
|
34389
|
-
const llmState = await startPiLlmSpan(
|
|
34981
|
+
const llmState = await startPiLlmSpan(
|
|
34982
|
+
state,
|
|
34983
|
+
model,
|
|
34984
|
+
context,
|
|
34985
|
+
property,
|
|
34986
|
+
options
|
|
34987
|
+
);
|
|
34390
34988
|
try {
|
|
34391
34989
|
const stream = await runWithAutoInstrumentationSuppressed(invokeOriginal);
|
|
34392
34990
|
return patchAssistantMessageStream(stream, state, llmState);
|
|
@@ -34423,12 +35021,12 @@ function wrapPiToolExecutors(tools) {
|
|
|
34423
35021
|
}
|
|
34424
35022
|
}
|
|
34425
35023
|
}
|
|
34426
|
-
async function startPiLlmSpan(state, model, context, options) {
|
|
35024
|
+
async function startPiLlmSpan(state, model, context, property, options) {
|
|
34427
35025
|
const metadata = {
|
|
34428
35026
|
...extractModelMetadata2(model),
|
|
34429
35027
|
...extractStreamOptionsMetadata(options),
|
|
34430
35028
|
...extractToolMetadata(context.tools),
|
|
34431
|
-
"pi_coding_agent.operation":
|
|
35029
|
+
"pi_coding_agent.operation": `agent.${property}`
|
|
34432
35030
|
};
|
|
34433
35031
|
const span = startSpan(
|
|
34434
35032
|
withSpanInstrumentationName(
|
|
@@ -37444,6 +38042,7 @@ __export(exports_exports, {
|
|
|
37444
38042
|
braintrustStreamChunkSchema: () => braintrustStreamChunkSchema,
|
|
37445
38043
|
buildLocalSummary: () => buildLocalSummary,
|
|
37446
38044
|
collectAnthropicSession: () => collectAnthropicSession,
|
|
38045
|
+
completeOpenAIBatchTrace: () => completeOpenAIBatchTrace,
|
|
37447
38046
|
configureInstrumentation: () => configureInstrumentation,
|
|
37448
38047
|
constructLogs3OverflowRequest: () => constructLogs3OverflowRequest,
|
|
37449
38048
|
createFinalValuePassThroughStream: () => createFinalValuePassThroughStream,
|
|
@@ -37482,6 +38081,8 @@ __export(exports_exports, {
|
|
|
37482
38081
|
loginToState: () => loginToState,
|
|
37483
38082
|
logs3OverflowUploadSchema: () => logs3OverflowUploadSchema,
|
|
37484
38083
|
newId: () => newId,
|
|
38084
|
+
openaiBatchesRetrieveTraced: () => openaiBatchesRetrieveTraced,
|
|
38085
|
+
openaiFilesCreateTraced: () => openaiFilesCreateTraced,
|
|
37485
38086
|
parseCachedHeader: () => parseCachedHeader,
|
|
37486
38087
|
parseTemplateFormat: () => parseTemplateFormat,
|
|
37487
38088
|
permalink: () => permalink,
|
|
@@ -37646,6 +38247,260 @@ async function registerSandbox(options) {
|
|
|
37646
38247
|
};
|
|
37647
38248
|
}
|
|
37648
38249
|
|
|
38250
|
+
// src/wrappers/openai-promise-utils.ts
|
|
38251
|
+
function splitSpanInfo(allParams) {
|
|
38252
|
+
const { span_info, ...params } = allParams;
|
|
38253
|
+
return {
|
|
38254
|
+
params,
|
|
38255
|
+
span_info
|
|
38256
|
+
};
|
|
38257
|
+
}
|
|
38258
|
+
function createChannelContext(_channel, params, span_info) {
|
|
38259
|
+
return {
|
|
38260
|
+
arguments: (
|
|
38261
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
38262
|
+
[params]
|
|
38263
|
+
),
|
|
38264
|
+
span_info
|
|
38265
|
+
};
|
|
38266
|
+
}
|
|
38267
|
+
async function tracePromiseWithResponse(channel2, traceContext, apiPromise) {
|
|
38268
|
+
let enhancedResponse;
|
|
38269
|
+
const tracePromise = (
|
|
38270
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
38271
|
+
channel2.tracePromise
|
|
38272
|
+
);
|
|
38273
|
+
const data = await tracePromise(async () => {
|
|
38274
|
+
enhancedResponse = await apiPromise.withResponse();
|
|
38275
|
+
traceContext.response = enhancedResponse.response;
|
|
38276
|
+
return enhancedResponse.data;
|
|
38277
|
+
}, traceContext);
|
|
38278
|
+
if (!enhancedResponse) {
|
|
38279
|
+
throw new Error("Expected withResponse() to provide response");
|
|
38280
|
+
}
|
|
38281
|
+
return {
|
|
38282
|
+
data,
|
|
38283
|
+
response: enhancedResponse.response,
|
|
38284
|
+
request_id: enhancedResponse.request_id
|
|
38285
|
+
};
|
|
38286
|
+
}
|
|
38287
|
+
async function tracePromiseAsResponse(channel2, traceContext, apiPromise) {
|
|
38288
|
+
const tracePromise = (
|
|
38289
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
38290
|
+
channel2.tracePromise
|
|
38291
|
+
);
|
|
38292
|
+
let response;
|
|
38293
|
+
await tracePromise(async () => {
|
|
38294
|
+
response = await apiPromise.asResponse();
|
|
38295
|
+
traceContext.response = response;
|
|
38296
|
+
return void 0;
|
|
38297
|
+
}, traceContext);
|
|
38298
|
+
if (!response) {
|
|
38299
|
+
throw new Error("Expected asResponse() to provide response");
|
|
38300
|
+
}
|
|
38301
|
+
return response;
|
|
38302
|
+
}
|
|
38303
|
+
function createLazyAPIPromise(ensureExecuted, ensureResponse, getAPIPromise) {
|
|
38304
|
+
let firstConsumption;
|
|
38305
|
+
let enhancedResponsePromise;
|
|
38306
|
+
let dataPromise;
|
|
38307
|
+
let responsePromise;
|
|
38308
|
+
const withResponse = () => {
|
|
38309
|
+
firstConsumption ??= "data";
|
|
38310
|
+
enhancedResponsePromise ??= firstConsumption === "data" ? ensureExecuted() : getAPIPromise().withResponse();
|
|
38311
|
+
return enhancedResponsePromise;
|
|
38312
|
+
};
|
|
38313
|
+
const asResponse = () => {
|
|
38314
|
+
firstConsumption ??= "response";
|
|
38315
|
+
responsePromise ??= firstConsumption === "response" ? ensureResponse() : getAPIPromise().asResponse();
|
|
38316
|
+
return responsePromise;
|
|
38317
|
+
};
|
|
38318
|
+
return new Proxy({}, {
|
|
38319
|
+
get(target, prop, receiver) {
|
|
38320
|
+
if (prop === "withResponse") {
|
|
38321
|
+
return withResponse;
|
|
38322
|
+
}
|
|
38323
|
+
if (prop === "asResponse") {
|
|
38324
|
+
return asResponse;
|
|
38325
|
+
}
|
|
38326
|
+
if (prop === "then" || prop === "catch" || prop === "finally" || prop in Promise.prototype) {
|
|
38327
|
+
dataPromise ??= withResponse().then((result) => result.data);
|
|
38328
|
+
const value = Reflect.get(dataPromise, prop, receiver);
|
|
38329
|
+
return typeof value === "function" ? value.bind(dataPromise) : value;
|
|
38330
|
+
}
|
|
38331
|
+
return Reflect.get(target, prop, receiver);
|
|
38332
|
+
}
|
|
38333
|
+
});
|
|
38334
|
+
}
|
|
38335
|
+
|
|
38336
|
+
// src/openai-batch.ts
|
|
38337
|
+
function read2(value, key) {
|
|
38338
|
+
if (value === null || typeof value !== "object" && typeof value !== "function") {
|
|
38339
|
+
return void 0;
|
|
38340
|
+
}
|
|
38341
|
+
try {
|
|
38342
|
+
return Reflect.get(value, key);
|
|
38343
|
+
} catch {
|
|
38344
|
+
return void 0;
|
|
38345
|
+
}
|
|
38346
|
+
}
|
|
38347
|
+
function isAsyncIterable5(value) {
|
|
38348
|
+
return typeof read2(value, Symbol.asyncIterator) === "function";
|
|
38349
|
+
}
|
|
38350
|
+
function teeAsyncIterable(source) {
|
|
38351
|
+
const iterator = source[Symbol.asyncIterator]();
|
|
38352
|
+
const stream = new ReadableStream({
|
|
38353
|
+
async pull(controller) {
|
|
38354
|
+
try {
|
|
38355
|
+
const result = await iterator.next();
|
|
38356
|
+
if (result.done) {
|
|
38357
|
+
controller.close();
|
|
38358
|
+
return;
|
|
38359
|
+
}
|
|
38360
|
+
if (!(result.value instanceof Uint8Array)) {
|
|
38361
|
+
throw new TypeError(
|
|
38362
|
+
"OpenAI upload streams must yield Uint8Array chunks"
|
|
38363
|
+
);
|
|
38364
|
+
}
|
|
38365
|
+
controller.enqueue(result.value);
|
|
38366
|
+
} catch (error) {
|
|
38367
|
+
controller.error(error);
|
|
38368
|
+
}
|
|
38369
|
+
},
|
|
38370
|
+
async cancel(reason) {
|
|
38371
|
+
await iterator.return?.(reason);
|
|
38372
|
+
}
|
|
38373
|
+
});
|
|
38374
|
+
const [uploadStream, trace] = stream.tee();
|
|
38375
|
+
const upload = {
|
|
38376
|
+
async *[Symbol.asyncIterator]() {
|
|
38377
|
+
const reader = uploadStream.getReader();
|
|
38378
|
+
try {
|
|
38379
|
+
while (true) {
|
|
38380
|
+
const result = await reader.read();
|
|
38381
|
+
if (result.done) {
|
|
38382
|
+
return;
|
|
38383
|
+
}
|
|
38384
|
+
yield result.value;
|
|
38385
|
+
}
|
|
38386
|
+
} finally {
|
|
38387
|
+
reader.releaseLock();
|
|
38388
|
+
}
|
|
38389
|
+
}
|
|
38390
|
+
};
|
|
38391
|
+
const path = read2(source, "path");
|
|
38392
|
+
if (typeof path === "string") {
|
|
38393
|
+
Object.defineProperty(upload, "path", { value: path });
|
|
38394
|
+
}
|
|
38395
|
+
return { upload, trace: new Response(trace) };
|
|
38396
|
+
}
|
|
38397
|
+
function teeUpload(upload) {
|
|
38398
|
+
if (upload instanceof Blob) {
|
|
38399
|
+
return { upload, trace: new Response(upload) };
|
|
38400
|
+
}
|
|
38401
|
+
if (upload instanceof Response) {
|
|
38402
|
+
return { upload, trace: upload.clone() };
|
|
38403
|
+
}
|
|
38404
|
+
if (isAsyncIterable5(upload)) {
|
|
38405
|
+
return teeAsyncIterable(upload);
|
|
38406
|
+
}
|
|
38407
|
+
return void 0;
|
|
38408
|
+
}
|
|
38409
|
+
function openaiFilesCreateTraced(files) {
|
|
38410
|
+
return (params, options) => {
|
|
38411
|
+
const parent = getSpanParentObject();
|
|
38412
|
+
const purpose = read2(params, "purpose");
|
|
38413
|
+
const file = read2(params, "file");
|
|
38414
|
+
if (purpose !== "batch") {
|
|
38415
|
+
return files.create(params, options);
|
|
38416
|
+
}
|
|
38417
|
+
let branches;
|
|
38418
|
+
try {
|
|
38419
|
+
branches = teeUpload(file);
|
|
38420
|
+
} catch {
|
|
38421
|
+
return files.create(params, options);
|
|
38422
|
+
}
|
|
38423
|
+
if (!branches) {
|
|
38424
|
+
return files.create(params, options);
|
|
38425
|
+
}
|
|
38426
|
+
const tracedParams = {
|
|
38427
|
+
...Object(params),
|
|
38428
|
+
file: branches.upload
|
|
38429
|
+
};
|
|
38430
|
+
const apiPromise = files.create(tracedParams, options);
|
|
38431
|
+
let enhancedResponse;
|
|
38432
|
+
const tracedResponse = openAIChannels.filesCreateTraced.invoke(
|
|
38433
|
+
async () => {
|
|
38434
|
+
enhancedResponse = await apiPromise.withResponse();
|
|
38435
|
+
return enhancedResponse.data;
|
|
38436
|
+
},
|
|
38437
|
+
files,
|
|
38438
|
+
[{ params, inputFileContent: branches.trace, parent }],
|
|
38439
|
+
{}
|
|
38440
|
+
).then((data) => {
|
|
38441
|
+
if (!enhancedResponse) {
|
|
38442
|
+
throw new Error(
|
|
38443
|
+
"Expected OpenAI withResponse() to provide a response"
|
|
38444
|
+
);
|
|
38445
|
+
}
|
|
38446
|
+
return { ...enhancedResponse, data };
|
|
38447
|
+
});
|
|
38448
|
+
return createLazyAPIPromise(
|
|
38449
|
+
() => tracedResponse,
|
|
38450
|
+
() => tracedResponse.then(({ response }) => response),
|
|
38451
|
+
() => apiPromise
|
|
38452
|
+
);
|
|
38453
|
+
};
|
|
38454
|
+
}
|
|
38455
|
+
function openaiBatchesRetrieveTraced(batches) {
|
|
38456
|
+
return (batchId, options) => {
|
|
38457
|
+
const apiPromise = batches.retrieve(batchId, options);
|
|
38458
|
+
let enhancedResponse;
|
|
38459
|
+
const tracedResponse = openAIChannels.batchesRetrieveTraced.invoke(
|
|
38460
|
+
async () => {
|
|
38461
|
+
enhancedResponse = await apiPromise.withResponse();
|
|
38462
|
+
return enhancedResponse.data;
|
|
38463
|
+
},
|
|
38464
|
+
batches,
|
|
38465
|
+
[{ batchId }],
|
|
38466
|
+
{}
|
|
38467
|
+
).then((data) => {
|
|
38468
|
+
if (!enhancedResponse) {
|
|
38469
|
+
throw new Error(
|
|
38470
|
+
"Expected OpenAI withResponse() to provide a response"
|
|
38471
|
+
);
|
|
38472
|
+
}
|
|
38473
|
+
return { ...enhancedResponse, data };
|
|
38474
|
+
});
|
|
38475
|
+
return createLazyAPIPromise(
|
|
38476
|
+
() => tracedResponse,
|
|
38477
|
+
() => tracedResponse.then(({ response }) => response),
|
|
38478
|
+
() => apiPromise
|
|
38479
|
+
);
|
|
38480
|
+
};
|
|
38481
|
+
}
|
|
38482
|
+
async function completeOpenAIBatchTrace(args) {
|
|
38483
|
+
const inputFileContent = Promise.resolve(args.inputFileContent);
|
|
38484
|
+
const outputFileContent = args.outputFileContent === void 0 ? void 0 : Promise.resolve(args.outputFileContent);
|
|
38485
|
+
const errorFileContent = args.errorFileContent === void 0 ? void 0 : Promise.resolve(args.errorFileContent);
|
|
38486
|
+
void inputFileContent.catch(() => void 0);
|
|
38487
|
+
void outputFileContent?.catch(() => void 0);
|
|
38488
|
+
void errorFileContent?.catch(() => void 0);
|
|
38489
|
+
await openAIChannels.batchesCompleteTrace.invoke(
|
|
38490
|
+
async () => void 0,
|
|
38491
|
+
void 0,
|
|
38492
|
+
[
|
|
38493
|
+
{
|
|
38494
|
+
...args,
|
|
38495
|
+
inputFileContent,
|
|
38496
|
+
outputFileContent,
|
|
38497
|
+
errorFileContent
|
|
38498
|
+
}
|
|
38499
|
+
],
|
|
38500
|
+
{}
|
|
38501
|
+
);
|
|
38502
|
+
}
|
|
38503
|
+
|
|
37649
38504
|
// src/functions/invoke.ts
|
|
37650
38505
|
async function invoke(args) {
|
|
37651
38506
|
const {
|
|
@@ -37748,58 +38603,6 @@ function initFunction({
|
|
|
37748
38603
|
return f;
|
|
37749
38604
|
}
|
|
37750
38605
|
|
|
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
38606
|
// src/wrappers/oai_responses.ts
|
|
37804
38607
|
function responsesProxy(openai) {
|
|
37805
38608
|
if (!openai.responses) {
|
|
@@ -37836,17 +38639,33 @@ function wrapResponsesAsync(target, channel2) {
|
|
|
37836
38639
|
return (allParams, options) => {
|
|
37837
38640
|
const { span_info, params } = splitSpanInfo(allParams);
|
|
37838
38641
|
let executionPromise = null;
|
|
38642
|
+
let apiPromise = null;
|
|
38643
|
+
const getAPIPromise = () => {
|
|
38644
|
+
apiPromise ??= target(params, options);
|
|
38645
|
+
return apiPromise;
|
|
38646
|
+
};
|
|
37839
38647
|
const ensureExecuted = () => {
|
|
37840
38648
|
if (!executionPromise) {
|
|
37841
38649
|
executionPromise = (async () => {
|
|
37842
38650
|
const traceContext = createChannelContext(channel2, params, span_info);
|
|
37843
|
-
|
|
37844
|
-
|
|
38651
|
+
return tracePromiseWithResponse(
|
|
38652
|
+
channel2,
|
|
38653
|
+
traceContext,
|
|
38654
|
+
getAPIPromise()
|
|
38655
|
+
);
|
|
37845
38656
|
})();
|
|
37846
38657
|
}
|
|
37847
38658
|
return executionPromise;
|
|
37848
38659
|
};
|
|
37849
|
-
return createLazyAPIPromise(
|
|
38660
|
+
return createLazyAPIPromise(
|
|
38661
|
+
ensureExecuted,
|
|
38662
|
+
() => tracePromiseAsResponse(
|
|
38663
|
+
channel2,
|
|
38664
|
+
createChannelContext(channel2, params, span_info),
|
|
38665
|
+
getAPIPromise()
|
|
38666
|
+
),
|
|
38667
|
+
getAPIPromise
|
|
38668
|
+
);
|
|
37850
38669
|
};
|
|
37851
38670
|
}
|
|
37852
38671
|
function wrapResponsesSyncStream(target, channel2) {
|
|
@@ -37992,6 +38811,11 @@ function wrapChatCompletion(completion) {
|
|
|
37992
38811
|
allParams
|
|
37993
38812
|
);
|
|
37994
38813
|
let executionPromise = null;
|
|
38814
|
+
let apiPromise = null;
|
|
38815
|
+
const getAPIPromise = () => {
|
|
38816
|
+
apiPromise ??= completion(params, options);
|
|
38817
|
+
return apiPromise;
|
|
38818
|
+
};
|
|
37995
38819
|
const ensureExecuted = () => {
|
|
37996
38820
|
if (!executionPromise) {
|
|
37997
38821
|
executionPromise = (async () => {
|
|
@@ -38001,32 +38825,44 @@ function wrapChatCompletion(completion) {
|
|
|
38001
38825
|
span_info
|
|
38002
38826
|
);
|
|
38003
38827
|
if (params.stream) {
|
|
38004
|
-
const completionPromise =
|
|
38005
|
-
|
|
38006
|
-
|
|
38828
|
+
const completionPromise = (
|
|
38829
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
38830
|
+
getAPIPromise()
|
|
38007
38831
|
);
|
|
38008
|
-
const { data: data2, response: response2 } = await tracePromiseWithResponse(
|
|
38832
|
+
const { data: data2, response: response2, request_id: request_id2 } = await tracePromiseWithResponse(
|
|
38009
38833
|
openAIChannels.chatCompletionsCreate,
|
|
38010
38834
|
traceContext,
|
|
38011
38835
|
completionPromise
|
|
38012
38836
|
);
|
|
38013
|
-
return { data: data2, response: response2 };
|
|
38837
|
+
return { data: data2, response: response2, request_id: request_id2 };
|
|
38014
38838
|
}
|
|
38015
|
-
const completionResponse =
|
|
38016
|
-
|
|
38017
|
-
|
|
38839
|
+
const completionResponse = (
|
|
38840
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
38841
|
+
getAPIPromise()
|
|
38018
38842
|
);
|
|
38019
|
-
const { data, response } = await tracePromiseWithResponse(
|
|
38843
|
+
const { data, response, request_id } = await tracePromiseWithResponse(
|
|
38020
38844
|
openAIChannels.chatCompletionsCreate,
|
|
38021
38845
|
traceContext,
|
|
38022
38846
|
completionResponse
|
|
38023
38847
|
);
|
|
38024
|
-
return { data, response };
|
|
38848
|
+
return { data, response, request_id };
|
|
38025
38849
|
})();
|
|
38026
38850
|
}
|
|
38027
38851
|
return executionPromise;
|
|
38028
38852
|
};
|
|
38029
|
-
return createLazyAPIPromise(
|
|
38853
|
+
return createLazyAPIPromise(
|
|
38854
|
+
ensureExecuted,
|
|
38855
|
+
() => tracePromiseAsResponse(
|
|
38856
|
+
openAIChannels.chatCompletionsCreate,
|
|
38857
|
+
createChannelContext(
|
|
38858
|
+
openAIChannels.chatCompletionsCreate,
|
|
38859
|
+
params,
|
|
38860
|
+
span_info
|
|
38861
|
+
),
|
|
38862
|
+
getAPIPromise()
|
|
38863
|
+
),
|
|
38864
|
+
getAPIPromise
|
|
38865
|
+
);
|
|
38030
38866
|
};
|
|
38031
38867
|
}
|
|
38032
38868
|
function createEndpointProxy(target, wrapperFn) {
|
|
@@ -38044,6 +38880,11 @@ function wrapApiCreateWithChannel(create, channel2) {
|
|
|
38044
38880
|
return (allParams, options) => {
|
|
38045
38881
|
const { span_info, params } = splitSpanInfo(allParams);
|
|
38046
38882
|
let executionPromise = null;
|
|
38883
|
+
let apiPromise = null;
|
|
38884
|
+
const getAPIPromise = () => {
|
|
38885
|
+
apiPromise ??= create(params, options);
|
|
38886
|
+
return apiPromise;
|
|
38887
|
+
};
|
|
38047
38888
|
const ensureExecuted = () => {
|
|
38048
38889
|
if (!executionPromise) {
|
|
38049
38890
|
executionPromise = (async () => {
|
|
@@ -38051,13 +38892,21 @@ function wrapApiCreateWithChannel(create, channel2) {
|
|
|
38051
38892
|
return tracePromiseWithResponse(
|
|
38052
38893
|
channel2,
|
|
38053
38894
|
traceContext,
|
|
38054
|
-
|
|
38895
|
+
getAPIPromise()
|
|
38055
38896
|
);
|
|
38056
38897
|
})();
|
|
38057
38898
|
}
|
|
38058
38899
|
return executionPromise;
|
|
38059
38900
|
};
|
|
38060
|
-
return createLazyAPIPromise(
|
|
38901
|
+
return createLazyAPIPromise(
|
|
38902
|
+
ensureExecuted,
|
|
38903
|
+
() => tracePromiseAsResponse(
|
|
38904
|
+
channel2,
|
|
38905
|
+
createChannelContext(channel2, params, span_info),
|
|
38906
|
+
getAPIPromise()
|
|
38907
|
+
),
|
|
38908
|
+
getAPIPromise
|
|
38909
|
+
);
|
|
38061
38910
|
};
|
|
38062
38911
|
}
|
|
38063
38912
|
var wrapEmbeddings = (create) => wrapApiCreateWithChannel(create, openAIChannels.embeddingsCreate);
|
|
@@ -40752,7 +41601,15 @@ var MAX_EVE_PROVIDER_CACHE_ENTRIES = 1e4;
|
|
|
40752
41601
|
function createEveInstrumentationProvider(options = {}) {
|
|
40753
41602
|
const bridge = new EveProviderBridge(options.metadata);
|
|
40754
41603
|
return {
|
|
41604
|
+
// Eve versions before tracePolicy use capture to decide whether provider
|
|
41605
|
+
// events include content. Newer versions prefer tracePolicy when both are
|
|
41606
|
+
// present, so keep the deprecated field for backwards compatibility.
|
|
40755
41607
|
capture: "content",
|
|
41608
|
+
tracePolicy: () => ({
|
|
41609
|
+
emit: true,
|
|
41610
|
+
recordInputs: true,
|
|
41611
|
+
recordOutputs: true
|
|
41612
|
+
}),
|
|
40756
41613
|
events: {
|
|
40757
41614
|
"action.completed": (event, context) => bridge.handleActionTerminal(event, context),
|
|
40758
41615
|
"action.failed": (event, context) => bridge.handleActionTerminal(event, context),
|
|
@@ -44360,8 +45217,8 @@ function normalizeScores(result) {
|
|
|
44360
45217
|
(s) => s !== null && s !== void 0 && typeof s === "object" && isScore(s)
|
|
44361
45218
|
);
|
|
44362
45219
|
}
|
|
44363
|
-
if (typeof result === "object" && result !== null &&
|
|
44364
|
-
return [result];
|
|
45220
|
+
if (typeof result === "object" && result !== null && "score" in result) {
|
|
45221
|
+
return [{ ...result, name: result.name ?? "score" }];
|
|
44365
45222
|
}
|
|
44366
45223
|
return [];
|
|
44367
45224
|
}
|
|
@@ -45181,7 +46038,7 @@ function isAsync(fn) {
|
|
|
45181
46038
|
function isAsyncGenerator2(fn) {
|
|
45182
46039
|
return fn[Symbol.toStringTag] === "AsyncGenerator";
|
|
45183
46040
|
}
|
|
45184
|
-
function
|
|
46041
|
+
function isAsyncIterable6(obj) {
|
|
45185
46042
|
return typeof obj[Symbol.asyncIterator] === "function";
|
|
45186
46043
|
}
|
|
45187
46044
|
function wrapAsync(asyncFn) {
|
|
@@ -45353,7 +46210,7 @@ var eachOfLimit$2 = (limit) => {
|
|
|
45353
46210
|
if (isAsyncGenerator2(obj)) {
|
|
45354
46211
|
return asyncEachOfLimit(obj, limit, iteratee, callback);
|
|
45355
46212
|
}
|
|
45356
|
-
if (
|
|
46213
|
+
if (isAsyncIterable6(obj)) {
|
|
45357
46214
|
return asyncEachOfLimit(obj[Symbol.asyncIterator](), limit, iteratee, callback);
|
|
45358
46215
|
}
|
|
45359
46216
|
var nextElem = createIterator(obj);
|
|
@@ -46708,7 +47565,7 @@ function callEvaluatorData(data) {
|
|
|
46708
47565
|
baseExperiment
|
|
46709
47566
|
};
|
|
46710
47567
|
}
|
|
46711
|
-
function
|
|
47568
|
+
function isAsyncIterable7(value) {
|
|
46712
47569
|
return typeof value === "object" && value !== null && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
|
|
46713
47570
|
}
|
|
46714
47571
|
function isIterable(value) {
|
|
@@ -46743,7 +47600,7 @@ async function _internalResolveEvaluatorData(evaluator, experiment) {
|
|
|
46743
47600
|
}).asDataset();
|
|
46744
47601
|
}
|
|
46745
47602
|
const resolvedDataResult = dataResult instanceof Promise ? await dataResult : dataResult;
|
|
46746
|
-
if (
|
|
47603
|
+
if (isAsyncIterable7(resolvedDataResult)) {
|
|
46747
47604
|
return resolvedDataResult;
|
|
46748
47605
|
}
|
|
46749
47606
|
if (Array.isArray(resolvedDataResult) || isIterable(resolvedDataResult)) {
|
|
@@ -46944,19 +47801,29 @@ function buildSpanScores(results) {
|
|
|
46944
47801
|
function _internalPrepareEvaluatorScore(scoreValue, name) {
|
|
46945
47802
|
if (scoreValue === null) return { results: null };
|
|
46946
47803
|
if (Array.isArray(scoreValue)) {
|
|
47804
|
+
const names = /* @__PURE__ */ new Set();
|
|
46947
47805
|
for (const score of scoreValue) {
|
|
46948
47806
|
if (!(typeof score === "object" && !isEmpty2(score))) {
|
|
46949
47807
|
throw new Error(
|
|
46950
47808
|
`When returning an array of scores, each score must be a non-empty object. Got: ${JSON.stringify(score)}`
|
|
46951
47809
|
);
|
|
46952
47810
|
}
|
|
47811
|
+
if (typeof score.name !== "string") {
|
|
47812
|
+
throw new Error(
|
|
47813
|
+
`When returning an array of scores, each score must have a name. Got: ${JSON.stringify(score)}`
|
|
47814
|
+
);
|
|
47815
|
+
}
|
|
47816
|
+
if (names.has(score.name)) {
|
|
47817
|
+
throw new Error(`Duplicate score name '${score.name}' in score array`);
|
|
47818
|
+
}
|
|
47819
|
+
names.add(score.name);
|
|
46953
47820
|
}
|
|
46954
47821
|
}
|
|
46955
47822
|
let results;
|
|
46956
47823
|
if (Array.isArray(scoreValue)) {
|
|
46957
47824
|
results = scoreValue;
|
|
46958
47825
|
} else if (typeof scoreValue === "object" && !isEmpty2(scoreValue)) {
|
|
46959
|
-
results = [scoreValue];
|
|
47826
|
+
results = [{ ...scoreValue, name: scoreValue.name ?? name }];
|
|
46960
47827
|
} else {
|
|
46961
47828
|
results = [{ name, score: scoreValue }];
|
|
46962
47829
|
}
|