braintrust 3.7.0 → 3.8.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/LICENSE +201 -0
- package/dev/dist/index.d.mts +144 -2
- package/dev/dist/index.d.ts +144 -2
- package/dev/dist/index.js +3322 -799
- package/dev/dist/index.mjs +3214 -691
- package/dist/auto-instrumentations/bundler/esbuild.cjs +377 -13
- package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
- package/dist/auto-instrumentations/bundler/rollup.cjs +377 -13
- package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
- package/dist/auto-instrumentations/bundler/vite.cjs +377 -13
- package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
- package/dist/auto-instrumentations/bundler/webpack-loader.cjs +377 -13
- package/dist/auto-instrumentations/bundler/webpack-loader.d.ts +11 -9
- package/dist/auto-instrumentations/bundler/webpack.cjs +377 -13
- package/dist/auto-instrumentations/bundler/webpack.mjs +2 -2
- package/dist/auto-instrumentations/{chunk-EVUKFMHG.mjs → chunk-ITP7RAUY.mjs} +21 -3
- package/dist/auto-instrumentations/{chunk-ZK2IYER2.mjs → chunk-MD7W27YH.mjs} +5 -1
- package/dist/auto-instrumentations/{chunk-AKEXR4AL.mjs → chunk-OLBMPZXE.mjs} +378 -14
- package/dist/auto-instrumentations/{chunk-VLEJ5AEK.mjs → chunk-P5YLNB2A.mjs} +21 -3
- package/dist/auto-instrumentations/hook.mjs +393 -19
- package/dist/auto-instrumentations/index.cjs +379 -13
- package/dist/auto-instrumentations/index.d.mts +5 -1
- package/dist/auto-instrumentations/index.d.ts +5 -1
- package/dist/auto-instrumentations/index.mjs +5 -1
- package/dist/auto-instrumentations/loader/cjs-patch.cjs +34 -6
- package/dist/auto-instrumentations/loader/cjs-patch.d.mts +1 -0
- package/dist/auto-instrumentations/loader/cjs-patch.d.ts +1 -0
- package/dist/auto-instrumentations/loader/cjs-patch.mjs +15 -5
- package/dist/auto-instrumentations/loader/esm-hook.mjs +8 -3
- package/dist/auto-instrumentations/loader/get-package-version.cjs +20 -2
- package/dist/auto-instrumentations/loader/get-package-version.mjs +1 -1
- package/dist/browser.d.mts +199 -44
- package/dist/browser.d.ts +199 -44
- package/dist/browser.js +7086 -6747
- package/dist/browser.mjs +7086 -6747
- package/dist/cli.js +3200 -677
- package/dist/edge-light.d.mts +1 -1
- package/dist/edge-light.d.ts +1 -1
- package/dist/edge-light.js +12645 -12215
- package/dist/edge-light.mjs +12645 -12215
- package/dist/index.d.mts +199 -44
- package/dist/index.d.ts +199 -44
- package/dist/index.js +7173 -6834
- package/dist/index.mjs +7022 -6683
- package/dist/instrumentation/index.d.mts +7 -0
- package/dist/instrumentation/index.d.ts +7 -0
- package/dist/instrumentation/index.js +3170 -669
- package/dist/instrumentation/index.mjs +3170 -669
- package/dist/workerd.d.mts +1 -1
- package/dist/workerd.d.ts +1 -1
- package/dist/workerd.js +12645 -12215
- package/dist/workerd.mjs +12645 -12215
- package/package.json +45 -45
|
@@ -70,7 +70,7 @@ var DefaultTracingChannel = class {
|
|
|
70
70
|
}
|
|
71
71
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
72
72
|
tracePromise(fn, _message, thisArg, ...args) {
|
|
73
|
-
return
|
|
73
|
+
return fn.apply(thisArg, args);
|
|
74
74
|
}
|
|
75
75
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
76
76
|
traceCallback(fn, _position, _message, thisArg, ...args) {
|
|
@@ -90,6 +90,7 @@ var iso = {
|
|
|
90
90
|
processOn: (_0, _1) => {
|
|
91
91
|
},
|
|
92
92
|
basename: (filepath) => filepath.split(/[\\/]/).pop() || filepath,
|
|
93
|
+
// eslint-disable-next-line no-restricted-properties -- preserving intentional console usage.
|
|
93
94
|
writeln: (text) => console.log(text)
|
|
94
95
|
};
|
|
95
96
|
var isomorph_default = iso;
|
|
@@ -125,7 +126,7 @@ function patchStreamIfNeeded(stream, options) {
|
|
|
125
126
|
if (!completed) {
|
|
126
127
|
completed = true;
|
|
127
128
|
try {
|
|
128
|
-
options.onComplete(chunks);
|
|
129
|
+
await options.onComplete(chunks);
|
|
129
130
|
} catch (error) {
|
|
130
131
|
console.error("Error in stream onComplete handler:", error);
|
|
131
132
|
}
|
|
@@ -137,7 +138,7 @@ function patchStreamIfNeeded(stream, options) {
|
|
|
137
138
|
chunks.push(chunk);
|
|
138
139
|
if (options.onChunk) {
|
|
139
140
|
try {
|
|
140
|
-
options.onChunk(chunk);
|
|
141
|
+
await options.onChunk(chunk);
|
|
141
142
|
} catch (error) {
|
|
142
143
|
console.error("Error in stream onChunk handler:", error);
|
|
143
144
|
}
|
|
@@ -150,7 +151,7 @@ function patchStreamIfNeeded(stream, options) {
|
|
|
150
151
|
completed = true;
|
|
151
152
|
if (options.onError) {
|
|
152
153
|
try {
|
|
153
|
-
options.onError(
|
|
154
|
+
await options.onError(
|
|
154
155
|
error instanceof Error ? error : new Error(String(error)),
|
|
155
156
|
chunks
|
|
156
157
|
);
|
|
@@ -168,7 +169,7 @@ function patchStreamIfNeeded(stream, options) {
|
|
|
168
169
|
if (!completed) {
|
|
169
170
|
completed = true;
|
|
170
171
|
try {
|
|
171
|
-
options.onComplete(chunks);
|
|
172
|
+
await options.onComplete(chunks);
|
|
172
173
|
} catch (error) {
|
|
173
174
|
console.error("Error in stream onComplete handler:", error);
|
|
174
175
|
}
|
|
@@ -185,7 +186,7 @@ function patchStreamIfNeeded(stream, options) {
|
|
|
185
186
|
const error = rawError instanceof Error ? rawError : new Error(String(rawError));
|
|
186
187
|
if (options.onError) {
|
|
187
188
|
try {
|
|
188
|
-
options.onError(error, chunks);
|
|
189
|
+
await options.onError(error, chunks);
|
|
189
190
|
} catch (handlerError) {
|
|
190
191
|
console.error("Error in stream onError handler:", handlerError);
|
|
191
192
|
}
|
|
@@ -1537,6 +1538,15 @@ function addAzureBlobHeaders(headers, url) {
|
|
|
1537
1538
|
headers["x-ms-blob-type"] = "BlockBlob";
|
|
1538
1539
|
}
|
|
1539
1540
|
}
|
|
1541
|
+
function filterFrom(record, keys) {
|
|
1542
|
+
const out = {};
|
|
1543
|
+
for (const k of Object.keys(record)) {
|
|
1544
|
+
if (!keys.includes(k)) {
|
|
1545
|
+
out[k] = record[k];
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1548
|
+
return out;
|
|
1549
|
+
}
|
|
1540
1550
|
|
|
1541
1551
|
// src/generated_types.ts
|
|
1542
1552
|
import { z as z6 } from "zod/v3";
|
|
@@ -1748,6 +1758,16 @@ var NullableSavedFunctionId = z6.union([
|
|
|
1748
1758
|
}),
|
|
1749
1759
|
z6.null()
|
|
1750
1760
|
]);
|
|
1761
|
+
var TopicMapGenerationSettings = z6.object({
|
|
1762
|
+
algorithm: z6.enum(["hdbscan", "kmeans"]),
|
|
1763
|
+
dimension_reduction: z6.enum(["umap", "pca", "none"]),
|
|
1764
|
+
sample_size: z6.number().int().gt(0).optional(),
|
|
1765
|
+
n_clusters: z6.number().int().gt(0).optional(),
|
|
1766
|
+
min_cluster_size: z6.number().int().gt(0).optional(),
|
|
1767
|
+
min_samples: z6.number().int().gt(0).optional(),
|
|
1768
|
+
hierarchy_threshold: z6.number().int().gt(0).optional(),
|
|
1769
|
+
naming_model: z6.string().optional()
|
|
1770
|
+
});
|
|
1751
1771
|
var TopicMapData = z6.object({
|
|
1752
1772
|
type: z6.literal("topic_map"),
|
|
1753
1773
|
source_facet: z6.string(),
|
|
@@ -1755,6 +1775,7 @@ var TopicMapData = z6.object({
|
|
|
1755
1775
|
bundle_key: z6.string().optional(),
|
|
1756
1776
|
report_key: z6.string().optional(),
|
|
1757
1777
|
topic_names: z6.record(z6.string()).optional(),
|
|
1778
|
+
generation_settings: TopicMapGenerationSettings.optional(),
|
|
1758
1779
|
distance_threshold: z6.number().optional()
|
|
1759
1780
|
});
|
|
1760
1781
|
var BatchedFacetData = z6.object({
|
|
@@ -1979,6 +2000,7 @@ var Dataset = z6.object({
|
|
|
1979
2000
|
created: z6.union([z6.string(), z6.null()]).optional(),
|
|
1980
2001
|
deleted_at: z6.union([z6.string(), z6.null()]).optional(),
|
|
1981
2002
|
user_id: z6.union([z6.string(), z6.null()]).optional(),
|
|
2003
|
+
tags: z6.union([z6.array(z6.string()), z6.null()]).optional(),
|
|
1982
2004
|
metadata: z6.union([z6.object({}).partial().passthrough(), z6.null()]).optional(),
|
|
1983
2005
|
url_slug: z6.string()
|
|
1984
2006
|
});
|
|
@@ -2061,6 +2083,14 @@ var DatasetEvent = z6.object({
|
|
|
2061
2083
|
z6.null()
|
|
2062
2084
|
]).optional()
|
|
2063
2085
|
});
|
|
2086
|
+
var DatasetSnapshot = z6.object({
|
|
2087
|
+
id: z6.string().uuid(),
|
|
2088
|
+
dataset_id: z6.string().uuid(),
|
|
2089
|
+
name: z6.string(),
|
|
2090
|
+
description: z6.union([z6.string(), z6.null()]),
|
|
2091
|
+
xact_id: z6.string(),
|
|
2092
|
+
created: z6.union([z6.string(), z6.null()])
|
|
2093
|
+
});
|
|
2064
2094
|
var EnvVar = z6.object({
|
|
2065
2095
|
id: z6.string().uuid(),
|
|
2066
2096
|
object_type: z6.enum(["organization", "project", "function"]),
|
|
@@ -2819,6 +2849,8 @@ var TopicAutomationConfig = z6.object({
|
|
|
2819
2849
|
scope: z6.union([SpanScope, TraceScope, GroupScope, z6.null()]).optional(),
|
|
2820
2850
|
data_scope: TopicAutomationDataScope.optional(),
|
|
2821
2851
|
btql_filter: z6.union([z6.string(), z6.null()]).optional(),
|
|
2852
|
+
rerun_seconds: z6.union([z6.number(), z6.null()]).optional(),
|
|
2853
|
+
relabel_overlap_seconds: z6.union([z6.number(), z6.null()]).optional(),
|
|
2822
2854
|
backfill_time_range: z6.union([
|
|
2823
2855
|
z6.string(),
|
|
2824
2856
|
z6.object({ from: z6.string(), to: z6.string() }),
|
|
@@ -3155,7 +3187,8 @@ var User = z6.object({
|
|
|
3155
3187
|
family_name: z6.union([z6.string(), z6.null()]).optional(),
|
|
3156
3188
|
email: z6.union([z6.string(), z6.null()]).optional(),
|
|
3157
3189
|
avatar_url: z6.union([z6.string(), z6.null()]).optional(),
|
|
3158
|
-
created: z6.union([z6.string(), z6.null()]).optional()
|
|
3190
|
+
created: z6.union([z6.string(), z6.null()]).optional(),
|
|
3191
|
+
last_active_at: z6.union([z6.number(), z6.null()]).optional()
|
|
3159
3192
|
});
|
|
3160
3193
|
var ViewDataSearch = z6.union([
|
|
3161
3194
|
z6.object({
|
|
@@ -4287,6 +4320,15 @@ var BRAINTRUST_CURRENT_SPAN_STORE = Symbol.for(
|
|
|
4287
4320
|
"braintrust.currentSpanStore"
|
|
4288
4321
|
);
|
|
4289
4322
|
var ContextManager = class {
|
|
4323
|
+
/**
|
|
4324
|
+
* Returns the value to store in the ALS bound to a TracingChannel's start event.
|
|
4325
|
+
* In default mode this is the Span itself; in OTEL mode it is the OTEL Context
|
|
4326
|
+
* containing the span so that OTEL's own ALS stores a proper Context object.
|
|
4327
|
+
*/
|
|
4328
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
4329
|
+
wrapSpanForStore(span) {
|
|
4330
|
+
return span;
|
|
4331
|
+
}
|
|
4290
4332
|
};
|
|
4291
4333
|
var BraintrustContextManager = class extends ContextManager {
|
|
4292
4334
|
_currentSpan;
|
|
@@ -8080,18 +8122,22 @@ function ensureSpanStateForEvent(states, config, event, channelName) {
|
|
|
8080
8122
|
function bindCurrentSpanStoreToStart(tracingChannel, states, config, channelName) {
|
|
8081
8123
|
const state = _internalGetGlobalState();
|
|
8082
8124
|
const startChannel = tracingChannel.start;
|
|
8083
|
-
const
|
|
8125
|
+
const contextManager = state?.contextManager;
|
|
8126
|
+
const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
|
|
8084
8127
|
if (!currentSpanStore || !startChannel) {
|
|
8085
8128
|
return void 0;
|
|
8086
8129
|
}
|
|
8087
8130
|
startChannel.bindStore(
|
|
8088
8131
|
currentSpanStore,
|
|
8089
|
-
(event) =>
|
|
8090
|
-
|
|
8091
|
-
|
|
8092
|
-
|
|
8093
|
-
|
|
8094
|
-
|
|
8132
|
+
(event) => {
|
|
8133
|
+
const span = ensureSpanStateForEvent(
|
|
8134
|
+
states,
|
|
8135
|
+
config,
|
|
8136
|
+
event,
|
|
8137
|
+
channelName
|
|
8138
|
+
).span;
|
|
8139
|
+
return contextManager.wrapSpanForStore(span);
|
|
8140
|
+
}
|
|
8095
8141
|
);
|
|
8096
8142
|
return () => {
|
|
8097
8143
|
startChannel.unbindStore(currentSpanStore);
|
|
@@ -8108,6 +8154,26 @@ function logErrorAndEnd(states, event) {
|
|
|
8108
8154
|
spanData.span.end();
|
|
8109
8155
|
states.delete(event);
|
|
8110
8156
|
}
|
|
8157
|
+
function runStreamingCompletionHook(args) {
|
|
8158
|
+
if (!args.config.onComplete) {
|
|
8159
|
+
return;
|
|
8160
|
+
}
|
|
8161
|
+
try {
|
|
8162
|
+
args.config.onComplete({
|
|
8163
|
+
channelName: args.channelName,
|
|
8164
|
+
...args.chunks ? { chunks: args.chunks } : {},
|
|
8165
|
+
endEvent: args.endEvent,
|
|
8166
|
+
...args.metadata !== void 0 ? { metadata: args.metadata } : {},
|
|
8167
|
+
metrics: args.metrics,
|
|
8168
|
+
output: args.output,
|
|
8169
|
+
result: args.result,
|
|
8170
|
+
span: args.span,
|
|
8171
|
+
startTime: args.startTime
|
|
8172
|
+
});
|
|
8173
|
+
} catch (error) {
|
|
8174
|
+
console.error(`Error in onComplete hook for ${args.channelName}:`, error);
|
|
8175
|
+
}
|
|
8176
|
+
}
|
|
8111
8177
|
function traceAsyncChannel(channel2, config) {
|
|
8112
8178
|
const tracingChannel = channel2.tracingChannel();
|
|
8113
8179
|
const states = /* @__PURE__ */ new WeakMap();
|
|
@@ -8235,6 +8301,18 @@ function traceStreamingChannel(channel2, config) {
|
|
|
8235
8301
|
} else if (metrics.time_to_first_token === void 0 && chunks.length > 0) {
|
|
8236
8302
|
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
8237
8303
|
}
|
|
8304
|
+
runStreamingCompletionHook({
|
|
8305
|
+
channelName,
|
|
8306
|
+
chunks,
|
|
8307
|
+
config,
|
|
8308
|
+
endEvent: asyncEndEvent,
|
|
8309
|
+
...metadata !== void 0 ? { metadata } : {},
|
|
8310
|
+
metrics,
|
|
8311
|
+
output,
|
|
8312
|
+
result: asyncEndEvent.result,
|
|
8313
|
+
span,
|
|
8314
|
+
startTime
|
|
8315
|
+
});
|
|
8238
8316
|
span.log({
|
|
8239
8317
|
output,
|
|
8240
8318
|
...metadata !== void 0 ? { metadata } : {},
|
|
@@ -8284,6 +8362,17 @@ function traceStreamingChannel(channel2, config) {
|
|
|
8284
8362
|
asyncEndEvent.result,
|
|
8285
8363
|
asyncEndEvent
|
|
8286
8364
|
);
|
|
8365
|
+
runStreamingCompletionHook({
|
|
8366
|
+
channelName,
|
|
8367
|
+
config,
|
|
8368
|
+
endEvent: asyncEndEvent,
|
|
8369
|
+
...normalizeMetadata(metadata) !== void 0 ? { metadata: normalizeMetadata(metadata) } : {},
|
|
8370
|
+
metrics,
|
|
8371
|
+
output,
|
|
8372
|
+
result: asyncEndEvent.result,
|
|
8373
|
+
span,
|
|
8374
|
+
startTime
|
|
8375
|
+
});
|
|
8287
8376
|
span.log({
|
|
8288
8377
|
output,
|
|
8289
8378
|
...normalizeMetadata(metadata) !== void 0 ? { metadata: normalizeMetadata(metadata) } : {},
|
|
@@ -8332,51 +8421,28 @@ function traceSyncStreamChannel(channel2, config) {
|
|
|
8332
8421
|
}
|
|
8333
8422
|
const { span, startTime } = spanData;
|
|
8334
8423
|
const endEvent = event;
|
|
8335
|
-
|
|
8336
|
-
|
|
8337
|
-
|
|
8338
|
-
|
|
8339
|
-
|
|
8340
|
-
|
|
8341
|
-
|
|
8342
|
-
|
|
8343
|
-
|
|
8344
|
-
|
|
8345
|
-
|
|
8346
|
-
|
|
8347
|
-
|
|
8348
|
-
return;
|
|
8349
|
-
}
|
|
8350
|
-
let first = true;
|
|
8351
|
-
stream.on("chunk", () => {
|
|
8352
|
-
if (first) {
|
|
8353
|
-
span.log({
|
|
8354
|
-
metrics: {
|
|
8355
|
-
time_to_first_token: getCurrentUnixTimestamp() - startTime
|
|
8356
|
-
}
|
|
8357
|
-
});
|
|
8358
|
-
first = false;
|
|
8359
|
-
}
|
|
8360
|
-
});
|
|
8361
|
-
stream.on("chatCompletion", (completion) => {
|
|
8362
|
-
try {
|
|
8363
|
-
if (hasChoices(completion)) {
|
|
8364
|
-
span.log({
|
|
8365
|
-
output: completion.choices
|
|
8366
|
-
});
|
|
8367
|
-
}
|
|
8368
|
-
} catch (error) {
|
|
8369
|
-
console.error(
|
|
8370
|
-
`Error extracting chatCompletion for ${channelName}:`,
|
|
8371
|
-
error
|
|
8372
|
-
);
|
|
8424
|
+
const handleResolvedResult = (result) => {
|
|
8425
|
+
const resolvedEndEvent = {
|
|
8426
|
+
...endEvent,
|
|
8427
|
+
result
|
|
8428
|
+
};
|
|
8429
|
+
if (config.patchResult?.({
|
|
8430
|
+
channelName,
|
|
8431
|
+
endEvent: resolvedEndEvent,
|
|
8432
|
+
result,
|
|
8433
|
+
span,
|
|
8434
|
+
startTime
|
|
8435
|
+
})) {
|
|
8436
|
+
return;
|
|
8373
8437
|
}
|
|
8374
|
-
|
|
8375
|
-
|
|
8376
|
-
|
|
8438
|
+
const stream = result;
|
|
8439
|
+
if (!isSyncStreamLike(stream)) {
|
|
8440
|
+
span.end();
|
|
8441
|
+
states.delete(event);
|
|
8377
8442
|
return;
|
|
8378
8443
|
}
|
|
8379
|
-
|
|
8444
|
+
let first = true;
|
|
8445
|
+
stream.on("chunk", () => {
|
|
8380
8446
|
if (first) {
|
|
8381
8447
|
span.log({
|
|
8382
8448
|
metrics: {
|
|
@@ -8385,25 +8451,55 @@ function traceSyncStreamChannel(channel2, config) {
|
|
|
8385
8451
|
});
|
|
8386
8452
|
first = false;
|
|
8387
8453
|
}
|
|
8388
|
-
|
|
8389
|
-
|
|
8390
|
-
|
|
8454
|
+
});
|
|
8455
|
+
stream.on("chatCompletion", (completion) => {
|
|
8456
|
+
try {
|
|
8457
|
+
if (hasChoices(completion)) {
|
|
8458
|
+
span.log({
|
|
8459
|
+
output: completion.choices
|
|
8460
|
+
});
|
|
8461
|
+
}
|
|
8462
|
+
} catch (error) {
|
|
8463
|
+
console.error(
|
|
8464
|
+
`Error extracting chatCompletion for ${channelName}:`,
|
|
8465
|
+
error
|
|
8466
|
+
);
|
|
8391
8467
|
}
|
|
8392
|
-
} catch (error) {
|
|
8393
|
-
console.error(`Error extracting event for ${channelName}:`, error);
|
|
8394
|
-
}
|
|
8395
|
-
});
|
|
8396
|
-
stream.on("end", () => {
|
|
8397
|
-
span.end();
|
|
8398
|
-
states.delete(event);
|
|
8399
|
-
});
|
|
8400
|
-
stream.on("error", (error) => {
|
|
8401
|
-
span.log({
|
|
8402
|
-
error: error.message
|
|
8403
8468
|
});
|
|
8404
|
-
|
|
8405
|
-
|
|
8406
|
-
|
|
8469
|
+
stream.on("event", (streamEvent) => {
|
|
8470
|
+
if (!config.extractFromEvent) {
|
|
8471
|
+
return;
|
|
8472
|
+
}
|
|
8473
|
+
try {
|
|
8474
|
+
if (first) {
|
|
8475
|
+
span.log({
|
|
8476
|
+
metrics: {
|
|
8477
|
+
time_to_first_token: getCurrentUnixTimestamp() - startTime
|
|
8478
|
+
}
|
|
8479
|
+
});
|
|
8480
|
+
first = false;
|
|
8481
|
+
}
|
|
8482
|
+
const extracted = config.extractFromEvent(streamEvent);
|
|
8483
|
+
if (extracted && Object.keys(extracted).length > 0) {
|
|
8484
|
+
span.log(extracted);
|
|
8485
|
+
}
|
|
8486
|
+
} catch (error) {
|
|
8487
|
+
console.error(`Error extracting event for ${channelName}:`, error);
|
|
8488
|
+
}
|
|
8489
|
+
});
|
|
8490
|
+
stream.on("end", () => {
|
|
8491
|
+
span.end();
|
|
8492
|
+
states.delete(event);
|
|
8493
|
+
});
|
|
8494
|
+
stream.on("error", (error) => {
|
|
8495
|
+
span.log({
|
|
8496
|
+
error: error.message
|
|
8497
|
+
});
|
|
8498
|
+
span.end();
|
|
8499
|
+
states.delete(event);
|
|
8500
|
+
});
|
|
8501
|
+
};
|
|
8502
|
+
handleResolvedResult(endEvent.result);
|
|
8407
8503
|
},
|
|
8408
8504
|
error: (event) => {
|
|
8409
8505
|
logErrorAndEnd(states, event);
|
|
@@ -8660,6 +8756,10 @@ var openAIChannels = defineChannels("openai", {
|
|
|
8660
8756
|
responsesParse: channel({
|
|
8661
8757
|
channelName: "responses.parse",
|
|
8662
8758
|
kind: "async"
|
|
8759
|
+
}),
|
|
8760
|
+
responsesCompact: channel({
|
|
8761
|
+
channelName: "responses.compact",
|
|
8762
|
+
kind: "async"
|
|
8663
8763
|
})
|
|
8664
8764
|
});
|
|
8665
8765
|
|
|
@@ -8939,6 +9039,40 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
8939
9039
|
aggregateChunks: aggregateResponseStreamEvents
|
|
8940
9040
|
})
|
|
8941
9041
|
);
|
|
9042
|
+
this.unsubscribers.push(
|
|
9043
|
+
traceAsyncChannel(openAIChannels.responsesCompact, {
|
|
9044
|
+
name: "openai.responses.compact",
|
|
9045
|
+
type: "llm" /* LLM */,
|
|
9046
|
+
extractInput: ([params]) => {
|
|
9047
|
+
const { input, ...metadata } = params;
|
|
9048
|
+
return {
|
|
9049
|
+
input: processInputAttachments(input),
|
|
9050
|
+
metadata: { ...metadata, provider: "openai" }
|
|
9051
|
+
};
|
|
9052
|
+
},
|
|
9053
|
+
extractOutput: (result) => {
|
|
9054
|
+
return processImagesInOutput(result?.output);
|
|
9055
|
+
},
|
|
9056
|
+
extractMetadata: (result) => {
|
|
9057
|
+
if (!result) {
|
|
9058
|
+
return void 0;
|
|
9059
|
+
}
|
|
9060
|
+
const { output: _output, usage: _usage, ...metadata } = result;
|
|
9061
|
+
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
9062
|
+
},
|
|
9063
|
+
extractMetrics: (result, startTime, endEvent) => {
|
|
9064
|
+
const metrics = withCachedMetric(
|
|
9065
|
+
parseMetricsFromUsage(result?.usage),
|
|
9066
|
+
result,
|
|
9067
|
+
endEvent
|
|
9068
|
+
);
|
|
9069
|
+
if (startTime) {
|
|
9070
|
+
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
9071
|
+
}
|
|
9072
|
+
return metrics;
|
|
9073
|
+
}
|
|
9074
|
+
})
|
|
9075
|
+
);
|
|
8942
9076
|
}
|
|
8943
9077
|
onDisable() {
|
|
8944
9078
|
this.unsubscribers = unsubscribeAll(this.unsubscribers);
|
|
@@ -9226,28 +9360,40 @@ function aggregateAnthropicStreamChunks(chunks) {
|
|
|
9226
9360
|
case "content_block_start":
|
|
9227
9361
|
if (event.content_block) {
|
|
9228
9362
|
contentBlocks[event.index] = event.content_block;
|
|
9229
|
-
contentBlockDeltas[event.index] = [];
|
|
9363
|
+
contentBlockDeltas[event.index] = { textDeltas: [], citations: [] };
|
|
9230
9364
|
}
|
|
9231
9365
|
break;
|
|
9232
|
-
case "content_block_delta":
|
|
9233
|
-
|
|
9234
|
-
|
|
9366
|
+
case "content_block_delta": {
|
|
9367
|
+
const acc = contentBlockDeltas[event.index];
|
|
9368
|
+
const delta = event.delta;
|
|
9369
|
+
if (!delta) break;
|
|
9370
|
+
if (delta.type === "text_delta" && "text" in delta) {
|
|
9371
|
+
const text = delta.text;
|
|
9235
9372
|
if (text) {
|
|
9236
|
-
if (
|
|
9237
|
-
|
|
9238
|
-
contentBlockDeltas[event.index].push(text);
|
|
9373
|
+
if (acc !== void 0) {
|
|
9374
|
+
acc.textDeltas.push(text);
|
|
9239
9375
|
} else {
|
|
9240
9376
|
fallbackTextDeltas.push(text);
|
|
9241
9377
|
}
|
|
9242
9378
|
}
|
|
9243
|
-
} else if (
|
|
9244
|
-
const partialJson =
|
|
9245
|
-
if (partialJson) {
|
|
9246
|
-
|
|
9247
|
-
|
|
9379
|
+
} else if (delta.type === "input_json_delta" && "partial_json" in delta) {
|
|
9380
|
+
const partialJson = delta.partial_json;
|
|
9381
|
+
if (partialJson && acc !== void 0) {
|
|
9382
|
+
acc.textDeltas.push(partialJson);
|
|
9383
|
+
}
|
|
9384
|
+
} else if (delta.type === "thinking_delta" && "thinking" in delta) {
|
|
9385
|
+
const thinking = delta.thinking;
|
|
9386
|
+
if (thinking && acc !== void 0) {
|
|
9387
|
+
acc.textDeltas.push(thinking);
|
|
9388
|
+
}
|
|
9389
|
+
} else if (delta.type === "citations_delta" && "citation" in delta) {
|
|
9390
|
+
const citation = delta.citation;
|
|
9391
|
+
if (citation && acc !== void 0) {
|
|
9392
|
+
acc.citations.push(citation);
|
|
9248
9393
|
}
|
|
9249
9394
|
}
|
|
9250
9395
|
break;
|
|
9396
|
+
}
|
|
9251
9397
|
case "content_block_stop":
|
|
9252
9398
|
finalizeContentBlock(
|
|
9253
9399
|
event.index,
|
|
@@ -9273,7 +9419,7 @@ function aggregateAnthropicStreamChunks(chunks) {
|
|
|
9273
9419
|
})).filter(({ block }) => block !== void 0).sort((left, right) => left.index - right.index).map(({ block }) => block);
|
|
9274
9420
|
let output = fallbackTextDeltas.join("");
|
|
9275
9421
|
if (orderedContent.length > 0) {
|
|
9276
|
-
if (orderedContent.every(isTextContentBlock)) {
|
|
9422
|
+
if (orderedContent.every(isTextContentBlock) && orderedContent.every((block) => !block.citations?.length)) {
|
|
9277
9423
|
output = orderedContent.map((block) => block.text).join("");
|
|
9278
9424
|
} else {
|
|
9279
9425
|
output = {
|
|
@@ -9299,7 +9445,8 @@ function finalizeContentBlock(index, contentBlocks, contentBlockDeltas, fallback
|
|
|
9299
9445
|
if (!contentBlock) {
|
|
9300
9446
|
return;
|
|
9301
9447
|
}
|
|
9302
|
-
const
|
|
9448
|
+
const acc = contentBlockDeltas[index];
|
|
9449
|
+
const text = acc?.textDeltas.join("") ?? "";
|
|
9303
9450
|
if (isToolUseContentBlock(contentBlock)) {
|
|
9304
9451
|
if (!text) {
|
|
9305
9452
|
return;
|
|
@@ -9316,20 +9463,28 @@ function finalizeContentBlock(index, contentBlocks, contentBlockDeltas, fallback
|
|
|
9316
9463
|
return;
|
|
9317
9464
|
}
|
|
9318
9465
|
if (isTextContentBlock(contentBlock)) {
|
|
9466
|
+
if (!text) {
|
|
9467
|
+
delete contentBlocks[index];
|
|
9468
|
+
return;
|
|
9469
|
+
}
|
|
9470
|
+
const updated = { ...contentBlock, text };
|
|
9471
|
+
if (acc?.citations.length) {
|
|
9472
|
+
updated.citations = acc.citations;
|
|
9473
|
+
}
|
|
9474
|
+
contentBlocks[index] = updated;
|
|
9475
|
+
return;
|
|
9476
|
+
}
|
|
9477
|
+
if (isThinkingContentBlock(contentBlock)) {
|
|
9319
9478
|
if (!text) {
|
|
9320
9479
|
delete contentBlocks[index];
|
|
9321
9480
|
return;
|
|
9322
9481
|
}
|
|
9323
9482
|
contentBlocks[index] = {
|
|
9324
9483
|
...contentBlock,
|
|
9325
|
-
text
|
|
9484
|
+
thinking: text
|
|
9326
9485
|
};
|
|
9327
9486
|
return;
|
|
9328
9487
|
}
|
|
9329
|
-
if (text) {
|
|
9330
|
-
fallbackTextDeltas.push(text);
|
|
9331
|
-
}
|
|
9332
|
-
delete contentBlocks[index];
|
|
9333
9488
|
}
|
|
9334
9489
|
function isTextContentBlock(contentBlock) {
|
|
9335
9490
|
return contentBlock.type === "text";
|
|
@@ -9337,6 +9492,9 @@ function isTextContentBlock(contentBlock) {
|
|
|
9337
9492
|
function isToolUseContentBlock(contentBlock) {
|
|
9338
9493
|
return contentBlock.type === "tool_use";
|
|
9339
9494
|
}
|
|
9495
|
+
function isThinkingContentBlock(contentBlock) {
|
|
9496
|
+
return contentBlock.type === "thinking";
|
|
9497
|
+
}
|
|
9340
9498
|
function isAnthropicBase64ContentBlock(input) {
|
|
9341
9499
|
return (input.type === "image" || input.type === "document") && isObject(input.source) && input.source.type === "base64";
|
|
9342
9500
|
}
|
|
@@ -9391,15 +9549,6 @@ function coalesceInput(messages, system) {
|
|
|
9391
9549
|
}
|
|
9392
9550
|
return input;
|
|
9393
9551
|
}
|
|
9394
|
-
function filterFrom(obj, fieldsToRemove) {
|
|
9395
|
-
const result = {};
|
|
9396
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
9397
|
-
if (!fieldsToRemove.includes(key)) {
|
|
9398
|
-
result[key] = value;
|
|
9399
|
-
}
|
|
9400
|
-
}
|
|
9401
|
-
return result;
|
|
9402
|
-
}
|
|
9403
9552
|
|
|
9404
9553
|
// src/wrappers/ai-sdk/normalize-logged-output.ts
|
|
9405
9554
|
var REMOVE_NORMALIZED_VALUE = Symbol("braintrust.ai-sdk.remove-normalized");
|
|
@@ -9529,6 +9678,16 @@ var aiSDKChannels = defineChannels("ai", {
|
|
|
9529
9678
|
channelName: "streamObject.sync",
|
|
9530
9679
|
kind: "sync-stream"
|
|
9531
9680
|
}),
|
|
9681
|
+
embed: channel(
|
|
9682
|
+
{
|
|
9683
|
+
channelName: "embed",
|
|
9684
|
+
kind: "async"
|
|
9685
|
+
}
|
|
9686
|
+
),
|
|
9687
|
+
embedMany: channel({
|
|
9688
|
+
channelName: "embedMany",
|
|
9689
|
+
kind: "async"
|
|
9690
|
+
}),
|
|
9532
9691
|
agentGenerate: channel({
|
|
9533
9692
|
channelName: "Agent.generate",
|
|
9534
9693
|
kind: "async"
|
|
@@ -9537,6 +9696,10 @@ var aiSDKChannels = defineChannels("ai", {
|
|
|
9537
9696
|
channelName: "Agent.stream",
|
|
9538
9697
|
kind: "async"
|
|
9539
9698
|
}),
|
|
9699
|
+
agentStreamSync: channel({
|
|
9700
|
+
channelName: "Agent.stream.sync",
|
|
9701
|
+
kind: "sync-stream"
|
|
9702
|
+
}),
|
|
9540
9703
|
toolLoopAgentGenerate: channel({
|
|
9541
9704
|
channelName: "ToolLoopAgent.generate",
|
|
9542
9705
|
kind: "async"
|
|
@@ -9564,6 +9727,9 @@ var DEFAULT_DENY_OUTPUT_PATHS = [
|
|
|
9564
9727
|
];
|
|
9565
9728
|
var AUTO_PATCHED_MODEL = Symbol.for("braintrust.ai-sdk.auto-patched-model");
|
|
9566
9729
|
var AUTO_PATCHED_TOOL = Symbol.for("braintrust.ai-sdk.auto-patched-tool");
|
|
9730
|
+
var RUNTIME_DENY_OUTPUT_PATHS = Symbol.for(
|
|
9731
|
+
"braintrust.ai-sdk.deny-output-paths"
|
|
9732
|
+
);
|
|
9567
9733
|
var AISDKPlugin = class extends BasePlugin {
|
|
9568
9734
|
config;
|
|
9569
9735
|
constructor(config = {}) {
|
|
@@ -9582,10 +9748,13 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
9582
9748
|
traceStreamingChannel(aiSDKChannels.generateText, {
|
|
9583
9749
|
name: "generateText",
|
|
9584
9750
|
type: "llm" /* LLM */,
|
|
9585
|
-
extractInput: ([params], event, span) =>
|
|
9751
|
+
extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
|
|
9586
9752
|
extractOutput: (result, endEvent) => {
|
|
9587
9753
|
finalizeAISDKChildTracing(endEvent);
|
|
9588
|
-
return processAISDKOutput(
|
|
9754
|
+
return processAISDKOutput(
|
|
9755
|
+
result,
|
|
9756
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
9757
|
+
);
|
|
9589
9758
|
},
|
|
9590
9759
|
extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
|
|
9591
9760
|
aggregateChunks: aggregateAISDKChunks
|
|
@@ -9595,12 +9764,15 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
9595
9764
|
traceStreamingChannel(aiSDKChannels.streamText, {
|
|
9596
9765
|
name: "streamText",
|
|
9597
9766
|
type: "llm" /* LLM */,
|
|
9598
|
-
extractInput: ([params], event, span) =>
|
|
9599
|
-
extractOutput: (result) => processAISDKOutput(
|
|
9767
|
+
extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
|
|
9768
|
+
extractOutput: (result, endEvent) => processAISDKOutput(
|
|
9769
|
+
result,
|
|
9770
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
9771
|
+
),
|
|
9600
9772
|
extractMetrics: (result, startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent, startTime),
|
|
9601
9773
|
aggregateChunks: aggregateAISDKChunks,
|
|
9602
9774
|
patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
|
|
9603
|
-
denyOutputPaths,
|
|
9775
|
+
defaultDenyOutputPaths: denyOutputPaths,
|
|
9604
9776
|
endEvent,
|
|
9605
9777
|
result,
|
|
9606
9778
|
span,
|
|
@@ -9612,9 +9784,9 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
9612
9784
|
traceSyncStreamChannel(aiSDKChannels.streamTextSync, {
|
|
9613
9785
|
name: "streamText",
|
|
9614
9786
|
type: "llm" /* LLM */,
|
|
9615
|
-
extractInput: ([params], event, span) =>
|
|
9787
|
+
extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
|
|
9616
9788
|
patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
|
|
9617
|
-
denyOutputPaths,
|
|
9789
|
+
defaultDenyOutputPaths: denyOutputPaths,
|
|
9618
9790
|
endEvent,
|
|
9619
9791
|
result,
|
|
9620
9792
|
span,
|
|
@@ -9626,10 +9798,13 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
9626
9798
|
traceStreamingChannel(aiSDKChannels.generateObject, {
|
|
9627
9799
|
name: "generateObject",
|
|
9628
9800
|
type: "llm" /* LLM */,
|
|
9629
|
-
extractInput: ([params], event, span) =>
|
|
9801
|
+
extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
|
|
9630
9802
|
extractOutput: (result, endEvent) => {
|
|
9631
9803
|
finalizeAISDKChildTracing(endEvent);
|
|
9632
|
-
return processAISDKOutput(
|
|
9804
|
+
return processAISDKOutput(
|
|
9805
|
+
result,
|
|
9806
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
9807
|
+
);
|
|
9633
9808
|
},
|
|
9634
9809
|
extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
|
|
9635
9810
|
aggregateChunks: aggregateAISDKChunks
|
|
@@ -9639,12 +9814,15 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
9639
9814
|
traceStreamingChannel(aiSDKChannels.streamObject, {
|
|
9640
9815
|
name: "streamObject",
|
|
9641
9816
|
type: "llm" /* LLM */,
|
|
9642
|
-
extractInput: ([params], event, span) =>
|
|
9643
|
-
extractOutput: (result) => processAISDKOutput(
|
|
9817
|
+
extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
|
|
9818
|
+
extractOutput: (result, endEvent) => processAISDKOutput(
|
|
9819
|
+
result,
|
|
9820
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
9821
|
+
),
|
|
9644
9822
|
extractMetrics: (result, startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent, startTime),
|
|
9645
9823
|
aggregateChunks: aggregateAISDKChunks,
|
|
9646
9824
|
patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
|
|
9647
|
-
denyOutputPaths,
|
|
9825
|
+
defaultDenyOutputPaths: denyOutputPaths,
|
|
9648
9826
|
endEvent,
|
|
9649
9827
|
result,
|
|
9650
9828
|
span,
|
|
@@ -9656,9 +9834,9 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
9656
9834
|
traceSyncStreamChannel(aiSDKChannels.streamObjectSync, {
|
|
9657
9835
|
name: "streamObject",
|
|
9658
9836
|
type: "llm" /* LLM */,
|
|
9659
|
-
extractInput: ([params], event, span) =>
|
|
9837
|
+
extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
|
|
9660
9838
|
patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
|
|
9661
|
-
denyOutputPaths,
|
|
9839
|
+
defaultDenyOutputPaths: denyOutputPaths,
|
|
9662
9840
|
endEvent,
|
|
9663
9841
|
result,
|
|
9664
9842
|
span,
|
|
@@ -9666,14 +9844,41 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
9666
9844
|
})
|
|
9667
9845
|
})
|
|
9668
9846
|
);
|
|
9847
|
+
this.unsubscribers.push(
|
|
9848
|
+
traceAsyncChannel(aiSDKChannels.embed, {
|
|
9849
|
+
name: "embed",
|
|
9850
|
+
type: "llm" /* LLM */,
|
|
9851
|
+
extractInput: ([params], event) => prepareAISDKEmbedInput(params, event.self),
|
|
9852
|
+
extractOutput: (result, endEvent) => processAISDKEmbeddingOutput(
|
|
9853
|
+
result,
|
|
9854
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
9855
|
+
),
|
|
9856
|
+
extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent)
|
|
9857
|
+
})
|
|
9858
|
+
);
|
|
9859
|
+
this.unsubscribers.push(
|
|
9860
|
+
traceAsyncChannel(aiSDKChannels.embedMany, {
|
|
9861
|
+
name: "embedMany",
|
|
9862
|
+
type: "llm" /* LLM */,
|
|
9863
|
+
extractInput: ([params], event) => prepareAISDKEmbedInput(params, event.self),
|
|
9864
|
+
extractOutput: (result, endEvent) => processAISDKEmbeddingOutput(
|
|
9865
|
+
result,
|
|
9866
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
9867
|
+
),
|
|
9868
|
+
extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent)
|
|
9869
|
+
})
|
|
9870
|
+
);
|
|
9669
9871
|
this.unsubscribers.push(
|
|
9670
9872
|
traceStreamingChannel(aiSDKChannels.agentGenerate, {
|
|
9671
9873
|
name: "Agent.generate",
|
|
9672
9874
|
type: "llm" /* LLM */,
|
|
9673
|
-
extractInput: ([params], event, span) =>
|
|
9875
|
+
extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
|
|
9674
9876
|
extractOutput: (result, endEvent) => {
|
|
9675
9877
|
finalizeAISDKChildTracing(endEvent);
|
|
9676
|
-
return processAISDKOutput(
|
|
9878
|
+
return processAISDKOutput(
|
|
9879
|
+
result,
|
|
9880
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
9881
|
+
);
|
|
9677
9882
|
},
|
|
9678
9883
|
extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
|
|
9679
9884
|
aggregateChunks: aggregateAISDKChunks
|
|
@@ -9683,12 +9888,29 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
9683
9888
|
traceStreamingChannel(aiSDKChannels.agentStream, {
|
|
9684
9889
|
name: "Agent.stream",
|
|
9685
9890
|
type: "llm" /* LLM */,
|
|
9686
|
-
extractInput: ([params], event, span) =>
|
|
9687
|
-
extractOutput: (result) => processAISDKOutput(
|
|
9891
|
+
extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
|
|
9892
|
+
extractOutput: (result, endEvent) => processAISDKOutput(
|
|
9893
|
+
result,
|
|
9894
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
9895
|
+
),
|
|
9688
9896
|
extractMetrics: (result, startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent, startTime),
|
|
9689
9897
|
aggregateChunks: aggregateAISDKChunks,
|
|
9690
9898
|
patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
|
|
9691
|
-
denyOutputPaths,
|
|
9899
|
+
defaultDenyOutputPaths: denyOutputPaths,
|
|
9900
|
+
endEvent,
|
|
9901
|
+
result,
|
|
9902
|
+
span,
|
|
9903
|
+
startTime
|
|
9904
|
+
})
|
|
9905
|
+
})
|
|
9906
|
+
);
|
|
9907
|
+
this.unsubscribers.push(
|
|
9908
|
+
traceSyncStreamChannel(aiSDKChannels.agentStreamSync, {
|
|
9909
|
+
name: "Agent.stream",
|
|
9910
|
+
type: "llm" /* LLM */,
|
|
9911
|
+
extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
|
|
9912
|
+
patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
|
|
9913
|
+
defaultDenyOutputPaths: denyOutputPaths,
|
|
9692
9914
|
endEvent,
|
|
9693
9915
|
result,
|
|
9694
9916
|
span,
|
|
@@ -9700,10 +9922,13 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
9700
9922
|
traceStreamingChannel(aiSDKChannels.toolLoopAgentGenerate, {
|
|
9701
9923
|
name: "ToolLoopAgent.generate",
|
|
9702
9924
|
type: "llm" /* LLM */,
|
|
9703
|
-
extractInput: ([params], event, span) =>
|
|
9925
|
+
extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
|
|
9704
9926
|
extractOutput: (result, endEvent) => {
|
|
9705
9927
|
finalizeAISDKChildTracing(endEvent);
|
|
9706
|
-
return processAISDKOutput(
|
|
9928
|
+
return processAISDKOutput(
|
|
9929
|
+
result,
|
|
9930
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
9931
|
+
);
|
|
9707
9932
|
},
|
|
9708
9933
|
extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
|
|
9709
9934
|
aggregateChunks: aggregateAISDKChunks
|
|
@@ -9713,12 +9938,15 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
9713
9938
|
traceStreamingChannel(aiSDKChannels.toolLoopAgentStream, {
|
|
9714
9939
|
name: "ToolLoopAgent.stream",
|
|
9715
9940
|
type: "llm" /* LLM */,
|
|
9716
|
-
extractInput: ([params], event, span) =>
|
|
9717
|
-
extractOutput: (result) => processAISDKOutput(
|
|
9941
|
+
extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
|
|
9942
|
+
extractOutput: (result, endEvent) => processAISDKOutput(
|
|
9943
|
+
result,
|
|
9944
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
9945
|
+
),
|
|
9718
9946
|
extractMetrics: (result, startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent, startTime),
|
|
9719
9947
|
aggregateChunks: aggregateAISDKChunks,
|
|
9720
9948
|
patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
|
|
9721
|
-
denyOutputPaths,
|
|
9949
|
+
defaultDenyOutputPaths: denyOutputPaths,
|
|
9722
9950
|
endEvent,
|
|
9723
9951
|
result,
|
|
9724
9952
|
span,
|
|
@@ -9728,75 +9956,391 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
9728
9956
|
);
|
|
9729
9957
|
}
|
|
9730
9958
|
};
|
|
9731
|
-
function
|
|
9732
|
-
if (
|
|
9733
|
-
|
|
9734
|
-
if (!input || typeof input !== "object" || Array.isArray(input)) {
|
|
9735
|
-
return input;
|
|
9959
|
+
function resolveDenyOutputPaths(event, defaultDenyOutputPaths) {
|
|
9960
|
+
if (Array.isArray(event?.denyOutputPaths)) {
|
|
9961
|
+
return event.denyOutputPaths;
|
|
9736
9962
|
}
|
|
9737
|
-
const
|
|
9738
|
-
|
|
9739
|
-
|
|
9740
|
-
function prepareAISDKInput(params, event, span, denyOutputPaths) {
|
|
9741
|
-
const input = processAISDKInput(params);
|
|
9742
|
-
const metadata = extractMetadataFromParams(params, event.self);
|
|
9743
|
-
const childTracing = prepareAISDKChildTracing(
|
|
9744
|
-
params,
|
|
9745
|
-
event.self,
|
|
9746
|
-
span,
|
|
9747
|
-
denyOutputPaths
|
|
9748
|
-
);
|
|
9749
|
-
event.__braintrust_ai_sdk_model_wrapped = childTracing.modelWrapped;
|
|
9750
|
-
if (childTracing.cleanup) {
|
|
9751
|
-
event.__braintrust_ai_sdk_cleanup = childTracing.cleanup;
|
|
9963
|
+
const firstArgument = event?.arguments && event.arguments.length > 0 ? event.arguments[0] : void 0;
|
|
9964
|
+
if (!firstArgument || typeof firstArgument !== "object") {
|
|
9965
|
+
return defaultDenyOutputPaths;
|
|
9752
9966
|
}
|
|
9753
|
-
|
|
9754
|
-
|
|
9755
|
-
|
|
9756
|
-
};
|
|
9757
|
-
}
|
|
9758
|
-
function extractTopLevelAISDKMetrics(result, event, startTime) {
|
|
9759
|
-
const metrics = hasModelChildTracing(event) ? {} : extractTokenMetrics(result);
|
|
9760
|
-
if (startTime) {
|
|
9761
|
-
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
9967
|
+
const runtimeDenyOutputPaths = firstArgument[RUNTIME_DENY_OUTPUT_PATHS];
|
|
9968
|
+
if (Array.isArray(runtimeDenyOutputPaths) && runtimeDenyOutputPaths.every((path) => typeof path === "string")) {
|
|
9969
|
+
return runtimeDenyOutputPaths;
|
|
9762
9970
|
}
|
|
9763
|
-
return
|
|
9764
|
-
}
|
|
9765
|
-
function hasModelChildTracing(event) {
|
|
9766
|
-
return event?.__braintrust_ai_sdk_model_wrapped === true;
|
|
9971
|
+
return defaultDenyOutputPaths;
|
|
9767
9972
|
}
|
|
9768
|
-
|
|
9769
|
-
|
|
9770
|
-
|
|
9771
|
-
|
|
9772
|
-
|
|
9773
|
-
|
|
9774
|
-
}
|
|
9775
|
-
|
|
9776
|
-
|
|
9777
|
-
|
|
9778
|
-
|
|
9779
|
-
if (model) {
|
|
9780
|
-
metadata.model = model;
|
|
9973
|
+
var isZodSchema2 = (value) => {
|
|
9974
|
+
return value != null && typeof value === "object" && "_def" in value && typeof value._def === "object";
|
|
9975
|
+
};
|
|
9976
|
+
var serializeZodSchema2 = (schema) => {
|
|
9977
|
+
try {
|
|
9978
|
+
return zodToJsonSchema(schema);
|
|
9979
|
+
} catch {
|
|
9980
|
+
return {
|
|
9981
|
+
type: "object",
|
|
9982
|
+
description: "Zod schema (conversion failed)"
|
|
9983
|
+
};
|
|
9781
9984
|
}
|
|
9782
|
-
|
|
9783
|
-
|
|
9985
|
+
};
|
|
9986
|
+
var isOutputObject = (value) => {
|
|
9987
|
+
if (value == null || typeof value !== "object") {
|
|
9988
|
+
return false;
|
|
9784
9989
|
}
|
|
9785
|
-
const
|
|
9786
|
-
if (
|
|
9787
|
-
|
|
9990
|
+
const output = value;
|
|
9991
|
+
if (!("responseFormat" in output)) {
|
|
9992
|
+
return false;
|
|
9788
9993
|
}
|
|
9789
|
-
|
|
9790
|
-
|
|
9791
|
-
|
|
9792
|
-
|
|
9793
|
-
|
|
9994
|
+
if (output.type === "object" || output.type === "text") {
|
|
9995
|
+
return true;
|
|
9996
|
+
}
|
|
9997
|
+
if (typeof output.responseFormat === "function" || typeof output.responseFormat === "object") {
|
|
9998
|
+
return true;
|
|
9999
|
+
}
|
|
10000
|
+
return false;
|
|
10001
|
+
};
|
|
10002
|
+
var serializeOutputObject = (output, model) => {
|
|
10003
|
+
try {
|
|
10004
|
+
const result = {
|
|
10005
|
+
response_format: null
|
|
10006
|
+
};
|
|
10007
|
+
if (output.type) {
|
|
10008
|
+
result.type = output.type;
|
|
10009
|
+
}
|
|
10010
|
+
let responseFormat;
|
|
10011
|
+
if (typeof output.responseFormat === "function") {
|
|
10012
|
+
const mockModelForSchema = {
|
|
10013
|
+
supportsStructuredOutputs: true,
|
|
10014
|
+
...model && typeof model === "object" ? model : {}
|
|
10015
|
+
};
|
|
10016
|
+
responseFormat = output.responseFormat({ model: mockModelForSchema });
|
|
10017
|
+
} else if (output.responseFormat != null && typeof output.responseFormat === "object") {
|
|
10018
|
+
responseFormat = output.responseFormat;
|
|
10019
|
+
}
|
|
10020
|
+
if (responseFormat) {
|
|
10021
|
+
if (typeof responseFormat.then === "function") {
|
|
10022
|
+
result.response_format = Promise.resolve(responseFormat).then(
|
|
10023
|
+
(resolved) => {
|
|
10024
|
+
if (resolved.schema && isZodSchema2(resolved.schema)) {
|
|
10025
|
+
return {
|
|
10026
|
+
...resolved,
|
|
10027
|
+
schema: serializeZodSchema2(resolved.schema)
|
|
10028
|
+
};
|
|
10029
|
+
}
|
|
10030
|
+
return resolved;
|
|
10031
|
+
}
|
|
10032
|
+
);
|
|
10033
|
+
} else {
|
|
10034
|
+
const syncResponseFormat = responseFormat;
|
|
10035
|
+
if (syncResponseFormat.schema && isZodSchema2(syncResponseFormat.schema)) {
|
|
10036
|
+
responseFormat = {
|
|
10037
|
+
...syncResponseFormat,
|
|
10038
|
+
schema: serializeZodSchema2(syncResponseFormat.schema)
|
|
10039
|
+
};
|
|
10040
|
+
}
|
|
10041
|
+
result.response_format = responseFormat;
|
|
10042
|
+
}
|
|
10043
|
+
}
|
|
10044
|
+
return result;
|
|
10045
|
+
} catch {
|
|
10046
|
+
return {
|
|
10047
|
+
response_format: null
|
|
10048
|
+
};
|
|
10049
|
+
}
|
|
10050
|
+
};
|
|
10051
|
+
var processInputAttachmentsSync = (input) => {
|
|
10052
|
+
if (!input) return { input };
|
|
10053
|
+
const processed = { ...input };
|
|
10054
|
+
if (input.messages && Array.isArray(input.messages)) {
|
|
10055
|
+
processed.messages = input.messages.map(processMessage);
|
|
10056
|
+
}
|
|
10057
|
+
if (input.prompt && typeof input.prompt === "object") {
|
|
10058
|
+
if (Array.isArray(input.prompt)) {
|
|
10059
|
+
processed.prompt = input.prompt.map(processMessage);
|
|
10060
|
+
} else {
|
|
10061
|
+
processed.prompt = processPromptContent(input.prompt);
|
|
10062
|
+
}
|
|
10063
|
+
}
|
|
10064
|
+
if (input.schema && isZodSchema2(input.schema)) {
|
|
10065
|
+
processed.schema = serializeZodSchema2(input.schema);
|
|
10066
|
+
}
|
|
10067
|
+
if (input.callOptionsSchema && isZodSchema2(input.callOptionsSchema)) {
|
|
10068
|
+
processed.callOptionsSchema = serializeZodSchema2(input.callOptionsSchema);
|
|
10069
|
+
}
|
|
10070
|
+
if (input.tools) {
|
|
10071
|
+
processed.tools = serializeAISDKToolsForLogging(input.tools);
|
|
10072
|
+
}
|
|
10073
|
+
let outputPromise;
|
|
10074
|
+
if (input.output && isOutputObject(input.output)) {
|
|
10075
|
+
const serialized = serializeOutputObject(input.output, input.model);
|
|
10076
|
+
if (serialized.response_format && typeof serialized.response_format.then === "function") {
|
|
10077
|
+
processed.output = { ...serialized, response_format: {} };
|
|
10078
|
+
outputPromise = serialized.response_format.then(
|
|
10079
|
+
(resolvedFormat) => ({
|
|
10080
|
+
output: { ...serialized, response_format: resolvedFormat }
|
|
10081
|
+
})
|
|
10082
|
+
);
|
|
10083
|
+
} else {
|
|
10084
|
+
processed.output = serialized;
|
|
10085
|
+
}
|
|
10086
|
+
}
|
|
10087
|
+
if ("prepareCall" in processed && typeof processed.prepareCall === "function") {
|
|
10088
|
+
processed.prepareCall = "[Function]";
|
|
10089
|
+
}
|
|
10090
|
+
return { input: processed, outputPromise };
|
|
10091
|
+
};
|
|
10092
|
+
var processMessage = (message) => {
|
|
10093
|
+
if (!message || typeof message !== "object") return message;
|
|
10094
|
+
if (Array.isArray(message.content)) {
|
|
10095
|
+
return {
|
|
10096
|
+
...message,
|
|
10097
|
+
content: message.content.map(processContentPart)
|
|
10098
|
+
};
|
|
10099
|
+
}
|
|
10100
|
+
if (typeof message.content === "object" && message.content !== null) {
|
|
10101
|
+
return {
|
|
10102
|
+
...message,
|
|
10103
|
+
content: processContentPart(message.content)
|
|
10104
|
+
};
|
|
10105
|
+
}
|
|
10106
|
+
return message;
|
|
10107
|
+
};
|
|
10108
|
+
var processPromptContent = (prompt) => {
|
|
10109
|
+
if (Array.isArray(prompt)) {
|
|
10110
|
+
return prompt.map(processContentPart);
|
|
10111
|
+
}
|
|
10112
|
+
if (prompt.content) {
|
|
10113
|
+
if (Array.isArray(prompt.content)) {
|
|
10114
|
+
return {
|
|
10115
|
+
...prompt,
|
|
10116
|
+
content: prompt.content.map(processContentPart)
|
|
10117
|
+
};
|
|
10118
|
+
} else if (typeof prompt.content === "object") {
|
|
10119
|
+
return {
|
|
10120
|
+
...prompt,
|
|
10121
|
+
content: processContentPart(prompt.content)
|
|
10122
|
+
};
|
|
10123
|
+
}
|
|
10124
|
+
}
|
|
10125
|
+
return prompt;
|
|
10126
|
+
};
|
|
10127
|
+
var processContentPart = (part) => {
|
|
10128
|
+
if (!part || typeof part !== "object") return part;
|
|
10129
|
+
try {
|
|
10130
|
+
if (part.type === "image" && part.image) {
|
|
10131
|
+
const imageAttachment = convertImageToAttachment(
|
|
10132
|
+
part.image,
|
|
10133
|
+
part.mimeType || part.mediaType
|
|
10134
|
+
);
|
|
10135
|
+
if (imageAttachment) {
|
|
10136
|
+
return {
|
|
10137
|
+
...part,
|
|
10138
|
+
image: imageAttachment
|
|
10139
|
+
};
|
|
10140
|
+
}
|
|
10141
|
+
}
|
|
10142
|
+
if (part.type === "file" && part.data && (part.mimeType || part.mediaType)) {
|
|
10143
|
+
const fileAttachment = convertDataToAttachment(
|
|
10144
|
+
part.data,
|
|
10145
|
+
part.mimeType || part.mediaType,
|
|
10146
|
+
part.name || part.filename
|
|
10147
|
+
);
|
|
10148
|
+
if (fileAttachment) {
|
|
10149
|
+
return {
|
|
10150
|
+
...part,
|
|
10151
|
+
data: fileAttachment
|
|
10152
|
+
};
|
|
10153
|
+
}
|
|
10154
|
+
}
|
|
10155
|
+
if (part.type === "image_url" && part.image_url) {
|
|
10156
|
+
if (typeof part.image_url === "object" && part.image_url.url) {
|
|
10157
|
+
const imageAttachment = convertImageToAttachment(part.image_url.url);
|
|
10158
|
+
if (imageAttachment) {
|
|
10159
|
+
return {
|
|
10160
|
+
...part,
|
|
10161
|
+
image_url: {
|
|
10162
|
+
...part.image_url,
|
|
10163
|
+
url: imageAttachment
|
|
10164
|
+
}
|
|
10165
|
+
};
|
|
10166
|
+
}
|
|
10167
|
+
}
|
|
10168
|
+
}
|
|
10169
|
+
} catch (error) {
|
|
10170
|
+
console.warn("Error processing content part:", error);
|
|
10171
|
+
}
|
|
10172
|
+
return part;
|
|
10173
|
+
};
|
|
10174
|
+
var convertImageToAttachment = (image, explicitMimeType) => {
|
|
10175
|
+
try {
|
|
10176
|
+
if (typeof image === "string" && image.startsWith("data:")) {
|
|
10177
|
+
const [mimeTypeSection, base64Data] = image.split(",");
|
|
10178
|
+
const mimeType = mimeTypeSection.match(/data:(.*?);/)?.[1];
|
|
10179
|
+
if (mimeType && base64Data) {
|
|
10180
|
+
const blob = convertDataToBlob(base64Data, mimeType);
|
|
10181
|
+
if (blob) {
|
|
10182
|
+
return new Attachment({
|
|
10183
|
+
data: blob,
|
|
10184
|
+
filename: `image.${getExtensionFromMediaType(mimeType)}`,
|
|
10185
|
+
contentType: mimeType
|
|
10186
|
+
});
|
|
10187
|
+
}
|
|
10188
|
+
}
|
|
10189
|
+
}
|
|
10190
|
+
if (explicitMimeType) {
|
|
10191
|
+
if (image instanceof Uint8Array) {
|
|
10192
|
+
return new Attachment({
|
|
10193
|
+
data: new Blob([image], { type: explicitMimeType }),
|
|
10194
|
+
filename: `image.${getExtensionFromMediaType(explicitMimeType)}`,
|
|
10195
|
+
contentType: explicitMimeType
|
|
10196
|
+
});
|
|
10197
|
+
}
|
|
10198
|
+
if (typeof Buffer !== "undefined" && Buffer.isBuffer(image)) {
|
|
10199
|
+
return new Attachment({
|
|
10200
|
+
data: new Blob([image], { type: explicitMimeType }),
|
|
10201
|
+
filename: `image.${getExtensionFromMediaType(explicitMimeType)}`,
|
|
10202
|
+
contentType: explicitMimeType
|
|
10203
|
+
});
|
|
10204
|
+
}
|
|
10205
|
+
}
|
|
10206
|
+
if (image instanceof Blob && image.type) {
|
|
10207
|
+
return new Attachment({
|
|
10208
|
+
data: image,
|
|
10209
|
+
filename: `image.${getExtensionFromMediaType(image.type)}`,
|
|
10210
|
+
contentType: image.type
|
|
10211
|
+
});
|
|
10212
|
+
}
|
|
10213
|
+
if (image instanceof Attachment) {
|
|
10214
|
+
return image;
|
|
10215
|
+
}
|
|
10216
|
+
} catch (error) {
|
|
10217
|
+
console.warn("Error converting image to attachment:", error);
|
|
10218
|
+
}
|
|
10219
|
+
return null;
|
|
10220
|
+
};
|
|
10221
|
+
var convertDataToAttachment = (data, mimeType, filename) => {
|
|
10222
|
+
if (!mimeType) return null;
|
|
10223
|
+
try {
|
|
10224
|
+
let blob = null;
|
|
10225
|
+
if (typeof data === "string" && data.startsWith("data:")) {
|
|
10226
|
+
const [, base64Data] = data.split(",");
|
|
10227
|
+
if (base64Data) {
|
|
10228
|
+
blob = convertDataToBlob(base64Data, mimeType);
|
|
10229
|
+
}
|
|
10230
|
+
} else if (typeof data === "string" && data.length > 0) {
|
|
10231
|
+
blob = convertDataToBlob(data, mimeType);
|
|
10232
|
+
} else if (data instanceof Uint8Array) {
|
|
10233
|
+
blob = new Blob([data], { type: mimeType });
|
|
10234
|
+
} else if (typeof Buffer !== "undefined" && Buffer.isBuffer(data)) {
|
|
10235
|
+
blob = new Blob([data], { type: mimeType });
|
|
10236
|
+
} else if (data instanceof Blob) {
|
|
10237
|
+
blob = data;
|
|
10238
|
+
}
|
|
10239
|
+
if (blob) {
|
|
10240
|
+
return new Attachment({
|
|
10241
|
+
data: blob,
|
|
10242
|
+
filename: filename || `file.${getExtensionFromMediaType(mimeType)}`,
|
|
10243
|
+
contentType: mimeType
|
|
10244
|
+
});
|
|
10245
|
+
}
|
|
10246
|
+
} catch (error) {
|
|
10247
|
+
console.warn("Error converting data to attachment:", error);
|
|
10248
|
+
}
|
|
10249
|
+
return null;
|
|
10250
|
+
};
|
|
10251
|
+
function processAISDKCallInput(params) {
|
|
10252
|
+
return processInputAttachmentsSync(params);
|
|
10253
|
+
}
|
|
10254
|
+
function prepareAISDKCallInput(params, event, span, defaultDenyOutputPaths) {
|
|
10255
|
+
const { input, outputPromise } = processAISDKCallInput(params);
|
|
10256
|
+
if (outputPromise && input && typeof input === "object") {
|
|
10257
|
+
outputPromise.then((resolvedData) => {
|
|
10258
|
+
span.log({
|
|
10259
|
+
input: {
|
|
10260
|
+
...input,
|
|
10261
|
+
...resolvedData
|
|
10262
|
+
}
|
|
10263
|
+
});
|
|
10264
|
+
}).catch(() => {
|
|
10265
|
+
});
|
|
10266
|
+
}
|
|
10267
|
+
const metadata = extractMetadataFromCallParams(params, event.self);
|
|
10268
|
+
const childTracing = prepareAISDKChildTracing(
|
|
10269
|
+
params,
|
|
10270
|
+
event.self,
|
|
10271
|
+
span,
|
|
10272
|
+
defaultDenyOutputPaths,
|
|
10273
|
+
event.aiSDK
|
|
10274
|
+
);
|
|
10275
|
+
event.modelWrapped = childTracing.modelWrapped;
|
|
10276
|
+
if (childTracing.cleanup) {
|
|
10277
|
+
event.__braintrust_ai_sdk_cleanup = childTracing.cleanup;
|
|
10278
|
+
}
|
|
10279
|
+
return {
|
|
10280
|
+
input,
|
|
10281
|
+
metadata
|
|
10282
|
+
};
|
|
10283
|
+
}
|
|
10284
|
+
function prepareAISDKEmbedInput(params, self) {
|
|
10285
|
+
return {
|
|
10286
|
+
input: { ...params },
|
|
10287
|
+
metadata: extractMetadataFromEmbedParams(params, self)
|
|
10288
|
+
};
|
|
10289
|
+
}
|
|
10290
|
+
function extractTopLevelAISDKMetrics(result, event, startTime) {
|
|
10291
|
+
const metrics = hasModelChildTracing(event) ? {} : extractTokenMetrics(result);
|
|
10292
|
+
if (startTime) {
|
|
10293
|
+
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
10294
|
+
}
|
|
10295
|
+
return metrics;
|
|
10296
|
+
}
|
|
10297
|
+
function hasModelChildTracing(event) {
|
|
10298
|
+
return event?.modelWrapped === true || event?.__braintrust_ai_sdk_model_wrapped === true;
|
|
10299
|
+
}
|
|
10300
|
+
function createAISDKIntegrationMetadata() {
|
|
10301
|
+
return {
|
|
10302
|
+
braintrust: {
|
|
10303
|
+
integration_name: "ai-sdk",
|
|
10304
|
+
sdk_language: "typescript"
|
|
10305
|
+
}
|
|
10306
|
+
};
|
|
10307
|
+
}
|
|
10308
|
+
function resolveModelFromSelf(self) {
|
|
10309
|
+
return self && typeof self === "object" && "model" in self && self.model ? self.model : self && typeof self === "object" && "settings" in self && self.settings?.model ? self.settings?.model : void 0;
|
|
10310
|
+
}
|
|
10311
|
+
function extractBaseMetadata(model, self) {
|
|
10312
|
+
const metadata = createAISDKIntegrationMetadata();
|
|
10313
|
+
const { model: modelId, provider } = serializeModelWithProvider(
|
|
10314
|
+
model ?? resolveModelFromSelf(self)
|
|
10315
|
+
);
|
|
10316
|
+
if (modelId) {
|
|
10317
|
+
metadata.model = modelId;
|
|
10318
|
+
}
|
|
10319
|
+
if (provider) {
|
|
10320
|
+
metadata.provider = provider;
|
|
10321
|
+
}
|
|
10322
|
+
return metadata;
|
|
10323
|
+
}
|
|
10324
|
+
function extractMetadataFromCallParams(params, self) {
|
|
10325
|
+
const metadata = extractBaseMetadata(params.model, self);
|
|
10326
|
+
const tools = serializeAISDKToolsForLogging(params.tools);
|
|
10327
|
+
if (tools) {
|
|
10328
|
+
metadata.tools = tools;
|
|
10329
|
+
}
|
|
10330
|
+
return metadata;
|
|
10331
|
+
}
|
|
10332
|
+
function extractMetadataFromEmbedParams(params, self) {
|
|
10333
|
+
return extractBaseMetadata(params.model, self);
|
|
10334
|
+
}
|
|
10335
|
+
function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiSDK) {
|
|
10336
|
+
const cleanup = [];
|
|
10337
|
+
const patchedModels = /* @__PURE__ */ new WeakSet();
|
|
9794
10338
|
const patchedTools = /* @__PURE__ */ new WeakSet();
|
|
9795
10339
|
let modelWrapped = false;
|
|
9796
10340
|
const patchModel = (model) => {
|
|
9797
|
-
const resolvedModel = resolveAISDKModel(model);
|
|
10341
|
+
const resolvedModel = resolveAISDKModel(model, aiSDK);
|
|
9798
10342
|
if (!resolvedModel || typeof resolvedModel !== "object" || typeof resolvedModel.doGenerate !== "function" || patchedModels.has(resolvedModel) || resolvedModel[AUTO_PATCHED_MODEL]) {
|
|
9799
|
-
return;
|
|
10343
|
+
return resolvedModel;
|
|
9800
10344
|
}
|
|
9801
10345
|
patchedModels.add(resolvedModel);
|
|
9802
10346
|
resolvedModel[AUTO_PATCHED_MODEL] = true;
|
|
@@ -9825,7 +10369,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths) {
|
|
|
9825
10369
|
type: "llm" /* LLM */
|
|
9826
10370
|
},
|
|
9827
10371
|
event: {
|
|
9828
|
-
input:
|
|
10372
|
+
input: processAISDKCallInput(options).input,
|
|
9829
10373
|
metadata: baseMetadata
|
|
9830
10374
|
}
|
|
9831
10375
|
}
|
|
@@ -9839,7 +10383,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths) {
|
|
|
9839
10383
|
type: "llm" /* LLM */
|
|
9840
10384
|
},
|
|
9841
10385
|
event: {
|
|
9842
|
-
input:
|
|
10386
|
+
input: processAISDKCallInput(options).input,
|
|
9843
10387
|
metadata: baseMetadata
|
|
9844
10388
|
}
|
|
9845
10389
|
});
|
|
@@ -9847,6 +10391,8 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths) {
|
|
|
9847
10391
|
span,
|
|
9848
10392
|
() => Reflect.apply(originalDoStream, resolvedModel, [options])
|
|
9849
10393
|
);
|
|
10394
|
+
const streamStartTime = getCurrentUnixTimestamp();
|
|
10395
|
+
let firstChunkTime;
|
|
9850
10396
|
const output = {};
|
|
9851
10397
|
let text = "";
|
|
9852
10398
|
let reasoning = "";
|
|
@@ -9854,6 +10400,9 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths) {
|
|
|
9854
10400
|
let object = void 0;
|
|
9855
10401
|
const transformStream = new TransformStream({
|
|
9856
10402
|
transform(chunk, controller) {
|
|
10403
|
+
if (firstChunkTime === void 0) {
|
|
10404
|
+
firstChunkTime = getCurrentUnixTimestamp();
|
|
10405
|
+
}
|
|
9857
10406
|
switch (chunk.type) {
|
|
9858
10407
|
case "text-delta":
|
|
9859
10408
|
text += extractTextDelta(chunk);
|
|
@@ -9894,12 +10443,19 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths) {
|
|
|
9894
10443
|
if (object !== void 0) {
|
|
9895
10444
|
output.object = object;
|
|
9896
10445
|
}
|
|
10446
|
+
const metrics = extractTokenMetrics(output);
|
|
10447
|
+
if (firstChunkTime !== void 0) {
|
|
10448
|
+
metrics.time_to_first_token = Math.max(
|
|
10449
|
+
firstChunkTime - streamStartTime,
|
|
10450
|
+
1e-6
|
|
10451
|
+
);
|
|
10452
|
+
}
|
|
9897
10453
|
span.log({
|
|
9898
10454
|
output: processAISDKOutput(
|
|
9899
10455
|
output,
|
|
9900
10456
|
denyOutputPaths
|
|
9901
10457
|
),
|
|
9902
|
-
metrics
|
|
10458
|
+
metrics,
|
|
9903
10459
|
...buildResolvedMetadataPayload(output)
|
|
9904
10460
|
});
|
|
9905
10461
|
span.end();
|
|
@@ -9921,6 +10477,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths) {
|
|
|
9921
10477
|
}
|
|
9922
10478
|
delete resolvedModel[AUTO_PATCHED_MODEL];
|
|
9923
10479
|
});
|
|
10480
|
+
return resolvedModel;
|
|
9924
10481
|
};
|
|
9925
10482
|
const patchTool = (tool, name) => {
|
|
9926
10483
|
if (tool == null || typeof tool !== "object" || !("execute" in tool) || typeof tool.execute !== "function" || patchedTools.has(tool) || tool[AUTO_PATCHED_TOOL]) {
|
|
@@ -9993,17 +10550,26 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths) {
|
|
|
9993
10550
|
}
|
|
9994
10551
|
};
|
|
9995
10552
|
if (params && typeof params === "object") {
|
|
9996
|
-
patchModel(params.model);
|
|
10553
|
+
const patchedParamModel = patchModel(params.model);
|
|
10554
|
+
if (typeof params.model === "string" && patchedParamModel && typeof patchedParamModel === "object") {
|
|
10555
|
+
params.model = patchedParamModel;
|
|
10556
|
+
}
|
|
9997
10557
|
patchTools(params.tools);
|
|
9998
10558
|
}
|
|
9999
10559
|
if (self && typeof self === "object") {
|
|
10000
10560
|
const selfRecord = self;
|
|
10001
10561
|
if (selfRecord.model !== void 0) {
|
|
10002
|
-
patchModel(selfRecord.model);
|
|
10562
|
+
const patchedSelfModel = patchModel(selfRecord.model);
|
|
10563
|
+
if (typeof selfRecord.model === "string" && patchedSelfModel && typeof patchedSelfModel === "object") {
|
|
10564
|
+
selfRecord.model = patchedSelfModel;
|
|
10565
|
+
}
|
|
10003
10566
|
}
|
|
10004
10567
|
if (selfRecord.settings && typeof selfRecord.settings === "object") {
|
|
10005
10568
|
if (selfRecord.settings.model !== void 0) {
|
|
10006
|
-
patchModel(selfRecord.settings.model);
|
|
10569
|
+
const patchedSettingsModel = patchModel(selfRecord.settings.model);
|
|
10570
|
+
if (typeof selfRecord.settings.model === "string" && patchedSettingsModel && typeof patchedSettingsModel === "object") {
|
|
10571
|
+
selfRecord.settings.model = patchedSettingsModel;
|
|
10572
|
+
}
|
|
10007
10573
|
}
|
|
10008
10574
|
if (selfRecord.settings.tools !== void 0) {
|
|
10009
10575
|
patchTools(selfRecord.settings.tools);
|
|
@@ -10027,63 +10593,178 @@ function finalizeAISDKChildTracing(event) {
|
|
|
10027
10593
|
}
|
|
10028
10594
|
}
|
|
10029
10595
|
function patchAISDKStreamingResult(args) {
|
|
10030
|
-
const {
|
|
10596
|
+
const { defaultDenyOutputPaths, endEvent, result, span, startTime } = args;
|
|
10031
10597
|
if (!result || typeof result !== "object") {
|
|
10032
10598
|
return false;
|
|
10033
10599
|
}
|
|
10034
10600
|
const resultRecord = result;
|
|
10035
|
-
|
|
10601
|
+
attachKnownResultPromiseHandlers(resultRecord);
|
|
10602
|
+
if (isReadableStreamLike(resultRecord.baseStream)) {
|
|
10603
|
+
let firstChunkTime2;
|
|
10604
|
+
const wrappedBaseStream = resultRecord.baseStream.pipeThrough(
|
|
10605
|
+
new TransformStream({
|
|
10606
|
+
transform(chunk, controller) {
|
|
10607
|
+
if (firstChunkTime2 === void 0) {
|
|
10608
|
+
firstChunkTime2 = getCurrentUnixTimestamp();
|
|
10609
|
+
}
|
|
10610
|
+
controller.enqueue(chunk);
|
|
10611
|
+
},
|
|
10612
|
+
async flush() {
|
|
10613
|
+
const metrics = extractTopLevelAISDKMetrics(result, endEvent);
|
|
10614
|
+
if (metrics.time_to_first_token === void 0 && firstChunkTime2 !== void 0) {
|
|
10615
|
+
metrics.time_to_first_token = firstChunkTime2 - startTime;
|
|
10616
|
+
}
|
|
10617
|
+
const output = await processAISDKStreamingOutput(
|
|
10618
|
+
result,
|
|
10619
|
+
resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
|
|
10620
|
+
);
|
|
10621
|
+
const metadata = buildResolvedMetadataPayload(result).metadata;
|
|
10622
|
+
span.log({
|
|
10623
|
+
output,
|
|
10624
|
+
...metadata ? { metadata } : {},
|
|
10625
|
+
metrics
|
|
10626
|
+
});
|
|
10627
|
+
finalizeAISDKChildTracing(endEvent);
|
|
10628
|
+
span.end();
|
|
10629
|
+
}
|
|
10630
|
+
})
|
|
10631
|
+
);
|
|
10632
|
+
Object.defineProperty(resultRecord, "baseStream", {
|
|
10633
|
+
configurable: true,
|
|
10634
|
+
enumerable: true,
|
|
10635
|
+
value: wrappedBaseStream,
|
|
10636
|
+
writable: true
|
|
10637
|
+
});
|
|
10638
|
+
return true;
|
|
10639
|
+
}
|
|
10640
|
+
const streamField = findAsyncIterableField(resultRecord, [
|
|
10641
|
+
"partialObjectStream",
|
|
10642
|
+
"textStream",
|
|
10643
|
+
"fullStream",
|
|
10644
|
+
"stream"
|
|
10645
|
+
]);
|
|
10646
|
+
if (!streamField) {
|
|
10036
10647
|
return false;
|
|
10037
10648
|
}
|
|
10038
10649
|
let firstChunkTime;
|
|
10039
|
-
const
|
|
10040
|
-
|
|
10041
|
-
|
|
10042
|
-
|
|
10043
|
-
firstChunkTime = getCurrentUnixTimestamp();
|
|
10044
|
-
}
|
|
10045
|
-
controller.enqueue(chunk);
|
|
10046
|
-
},
|
|
10047
|
-
async flush() {
|
|
10048
|
-
const metrics = extractTopLevelAISDKMetrics(result, endEvent);
|
|
10049
|
-
if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
|
|
10050
|
-
metrics.time_to_first_token = firstChunkTime - startTime;
|
|
10051
|
-
}
|
|
10052
|
-
const output = await processAISDKStreamingOutput(
|
|
10053
|
-
result,
|
|
10054
|
-
denyOutputPaths
|
|
10055
|
-
);
|
|
10056
|
-
const metadata = buildResolvedMetadataPayload(result).metadata;
|
|
10057
|
-
span.log({
|
|
10058
|
-
output,
|
|
10059
|
-
...metadata ? { metadata } : {},
|
|
10060
|
-
metrics
|
|
10061
|
-
});
|
|
10062
|
-
finalizeAISDKChildTracing(endEvent);
|
|
10063
|
-
span.end();
|
|
10650
|
+
const wrappedStream = createPatchedAsyncIterable(streamField.stream, {
|
|
10651
|
+
onChunk: () => {
|
|
10652
|
+
if (firstChunkTime === void 0) {
|
|
10653
|
+
firstChunkTime = getCurrentUnixTimestamp();
|
|
10064
10654
|
}
|
|
10065
|
-
}
|
|
10066
|
-
|
|
10067
|
-
|
|
10655
|
+
},
|
|
10656
|
+
onComplete: async () => {
|
|
10657
|
+
const metrics = extractTopLevelAISDKMetrics(result, endEvent);
|
|
10658
|
+
if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
|
|
10659
|
+
metrics.time_to_first_token = firstChunkTime - startTime;
|
|
10660
|
+
}
|
|
10661
|
+
const output = await processAISDKStreamingOutput(
|
|
10662
|
+
result,
|
|
10663
|
+
resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
|
|
10664
|
+
);
|
|
10665
|
+
const metadata = buildResolvedMetadataPayload(result).metadata;
|
|
10666
|
+
span.log({
|
|
10667
|
+
output,
|
|
10668
|
+
...metadata ? { metadata } : {},
|
|
10669
|
+
metrics
|
|
10670
|
+
});
|
|
10671
|
+
finalizeAISDKChildTracing(endEvent);
|
|
10672
|
+
span.end();
|
|
10673
|
+
},
|
|
10674
|
+
onError: (error) => {
|
|
10675
|
+
span.log({
|
|
10676
|
+
error: error.message
|
|
10677
|
+
});
|
|
10678
|
+
finalizeAISDKChildTracing(endEvent);
|
|
10679
|
+
span.end();
|
|
10680
|
+
}
|
|
10681
|
+
});
|
|
10682
|
+
Object.defineProperty(resultRecord, streamField.field, {
|
|
10068
10683
|
configurable: true,
|
|
10069
10684
|
enumerable: true,
|
|
10070
|
-
value:
|
|
10685
|
+
value: wrappedStream,
|
|
10071
10686
|
writable: true
|
|
10072
10687
|
});
|
|
10073
10688
|
return true;
|
|
10074
10689
|
}
|
|
10690
|
+
function attachKnownResultPromiseHandlers(result) {
|
|
10691
|
+
const promiseLikeFields = [
|
|
10692
|
+
"content",
|
|
10693
|
+
"text",
|
|
10694
|
+
"object",
|
|
10695
|
+
"value",
|
|
10696
|
+
"values",
|
|
10697
|
+
"finishReason",
|
|
10698
|
+
"embedding",
|
|
10699
|
+
"embeddings",
|
|
10700
|
+
"usage",
|
|
10701
|
+
"totalUsage",
|
|
10702
|
+
"responses",
|
|
10703
|
+
"steps"
|
|
10704
|
+
];
|
|
10705
|
+
for (const field of promiseLikeFields) {
|
|
10706
|
+
try {
|
|
10707
|
+
if (!(field in result)) {
|
|
10708
|
+
continue;
|
|
10709
|
+
}
|
|
10710
|
+
const value = result[field];
|
|
10711
|
+
if (isPromiseLike(value)) {
|
|
10712
|
+
void Promise.resolve(value).catch(() => {
|
|
10713
|
+
});
|
|
10714
|
+
}
|
|
10715
|
+
} catch {
|
|
10716
|
+
}
|
|
10717
|
+
}
|
|
10718
|
+
}
|
|
10075
10719
|
function isReadableStreamLike(value) {
|
|
10076
10720
|
return value != null && typeof value === "object" && typeof value.pipeThrough === "function";
|
|
10077
10721
|
}
|
|
10722
|
+
function isAsyncIterableLike(value) {
|
|
10723
|
+
return value != null && typeof value === "object" && typeof value[Symbol.asyncIterator] === "function";
|
|
10724
|
+
}
|
|
10725
|
+
function findAsyncIterableField(result, candidateFields) {
|
|
10726
|
+
for (const field of candidateFields) {
|
|
10727
|
+
try {
|
|
10728
|
+
const stream = result[field];
|
|
10729
|
+
if (isAsyncIterableLike(stream)) {
|
|
10730
|
+
return { field, stream };
|
|
10731
|
+
}
|
|
10732
|
+
} catch {
|
|
10733
|
+
}
|
|
10734
|
+
}
|
|
10735
|
+
return null;
|
|
10736
|
+
}
|
|
10737
|
+
function createPatchedAsyncIterable(stream, hooks) {
|
|
10738
|
+
return {
|
|
10739
|
+
async *[Symbol.asyncIterator]() {
|
|
10740
|
+
try {
|
|
10741
|
+
for await (const chunk of stream) {
|
|
10742
|
+
hooks.onChunk(chunk);
|
|
10743
|
+
yield chunk;
|
|
10744
|
+
}
|
|
10745
|
+
await hooks.onComplete();
|
|
10746
|
+
} catch (error) {
|
|
10747
|
+
hooks.onError(
|
|
10748
|
+
error instanceof Error ? error : new Error(String(error))
|
|
10749
|
+
);
|
|
10750
|
+
throw error;
|
|
10751
|
+
}
|
|
10752
|
+
}
|
|
10753
|
+
};
|
|
10754
|
+
}
|
|
10078
10755
|
async function processAISDKStreamingOutput(result, denyOutputPaths) {
|
|
10079
10756
|
const output = processAISDKOutput(result, denyOutputPaths);
|
|
10080
10757
|
if (!output || typeof output !== "object") {
|
|
10081
10758
|
return output;
|
|
10082
10759
|
}
|
|
10083
10760
|
const outputRecord = output;
|
|
10761
|
+
const isObjectStreamingResult = result != null && typeof result === "object" && "partialObjectStream" in result;
|
|
10084
10762
|
try {
|
|
10085
|
-
if ("text" in result
|
|
10086
|
-
|
|
10763
|
+
if (!isObjectStreamingResult && "text" in result) {
|
|
10764
|
+
const resolvedText = await Promise.resolve(result.text);
|
|
10765
|
+
if (typeof resolvedText === "string") {
|
|
10766
|
+
outputRecord.text = resolvedText;
|
|
10767
|
+
}
|
|
10087
10768
|
}
|
|
10088
10769
|
} catch {
|
|
10089
10770
|
}
|
|
@@ -10096,6 +10777,15 @@ async function processAISDKStreamingOutput(result, denyOutputPaths) {
|
|
|
10096
10777
|
}
|
|
10097
10778
|
} catch {
|
|
10098
10779
|
}
|
|
10780
|
+
try {
|
|
10781
|
+
if ("finishReason" in result) {
|
|
10782
|
+
const resolvedFinishReason = await Promise.resolve(result.finishReason);
|
|
10783
|
+
if (resolvedFinishReason !== void 0) {
|
|
10784
|
+
outputRecord.finishReason = resolvedFinishReason;
|
|
10785
|
+
}
|
|
10786
|
+
}
|
|
10787
|
+
} catch {
|
|
10788
|
+
}
|
|
10099
10789
|
return outputRecord;
|
|
10100
10790
|
}
|
|
10101
10791
|
function buildAISDKChildMetadata(model) {
|
|
@@ -10118,16 +10808,25 @@ function buildResolvedMetadataPayload(result) {
|
|
|
10118
10808
|
if (gatewayInfo?.model) {
|
|
10119
10809
|
metadata.model = gatewayInfo.model;
|
|
10120
10810
|
}
|
|
10121
|
-
|
|
10122
|
-
|
|
10811
|
+
let finishReason;
|
|
10812
|
+
try {
|
|
10813
|
+
finishReason = result.finishReason;
|
|
10814
|
+
} catch {
|
|
10815
|
+
finishReason = void 0;
|
|
10816
|
+
}
|
|
10817
|
+
if (isPromiseLike(finishReason)) {
|
|
10818
|
+
void Promise.resolve(finishReason).catch(() => {
|
|
10819
|
+
});
|
|
10820
|
+
} else if (finishReason !== void 0) {
|
|
10821
|
+
metadata.finish_reason = finishReason;
|
|
10123
10822
|
}
|
|
10124
10823
|
return Object.keys(metadata).length > 0 ? { metadata } : {};
|
|
10125
10824
|
}
|
|
10126
|
-
function resolveAISDKModel(model) {
|
|
10825
|
+
function resolveAISDKModel(model, aiSDK) {
|
|
10127
10826
|
if (typeof model !== "string") {
|
|
10128
10827
|
return model;
|
|
10129
10828
|
}
|
|
10130
|
-
const provider = globalThis.AI_SDK_DEFAULT_PROVIDER ?? null;
|
|
10829
|
+
const provider = globalThis.AI_SDK_DEFAULT_PROVIDER ?? aiSDK?.gateway ?? null;
|
|
10131
10830
|
if (provider && typeof provider.languageModel === "function") {
|
|
10132
10831
|
return provider.languageModel(model);
|
|
10133
10832
|
}
|
|
@@ -10148,18 +10847,50 @@ function processAISDKOutput(output, denyOutputPaths) {
|
|
|
10148
10847
|
const merged = extractSerializableOutputFields(output);
|
|
10149
10848
|
return normalizeAISDKLoggedOutput(omit(merged, denyOutputPaths));
|
|
10150
10849
|
}
|
|
10151
|
-
function
|
|
10152
|
-
|
|
10153
|
-
|
|
10154
|
-
|
|
10155
|
-
|
|
10156
|
-
|
|
10157
|
-
|
|
10158
|
-
|
|
10159
|
-
|
|
10160
|
-
|
|
10161
|
-
|
|
10162
|
-
|
|
10850
|
+
function processAISDKEmbeddingOutput(output, denyOutputPaths) {
|
|
10851
|
+
if (!output || typeof output !== "object") {
|
|
10852
|
+
return output;
|
|
10853
|
+
}
|
|
10854
|
+
const summarized = {};
|
|
10855
|
+
const whitelistedFields = [
|
|
10856
|
+
"usage",
|
|
10857
|
+
"totalUsage",
|
|
10858
|
+
"warnings",
|
|
10859
|
+
"providerMetadata",
|
|
10860
|
+
"experimental_providerMetadata"
|
|
10861
|
+
];
|
|
10862
|
+
for (const field of whitelistedFields) {
|
|
10863
|
+
const value = safeSerializableFieldRead(output, field);
|
|
10864
|
+
if (value !== void 0 && isSerializableOutputValue(value)) {
|
|
10865
|
+
summarized[field] = value;
|
|
10866
|
+
}
|
|
10867
|
+
}
|
|
10868
|
+
const embedding = safeSerializableFieldRead(output, "embedding");
|
|
10869
|
+
if (Array.isArray(embedding)) {
|
|
10870
|
+
summarized.embedding_length = embedding.length;
|
|
10871
|
+
}
|
|
10872
|
+
const embeddings = safeSerializableFieldRead(output, "embeddings");
|
|
10873
|
+
if (Array.isArray(embeddings)) {
|
|
10874
|
+
summarized.embedding_count = embeddings.length;
|
|
10875
|
+
const firstEmbedding = embeddings.find((item) => Array.isArray(item));
|
|
10876
|
+
if (Array.isArray(firstEmbedding)) {
|
|
10877
|
+
summarized.embedding_length = firstEmbedding.length;
|
|
10878
|
+
}
|
|
10879
|
+
}
|
|
10880
|
+
return normalizeAISDKLoggedOutput(omit(summarized, denyOutputPaths));
|
|
10881
|
+
}
|
|
10882
|
+
function extractTokenMetrics(result) {
|
|
10883
|
+
const metrics = {};
|
|
10884
|
+
let usage;
|
|
10885
|
+
const totalUsageValue = safeResultFieldRead(result, "totalUsage");
|
|
10886
|
+
if (totalUsageValue !== void 0 && !isPromiseLike(totalUsageValue)) {
|
|
10887
|
+
usage = totalUsageValue;
|
|
10888
|
+
}
|
|
10889
|
+
if (!usage) {
|
|
10890
|
+
const usageValue = safeResultFieldRead(result, "usage");
|
|
10891
|
+
if (usageValue !== void 0 && !isPromiseLike(usageValue)) {
|
|
10892
|
+
usage = usageValue;
|
|
10893
|
+
}
|
|
10163
10894
|
}
|
|
10164
10895
|
if (!usage) {
|
|
10165
10896
|
return metrics;
|
|
@@ -10196,6 +10927,22 @@ function extractTokenMetrics(result) {
|
|
|
10196
10927
|
}
|
|
10197
10928
|
return metrics;
|
|
10198
10929
|
}
|
|
10930
|
+
function safeResultFieldRead(result, field) {
|
|
10931
|
+
return safeSerializableFieldRead(result, field);
|
|
10932
|
+
}
|
|
10933
|
+
function safeSerializableFieldRead(obj, field) {
|
|
10934
|
+
try {
|
|
10935
|
+
const value = obj?.[field];
|
|
10936
|
+
if (isPromiseLike(value)) {
|
|
10937
|
+
void Promise.resolve(value).catch(() => {
|
|
10938
|
+
});
|
|
10939
|
+
return void 0;
|
|
10940
|
+
}
|
|
10941
|
+
return value;
|
|
10942
|
+
} catch {
|
|
10943
|
+
return void 0;
|
|
10944
|
+
}
|
|
10945
|
+
}
|
|
10199
10946
|
function aggregateAISDKChunks(chunks, _result, endEvent) {
|
|
10200
10947
|
const lastChunk = chunks[chunks.length - 1];
|
|
10201
10948
|
const output = {};
|
|
@@ -10204,17 +10951,21 @@ function aggregateAISDKChunks(chunks, _result, endEvent) {
|
|
|
10204
10951
|
if (lastChunk) {
|
|
10205
10952
|
metrics = hasModelChildTracing(endEvent) ? {} : extractTokenMetrics(lastChunk);
|
|
10206
10953
|
metadata = buildResolvedMetadataPayload(lastChunk).metadata;
|
|
10207
|
-
|
|
10208
|
-
|
|
10954
|
+
const text = safeSerializableFieldRead(lastChunk, "text");
|
|
10955
|
+
if (text !== void 0) {
|
|
10956
|
+
output.text = text;
|
|
10209
10957
|
}
|
|
10210
|
-
|
|
10211
|
-
|
|
10958
|
+
const objectValue = safeSerializableFieldRead(lastChunk, "object");
|
|
10959
|
+
if (objectValue !== void 0) {
|
|
10960
|
+
output.object = objectValue;
|
|
10212
10961
|
}
|
|
10213
|
-
|
|
10214
|
-
|
|
10962
|
+
const finishReason = safeSerializableFieldRead(lastChunk, "finishReason");
|
|
10963
|
+
if (finishReason !== void 0) {
|
|
10964
|
+
output.finishReason = finishReason;
|
|
10215
10965
|
}
|
|
10216
|
-
|
|
10217
|
-
|
|
10966
|
+
const toolCalls = safeSerializableFieldRead(lastChunk, "toolCalls");
|
|
10967
|
+
if (toolCalls !== void 0) {
|
|
10968
|
+
output.toolCalls = toolCalls;
|
|
10218
10969
|
}
|
|
10219
10970
|
}
|
|
10220
10971
|
finalizeAISDKChildTracing(endEvent);
|
|
@@ -10223,14 +10974,20 @@ function aggregateAISDKChunks(chunks, _result, endEvent) {
|
|
|
10223
10974
|
function extractGetterValues(obj) {
|
|
10224
10975
|
const getterValues = {};
|
|
10225
10976
|
const getterNames = [
|
|
10977
|
+
"content",
|
|
10226
10978
|
"text",
|
|
10227
10979
|
"object",
|
|
10980
|
+
"value",
|
|
10981
|
+
"values",
|
|
10982
|
+
"embedding",
|
|
10983
|
+
"embeddings",
|
|
10228
10984
|
"finishReason",
|
|
10229
10985
|
"usage",
|
|
10230
10986
|
"totalUsage",
|
|
10231
10987
|
"toolCalls",
|
|
10232
10988
|
"toolResults",
|
|
10233
10989
|
"warnings",
|
|
10990
|
+
"responses",
|
|
10234
10991
|
"experimental_providerMetadata",
|
|
10235
10992
|
"providerMetadata",
|
|
10236
10993
|
"rawResponse",
|
|
@@ -10238,8 +10995,17 @@ function extractGetterValues(obj) {
|
|
|
10238
10995
|
];
|
|
10239
10996
|
for (const name of getterNames) {
|
|
10240
10997
|
try {
|
|
10241
|
-
if (obj
|
|
10242
|
-
|
|
10998
|
+
if (!obj || !(name in obj)) {
|
|
10999
|
+
continue;
|
|
11000
|
+
}
|
|
11001
|
+
const value = obj[name];
|
|
11002
|
+
if (isPromiseLike(value)) {
|
|
11003
|
+
void Promise.resolve(value).catch(() => {
|
|
11004
|
+
});
|
|
11005
|
+
continue;
|
|
11006
|
+
}
|
|
11007
|
+
if (isSerializableOutputValue(value)) {
|
|
11008
|
+
getterValues[name] = value;
|
|
10243
11009
|
}
|
|
10244
11010
|
} catch {
|
|
10245
11011
|
}
|
|
@@ -10261,6 +11027,11 @@ function extractSerializableOutputFields(output) {
|
|
|
10261
11027
|
for (const name of directFieldNames) {
|
|
10262
11028
|
try {
|
|
10263
11029
|
const value = output?.[name];
|
|
11030
|
+
if (isPromiseLike(value)) {
|
|
11031
|
+
void Promise.resolve(value).catch(() => {
|
|
11032
|
+
});
|
|
11033
|
+
continue;
|
|
11034
|
+
}
|
|
10264
11035
|
if (isSerializableOutputValue(value)) {
|
|
10265
11036
|
serialized[name] = value;
|
|
10266
11037
|
}
|
|
@@ -10272,6 +11043,9 @@ function extractSerializableOutputFields(output) {
|
|
|
10272
11043
|
...extractGetterValues(output)
|
|
10273
11044
|
};
|
|
10274
11045
|
}
|
|
11046
|
+
function isPromiseLike(value) {
|
|
11047
|
+
return value != null && typeof value === "object" && typeof value.then === "function";
|
|
11048
|
+
}
|
|
10275
11049
|
function isSerializableOutputValue(value) {
|
|
10276
11050
|
if (typeof value === "function") {
|
|
10277
11051
|
return false;
|
|
@@ -10313,8 +11087,9 @@ function parseGatewayModelString(modelString) {
|
|
|
10313
11087
|
return { model: modelString };
|
|
10314
11088
|
}
|
|
10315
11089
|
function extractGatewayRoutingInfo(result) {
|
|
10316
|
-
|
|
10317
|
-
|
|
11090
|
+
const steps = safeSerializableFieldRead(result, "steps");
|
|
11091
|
+
if (Array.isArray(steps) && steps.length > 0) {
|
|
11092
|
+
const routing2 = steps[0]?.providerMetadata?.gateway?.routing;
|
|
10318
11093
|
if (routing2) {
|
|
10319
11094
|
return {
|
|
10320
11095
|
provider: routing2.resolvedProvider || routing2.finalProvider,
|
|
@@ -10322,7 +11097,11 @@ function extractGatewayRoutingInfo(result) {
|
|
|
10322
11097
|
};
|
|
10323
11098
|
}
|
|
10324
11099
|
}
|
|
10325
|
-
const
|
|
11100
|
+
const providerMetadata = safeSerializableFieldRead(
|
|
11101
|
+
result,
|
|
11102
|
+
"providerMetadata"
|
|
11103
|
+
);
|
|
11104
|
+
const routing = providerMetadata?.gateway?.routing;
|
|
10326
11105
|
if (routing) {
|
|
10327
11106
|
return {
|
|
10328
11107
|
provider: routing.resolvedProvider || routing.finalProvider,
|
|
@@ -10332,10 +11111,11 @@ function extractGatewayRoutingInfo(result) {
|
|
|
10332
11111
|
return null;
|
|
10333
11112
|
}
|
|
10334
11113
|
function extractCostFromResult(result) {
|
|
10335
|
-
|
|
11114
|
+
const steps = safeSerializableFieldRead(result, "steps");
|
|
11115
|
+
if (Array.isArray(steps) && steps.length > 0) {
|
|
10336
11116
|
let totalCost = 0;
|
|
10337
11117
|
let foundCost = false;
|
|
10338
|
-
for (const step of
|
|
11118
|
+
for (const step of steps) {
|
|
10339
11119
|
const gateway2 = step?.providerMetadata?.gateway;
|
|
10340
11120
|
const stepCost = parseGatewayCost(gateway2?.cost) || parseGatewayCost(gateway2?.marketCost);
|
|
10341
11121
|
if (stepCost !== void 0 && stepCost > 0) {
|
|
@@ -10347,7 +11127,11 @@ function extractCostFromResult(result) {
|
|
|
10347
11127
|
return totalCost;
|
|
10348
11128
|
}
|
|
10349
11129
|
}
|
|
10350
|
-
const
|
|
11130
|
+
const providerMetadata = safeSerializableFieldRead(
|
|
11131
|
+
result,
|
|
11132
|
+
"providerMetadata"
|
|
11133
|
+
);
|
|
11134
|
+
const gateway = providerMetadata?.gateway;
|
|
10351
11135
|
const directCost = parseGatewayCost(gateway?.cost) || parseGatewayCost(gateway?.marketCost);
|
|
10352
11136
|
if (directCost !== void 0 && directCost > 0) {
|
|
10353
11137
|
return directCost;
|
|
@@ -10464,7 +11248,307 @@ var claudeAgentSDKChannels = defineChannels(
|
|
|
10464
11248
|
}
|
|
10465
11249
|
);
|
|
10466
11250
|
|
|
11251
|
+
// src/instrumentation/plugins/claude-agent-sdk-instrumentation-constants.ts
|
|
11252
|
+
var CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION = "__braintrust_skip_local_tool_hooks";
|
|
11253
|
+
|
|
11254
|
+
// src/instrumentation/plugins/claude-agent-sdk-local-tool-context.ts
|
|
11255
|
+
var LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED = Symbol.for(
|
|
11256
|
+
"braintrust.claude_agent_sdk.local_tool_context_async_iterator_patched"
|
|
11257
|
+
);
|
|
11258
|
+
function createLocalToolContextStore() {
|
|
11259
|
+
const maybeIsoWithAsyncLocalStorage = isomorph_default;
|
|
11260
|
+
if (typeof maybeIsoWithAsyncLocalStorage.newAsyncLocalStorage === "function") {
|
|
11261
|
+
return maybeIsoWithAsyncLocalStorage.newAsyncLocalStorage();
|
|
11262
|
+
}
|
|
11263
|
+
let currentStore;
|
|
11264
|
+
return {
|
|
11265
|
+
enterWith(store) {
|
|
11266
|
+
currentStore = store;
|
|
11267
|
+
},
|
|
11268
|
+
getStore() {
|
|
11269
|
+
return currentStore;
|
|
11270
|
+
},
|
|
11271
|
+
run(store, callback) {
|
|
11272
|
+
const previousStore = currentStore;
|
|
11273
|
+
currentStore = store;
|
|
11274
|
+
try {
|
|
11275
|
+
return callback();
|
|
11276
|
+
} finally {
|
|
11277
|
+
currentStore = previousStore;
|
|
11278
|
+
}
|
|
11279
|
+
}
|
|
11280
|
+
};
|
|
11281
|
+
}
|
|
11282
|
+
var localToolContextStore = createLocalToolContextStore();
|
|
11283
|
+
var fallbackLocalToolParentResolver;
|
|
11284
|
+
function createClaudeLocalToolContext() {
|
|
11285
|
+
return {};
|
|
11286
|
+
}
|
|
11287
|
+
function runWithClaudeLocalToolContext(callback, context) {
|
|
11288
|
+
return localToolContextStore.run(
|
|
11289
|
+
context ?? createClaudeLocalToolContext(),
|
|
11290
|
+
callback
|
|
11291
|
+
);
|
|
11292
|
+
}
|
|
11293
|
+
function ensureClaudeLocalToolContext() {
|
|
11294
|
+
const existing = localToolContextStore.getStore();
|
|
11295
|
+
if (existing) {
|
|
11296
|
+
return existing;
|
|
11297
|
+
}
|
|
11298
|
+
const created = {};
|
|
11299
|
+
localToolContextStore.enterWith(created);
|
|
11300
|
+
return created;
|
|
11301
|
+
}
|
|
11302
|
+
function setClaudeLocalToolParentResolver(resolver) {
|
|
11303
|
+
fallbackLocalToolParentResolver = resolver;
|
|
11304
|
+
const context = ensureClaudeLocalToolContext();
|
|
11305
|
+
if (!context) {
|
|
11306
|
+
return;
|
|
11307
|
+
}
|
|
11308
|
+
context.resolveLocalToolParent = resolver;
|
|
11309
|
+
}
|
|
11310
|
+
function getClaudeLocalToolParentResolver() {
|
|
11311
|
+
return localToolContextStore.getStore()?.resolveLocalToolParent ?? fallbackLocalToolParentResolver;
|
|
11312
|
+
}
|
|
11313
|
+
function isAsyncIterable2(value) {
|
|
11314
|
+
return value !== null && typeof value === "object" && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
|
|
11315
|
+
}
|
|
11316
|
+
function bindClaudeLocalToolContextToAsyncIterable(result, localToolContext) {
|
|
11317
|
+
if (!isAsyncIterable2(result) || Object.isFrozen(result) || Object.isSealed(result)) {
|
|
11318
|
+
return result;
|
|
11319
|
+
}
|
|
11320
|
+
const stream = result;
|
|
11321
|
+
const originalAsyncIterator = stream[Symbol.asyncIterator];
|
|
11322
|
+
if (originalAsyncIterator[LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED]) {
|
|
11323
|
+
return result;
|
|
11324
|
+
}
|
|
11325
|
+
const patchedAsyncIterator = function() {
|
|
11326
|
+
return runWithClaudeLocalToolContext(() => {
|
|
11327
|
+
const iterator = Reflect.apply(originalAsyncIterator, this, []);
|
|
11328
|
+
if (!iterator || typeof iterator !== "object") {
|
|
11329
|
+
return iterator;
|
|
11330
|
+
}
|
|
11331
|
+
const patchMethod = (methodName) => {
|
|
11332
|
+
const originalMethod = Reflect.get(iterator, methodName);
|
|
11333
|
+
if (typeof originalMethod !== "function") {
|
|
11334
|
+
return;
|
|
11335
|
+
}
|
|
11336
|
+
Reflect.set(
|
|
11337
|
+
iterator,
|
|
11338
|
+
methodName,
|
|
11339
|
+
(...args) => runWithClaudeLocalToolContext(
|
|
11340
|
+
() => Reflect.apply(
|
|
11341
|
+
originalMethod,
|
|
11342
|
+
iterator,
|
|
11343
|
+
args
|
|
11344
|
+
),
|
|
11345
|
+
localToolContext
|
|
11346
|
+
)
|
|
11347
|
+
);
|
|
11348
|
+
};
|
|
11349
|
+
patchMethod("next");
|
|
11350
|
+
patchMethod("return");
|
|
11351
|
+
patchMethod("throw");
|
|
11352
|
+
return iterator;
|
|
11353
|
+
}, localToolContext);
|
|
11354
|
+
};
|
|
11355
|
+
Object.defineProperty(
|
|
11356
|
+
patchedAsyncIterator,
|
|
11357
|
+
LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED,
|
|
11358
|
+
{
|
|
11359
|
+
configurable: false,
|
|
11360
|
+
enumerable: false,
|
|
11361
|
+
value: true,
|
|
11362
|
+
writable: false
|
|
11363
|
+
}
|
|
11364
|
+
);
|
|
11365
|
+
Reflect.set(stream, Symbol.asyncIterator, patchedAsyncIterator);
|
|
11366
|
+
return result;
|
|
11367
|
+
}
|
|
11368
|
+
|
|
11369
|
+
// src/instrumentation/plugins/claude-agent-sdk-local-tool-spans.ts
|
|
11370
|
+
var LOCAL_TOOL_HANDLER_WRAPPED = Symbol.for(
|
|
11371
|
+
"braintrust.claude_agent_sdk.local_tool_handler_wrapped"
|
|
11372
|
+
);
|
|
11373
|
+
function toErrorMessage(error) {
|
|
11374
|
+
return error instanceof Error ? error.message : String(error);
|
|
11375
|
+
}
|
|
11376
|
+
function isPromiseLike2(value) {
|
|
11377
|
+
return value !== null && typeof value === "object" && "then" in value && typeof value.then === "function";
|
|
11378
|
+
}
|
|
11379
|
+
function getToolUseIdFromExtra(extra) {
|
|
11380
|
+
if (!extra || typeof extra !== "object" || !("_meta" in extra)) {
|
|
11381
|
+
return void 0;
|
|
11382
|
+
}
|
|
11383
|
+
const meta = Reflect.get(extra, "_meta");
|
|
11384
|
+
if (!meta || typeof meta !== "object") {
|
|
11385
|
+
return void 0;
|
|
11386
|
+
}
|
|
11387
|
+
const toolUseId = Reflect.get(meta, "claudecode/toolUseId");
|
|
11388
|
+
return typeof toolUseId === "string" ? toolUseId : void 0;
|
|
11389
|
+
}
|
|
11390
|
+
function wrapLocalClaudeToolHandler(handler, getMetadata) {
|
|
11391
|
+
if (handler[LOCAL_TOOL_HANDLER_WRAPPED]) {
|
|
11392
|
+
return handler;
|
|
11393
|
+
}
|
|
11394
|
+
const wrappedHandler = function wrappedLocalToolHandler(...handlerArgs) {
|
|
11395
|
+
const metadata = getMetadata();
|
|
11396
|
+
const rawToolName = metadata.serverName ? `mcp__${metadata.serverName}__${metadata.toolName}` : metadata.toolName;
|
|
11397
|
+
const toolUseId = getToolUseIdFromExtra(handlerArgs[1]);
|
|
11398
|
+
const localToolParentResolver = getClaudeLocalToolParentResolver();
|
|
11399
|
+
const spanName = metadata.serverName ? `tool: ${metadata.serverName}/${metadata.toolName}` : `tool: ${metadata.toolName}`;
|
|
11400
|
+
const runWithResolvedParent = async () => {
|
|
11401
|
+
const parent = toolUseId && localToolParentResolver ? await localToolParentResolver(toolUseId).catch(() => void 0) : void 0;
|
|
11402
|
+
const span = startSpan({
|
|
11403
|
+
event: {
|
|
11404
|
+
input: handlerArgs[0],
|
|
11405
|
+
metadata: {
|
|
11406
|
+
"claude_agent_sdk.raw_tool_name": rawToolName,
|
|
11407
|
+
"gen_ai.tool.name": metadata.toolName,
|
|
11408
|
+
...toolUseId && { "gen_ai.tool.call.id": toolUseId },
|
|
11409
|
+
...metadata.serverName && {
|
|
11410
|
+
"mcp.server": metadata.serverName
|
|
11411
|
+
}
|
|
11412
|
+
}
|
|
11413
|
+
},
|
|
11414
|
+
name: spanName,
|
|
11415
|
+
...parent && { parent },
|
|
11416
|
+
spanAttributes: { type: "tool" /* TOOL */ }
|
|
11417
|
+
});
|
|
11418
|
+
const runHandler = () => Reflect.apply(handler, this, handlerArgs);
|
|
11419
|
+
const finalizeSuccess = (result) => {
|
|
11420
|
+
span.log({ output: result });
|
|
11421
|
+
span.end();
|
|
11422
|
+
return result;
|
|
11423
|
+
};
|
|
11424
|
+
const finalizeError = (error) => {
|
|
11425
|
+
span.log({ error: toErrorMessage(error) });
|
|
11426
|
+
span.end();
|
|
11427
|
+
throw error;
|
|
11428
|
+
};
|
|
11429
|
+
return withCurrent(span, () => {
|
|
11430
|
+
try {
|
|
11431
|
+
const result = runHandler();
|
|
11432
|
+
if (isPromiseLike2(result)) {
|
|
11433
|
+
return result.then(finalizeSuccess, finalizeError);
|
|
11434
|
+
}
|
|
11435
|
+
return finalizeSuccess(result);
|
|
11436
|
+
} catch (error) {
|
|
11437
|
+
return finalizeError(error);
|
|
11438
|
+
}
|
|
11439
|
+
});
|
|
11440
|
+
};
|
|
11441
|
+
return runWithResolvedParent();
|
|
11442
|
+
};
|
|
11443
|
+
Object.defineProperty(wrappedHandler, LOCAL_TOOL_HANDLER_WRAPPED, {
|
|
11444
|
+
configurable: false,
|
|
11445
|
+
enumerable: false,
|
|
11446
|
+
value: true,
|
|
11447
|
+
writable: false
|
|
11448
|
+
});
|
|
11449
|
+
return wrappedHandler;
|
|
11450
|
+
}
|
|
11451
|
+
function getRegisteredTools(instance) {
|
|
11452
|
+
if (!instance || typeof instance !== "object") {
|
|
11453
|
+
return void 0;
|
|
11454
|
+
}
|
|
11455
|
+
if (!("_registeredTools" in instance)) {
|
|
11456
|
+
return void 0;
|
|
11457
|
+
}
|
|
11458
|
+
const registeredTools = Reflect.get(instance, "_registeredTools");
|
|
11459
|
+
if (registeredTools instanceof Map) {
|
|
11460
|
+
return registeredTools;
|
|
11461
|
+
}
|
|
11462
|
+
if (registeredTools && typeof registeredTools === "object") {
|
|
11463
|
+
return registeredTools;
|
|
11464
|
+
}
|
|
11465
|
+
return void 0;
|
|
11466
|
+
}
|
|
11467
|
+
function wrapLocalMcpServerToolHandlers(serverName, serverConfig) {
|
|
11468
|
+
if (!serverConfig || typeof serverConfig !== "object") {
|
|
11469
|
+
return false;
|
|
11470
|
+
}
|
|
11471
|
+
if (!("instance" in serverConfig)) {
|
|
11472
|
+
return false;
|
|
11473
|
+
}
|
|
11474
|
+
const instance = Reflect.get(serverConfig, "instance");
|
|
11475
|
+
const registeredTools = getRegisteredTools(instance);
|
|
11476
|
+
if (!registeredTools) {
|
|
11477
|
+
return false;
|
|
11478
|
+
}
|
|
11479
|
+
let wrappedAny = false;
|
|
11480
|
+
const wrapHandler = (toolName, registration) => {
|
|
11481
|
+
if (!registration || typeof registration !== "object") {
|
|
11482
|
+
return;
|
|
11483
|
+
}
|
|
11484
|
+
const handler = Reflect.get(registration, "handler");
|
|
11485
|
+
if (typeof handler !== "function") {
|
|
11486
|
+
return;
|
|
11487
|
+
}
|
|
11488
|
+
const wrappedHandler = wrapLocalClaudeToolHandler(handler, () => ({
|
|
11489
|
+
serverName,
|
|
11490
|
+
toolName
|
|
11491
|
+
}));
|
|
11492
|
+
if (wrappedHandler !== handler) {
|
|
11493
|
+
Reflect.set(registration, "handler", wrappedHandler);
|
|
11494
|
+
wrappedAny = true;
|
|
11495
|
+
}
|
|
11496
|
+
};
|
|
11497
|
+
if (registeredTools instanceof Map) {
|
|
11498
|
+
for (const [toolName, registration] of registeredTools.entries()) {
|
|
11499
|
+
wrapHandler(toolName, registration);
|
|
11500
|
+
}
|
|
11501
|
+
return wrappedAny;
|
|
11502
|
+
}
|
|
11503
|
+
for (const [toolName, registration] of Object.entries(registeredTools)) {
|
|
11504
|
+
wrapHandler(toolName, registration);
|
|
11505
|
+
}
|
|
11506
|
+
return wrappedAny;
|
|
11507
|
+
}
|
|
11508
|
+
function collectLocalMcpServerToolHookNames(serverName, serverConfig) {
|
|
11509
|
+
const toolNames = /* @__PURE__ */ new Set();
|
|
11510
|
+
if (!serverConfig || typeof serverConfig !== "object") {
|
|
11511
|
+
return toolNames;
|
|
11512
|
+
}
|
|
11513
|
+
if ("instance" in serverConfig) {
|
|
11514
|
+
const instance = Reflect.get(serverConfig, "instance");
|
|
11515
|
+
const registeredTools = getRegisteredTools(instance);
|
|
11516
|
+
if (registeredTools instanceof Map) {
|
|
11517
|
+
for (const toolName of registeredTools.keys()) {
|
|
11518
|
+
toolNames.add(toolName);
|
|
11519
|
+
toolNames.add(`mcp__${serverName}__${toolName}`);
|
|
11520
|
+
}
|
|
11521
|
+
} else if (registeredTools) {
|
|
11522
|
+
for (const toolName of Object.keys(registeredTools)) {
|
|
11523
|
+
toolNames.add(toolName);
|
|
11524
|
+
toolNames.add(`mcp__${serverName}__${toolName}`);
|
|
11525
|
+
}
|
|
11526
|
+
}
|
|
11527
|
+
}
|
|
11528
|
+
if ("tools" in serverConfig) {
|
|
11529
|
+
const rawTools = Reflect.get(serverConfig, "tools");
|
|
11530
|
+
if (Array.isArray(rawTools)) {
|
|
11531
|
+
for (const tool of rawTools) {
|
|
11532
|
+
if (!tool || typeof tool !== "object") {
|
|
11533
|
+
continue;
|
|
11534
|
+
}
|
|
11535
|
+
const toolName = Reflect.get(tool, "name");
|
|
11536
|
+
if (typeof toolName !== "string") {
|
|
11537
|
+
continue;
|
|
11538
|
+
}
|
|
11539
|
+
toolNames.add(toolName);
|
|
11540
|
+
toolNames.add(`mcp__${serverName}__${toolName}`);
|
|
11541
|
+
}
|
|
11542
|
+
}
|
|
11543
|
+
}
|
|
11544
|
+
return toolNames;
|
|
11545
|
+
}
|
|
11546
|
+
|
|
10467
11547
|
// src/instrumentation/plugins/claude-agent-sdk-plugin.ts
|
|
11548
|
+
var ROOT_LLM_PARENT_KEY = "__root__";
|
|
11549
|
+
function llmParentKey(parentToolUseId) {
|
|
11550
|
+
return parentToolUseId ?? ROOT_LLM_PARENT_KEY;
|
|
11551
|
+
}
|
|
10468
11552
|
function isSubAgentToolName(toolName) {
|
|
10469
11553
|
return toolName === "Agent" || toolName === "Task";
|
|
10470
11554
|
}
|
|
@@ -10550,7 +11634,7 @@ function buildLLMInput(prompt, conversationHistory, capturedPromptMessages) {
|
|
|
10550
11634
|
function formatCapturedMessages(messages) {
|
|
10551
11635
|
return messages.length > 0 ? messages : [];
|
|
10552
11636
|
}
|
|
10553
|
-
async function createLLMSpanForMessages(messages, prompt, conversationHistory, options, startTime, capturedPromptMessages, parentSpan) {
|
|
11637
|
+
async function createLLMSpanForMessages(messages, prompt, conversationHistory, options, startTime, capturedPromptMessages, parentSpan, existingSpan) {
|
|
10554
11638
|
if (messages.length === 0) {
|
|
10555
11639
|
return void 0;
|
|
10556
11640
|
}
|
|
@@ -10570,7 +11654,7 @@ async function createLLMSpanForMessages(messages, prompt, conversationHistory, o
|
|
|
10570
11654
|
).filter(
|
|
10571
11655
|
(c) => c !== void 0
|
|
10572
11656
|
);
|
|
10573
|
-
const span = startSpan({
|
|
11657
|
+
const span = existingSpan ?? startSpan({
|
|
10574
11658
|
name: "anthropic.messages.create",
|
|
10575
11659
|
parent: parentSpan,
|
|
10576
11660
|
spanAttributes: {
|
|
@@ -10584,8 +11668,13 @@ async function createLLMSpanForMessages(messages, prompt, conversationHistory, o
|
|
|
10584
11668
|
metrics: usage,
|
|
10585
11669
|
output: outputs
|
|
10586
11670
|
});
|
|
11671
|
+
const spanExport = await span.export();
|
|
10587
11672
|
await span.end();
|
|
10588
|
-
|
|
11673
|
+
const finalMessage = lastMessage.message?.content && lastMessage.message?.role ? { content: lastMessage.message.content, role: lastMessage.message.role } : void 0;
|
|
11674
|
+
return {
|
|
11675
|
+
finalMessage,
|
|
11676
|
+
spanExport
|
|
11677
|
+
};
|
|
10589
11678
|
}
|
|
10590
11679
|
function getMcpServerMetadata(serverName, mcpServers) {
|
|
10591
11680
|
if (!serverName || !mcpServers) {
|
|
@@ -10629,11 +11718,51 @@ function parseToolName(rawToolName) {
|
|
|
10629
11718
|
toolName: rawToolName
|
|
10630
11719
|
};
|
|
10631
11720
|
}
|
|
10632
|
-
function
|
|
11721
|
+
function isLocalToolUse(rawToolName, mcpServers) {
|
|
11722
|
+
const parsed = parseToolName(rawToolName);
|
|
11723
|
+
if (!parsed.mcpServer || !mcpServers) {
|
|
11724
|
+
return false;
|
|
11725
|
+
}
|
|
11726
|
+
const serverConfig = mcpServers[parsed.mcpServer];
|
|
11727
|
+
if (!serverConfig || typeof serverConfig !== "object") {
|
|
11728
|
+
return false;
|
|
11729
|
+
}
|
|
11730
|
+
return serverConfig.type === "sdk" || "transport" in serverConfig;
|
|
11731
|
+
}
|
|
11732
|
+
function prepareLocalToolHandlersInMcpServers(mcpServers) {
|
|
11733
|
+
const localToolHookNames = /* @__PURE__ */ new Set();
|
|
11734
|
+
if (!mcpServers) {
|
|
11735
|
+
return {
|
|
11736
|
+
hasLocalToolHandlers: false,
|
|
11737
|
+
localToolHookNames
|
|
11738
|
+
};
|
|
11739
|
+
}
|
|
11740
|
+
let hasLocalToolHandlers = false;
|
|
11741
|
+
for (const [serverName, serverConfig] of Object.entries(mcpServers)) {
|
|
11742
|
+
const toolNames = collectLocalMcpServerToolHookNames(
|
|
11743
|
+
serverName,
|
|
11744
|
+
serverConfig
|
|
11745
|
+
);
|
|
11746
|
+
for (const toolName of toolNames) {
|
|
11747
|
+
localToolHookNames.add(toolName);
|
|
11748
|
+
}
|
|
11749
|
+
if (toolNames.size > 0) {
|
|
11750
|
+
hasLocalToolHandlers = true;
|
|
11751
|
+
}
|
|
11752
|
+
if (wrapLocalMcpServerToolHandlers(serverName, serverConfig)) {
|
|
11753
|
+
hasLocalToolHandlers = true;
|
|
11754
|
+
}
|
|
11755
|
+
}
|
|
11756
|
+
return { hasLocalToolHandlers, localToolHookNames };
|
|
11757
|
+
}
|
|
11758
|
+
function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers, localToolHookNames, skipLocalToolHooks, subAgentSpans, endedSubAgentSpans) {
|
|
10633
11759
|
const preToolUse = async (input, toolUseID) => {
|
|
10634
11760
|
if (input.hook_event_name !== "PreToolUse" || !toolUseID) {
|
|
10635
11761
|
return {};
|
|
10636
11762
|
}
|
|
11763
|
+
if (skipLocalToolHooks && (isLocalToolUse(input.tool_name, mcpServers) || localToolHookNames.has(input.tool_name))) {
|
|
11764
|
+
return {};
|
|
11765
|
+
}
|
|
10637
11766
|
if (isSubAgentToolName(input.tool_name)) {
|
|
10638
11767
|
return {};
|
|
10639
11768
|
}
|
|
@@ -10662,6 +11791,9 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
|
|
|
10662
11791
|
if (input.hook_event_name !== "PostToolUse" || !toolUseID) {
|
|
10663
11792
|
return {};
|
|
10664
11793
|
}
|
|
11794
|
+
if (skipLocalToolHooks && (isLocalToolUse(input.tool_name, mcpServers) || localToolHookNames.has(input.tool_name))) {
|
|
11795
|
+
return {};
|
|
11796
|
+
}
|
|
10665
11797
|
const subAgentSpan = subAgentSpans.get(toolUseID);
|
|
10666
11798
|
if (subAgentSpan) {
|
|
10667
11799
|
try {
|
|
@@ -10702,6 +11834,9 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
|
|
|
10702
11834
|
if (input.hook_event_name !== "PostToolUseFailure" || !toolUseID) {
|
|
10703
11835
|
return {};
|
|
10704
11836
|
}
|
|
11837
|
+
if (skipLocalToolHooks && (isLocalToolUse(input.tool_name, mcpServers) || localToolHookNames.has(input.tool_name))) {
|
|
11838
|
+
return {};
|
|
11839
|
+
}
|
|
10705
11840
|
const subAgentSpan = subAgentSpans.get(toolUseID);
|
|
10706
11841
|
if (subAgentSpan) {
|
|
10707
11842
|
try {
|
|
@@ -10736,11 +11871,13 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
|
|
|
10736
11871
|
};
|
|
10737
11872
|
return { postToolUse, postToolUseFailure, preToolUse };
|
|
10738
11873
|
}
|
|
10739
|
-
function injectTracingHooks(options, resolveParentSpan, activeToolSpans, subAgentSpans, endedSubAgentSpans) {
|
|
11874
|
+
function injectTracingHooks(options, resolveParentSpan, activeToolSpans, localToolHookNames, skipLocalToolHooks, subAgentSpans, endedSubAgentSpans) {
|
|
10740
11875
|
const { preToolUse, postToolUse, postToolUseFailure } = createToolTracingHooks(
|
|
10741
11876
|
resolveParentSpan,
|
|
10742
11877
|
activeToolSpans,
|
|
10743
11878
|
options.mcpServers,
|
|
11879
|
+
localToolHookNames,
|
|
11880
|
+
skipLocalToolHooks,
|
|
10744
11881
|
subAgentSpans,
|
|
10745
11882
|
endedSubAgentSpans
|
|
10746
11883
|
);
|
|
@@ -10771,6 +11908,7 @@ async function finalizeCurrentMessageGroup(state) {
|
|
|
10771
11908
|
return;
|
|
10772
11909
|
}
|
|
10773
11910
|
const parentToolUseId = state.currentMessages[0]?.parent_tool_use_id ?? null;
|
|
11911
|
+
const parentKey = llmParentKey(parentToolUseId);
|
|
10774
11912
|
let parentSpan = await state.span.export();
|
|
10775
11913
|
if (parentToolUseId) {
|
|
10776
11914
|
const subAgentSpan = state.subAgentSpans.get(parentToolUseId);
|
|
@@ -10778,17 +11916,30 @@ async function finalizeCurrentMessageGroup(state) {
|
|
|
10778
11916
|
parentSpan = await subAgentSpan.export();
|
|
10779
11917
|
}
|
|
10780
11918
|
}
|
|
10781
|
-
const
|
|
11919
|
+
const existingLlmSpan = state.activeLlmSpansByParentToolUse.get(parentKey);
|
|
11920
|
+
const llmSpanResult = await createLLMSpanForMessages(
|
|
10782
11921
|
state.currentMessages,
|
|
10783
11922
|
state.originalPrompt,
|
|
10784
11923
|
state.finalResults,
|
|
10785
11924
|
state.options,
|
|
10786
11925
|
state.currentMessageStartTime,
|
|
10787
11926
|
state.capturedPromptMessages,
|
|
10788
|
-
parentSpan
|
|
11927
|
+
parentSpan,
|
|
11928
|
+
existingLlmSpan
|
|
10789
11929
|
);
|
|
10790
|
-
|
|
10791
|
-
|
|
11930
|
+
state.activeLlmSpansByParentToolUse.delete(parentKey);
|
|
11931
|
+
if (llmSpanResult) {
|
|
11932
|
+
if (parentToolUseId) {
|
|
11933
|
+
state.latestLlmParentBySubAgentToolUse.set(
|
|
11934
|
+
parentToolUseId,
|
|
11935
|
+
llmSpanResult.spanExport
|
|
11936
|
+
);
|
|
11937
|
+
} else {
|
|
11938
|
+
state.latestRootLlmParentRef.value = llmSpanResult.spanExport;
|
|
11939
|
+
}
|
|
11940
|
+
if (llmSpanResult.finalMessage) {
|
|
11941
|
+
state.finalResults.push(llmSpanResult.finalMessage);
|
|
11942
|
+
}
|
|
10792
11943
|
}
|
|
10793
11944
|
const lastMessage = state.currentMessages[state.currentMessages.length - 1];
|
|
10794
11945
|
if (lastMessage?.message?.usage) {
|
|
@@ -10856,6 +12007,29 @@ async function handleStreamMessage(state, message) {
|
|
|
10856
12007
|
state.currentMessageStartTime = getCurrentUnixTimestamp();
|
|
10857
12008
|
}
|
|
10858
12009
|
if (message.type === "assistant" && message.message?.usage) {
|
|
12010
|
+
const parentToolUseId = message.parent_tool_use_id ?? null;
|
|
12011
|
+
const parentKey = llmParentKey(parentToolUseId);
|
|
12012
|
+
if (!state.activeLlmSpansByParentToolUse.has(parentKey)) {
|
|
12013
|
+
let llmParentSpan = await state.span.export();
|
|
12014
|
+
if (parentToolUseId) {
|
|
12015
|
+
const subAgentSpan = await ensureSubAgentSpan(
|
|
12016
|
+
state.pendingSubAgentNames,
|
|
12017
|
+
state.span,
|
|
12018
|
+
state.subAgentSpans,
|
|
12019
|
+
parentToolUseId
|
|
12020
|
+
);
|
|
12021
|
+
llmParentSpan = await subAgentSpan.export();
|
|
12022
|
+
}
|
|
12023
|
+
const llmSpan = startSpan({
|
|
12024
|
+
name: "anthropic.messages.create",
|
|
12025
|
+
parent: llmParentSpan,
|
|
12026
|
+
spanAttributes: {
|
|
12027
|
+
type: "llm" /* LLM */
|
|
12028
|
+
},
|
|
12029
|
+
startTime: state.currentMessageStartTime
|
|
12030
|
+
});
|
|
12031
|
+
state.activeLlmSpansByParentToolUse.set(parentKey, llmSpan);
|
|
12032
|
+
}
|
|
10859
12033
|
state.currentMessages.push(message);
|
|
10860
12034
|
}
|
|
10861
12035
|
if (message.type !== "result" || !message.usage) {
|
|
@@ -10916,6 +12090,10 @@ async function finalizeQuerySpan(state) {
|
|
|
10916
12090
|
}
|
|
10917
12091
|
}
|
|
10918
12092
|
} finally {
|
|
12093
|
+
for (const llmSpan of state.activeLlmSpansByParentToolUse.values()) {
|
|
12094
|
+
llmSpan.end();
|
|
12095
|
+
}
|
|
12096
|
+
state.activeLlmSpansByParentToolUse.clear();
|
|
10919
12097
|
for (const [id, subAgentSpan] of state.subAgentSpans) {
|
|
10920
12098
|
if (!state.endedSubAgentSpans.has(id)) {
|
|
10921
12099
|
subAgentSpan.end();
|
|
@@ -10981,26 +12159,51 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
10981
12159
|
console.error("Error extracting input for Claude Agent SDK:", error);
|
|
10982
12160
|
}
|
|
10983
12161
|
const activeToolSpans = /* @__PURE__ */ new Map();
|
|
12162
|
+
const activeLlmSpansByParentToolUse = /* @__PURE__ */ new Map();
|
|
10984
12163
|
const subAgentSpans = /* @__PURE__ */ new Map();
|
|
10985
12164
|
const endedSubAgentSpans = /* @__PURE__ */ new Set();
|
|
10986
12165
|
const toolUseToParent = /* @__PURE__ */ new Map();
|
|
12166
|
+
const latestLlmParentBySubAgentToolUse = /* @__PURE__ */ new Map();
|
|
12167
|
+
const latestRootLlmParentRef = {
|
|
12168
|
+
value: void 0
|
|
12169
|
+
};
|
|
10987
12170
|
const pendingSubAgentNames = /* @__PURE__ */ new Map();
|
|
12171
|
+
const localToolContext = createClaudeLocalToolContext();
|
|
12172
|
+
const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
|
|
12173
|
+
const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
|
|
12174
|
+
const resolveToolUseParentSpan = async (toolUseID) => {
|
|
12175
|
+
const parentToolUseId = toolUseToParent.get(toolUseID) ?? null;
|
|
12176
|
+
const parentKey = llmParentKey(parentToolUseId);
|
|
12177
|
+
const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
|
|
12178
|
+
if (activeLlmSpan) {
|
|
12179
|
+
return activeLlmSpan.export();
|
|
12180
|
+
}
|
|
12181
|
+
if (parentToolUseId) {
|
|
12182
|
+
const parentLlm = latestLlmParentBySubAgentToolUse.get(parentToolUseId);
|
|
12183
|
+
if (parentLlm) {
|
|
12184
|
+
return parentLlm;
|
|
12185
|
+
}
|
|
12186
|
+
const subAgentSpan = await ensureSubAgentSpan(
|
|
12187
|
+
pendingSubAgentNames,
|
|
12188
|
+
span,
|
|
12189
|
+
subAgentSpans,
|
|
12190
|
+
parentToolUseId
|
|
12191
|
+
);
|
|
12192
|
+
return subAgentSpan.export();
|
|
12193
|
+
}
|
|
12194
|
+
if (latestRootLlmParentRef.value) {
|
|
12195
|
+
return latestRootLlmParentRef.value;
|
|
12196
|
+
}
|
|
12197
|
+
return span.export();
|
|
12198
|
+
};
|
|
12199
|
+
localToolContext.resolveLocalToolParent = resolveToolUseParentSpan;
|
|
12200
|
+
setClaudeLocalToolParentResolver(resolveToolUseParentSpan);
|
|
10988
12201
|
const optionsWithHooks = injectTracingHooks(
|
|
10989
12202
|
options,
|
|
10990
|
-
|
|
10991
|
-
const parentToolUseId = toolUseToParent.get(toolUseID);
|
|
10992
|
-
if (parentToolUseId) {
|
|
10993
|
-
const subAgentSpan = await ensureSubAgentSpan(
|
|
10994
|
-
pendingSubAgentNames,
|
|
10995
|
-
span,
|
|
10996
|
-
subAgentSpans,
|
|
10997
|
-
parentToolUseId
|
|
10998
|
-
);
|
|
10999
|
-
return subAgentSpan.export();
|
|
11000
|
-
}
|
|
11001
|
-
return span.export();
|
|
11002
|
-
},
|
|
12203
|
+
resolveToolUseParentSpan,
|
|
11003
12204
|
activeToolSpans,
|
|
12205
|
+
localToolHookNames,
|
|
12206
|
+
skipLocalToolHooks,
|
|
11004
12207
|
subAgentSpans,
|
|
11005
12208
|
endedSubAgentSpans
|
|
11006
12209
|
);
|
|
@@ -11008,6 +12211,7 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
11008
12211
|
event.arguments[0] = params;
|
|
11009
12212
|
spans.set(event, {
|
|
11010
12213
|
accumulatedOutputTokens: 0,
|
|
12214
|
+
activeLlmSpansByParentToolUse,
|
|
11011
12215
|
activeToolSpans,
|
|
11012
12216
|
capturedPromptMessages,
|
|
11013
12217
|
currentMessageId: void 0,
|
|
@@ -11023,7 +12227,10 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
11023
12227
|
promptStarted: () => promptStarted,
|
|
11024
12228
|
span,
|
|
11025
12229
|
subAgentSpans,
|
|
11026
|
-
|
|
12230
|
+
latestLlmParentBySubAgentToolUse,
|
|
12231
|
+
latestRootLlmParentRef,
|
|
12232
|
+
toolUseToParent,
|
|
12233
|
+
localToolContext
|
|
11027
12234
|
});
|
|
11028
12235
|
},
|
|
11029
12236
|
end: (event) => {
|
|
@@ -11031,7 +12238,10 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
11031
12238
|
if (!state) {
|
|
11032
12239
|
return;
|
|
11033
12240
|
}
|
|
11034
|
-
const eventResult =
|
|
12241
|
+
const eventResult = bindClaudeLocalToolContextToAsyncIterable(
|
|
12242
|
+
event.result,
|
|
12243
|
+
state.localToolContext
|
|
12244
|
+
);
|
|
11035
12245
|
if (eventResult === void 0) {
|
|
11036
12246
|
state.span.end();
|
|
11037
12247
|
spans.delete(event);
|
|
@@ -11048,20 +12258,16 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
11048
12258
|
);
|
|
11049
12259
|
});
|
|
11050
12260
|
},
|
|
11051
|
-
onComplete: () => {
|
|
11052
|
-
|
|
11053
|
-
|
|
11054
|
-
|
|
11055
|
-
|
|
11056
|
-
|
|
11057
|
-
void state.processing.then(() => {
|
|
11058
|
-
state.span.log({
|
|
11059
|
-
error: error.message
|
|
11060
|
-
});
|
|
11061
|
-
}).then(() => finalizeQuerySpan(state)).finally(() => {
|
|
11062
|
-
spans.delete(event);
|
|
12261
|
+
onComplete: () => state.processing.then(() => finalizeQuerySpan(state)).finally(() => {
|
|
12262
|
+
spans.delete(event);
|
|
12263
|
+
}),
|
|
12264
|
+
onError: (error) => state.processing.then(() => {
|
|
12265
|
+
state.span.log({
|
|
12266
|
+
error: error.message
|
|
11063
12267
|
});
|
|
11064
|
-
}
|
|
12268
|
+
}).then(() => finalizeQuerySpan(state)).finally(() => {
|
|
12269
|
+
spans.delete(event);
|
|
12270
|
+
})
|
|
11065
12271
|
});
|
|
11066
12272
|
return;
|
|
11067
12273
|
}
|
|
@@ -11209,12 +12415,14 @@ var GoogleGenAIPlugin = class extends BasePlugin {
|
|
|
11209
12415
|
const params = event.arguments[0];
|
|
11210
12416
|
streamEvent.googleGenAIInput = serializeInput(params);
|
|
11211
12417
|
streamEvent.googleGenAIMetadata = extractMetadata(params);
|
|
12418
|
+
streamEvent.googleGenAIStartTime = getCurrentUnixTimestamp();
|
|
11212
12419
|
},
|
|
11213
12420
|
asyncEnd: (event) => {
|
|
11214
12421
|
const streamEvent = event;
|
|
11215
12422
|
patchGoogleGenAIStreamingResult({
|
|
11216
12423
|
input: streamEvent.googleGenAIInput,
|
|
11217
12424
|
metadata: streamEvent.googleGenAIMetadata,
|
|
12425
|
+
startTime: streamEvent.googleGenAIStartTime,
|
|
11218
12426
|
result: streamEvent.result
|
|
11219
12427
|
});
|
|
11220
12428
|
},
|
|
@@ -11238,19 +12446,20 @@ function ensureSpanState(states, event, create) {
|
|
|
11238
12446
|
}
|
|
11239
12447
|
function bindCurrentSpanStoreToStart2(tracingChannel, states, create) {
|
|
11240
12448
|
const state = _internalGetGlobalState();
|
|
12449
|
+
const contextManager = state?.contextManager;
|
|
11241
12450
|
const startChannel = tracingChannel.start;
|
|
11242
|
-
const currentSpanStore =
|
|
12451
|
+
const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
|
|
11243
12452
|
if (!startChannel?.bindStore || !currentSpanStore) {
|
|
11244
12453
|
return void 0;
|
|
11245
12454
|
}
|
|
11246
|
-
startChannel.bindStore(
|
|
11247
|
-
|
|
11248
|
-
(event) => ensureSpanState(
|
|
12455
|
+
startChannel.bindStore(currentSpanStore, (event) => {
|
|
12456
|
+
const span = ensureSpanState(
|
|
11249
12457
|
states,
|
|
11250
12458
|
event,
|
|
11251
12459
|
() => create(event)
|
|
11252
|
-
).span
|
|
11253
|
-
|
|
12460
|
+
).span;
|
|
12461
|
+
return contextManager.wrapSpanForStore(span);
|
|
12462
|
+
});
|
|
11254
12463
|
return () => {
|
|
11255
12464
|
startChannel.unbindStore?.(currentSpanStore);
|
|
11256
12465
|
};
|
|
@@ -11267,7 +12476,7 @@ function logErrorAndEndSpan(states, event) {
|
|
|
11267
12476
|
states.delete(event);
|
|
11268
12477
|
}
|
|
11269
12478
|
function patchGoogleGenAIStreamingResult(args) {
|
|
11270
|
-
const { input, metadata, result } = args;
|
|
12479
|
+
const { input, metadata, result, startTime } = args;
|
|
11271
12480
|
if (!input || !metadata || !result || typeof result !== "object" || typeof result.next !== "function") {
|
|
11272
12481
|
return false;
|
|
11273
12482
|
}
|
|
@@ -11275,7 +12484,7 @@ function patchGoogleGenAIStreamingResult(args) {
|
|
|
11275
12484
|
let firstTokenTime = null;
|
|
11276
12485
|
let finalized = false;
|
|
11277
12486
|
let span = null;
|
|
11278
|
-
|
|
12487
|
+
const requestStartTime = startTime ?? getCurrentUnixTimestamp();
|
|
11279
12488
|
const ensureSpan = () => {
|
|
11280
12489
|
if (!span) {
|
|
11281
12490
|
span = startSpan({
|
|
@@ -11288,7 +12497,6 @@ function patchGoogleGenAIStreamingResult(args) {
|
|
|
11288
12497
|
metadata
|
|
11289
12498
|
}
|
|
11290
12499
|
});
|
|
11291
|
-
startTime = getCurrentUnixTimestamp();
|
|
11292
12500
|
}
|
|
11293
12501
|
return span;
|
|
11294
12502
|
};
|
|
@@ -11342,11 +12550,11 @@ function patchGoogleGenAIStreamingResult(args) {
|
|
|
11342
12550
|
}
|
|
11343
12551
|
chunks.push(nextResult.value);
|
|
11344
12552
|
}
|
|
11345
|
-
if (nextResult.done
|
|
12553
|
+
if (nextResult.done) {
|
|
11346
12554
|
finalize({
|
|
11347
12555
|
result: aggregateGenerateContentChunks(
|
|
11348
12556
|
chunks,
|
|
11349
|
-
|
|
12557
|
+
requestStartTime,
|
|
11350
12558
|
firstTokenTime
|
|
11351
12559
|
)
|
|
11352
12560
|
});
|
|
@@ -11366,13 +12574,13 @@ function patchGoogleGenAIStreamingResult(args) {
|
|
|
11366
12574
|
...returnArgs
|
|
11367
12575
|
);
|
|
11368
12576
|
} finally {
|
|
11369
|
-
if (
|
|
12577
|
+
if (chunks.length > 0) {
|
|
11370
12578
|
finalize({
|
|
11371
|
-
result:
|
|
12579
|
+
result: aggregateGenerateContentChunks(
|
|
11372
12580
|
chunks,
|
|
11373
|
-
|
|
12581
|
+
requestStartTime,
|
|
11374
12582
|
firstTokenTime
|
|
11375
|
-
)
|
|
12583
|
+
)
|
|
11376
12584
|
});
|
|
11377
12585
|
} else {
|
|
11378
12586
|
finalize({});
|
|
@@ -11646,50 +12854,165 @@ function tryToDict(obj) {
|
|
|
11646
12854
|
return null;
|
|
11647
12855
|
}
|
|
11648
12856
|
|
|
11649
|
-
// src/instrumentation/plugins/openrouter-channels.ts
|
|
11650
|
-
var
|
|
11651
|
-
chatSend: channel({
|
|
11652
|
-
channelName: "chat.send",
|
|
11653
|
-
kind: "async"
|
|
11654
|
-
}),
|
|
11655
|
-
embeddingsGenerate: channel({
|
|
11656
|
-
channelName: "embeddings.generate",
|
|
11657
|
-
kind: "async"
|
|
11658
|
-
}),
|
|
11659
|
-
betaResponsesSend: channel({
|
|
11660
|
-
channelName: "beta.responses.send",
|
|
11661
|
-
kind: "async"
|
|
11662
|
-
}),
|
|
12857
|
+
// src/instrumentation/plugins/openrouter-agent-channels.ts
|
|
12858
|
+
var openRouterAgentChannels = defineChannels("@openrouter/agent", {
|
|
11663
12859
|
callModel: channel({
|
|
11664
12860
|
channelName: "callModel",
|
|
11665
12861
|
kind: "sync-stream"
|
|
11666
12862
|
}),
|
|
12863
|
+
callModelTurn: channel({
|
|
12864
|
+
channelName: "callModel.turn",
|
|
12865
|
+
kind: "async"
|
|
12866
|
+
}),
|
|
11667
12867
|
toolExecute: channel({
|
|
11668
12868
|
channelName: "tool.execute",
|
|
11669
12869
|
kind: "async"
|
|
11670
12870
|
})
|
|
11671
12871
|
});
|
|
11672
12872
|
|
|
11673
|
-
// src/openrouter-
|
|
11674
|
-
var
|
|
11675
|
-
|
|
11676
|
-
|
|
11677
|
-
|
|
11678
|
-
|
|
11679
|
-
|
|
11680
|
-
|
|
11681
|
-
|
|
11682
|
-
|
|
11683
|
-
|
|
11684
|
-
|
|
11685
|
-
|
|
11686
|
-
|
|
11687
|
-
|
|
11688
|
-
|
|
11689
|
-
|
|
11690
|
-
|
|
11691
|
-
|
|
11692
|
-
|
|
12873
|
+
// src/instrumentation/plugins/openrouter-agent-plugin.ts
|
|
12874
|
+
var OpenRouterAgentPlugin = class extends BasePlugin {
|
|
12875
|
+
onEnable() {
|
|
12876
|
+
this.subscribeToOpenRouterAgentChannels();
|
|
12877
|
+
}
|
|
12878
|
+
onDisable() {
|
|
12879
|
+
this.unsubscribers = unsubscribeAll(this.unsubscribers);
|
|
12880
|
+
}
|
|
12881
|
+
subscribeToOpenRouterAgentChannels() {
|
|
12882
|
+
this.unsubscribers.push(
|
|
12883
|
+
traceSyncStreamChannel(openRouterAgentChannels.callModel, {
|
|
12884
|
+
name: "openrouter.callModel",
|
|
12885
|
+
type: "llm" /* LLM */,
|
|
12886
|
+
extractInput: (args) => {
|
|
12887
|
+
const request = getOpenRouterCallModelRequestArg(args);
|
|
12888
|
+
return {
|
|
12889
|
+
input: request ? extractOpenRouterCallModelInput(request) : void 0,
|
|
12890
|
+
metadata: request ? extractOpenRouterCallModelMetadata(request) : { provider: "openrouter" }
|
|
12891
|
+
};
|
|
12892
|
+
},
|
|
12893
|
+
patchResult: ({ endEvent, result, span }) => {
|
|
12894
|
+
return patchOpenRouterCallModelResult({
|
|
12895
|
+
request: getOpenRouterCallModelRequestArg(endEvent.arguments),
|
|
12896
|
+
result,
|
|
12897
|
+
span
|
|
12898
|
+
});
|
|
12899
|
+
}
|
|
12900
|
+
})
|
|
12901
|
+
);
|
|
12902
|
+
this.unsubscribers.push(
|
|
12903
|
+
traceAsyncChannel(openRouterAgentChannels.callModelTurn, {
|
|
12904
|
+
name: "openrouter.beta.responses.send",
|
|
12905
|
+
type: "llm" /* LLM */,
|
|
12906
|
+
extractInput: (args, event) => {
|
|
12907
|
+
const request = getOpenRouterCallModelRequestArg(args);
|
|
12908
|
+
const metadata = request ? extractOpenRouterCallModelMetadata(request) : { provider: "openrouter" };
|
|
12909
|
+
if (isObject(metadata) && "tools" in metadata) {
|
|
12910
|
+
delete metadata.tools;
|
|
12911
|
+
}
|
|
12912
|
+
return {
|
|
12913
|
+
input: request ? extractOpenRouterCallModelInput(request) : void 0,
|
|
12914
|
+
metadata: {
|
|
12915
|
+
...metadata,
|
|
12916
|
+
step: event.step,
|
|
12917
|
+
step_type: event.stepType
|
|
12918
|
+
}
|
|
12919
|
+
};
|
|
12920
|
+
},
|
|
12921
|
+
extractOutput: (result) => extractOpenRouterResponseOutput(result),
|
|
12922
|
+
extractMetadata: (result, event) => {
|
|
12923
|
+
if (!isObject(result)) {
|
|
12924
|
+
return {
|
|
12925
|
+
step: event?.step,
|
|
12926
|
+
step_type: event?.stepType
|
|
12927
|
+
};
|
|
12928
|
+
}
|
|
12929
|
+
return {
|
|
12930
|
+
...extractOpenRouterResponseMetadata(result) || {},
|
|
12931
|
+
...event?.step !== void 0 ? { step: event.step } : {},
|
|
12932
|
+
...event?.stepType ? { step_type: event.stepType } : {}
|
|
12933
|
+
};
|
|
12934
|
+
},
|
|
12935
|
+
extractMetrics: (result) => isObject(result) ? parseOpenRouterMetricsFromUsage(result.usage) : {}
|
|
12936
|
+
})
|
|
12937
|
+
);
|
|
12938
|
+
this.unsubscribers.push(
|
|
12939
|
+
traceStreamingChannel(openRouterAgentChannels.toolExecute, {
|
|
12940
|
+
name: "openrouter.tool",
|
|
12941
|
+
type: "tool" /* TOOL */,
|
|
12942
|
+
extractInput: (args, event) => ({
|
|
12943
|
+
input: args[0],
|
|
12944
|
+
metadata: {
|
|
12945
|
+
provider: "openrouter",
|
|
12946
|
+
tool_name: event.toolName,
|
|
12947
|
+
...event.toolCallId ? { tool_call_id: event.toolCallId } : {}
|
|
12948
|
+
}
|
|
12949
|
+
}),
|
|
12950
|
+
extractOutput: (result) => result,
|
|
12951
|
+
extractMetrics: () => ({}),
|
|
12952
|
+
aggregateChunks: (chunks) => ({
|
|
12953
|
+
output: chunks.length > 0 ? chunks[chunks.length - 1] : void 0,
|
|
12954
|
+
metrics: {}
|
|
12955
|
+
})
|
|
12956
|
+
})
|
|
12957
|
+
);
|
|
12958
|
+
const callModelChannel = openRouterAgentChannels.callModel.tracingChannel();
|
|
12959
|
+
const callModelHandlers = {
|
|
12960
|
+
start: (event) => {
|
|
12961
|
+
const request = getOpenRouterCallModelRequestArg(event.arguments);
|
|
12962
|
+
if (!request) {
|
|
12963
|
+
return;
|
|
12964
|
+
}
|
|
12965
|
+
patchOpenRouterCallModelRequestTools(request);
|
|
12966
|
+
}
|
|
12967
|
+
};
|
|
12968
|
+
callModelChannel.subscribe(callModelHandlers);
|
|
12969
|
+
this.unsubscribers.push(() => {
|
|
12970
|
+
callModelChannel.unsubscribe(callModelHandlers);
|
|
12971
|
+
});
|
|
12972
|
+
}
|
|
12973
|
+
};
|
|
12974
|
+
function normalizeArgs(args) {
|
|
12975
|
+
if (Array.isArray(args)) {
|
|
12976
|
+
return args;
|
|
12977
|
+
}
|
|
12978
|
+
if (isArrayLike(args)) {
|
|
12979
|
+
return Array.from(args);
|
|
12980
|
+
}
|
|
12981
|
+
return [args];
|
|
12982
|
+
}
|
|
12983
|
+
function isArrayLike(value) {
|
|
12984
|
+
return isObject(value) && "length" in value && typeof value.length === "number" && Number.isInteger(value.length) && value.length >= 0;
|
|
12985
|
+
}
|
|
12986
|
+
function getOpenRouterCallModelRequestArg(args) {
|
|
12987
|
+
const normalizedArgs = normalizeArgs(args);
|
|
12988
|
+
const keyedRequestArg = normalizedArgs.find(
|
|
12989
|
+
(arg) => isObject(arg) && ("input" in arg || "model" in arg || "tools" in arg)
|
|
12990
|
+
);
|
|
12991
|
+
if (isObject(keyedRequestArg)) {
|
|
12992
|
+
return keyedRequestArg;
|
|
12993
|
+
}
|
|
12994
|
+
const firstObjectArg = normalizedArgs.find((arg) => isObject(arg));
|
|
12995
|
+
return isObject(firstObjectArg) ? firstObjectArg : void 0;
|
|
12996
|
+
}
|
|
12997
|
+
var TOKEN_NAME_MAP2 = {
|
|
12998
|
+
promptTokens: "prompt_tokens",
|
|
12999
|
+
inputTokens: "prompt_tokens",
|
|
13000
|
+
completionTokens: "completion_tokens",
|
|
13001
|
+
outputTokens: "completion_tokens",
|
|
13002
|
+
totalTokens: "tokens",
|
|
13003
|
+
prompt_tokens: "prompt_tokens",
|
|
13004
|
+
input_tokens: "prompt_tokens",
|
|
13005
|
+
completion_tokens: "completion_tokens",
|
|
13006
|
+
output_tokens: "completion_tokens",
|
|
13007
|
+
total_tokens: "tokens"
|
|
13008
|
+
};
|
|
13009
|
+
var TOKEN_DETAIL_PREFIX_MAP = {
|
|
13010
|
+
promptTokensDetails: "prompt",
|
|
13011
|
+
inputTokensDetails: "prompt",
|
|
13012
|
+
completionTokensDetails: "completion",
|
|
13013
|
+
outputTokensDetails: "completion",
|
|
13014
|
+
costDetails: "cost",
|
|
13015
|
+
prompt_tokens_details: "prompt",
|
|
11693
13016
|
input_tokens_details: "prompt",
|
|
11694
13017
|
completion_tokens_details: "completion",
|
|
11695
13018
|
output_tokens_details: "completion",
|
|
@@ -11736,8 +13059,6 @@ function extractOpenRouterUsageMetadata(usage) {
|
|
|
11736
13059
|
}
|
|
11737
13060
|
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
11738
13061
|
}
|
|
11739
|
-
|
|
11740
|
-
// src/openrouter-logging.ts
|
|
11741
13062
|
var OMITTED_OPENROUTER_KEYS = /* @__PURE__ */ new Set([
|
|
11742
13063
|
"execute",
|
|
11743
13064
|
"render",
|
|
@@ -11757,10 +13078,10 @@ function parseOpenRouterModelString(model) {
|
|
|
11757
13078
|
}
|
|
11758
13079
|
return { model };
|
|
11759
13080
|
}
|
|
11760
|
-
function
|
|
13081
|
+
function isZodSchema3(value) {
|
|
11761
13082
|
return value != null && typeof value === "object" && "_def" in value && typeof value._def === "object";
|
|
11762
13083
|
}
|
|
11763
|
-
function
|
|
13084
|
+
function serializeZodSchema3(schema) {
|
|
11764
13085
|
try {
|
|
11765
13086
|
return zodToJsonSchema(schema);
|
|
11766
13087
|
} catch {
|
|
@@ -11794,8 +13115,8 @@ function serializeOpenRouterToolsForLogging(tools) {
|
|
|
11794
13115
|
return tools.map((tool) => serializeOpenRouterTool(tool));
|
|
11795
13116
|
}
|
|
11796
13117
|
function sanitizeOpenRouterLoggedValue(value) {
|
|
11797
|
-
if (
|
|
11798
|
-
return
|
|
13118
|
+
if (isZodSchema3(value)) {
|
|
13119
|
+
return serializeZodSchema3(value);
|
|
11799
13120
|
}
|
|
11800
13121
|
if (typeof value === "function") {
|
|
11801
13122
|
return "[Function]";
|
|
@@ -11819,7 +13140,7 @@ function sanitizeOpenRouterLoggedValue(value) {
|
|
|
11819
13140
|
}
|
|
11820
13141
|
return sanitized;
|
|
11821
13142
|
}
|
|
11822
|
-
function buildOpenRouterMetadata(metadata, httpReferer, xTitle) {
|
|
13143
|
+
function buildOpenRouterMetadata(metadata, httpReferer, appTitle, appCategories, xTitle) {
|
|
11823
13144
|
const sanitized = sanitizeOpenRouterLoggedValue(metadata);
|
|
11824
13145
|
const metadataRecord = isObject(sanitized) ? sanitized : {};
|
|
11825
13146
|
const { model, provider: providerRouting, ...rest } = metadataRecord;
|
|
@@ -11829,17 +13150,12 @@ function buildOpenRouterMetadata(metadata, httpReferer, xTitle) {
|
|
|
11829
13150
|
...normalizedModel.model !== void 0 ? { model: normalizedModel.model } : {},
|
|
11830
13151
|
...providerRouting !== void 0 ? { providerRouting } : {},
|
|
11831
13152
|
...httpReferer !== void 0 ? { httpReferer } : {},
|
|
13153
|
+
...appTitle !== void 0 ? { appTitle } : {},
|
|
13154
|
+
...appCategories !== void 0 ? { appCategories } : {},
|
|
11832
13155
|
...xTitle !== void 0 ? { xTitle } : {},
|
|
11833
13156
|
provider: normalizedModel.provider || "openrouter"
|
|
11834
13157
|
};
|
|
11835
13158
|
}
|
|
11836
|
-
function buildOpenRouterEmbeddingMetadata(metadata, httpReferer, xTitle) {
|
|
11837
|
-
const normalized = buildOpenRouterMetadata(metadata, httpReferer, xTitle);
|
|
11838
|
-
return typeof normalized.model === "string" ? {
|
|
11839
|
-
...normalized,
|
|
11840
|
-
embedding_model: normalized.model
|
|
11841
|
-
} : normalized;
|
|
11842
|
-
}
|
|
11843
13159
|
function extractOpenRouterCallModelInput(request) {
|
|
11844
13160
|
return isObject(request) && "input" in request ? sanitizeOpenRouterLoggedValue(request.input) : void 0;
|
|
11845
13161
|
}
|
|
@@ -11848,7 +13164,13 @@ function extractOpenRouterCallModelMetadata(request) {
|
|
|
11848
13164
|
return { provider: "openrouter" };
|
|
11849
13165
|
}
|
|
11850
13166
|
const { input: _input, ...metadata } = request;
|
|
11851
|
-
return buildOpenRouterMetadata(
|
|
13167
|
+
return buildOpenRouterMetadata(
|
|
13168
|
+
metadata,
|
|
13169
|
+
void 0,
|
|
13170
|
+
void 0,
|
|
13171
|
+
void 0,
|
|
13172
|
+
void 0
|
|
13173
|
+
);
|
|
11852
13174
|
}
|
|
11853
13175
|
function extractOpenRouterResponseMetadata(result) {
|
|
11854
13176
|
if (!isObject(result)) {
|
|
@@ -11878,9 +13200,101 @@ function extractOpenRouterResponseOutput(response, fallbackOutput) {
|
|
|
11878
13200
|
}
|
|
11879
13201
|
return void 0;
|
|
11880
13202
|
}
|
|
11881
|
-
|
|
11882
|
-
// src/openrouter-tool-wrapping.ts
|
|
11883
13203
|
var OPENROUTER_WRAPPED_TOOL = Symbol("braintrust.openrouter.wrappedTool");
|
|
13204
|
+
function patchOpenRouterCallModelRequestTools(request) {
|
|
13205
|
+
if (!Array.isArray(request.tools) || request.tools.length === 0) {
|
|
13206
|
+
return void 0;
|
|
13207
|
+
}
|
|
13208
|
+
const originalTools = request.tools;
|
|
13209
|
+
const wrappedTools = originalTools.map((tool) => wrapOpenRouterTool(tool));
|
|
13210
|
+
const didPatch = wrappedTools.some(
|
|
13211
|
+
(tool, index) => tool !== originalTools[index]
|
|
13212
|
+
);
|
|
13213
|
+
if (!didPatch) {
|
|
13214
|
+
return void 0;
|
|
13215
|
+
}
|
|
13216
|
+
request.tools = wrappedTools;
|
|
13217
|
+
return () => {
|
|
13218
|
+
request.tools = originalTools;
|
|
13219
|
+
};
|
|
13220
|
+
}
|
|
13221
|
+
function wrapOpenRouterTool(tool) {
|
|
13222
|
+
if (isWrappedTool(tool) || !tool.function || typeof tool.function !== "object" || typeof tool.function.execute !== "function") {
|
|
13223
|
+
return tool;
|
|
13224
|
+
}
|
|
13225
|
+
const toolName = tool.function.name || "tool";
|
|
13226
|
+
const originalExecute = tool.function.execute;
|
|
13227
|
+
const wrappedTool = {
|
|
13228
|
+
...tool,
|
|
13229
|
+
function: {
|
|
13230
|
+
...tool.function,
|
|
13231
|
+
execute(...args) {
|
|
13232
|
+
return traceToolExecution({
|
|
13233
|
+
args,
|
|
13234
|
+
execute: () => Reflect.apply(originalExecute, this, args),
|
|
13235
|
+
toolCallId: getToolCallId(args[1]),
|
|
13236
|
+
toolName
|
|
13237
|
+
});
|
|
13238
|
+
}
|
|
13239
|
+
}
|
|
13240
|
+
};
|
|
13241
|
+
Object.defineProperty(wrappedTool, OPENROUTER_WRAPPED_TOOL, {
|
|
13242
|
+
value: true,
|
|
13243
|
+
enumerable: false,
|
|
13244
|
+
configurable: false
|
|
13245
|
+
});
|
|
13246
|
+
return wrappedTool;
|
|
13247
|
+
}
|
|
13248
|
+
function isWrappedTool(tool) {
|
|
13249
|
+
return Boolean(tool[OPENROUTER_WRAPPED_TOOL]);
|
|
13250
|
+
}
|
|
13251
|
+
function traceToolExecution(args) {
|
|
13252
|
+
const tracingChannel = openRouterAgentChannels.toolExecute.tracingChannel();
|
|
13253
|
+
const input = args.args.length > 0 ? args.args[0] : void 0;
|
|
13254
|
+
const event = {
|
|
13255
|
+
arguments: [input],
|
|
13256
|
+
span_info: {
|
|
13257
|
+
name: args.toolName
|
|
13258
|
+
},
|
|
13259
|
+
toolCallId: args.toolCallId,
|
|
13260
|
+
toolName: args.toolName
|
|
13261
|
+
};
|
|
13262
|
+
tracingChannel.start.publish(event);
|
|
13263
|
+
try {
|
|
13264
|
+
const result = args.execute();
|
|
13265
|
+
return publishToolResult(tracingChannel, event, result);
|
|
13266
|
+
} catch (error) {
|
|
13267
|
+
event.error = normalizeError(error);
|
|
13268
|
+
tracingChannel.error.publish(event);
|
|
13269
|
+
throw error;
|
|
13270
|
+
}
|
|
13271
|
+
}
|
|
13272
|
+
function publishToolResult(tracingChannel, event, result) {
|
|
13273
|
+
if (isPromiseLike3(result)) {
|
|
13274
|
+
return result.then(
|
|
13275
|
+
(resolved) => {
|
|
13276
|
+
event.result = resolved;
|
|
13277
|
+
tracingChannel.asyncEnd.publish(event);
|
|
13278
|
+
return resolved;
|
|
13279
|
+
},
|
|
13280
|
+
(error) => {
|
|
13281
|
+
event.error = normalizeError(error);
|
|
13282
|
+
tracingChannel.error.publish(event);
|
|
13283
|
+
throw error;
|
|
13284
|
+
}
|
|
13285
|
+
);
|
|
13286
|
+
}
|
|
13287
|
+
event.result = result;
|
|
13288
|
+
tracingChannel.asyncEnd.publish(event);
|
|
13289
|
+
return result;
|
|
13290
|
+
}
|
|
13291
|
+
function getToolCallId(context) {
|
|
13292
|
+
const toolContext = context;
|
|
13293
|
+
return typeof toolContext?.toolCall?.id === "string" ? toolContext.toolCall.id : void 0;
|
|
13294
|
+
}
|
|
13295
|
+
function isPromiseLike3(value) {
|
|
13296
|
+
return !!value && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function";
|
|
13297
|
+
}
|
|
11884
13298
|
var OPENROUTER_WRAPPED_CALL_MODEL_RESULT = Symbol(
|
|
11885
13299
|
"braintrust.openrouter.wrappedCallModelResult"
|
|
11886
13300
|
);
|
|
@@ -11900,24 +13314,8 @@ var OPENROUTER_CALL_MODEL_CONTEXT_METHODS = [
|
|
|
11900
13314
|
"getToolCalls",
|
|
11901
13315
|
"requiresApproval"
|
|
11902
13316
|
];
|
|
11903
|
-
function
|
|
11904
|
-
|
|
11905
|
-
return void 0;
|
|
11906
|
-
}
|
|
11907
|
-
const originalTools = request.tools;
|
|
11908
|
-
const wrappedTools = originalTools.map((tool) => wrapOpenRouterTool(tool));
|
|
11909
|
-
const didPatch = wrappedTools.some(
|
|
11910
|
-
(tool, index) => tool !== originalTools[index]
|
|
11911
|
-
);
|
|
11912
|
-
if (!didPatch) {
|
|
11913
|
-
return void 0;
|
|
11914
|
-
}
|
|
11915
|
-
request.tools = wrappedTools;
|
|
11916
|
-
return () => {
|
|
11917
|
-
request.tools = originalTools;
|
|
11918
|
-
};
|
|
11919
|
-
}
|
|
11920
|
-
function patchOpenRouterCallModelResult(span, result, request) {
|
|
13317
|
+
function patchOpenRouterCallModelResult(args) {
|
|
13318
|
+
const { request, result, span } = args;
|
|
11921
13319
|
if (!isObject(result) || isWrappedCallModelResult(result)) {
|
|
11922
13320
|
return false;
|
|
11923
13321
|
}
|
|
@@ -11990,10 +13388,10 @@ function patchOpenRouterCallModelResult(span, result, request) {
|
|
|
11990
13388
|
}
|
|
11991
13389
|
};
|
|
11992
13390
|
if (originalGetResponse) {
|
|
11993
|
-
resultLike.getResponse = async (...
|
|
13391
|
+
resultLike.getResponse = async (...args2) => {
|
|
11994
13392
|
return await withCurrent(span, async () => {
|
|
11995
13393
|
try {
|
|
11996
|
-
const response = await originalGetResponse(...
|
|
13394
|
+
const response = await originalGetResponse(...args2);
|
|
11997
13395
|
await endSpanWithResult(response);
|
|
11998
13396
|
return response;
|
|
11999
13397
|
} catch (error) {
|
|
@@ -12005,10 +13403,10 @@ function patchOpenRouterCallModelResult(span, result, request) {
|
|
|
12005
13403
|
}
|
|
12006
13404
|
if (typeof resultLike.getText === "function") {
|
|
12007
13405
|
const originalGetText = resultLike.getText.bind(resultLike);
|
|
12008
|
-
resultLike.getText = async (...
|
|
13406
|
+
resultLike.getText = async (...args2) => {
|
|
12009
13407
|
return await withCurrent(span, async () => {
|
|
12010
13408
|
try {
|
|
12011
|
-
const text = await originalGetText(...
|
|
13409
|
+
const text = await originalGetText(...args2);
|
|
12012
13410
|
await finalizeFromResponse(text);
|
|
12013
13411
|
return text;
|
|
12014
13412
|
} catch (error) {
|
|
@@ -12023,9 +13421,9 @@ function patchOpenRouterCallModelResult(span, result, request) {
|
|
|
12023
13421
|
continue;
|
|
12024
13422
|
}
|
|
12025
13423
|
const originalMethod = resultLike[methodName];
|
|
12026
|
-
resultLike[methodName] = async (...
|
|
13424
|
+
resultLike[methodName] = async (...args2) => {
|
|
12027
13425
|
return await withCurrent(span, async () => {
|
|
12028
|
-
return await originalMethod.apply(resultLike,
|
|
13426
|
+
return await originalMethod.apply(resultLike, args2);
|
|
12029
13427
|
});
|
|
12030
13428
|
};
|
|
12031
13429
|
}
|
|
@@ -12034,12 +13432,12 @@ function patchOpenRouterCallModelResult(span, result, request) {
|
|
|
12034
13432
|
continue;
|
|
12035
13433
|
}
|
|
12036
13434
|
const originalMethod = resultLike[methodName];
|
|
12037
|
-
resultLike[methodName] = (...
|
|
13435
|
+
resultLike[methodName] = (...args2) => {
|
|
12038
13436
|
const stream = withCurrent(
|
|
12039
13437
|
span,
|
|
12040
|
-
() => originalMethod.apply(resultLike,
|
|
13438
|
+
() => originalMethod.apply(resultLike, args2)
|
|
12041
13439
|
);
|
|
12042
|
-
if (!
|
|
13440
|
+
if (!isAsyncIterable3(stream)) {
|
|
12043
13441
|
return stream;
|
|
12044
13442
|
}
|
|
12045
13443
|
return wrapAsyncIterableWithSpan({
|
|
@@ -12052,157 +13450,70 @@ function patchOpenRouterCallModelResult(span, result, request) {
|
|
|
12052
13450
|
}
|
|
12053
13451
|
if (originalGetInitialResponse) {
|
|
12054
13452
|
let initialTurnTraced = false;
|
|
12055
|
-
resultLike.getInitialResponse = async (...
|
|
13453
|
+
resultLike.getInitialResponse = async (...args2) => {
|
|
12056
13454
|
if (initialTurnTraced) {
|
|
12057
13455
|
return await withCurrent(span, async () => {
|
|
12058
|
-
return await originalGetInitialResponse(...
|
|
13456
|
+
return await originalGetInitialResponse(...args2);
|
|
12059
13457
|
});
|
|
12060
13458
|
}
|
|
12061
13459
|
initialTurnTraced = true;
|
|
12062
|
-
const
|
|
12063
|
-
const
|
|
12064
|
-
|
|
12065
|
-
|
|
12066
|
-
|
|
12067
|
-
});
|
|
12068
|
-
return await withCurrent(childSpan, async () => {
|
|
12069
|
-
try {
|
|
12070
|
-
const response = await originalGetInitialResponse(...args);
|
|
13460
|
+
const step = tracedTurnCount + 1;
|
|
13461
|
+
const stepType = tracedTurnCount === 0 ? "initial" : "continue";
|
|
13462
|
+
const response = await traceOpenRouterCallModelTurn({
|
|
13463
|
+
fn: async () => {
|
|
13464
|
+
const nextResponse = await originalGetInitialResponse(...args2);
|
|
12071
13465
|
tracedTurnCount++;
|
|
12072
|
-
|
|
12073
|
-
|
|
12074
|
-
|
|
12075
|
-
|
|
12076
|
-
|
|
12077
|
-
|
|
12078
|
-
return response;
|
|
12079
|
-
} catch (error) {
|
|
12080
|
-
childSpan.log({
|
|
12081
|
-
error: normalizeError(error).message
|
|
12082
|
-
});
|
|
12083
|
-
childSpan.end();
|
|
12084
|
-
throw error;
|
|
12085
|
-
}
|
|
13466
|
+
return nextResponse;
|
|
13467
|
+
},
|
|
13468
|
+
parentSpan: span,
|
|
13469
|
+
request: getOpenRouterResolvedRequest(resultLike, request),
|
|
13470
|
+
step,
|
|
13471
|
+
stepType
|
|
12086
13472
|
});
|
|
13473
|
+
return response;
|
|
12087
13474
|
};
|
|
12088
13475
|
}
|
|
12089
13476
|
if (originalMakeFollowupRequest) {
|
|
12090
|
-
resultLike.makeFollowupRequest = async (...
|
|
12091
|
-
const currentResponse =
|
|
12092
|
-
const toolResults = Array.isArray(
|
|
12093
|
-
const
|
|
12094
|
-
const
|
|
12095
|
-
|
|
12096
|
-
|
|
12097
|
-
toolResults
|
|
12098
|
-
);
|
|
12099
|
-
const childSpan = startOpenRouterCallModelTurnSpan({
|
|
12100
|
-
request: followupRequest,
|
|
12101
|
-
step: tracedTurnCount + 1,
|
|
12102
|
-
stepType: "continue"
|
|
12103
|
-
});
|
|
12104
|
-
return await withCurrent(childSpan, async () => {
|
|
12105
|
-
try {
|
|
12106
|
-
const response = await originalMakeFollowupRequest(...args);
|
|
13477
|
+
resultLike.makeFollowupRequest = async (...args2) => {
|
|
13478
|
+
const currentResponse = args2[0];
|
|
13479
|
+
const toolResults = Array.isArray(args2[1]) ? args2[1] : [];
|
|
13480
|
+
const step = tracedTurnCount + 1;
|
|
13481
|
+
const response = await traceOpenRouterCallModelTurn({
|
|
13482
|
+
fn: async () => {
|
|
13483
|
+
const nextResponse = await originalMakeFollowupRequest(...args2);
|
|
12107
13484
|
tracedTurnCount++;
|
|
12108
|
-
|
|
12109
|
-
|
|
12110
|
-
|
|
12111
|
-
|
|
12112
|
-
|
|
12113
|
-
|
|
12114
|
-
|
|
12115
|
-
|
|
12116
|
-
|
|
12117
|
-
|
|
12118
|
-
});
|
|
12119
|
-
childSpan.end();
|
|
12120
|
-
throw error;
|
|
12121
|
-
}
|
|
13485
|
+
return nextResponse;
|
|
13486
|
+
},
|
|
13487
|
+
parentSpan: span,
|
|
13488
|
+
request: buildOpenRouterFollowupRequest(
|
|
13489
|
+
getOpenRouterResolvedRequest(resultLike, request),
|
|
13490
|
+
currentResponse,
|
|
13491
|
+
toolResults
|
|
13492
|
+
),
|
|
13493
|
+
step,
|
|
13494
|
+
stepType: "continue"
|
|
12122
13495
|
});
|
|
13496
|
+
return response;
|
|
12123
13497
|
};
|
|
12124
13498
|
}
|
|
12125
13499
|
return true;
|
|
12126
13500
|
}
|
|
12127
|
-
function
|
|
12128
|
-
|
|
12129
|
-
|
|
12130
|
-
|
|
12131
|
-
|
|
12132
|
-
const originalExecute = tool.function.execute;
|
|
12133
|
-
const wrappedTool = {
|
|
12134
|
-
...tool,
|
|
12135
|
-
function: {
|
|
12136
|
-
...tool.function,
|
|
12137
|
-
execute(...args) {
|
|
12138
|
-
return traceToolExecution({
|
|
12139
|
-
args,
|
|
12140
|
-
execute: () => Reflect.apply(originalExecute, this, args),
|
|
12141
|
-
toolCallId: getToolCallId(args[1]),
|
|
12142
|
-
toolName
|
|
12143
|
-
});
|
|
12144
|
-
}
|
|
12145
|
-
}
|
|
13501
|
+
async function traceOpenRouterCallModelTurn(args) {
|
|
13502
|
+
const context = {
|
|
13503
|
+
arguments: [args.request],
|
|
13504
|
+
step: args.step,
|
|
13505
|
+
stepType: args.stepType
|
|
12146
13506
|
};
|
|
12147
|
-
|
|
12148
|
-
|
|
12149
|
-
|
|
12150
|
-
|
|
12151
|
-
});
|
|
12152
|
-
return wrappedTool;
|
|
12153
|
-
}
|
|
12154
|
-
function isWrappedTool(tool) {
|
|
12155
|
-
return Boolean(tool[OPENROUTER_WRAPPED_TOOL]);
|
|
13507
|
+
return await withCurrent(
|
|
13508
|
+
args.parentSpan,
|
|
13509
|
+
() => openRouterAgentChannels.callModelTurn.tracePromise(args.fn, context)
|
|
13510
|
+
);
|
|
12156
13511
|
}
|
|
12157
13512
|
function isWrappedCallModelResult(value) {
|
|
12158
13513
|
return Boolean(
|
|
12159
13514
|
isObject(value) && value[OPENROUTER_WRAPPED_CALL_MODEL_RESULT]
|
|
12160
13515
|
);
|
|
12161
13516
|
}
|
|
12162
|
-
function traceToolExecution(args) {
|
|
12163
|
-
const tracingChannel = openRouterChannels.toolExecute.tracingChannel();
|
|
12164
|
-
const input = args.args.length > 0 ? args.args[0] : void 0;
|
|
12165
|
-
const event = {
|
|
12166
|
-
arguments: [input],
|
|
12167
|
-
span_info: {
|
|
12168
|
-
name: args.toolName
|
|
12169
|
-
},
|
|
12170
|
-
toolCallId: args.toolCallId,
|
|
12171
|
-
toolName: args.toolName
|
|
12172
|
-
};
|
|
12173
|
-
tracingChannel.start.publish(event);
|
|
12174
|
-
try {
|
|
12175
|
-
const result = args.execute();
|
|
12176
|
-
return publishToolResult(tracingChannel, event, result);
|
|
12177
|
-
} catch (error) {
|
|
12178
|
-
event.error = normalizeError(error);
|
|
12179
|
-
tracingChannel.error.publish(event);
|
|
12180
|
-
throw error;
|
|
12181
|
-
}
|
|
12182
|
-
}
|
|
12183
|
-
function publishToolResult(tracingChannel, event, result) {
|
|
12184
|
-
if (isPromiseLike(result)) {
|
|
12185
|
-
return result.then(
|
|
12186
|
-
(resolved) => {
|
|
12187
|
-
event.result = resolved;
|
|
12188
|
-
tracingChannel.asyncEnd.publish(event);
|
|
12189
|
-
return resolved;
|
|
12190
|
-
},
|
|
12191
|
-
(error) => {
|
|
12192
|
-
event.error = normalizeError(error);
|
|
12193
|
-
tracingChannel.error.publish(event);
|
|
12194
|
-
throw error;
|
|
12195
|
-
}
|
|
12196
|
-
);
|
|
12197
|
-
}
|
|
12198
|
-
event.result = result;
|
|
12199
|
-
tracingChannel.asyncEnd.publish(event);
|
|
12200
|
-
return result;
|
|
12201
|
-
}
|
|
12202
|
-
function getToolCallId(context) {
|
|
12203
|
-
const toolContext = context;
|
|
12204
|
-
return typeof toolContext?.toolCall?.id === "string" ? toolContext.toolCall.id : void 0;
|
|
12205
|
-
}
|
|
12206
13517
|
function extractOpenRouterCallModelResultMetadata(response, turnCount) {
|
|
12207
13518
|
const combined = {
|
|
12208
13519
|
...extractOpenRouterResponseMetadata(response) || {},
|
|
@@ -12247,45 +13558,6 @@ function buildNextOpenRouterCallModelInput(currentInput, response, toolResults)
|
|
|
12247
13558
|
(entry) => sanitizeOpenRouterLoggedValue(entry)
|
|
12248
13559
|
);
|
|
12249
13560
|
}
|
|
12250
|
-
function startOpenRouterCallModelTurnSpan(args) {
|
|
12251
|
-
const requestRecord = isObject(args.request) ? args.request : void 0;
|
|
12252
|
-
const metadata = requestRecord ? extractOpenRouterCallModelMetadata(requestRecord) : { provider: "openrouter" };
|
|
12253
|
-
if (isObject(metadata) && "tools" in metadata) {
|
|
12254
|
-
delete metadata.tools;
|
|
12255
|
-
}
|
|
12256
|
-
return startSpan({
|
|
12257
|
-
name: "openrouter.beta.responses.send",
|
|
12258
|
-
spanAttributes: {
|
|
12259
|
-
type: "llm" /* LLM */
|
|
12260
|
-
},
|
|
12261
|
-
event: {
|
|
12262
|
-
input: requestRecord ? extractOpenRouterCallModelInput(requestRecord) : void 0,
|
|
12263
|
-
metadata: {
|
|
12264
|
-
...metadata,
|
|
12265
|
-
step: args.step,
|
|
12266
|
-
step_type: args.stepType
|
|
12267
|
-
}
|
|
12268
|
-
}
|
|
12269
|
-
});
|
|
12270
|
-
}
|
|
12271
|
-
function finishOpenRouterCallModelTurnSpan(args) {
|
|
12272
|
-
if (!isObject(args.response)) {
|
|
12273
|
-
args.span.end();
|
|
12274
|
-
return;
|
|
12275
|
-
}
|
|
12276
|
-
args.span.log({
|
|
12277
|
-
output: extractOpenRouterResponseOutput(args.response),
|
|
12278
|
-
...extractOpenRouterResponseMetadata(args.response) ? {
|
|
12279
|
-
metadata: {
|
|
12280
|
-
...extractOpenRouterResponseMetadata(args.response),
|
|
12281
|
-
...args.step !== void 0 ? { step: args.step } : {},
|
|
12282
|
-
...args.stepType ? { step_type: args.stepType } : {}
|
|
12283
|
-
}
|
|
12284
|
-
} : {},
|
|
12285
|
-
metrics: parseOpenRouterMetricsFromUsage(args.response.usage)
|
|
12286
|
-
});
|
|
12287
|
-
args.span.end();
|
|
12288
|
-
}
|
|
12289
13561
|
function getOpenRouterResolvedRequest(result, request) {
|
|
12290
13562
|
if (isObject(result.resolvedRequest)) {
|
|
12291
13563
|
return result.resolvedRequest;
|
|
@@ -12360,16 +13632,41 @@ function wrapAsyncIterableWithSpan(args) {
|
|
|
12360
13632
|
}
|
|
12361
13633
|
};
|
|
12362
13634
|
}
|
|
12363
|
-
function
|
|
13635
|
+
function isAsyncIterable3(value) {
|
|
12364
13636
|
return !!value && (typeof value === "object" || typeof value === "function") && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
|
|
12365
13637
|
}
|
|
12366
|
-
function isPromiseLike(value) {
|
|
12367
|
-
return !!value && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function";
|
|
12368
|
-
}
|
|
12369
13638
|
function normalizeError(error) {
|
|
12370
13639
|
return error instanceof Error ? error : new Error(String(error));
|
|
12371
13640
|
}
|
|
12372
13641
|
|
|
13642
|
+
// src/instrumentation/plugins/openrouter-channels.ts
|
|
13643
|
+
var openRouterChannels = defineChannels("@openrouter/sdk", {
|
|
13644
|
+
chatSend: channel({
|
|
13645
|
+
channelName: "chat.send",
|
|
13646
|
+
kind: "async"
|
|
13647
|
+
}),
|
|
13648
|
+
embeddingsGenerate: channel({
|
|
13649
|
+
channelName: "embeddings.generate",
|
|
13650
|
+
kind: "async"
|
|
13651
|
+
}),
|
|
13652
|
+
betaResponsesSend: channel({
|
|
13653
|
+
channelName: "beta.responses.send",
|
|
13654
|
+
kind: "async"
|
|
13655
|
+
}),
|
|
13656
|
+
callModel: channel({
|
|
13657
|
+
channelName: "callModel",
|
|
13658
|
+
kind: "sync-stream"
|
|
13659
|
+
}),
|
|
13660
|
+
callModelTurn: channel({
|
|
13661
|
+
channelName: "callModel.turn",
|
|
13662
|
+
kind: "async"
|
|
13663
|
+
}),
|
|
13664
|
+
toolExecute: channel({
|
|
13665
|
+
channelName: "tool.execute",
|
|
13666
|
+
kind: "async"
|
|
13667
|
+
})
|
|
13668
|
+
});
|
|
13669
|
+
|
|
12373
13670
|
// src/instrumentation/plugins/openrouter-plugin.ts
|
|
12374
13671
|
var OpenRouterPlugin = class extends BasePlugin {
|
|
12375
13672
|
onEnable() {
|
|
@@ -12391,14 +13688,14 @@ var OpenRouterPlugin = class extends BasePlugin {
|
|
|
12391
13688
|
const { messages, ...metadata } = chatGenerationParams;
|
|
12392
13689
|
return {
|
|
12393
13690
|
input: messages,
|
|
12394
|
-
metadata:
|
|
13691
|
+
metadata: buildOpenRouterMetadata2(metadata, httpReferer, xTitle)
|
|
12395
13692
|
};
|
|
12396
13693
|
},
|
|
12397
13694
|
extractOutput: (result) => {
|
|
12398
13695
|
return isObject(result) ? result.choices : void 0;
|
|
12399
13696
|
},
|
|
12400
13697
|
extractMetrics: (result, startTime) => {
|
|
12401
|
-
const metrics =
|
|
13698
|
+
const metrics = parseOpenRouterMetricsFromUsage2(result?.usage);
|
|
12402
13699
|
if (startTime) {
|
|
12403
13700
|
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
12404
13701
|
}
|
|
@@ -12437,10 +13734,10 @@ var OpenRouterPlugin = class extends BasePlugin {
|
|
|
12437
13734
|
if (!isObject(result)) {
|
|
12438
13735
|
return void 0;
|
|
12439
13736
|
}
|
|
12440
|
-
return
|
|
13737
|
+
return extractOpenRouterResponseMetadata2(result);
|
|
12441
13738
|
},
|
|
12442
13739
|
extractMetrics: (result) => {
|
|
12443
|
-
return isObject(result) ?
|
|
13740
|
+
return isObject(result) ? parseOpenRouterMetricsFromUsage2(result.usage) : {};
|
|
12444
13741
|
}
|
|
12445
13742
|
})
|
|
12446
13743
|
);
|
|
@@ -12456,13 +13753,13 @@ var OpenRouterPlugin = class extends BasePlugin {
|
|
|
12456
13753
|
const { input, ...metadata } = openResponsesRequest;
|
|
12457
13754
|
return {
|
|
12458
13755
|
input,
|
|
12459
|
-
metadata:
|
|
13756
|
+
metadata: buildOpenRouterMetadata2(metadata, httpReferer, xTitle)
|
|
12460
13757
|
};
|
|
12461
13758
|
},
|
|
12462
|
-
extractOutput: (result) =>
|
|
12463
|
-
extractMetadata: (result) =>
|
|
13759
|
+
extractOutput: (result) => extractOpenRouterResponseOutput2(result),
|
|
13760
|
+
extractMetadata: (result) => extractOpenRouterResponseMetadata2(result),
|
|
12464
13761
|
extractMetrics: (result, startTime) => {
|
|
12465
|
-
const metrics =
|
|
13762
|
+
const metrics = parseOpenRouterMetricsFromUsage2(result?.usage);
|
|
12466
13763
|
if (startTime) {
|
|
12467
13764
|
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
12468
13765
|
}
|
|
@@ -12476,21 +13773,57 @@ var OpenRouterPlugin = class extends BasePlugin {
|
|
|
12476
13773
|
name: "openrouter.callModel",
|
|
12477
13774
|
type: "llm" /* LLM */,
|
|
12478
13775
|
extractInput: (args) => {
|
|
12479
|
-
const request =
|
|
13776
|
+
const request = getOpenRouterCallModelRequestArg2(args);
|
|
12480
13777
|
return {
|
|
12481
|
-
input: request ?
|
|
12482
|
-
metadata: request ?
|
|
13778
|
+
input: request ? extractOpenRouterCallModelInput2(request) : void 0,
|
|
13779
|
+
metadata: request ? extractOpenRouterCallModelMetadata2(request) : { provider: "openrouter" }
|
|
12483
13780
|
};
|
|
12484
13781
|
},
|
|
12485
13782
|
patchResult: ({ endEvent, result, span }) => {
|
|
12486
|
-
return
|
|
12487
|
-
|
|
13783
|
+
return patchOpenRouterCallModelResult2({
|
|
13784
|
+
request: getOpenRouterCallModelRequestArg2(endEvent.arguments),
|
|
12488
13785
|
result,
|
|
12489
|
-
|
|
12490
|
-
);
|
|
13786
|
+
span
|
|
13787
|
+
});
|
|
12491
13788
|
}
|
|
12492
13789
|
})
|
|
12493
13790
|
);
|
|
13791
|
+
this.unsubscribers.push(
|
|
13792
|
+
traceAsyncChannel(openRouterChannels.callModelTurn, {
|
|
13793
|
+
name: "openrouter.beta.responses.send",
|
|
13794
|
+
type: "llm" /* LLM */,
|
|
13795
|
+
extractInput: (args, event) => {
|
|
13796
|
+
const request = getOpenRouterCallModelRequestArg2(args);
|
|
13797
|
+
const metadata = request ? extractOpenRouterCallModelMetadata2(request) : { provider: "openrouter" };
|
|
13798
|
+
if (isObject(metadata) && "tools" in metadata) {
|
|
13799
|
+
delete metadata.tools;
|
|
13800
|
+
}
|
|
13801
|
+
return {
|
|
13802
|
+
input: request ? extractOpenRouterCallModelInput2(request) : void 0,
|
|
13803
|
+
metadata: {
|
|
13804
|
+
...metadata,
|
|
13805
|
+
step: event.step,
|
|
13806
|
+
step_type: event.stepType
|
|
13807
|
+
}
|
|
13808
|
+
};
|
|
13809
|
+
},
|
|
13810
|
+
extractOutput: (result) => extractOpenRouterResponseOutput2(result),
|
|
13811
|
+
extractMetadata: (result, event) => {
|
|
13812
|
+
if (!isObject(result)) {
|
|
13813
|
+
return {
|
|
13814
|
+
step: event?.step,
|
|
13815
|
+
step_type: event?.stepType
|
|
13816
|
+
};
|
|
13817
|
+
}
|
|
13818
|
+
return {
|
|
13819
|
+
...extractOpenRouterResponseMetadata2(result) || {},
|
|
13820
|
+
...event?.step !== void 0 ? { step: event.step } : {},
|
|
13821
|
+
...event?.stepType ? { step_type: event.stepType } : {}
|
|
13822
|
+
};
|
|
13823
|
+
},
|
|
13824
|
+
extractMetrics: (result) => isObject(result) ? parseOpenRouterMetricsFromUsage2(result.usage) : {}
|
|
13825
|
+
})
|
|
13826
|
+
);
|
|
12494
13827
|
this.unsubscribers.push(
|
|
12495
13828
|
traceStreamingChannel(openRouterChannels.toolExecute, {
|
|
12496
13829
|
name: "openrouter.tool",
|
|
@@ -12514,11 +13847,11 @@ var OpenRouterPlugin = class extends BasePlugin {
|
|
|
12514
13847
|
const callModelChannel = openRouterChannels.callModel.tracingChannel();
|
|
12515
13848
|
const callModelHandlers = {
|
|
12516
13849
|
start: (event) => {
|
|
12517
|
-
const request =
|
|
13850
|
+
const request = getOpenRouterCallModelRequestArg2(event.arguments);
|
|
12518
13851
|
if (!request) {
|
|
12519
13852
|
return;
|
|
12520
13853
|
}
|
|
12521
|
-
|
|
13854
|
+
patchOpenRouterCallModelRequestTools2(request);
|
|
12522
13855
|
}
|
|
12523
13856
|
};
|
|
12524
13857
|
callModelChannel.subscribe(callModelHandlers);
|
|
@@ -12527,20 +13860,20 @@ var OpenRouterPlugin = class extends BasePlugin {
|
|
|
12527
13860
|
});
|
|
12528
13861
|
}
|
|
12529
13862
|
};
|
|
12530
|
-
function
|
|
13863
|
+
function normalizeArgs2(args) {
|
|
12531
13864
|
if (Array.isArray(args)) {
|
|
12532
13865
|
return args;
|
|
12533
13866
|
}
|
|
12534
|
-
if (
|
|
13867
|
+
if (isArrayLike2(args)) {
|
|
12535
13868
|
return Array.from(args);
|
|
12536
13869
|
}
|
|
12537
13870
|
return [args];
|
|
12538
13871
|
}
|
|
12539
|
-
function
|
|
13872
|
+
function isArrayLike2(value) {
|
|
12540
13873
|
return isObject(value) && "length" in value && typeof value.length === "number" && Number.isInteger(value.length) && value.length >= 0;
|
|
12541
13874
|
}
|
|
12542
13875
|
function getOpenRouterRequestArg(args) {
|
|
12543
|
-
const normalizedArgs =
|
|
13876
|
+
const normalizedArgs = normalizeArgs2(args);
|
|
12544
13877
|
const keyedCandidate = normalizedArgs.find(
|
|
12545
13878
|
(arg) => isObject(arg) && ("chatGenerationParams" in arg || "requestBody" in arg || "openResponsesRequest" in arg)
|
|
12546
13879
|
);
|
|
@@ -12550,116 +13883,1264 @@ function getOpenRouterRequestArg(args) {
|
|
|
12550
13883
|
const firstObjectArg = normalizedArgs.find((arg) => isObject(arg));
|
|
12551
13884
|
return isObject(firstObjectArg) ? firstObjectArg : void 0;
|
|
12552
13885
|
}
|
|
12553
|
-
function
|
|
12554
|
-
const firstObjectArg =
|
|
13886
|
+
function getOpenRouterCallModelRequestArg2(args) {
|
|
13887
|
+
const firstObjectArg = normalizeArgs2(args).find((arg) => isObject(arg));
|
|
12555
13888
|
return isObject(firstObjectArg) ? firstObjectArg : void 0;
|
|
12556
13889
|
}
|
|
12557
|
-
|
|
12558
|
-
|
|
12559
|
-
|
|
12560
|
-
|
|
12561
|
-
|
|
12562
|
-
|
|
12563
|
-
|
|
12564
|
-
|
|
12565
|
-
|
|
12566
|
-
|
|
12567
|
-
|
|
12568
|
-
|
|
12569
|
-
|
|
12570
|
-
|
|
12571
|
-
|
|
12572
|
-
|
|
12573
|
-
|
|
13890
|
+
var TOKEN_NAME_MAP3 = {
|
|
13891
|
+
promptTokens: "prompt_tokens",
|
|
13892
|
+
inputTokens: "prompt_tokens",
|
|
13893
|
+
completionTokens: "completion_tokens",
|
|
13894
|
+
outputTokens: "completion_tokens",
|
|
13895
|
+
totalTokens: "tokens",
|
|
13896
|
+
prompt_tokens: "prompt_tokens",
|
|
13897
|
+
input_tokens: "prompt_tokens",
|
|
13898
|
+
completion_tokens: "completion_tokens",
|
|
13899
|
+
output_tokens: "completion_tokens",
|
|
13900
|
+
total_tokens: "tokens"
|
|
13901
|
+
};
|
|
13902
|
+
var TOKEN_DETAIL_PREFIX_MAP2 = {
|
|
13903
|
+
promptTokensDetails: "prompt",
|
|
13904
|
+
inputTokensDetails: "prompt",
|
|
13905
|
+
completionTokensDetails: "completion",
|
|
13906
|
+
outputTokensDetails: "completion",
|
|
13907
|
+
costDetails: "cost",
|
|
13908
|
+
prompt_tokens_details: "prompt",
|
|
13909
|
+
input_tokens_details: "prompt",
|
|
13910
|
+
completion_tokens_details: "completion",
|
|
13911
|
+
output_tokens_details: "completion",
|
|
13912
|
+
cost_details: "cost"
|
|
13913
|
+
};
|
|
13914
|
+
function camelToSnake2(value) {
|
|
13915
|
+
return value.replace(/[A-Z]/g, (match) => `_${match.toLowerCase()}`);
|
|
13916
|
+
}
|
|
13917
|
+
function parseOpenRouterMetricsFromUsage2(usage) {
|
|
13918
|
+
if (!isObject(usage)) {
|
|
13919
|
+
return {};
|
|
13920
|
+
}
|
|
13921
|
+
const metrics = {};
|
|
13922
|
+
for (const [name, value] of Object.entries(usage)) {
|
|
13923
|
+
if (typeof value === "number") {
|
|
13924
|
+
metrics[TOKEN_NAME_MAP3[name] || camelToSnake2(name)] = value;
|
|
12574
13925
|
continue;
|
|
12575
13926
|
}
|
|
12576
|
-
if (!
|
|
12577
|
-
|
|
12578
|
-
}
|
|
12579
|
-
if (typeof delta.content === "string") {
|
|
12580
|
-
content += delta.content;
|
|
12581
|
-
}
|
|
12582
|
-
const choiceFinishReason = choice?.finishReason ?? choice?.finish_reason ?? void 0;
|
|
12583
|
-
const deltaFinishReason = delta.finishReason ?? delta.finish_reason ?? void 0;
|
|
12584
|
-
if (choiceFinishReason !== void 0) {
|
|
12585
|
-
finishReason = choiceFinishReason;
|
|
12586
|
-
} else if (deltaFinishReason !== void 0) {
|
|
12587
|
-
finishReason = deltaFinishReason;
|
|
13927
|
+
if (!isObject(value)) {
|
|
13928
|
+
continue;
|
|
12588
13929
|
}
|
|
12589
|
-
const
|
|
12590
|
-
if (!
|
|
13930
|
+
const prefix = TOKEN_DETAIL_PREFIX_MAP2[name];
|
|
13931
|
+
if (!prefix) {
|
|
12591
13932
|
continue;
|
|
12592
13933
|
}
|
|
12593
|
-
for (const
|
|
12594
|
-
if (
|
|
12595
|
-
continue;
|
|
12596
|
-
}
|
|
12597
|
-
const toolIndex = toolDelta.index ?? 0;
|
|
12598
|
-
const existingToolCall = toolCalls?.[toolIndex];
|
|
12599
|
-
if (!existingToolCall || toolDelta.id && existingToolCall.id !== void 0 && existingToolCall.id !== toolDelta.id) {
|
|
12600
|
-
const nextToolCalls = [...toolCalls || []];
|
|
12601
|
-
nextToolCalls[toolIndex] = {
|
|
12602
|
-
index: toolIndex,
|
|
12603
|
-
id: toolDelta.id,
|
|
12604
|
-
type: toolDelta.type,
|
|
12605
|
-
function: {
|
|
12606
|
-
name: toolDelta.function.name,
|
|
12607
|
-
arguments: toolDelta.function.arguments || ""
|
|
12608
|
-
}
|
|
12609
|
-
};
|
|
12610
|
-
toolCalls = nextToolCalls;
|
|
13934
|
+
for (const [nestedName, nestedValue] of Object.entries(value)) {
|
|
13935
|
+
if (typeof nestedValue !== "number") {
|
|
12611
13936
|
continue;
|
|
12612
13937
|
}
|
|
12613
|
-
|
|
12614
|
-
if (toolDelta.id && !current.id) {
|
|
12615
|
-
current.id = toolDelta.id;
|
|
12616
|
-
}
|
|
12617
|
-
if (toolDelta.type && !current.type) {
|
|
12618
|
-
current.type = toolDelta.type;
|
|
12619
|
-
}
|
|
12620
|
-
if (toolDelta.function.name && !current.function.name) {
|
|
12621
|
-
current.function.name = toolDelta.function.name;
|
|
12622
|
-
}
|
|
12623
|
-
current.function.arguments += toolDelta.function.arguments || "";
|
|
13938
|
+
metrics[`${prefix}_${camelToSnake2(nestedName)}`] = nestedValue;
|
|
12624
13939
|
}
|
|
12625
13940
|
}
|
|
12626
|
-
return
|
|
12627
|
-
output: [
|
|
12628
|
-
{
|
|
12629
|
-
index: 0,
|
|
12630
|
-
message: {
|
|
12631
|
-
role,
|
|
12632
|
-
content: content || void 0,
|
|
12633
|
-
...toolCalls ? { tool_calls: toolCalls } : {}
|
|
12634
|
-
},
|
|
12635
|
-
logprobs: null,
|
|
12636
|
-
finish_reason: finishReason
|
|
12637
|
-
}
|
|
12638
|
-
],
|
|
12639
|
-
metrics
|
|
12640
|
-
};
|
|
13941
|
+
return metrics;
|
|
12641
13942
|
}
|
|
12642
|
-
function
|
|
12643
|
-
|
|
12644
|
-
|
|
12645
|
-
|
|
12646
|
-
|
|
13943
|
+
function extractOpenRouterUsageMetadata2(usage) {
|
|
13944
|
+
if (!isObject(usage)) {
|
|
13945
|
+
return void 0;
|
|
13946
|
+
}
|
|
13947
|
+
const metadata = {};
|
|
13948
|
+
if (typeof usage.isByok === "boolean") {
|
|
13949
|
+
metadata.is_byok = usage.isByok;
|
|
13950
|
+
} else if (typeof usage.is_byok === "boolean") {
|
|
13951
|
+
metadata.is_byok = usage.is_byok;
|
|
13952
|
+
}
|
|
13953
|
+
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
13954
|
+
}
|
|
13955
|
+
var OMITTED_OPENROUTER_KEYS2 = /* @__PURE__ */ new Set([
|
|
13956
|
+
"execute",
|
|
13957
|
+
"render",
|
|
13958
|
+
"nextTurnParams",
|
|
13959
|
+
"requireApproval"
|
|
13960
|
+
]);
|
|
13961
|
+
function parseOpenRouterModelString2(model) {
|
|
13962
|
+
if (typeof model !== "string") {
|
|
13963
|
+
return { model };
|
|
13964
|
+
}
|
|
13965
|
+
const slashIndex = model.indexOf("/");
|
|
13966
|
+
if (slashIndex > 0 && slashIndex < model.length - 1) {
|
|
13967
|
+
return {
|
|
13968
|
+
provider: model.substring(0, slashIndex),
|
|
13969
|
+
model: model.substring(slashIndex + 1)
|
|
13970
|
+
};
|
|
13971
|
+
}
|
|
13972
|
+
return { model };
|
|
13973
|
+
}
|
|
13974
|
+
function isZodSchema4(value) {
|
|
13975
|
+
return value != null && typeof value === "object" && "_def" in value && typeof value._def === "object";
|
|
13976
|
+
}
|
|
13977
|
+
function serializeZodSchema4(schema) {
|
|
13978
|
+
try {
|
|
13979
|
+
return zodToJsonSchema(schema);
|
|
13980
|
+
} catch {
|
|
13981
|
+
return {
|
|
13982
|
+
type: "object",
|
|
13983
|
+
description: "Zod schema (conversion failed)"
|
|
13984
|
+
};
|
|
13985
|
+
}
|
|
13986
|
+
}
|
|
13987
|
+
function serializeOpenRouterTool2(tool) {
|
|
13988
|
+
if (!isObject(tool)) {
|
|
13989
|
+
return tool;
|
|
13990
|
+
}
|
|
13991
|
+
const serialized = {};
|
|
13992
|
+
for (const [key, value] of Object.entries(tool)) {
|
|
13993
|
+
if (OMITTED_OPENROUTER_KEYS2.has(key)) {
|
|
13994
|
+
continue;
|
|
13995
|
+
}
|
|
13996
|
+
if (key === "function" && isObject(value)) {
|
|
13997
|
+
serialized.function = sanitizeOpenRouterLoggedValue2(value);
|
|
13998
|
+
continue;
|
|
13999
|
+
}
|
|
14000
|
+
serialized[key] = sanitizeOpenRouterLoggedValue2(value);
|
|
14001
|
+
}
|
|
14002
|
+
return serialized;
|
|
14003
|
+
}
|
|
14004
|
+
function serializeOpenRouterToolsForLogging2(tools) {
|
|
14005
|
+
if (!Array.isArray(tools)) {
|
|
14006
|
+
return void 0;
|
|
14007
|
+
}
|
|
14008
|
+
return tools.map((tool) => serializeOpenRouterTool2(tool));
|
|
14009
|
+
}
|
|
14010
|
+
function sanitizeOpenRouterLoggedValue2(value) {
|
|
14011
|
+
if (isZodSchema4(value)) {
|
|
14012
|
+
return serializeZodSchema4(value);
|
|
14013
|
+
}
|
|
14014
|
+
if (typeof value === "function") {
|
|
14015
|
+
return "[Function]";
|
|
14016
|
+
}
|
|
14017
|
+
if (Array.isArray(value)) {
|
|
14018
|
+
return value.map((entry) => sanitizeOpenRouterLoggedValue2(entry));
|
|
14019
|
+
}
|
|
14020
|
+
if (!isObject(value)) {
|
|
14021
|
+
return value;
|
|
14022
|
+
}
|
|
14023
|
+
const sanitized = {};
|
|
14024
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
14025
|
+
if (OMITTED_OPENROUTER_KEYS2.has(key)) {
|
|
14026
|
+
continue;
|
|
14027
|
+
}
|
|
14028
|
+
if (key === "tools" && Array.isArray(entry)) {
|
|
14029
|
+
sanitized.tools = serializeOpenRouterToolsForLogging2(entry);
|
|
14030
|
+
continue;
|
|
14031
|
+
}
|
|
14032
|
+
sanitized[key] = sanitizeOpenRouterLoggedValue2(entry);
|
|
14033
|
+
}
|
|
14034
|
+
return sanitized;
|
|
14035
|
+
}
|
|
14036
|
+
function buildOpenRouterMetadata2(metadata, httpReferer, xTitle) {
|
|
14037
|
+
const sanitized = sanitizeOpenRouterLoggedValue2(metadata);
|
|
14038
|
+
const metadataRecord = isObject(sanitized) ? sanitized : {};
|
|
14039
|
+
const { model, provider: providerRouting, ...rest } = metadataRecord;
|
|
14040
|
+
const normalizedModel = parseOpenRouterModelString2(model);
|
|
14041
|
+
return {
|
|
14042
|
+
...rest,
|
|
14043
|
+
...normalizedModel.model !== void 0 ? { model: normalizedModel.model } : {},
|
|
14044
|
+
...providerRouting !== void 0 ? { providerRouting } : {},
|
|
14045
|
+
...httpReferer !== void 0 ? { httpReferer } : {},
|
|
14046
|
+
...xTitle !== void 0 ? { xTitle } : {},
|
|
14047
|
+
provider: normalizedModel.provider || "openrouter"
|
|
14048
|
+
};
|
|
14049
|
+
}
|
|
14050
|
+
function buildOpenRouterEmbeddingMetadata(metadata, httpReferer, xTitle) {
|
|
14051
|
+
const normalized = buildOpenRouterMetadata2(metadata, httpReferer, xTitle);
|
|
14052
|
+
return typeof normalized.model === "string" ? {
|
|
14053
|
+
...normalized,
|
|
14054
|
+
embedding_model: normalized.model
|
|
14055
|
+
} : normalized;
|
|
14056
|
+
}
|
|
14057
|
+
function extractOpenRouterCallModelInput2(request) {
|
|
14058
|
+
return isObject(request) && "input" in request ? sanitizeOpenRouterLoggedValue2(request.input) : void 0;
|
|
14059
|
+
}
|
|
14060
|
+
function extractOpenRouterCallModelMetadata2(request) {
|
|
14061
|
+
if (!isObject(request)) {
|
|
14062
|
+
return { provider: "openrouter" };
|
|
14063
|
+
}
|
|
14064
|
+
const { input: _input, ...metadata } = request;
|
|
14065
|
+
return buildOpenRouterMetadata2(metadata, void 0, void 0);
|
|
14066
|
+
}
|
|
14067
|
+
function extractOpenRouterResponseMetadata2(result) {
|
|
14068
|
+
if (!isObject(result)) {
|
|
14069
|
+
return void 0;
|
|
14070
|
+
}
|
|
14071
|
+
const { output: _output, data: _data, usage, ...metadata } = result;
|
|
14072
|
+
const sanitized = sanitizeOpenRouterLoggedValue2(metadata);
|
|
14073
|
+
const metadataRecord = isObject(sanitized) ? sanitized : {};
|
|
14074
|
+
const { model, provider, ...rest } = metadataRecord;
|
|
14075
|
+
const normalizedModel = parseOpenRouterModelString2(model);
|
|
14076
|
+
const normalizedProvider = (typeof provider === "string" ? provider : void 0) || normalizedModel.provider;
|
|
14077
|
+
const usageMetadata = extractOpenRouterUsageMetadata2(usage);
|
|
14078
|
+
const combined = {
|
|
14079
|
+
...rest,
|
|
14080
|
+
...normalizedModel.model !== void 0 ? { model: normalizedModel.model } : {},
|
|
14081
|
+
...usageMetadata || {},
|
|
14082
|
+
...normalizedProvider !== void 0 ? { provider: normalizedProvider } : {}
|
|
14083
|
+
};
|
|
14084
|
+
return Object.keys(combined).length > 0 ? combined : void 0;
|
|
14085
|
+
}
|
|
14086
|
+
function extractOpenRouterResponseOutput2(response, fallbackOutput) {
|
|
14087
|
+
if (isObject(response) && "output" in response && response.output !== void 0) {
|
|
14088
|
+
return sanitizeOpenRouterLoggedValue2(response.output);
|
|
14089
|
+
}
|
|
14090
|
+
if (fallbackOutput !== void 0) {
|
|
14091
|
+
return sanitizeOpenRouterLoggedValue2(fallbackOutput);
|
|
14092
|
+
}
|
|
14093
|
+
return void 0;
|
|
14094
|
+
}
|
|
14095
|
+
var OPENROUTER_WRAPPED_TOOL2 = Symbol("braintrust.openrouter.wrappedTool");
|
|
14096
|
+
function patchOpenRouterCallModelRequestTools2(request) {
|
|
14097
|
+
if (!Array.isArray(request.tools) || request.tools.length === 0) {
|
|
14098
|
+
return void 0;
|
|
14099
|
+
}
|
|
14100
|
+
const originalTools = request.tools;
|
|
14101
|
+
const wrappedTools = originalTools.map((tool) => wrapOpenRouterTool2(tool));
|
|
14102
|
+
const didPatch = wrappedTools.some(
|
|
14103
|
+
(tool, index) => tool !== originalTools[index]
|
|
14104
|
+
);
|
|
14105
|
+
if (!didPatch) {
|
|
14106
|
+
return void 0;
|
|
14107
|
+
}
|
|
14108
|
+
request.tools = wrappedTools;
|
|
14109
|
+
return () => {
|
|
14110
|
+
request.tools = originalTools;
|
|
14111
|
+
};
|
|
14112
|
+
}
|
|
14113
|
+
function wrapOpenRouterTool2(tool) {
|
|
14114
|
+
if (isWrappedTool2(tool) || !tool.function || typeof tool.function !== "object" || typeof tool.function.execute !== "function") {
|
|
14115
|
+
return tool;
|
|
14116
|
+
}
|
|
14117
|
+
const toolName = tool.function.name || "tool";
|
|
14118
|
+
const originalExecute = tool.function.execute;
|
|
14119
|
+
const wrappedTool = {
|
|
14120
|
+
...tool,
|
|
14121
|
+
function: {
|
|
14122
|
+
...tool.function,
|
|
14123
|
+
execute(...args) {
|
|
14124
|
+
return traceToolExecution2({
|
|
14125
|
+
args,
|
|
14126
|
+
execute: () => Reflect.apply(originalExecute, this, args),
|
|
14127
|
+
toolCallId: getToolCallId2(args[1]),
|
|
14128
|
+
toolName
|
|
14129
|
+
});
|
|
14130
|
+
}
|
|
14131
|
+
}
|
|
14132
|
+
};
|
|
14133
|
+
Object.defineProperty(wrappedTool, OPENROUTER_WRAPPED_TOOL2, {
|
|
14134
|
+
value: true,
|
|
14135
|
+
enumerable: false,
|
|
14136
|
+
configurable: false
|
|
14137
|
+
});
|
|
14138
|
+
return wrappedTool;
|
|
14139
|
+
}
|
|
14140
|
+
function isWrappedTool2(tool) {
|
|
14141
|
+
return Boolean(tool[OPENROUTER_WRAPPED_TOOL2]);
|
|
14142
|
+
}
|
|
14143
|
+
function traceToolExecution2(args) {
|
|
14144
|
+
const tracingChannel = openRouterChannels.toolExecute.tracingChannel();
|
|
14145
|
+
const input = args.args.length > 0 ? args.args[0] : void 0;
|
|
14146
|
+
const event = {
|
|
14147
|
+
arguments: [input],
|
|
14148
|
+
span_info: {
|
|
14149
|
+
name: args.toolName
|
|
14150
|
+
},
|
|
14151
|
+
toolCallId: args.toolCallId,
|
|
14152
|
+
toolName: args.toolName
|
|
14153
|
+
};
|
|
14154
|
+
tracingChannel.start.publish(event);
|
|
14155
|
+
try {
|
|
14156
|
+
const result = args.execute();
|
|
14157
|
+
return publishToolResult2(tracingChannel, event, result);
|
|
14158
|
+
} catch (error) {
|
|
14159
|
+
event.error = normalizeError2(error);
|
|
14160
|
+
tracingChannel.error.publish(event);
|
|
14161
|
+
throw error;
|
|
14162
|
+
}
|
|
14163
|
+
}
|
|
14164
|
+
function publishToolResult2(tracingChannel, event, result) {
|
|
14165
|
+
if (isPromiseLike4(result)) {
|
|
14166
|
+
return result.then(
|
|
14167
|
+
(resolved) => {
|
|
14168
|
+
event.result = resolved;
|
|
14169
|
+
tracingChannel.asyncEnd.publish(event);
|
|
14170
|
+
return resolved;
|
|
14171
|
+
},
|
|
14172
|
+
(error) => {
|
|
14173
|
+
event.error = normalizeError2(error);
|
|
14174
|
+
tracingChannel.error.publish(event);
|
|
14175
|
+
throw error;
|
|
14176
|
+
}
|
|
14177
|
+
);
|
|
14178
|
+
}
|
|
14179
|
+
event.result = result;
|
|
14180
|
+
tracingChannel.asyncEnd.publish(event);
|
|
14181
|
+
return result;
|
|
14182
|
+
}
|
|
14183
|
+
function getToolCallId2(context) {
|
|
14184
|
+
const toolContext = context;
|
|
14185
|
+
return typeof toolContext?.toolCall?.id === "string" ? toolContext.toolCall.id : void 0;
|
|
14186
|
+
}
|
|
14187
|
+
function isPromiseLike4(value) {
|
|
14188
|
+
return !!value && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function";
|
|
14189
|
+
}
|
|
14190
|
+
function aggregateOpenRouterChatChunks(chunks) {
|
|
14191
|
+
let role;
|
|
14192
|
+
let content = "";
|
|
14193
|
+
let toolCalls;
|
|
14194
|
+
let finishReason;
|
|
14195
|
+
let metrics = {};
|
|
14196
|
+
for (const chunk of chunks) {
|
|
14197
|
+
metrics = {
|
|
14198
|
+
...metrics,
|
|
14199
|
+
...parseOpenRouterMetricsFromUsage2(chunk?.usage)
|
|
14200
|
+
};
|
|
14201
|
+
const choice = chunk?.choices?.[0];
|
|
14202
|
+
const delta = choice?.delta;
|
|
14203
|
+
if (!delta) {
|
|
14204
|
+
if (choice?.finish_reason !== void 0) {
|
|
14205
|
+
finishReason = choice.finish_reason;
|
|
14206
|
+
}
|
|
14207
|
+
continue;
|
|
14208
|
+
}
|
|
14209
|
+
if (!role && delta.role) {
|
|
14210
|
+
role = delta.role;
|
|
14211
|
+
}
|
|
14212
|
+
if (typeof delta.content === "string") {
|
|
14213
|
+
content += delta.content;
|
|
14214
|
+
}
|
|
14215
|
+
const choiceFinishReason = choice?.finishReason ?? choice?.finish_reason ?? void 0;
|
|
14216
|
+
const deltaFinishReason = delta.finishReason ?? delta.finish_reason ?? void 0;
|
|
14217
|
+
if (choiceFinishReason !== void 0) {
|
|
14218
|
+
finishReason = choiceFinishReason;
|
|
14219
|
+
} else if (deltaFinishReason !== void 0) {
|
|
14220
|
+
finishReason = deltaFinishReason;
|
|
14221
|
+
}
|
|
14222
|
+
const toolCallDeltas = Array.isArray(delta.toolCalls) ? delta.toolCalls : Array.isArray(delta.tool_calls) ? delta.tool_calls : void 0;
|
|
14223
|
+
if (!toolCallDeltas) {
|
|
14224
|
+
continue;
|
|
14225
|
+
}
|
|
14226
|
+
for (const toolDelta of toolCallDeltas) {
|
|
14227
|
+
if (!toolDelta?.function) {
|
|
14228
|
+
continue;
|
|
14229
|
+
}
|
|
14230
|
+
const toolIndex = toolDelta.index ?? 0;
|
|
14231
|
+
const existingToolCall = toolCalls?.[toolIndex];
|
|
14232
|
+
if (!existingToolCall || toolDelta.id && existingToolCall.id !== void 0 && existingToolCall.id !== toolDelta.id) {
|
|
14233
|
+
const nextToolCalls = [...toolCalls || []];
|
|
14234
|
+
nextToolCalls[toolIndex] = {
|
|
14235
|
+
index: toolIndex,
|
|
14236
|
+
id: toolDelta.id,
|
|
14237
|
+
type: toolDelta.type,
|
|
14238
|
+
function: {
|
|
14239
|
+
name: toolDelta.function.name,
|
|
14240
|
+
arguments: toolDelta.function.arguments || ""
|
|
14241
|
+
}
|
|
14242
|
+
};
|
|
14243
|
+
toolCalls = nextToolCalls;
|
|
14244
|
+
continue;
|
|
14245
|
+
}
|
|
14246
|
+
const current = existingToolCall;
|
|
14247
|
+
if (toolDelta.id && !current.id) {
|
|
14248
|
+
current.id = toolDelta.id;
|
|
14249
|
+
}
|
|
14250
|
+
if (toolDelta.type && !current.type) {
|
|
14251
|
+
current.type = toolDelta.type;
|
|
14252
|
+
}
|
|
14253
|
+
if (toolDelta.function.name && !current.function.name) {
|
|
14254
|
+
current.function.name = toolDelta.function.name;
|
|
14255
|
+
}
|
|
14256
|
+
current.function.arguments += toolDelta.function.arguments || "";
|
|
14257
|
+
}
|
|
14258
|
+
}
|
|
14259
|
+
return {
|
|
14260
|
+
output: [
|
|
14261
|
+
{
|
|
14262
|
+
index: 0,
|
|
14263
|
+
message: {
|
|
14264
|
+
role,
|
|
14265
|
+
content: content || void 0,
|
|
14266
|
+
...toolCalls ? { tool_calls: toolCalls } : {}
|
|
14267
|
+
},
|
|
14268
|
+
logprobs: null,
|
|
14269
|
+
finish_reason: finishReason
|
|
14270
|
+
}
|
|
14271
|
+
],
|
|
14272
|
+
metrics
|
|
14273
|
+
};
|
|
14274
|
+
}
|
|
14275
|
+
function aggregateOpenRouterResponseStreamEvents(chunks) {
|
|
14276
|
+
let finalResponse;
|
|
14277
|
+
for (const chunk of chunks) {
|
|
14278
|
+
const response = chunk?.response;
|
|
14279
|
+
if (!response) {
|
|
14280
|
+
continue;
|
|
14281
|
+
}
|
|
14282
|
+
if (chunk.type === "response.completed" || chunk.type === "response.incomplete" || chunk.type === "response.failed") {
|
|
14283
|
+
finalResponse = response;
|
|
14284
|
+
}
|
|
14285
|
+
}
|
|
14286
|
+
if (!finalResponse) {
|
|
14287
|
+
return {
|
|
14288
|
+
output: void 0,
|
|
14289
|
+
metrics: {}
|
|
14290
|
+
};
|
|
14291
|
+
}
|
|
14292
|
+
return {
|
|
14293
|
+
output: extractOpenRouterResponseOutput2(finalResponse),
|
|
14294
|
+
metrics: parseOpenRouterMetricsFromUsage2(finalResponse.usage),
|
|
14295
|
+
...extractOpenRouterResponseMetadata2(finalResponse) ? { metadata: extractOpenRouterResponseMetadata2(finalResponse) } : {}
|
|
14296
|
+
};
|
|
14297
|
+
}
|
|
14298
|
+
var OPENROUTER_WRAPPED_CALL_MODEL_RESULT2 = Symbol(
|
|
14299
|
+
"braintrust.openrouter.wrappedCallModelResult"
|
|
14300
|
+
);
|
|
14301
|
+
var OPENROUTER_CALL_MODEL_STREAM_METHODS2 = [
|
|
14302
|
+
"getFullResponsesStream",
|
|
14303
|
+
"getItemsStream",
|
|
14304
|
+
"getNewMessagesStream",
|
|
14305
|
+
"getReasoningStream",
|
|
14306
|
+
"getTextStream",
|
|
14307
|
+
"getToolCallsStream",
|
|
14308
|
+
"getToolStream"
|
|
14309
|
+
];
|
|
14310
|
+
var OPENROUTER_CALL_MODEL_CONTEXT_METHODS2 = [
|
|
14311
|
+
"cancel",
|
|
14312
|
+
"getPendingToolCalls",
|
|
14313
|
+
"getState",
|
|
14314
|
+
"getToolCalls",
|
|
14315
|
+
"requiresApproval"
|
|
14316
|
+
];
|
|
14317
|
+
function patchOpenRouterCallModelResult2(args) {
|
|
14318
|
+
const { request, result, span } = args;
|
|
14319
|
+
if (!isObject(result) || isWrappedCallModelResult2(result)) {
|
|
14320
|
+
return false;
|
|
14321
|
+
}
|
|
14322
|
+
const resultLike = result;
|
|
14323
|
+
const hasInstrumentableMethod = typeof resultLike.getResponse === "function" || typeof resultLike.getText === "function" || OPENROUTER_CALL_MODEL_STREAM_METHODS2.some(
|
|
14324
|
+
(methodName) => typeof resultLike[methodName] === "function"
|
|
14325
|
+
);
|
|
14326
|
+
if (!hasInstrumentableMethod) {
|
|
14327
|
+
return false;
|
|
14328
|
+
}
|
|
14329
|
+
Object.defineProperty(resultLike, OPENROUTER_WRAPPED_CALL_MODEL_RESULT2, {
|
|
14330
|
+
value: true,
|
|
14331
|
+
enumerable: false,
|
|
14332
|
+
configurable: false
|
|
14333
|
+
});
|
|
14334
|
+
const originalGetResponse = typeof resultLike.getResponse === "function" ? resultLike.getResponse.bind(resultLike) : void 0;
|
|
14335
|
+
const originalGetInitialResponse = typeof resultLike.getInitialResponse === "function" ? resultLike.getInitialResponse.bind(resultLike) : void 0;
|
|
14336
|
+
const originalMakeFollowupRequest = typeof resultLike.makeFollowupRequest === "function" ? resultLike.makeFollowupRequest.bind(resultLike) : void 0;
|
|
14337
|
+
let ended = false;
|
|
14338
|
+
let tracedTurnCount = 0;
|
|
14339
|
+
const endSpanWithResult = async (response, fallbackOutput) => {
|
|
14340
|
+
if (ended) {
|
|
14341
|
+
return;
|
|
14342
|
+
}
|
|
14343
|
+
ended = true;
|
|
14344
|
+
const finalResponse = getFinalOpenRouterCallModelResponse2(
|
|
14345
|
+
resultLike,
|
|
14346
|
+
response
|
|
14347
|
+
);
|
|
14348
|
+
if (finalResponse) {
|
|
14349
|
+
const rounds = getOpenRouterCallModelRounds2(resultLike);
|
|
14350
|
+
const metadata = extractOpenRouterCallModelResultMetadata2(
|
|
14351
|
+
finalResponse,
|
|
14352
|
+
rounds.length + 1
|
|
14353
|
+
);
|
|
14354
|
+
span.log({
|
|
14355
|
+
output: extractOpenRouterResponseOutput2(finalResponse, fallbackOutput),
|
|
14356
|
+
...metadata ? { metadata } : {},
|
|
14357
|
+
metrics: aggregateOpenRouterCallModelMetrics2(rounds, finalResponse)
|
|
14358
|
+
});
|
|
14359
|
+
span.end();
|
|
14360
|
+
return;
|
|
14361
|
+
}
|
|
14362
|
+
if (fallbackOutput !== void 0) {
|
|
14363
|
+
span.log({
|
|
14364
|
+
output: fallbackOutput
|
|
14365
|
+
});
|
|
14366
|
+
}
|
|
14367
|
+
span.end();
|
|
14368
|
+
};
|
|
14369
|
+
const endSpanWithError = (error) => {
|
|
14370
|
+
if (ended) {
|
|
14371
|
+
return;
|
|
14372
|
+
}
|
|
14373
|
+
ended = true;
|
|
14374
|
+
span.log({
|
|
14375
|
+
error: normalizeError2(error).message
|
|
14376
|
+
});
|
|
14377
|
+
span.end();
|
|
14378
|
+
};
|
|
14379
|
+
const finalizeFromResponse = async (fallbackOutput) => {
|
|
14380
|
+
if (!originalGetResponse) {
|
|
14381
|
+
await endSpanWithResult(void 0, fallbackOutput);
|
|
14382
|
+
return;
|
|
14383
|
+
}
|
|
14384
|
+
try {
|
|
14385
|
+
await endSpanWithResult(await originalGetResponse(), fallbackOutput);
|
|
14386
|
+
} catch {
|
|
14387
|
+
await endSpanWithResult(void 0, fallbackOutput);
|
|
14388
|
+
}
|
|
14389
|
+
};
|
|
14390
|
+
if (originalGetResponse) {
|
|
14391
|
+
resultLike.getResponse = async (...args2) => {
|
|
14392
|
+
return await withCurrent(span, async () => {
|
|
14393
|
+
try {
|
|
14394
|
+
const response = await originalGetResponse(...args2);
|
|
14395
|
+
await endSpanWithResult(response);
|
|
14396
|
+
return response;
|
|
14397
|
+
} catch (error) {
|
|
14398
|
+
endSpanWithError(error);
|
|
14399
|
+
throw error;
|
|
14400
|
+
}
|
|
14401
|
+
});
|
|
14402
|
+
};
|
|
14403
|
+
}
|
|
14404
|
+
if (typeof resultLike.getText === "function") {
|
|
14405
|
+
const originalGetText = resultLike.getText.bind(resultLike);
|
|
14406
|
+
resultLike.getText = async (...args2) => {
|
|
14407
|
+
return await withCurrent(span, async () => {
|
|
14408
|
+
try {
|
|
14409
|
+
const text = await originalGetText(...args2);
|
|
14410
|
+
await finalizeFromResponse(text);
|
|
14411
|
+
return text;
|
|
14412
|
+
} catch (error) {
|
|
14413
|
+
endSpanWithError(error);
|
|
14414
|
+
throw error;
|
|
14415
|
+
}
|
|
14416
|
+
});
|
|
14417
|
+
};
|
|
14418
|
+
}
|
|
14419
|
+
for (const methodName of OPENROUTER_CALL_MODEL_CONTEXT_METHODS2) {
|
|
14420
|
+
if (typeof resultLike[methodName] !== "function") {
|
|
14421
|
+
continue;
|
|
14422
|
+
}
|
|
14423
|
+
const originalMethod = resultLike[methodName];
|
|
14424
|
+
resultLike[methodName] = async (...args2) => {
|
|
14425
|
+
return await withCurrent(span, async () => {
|
|
14426
|
+
return await originalMethod.apply(resultLike, args2);
|
|
14427
|
+
});
|
|
14428
|
+
};
|
|
14429
|
+
}
|
|
14430
|
+
for (const methodName of OPENROUTER_CALL_MODEL_STREAM_METHODS2) {
|
|
14431
|
+
if (typeof resultLike[methodName] !== "function") {
|
|
14432
|
+
continue;
|
|
14433
|
+
}
|
|
14434
|
+
const originalMethod = resultLike[methodName];
|
|
14435
|
+
resultLike[methodName] = (...args2) => {
|
|
14436
|
+
const stream = withCurrent(
|
|
14437
|
+
span,
|
|
14438
|
+
() => originalMethod.apply(resultLike, args2)
|
|
14439
|
+
);
|
|
14440
|
+
if (!isAsyncIterable4(stream)) {
|
|
14441
|
+
return stream;
|
|
14442
|
+
}
|
|
14443
|
+
return wrapAsyncIterableWithSpan2({
|
|
14444
|
+
finalize: finalizeFromResponse,
|
|
14445
|
+
iteratorFactory: () => stream[Symbol.asyncIterator](),
|
|
14446
|
+
onError: endSpanWithError,
|
|
14447
|
+
span
|
|
14448
|
+
});
|
|
14449
|
+
};
|
|
14450
|
+
}
|
|
14451
|
+
if (originalGetInitialResponse) {
|
|
14452
|
+
let initialTurnTraced = false;
|
|
14453
|
+
resultLike.getInitialResponse = async (...args2) => {
|
|
14454
|
+
if (initialTurnTraced) {
|
|
14455
|
+
return await withCurrent(span, async () => {
|
|
14456
|
+
return await originalGetInitialResponse(...args2);
|
|
14457
|
+
});
|
|
14458
|
+
}
|
|
14459
|
+
initialTurnTraced = true;
|
|
14460
|
+
const step = tracedTurnCount + 1;
|
|
14461
|
+
const stepType = tracedTurnCount === 0 ? "initial" : "continue";
|
|
14462
|
+
const response = await traceOpenRouterCallModelTurn2({
|
|
14463
|
+
fn: async () => {
|
|
14464
|
+
const nextResponse = await originalGetInitialResponse(...args2);
|
|
14465
|
+
tracedTurnCount++;
|
|
14466
|
+
return nextResponse;
|
|
14467
|
+
},
|
|
14468
|
+
parentSpan: span,
|
|
14469
|
+
request: getOpenRouterResolvedRequest2(resultLike, request),
|
|
14470
|
+
step,
|
|
14471
|
+
stepType
|
|
14472
|
+
});
|
|
14473
|
+
return response;
|
|
14474
|
+
};
|
|
14475
|
+
}
|
|
14476
|
+
if (originalMakeFollowupRequest) {
|
|
14477
|
+
resultLike.makeFollowupRequest = async (...args2) => {
|
|
14478
|
+
const currentResponse = args2[0];
|
|
14479
|
+
const toolResults = Array.isArray(args2[1]) ? args2[1] : [];
|
|
14480
|
+
const step = tracedTurnCount + 1;
|
|
14481
|
+
const response = await traceOpenRouterCallModelTurn2({
|
|
14482
|
+
fn: async () => {
|
|
14483
|
+
const nextResponse = await originalMakeFollowupRequest(...args2);
|
|
14484
|
+
tracedTurnCount++;
|
|
14485
|
+
return nextResponse;
|
|
14486
|
+
},
|
|
14487
|
+
parentSpan: span,
|
|
14488
|
+
request: buildOpenRouterFollowupRequest2(
|
|
14489
|
+
getOpenRouterResolvedRequest2(resultLike, request),
|
|
14490
|
+
currentResponse,
|
|
14491
|
+
toolResults
|
|
14492
|
+
),
|
|
14493
|
+
step,
|
|
14494
|
+
stepType: "continue"
|
|
14495
|
+
});
|
|
14496
|
+
return response;
|
|
14497
|
+
};
|
|
14498
|
+
}
|
|
14499
|
+
return true;
|
|
14500
|
+
}
|
|
14501
|
+
async function traceOpenRouterCallModelTurn2(args) {
|
|
14502
|
+
const context = {
|
|
14503
|
+
arguments: [args.request],
|
|
14504
|
+
step: args.step,
|
|
14505
|
+
stepType: args.stepType
|
|
14506
|
+
};
|
|
14507
|
+
return await withCurrent(
|
|
14508
|
+
args.parentSpan,
|
|
14509
|
+
() => openRouterChannels.callModelTurn.tracePromise(args.fn, context)
|
|
14510
|
+
);
|
|
14511
|
+
}
|
|
14512
|
+
function isWrappedCallModelResult2(value) {
|
|
14513
|
+
return Boolean(
|
|
14514
|
+
isObject(value) && value[OPENROUTER_WRAPPED_CALL_MODEL_RESULT2]
|
|
14515
|
+
);
|
|
14516
|
+
}
|
|
14517
|
+
function extractOpenRouterCallModelResultMetadata2(response, turnCount) {
|
|
14518
|
+
const combined = {
|
|
14519
|
+
...extractOpenRouterResponseMetadata2(response) || {},
|
|
14520
|
+
...turnCount !== void 0 ? { turn_count: turnCount } : {}
|
|
14521
|
+
};
|
|
14522
|
+
return Object.keys(combined).length > 0 ? combined : void 0;
|
|
14523
|
+
}
|
|
14524
|
+
function getFinalOpenRouterCallModelResponse2(result, response) {
|
|
14525
|
+
if (isObject(response)) {
|
|
14526
|
+
return response;
|
|
14527
|
+
}
|
|
14528
|
+
return isObject(result.finalResponse) ? result.finalResponse : void 0;
|
|
14529
|
+
}
|
|
14530
|
+
function getOpenRouterCallModelRounds2(result) {
|
|
14531
|
+
if (!Array.isArray(result.allToolExecutionRounds)) {
|
|
14532
|
+
return [];
|
|
14533
|
+
}
|
|
14534
|
+
return result.allToolExecutionRounds.filter((round) => isObject(round)).map((round) => ({
|
|
14535
|
+
response: isObject(round.response) ? round.response : void 0,
|
|
14536
|
+
round: typeof round.round === "number" ? round.round : void 0,
|
|
14537
|
+
toolResults: Array.isArray(round.toolResults) ? round.toolResults : []
|
|
14538
|
+
})).filter((round) => round.response !== void 0);
|
|
14539
|
+
}
|
|
14540
|
+
function aggregateOpenRouterCallModelMetrics2(rounds, finalResponse) {
|
|
14541
|
+
const metrics = {};
|
|
14542
|
+
const responses = [
|
|
14543
|
+
...rounds.map((round) => round.response).filter(isObject),
|
|
14544
|
+
finalResponse
|
|
14545
|
+
];
|
|
14546
|
+
for (const response of responses) {
|
|
14547
|
+
const responseMetrics = parseOpenRouterMetricsFromUsage2(response.usage);
|
|
14548
|
+
for (const [name, value] of Object.entries(responseMetrics)) {
|
|
14549
|
+
metrics[name] = (metrics[name] || 0) + value;
|
|
14550
|
+
}
|
|
14551
|
+
}
|
|
14552
|
+
return metrics;
|
|
14553
|
+
}
|
|
14554
|
+
function buildNextOpenRouterCallModelInput2(currentInput, response, toolResults) {
|
|
14555
|
+
const normalizedInput = Array.isArray(currentInput) ? [...currentInput] : currentInput === void 0 ? [] : [currentInput];
|
|
14556
|
+
const responseOutput = Array.isArray(response.output) ? response.output : response.output === void 0 ? [] : [response.output];
|
|
14557
|
+
return [...normalizedInput, ...responseOutput, ...toolResults].map(
|
|
14558
|
+
(entry) => sanitizeOpenRouterLoggedValue2(entry)
|
|
14559
|
+
);
|
|
14560
|
+
}
|
|
14561
|
+
function getOpenRouterResolvedRequest2(result, request) {
|
|
14562
|
+
if (isObject(result.resolvedRequest)) {
|
|
14563
|
+
return result.resolvedRequest;
|
|
14564
|
+
}
|
|
14565
|
+
return request;
|
|
14566
|
+
}
|
|
14567
|
+
function buildOpenRouterFollowupRequest2(request, currentResponse, toolResults) {
|
|
14568
|
+
if (!request) {
|
|
14569
|
+
return void 0;
|
|
14570
|
+
}
|
|
14571
|
+
return {
|
|
14572
|
+
...request,
|
|
14573
|
+
input: buildNextOpenRouterCallModelInput2(
|
|
14574
|
+
extractOpenRouterCallModelInput2(request),
|
|
14575
|
+
isObject(currentResponse) ? currentResponse : {},
|
|
14576
|
+
toolResults
|
|
14577
|
+
),
|
|
14578
|
+
stream: false
|
|
14579
|
+
};
|
|
14580
|
+
}
|
|
14581
|
+
function wrapAsyncIterableWithSpan2(args) {
|
|
14582
|
+
return {
|
|
14583
|
+
[Symbol.asyncIterator]() {
|
|
14584
|
+
const iterator = args.iteratorFactory();
|
|
14585
|
+
return {
|
|
14586
|
+
next(value) {
|
|
14587
|
+
return withCurrent(
|
|
14588
|
+
args.span,
|
|
14589
|
+
() => value === void 0 ? iterator.next() : iterator.next(value)
|
|
14590
|
+
).then(
|
|
14591
|
+
async (result) => {
|
|
14592
|
+
if (result.done) {
|
|
14593
|
+
await args.finalize();
|
|
14594
|
+
}
|
|
14595
|
+
return result;
|
|
14596
|
+
},
|
|
14597
|
+
(error) => {
|
|
14598
|
+
args.onError(error);
|
|
14599
|
+
throw error;
|
|
14600
|
+
}
|
|
14601
|
+
);
|
|
14602
|
+
},
|
|
14603
|
+
return(value) {
|
|
14604
|
+
if (typeof iterator.return !== "function") {
|
|
14605
|
+
return args.finalize().then(() => ({
|
|
14606
|
+
done: true,
|
|
14607
|
+
value
|
|
14608
|
+
}));
|
|
14609
|
+
}
|
|
14610
|
+
return withCurrent(args.span, () => iterator.return(value)).then(
|
|
14611
|
+
async (result) => {
|
|
14612
|
+
await args.finalize();
|
|
14613
|
+
return result;
|
|
14614
|
+
},
|
|
14615
|
+
(error) => {
|
|
14616
|
+
args.onError(error);
|
|
14617
|
+
throw error;
|
|
14618
|
+
}
|
|
14619
|
+
);
|
|
14620
|
+
},
|
|
14621
|
+
throw(error) {
|
|
14622
|
+
args.onError(error);
|
|
14623
|
+
if (typeof iterator.throw !== "function") {
|
|
14624
|
+
return Promise.reject(error);
|
|
14625
|
+
}
|
|
14626
|
+
return withCurrent(args.span, () => iterator.throw(error));
|
|
14627
|
+
},
|
|
14628
|
+
[Symbol.asyncIterator]() {
|
|
14629
|
+
return this;
|
|
14630
|
+
}
|
|
14631
|
+
};
|
|
14632
|
+
}
|
|
14633
|
+
};
|
|
14634
|
+
}
|
|
14635
|
+
function isAsyncIterable4(value) {
|
|
14636
|
+
return !!value && (typeof value === "object" || typeof value === "function") && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
|
|
14637
|
+
}
|
|
14638
|
+
function normalizeError2(error) {
|
|
14639
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
14640
|
+
}
|
|
14641
|
+
|
|
14642
|
+
// src/instrumentation/plugins/mistral-channels.ts
|
|
14643
|
+
var mistralChannels = defineChannels("@mistralai/mistralai", {
|
|
14644
|
+
chatComplete: channel({
|
|
14645
|
+
channelName: "chat.complete",
|
|
14646
|
+
kind: "async"
|
|
14647
|
+
}),
|
|
14648
|
+
chatStream: channel({
|
|
14649
|
+
channelName: "chat.stream",
|
|
14650
|
+
kind: "async"
|
|
14651
|
+
}),
|
|
14652
|
+
embeddingsCreate: channel({
|
|
14653
|
+
channelName: "embeddings.create",
|
|
14654
|
+
kind: "async"
|
|
14655
|
+
}),
|
|
14656
|
+
fimComplete: channel({
|
|
14657
|
+
channelName: "fim.complete",
|
|
14658
|
+
kind: "async"
|
|
14659
|
+
}),
|
|
14660
|
+
fimStream: channel({
|
|
14661
|
+
channelName: "fim.stream",
|
|
14662
|
+
kind: "async"
|
|
14663
|
+
}),
|
|
14664
|
+
agentsComplete: channel({
|
|
14665
|
+
channelName: "agents.complete",
|
|
14666
|
+
kind: "async"
|
|
14667
|
+
}),
|
|
14668
|
+
agentsStream: channel({
|
|
14669
|
+
channelName: "agents.stream",
|
|
14670
|
+
kind: "async"
|
|
14671
|
+
})
|
|
14672
|
+
});
|
|
14673
|
+
|
|
14674
|
+
// src/instrumentation/plugins/mistral-plugin.ts
|
|
14675
|
+
var MistralPlugin = class extends BasePlugin {
|
|
14676
|
+
onEnable() {
|
|
14677
|
+
this.subscribeToMistralChannels();
|
|
14678
|
+
}
|
|
14679
|
+
onDisable() {
|
|
14680
|
+
this.unsubscribers = unsubscribeAll(this.unsubscribers);
|
|
14681
|
+
}
|
|
14682
|
+
subscribeToMistralChannels() {
|
|
14683
|
+
this.unsubscribers.push(
|
|
14684
|
+
traceStreamingChannel(mistralChannels.chatComplete, {
|
|
14685
|
+
name: "mistral.chat.complete",
|
|
14686
|
+
type: "llm" /* LLM */,
|
|
14687
|
+
extractInput: extractMessagesInputWithMetadata,
|
|
14688
|
+
extractOutput: (result) => {
|
|
14689
|
+
return result?.choices;
|
|
14690
|
+
},
|
|
14691
|
+
extractMetadata: (result) => extractMistralResponseMetadata(result),
|
|
14692
|
+
extractMetrics: (result, startTime) => extractMistralMetrics(result?.usage, startTime)
|
|
14693
|
+
})
|
|
14694
|
+
);
|
|
14695
|
+
this.unsubscribers.push(
|
|
14696
|
+
traceStreamingChannel(mistralChannels.chatStream, {
|
|
14697
|
+
name: "mistral.chat.stream",
|
|
14698
|
+
type: "llm" /* LLM */,
|
|
14699
|
+
extractInput: extractMessagesInputWithMetadata,
|
|
14700
|
+
extractOutput: extractMistralStreamOutput,
|
|
14701
|
+
extractMetadata: (result) => extractMistralResponseMetadata(result),
|
|
14702
|
+
extractMetrics: (result, startTime) => extractMistralStreamingMetrics(result, startTime),
|
|
14703
|
+
aggregateChunks: aggregateMistralStreamChunks
|
|
14704
|
+
})
|
|
14705
|
+
);
|
|
14706
|
+
this.unsubscribers.push(
|
|
14707
|
+
traceAsyncChannel(mistralChannels.embeddingsCreate, {
|
|
14708
|
+
name: "mistral.embeddings.create",
|
|
14709
|
+
type: "llm" /* LLM */,
|
|
14710
|
+
extractInput: extractEmbeddingInputWithMetadata,
|
|
14711
|
+
extractOutput: (result) => {
|
|
14712
|
+
const embedding = result?.data?.[0]?.embedding;
|
|
14713
|
+
return Array.isArray(embedding) ? { embedding_length: embedding.length } : void 0;
|
|
14714
|
+
},
|
|
14715
|
+
extractMetadata: (result) => extractMistralResponseMetadata(result),
|
|
14716
|
+
extractMetrics: (result) => parseMistralMetricsFromUsage(result?.usage)
|
|
14717
|
+
})
|
|
14718
|
+
);
|
|
14719
|
+
this.unsubscribers.push(
|
|
14720
|
+
traceStreamingChannel(mistralChannels.fimComplete, {
|
|
14721
|
+
name: "mistral.fim.complete",
|
|
14722
|
+
type: "llm" /* LLM */,
|
|
14723
|
+
extractInput: extractPromptInputWithMetadata,
|
|
14724
|
+
extractOutput: (result) => {
|
|
14725
|
+
return result?.choices;
|
|
14726
|
+
},
|
|
14727
|
+
extractMetadata: (result) => extractMistralResponseMetadata(result),
|
|
14728
|
+
extractMetrics: (result, startTime) => extractMistralMetrics(result?.usage, startTime)
|
|
14729
|
+
})
|
|
14730
|
+
);
|
|
14731
|
+
this.unsubscribers.push(
|
|
14732
|
+
traceStreamingChannel(mistralChannels.fimStream, {
|
|
14733
|
+
name: "mistral.fim.stream",
|
|
14734
|
+
type: "llm" /* LLM */,
|
|
14735
|
+
extractInput: extractPromptInputWithMetadata,
|
|
14736
|
+
extractOutput: extractMistralStreamOutput,
|
|
14737
|
+
extractMetadata: (result) => extractMistralResponseMetadata(result),
|
|
14738
|
+
extractMetrics: (result, startTime) => extractMistralStreamingMetrics(result, startTime),
|
|
14739
|
+
aggregateChunks: aggregateMistralStreamChunks
|
|
14740
|
+
})
|
|
14741
|
+
);
|
|
14742
|
+
this.unsubscribers.push(
|
|
14743
|
+
traceStreamingChannel(mistralChannels.agentsComplete, {
|
|
14744
|
+
name: "mistral.agents.complete",
|
|
14745
|
+
type: "llm" /* LLM */,
|
|
14746
|
+
extractInput: extractMessagesInputWithMetadata,
|
|
14747
|
+
extractOutput: (result) => {
|
|
14748
|
+
return result?.choices;
|
|
14749
|
+
},
|
|
14750
|
+
extractMetadata: (result) => extractMistralResponseMetadata(result),
|
|
14751
|
+
extractMetrics: (result, startTime) => extractMistralMetrics(result?.usage, startTime)
|
|
14752
|
+
})
|
|
14753
|
+
);
|
|
14754
|
+
this.unsubscribers.push(
|
|
14755
|
+
traceStreamingChannel(mistralChannels.agentsStream, {
|
|
14756
|
+
name: "mistral.agents.stream",
|
|
14757
|
+
type: "llm" /* LLM */,
|
|
14758
|
+
extractInput: extractMessagesInputWithMetadata,
|
|
14759
|
+
extractOutput: extractMistralStreamOutput,
|
|
14760
|
+
extractMetadata: (result) => extractMistralResponseMetadata(result),
|
|
14761
|
+
extractMetrics: (result, startTime) => extractMistralStreamingMetrics(result, startTime),
|
|
14762
|
+
aggregateChunks: aggregateMistralStreamChunks
|
|
14763
|
+
})
|
|
14764
|
+
);
|
|
14765
|
+
}
|
|
14766
|
+
};
|
|
14767
|
+
var TOKEN_NAME_MAP4 = {
|
|
14768
|
+
promptTokens: "prompt_tokens",
|
|
14769
|
+
inputTokens: "prompt_tokens",
|
|
14770
|
+
completionTokens: "completion_tokens",
|
|
14771
|
+
outputTokens: "completion_tokens",
|
|
14772
|
+
totalTokens: "tokens",
|
|
14773
|
+
prompt_tokens: "prompt_tokens",
|
|
14774
|
+
input_tokens: "prompt_tokens",
|
|
14775
|
+
completion_tokens: "completion_tokens",
|
|
14776
|
+
output_tokens: "completion_tokens",
|
|
14777
|
+
total_tokens: "tokens",
|
|
14778
|
+
promptAudioSeconds: "prompt_audio_seconds",
|
|
14779
|
+
prompt_audio_seconds: "prompt_audio_seconds"
|
|
14780
|
+
};
|
|
14781
|
+
var TOKEN_DETAIL_PREFIX_MAP3 = {
|
|
14782
|
+
promptTokensDetails: "prompt",
|
|
14783
|
+
inputTokensDetails: "prompt",
|
|
14784
|
+
completionTokensDetails: "completion",
|
|
14785
|
+
outputTokensDetails: "completion",
|
|
14786
|
+
prompt_tokens_details: "prompt",
|
|
14787
|
+
input_tokens_details: "prompt",
|
|
14788
|
+
completion_tokens_details: "completion",
|
|
14789
|
+
output_tokens_details: "completion"
|
|
14790
|
+
};
|
|
14791
|
+
var MISTRAL_REQUEST_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
|
|
14792
|
+
"agentId",
|
|
14793
|
+
"agent_id",
|
|
14794
|
+
"encodingFormat",
|
|
14795
|
+
"encoding_format",
|
|
14796
|
+
"frequencyPenalty",
|
|
14797
|
+
"frequency_penalty",
|
|
14798
|
+
"maxTokens",
|
|
14799
|
+
"max_tokens",
|
|
14800
|
+
"model",
|
|
14801
|
+
"n",
|
|
14802
|
+
"presencePenalty",
|
|
14803
|
+
"presence_penalty",
|
|
14804
|
+
"randomSeed",
|
|
14805
|
+
"random_seed",
|
|
14806
|
+
"responseFormat",
|
|
14807
|
+
"response_format",
|
|
14808
|
+
"safePrompt",
|
|
14809
|
+
"safe_prompt",
|
|
14810
|
+
"stream",
|
|
14811
|
+
"stop",
|
|
14812
|
+
"temperature",
|
|
14813
|
+
"toolChoice",
|
|
14814
|
+
"tool_choice",
|
|
14815
|
+
"topP",
|
|
14816
|
+
"top_p"
|
|
14817
|
+
]);
|
|
14818
|
+
var MISTRAL_RESPONSE_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
|
|
14819
|
+
"agentId",
|
|
14820
|
+
"agent_id",
|
|
14821
|
+
"created",
|
|
14822
|
+
"id",
|
|
14823
|
+
"model",
|
|
14824
|
+
"object"
|
|
14825
|
+
]);
|
|
14826
|
+
function camelToSnake3(value) {
|
|
14827
|
+
return value.replace(/[A-Z]/g, (match) => `_${match.toLowerCase()}`);
|
|
14828
|
+
}
|
|
14829
|
+
function normalizeArgs3(args) {
|
|
14830
|
+
if (Array.isArray(args)) {
|
|
14831
|
+
return args;
|
|
14832
|
+
}
|
|
14833
|
+
if (isArrayLike3(args)) {
|
|
14834
|
+
return Array.from(args);
|
|
14835
|
+
}
|
|
14836
|
+
return [args];
|
|
14837
|
+
}
|
|
14838
|
+
function isArrayLike3(value) {
|
|
14839
|
+
return isObject(value) && "length" in value && typeof value.length === "number" && Number.isInteger(value.length) && value.length >= 0;
|
|
14840
|
+
}
|
|
14841
|
+
function getMistralRequestArg(args) {
|
|
14842
|
+
const firstObjectArg = normalizeArgs3(args).find((arg) => isObject(arg));
|
|
14843
|
+
return isObject(firstObjectArg) ? firstObjectArg : void 0;
|
|
14844
|
+
}
|
|
14845
|
+
function addMistralProviderMetadata(metadata) {
|
|
14846
|
+
return {
|
|
14847
|
+
...metadata,
|
|
14848
|
+
provider: "mistral"
|
|
14849
|
+
};
|
|
14850
|
+
}
|
|
14851
|
+
function pickAllowedMetadata(metadata, allowlist) {
|
|
14852
|
+
if (!metadata) {
|
|
14853
|
+
return {};
|
|
14854
|
+
}
|
|
14855
|
+
const picked = {};
|
|
14856
|
+
for (const key of allowlist) {
|
|
14857
|
+
const value = metadata[key];
|
|
14858
|
+
if (value !== void 0) {
|
|
14859
|
+
picked[key] = value;
|
|
14860
|
+
}
|
|
14861
|
+
}
|
|
14862
|
+
return picked;
|
|
14863
|
+
}
|
|
14864
|
+
function extractMistralRequestMetadata(metadata) {
|
|
14865
|
+
return pickAllowedMetadata(metadata, MISTRAL_REQUEST_METADATA_ALLOWLIST);
|
|
14866
|
+
}
|
|
14867
|
+
function isMistralChatCompletionChunk(value) {
|
|
14868
|
+
return isObject(value);
|
|
14869
|
+
}
|
|
14870
|
+
function isMistralChunkChoice(value) {
|
|
14871
|
+
return isObject(value);
|
|
14872
|
+
}
|
|
14873
|
+
function extractMessagesInputWithMetadata(args) {
|
|
14874
|
+
const params = getMistralRequestArg(args);
|
|
14875
|
+
const { messages, ...rawMetadata } = params || {};
|
|
14876
|
+
return {
|
|
14877
|
+
input: processInputAttachments(messages),
|
|
14878
|
+
metadata: addMistralProviderMetadata(
|
|
14879
|
+
extractMistralRequestMetadata(rawMetadata)
|
|
14880
|
+
)
|
|
14881
|
+
};
|
|
14882
|
+
}
|
|
14883
|
+
function extractEmbeddingInputWithMetadata(args) {
|
|
14884
|
+
const params = getMistralRequestArg(args);
|
|
14885
|
+
const { inputs, ...rawMetadata } = params || {};
|
|
14886
|
+
return {
|
|
14887
|
+
input: inputs,
|
|
14888
|
+
metadata: addMistralProviderMetadata(
|
|
14889
|
+
extractMistralRequestMetadata(rawMetadata)
|
|
14890
|
+
)
|
|
14891
|
+
};
|
|
14892
|
+
}
|
|
14893
|
+
function extractPromptInputWithMetadata(args) {
|
|
14894
|
+
const params = getMistralRequestArg(args);
|
|
14895
|
+
const { prompt, ...rawMetadata } = params || {};
|
|
14896
|
+
return {
|
|
14897
|
+
input: prompt,
|
|
14898
|
+
metadata: addMistralProviderMetadata(
|
|
14899
|
+
extractMistralRequestMetadata(rawMetadata)
|
|
14900
|
+
)
|
|
14901
|
+
};
|
|
14902
|
+
}
|
|
14903
|
+
function extractMistralResponseMetadata(result) {
|
|
14904
|
+
if (!isObject(result)) {
|
|
14905
|
+
return void 0;
|
|
14906
|
+
}
|
|
14907
|
+
const { choices: _choices, usage: _usage, data: _data, ...metadata } = result;
|
|
14908
|
+
const picked = pickAllowedMetadata(
|
|
14909
|
+
metadata,
|
|
14910
|
+
MISTRAL_RESPONSE_METADATA_ALLOWLIST
|
|
14911
|
+
);
|
|
14912
|
+
return Object.keys(picked).length > 0 ? picked : void 0;
|
|
14913
|
+
}
|
|
14914
|
+
function extractMistralMetrics(usage, startTime) {
|
|
14915
|
+
const metrics = parseMistralMetricsFromUsage(usage);
|
|
14916
|
+
if (startTime) {
|
|
14917
|
+
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
14918
|
+
}
|
|
14919
|
+
return metrics;
|
|
14920
|
+
}
|
|
14921
|
+
function extractMistralStreamOutput(result) {
|
|
14922
|
+
return isObject(result) ? result.choices : void 0;
|
|
14923
|
+
}
|
|
14924
|
+
function extractMistralStreamingMetrics(result, startTime) {
|
|
14925
|
+
const metrics = isObject(result) ? parseMistralMetricsFromUsage(result.usage) : {};
|
|
14926
|
+
if (startTime) {
|
|
14927
|
+
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
14928
|
+
}
|
|
14929
|
+
return metrics;
|
|
14930
|
+
}
|
|
14931
|
+
function extractDeltaText(content) {
|
|
14932
|
+
if (typeof content === "string") {
|
|
14933
|
+
return content;
|
|
14934
|
+
}
|
|
14935
|
+
if (!Array.isArray(content)) {
|
|
14936
|
+
return void 0;
|
|
14937
|
+
}
|
|
14938
|
+
const textParts = content.map((part) => {
|
|
14939
|
+
if (!isObject(part) || part.type !== "text") {
|
|
14940
|
+
return "";
|
|
14941
|
+
}
|
|
14942
|
+
return typeof part.text === "string" ? part.text : "";
|
|
14943
|
+
}).filter((part) => part.length > 0);
|
|
14944
|
+
return textParts.length > 0 ? textParts.join("") : void 0;
|
|
14945
|
+
}
|
|
14946
|
+
function getDeltaToolCalls(delta) {
|
|
14947
|
+
const toolCalls = Array.isArray(delta.toolCalls) && delta.toolCalls || Array.isArray(delta.tool_calls) && delta.tool_calls || [];
|
|
14948
|
+
return toolCalls.filter((toolCall) => isObject(toolCall));
|
|
14949
|
+
}
|
|
14950
|
+
function getToolCallIndex(toolCall) {
|
|
14951
|
+
return typeof toolCall.index === "number" && toolCall.index >= 0 ? toolCall.index : void 0;
|
|
14952
|
+
}
|
|
14953
|
+
function createMergedToolCallDelta(delta) {
|
|
14954
|
+
return {
|
|
14955
|
+
...delta,
|
|
14956
|
+
function: {
|
|
14957
|
+
...delta.function,
|
|
14958
|
+
arguments: typeof delta.function?.arguments === "string" ? delta.function.arguments : ""
|
|
14959
|
+
}
|
|
14960
|
+
};
|
|
14961
|
+
}
|
|
14962
|
+
function mergeToolCallDeltaPair(current, delta) {
|
|
14963
|
+
const currentArguments = typeof current.function?.arguments === "string" ? current.function.arguments : "";
|
|
14964
|
+
const deltaArguments = typeof delta.function?.arguments === "string" ? delta.function.arguments : "";
|
|
14965
|
+
return {
|
|
14966
|
+
...current,
|
|
14967
|
+
...delta,
|
|
14968
|
+
function: {
|
|
14969
|
+
...current.function || {},
|
|
14970
|
+
...delta.function || {},
|
|
14971
|
+
arguments: `${currentArguments}${deltaArguments}`
|
|
14972
|
+
}
|
|
14973
|
+
};
|
|
14974
|
+
}
|
|
14975
|
+
function mergeToolCallDeltas(toolCalls, deltas) {
|
|
14976
|
+
if (deltas.length === 0) {
|
|
14977
|
+
return toolCalls;
|
|
14978
|
+
}
|
|
14979
|
+
const merged = toolCalls ? [...toolCalls] : [];
|
|
14980
|
+
const indexToPosition = /* @__PURE__ */ new Map();
|
|
14981
|
+
const idToPosition = /* @__PURE__ */ new Map();
|
|
14982
|
+
for (const [position, toolCall] of merged.entries()) {
|
|
14983
|
+
const index = getToolCallIndex(toolCall);
|
|
14984
|
+
if (index !== void 0 && !indexToPosition.has(index)) {
|
|
14985
|
+
indexToPosition.set(index, position);
|
|
14986
|
+
}
|
|
14987
|
+
if (typeof toolCall.id === "string" && !idToPosition.has(toolCall.id)) {
|
|
14988
|
+
idToPosition.set(toolCall.id, position);
|
|
14989
|
+
}
|
|
14990
|
+
}
|
|
14991
|
+
for (const delta of deltas) {
|
|
14992
|
+
const deltaIndex = getToolCallIndex(delta);
|
|
14993
|
+
const existingByIndex = deltaIndex !== void 0 ? indexToPosition.get(deltaIndex) : void 0;
|
|
14994
|
+
const existingById = typeof delta.id === "string" ? idToPosition.get(delta.id) : void 0;
|
|
14995
|
+
const existingPosition = existingByIndex ?? existingById;
|
|
14996
|
+
if (existingPosition === void 0) {
|
|
14997
|
+
const newToolCall = createMergedToolCallDelta(delta);
|
|
14998
|
+
merged.push(newToolCall);
|
|
14999
|
+
const newPosition = merged.length - 1;
|
|
15000
|
+
const newIndex = getToolCallIndex(newToolCall);
|
|
15001
|
+
if (newIndex !== void 0 && !indexToPosition.has(newIndex)) {
|
|
15002
|
+
indexToPosition.set(newIndex, newPosition);
|
|
15003
|
+
}
|
|
15004
|
+
if (typeof newToolCall.id === "string" && !idToPosition.has(newToolCall.id)) {
|
|
15005
|
+
idToPosition.set(newToolCall.id, newPosition);
|
|
15006
|
+
}
|
|
12647
15007
|
continue;
|
|
12648
15008
|
}
|
|
12649
|
-
|
|
12650
|
-
|
|
15009
|
+
const mergedToolCall = mergeToolCallDeltaPair(
|
|
15010
|
+
merged[existingPosition],
|
|
15011
|
+
delta
|
|
15012
|
+
);
|
|
15013
|
+
merged[existingPosition] = mergedToolCall;
|
|
15014
|
+
const mergedIndex = getToolCallIndex(mergedToolCall);
|
|
15015
|
+
if (mergedIndex !== void 0 && !indexToPosition.has(mergedIndex)) {
|
|
15016
|
+
indexToPosition.set(mergedIndex, existingPosition);
|
|
15017
|
+
}
|
|
15018
|
+
if (typeof mergedToolCall.id === "string" && !idToPosition.has(mergedToolCall.id)) {
|
|
15019
|
+
idToPosition.set(mergedToolCall.id, existingPosition);
|
|
12651
15020
|
}
|
|
12652
15021
|
}
|
|
12653
|
-
|
|
12654
|
-
|
|
12655
|
-
|
|
12656
|
-
|
|
12657
|
-
|
|
15022
|
+
return merged.length > 0 ? merged : void 0;
|
|
15023
|
+
}
|
|
15024
|
+
function getChoiceFinishReason(choice) {
|
|
15025
|
+
if (typeof choice.finishReason === "string" || choice.finishReason === null) {
|
|
15026
|
+
return choice.finishReason;
|
|
15027
|
+
}
|
|
15028
|
+
if (typeof choice.finish_reason === "string" || choice.finish_reason === null) {
|
|
15029
|
+
return choice.finish_reason;
|
|
15030
|
+
}
|
|
15031
|
+
return void 0;
|
|
15032
|
+
}
|
|
15033
|
+
function parseMistralMetricsFromUsage(usage) {
|
|
15034
|
+
if (!isObject(usage)) {
|
|
15035
|
+
return {};
|
|
15036
|
+
}
|
|
15037
|
+
const metrics = {};
|
|
15038
|
+
for (const [name, value] of Object.entries(usage)) {
|
|
15039
|
+
if (typeof value === "number") {
|
|
15040
|
+
metrics[TOKEN_NAME_MAP4[name] || camelToSnake3(name)] = value;
|
|
15041
|
+
continue;
|
|
15042
|
+
}
|
|
15043
|
+
if (!isObject(value)) {
|
|
15044
|
+
continue;
|
|
15045
|
+
}
|
|
15046
|
+
const prefix = TOKEN_DETAIL_PREFIX_MAP3[name];
|
|
15047
|
+
if (!prefix) {
|
|
15048
|
+
continue;
|
|
15049
|
+
}
|
|
15050
|
+
for (const [nestedName, nestedValue] of Object.entries(value)) {
|
|
15051
|
+
if (typeof nestedValue !== "number") {
|
|
15052
|
+
continue;
|
|
15053
|
+
}
|
|
15054
|
+
metrics[`${prefix}_${camelToSnake3(nestedName)}`] = nestedValue;
|
|
15055
|
+
}
|
|
15056
|
+
}
|
|
15057
|
+
return metrics;
|
|
15058
|
+
}
|
|
15059
|
+
function aggregateMistralStreamChunks(chunks) {
|
|
15060
|
+
const choiceAccumulators = /* @__PURE__ */ new Map();
|
|
15061
|
+
const indexToAccumulatorKey = /* @__PURE__ */ new Map();
|
|
15062
|
+
const positionToAccumulatorKey = /* @__PURE__ */ new Map();
|
|
15063
|
+
let nextAccumulatorOrder = 0;
|
|
15064
|
+
let metrics = {};
|
|
15065
|
+
let metadata;
|
|
15066
|
+
for (const event of chunks) {
|
|
15067
|
+
const chunk = isMistralChatCompletionChunk(event?.data) ? event.data : void 0;
|
|
15068
|
+
if (!chunk) {
|
|
15069
|
+
continue;
|
|
15070
|
+
}
|
|
15071
|
+
if (isObject(chunk.usage)) {
|
|
15072
|
+
metrics = {
|
|
15073
|
+
...metrics,
|
|
15074
|
+
...parseMistralMetricsFromUsage(chunk.usage)
|
|
15075
|
+
};
|
|
15076
|
+
}
|
|
15077
|
+
const chunkMetadata = extractMistralResponseMetadata(chunk);
|
|
15078
|
+
if (chunkMetadata) {
|
|
15079
|
+
metadata = { ...metadata || {}, ...chunkMetadata };
|
|
15080
|
+
}
|
|
15081
|
+
for (const [choicePosition, rawChoice] of (chunk.choices || []).entries()) {
|
|
15082
|
+
if (!isMistralChunkChoice(rawChoice)) {
|
|
15083
|
+
continue;
|
|
15084
|
+
}
|
|
15085
|
+
const choice = rawChoice;
|
|
15086
|
+
const choiceIndex = typeof choice.index === "number" && choice.index >= 0 ? choice.index : void 0;
|
|
15087
|
+
let accumulatorKey = choiceIndex !== void 0 ? indexToAccumulatorKey.get(choiceIndex) : void 0;
|
|
15088
|
+
if (!accumulatorKey) {
|
|
15089
|
+
accumulatorKey = positionToAccumulatorKey.get(choicePosition);
|
|
15090
|
+
}
|
|
15091
|
+
if (!accumulatorKey) {
|
|
15092
|
+
const initialIndex = choiceIndex ?? choicePosition;
|
|
15093
|
+
const keyPrefix = choiceIndex !== void 0 ? "index" : "position";
|
|
15094
|
+
accumulatorKey = `${keyPrefix}:${initialIndex}`;
|
|
15095
|
+
choiceAccumulators.set(accumulatorKey, {
|
|
15096
|
+
index: initialIndex,
|
|
15097
|
+
order: nextAccumulatorOrder++
|
|
15098
|
+
});
|
|
15099
|
+
}
|
|
15100
|
+
const accumulator = choiceAccumulators.get(accumulatorKey);
|
|
15101
|
+
if (!accumulator) {
|
|
15102
|
+
continue;
|
|
15103
|
+
}
|
|
15104
|
+
if (choiceIndex !== void 0) {
|
|
15105
|
+
accumulator.index = choiceIndex;
|
|
15106
|
+
indexToAccumulatorKey.set(choiceIndex, accumulatorKey);
|
|
15107
|
+
}
|
|
15108
|
+
positionToAccumulatorKey.set(choicePosition, accumulatorKey);
|
|
15109
|
+
const delta = isObject(choice.delta) ? choice.delta : void 0;
|
|
15110
|
+
if (delta) {
|
|
15111
|
+
if (!accumulator.role && typeof delta.role === "string") {
|
|
15112
|
+
accumulator.role = delta.role;
|
|
15113
|
+
}
|
|
15114
|
+
const deltaText = extractDeltaText(delta.content);
|
|
15115
|
+
if (deltaText) {
|
|
15116
|
+
accumulator.content = `${accumulator.content || ""}${deltaText}`;
|
|
15117
|
+
}
|
|
15118
|
+
accumulator.toolCalls = mergeToolCallDeltas(
|
|
15119
|
+
accumulator.toolCalls,
|
|
15120
|
+
getDeltaToolCalls(delta)
|
|
15121
|
+
);
|
|
15122
|
+
}
|
|
15123
|
+
const choiceFinishReason = getChoiceFinishReason(choice);
|
|
15124
|
+
if (choiceFinishReason !== void 0) {
|
|
15125
|
+
accumulator.finishReason = choiceFinishReason;
|
|
15126
|
+
}
|
|
15127
|
+
}
|
|
12658
15128
|
}
|
|
15129
|
+
const output = Array.from(choiceAccumulators.values()).sort(
|
|
15130
|
+
(left, right) => left.index === right.index ? left.order - right.order : left.index - right.index
|
|
15131
|
+
).map((choice) => ({
|
|
15132
|
+
index: choice.index,
|
|
15133
|
+
message: {
|
|
15134
|
+
...choice.role ? { role: choice.role } : {},
|
|
15135
|
+
content: choice.content ?? null,
|
|
15136
|
+
...choice.toolCalls ? { toolCalls: choice.toolCalls } : {}
|
|
15137
|
+
},
|
|
15138
|
+
...choice.finishReason !== void 0 ? { finishReason: choice.finishReason } : {}
|
|
15139
|
+
}));
|
|
12659
15140
|
return {
|
|
12660
|
-
output
|
|
12661
|
-
metrics
|
|
12662
|
-
...
|
|
15141
|
+
output,
|
|
15142
|
+
metrics,
|
|
15143
|
+
...metadata ? { metadata } : {}
|
|
12663
15144
|
};
|
|
12664
15145
|
}
|
|
12665
15146
|
|
|
@@ -12672,6 +15153,8 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
12672
15153
|
claudeAgentSDKPlugin = null;
|
|
12673
15154
|
googleGenAIPlugin = null;
|
|
12674
15155
|
openRouterPlugin = null;
|
|
15156
|
+
openRouterAgentPlugin = null;
|
|
15157
|
+
mistralPlugin = null;
|
|
12675
15158
|
constructor(config = {}) {
|
|
12676
15159
|
super();
|
|
12677
15160
|
this.config = config;
|
|
@@ -12702,6 +15185,14 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
12702
15185
|
this.openRouterPlugin = new OpenRouterPlugin();
|
|
12703
15186
|
this.openRouterPlugin.enable();
|
|
12704
15187
|
}
|
|
15188
|
+
if (integrations.openrouterAgent !== false) {
|
|
15189
|
+
this.openRouterAgentPlugin = new OpenRouterAgentPlugin();
|
|
15190
|
+
this.openRouterAgentPlugin.enable();
|
|
15191
|
+
}
|
|
15192
|
+
if (integrations.mistral !== false) {
|
|
15193
|
+
this.mistralPlugin = new MistralPlugin();
|
|
15194
|
+
this.mistralPlugin.enable();
|
|
15195
|
+
}
|
|
12705
15196
|
}
|
|
12706
15197
|
onDisable() {
|
|
12707
15198
|
if (this.openaiPlugin) {
|
|
@@ -12728,6 +15219,14 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
12728
15219
|
this.openRouterPlugin.disable();
|
|
12729
15220
|
this.openRouterPlugin = null;
|
|
12730
15221
|
}
|
|
15222
|
+
if (this.openRouterAgentPlugin) {
|
|
15223
|
+
this.openRouterAgentPlugin.disable();
|
|
15224
|
+
this.openRouterAgentPlugin = null;
|
|
15225
|
+
}
|
|
15226
|
+
if (this.mistralPlugin) {
|
|
15227
|
+
this.mistralPlugin.disable();
|
|
15228
|
+
this.mistralPlugin = null;
|
|
15229
|
+
}
|
|
12731
15230
|
}
|
|
12732
15231
|
};
|
|
12733
15232
|
|
|
@@ -12800,7 +15299,9 @@ var PluginRegistry = class {
|
|
|
12800
15299
|
aisdk: true,
|
|
12801
15300
|
google: true,
|
|
12802
15301
|
claudeAgentSDK: true,
|
|
12803
|
-
openrouter: true
|
|
15302
|
+
openrouter: true,
|
|
15303
|
+
openrouterAgent: true,
|
|
15304
|
+
mistral: true
|
|
12804
15305
|
};
|
|
12805
15306
|
}
|
|
12806
15307
|
/**
|