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
|
@@ -3917,6 +3917,7 @@ var ProjectSettings = z6.union([
|
|
|
3917
3917
|
]),
|
|
3918
3918
|
disable_realtime_queries: z6.union([z6.boolean(), z6.null()]),
|
|
3919
3919
|
monitor_charts_use_metrics_start: z6.union([z6.boolean(), z6.null()]),
|
|
3920
|
+
blind_reviews: z6.union([z6.boolean(), z6.null()]),
|
|
3920
3921
|
default_preprocessor: NullableSavedFunctionId
|
|
3921
3922
|
}).partial(),
|
|
3922
3923
|
z6.null()
|
|
@@ -3978,6 +3979,7 @@ var WindowedAutomationConfig = z6.object({
|
|
|
3978
3979
|
auto_approve_tools: z6.array(z6.string().min(1)).optional().default([]),
|
|
3979
3980
|
harness: z6.enum(["native", "codex", "claude-code"]).optional(),
|
|
3980
3981
|
model: z6.string().min(1).optional(),
|
|
3982
|
+
endpoint_name: z6.string().min(1).optional(),
|
|
3981
3983
|
reasoning_effort: z6.enum(["none", "minimal", "low", "medium", "high", "xhigh", "max"]).optional()
|
|
3982
3984
|
}).optional(),
|
|
3983
3985
|
actions: z6.array(
|
|
@@ -5771,7 +5773,7 @@ var INSTRUMENTATION_NAMES = {
|
|
|
5771
5773
|
var INTERNAL_SPAN_INSTRUMENTATION_NAME = /* @__PURE__ */ Symbol.for(
|
|
5772
5774
|
"braintrust.spanInstrumentationName"
|
|
5773
5775
|
);
|
|
5774
|
-
var SDK_VERSION = true ? "3.
|
|
5776
|
+
var SDK_VERSION = true ? "3.31.0" : "0.0.0";
|
|
5775
5777
|
function withSpanInstrumentationName(args, instrumentationName) {
|
|
5776
5778
|
return {
|
|
5777
5779
|
...args,
|
|
@@ -8487,6 +8489,9 @@ function getSpanParentObjectAndPropagatedState(options) {
|
|
|
8487
8489
|
}
|
|
8488
8490
|
return { parentObject: NOOP_SPAN, propagatedState: void 0 };
|
|
8489
8491
|
}
|
|
8492
|
+
function getSpanParentObject(options) {
|
|
8493
|
+
return getSpanParentObjectAndPropagatedState(options).parentObject;
|
|
8494
|
+
}
|
|
8490
8495
|
function currentBraintrustParent(state) {
|
|
8491
8496
|
const resolvedState = state ?? _globalState;
|
|
8492
8497
|
const experiment = currentExperiment({ state: resolvedState });
|
|
@@ -8733,6 +8738,15 @@ function _internalStartSpanWithInitialMerge(args) {
|
|
|
8733
8738
|
[INITIAL_SPAN_WRITE_AS_MERGE]: true
|
|
8734
8739
|
}).span;
|
|
8735
8740
|
}
|
|
8741
|
+
function _internalStartSpanWithInitialMergeAndParentSpanIds(args) {
|
|
8742
|
+
return startSpanAndIsLogger(
|
|
8743
|
+
{
|
|
8744
|
+
...args,
|
|
8745
|
+
[INITIAL_SPAN_WRITE_AS_MERGE]: true
|
|
8746
|
+
},
|
|
8747
|
+
{ useParentSpanIdsForObjectParent: true }
|
|
8748
|
+
).span;
|
|
8749
|
+
}
|
|
8736
8750
|
function _internalStartSpanWithContext(args, context) {
|
|
8737
8751
|
return startSpanAndIsLogger({
|
|
8738
8752
|
...args,
|
|
@@ -8743,7 +8757,7 @@ async function flush(options) {
|
|
|
8743
8757
|
const state = options?.state ?? _globalState;
|
|
8744
8758
|
return await state.bgLogger().flush();
|
|
8745
8759
|
}
|
|
8746
|
-
function startSpanAndIsLogger(args) {
|
|
8760
|
+
function startSpanAndIsLogger(args, internalOptions) {
|
|
8747
8761
|
const state = args?.state ?? _globalState;
|
|
8748
8762
|
const { parentObject, propagatedState } = getSpanParentObjectAndPropagatedState({
|
|
8749
8763
|
asyncFlush: args?.asyncFlush,
|
|
@@ -8757,7 +8771,7 @@ function startSpanAndIsLogger(args) {
|
|
|
8757
8771
|
) ? {
|
|
8758
8772
|
spanId: parentObject.data.span_id,
|
|
8759
8773
|
rootSpanId: parentObject.data.root_span_id
|
|
8760
|
-
} : void 0;
|
|
8774
|
+
} : internalOptions?.useParentSpanIdsForObjectParent ? args?.parentSpanIds : void 0;
|
|
8761
8775
|
const { parent: _ignoredParent, ...spanArgs } = args ?? {};
|
|
8762
8776
|
const span = new SpanImpl({
|
|
8763
8777
|
state,
|
|
@@ -11787,6 +11801,131 @@ function unsubscribeAll(unsubscribers) {
|
|
|
11787
11801
|
return [];
|
|
11788
11802
|
}
|
|
11789
11803
|
|
|
11804
|
+
// src/instrumentation/core/channel-definitions.ts
|
|
11805
|
+
function channel(spec) {
|
|
11806
|
+
return spec;
|
|
11807
|
+
}
|
|
11808
|
+
function defineChannels(pkg, channels, options) {
|
|
11809
|
+
const { instrumentationName } = options;
|
|
11810
|
+
return Object.fromEntries(
|
|
11811
|
+
Object.entries(channels).map(([key, spec]) => {
|
|
11812
|
+
const fullChannelName = `orchestrion:${pkg}:${spec.channelName}`;
|
|
11813
|
+
if (spec.kind === "async") {
|
|
11814
|
+
const asyncSpec = spec;
|
|
11815
|
+
const tracingChannel2 = () => isomorph_default.newTracingChannel(
|
|
11816
|
+
fullChannelName
|
|
11817
|
+
);
|
|
11818
|
+
const intercept2 = (interceptor) => {
|
|
11819
|
+
const hook = tracingChannel2();
|
|
11820
|
+
return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
|
|
11821
|
+
};
|
|
11822
|
+
};
|
|
11823
|
+
return [
|
|
11824
|
+
key,
|
|
11825
|
+
{
|
|
11826
|
+
...asyncSpec,
|
|
11827
|
+
instrumentationName,
|
|
11828
|
+
intercept: intercept2,
|
|
11829
|
+
invoke: (target, thisArg, args, additional) => {
|
|
11830
|
+
const hook = tracingChannel2();
|
|
11831
|
+
return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
|
|
11832
|
+
},
|
|
11833
|
+
tracingChannel: tracingChannel2,
|
|
11834
|
+
tracePromise: (fn, context) => tracingChannel2().tracePromise(
|
|
11835
|
+
fn,
|
|
11836
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
11837
|
+
context
|
|
11838
|
+
)
|
|
11839
|
+
}
|
|
11840
|
+
];
|
|
11841
|
+
}
|
|
11842
|
+
const syncSpec = spec;
|
|
11843
|
+
const tracingChannel = () => isomorph_default.newTracingChannel(
|
|
11844
|
+
fullChannelName
|
|
11845
|
+
);
|
|
11846
|
+
const intercept = (interceptor) => {
|
|
11847
|
+
const hook = tracingChannel();
|
|
11848
|
+
return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
|
|
11849
|
+
};
|
|
11850
|
+
};
|
|
11851
|
+
return [
|
|
11852
|
+
key,
|
|
11853
|
+
{
|
|
11854
|
+
...syncSpec,
|
|
11855
|
+
instrumentationName,
|
|
11856
|
+
intercept,
|
|
11857
|
+
invoke: (target, thisArg, args, additional) => {
|
|
11858
|
+
const hook = tracingChannel();
|
|
11859
|
+
return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
|
|
11860
|
+
},
|
|
11861
|
+
tracingChannel,
|
|
11862
|
+
traceSync: (fn, context) => tracingChannel().traceSync(
|
|
11863
|
+
fn,
|
|
11864
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
11865
|
+
context
|
|
11866
|
+
)
|
|
11867
|
+
}
|
|
11868
|
+
];
|
|
11869
|
+
})
|
|
11870
|
+
);
|
|
11871
|
+
}
|
|
11872
|
+
|
|
11873
|
+
// src/instrumentation/plugins/openai-channels.ts
|
|
11874
|
+
var openAIChannels = defineChannels(
|
|
11875
|
+
"openai",
|
|
11876
|
+
{
|
|
11877
|
+
filesCreateTraced: channel({
|
|
11878
|
+
channelName: "files.create-traced",
|
|
11879
|
+
kind: "async"
|
|
11880
|
+
}),
|
|
11881
|
+
batchesRetrieveTraced: channel({
|
|
11882
|
+
channelName: "batches.retrieve-traced",
|
|
11883
|
+
kind: "async"
|
|
11884
|
+
}),
|
|
11885
|
+
batchesCompleteTrace: channel({
|
|
11886
|
+
channelName: "batches.complete-trace",
|
|
11887
|
+
kind: "async"
|
|
11888
|
+
}),
|
|
11889
|
+
chatCompletionsCreate: channel({
|
|
11890
|
+
channelName: "chat.completions.create",
|
|
11891
|
+
kind: "async"
|
|
11892
|
+
}),
|
|
11893
|
+
embeddingsCreate: channel({
|
|
11894
|
+
channelName: "embeddings.create",
|
|
11895
|
+
kind: "async"
|
|
11896
|
+
}),
|
|
11897
|
+
betaChatCompletionsParse: channel({
|
|
11898
|
+
channelName: "beta.chat.completions.parse",
|
|
11899
|
+
kind: "async"
|
|
11900
|
+
}),
|
|
11901
|
+
betaChatCompletionsStream: channel({
|
|
11902
|
+
channelName: "beta.chat.completions.stream",
|
|
11903
|
+
kind: "sync-stream"
|
|
11904
|
+
}),
|
|
11905
|
+
moderationsCreate: channel({
|
|
11906
|
+
channelName: "moderations.create",
|
|
11907
|
+
kind: "async"
|
|
11908
|
+
}),
|
|
11909
|
+
responsesCreate: channel({
|
|
11910
|
+
channelName: "responses.create",
|
|
11911
|
+
kind: "async"
|
|
11912
|
+
}),
|
|
11913
|
+
responsesStream: channel({
|
|
11914
|
+
channelName: "responses.stream",
|
|
11915
|
+
kind: "sync-stream"
|
|
11916
|
+
}),
|
|
11917
|
+
responsesParse: channel({
|
|
11918
|
+
channelName: "responses.parse",
|
|
11919
|
+
kind: "async"
|
|
11920
|
+
}),
|
|
11921
|
+
responsesCompact: channel({
|
|
11922
|
+
channelName: "responses.compact",
|
|
11923
|
+
kind: "async"
|
|
11924
|
+
})
|
|
11925
|
+
},
|
|
11926
|
+
{ instrumentationName: INSTRUMENTATION_NAMES.OPENAI }
|
|
11927
|
+
);
|
|
11928
|
+
|
|
11790
11929
|
// src/wrappers/attachment-utils.ts
|
|
11791
11930
|
function getExtensionFromMediaType(mediaType) {
|
|
11792
11931
|
const extensionMap = {
|
|
@@ -11962,118 +12101,91 @@ function processInputAttachments(input) {
|
|
|
11962
12101
|
return processNode(input);
|
|
11963
12102
|
}
|
|
11964
12103
|
|
|
11965
|
-
// src/instrumentation/
|
|
11966
|
-
|
|
11967
|
-
|
|
11968
|
-
|
|
11969
|
-
|
|
11970
|
-
|
|
11971
|
-
|
|
11972
|
-
|
|
11973
|
-
|
|
11974
|
-
|
|
11975
|
-
|
|
11976
|
-
|
|
11977
|
-
|
|
11978
|
-
|
|
11979
|
-
|
|
11980
|
-
|
|
11981
|
-
|
|
11982
|
-
|
|
11983
|
-
|
|
11984
|
-
|
|
11985
|
-
|
|
11986
|
-
|
|
11987
|
-
...asyncSpec,
|
|
11988
|
-
instrumentationName,
|
|
11989
|
-
intercept: intercept2,
|
|
11990
|
-
invoke: (target, thisArg, args, additional) => {
|
|
11991
|
-
const hook = tracingChannel2();
|
|
11992
|
-
return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
|
|
11993
|
-
},
|
|
11994
|
-
tracingChannel: tracingChannel2,
|
|
11995
|
-
tracePromise: (fn, context) => tracingChannel2().tracePromise(
|
|
11996
|
-
fn,
|
|
11997
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
11998
|
-
context
|
|
11999
|
-
)
|
|
12000
|
-
}
|
|
12001
|
-
];
|
|
12104
|
+
// src/instrumentation/plugins/openai-span-data.ts
|
|
12105
|
+
var OPENAI_METADATA_KEYS = [
|
|
12106
|
+
"model",
|
|
12107
|
+
"temperature",
|
|
12108
|
+
"top_p",
|
|
12109
|
+
"max_tokens",
|
|
12110
|
+
"frequency_penalty",
|
|
12111
|
+
"presence_penalty",
|
|
12112
|
+
"stop",
|
|
12113
|
+
"response_format",
|
|
12114
|
+
"tools",
|
|
12115
|
+
"tool_choice",
|
|
12116
|
+
"parallel_tool_calls",
|
|
12117
|
+
"max_tool_calls"
|
|
12118
|
+
];
|
|
12119
|
+
function batchMetadata(params) {
|
|
12120
|
+
const metadata = { provider: "openai" };
|
|
12121
|
+
for (const key of OPENAI_METADATA_KEYS) {
|
|
12122
|
+
try {
|
|
12123
|
+
const value = Reflect.get(params, key);
|
|
12124
|
+
if (value !== void 0) {
|
|
12125
|
+
metadata[key] = value;
|
|
12002
12126
|
}
|
|
12003
|
-
|
|
12004
|
-
|
|
12005
|
-
|
|
12006
|
-
|
|
12007
|
-
|
|
12008
|
-
|
|
12009
|
-
|
|
12010
|
-
|
|
12011
|
-
|
|
12012
|
-
|
|
12013
|
-
|
|
12014
|
-
|
|
12015
|
-
|
|
12016
|
-
|
|
12017
|
-
|
|
12018
|
-
|
|
12019
|
-
|
|
12020
|
-
|
|
12021
|
-
|
|
12022
|
-
|
|
12023
|
-
|
|
12024
|
-
|
|
12025
|
-
|
|
12026
|
-
|
|
12027
|
-
|
|
12028
|
-
|
|
12029
|
-
|
|
12030
|
-
|
|
12031
|
-
|
|
12127
|
+
} catch {
|
|
12128
|
+
}
|
|
12129
|
+
}
|
|
12130
|
+
return metadata;
|
|
12131
|
+
}
|
|
12132
|
+
function extractOpenAIBatchInput(endpoint, params) {
|
|
12133
|
+
const input = endpoint === "/v1/chat/completions" ? params.messages : params.input;
|
|
12134
|
+
return {
|
|
12135
|
+
input: processInputAttachments(input),
|
|
12136
|
+
metadata: batchMetadata(params)
|
|
12137
|
+
};
|
|
12138
|
+
}
|
|
12139
|
+
function extractOpenAIChatInput(params) {
|
|
12140
|
+
const { messages, ...metadata } = params;
|
|
12141
|
+
return {
|
|
12142
|
+
input: processInputAttachments(messages),
|
|
12143
|
+
metadata: { ...metadata, provider: "openai" }
|
|
12144
|
+
};
|
|
12145
|
+
}
|
|
12146
|
+
function extractOpenAIResponsesInput(params) {
|
|
12147
|
+
const { input, ...metadata } = params;
|
|
12148
|
+
return {
|
|
12149
|
+
input: processInputAttachments(input),
|
|
12150
|
+
metadata: { ...metadata, provider: "openai" }
|
|
12151
|
+
};
|
|
12152
|
+
}
|
|
12153
|
+
function extractOpenAIResponsesMetadata(result) {
|
|
12154
|
+
if (!result) {
|
|
12155
|
+
return void 0;
|
|
12156
|
+
}
|
|
12157
|
+
const { output: _output, usage: _usage, ...metadata } = result;
|
|
12158
|
+
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
12159
|
+
}
|
|
12160
|
+
function processImagesInOutput(output) {
|
|
12161
|
+
if (Array.isArray(output)) {
|
|
12162
|
+
return output.map(processImagesInOutput);
|
|
12163
|
+
}
|
|
12164
|
+
if (isObject(output) && output.type === "image_generation_call" && typeof output.result === "string" && output.result) {
|
|
12165
|
+
const fileExtension = output.output_format || "png";
|
|
12166
|
+
const contentType = `image/${fileExtension}`;
|
|
12167
|
+
const baseFilename = typeof output.revised_prompt === "string" ? output.revised_prompt.slice(0, 50).replace(/[^a-zA-Z0-9]/g, "_") : "generated_image";
|
|
12168
|
+
let binaryString;
|
|
12169
|
+
try {
|
|
12170
|
+
binaryString = atob(output.result);
|
|
12171
|
+
} catch {
|
|
12172
|
+
return output;
|
|
12173
|
+
}
|
|
12174
|
+
const bytes = new Uint8Array(binaryString.length);
|
|
12175
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
12176
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
12177
|
+
}
|
|
12178
|
+
return {
|
|
12179
|
+
...output,
|
|
12180
|
+
result: new Attachment({
|
|
12181
|
+
data: new Blob([bytes], { type: contentType }),
|
|
12182
|
+
filename: `${baseFilename}.${fileExtension}`,
|
|
12183
|
+
contentType
|
|
12184
|
+
})
|
|
12185
|
+
};
|
|
12186
|
+
}
|
|
12187
|
+
return output;
|
|
12032
12188
|
}
|
|
12033
|
-
|
|
12034
|
-
// src/instrumentation/plugins/openai-channels.ts
|
|
12035
|
-
var openAIChannels = defineChannels(
|
|
12036
|
-
"openai",
|
|
12037
|
-
{
|
|
12038
|
-
chatCompletionsCreate: channel({
|
|
12039
|
-
channelName: "chat.completions.create",
|
|
12040
|
-
kind: "async"
|
|
12041
|
-
}),
|
|
12042
|
-
embeddingsCreate: channel({
|
|
12043
|
-
channelName: "embeddings.create",
|
|
12044
|
-
kind: "async"
|
|
12045
|
-
}),
|
|
12046
|
-
betaChatCompletionsParse: channel({
|
|
12047
|
-
channelName: "beta.chat.completions.parse",
|
|
12048
|
-
kind: "async"
|
|
12049
|
-
}),
|
|
12050
|
-
betaChatCompletionsStream: channel({
|
|
12051
|
-
channelName: "beta.chat.completions.stream",
|
|
12052
|
-
kind: "sync-stream"
|
|
12053
|
-
}),
|
|
12054
|
-
moderationsCreate: channel({
|
|
12055
|
-
channelName: "moderations.create",
|
|
12056
|
-
kind: "async"
|
|
12057
|
-
}),
|
|
12058
|
-
responsesCreate: channel({
|
|
12059
|
-
channelName: "responses.create",
|
|
12060
|
-
kind: "async"
|
|
12061
|
-
}),
|
|
12062
|
-
responsesStream: channel({
|
|
12063
|
-
channelName: "responses.stream",
|
|
12064
|
-
kind: "sync-stream"
|
|
12065
|
-
}),
|
|
12066
|
-
responsesParse: channel({
|
|
12067
|
-
channelName: "responses.parse",
|
|
12068
|
-
kind: "async"
|
|
12069
|
-
}),
|
|
12070
|
-
responsesCompact: channel({
|
|
12071
|
-
channelName: "responses.compact",
|
|
12072
|
-
kind: "async"
|
|
12073
|
-
})
|
|
12074
|
-
},
|
|
12075
|
-
{ instrumentationName: INSTRUMENTATION_NAMES.OPENAI }
|
|
12076
|
-
);
|
|
12077
12189
|
|
|
12078
12190
|
// src/openai-utils.ts
|
|
12079
12191
|
var BRAINTRUST_CACHED_STREAM_METRIC = "__braintrust_cached_metric";
|
|
@@ -12130,23 +12242,573 @@ function getCachedMetricFromHeaders(headers) {
|
|
|
12130
12242
|
return parseCachedHeader(headers.get(LEGACY_CACHED_HEADER));
|
|
12131
12243
|
}
|
|
12132
12244
|
|
|
12245
|
+
// src/instrumentation/plugins/openai-batch-instrumentation.ts
|
|
12246
|
+
var SUPPORTED_ENDPOINTS = /* @__PURE__ */ new Set(["/v1/chat/completions", "/v1/responses"]);
|
|
12247
|
+
var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
|
|
12248
|
+
"completed",
|
|
12249
|
+
"failed",
|
|
12250
|
+
"expired",
|
|
12251
|
+
"cancelled"
|
|
12252
|
+
]);
|
|
12253
|
+
var pendingBatchTraces = /* @__PURE__ */ new Map();
|
|
12254
|
+
function read(value, key) {
|
|
12255
|
+
if (!isObject(value)) {
|
|
12256
|
+
return void 0;
|
|
12257
|
+
}
|
|
12258
|
+
try {
|
|
12259
|
+
return Reflect.get(value, key);
|
|
12260
|
+
} catch {
|
|
12261
|
+
return void 0;
|
|
12262
|
+
}
|
|
12263
|
+
}
|
|
12264
|
+
function isBatchRecordIterable(value) {
|
|
12265
|
+
if (value === null || typeof value !== "object" && typeof value !== "function") {
|
|
12266
|
+
return false;
|
|
12267
|
+
}
|
|
12268
|
+
return typeof read(value, Symbol.iterator) === "function" || typeof read(value, Symbol.asyncIterator) === "function";
|
|
12269
|
+
}
|
|
12270
|
+
function validCustomId(value) {
|
|
12271
|
+
return typeof value === "string" && value.length > 0 && value.length <= 64;
|
|
12272
|
+
}
|
|
12273
|
+
function logBatchInstrumentationError(context, error) {
|
|
12274
|
+
debugLogger.debug(`OpenAI Batch instrumentation ${context}:`, error);
|
|
12275
|
+
}
|
|
12276
|
+
async function exportParent(parent) {
|
|
12277
|
+
if ("toStr" in parent && typeof parent.toStr === "function") {
|
|
12278
|
+
return parent.toStr();
|
|
12279
|
+
}
|
|
12280
|
+
if ("export" in parent && typeof parent.export === "function") {
|
|
12281
|
+
return await parent.export();
|
|
12282
|
+
}
|
|
12283
|
+
return void 0;
|
|
12284
|
+
}
|
|
12285
|
+
async function deterministicDigest(namespace, ...parts) {
|
|
12286
|
+
const encoded = new TextEncoder().encode(
|
|
12287
|
+
[namespace, ...parts].map((part) => `${part.length}:${part}`).join("\0")
|
|
12288
|
+
);
|
|
12289
|
+
return new Uint8Array(
|
|
12290
|
+
await globalThis.crypto.subtle.digest("SHA-256", encoded)
|
|
12291
|
+
);
|
|
12292
|
+
}
|
|
12293
|
+
function digestHex(bytes, length) {
|
|
12294
|
+
return Array.from(bytes.slice(0, length)).map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
12295
|
+
}
|
|
12296
|
+
function digestUuid(bytes) {
|
|
12297
|
+
const hex = digestHex(bytes, 16);
|
|
12298
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
12299
|
+
}
|
|
12300
|
+
async function batchSpanIds(inputFileId) {
|
|
12301
|
+
const [row, span, root] = await Promise.all([
|
|
12302
|
+
deterministicDigest("openai:batch:row", inputFileId),
|
|
12303
|
+
deterministicDigest("openai:batch:span", inputFileId),
|
|
12304
|
+
deterministicDigest("openai:batch:root", inputFileId)
|
|
12305
|
+
]);
|
|
12306
|
+
return {
|
|
12307
|
+
rowId: digestUuid(row),
|
|
12308
|
+
spanId: digestHex(span, 8),
|
|
12309
|
+
rootSpanId: digestHex(root, 16)
|
|
12310
|
+
};
|
|
12311
|
+
}
|
|
12312
|
+
async function childSpanIds(inputFileId, customId) {
|
|
12313
|
+
const [row, span] = await Promise.all([
|
|
12314
|
+
deterministicDigest("openai:batch:child:row", inputFileId, customId),
|
|
12315
|
+
deterministicDigest("openai:batch:child:span", inputFileId, customId)
|
|
12316
|
+
]);
|
|
12317
|
+
return { rowId: digestUuid(row), spanId: digestHex(span, 8) };
|
|
12318
|
+
}
|
|
12319
|
+
async function startBatchSpan(context) {
|
|
12320
|
+
const ids = await batchSpanIds(context.inputFileId);
|
|
12321
|
+
const parent = SpanComponentsV4.fromStr(context.parent);
|
|
12322
|
+
const hasParentSpan = Boolean(
|
|
12323
|
+
parent.data.row_id && parent.data.span_id && parent.data.root_span_id
|
|
12324
|
+
);
|
|
12325
|
+
return withCurrent(
|
|
12326
|
+
NOOP_SPAN,
|
|
12327
|
+
() => _internalStartSpanWithInitialMergeAndParentSpanIds(
|
|
12328
|
+
withSpanInstrumentationName(
|
|
12329
|
+
{
|
|
12330
|
+
name: "openai.batch",
|
|
12331
|
+
type: "task" /* TASK */,
|
|
12332
|
+
parent: context.parent,
|
|
12333
|
+
...!hasParentSpan ? {
|
|
12334
|
+
parentSpanIds: {
|
|
12335
|
+
parentSpanIds: [],
|
|
12336
|
+
rootSpanId: ids.rootSpanId
|
|
12337
|
+
}
|
|
12338
|
+
} : {},
|
|
12339
|
+
spanId: ids.spanId,
|
|
12340
|
+
startTime: context.taskStartTime,
|
|
12341
|
+
event: {
|
|
12342
|
+
id: ids.rowId,
|
|
12343
|
+
metadata: {
|
|
12344
|
+
endpoint: context.endpoint,
|
|
12345
|
+
input_file_id: context.inputFileId,
|
|
12346
|
+
provider: "openai"
|
|
12347
|
+
}
|
|
12348
|
+
}
|
|
12349
|
+
},
|
|
12350
|
+
INSTRUMENTATION_NAMES.OPENAI
|
|
12351
|
+
)
|
|
12352
|
+
)
|
|
12353
|
+
);
|
|
12354
|
+
}
|
|
12355
|
+
async function startBatchChild(context, taskParent, input) {
|
|
12356
|
+
const ids = await childSpanIds(context.inputFileId, input.customId);
|
|
12357
|
+
return withCurrent(
|
|
12358
|
+
NOOP_SPAN,
|
|
12359
|
+
() => _internalStartSpanWithInitialMerge(
|
|
12360
|
+
withSpanInstrumentationName(
|
|
12361
|
+
{
|
|
12362
|
+
name: context.endpoint === "/v1/chat/completions" ? "Chat Completion" : "openai.responses.create",
|
|
12363
|
+
type: "llm" /* LLM */,
|
|
12364
|
+
parent: taskParent,
|
|
12365
|
+
spanId: ids.spanId,
|
|
12366
|
+
startTime: context.childStartTime,
|
|
12367
|
+
event: {
|
|
12368
|
+
id: ids.rowId,
|
|
12369
|
+
...input.spanData?.input !== void 0 ? { input: input.spanData.input } : {},
|
|
12370
|
+
metadata: {
|
|
12371
|
+
...input.spanData?.metadata,
|
|
12372
|
+
custom_id: input.customId,
|
|
12373
|
+
provider: "openai"
|
|
12374
|
+
}
|
|
12375
|
+
}
|
|
12376
|
+
},
|
|
12377
|
+
INSTRUMENTATION_NAMES.OPENAI
|
|
12378
|
+
)
|
|
12379
|
+
)
|
|
12380
|
+
);
|
|
12381
|
+
}
|
|
12382
|
+
async function* jsonlRecords(file, onIssue = () => {
|
|
12383
|
+
}) {
|
|
12384
|
+
const resolvedFile = await file;
|
|
12385
|
+
if (typeof resolvedFile === "string") {
|
|
12386
|
+
for (const line of resolvedFile.split("\n")) {
|
|
12387
|
+
if (!line.trim()) {
|
|
12388
|
+
continue;
|
|
12389
|
+
}
|
|
12390
|
+
try {
|
|
12391
|
+
yield JSON.parse(line.replace(/\r$/, ""));
|
|
12392
|
+
} catch (error) {
|
|
12393
|
+
logBatchInstrumentationError("skipped malformed JSONL", error);
|
|
12394
|
+
onIssue(new Error("OpenAI Batch file contains malformed JSONL"));
|
|
12395
|
+
}
|
|
12396
|
+
}
|
|
12397
|
+
return;
|
|
12398
|
+
}
|
|
12399
|
+
const body = read(resolvedFile, "body");
|
|
12400
|
+
const getReader = read(body, "getReader");
|
|
12401
|
+
if (isObject(body) && typeof getReader === "function") {
|
|
12402
|
+
let reader;
|
|
12403
|
+
try {
|
|
12404
|
+
reader = Reflect.apply(getReader, body, []);
|
|
12405
|
+
const decoder = new TextDecoder();
|
|
12406
|
+
let pending = "";
|
|
12407
|
+
while (true) {
|
|
12408
|
+
const readChunk = read(reader, "read");
|
|
12409
|
+
if (typeof readChunk !== "function") {
|
|
12410
|
+
throw new Error("Response body stream has no read method");
|
|
12411
|
+
}
|
|
12412
|
+
const chunk = await Reflect.apply(readChunk, reader, []);
|
|
12413
|
+
if (!isObject(chunk)) {
|
|
12414
|
+
throw new Error("Response body stream returned an invalid chunk");
|
|
12415
|
+
}
|
|
12416
|
+
if (chunk.done === true) {
|
|
12417
|
+
pending += decoder.decode();
|
|
12418
|
+
break;
|
|
12419
|
+
}
|
|
12420
|
+
if (!(chunk.value instanceof Uint8Array)) {
|
|
12421
|
+
throw new Error("Response body stream returned a non-byte chunk");
|
|
12422
|
+
}
|
|
12423
|
+
pending += decoder.decode(chunk.value, { stream: true });
|
|
12424
|
+
let newline = pending.indexOf("\n");
|
|
12425
|
+
while (newline !== -1) {
|
|
12426
|
+
const line = pending.slice(0, newline).replace(/\r$/, "");
|
|
12427
|
+
pending = pending.slice(newline + 1);
|
|
12428
|
+
if (line.trim()) {
|
|
12429
|
+
try {
|
|
12430
|
+
yield JSON.parse(line);
|
|
12431
|
+
} catch (error) {
|
|
12432
|
+
logBatchInstrumentationError("skipped malformed JSONL", error);
|
|
12433
|
+
onIssue(new Error("OpenAI Batch file contains malformed JSONL"));
|
|
12434
|
+
}
|
|
12435
|
+
}
|
|
12436
|
+
newline = pending.indexOf("\n");
|
|
12437
|
+
}
|
|
12438
|
+
}
|
|
12439
|
+
if (pending.trim()) {
|
|
12440
|
+
try {
|
|
12441
|
+
yield JSON.parse(pending.replace(/\r$/, ""));
|
|
12442
|
+
} catch (error) {
|
|
12443
|
+
logBatchInstrumentationError("skipped malformed JSONL", error);
|
|
12444
|
+
onIssue(new Error("OpenAI Batch file contains malformed JSONL"));
|
|
12445
|
+
}
|
|
12446
|
+
}
|
|
12447
|
+
} catch (error) {
|
|
12448
|
+
logBatchInstrumentationError("could not read JSONL response body", error);
|
|
12449
|
+
onIssue(new Error("OpenAI Batch response body could not be read"));
|
|
12450
|
+
} finally {
|
|
12451
|
+
const releaseLock = read(reader, "releaseLock");
|
|
12452
|
+
if (typeof releaseLock === "function") {
|
|
12453
|
+
try {
|
|
12454
|
+
Reflect.apply(releaseLock, reader, []);
|
|
12455
|
+
} catch (error) {
|
|
12456
|
+
logBatchInstrumentationError(
|
|
12457
|
+
"could not release stream reader",
|
|
12458
|
+
error
|
|
12459
|
+
);
|
|
12460
|
+
}
|
|
12461
|
+
}
|
|
12462
|
+
}
|
|
12463
|
+
return;
|
|
12464
|
+
}
|
|
12465
|
+
if (isBatchRecordIterable(resolvedFile)) {
|
|
12466
|
+
for await (const record of resolvedFile) {
|
|
12467
|
+
yield record;
|
|
12468
|
+
}
|
|
12469
|
+
return;
|
|
12470
|
+
}
|
|
12471
|
+
logBatchInstrumentationError("skipped invalid JSONL source", resolvedFile);
|
|
12472
|
+
onIssue(new Error("OpenAI Batch file source is invalid"));
|
|
12473
|
+
}
|
|
12474
|
+
async function readBatchInputs(file) {
|
|
12475
|
+
const inputs = /* @__PURE__ */ new Map();
|
|
12476
|
+
const issues = [];
|
|
12477
|
+
let endpoint;
|
|
12478
|
+
try {
|
|
12479
|
+
for await (const value of jsonlRecords(
|
|
12480
|
+
file,
|
|
12481
|
+
(issue) => issues.push(issue)
|
|
12482
|
+
)) {
|
|
12483
|
+
const customId = read(value, "custom_id");
|
|
12484
|
+
const url = read(value, "url");
|
|
12485
|
+
const body = read(value, "body");
|
|
12486
|
+
if (!validCustomId(customId) || inputs.has(customId) || read(value, "method") !== "POST" || typeof url !== "string" || !SUPPORTED_ENDPOINTS.has(url) || endpoint !== void 0 && endpoint !== url || !isObject(body)) {
|
|
12487
|
+
issues.push(new Error("OpenAI Batch input contains an invalid record"));
|
|
12488
|
+
continue;
|
|
12489
|
+
}
|
|
12490
|
+
endpoint = url;
|
|
12491
|
+
let spanData;
|
|
12492
|
+
try {
|
|
12493
|
+
spanData = extractOpenAIBatchInput(url, body);
|
|
12494
|
+
} catch (error) {
|
|
12495
|
+
logBatchInstrumentationError("could not extract batch input", error);
|
|
12496
|
+
}
|
|
12497
|
+
inputs.set(customId, { customId, spanData });
|
|
12498
|
+
}
|
|
12499
|
+
} catch (error) {
|
|
12500
|
+
logBatchInstrumentationError("could not process input file", error);
|
|
12501
|
+
issues.push(new Error("OpenAI Batch input file could not be processed"));
|
|
12502
|
+
}
|
|
12503
|
+
if (!endpoint || inputs.size === 0) {
|
|
12504
|
+
issues.push(new Error("OpenAI Batch input contains no supported records"));
|
|
12505
|
+
}
|
|
12506
|
+
return { endpoint, inputs, issues };
|
|
12507
|
+
}
|
|
12508
|
+
async function writePendingSpans(trace, endTime) {
|
|
12509
|
+
const task = await startBatchSpan(trace.context);
|
|
12510
|
+
const taskParent = await task.export();
|
|
12511
|
+
for (const input of trace.inputs.values()) {
|
|
12512
|
+
try {
|
|
12513
|
+
const child = await startBatchChild(trace.context, taskParent, input);
|
|
12514
|
+
if (endTime !== void 0) {
|
|
12515
|
+
child.end({ endTime });
|
|
12516
|
+
}
|
|
12517
|
+
} catch (error) {
|
|
12518
|
+
logBatchInstrumentationError("could not write batch request span", error);
|
|
12519
|
+
}
|
|
12520
|
+
}
|
|
12521
|
+
if (endTime !== void 0) {
|
|
12522
|
+
if (trace.status && trace.status !== "completed") {
|
|
12523
|
+
task.log({ error: new Error(`OpenAI Batch ${trace.status}`) });
|
|
12524
|
+
}
|
|
12525
|
+
task.end({ endTime });
|
|
12526
|
+
}
|
|
12527
|
+
}
|
|
12528
|
+
var interceptOpenAIFilesCreateTraced = async (target, thisArg, args) => {
|
|
12529
|
+
const startTime = getCurrentUnixTimestamp();
|
|
12530
|
+
const inputPromise = readBatchInputs(args[0].inputFileContent);
|
|
12531
|
+
const parentPromise = exportParent(args[0].parent);
|
|
12532
|
+
const file = await Reflect.apply(target, thisArg, args);
|
|
12533
|
+
try {
|
|
12534
|
+
const inputFileId = read(file, "id");
|
|
12535
|
+
const [inputData, exportedParent2] = await Promise.all([
|
|
12536
|
+
inputPromise,
|
|
12537
|
+
parentPromise
|
|
12538
|
+
]);
|
|
12539
|
+
if (typeof inputFileId !== "string" || !exportedParent2 || !inputData.endpoint || inputData.issues.length > 0) {
|
|
12540
|
+
if (inputData.issues[0]) {
|
|
12541
|
+
logBatchInstrumentationError(
|
|
12542
|
+
"skipped invalid input file",
|
|
12543
|
+
inputData.issues[0]
|
|
12544
|
+
);
|
|
12545
|
+
}
|
|
12546
|
+
return file;
|
|
12547
|
+
}
|
|
12548
|
+
const trace = {
|
|
12549
|
+
context: {
|
|
12550
|
+
inputFileId,
|
|
12551
|
+
endpoint: inputData.endpoint,
|
|
12552
|
+
parent: exportedParent2,
|
|
12553
|
+
taskStartTime: startTime,
|
|
12554
|
+
childStartTime: startTime
|
|
12555
|
+
},
|
|
12556
|
+
inputs: inputData.inputs
|
|
12557
|
+
};
|
|
12558
|
+
pendingBatchTraces.set(inputFileId, trace);
|
|
12559
|
+
await writePendingSpans(trace);
|
|
12560
|
+
} catch (error) {
|
|
12561
|
+
logBatchInstrumentationError("could not start batch spans", error);
|
|
12562
|
+
}
|
|
12563
|
+
return file;
|
|
12564
|
+
};
|
|
12565
|
+
function validTimestamp(value) {
|
|
12566
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0;
|
|
12567
|
+
}
|
|
12568
|
+
function terminalEndTime(batch, startTime) {
|
|
12569
|
+
let timestamp;
|
|
12570
|
+
switch (batch.status) {
|
|
12571
|
+
case "completed":
|
|
12572
|
+
timestamp = batch.completed_at;
|
|
12573
|
+
break;
|
|
12574
|
+
case "failed":
|
|
12575
|
+
timestamp = batch.failed_at;
|
|
12576
|
+
break;
|
|
12577
|
+
case "expired":
|
|
12578
|
+
timestamp = batch.expired_at;
|
|
12579
|
+
break;
|
|
12580
|
+
default:
|
|
12581
|
+
timestamp = batch.cancelled_at;
|
|
12582
|
+
}
|
|
12583
|
+
return validTimestamp(timestamp) ? Math.max(timestamp, startTime) : Math.max(getCurrentUnixTimestamp(), startTime);
|
|
12584
|
+
}
|
|
12585
|
+
async function updateBatchTimestamps(batch) {
|
|
12586
|
+
const trace = pendingBatchTraces.get(batch.input_file_id);
|
|
12587
|
+
if (!trace || trace.context.endpoint !== batch.endpoint) {
|
|
12588
|
+
return;
|
|
12589
|
+
}
|
|
12590
|
+
if (validTimestamp(batch.created_at)) {
|
|
12591
|
+
trace.context.taskStartTime = batch.created_at;
|
|
12592
|
+
}
|
|
12593
|
+
trace.context.childStartTime = validTimestamp(batch.in_progress_at) ? Math.max(batch.in_progress_at, trace.context.taskStartTime) : trace.context.taskStartTime;
|
|
12594
|
+
trace.status = batch.status;
|
|
12595
|
+
if (TERMINAL_STATUSES.has(batch.status)) {
|
|
12596
|
+
trace.endTime = terminalEndTime(batch, trace.context.childStartTime);
|
|
12597
|
+
}
|
|
12598
|
+
await writePendingSpans(trace, trace.endTime);
|
|
12599
|
+
}
|
|
12600
|
+
var interceptOpenAIBatchesRetrieveTraced = (target, thisArg, args) => Promise.resolve(Reflect.apply(target, thisArg, args)).then(async (batch) => {
|
|
12601
|
+
try {
|
|
12602
|
+
await updateBatchTimestamps(batch);
|
|
12603
|
+
} catch (error) {
|
|
12604
|
+
logBatchInstrumentationError("could not update batch timestamps", error);
|
|
12605
|
+
}
|
|
12606
|
+
return batch;
|
|
12607
|
+
});
|
|
12608
|
+
function errorFromResult(result) {
|
|
12609
|
+
const error = read(result.value, "error");
|
|
12610
|
+
if (isObject(error)) {
|
|
12611
|
+
const message = read(error, "message");
|
|
12612
|
+
return new Error(
|
|
12613
|
+
typeof message === "string" ? message : "OpenAI Batch request failed"
|
|
12614
|
+
);
|
|
12615
|
+
}
|
|
12616
|
+
const response = read(result.value, "response");
|
|
12617
|
+
const statusCode = read(response, "status_code");
|
|
12618
|
+
if (result.source === "error" || typeof statusCode === "number" && (statusCode < 200 || statusCode >= 300)) {
|
|
12619
|
+
const message = read(read(read(response, "body"), "error"), "message");
|
|
12620
|
+
return new Error(
|
|
12621
|
+
typeof message === "string" ? message : "OpenAI Batch request failed"
|
|
12622
|
+
);
|
|
12623
|
+
}
|
|
12624
|
+
return void 0;
|
|
12625
|
+
}
|
|
12626
|
+
async function completeBatchResult(context, taskParent, endTime, input, result) {
|
|
12627
|
+
const child = await startBatchChild(context, taskParent, input);
|
|
12628
|
+
try {
|
|
12629
|
+
const resultError = errorFromResult(result);
|
|
12630
|
+
const responseBody = read(read(result.value, "response"), "body");
|
|
12631
|
+
if (resultError) {
|
|
12632
|
+
child.log({ error: resultError });
|
|
12633
|
+
} else if (isObject(responseBody)) {
|
|
12634
|
+
const model = read(responseBody, "model");
|
|
12635
|
+
child.log({
|
|
12636
|
+
output: context.endpoint === "/v1/chat/completions" ? read(responseBody, "choices") : processImagesInOutput(read(responseBody, "output")),
|
|
12637
|
+
...typeof model === "string" ? { metadata: { model } } : {},
|
|
12638
|
+
metrics: parseMetricsFromUsage(read(responseBody, "usage"))
|
|
12639
|
+
});
|
|
12640
|
+
} else {
|
|
12641
|
+
child.log({ error: new Error("OpenAI Batch response body is missing") });
|
|
12642
|
+
}
|
|
12643
|
+
} catch (error) {
|
|
12644
|
+
child.log({ error });
|
|
12645
|
+
} finally {
|
|
12646
|
+
child.end({ endTime });
|
|
12647
|
+
}
|
|
12648
|
+
}
|
|
12649
|
+
async function completeResultFile({
|
|
12650
|
+
context,
|
|
12651
|
+
endTime,
|
|
12652
|
+
file,
|
|
12653
|
+
inputs,
|
|
12654
|
+
issues,
|
|
12655
|
+
seen,
|
|
12656
|
+
source,
|
|
12657
|
+
taskParent
|
|
12658
|
+
}) {
|
|
12659
|
+
if (file === void 0) {
|
|
12660
|
+
return;
|
|
12661
|
+
}
|
|
12662
|
+
for await (const value of jsonlRecords(file, (issue) => issues.push(issue))) {
|
|
12663
|
+
const customId = read(value, "custom_id");
|
|
12664
|
+
if (!validCustomId(customId) || !isObject(value)) {
|
|
12665
|
+
issues.push(
|
|
12666
|
+
new Error("OpenAI Batch result is missing a valid custom_id")
|
|
12667
|
+
);
|
|
12668
|
+
continue;
|
|
12669
|
+
}
|
|
12670
|
+
if (seen.has(customId)) {
|
|
12671
|
+
issues.push(new Error("OpenAI Batch result contains a duplicate"));
|
|
12672
|
+
continue;
|
|
12673
|
+
}
|
|
12674
|
+
const input = inputs.get(customId);
|
|
12675
|
+
if (!input) {
|
|
12676
|
+
issues.push(
|
|
12677
|
+
new Error("OpenAI Batch result does not match an input record")
|
|
12678
|
+
);
|
|
12679
|
+
continue;
|
|
12680
|
+
}
|
|
12681
|
+
seen.add(customId);
|
|
12682
|
+
await completeBatchResult(context, taskParent, endTime, input, {
|
|
12683
|
+
value,
|
|
12684
|
+
source
|
|
12685
|
+
});
|
|
12686
|
+
}
|
|
12687
|
+
}
|
|
12688
|
+
function sameInputs(first, second) {
|
|
12689
|
+
return first.size === second.size && [...first.keys()].every((customId) => second.has(customId));
|
|
12690
|
+
}
|
|
12691
|
+
async function contextForCompletion(inputFileId, inputData) {
|
|
12692
|
+
if (!inputData.endpoint || inputData.issues.length > 0) {
|
|
12693
|
+
return void 0;
|
|
12694
|
+
}
|
|
12695
|
+
const existing = pendingBatchTraces.get(inputFileId);
|
|
12696
|
+
if (existing) {
|
|
12697
|
+
if (existing.context.endpoint !== inputData.endpoint || !sameInputs(existing.inputs, inputData.inputs)) {
|
|
12698
|
+
return void 0;
|
|
12699
|
+
}
|
|
12700
|
+
return { ...existing, inputs: inputData.inputs };
|
|
12701
|
+
}
|
|
12702
|
+
const parent = await exportParent(getSpanParentObject());
|
|
12703
|
+
if (!parent) {
|
|
12704
|
+
return void 0;
|
|
12705
|
+
}
|
|
12706
|
+
const startTime = getCurrentUnixTimestamp();
|
|
12707
|
+
return {
|
|
12708
|
+
context: {
|
|
12709
|
+
inputFileId,
|
|
12710
|
+
endpoint: inputData.endpoint,
|
|
12711
|
+
parent,
|
|
12712
|
+
taskStartTime: startTime,
|
|
12713
|
+
childStartTime: startTime
|
|
12714
|
+
},
|
|
12715
|
+
inputs: inputData.inputs
|
|
12716
|
+
};
|
|
12717
|
+
}
|
|
12718
|
+
async function completeBatch(args) {
|
|
12719
|
+
const inputData = await readBatchInputs(args.inputFileContent);
|
|
12720
|
+
const trace = await contextForCompletion(args.inputFileId, inputData);
|
|
12721
|
+
if (!trace) {
|
|
12722
|
+
logBatchInstrumentationError(
|
|
12723
|
+
"left batch spans pending",
|
|
12724
|
+
inputData.issues[0] ?? new Error("OpenAI Batch input does not match")
|
|
12725
|
+
);
|
|
12726
|
+
return;
|
|
12727
|
+
}
|
|
12728
|
+
const endTime = trace.endTime ?? getCurrentUnixTimestamp();
|
|
12729
|
+
const task = await startBatchSpan(trace.context);
|
|
12730
|
+
const taskParent = await task.export();
|
|
12731
|
+
const issues = [];
|
|
12732
|
+
const seen = /* @__PURE__ */ new Set();
|
|
12733
|
+
await Promise.all([
|
|
12734
|
+
completeResultFile({
|
|
12735
|
+
context: trace.context,
|
|
12736
|
+
endTime,
|
|
12737
|
+
file: args.outputFileContent,
|
|
12738
|
+
inputs: trace.inputs,
|
|
12739
|
+
issues,
|
|
12740
|
+
seen,
|
|
12741
|
+
source: "output",
|
|
12742
|
+
taskParent
|
|
12743
|
+
}),
|
|
12744
|
+
completeResultFile({
|
|
12745
|
+
context: trace.context,
|
|
12746
|
+
endTime,
|
|
12747
|
+
file: args.errorFileContent,
|
|
12748
|
+
inputs: trace.inputs,
|
|
12749
|
+
issues,
|
|
12750
|
+
seen,
|
|
12751
|
+
source: "error",
|
|
12752
|
+
taskParent
|
|
12753
|
+
})
|
|
12754
|
+
]);
|
|
12755
|
+
if (issues.length > 0) {
|
|
12756
|
+
logBatchInstrumentationError("left batch spans pending", issues[0]);
|
|
12757
|
+
return;
|
|
12758
|
+
}
|
|
12759
|
+
const missing = [...trace.inputs.values()].filter(
|
|
12760
|
+
({ customId }) => !seen.has(customId)
|
|
12761
|
+
);
|
|
12762
|
+
if (!trace.status || trace.status === "completed") {
|
|
12763
|
+
if (missing.length > 0) {
|
|
12764
|
+
logBatchInstrumentationError(
|
|
12765
|
+
"left batch spans pending",
|
|
12766
|
+
new Error("OpenAI Batch result files are incomplete")
|
|
12767
|
+
);
|
|
12768
|
+
return;
|
|
12769
|
+
}
|
|
12770
|
+
} else {
|
|
12771
|
+
for (const input of missing) {
|
|
12772
|
+
const child = await startBatchChild(trace.context, taskParent, input);
|
|
12773
|
+
child.log({ error: new Error(`OpenAI Batch ${trace.status}`) });
|
|
12774
|
+
child.end({ endTime });
|
|
12775
|
+
}
|
|
12776
|
+
task.log({ error: new Error(`OpenAI Batch ${trace.status}`) });
|
|
12777
|
+
}
|
|
12778
|
+
task.end({ endTime });
|
|
12779
|
+
pendingBatchTraces.delete(args.inputFileId);
|
|
12780
|
+
}
|
|
12781
|
+
var interceptOpenAIBatchTraceComplete = (target, thisArg, args) => Promise.resolve(Reflect.apply(target, thisArg, args)).then(async (result) => {
|
|
12782
|
+
try {
|
|
12783
|
+
await completeBatch(args[0]);
|
|
12784
|
+
} catch (error) {
|
|
12785
|
+
logBatchInstrumentationError("could not complete batch", error);
|
|
12786
|
+
}
|
|
12787
|
+
return result;
|
|
12788
|
+
});
|
|
12789
|
+
|
|
12133
12790
|
// src/instrumentation/plugins/openai-plugin.ts
|
|
12134
12791
|
var OpenAIPlugin = class extends BasePlugin {
|
|
12135
12792
|
constructor() {
|
|
12136
12793
|
super();
|
|
12137
12794
|
}
|
|
12138
12795
|
onEnable() {
|
|
12796
|
+
this.unsubscribers.push(
|
|
12797
|
+
openAIChannels.filesCreateTraced.intercept(
|
|
12798
|
+
interceptOpenAIFilesCreateTraced
|
|
12799
|
+
),
|
|
12800
|
+
openAIChannels.batchesRetrieveTraced.intercept(
|
|
12801
|
+
interceptOpenAIBatchesRetrieveTraced
|
|
12802
|
+
),
|
|
12803
|
+
openAIChannels.batchesCompleteTrace.intercept(
|
|
12804
|
+
interceptOpenAIBatchTraceComplete
|
|
12805
|
+
)
|
|
12806
|
+
);
|
|
12139
12807
|
this.unsubscribers.push(
|
|
12140
12808
|
traceStreamingChannel(openAIChannels.chatCompletionsCreate, {
|
|
12141
12809
|
name: "Chat Completion",
|
|
12142
12810
|
type: "llm" /* LLM */,
|
|
12143
|
-
extractInput: ([params]) =>
|
|
12144
|
-
const { messages, ...metadata } = params;
|
|
12145
|
-
return {
|
|
12146
|
-
input: processInputAttachments(messages),
|
|
12147
|
-
metadata: { ...metadata, provider: "openai" }
|
|
12148
|
-
};
|
|
12149
|
-
},
|
|
12811
|
+
extractInput: ([params]) => extractOpenAIChatInput(params),
|
|
12150
12812
|
extractOutput: (result) => {
|
|
12151
12813
|
return result?.choices;
|
|
12152
12814
|
},
|
|
@@ -12192,13 +12854,7 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
12192
12854
|
traceStreamingChannel(openAIChannels.betaChatCompletionsParse, {
|
|
12193
12855
|
name: "Chat Completion",
|
|
12194
12856
|
type: "llm" /* LLM */,
|
|
12195
|
-
extractInput: ([params]) =>
|
|
12196
|
-
const { messages, ...metadata } = params;
|
|
12197
|
-
return {
|
|
12198
|
-
input: processInputAttachments(messages),
|
|
12199
|
-
metadata: { ...metadata, provider: "openai" }
|
|
12200
|
-
};
|
|
12201
|
-
},
|
|
12857
|
+
extractInput: ([params]) => extractOpenAIChatInput(params),
|
|
12202
12858
|
extractOutput: (result) => {
|
|
12203
12859
|
return result?.choices;
|
|
12204
12860
|
},
|
|
@@ -12220,13 +12876,7 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
12220
12876
|
traceSyncStreamChannel(openAIChannels.betaChatCompletionsStream, {
|
|
12221
12877
|
name: "Chat Completion",
|
|
12222
12878
|
type: "llm" /* LLM */,
|
|
12223
|
-
extractInput: ([params]) =>
|
|
12224
|
-
const { messages, ...metadata } = params;
|
|
12225
|
-
return {
|
|
12226
|
-
input: processInputAttachments(messages),
|
|
12227
|
-
metadata: { ...metadata, provider: "openai" }
|
|
12228
|
-
};
|
|
12229
|
-
}
|
|
12879
|
+
extractInput: ([params]) => extractOpenAIChatInput(params)
|
|
12230
12880
|
})
|
|
12231
12881
|
);
|
|
12232
12882
|
this.unsubscribers.push(
|
|
@@ -12256,23 +12906,11 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
12256
12906
|
traceStreamingChannel(openAIChannels.responsesCreate, {
|
|
12257
12907
|
name: "openai.responses.create",
|
|
12258
12908
|
type: "llm" /* LLM */,
|
|
12259
|
-
extractInput: ([params]) =>
|
|
12260
|
-
const { input, ...metadata } = params;
|
|
12261
|
-
return {
|
|
12262
|
-
input: processInputAttachments(input),
|
|
12263
|
-
metadata: { ...metadata, provider: "openai" }
|
|
12264
|
-
};
|
|
12265
|
-
},
|
|
12909
|
+
extractInput: ([params]) => extractOpenAIResponsesInput(params),
|
|
12266
12910
|
extractOutput: (result) => {
|
|
12267
12911
|
return processImagesInOutput(result?.output);
|
|
12268
12912
|
},
|
|
12269
|
-
extractMetadata: (result) =>
|
|
12270
|
-
if (!result) {
|
|
12271
|
-
return void 0;
|
|
12272
|
-
}
|
|
12273
|
-
const { output: _output, usage: _usage, ...metadata } = result;
|
|
12274
|
-
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
12275
|
-
},
|
|
12913
|
+
extractMetadata: (result) => extractOpenAIResponsesMetadata(result),
|
|
12276
12914
|
extractMetrics: (result, startTime, endEvent) => {
|
|
12277
12915
|
const metrics = withCachedMetric(
|
|
12278
12916
|
parseMetricsFromUsage(result?.usage),
|
|
@@ -12291,13 +12929,7 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
12291
12929
|
traceSyncStreamChannel(openAIChannels.responsesStream, {
|
|
12292
12930
|
name: "openai.responses.create",
|
|
12293
12931
|
type: "llm" /* LLM */,
|
|
12294
|
-
extractInput: ([params]) =>
|
|
12295
|
-
const { input, ...metadata } = params;
|
|
12296
|
-
return {
|
|
12297
|
-
input: processInputAttachments(input),
|
|
12298
|
-
metadata: { ...metadata, provider: "openai" }
|
|
12299
|
-
};
|
|
12300
|
-
},
|
|
12932
|
+
extractInput: ([params]) => extractOpenAIResponsesInput(params),
|
|
12301
12933
|
extractFromEvent: (event) => {
|
|
12302
12934
|
if (event.type !== "response.completed" || !event.response) {
|
|
12303
12935
|
return {};
|
|
@@ -12320,23 +12952,11 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
12320
12952
|
traceStreamingChannel(openAIChannels.responsesParse, {
|
|
12321
12953
|
name: "openai.responses.parse",
|
|
12322
12954
|
type: "llm" /* LLM */,
|
|
12323
|
-
extractInput: ([params]) =>
|
|
12324
|
-
const { input, ...metadata } = params;
|
|
12325
|
-
return {
|
|
12326
|
-
input: processInputAttachments(input),
|
|
12327
|
-
metadata: { ...metadata, provider: "openai" }
|
|
12328
|
-
};
|
|
12329
|
-
},
|
|
12955
|
+
extractInput: ([params]) => extractOpenAIResponsesInput(params),
|
|
12330
12956
|
extractOutput: (result) => {
|
|
12331
12957
|
return processImagesInOutput(result?.output);
|
|
12332
12958
|
},
|
|
12333
|
-
extractMetadata: (result) =>
|
|
12334
|
-
if (!result) {
|
|
12335
|
-
return void 0;
|
|
12336
|
-
}
|
|
12337
|
-
const { output: _output, usage: _usage, ...metadata } = result;
|
|
12338
|
-
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
12339
|
-
},
|
|
12959
|
+
extractMetadata: (result) => extractOpenAIResponsesMetadata(result),
|
|
12340
12960
|
extractMetrics: (result, startTime, endEvent) => {
|
|
12341
12961
|
const metrics = withCachedMetric(
|
|
12342
12962
|
parseMetricsFromUsage(result?.usage),
|
|
@@ -12355,23 +12975,11 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
12355
12975
|
traceAsyncChannel(openAIChannels.responsesCompact, {
|
|
12356
12976
|
name: "openai.responses.compact",
|
|
12357
12977
|
type: "llm" /* LLM */,
|
|
12358
|
-
extractInput: ([params]) =>
|
|
12359
|
-
const { input, ...metadata } = params;
|
|
12360
|
-
return {
|
|
12361
|
-
input: processInputAttachments(input),
|
|
12362
|
-
metadata: { ...metadata, provider: "openai" }
|
|
12363
|
-
};
|
|
12364
|
-
},
|
|
12978
|
+
extractInput: ([params]) => extractOpenAIResponsesInput(params),
|
|
12365
12979
|
extractOutput: (result) => {
|
|
12366
12980
|
return processImagesInOutput(result?.output);
|
|
12367
12981
|
},
|
|
12368
|
-
extractMetadata: (result) =>
|
|
12369
|
-
if (!result) {
|
|
12370
|
-
return void 0;
|
|
12371
|
-
}
|
|
12372
|
-
const { output: _output, usage: _usage, ...metadata } = result;
|
|
12373
|
-
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
12374
|
-
},
|
|
12982
|
+
extractMetadata: (result) => extractOpenAIResponsesMetadata(result),
|
|
12375
12983
|
extractMetrics: (result, startTime, endEvent) => {
|
|
12376
12984
|
const metrics = withCachedMetric(
|
|
12377
12985
|
parseMetricsFromUsage(result?.usage),
|
|
@@ -12427,35 +13035,6 @@ function withCachedMetric(metrics, result, endEvent) {
|
|
|
12427
13035
|
cached
|
|
12428
13036
|
};
|
|
12429
13037
|
}
|
|
12430
|
-
function processImagesInOutput(output) {
|
|
12431
|
-
if (Array.isArray(output)) {
|
|
12432
|
-
return output.map(processImagesInOutput);
|
|
12433
|
-
}
|
|
12434
|
-
if (isObject(output)) {
|
|
12435
|
-
if (output.type === "image_generation_call" && output.result && typeof output.result === "string") {
|
|
12436
|
-
const fileExtension = output.output_format || "png";
|
|
12437
|
-
const contentType = `image/${fileExtension}`;
|
|
12438
|
-
const baseFilename = output.revised_prompt && typeof output.revised_prompt === "string" ? output.revised_prompt.slice(0, 50).replace(/[^a-zA-Z0-9]/g, "_") : "generated_image";
|
|
12439
|
-
const filename = `${baseFilename}.${fileExtension}`;
|
|
12440
|
-
const binaryString = atob(output.result);
|
|
12441
|
-
const bytes = new Uint8Array(binaryString.length);
|
|
12442
|
-
for (let i = 0; i < binaryString.length; i++) {
|
|
12443
|
-
bytes[i] = binaryString.charCodeAt(i);
|
|
12444
|
-
}
|
|
12445
|
-
const blob = new Blob([bytes], { type: contentType });
|
|
12446
|
-
const attachment = new Attachment({
|
|
12447
|
-
data: blob,
|
|
12448
|
-
filename,
|
|
12449
|
-
contentType
|
|
12450
|
-
});
|
|
12451
|
-
return {
|
|
12452
|
-
...output,
|
|
12453
|
-
result: attachment
|
|
12454
|
-
};
|
|
12455
|
-
}
|
|
12456
|
-
}
|
|
12457
|
-
return output;
|
|
12458
|
-
}
|
|
12459
13038
|
function mergeLogprobTokens(existing, incoming) {
|
|
12460
13039
|
if (incoming === void 0) {
|
|
12461
13040
|
return existing;
|
|
@@ -17599,6 +18178,12 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
|
|
|
17599
18178
|
if (!activeEntry) {
|
|
17600
18179
|
return result;
|
|
17601
18180
|
}
|
|
18181
|
+
const executionOptions = args[1];
|
|
18182
|
+
const toolCallId = isObject(executionOptions) ? executionOptions.toolCallId : void 0;
|
|
18183
|
+
const toolInput = {
|
|
18184
|
+
input: serializeToolExecutionInput(args),
|
|
18185
|
+
...typeof toolCallId === "string" ? { metadata: { toolCallId } } : {}
|
|
18186
|
+
};
|
|
17602
18187
|
if (isAsyncGenerator(result)) {
|
|
17603
18188
|
return (async function* () {
|
|
17604
18189
|
const span = activeEntry.parentSpan.startSpan(
|
|
@@ -17612,7 +18197,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
|
|
|
17612
18197
|
INSTRUMENTATION_NAMES.AI_SDK
|
|
17613
18198
|
)
|
|
17614
18199
|
);
|
|
17615
|
-
span.log(
|
|
18200
|
+
span.log(toolInput);
|
|
17616
18201
|
try {
|
|
17617
18202
|
let lastValue;
|
|
17618
18203
|
for await (const value of result) {
|
|
@@ -17630,7 +18215,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
|
|
|
17630
18215
|
}
|
|
17631
18216
|
return activeEntry.parentSpan.traced(
|
|
17632
18217
|
async (span) => {
|
|
17633
|
-
span.log(
|
|
18218
|
+
span.log(toolInput);
|
|
17634
18219
|
const awaitedResult = await result;
|
|
17635
18220
|
span.log({ output: awaitedResult });
|
|
17636
18221
|
return awaitedResult;
|
|
@@ -31752,14 +32337,17 @@ function getMetricsFromResponse(response) {
|
|
|
31752
32337
|
if (!isRecord(usageMetadata)) {
|
|
31753
32338
|
continue;
|
|
31754
32339
|
}
|
|
31755
|
-
const inputTokenDetails = usageMetadata.input_token_details;
|
|
32340
|
+
const inputTokenDetails = isRecord(usageMetadata.input_token_details) ? usageMetadata.input_token_details : {};
|
|
31756
32341
|
const outputTokenDetails = usageMetadata.output_token_details;
|
|
31757
32342
|
return normalizeTokenMetrics({
|
|
31758
32343
|
total_tokens: usageMetadata.total_tokens,
|
|
31759
32344
|
prompt_tokens: usageMetadata.input_tokens,
|
|
31760
32345
|
completion_tokens: usageMetadata.output_tokens,
|
|
31761
|
-
|
|
31762
|
-
|
|
32346
|
+
// Prefer TTL-specific cache writes over the aggregate when available.
|
|
32347
|
+
prompt_cache_creation_tokens: inputTokenDetails.ephemeral_5m_input_tokens == null && inputTokenDetails.ephemeral_1h_input_tokens == null ? inputTokenDetails.cache_creation : void 0,
|
|
32348
|
+
prompt_cache_creation_5m_tokens: inputTokenDetails.ephemeral_5m_input_tokens,
|
|
32349
|
+
prompt_cache_creation_1h_tokens: inputTokenDetails.ephemeral_1h_input_tokens,
|
|
32350
|
+
prompt_cached_tokens: inputTokenDetails.cache_read,
|
|
31763
32351
|
completion_reasoning_tokens: isRecord(outputTokenDetails) ? outputTokenDetails.reasoning : void 0
|
|
31764
32352
|
});
|
|
31765
32353
|
}
|
|
@@ -32475,7 +33063,7 @@ function extractSession(event) {
|
|
|
32475
33063
|
return isObject(candidate) && typeof candidate.prompt === "function" ? candidate : void 0;
|
|
32476
33064
|
}
|
|
32477
33065
|
function isPiAgent(value) {
|
|
32478
|
-
return isObject(value) && typeof value.streamFn === "function" && typeof value.subscribe === "function";
|
|
33066
|
+
return isObject(value) && (typeof value.streamFunction === "function" || typeof value.streamFn === "function") && typeof value.subscribe === "function";
|
|
32479
33067
|
}
|
|
32480
33068
|
function promptContextStore() {
|
|
32481
33069
|
piPromptContextStore ??= isomorph_default.newAsyncLocalStorage();
|
|
@@ -32485,17 +33073,21 @@ function currentPiPromptState() {
|
|
|
32485
33073
|
return promptContextStore().getStore();
|
|
32486
33074
|
}
|
|
32487
33075
|
function installPiAgentInstrumentation(agent) {
|
|
33076
|
+
const property = typeof agent.streamFunction === "function" ? "streamFunction" : "streamFn";
|
|
33077
|
+
const streamFunction = agent[property];
|
|
32488
33078
|
const existing = piAgentPatchStates.get(agent);
|
|
32489
|
-
if (!existing ||
|
|
33079
|
+
if (streamFunction && (!existing || existing.property !== property || streamFunction !== existing.wrappedStreamFunction)) {
|
|
32490
33080
|
const patchState = {
|
|
32491
|
-
|
|
32492
|
-
|
|
33081
|
+
originalStreamFunction: streamFunction,
|
|
33082
|
+
property,
|
|
33083
|
+
wrappedStreamFunction: streamFunction
|
|
32493
33084
|
};
|
|
32494
|
-
patchState.
|
|
33085
|
+
patchState.wrappedStreamFunction = makeInstrumentedStreamFunction(
|
|
32495
33086
|
agent,
|
|
32496
|
-
patchState.
|
|
33087
|
+
patchState.originalStreamFunction,
|
|
33088
|
+
property
|
|
32497
33089
|
);
|
|
32498
|
-
agent
|
|
33090
|
+
agent[property] = patchState.wrappedStreamFunction;
|
|
32499
33091
|
piAgentPatchStates.set(agent, patchState);
|
|
32500
33092
|
}
|
|
32501
33093
|
if (piAgentEventSubscriptions.has(agent)) {
|
|
@@ -32520,15 +33112,21 @@ function installPiAgentInstrumentation(agent) {
|
|
|
32520
33112
|
logInstrumentationError4("Pi Coding Agent event subscription", error);
|
|
32521
33113
|
}
|
|
32522
33114
|
}
|
|
32523
|
-
function
|
|
32524
|
-
return async function
|
|
32525
|
-
const invokeOriginal = () => Reflect.apply(
|
|
33115
|
+
function makeInstrumentedStreamFunction(agent, originalStreamFunction, property) {
|
|
33116
|
+
return async function instrumentedPiStreamFunction(model, context, options) {
|
|
33117
|
+
const invokeOriginal = () => Reflect.apply(originalStreamFunction, this, [model, context, options]);
|
|
32526
33118
|
const state = currentPiPromptState();
|
|
32527
33119
|
if (!state || state.agent !== agent || state.finalized) {
|
|
32528
33120
|
return invokeOriginal();
|
|
32529
33121
|
}
|
|
32530
33122
|
wrapPiToolExecutors(context.tools);
|
|
32531
|
-
const llmState = await startPiLlmSpan(
|
|
33123
|
+
const llmState = await startPiLlmSpan(
|
|
33124
|
+
state,
|
|
33125
|
+
model,
|
|
33126
|
+
context,
|
|
33127
|
+
property,
|
|
33128
|
+
options
|
|
33129
|
+
);
|
|
32532
33130
|
try {
|
|
32533
33131
|
const stream = await runWithAutoInstrumentationSuppressed(invokeOriginal);
|
|
32534
33132
|
return patchAssistantMessageStream(stream, state, llmState);
|
|
@@ -32565,12 +33163,12 @@ function wrapPiToolExecutors(tools) {
|
|
|
32565
33163
|
}
|
|
32566
33164
|
}
|
|
32567
33165
|
}
|
|
32568
|
-
async function startPiLlmSpan(state, model, context, options) {
|
|
33166
|
+
async function startPiLlmSpan(state, model, context, property, options) {
|
|
32569
33167
|
const metadata = {
|
|
32570
33168
|
...extractModelMetadata2(model),
|
|
32571
33169
|
...extractStreamOptionsMetadata(options),
|
|
32572
33170
|
...extractToolMetadata(context.tools),
|
|
32573
|
-
"pi_coding_agent.operation":
|
|
33171
|
+
"pi_coding_agent.operation": `agent.${property}`
|
|
32574
33172
|
};
|
|
32575
33173
|
const span = startSpan(
|
|
32576
33174
|
withSpanInstrumentationName(
|
|
@@ -36881,7 +37479,15 @@ var MAX_EVE_PROVIDER_CACHE_ENTRIES = 1e4;
|
|
|
36881
37479
|
function createEveInstrumentationProvider(options = {}) {
|
|
36882
37480
|
const bridge = new EveProviderBridge(options.metadata);
|
|
36883
37481
|
return {
|
|
37482
|
+
// Eve versions before tracePolicy use capture to decide whether provider
|
|
37483
|
+
// events include content. Newer versions prefer tracePolicy when both are
|
|
37484
|
+
// present, so keep the deprecated field for backwards compatibility.
|
|
36884
37485
|
capture: "content",
|
|
37486
|
+
tracePolicy: () => ({
|
|
37487
|
+
emit: true,
|
|
37488
|
+
recordInputs: true,
|
|
37489
|
+
recordOutputs: true
|
|
37490
|
+
}),
|
|
36885
37491
|
events: {
|
|
36886
37492
|
"action.completed": (event, context) => bridge.handleActionTerminal(event, context),
|
|
36887
37493
|
"action.failed": (event, context) => bridge.handleActionTerminal(event, context),
|