braintrust 3.4.0 → 3.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dev/dist/index.d.mts +49 -7
- package/dev/dist/index.d.ts +49 -7
- package/dev/dist/index.js +2383 -494
- package/dev/dist/index.mjs +2213 -324
- package/dist/auto-instrumentations/bundler/esbuild.cjs +289 -10
- package/dist/auto-instrumentations/bundler/esbuild.d.mts +2 -2
- package/dist/auto-instrumentations/bundler/esbuild.d.ts +2 -2
- package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
- package/dist/auto-instrumentations/bundler/rollup.cjs +289 -10
- package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
- package/dist/auto-instrumentations/bundler/vite.cjs +289 -10
- package/dist/auto-instrumentations/bundler/vite.d.mts +2 -2
- package/dist/auto-instrumentations/bundler/vite.d.ts +2 -2
- package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
- package/dist/auto-instrumentations/bundler/webpack.cjs +289 -10
- package/dist/auto-instrumentations/bundler/webpack.d.mts +2 -2
- package/dist/auto-instrumentations/bundler/webpack.d.ts +2 -2
- package/dist/auto-instrumentations/bundler/webpack.mjs +2 -2
- package/dist/auto-instrumentations/chunk-EVUKFMHG.mjs +41 -0
- package/dist/auto-instrumentations/{chunk-LVWWLUMN.mjs → chunk-F7WAXFNM.mjs} +290 -11
- package/dist/auto-instrumentations/chunk-VLEJ5AEK.mjs +41 -0
- package/dist/auto-instrumentations/{chunk-D5ZPIUEL.mjs → chunk-WOUC73KB.mjs} +3 -1
- package/dist/auto-instrumentations/hook.mjs +358 -48
- package/dist/auto-instrumentations/index.cjs +290 -10
- package/dist/auto-instrumentations/index.d.mts +3 -1
- package/dist/auto-instrumentations/index.d.ts +3 -1
- package/dist/auto-instrumentations/index.mjs +3 -1
- package/dist/auto-instrumentations/loader/cjs-patch.cjs +32 -10
- package/dist/auto-instrumentations/loader/cjs-patch.mjs +10 -5
- package/dist/auto-instrumentations/loader/esm-hook.mjs +4 -4
- package/dist/auto-instrumentations/loader/get-package-version.cjs +28 -8
- package/dist/auto-instrumentations/loader/get-package-version.d.mts +2 -1
- package/dist/auto-instrumentations/loader/get-package-version.d.ts +2 -1
- package/dist/auto-instrumentations/loader/get-package-version.mjs +3 -1
- package/dist/browser.d.mts +357 -271
- package/dist/browser.d.ts +357 -271
- package/dist/browser.js +2345 -343
- package/dist/browser.mjs +2345 -343
- package/dist/cli.js +2296 -414
- package/dist/edge-light.d.mts +1 -1
- package/dist/edge-light.d.ts +1 -1
- package/dist/edge-light.js +2292 -315
- package/dist/edge-light.mjs +2292 -315
- package/dist/index.d.mts +370 -284
- package/dist/index.d.ts +370 -284
- package/dist/index.js +2642 -638
- package/dist/index.mjs +2385 -381
- package/dist/instrumentation/index.d.mts +3 -0
- package/dist/instrumentation/index.d.ts +3 -0
- package/dist/instrumentation/index.js +1955 -198
- package/dist/instrumentation/index.mjs +1955 -198
- package/dist/workerd.d.mts +1 -1
- package/dist/workerd.d.ts +1 -1
- package/dist/workerd.js +2292 -315
- package/dist/workerd.mjs +2292 -315
- package/package.json +22 -6
- package/dist/auto-instrumentations/chunk-XDBPUTVE.mjs +0 -22
- package/dist/auto-instrumentations/chunk-ZEC7BCL4.mjs +0 -22
|
@@ -52,8 +52,54 @@ var DefaultAsyncLocalStorage = class {
|
|
|
52
52
|
return void 0;
|
|
53
53
|
}
|
|
54
54
|
};
|
|
55
|
-
var
|
|
55
|
+
var DefaultChannel = class {
|
|
56
|
+
constructor(name) {
|
|
57
|
+
this.name = name;
|
|
58
|
+
}
|
|
56
59
|
hasSubscribers = false;
|
|
60
|
+
subscribe(_subscription) {
|
|
61
|
+
}
|
|
62
|
+
unsubscribe(_subscription) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
bindStore(_store, _transform) {
|
|
66
|
+
}
|
|
67
|
+
unbindStore(_store) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
publish(_message) {
|
|
71
|
+
}
|
|
72
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
73
|
+
runStores(_message, fn, thisArg, ...args) {
|
|
74
|
+
return fn.apply(thisArg, args);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
var DefaultTracingChannel = class {
|
|
78
|
+
start;
|
|
79
|
+
end;
|
|
80
|
+
asyncStart;
|
|
81
|
+
asyncEnd;
|
|
82
|
+
error;
|
|
83
|
+
constructor(nameOrChannels) {
|
|
84
|
+
if (typeof nameOrChannels === "string") {
|
|
85
|
+
this.start = new DefaultChannel(`tracing:${nameOrChannels}:start`);
|
|
86
|
+
this.end = new DefaultChannel(`tracing:${nameOrChannels}:end`);
|
|
87
|
+
this.asyncStart = new DefaultChannel(
|
|
88
|
+
`tracing:${nameOrChannels}:asyncStart`
|
|
89
|
+
);
|
|
90
|
+
this.asyncEnd = new DefaultChannel(`tracing:${nameOrChannels}:asyncEnd`);
|
|
91
|
+
this.error = new DefaultChannel(`tracing:${nameOrChannels}:error`);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
this.start = nameOrChannels.start ?? new DefaultChannel("tracing:start");
|
|
95
|
+
this.end = nameOrChannels.end ?? new DefaultChannel("tracing:end");
|
|
96
|
+
this.asyncStart = nameOrChannels.asyncStart ?? new DefaultChannel("tracing:asyncStart");
|
|
97
|
+
this.asyncEnd = nameOrChannels.asyncEnd ?? new DefaultChannel("tracing:asyncEnd");
|
|
98
|
+
this.error = nameOrChannels.error ?? new DefaultChannel("tracing:error");
|
|
99
|
+
}
|
|
100
|
+
get hasSubscribers() {
|
|
101
|
+
return this.start.hasSubscribers || this.end.hasSubscribers || this.asyncStart.hasSubscribers || this.asyncEnd.hasSubscribers || this.error.hasSubscribers;
|
|
102
|
+
}
|
|
57
103
|
subscribe(_handlers) {
|
|
58
104
|
}
|
|
59
105
|
unsubscribe(_handlers) {
|
|
@@ -81,7 +127,7 @@ var iso = {
|
|
|
81
127
|
getCallerLocation: () => void 0,
|
|
82
128
|
newAsyncLocalStorage: () => new DefaultAsyncLocalStorage(),
|
|
83
129
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
84
|
-
newTracingChannel: (
|
|
130
|
+
newTracingChannel: (nameOrChannels) => new DefaultTracingChannel(nameOrChannels),
|
|
85
131
|
processOn: (_0, _1) => {
|
|
86
132
|
},
|
|
87
133
|
basename: (filepath) => filepath.split(/[\\/]/).pop() || filepath,
|
|
@@ -2115,6 +2161,8 @@ var Experiment = import_v36.z.object({
|
|
|
2115
2161
|
deleted_at: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
|
|
2116
2162
|
dataset_id: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
|
|
2117
2163
|
dataset_version: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
|
|
2164
|
+
parameters_id: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
|
|
2165
|
+
parameters_version: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
|
|
2118
2166
|
public: import_v36.z.boolean(),
|
|
2119
2167
|
user_id: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
|
|
2120
2168
|
metadata: import_v36.z.union([import_v36.z.object({}).partial().passthrough(), import_v36.z.null()]).optional(),
|
|
@@ -2137,7 +2185,11 @@ var SpanType = import_v36.z.union([
|
|
|
2137
2185
|
import_v36.z.null()
|
|
2138
2186
|
]);
|
|
2139
2187
|
var SpanAttributes = import_v36.z.union([
|
|
2140
|
-
import_v36.z.object({
|
|
2188
|
+
import_v36.z.object({
|
|
2189
|
+
name: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]),
|
|
2190
|
+
type: SpanType,
|
|
2191
|
+
purpose: import_v36.z.union([import_v36.z.literal("scorer"), import_v36.z.null()])
|
|
2192
|
+
}).partial().passthrough(),
|
|
2141
2193
|
import_v36.z.null()
|
|
2142
2194
|
]);
|
|
2143
2195
|
var ExperimentEvent = import_v36.z.object({
|
|
@@ -2577,6 +2629,7 @@ var FunctionId = import_v36.z.union([
|
|
|
2577
2629
|
version: import_v36.z.string()
|
|
2578
2630
|
}),
|
|
2579
2631
|
code: import_v36.z.string(),
|
|
2632
|
+
function_type: FunctionTypeEnum.and(import_v36.z.unknown()).optional(),
|
|
2580
2633
|
name: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional()
|
|
2581
2634
|
}),
|
|
2582
2635
|
import_v36.z.object({
|
|
@@ -2806,7 +2859,12 @@ var TopicAutomationConfig = import_v36.z.object({
|
|
|
2806
2859
|
topic_map_functions: import_v36.z.array(TopicMapFunctionAutomation),
|
|
2807
2860
|
scope: import_v36.z.union([SpanScope, TraceScope, GroupScope, import_v36.z.null()]).optional(),
|
|
2808
2861
|
data_scope: TopicAutomationDataScope.optional(),
|
|
2809
|
-
btql_filter: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional()
|
|
2862
|
+
btql_filter: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
|
|
2863
|
+
backfill_time_range: import_v36.z.union([
|
|
2864
|
+
import_v36.z.string(),
|
|
2865
|
+
import_v36.z.object({ from: import_v36.z.string(), to: import_v36.z.string() }),
|
|
2866
|
+
import_v36.z.null()
|
|
2867
|
+
]).optional()
|
|
2810
2868
|
});
|
|
2811
2869
|
var ProjectAutomation = import_v36.z.object({
|
|
2812
2870
|
id: import_v36.z.string().uuid(),
|
|
@@ -4199,6 +4257,9 @@ var BRAINTRUST_ATTACHMENT = BraintrustAttachmentReference.shape.type.value;
|
|
|
4199
4257
|
var EXTERNAL_ATTACHMENT = ExternalAttachmentReference.shape.type.value;
|
|
4200
4258
|
var LOGS3_OVERFLOW_REFERENCE_TYPE = "logs3_overflow";
|
|
4201
4259
|
var BRAINTRUST_PARAMS = Object.keys(BraintrustModelParams.shape);
|
|
4260
|
+
var RESET_CONTEXT_MANAGER_STATE = Symbol.for(
|
|
4261
|
+
"braintrust.resetContextManagerState"
|
|
4262
|
+
);
|
|
4202
4263
|
var DEFAULT_MAX_REQUEST_SIZE = 6 * 1024 * 1024;
|
|
4203
4264
|
var parametersRowSchema = import_v38.z.object({
|
|
4204
4265
|
id: import_v38.z.string().uuid(),
|
|
@@ -4215,6 +4276,12 @@ var parametersRowSchema = import_v38.z.object({
|
|
|
4215
4276
|
}),
|
|
4216
4277
|
metadata: import_v38.z.union([import_v38.z.object({}).partial().passthrough(), import_v38.z.null()]).optional()
|
|
4217
4278
|
});
|
|
4279
|
+
var InlineAttachmentReferenceSchema = import_v38.z.object({
|
|
4280
|
+
type: import_v38.z.literal("inline_attachment"),
|
|
4281
|
+
src: import_v38.z.string().min(1),
|
|
4282
|
+
content_type: import_v38.z.string().optional(),
|
|
4283
|
+
filename: import_v38.z.string().optional()
|
|
4284
|
+
});
|
|
4218
4285
|
var LoginInvalidOrgError = class extends Error {
|
|
4219
4286
|
constructor(message) {
|
|
4220
4287
|
super(message);
|
|
@@ -4255,13 +4322,18 @@ function applyMaskingToField(maskingFunction, data, fieldName) {
|
|
|
4255
4322
|
return `ERROR: Failed to mask field '${fieldName}' - ${errorType}`;
|
|
4256
4323
|
}
|
|
4257
4324
|
}
|
|
4325
|
+
var BRAINTRUST_CURRENT_SPAN_STORE = Symbol.for(
|
|
4326
|
+
"braintrust.currentSpanStore"
|
|
4327
|
+
);
|
|
4258
4328
|
var ContextManager = class {
|
|
4259
4329
|
};
|
|
4260
4330
|
var BraintrustContextManager = class extends ContextManager {
|
|
4261
4331
|
_currentSpan;
|
|
4332
|
+
[BRAINTRUST_CURRENT_SPAN_STORE];
|
|
4262
4333
|
constructor() {
|
|
4263
4334
|
super();
|
|
4264
4335
|
this._currentSpan = isomorph_default.newAsyncLocalStorage();
|
|
4336
|
+
this[BRAINTRUST_CURRENT_SPAN_STORE] = this._currentSpan;
|
|
4265
4337
|
}
|
|
4266
4338
|
getParentSpanIds() {
|
|
4267
4339
|
const currentSpan2 = this._currentSpan.getStore();
|
|
@@ -4468,6 +4540,9 @@ var BraintrustState = class _BraintrustState {
|
|
|
4468
4540
|
resetIdGenState() {
|
|
4469
4541
|
this._idGenerator = null;
|
|
4470
4542
|
}
|
|
4543
|
+
[RESET_CONTEXT_MANAGER_STATE]() {
|
|
4544
|
+
this._contextManager = null;
|
|
4545
|
+
}
|
|
4471
4546
|
get idGenerator() {
|
|
4472
4547
|
if (this._idGenerator === null) {
|
|
4473
4548
|
this._idGenerator = getIdGenerator();
|
|
@@ -8017,7 +8092,11 @@ function startSpanForEvent(config, event, channelName) {
|
|
|
8017
8092
|
});
|
|
8018
8093
|
const startTime = getCurrentUnixTimestamp();
|
|
8019
8094
|
try {
|
|
8020
|
-
const { input, metadata } = config.extractInput(
|
|
8095
|
+
const { input, metadata } = config.extractInput(
|
|
8096
|
+
event.arguments,
|
|
8097
|
+
event,
|
|
8098
|
+
span
|
|
8099
|
+
);
|
|
8021
8100
|
span.log({
|
|
8022
8101
|
input,
|
|
8023
8102
|
metadata: mergeInputMetadata(metadata, spanInfoMetadata)
|
|
@@ -8027,6 +8106,36 @@ function startSpanForEvent(config, event, channelName) {
|
|
|
8027
8106
|
}
|
|
8028
8107
|
return { span, startTime };
|
|
8029
8108
|
}
|
|
8109
|
+
function ensureSpanStateForEvent(states, config, event, channelName) {
|
|
8110
|
+
const key = event;
|
|
8111
|
+
const existing = states.get(key);
|
|
8112
|
+
if (existing) {
|
|
8113
|
+
return existing;
|
|
8114
|
+
}
|
|
8115
|
+
const created = startSpanForEvent(config, event, channelName);
|
|
8116
|
+
states.set(key, created);
|
|
8117
|
+
return created;
|
|
8118
|
+
}
|
|
8119
|
+
function bindCurrentSpanStoreToStart(tracingChannel, states, config, channelName) {
|
|
8120
|
+
const state = _internalGetGlobalState();
|
|
8121
|
+
const startChannel = tracingChannel.start;
|
|
8122
|
+
const currentSpanStore = state?.contextManager ? state.contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
|
|
8123
|
+
if (!currentSpanStore || !startChannel) {
|
|
8124
|
+
return void 0;
|
|
8125
|
+
}
|
|
8126
|
+
startChannel.bindStore(
|
|
8127
|
+
currentSpanStore,
|
|
8128
|
+
(event) => ensureSpanStateForEvent(
|
|
8129
|
+
states,
|
|
8130
|
+
config,
|
|
8131
|
+
event,
|
|
8132
|
+
channelName
|
|
8133
|
+
).span
|
|
8134
|
+
);
|
|
8135
|
+
return () => {
|
|
8136
|
+
startChannel.unbindStore(currentSpanStore);
|
|
8137
|
+
};
|
|
8138
|
+
}
|
|
8030
8139
|
function logErrorAndEnd(states, event) {
|
|
8031
8140
|
const spanData = states.get(event);
|
|
8032
8141
|
if (!spanData) {
|
|
@@ -8042,15 +8151,19 @@ function traceAsyncChannel(channel2, config) {
|
|
|
8042
8151
|
const tracingChannel = channel2.tracingChannel();
|
|
8043
8152
|
const states = /* @__PURE__ */ new WeakMap();
|
|
8044
8153
|
const channelName = channel2.channelName;
|
|
8154
|
+
const unbindCurrentSpanStore = bindCurrentSpanStoreToStart(
|
|
8155
|
+
tracingChannel,
|
|
8156
|
+
states,
|
|
8157
|
+
config,
|
|
8158
|
+
channelName
|
|
8159
|
+
);
|
|
8045
8160
|
const handlers = {
|
|
8046
8161
|
start: (event) => {
|
|
8047
|
-
|
|
8162
|
+
ensureSpanStateForEvent(
|
|
8163
|
+
states,
|
|
8164
|
+
config,
|
|
8048
8165
|
event,
|
|
8049
|
-
|
|
8050
|
-
config,
|
|
8051
|
-
event,
|
|
8052
|
-
channelName
|
|
8053
|
-
)
|
|
8166
|
+
channelName
|
|
8054
8167
|
);
|
|
8055
8168
|
},
|
|
8056
8169
|
asyncEnd: (event) => {
|
|
@@ -8092,6 +8205,7 @@ function traceAsyncChannel(channel2, config) {
|
|
|
8092
8205
|
};
|
|
8093
8206
|
tracingChannel.subscribe(handlers);
|
|
8094
8207
|
return () => {
|
|
8208
|
+
unbindCurrentSpanStore?.();
|
|
8095
8209
|
tracingChannel.unsubscribe(handlers);
|
|
8096
8210
|
};
|
|
8097
8211
|
}
|
|
@@ -8099,15 +8213,19 @@ function traceStreamingChannel(channel2, config) {
|
|
|
8099
8213
|
const tracingChannel = channel2.tracingChannel();
|
|
8100
8214
|
const states = /* @__PURE__ */ new WeakMap();
|
|
8101
8215
|
const channelName = channel2.channelName;
|
|
8216
|
+
const unbindCurrentSpanStore = bindCurrentSpanStoreToStart(
|
|
8217
|
+
tracingChannel,
|
|
8218
|
+
states,
|
|
8219
|
+
config,
|
|
8220
|
+
channelName
|
|
8221
|
+
);
|
|
8102
8222
|
const handlers = {
|
|
8103
8223
|
start: (event) => {
|
|
8104
|
-
|
|
8224
|
+
ensureSpanStateForEvent(
|
|
8225
|
+
states,
|
|
8226
|
+
config,
|
|
8105
8227
|
event,
|
|
8106
|
-
|
|
8107
|
-
config,
|
|
8108
|
-
event,
|
|
8109
|
-
channelName
|
|
8110
|
-
)
|
|
8228
|
+
channelName
|
|
8111
8229
|
);
|
|
8112
8230
|
},
|
|
8113
8231
|
asyncEnd: (event) => {
|
|
@@ -8181,6 +8299,16 @@ function traceStreamingChannel(channel2, config) {
|
|
|
8181
8299
|
});
|
|
8182
8300
|
return;
|
|
8183
8301
|
}
|
|
8302
|
+
if (config.patchResult?.({
|
|
8303
|
+
channelName,
|
|
8304
|
+
endEvent: asyncEndEvent,
|
|
8305
|
+
result: asyncEndEvent.result,
|
|
8306
|
+
span,
|
|
8307
|
+
startTime
|
|
8308
|
+
})) {
|
|
8309
|
+
states.delete(event);
|
|
8310
|
+
return;
|
|
8311
|
+
}
|
|
8184
8312
|
try {
|
|
8185
8313
|
const output = config.extractOutput(
|
|
8186
8314
|
asyncEndEvent.result,
|
|
@@ -8213,6 +8341,7 @@ function traceStreamingChannel(channel2, config) {
|
|
|
8213
8341
|
};
|
|
8214
8342
|
tracingChannel.subscribe(handlers);
|
|
8215
8343
|
return () => {
|
|
8344
|
+
unbindCurrentSpanStore?.();
|
|
8216
8345
|
tracingChannel.unsubscribe(handlers);
|
|
8217
8346
|
};
|
|
8218
8347
|
}
|
|
@@ -8220,15 +8349,19 @@ function traceSyncStreamChannel(channel2, config) {
|
|
|
8220
8349
|
const tracingChannel = channel2.tracingChannel();
|
|
8221
8350
|
const states = /* @__PURE__ */ new WeakMap();
|
|
8222
8351
|
const channelName = channel2.channelName;
|
|
8352
|
+
const unbindCurrentSpanStore = bindCurrentSpanStoreToStart(
|
|
8353
|
+
tracingChannel,
|
|
8354
|
+
states,
|
|
8355
|
+
config,
|
|
8356
|
+
channelName
|
|
8357
|
+
);
|
|
8223
8358
|
const handlers = {
|
|
8224
8359
|
start: (event) => {
|
|
8225
|
-
|
|
8360
|
+
ensureSpanStateForEvent(
|
|
8361
|
+
states,
|
|
8362
|
+
config,
|
|
8226
8363
|
event,
|
|
8227
|
-
|
|
8228
|
-
config,
|
|
8229
|
-
event,
|
|
8230
|
-
channelName
|
|
8231
|
-
)
|
|
8364
|
+
channelName
|
|
8232
8365
|
);
|
|
8233
8366
|
},
|
|
8234
8367
|
end: (event) => {
|
|
@@ -8237,8 +8370,17 @@ function traceSyncStreamChannel(channel2, config) {
|
|
|
8237
8370
|
return;
|
|
8238
8371
|
}
|
|
8239
8372
|
const { span, startTime } = spanData;
|
|
8240
|
-
const
|
|
8241
|
-
|
|
8373
|
+
const endEvent = event;
|
|
8374
|
+
if (config.patchResult?.({
|
|
8375
|
+
channelName,
|
|
8376
|
+
endEvent,
|
|
8377
|
+
result: endEvent.result,
|
|
8378
|
+
span,
|
|
8379
|
+
startTime
|
|
8380
|
+
})) {
|
|
8381
|
+
return;
|
|
8382
|
+
}
|
|
8383
|
+
const stream = endEvent.result;
|
|
8242
8384
|
if (!isSyncStreamLike(stream)) {
|
|
8243
8385
|
span.end();
|
|
8244
8386
|
states.delete(event);
|
|
@@ -8308,6 +8450,7 @@ function traceSyncStreamChannel(channel2, config) {
|
|
|
8308
8450
|
};
|
|
8309
8451
|
tracingChannel.subscribe(handlers);
|
|
8310
8452
|
return () => {
|
|
8453
|
+
unbindCurrentSpanStore?.();
|
|
8311
8454
|
tracingChannel.unsubscribe(handlers);
|
|
8312
8455
|
};
|
|
8313
8456
|
}
|
|
@@ -9209,6 +9352,108 @@ function filterFrom(obj, fieldsToRemove) {
|
|
|
9209
9352
|
return result;
|
|
9210
9353
|
}
|
|
9211
9354
|
|
|
9355
|
+
// src/wrappers/ai-sdk/normalize-logged-output.ts
|
|
9356
|
+
var REMOVE_NORMALIZED_VALUE = Symbol("braintrust.ai-sdk.remove-normalized");
|
|
9357
|
+
function normalizeAISDKLoggedOutput(value) {
|
|
9358
|
+
const normalized = normalizeAISDKLoggedValue(value);
|
|
9359
|
+
return normalized === REMOVE_NORMALIZED_VALUE ? {} : normalized;
|
|
9360
|
+
}
|
|
9361
|
+
function normalizeAISDKLoggedValue(value, context = {}) {
|
|
9362
|
+
if (Array.isArray(value)) {
|
|
9363
|
+
return value.map((entry) => normalizeAISDKLoggedValue(entry, context)).filter((entry) => entry !== REMOVE_NORMALIZED_VALUE);
|
|
9364
|
+
}
|
|
9365
|
+
if (!value || typeof value !== "object") {
|
|
9366
|
+
return value;
|
|
9367
|
+
}
|
|
9368
|
+
const nextInProviderMetadata = context.inProviderMetadata || context.parentKey === "providerMetadata" || context.parentKey === "experimental_providerMetadata";
|
|
9369
|
+
const normalizedEntries = [];
|
|
9370
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
9371
|
+
if (key === "cachedPromptTokens" && entry === 0) {
|
|
9372
|
+
continue;
|
|
9373
|
+
}
|
|
9374
|
+
if (context.parentKey === "request" && key === "body" && entry === "<omitted>") {
|
|
9375
|
+
continue;
|
|
9376
|
+
}
|
|
9377
|
+
const normalizedEntry = normalizeAISDKLoggedValue(entry, {
|
|
9378
|
+
inProviderMetadata: nextInProviderMetadata,
|
|
9379
|
+
parentKey: key
|
|
9380
|
+
});
|
|
9381
|
+
if (normalizedEntry === REMOVE_NORMALIZED_VALUE) {
|
|
9382
|
+
continue;
|
|
9383
|
+
}
|
|
9384
|
+
normalizedEntries.push([key, normalizedEntry]);
|
|
9385
|
+
}
|
|
9386
|
+
if (normalizedEntries.length === 0) {
|
|
9387
|
+
if (context.parentKey === "request" || nextInProviderMetadata) {
|
|
9388
|
+
return REMOVE_NORMALIZED_VALUE;
|
|
9389
|
+
}
|
|
9390
|
+
return {};
|
|
9391
|
+
}
|
|
9392
|
+
return Object.fromEntries(normalizedEntries);
|
|
9393
|
+
}
|
|
9394
|
+
|
|
9395
|
+
// src/zod/utils.ts
|
|
9396
|
+
var import_zod_to_json_schema = require("zod-to-json-schema");
|
|
9397
|
+
var z42 = __toESM(require("zod/v4"));
|
|
9398
|
+
function isZodV4(zodObject) {
|
|
9399
|
+
return typeof zodObject === "object" && zodObject !== null && "_zod" in zodObject && zodObject._zod !== void 0;
|
|
9400
|
+
}
|
|
9401
|
+
function zodToJsonSchema(schema) {
|
|
9402
|
+
if (isZodV4(schema)) {
|
|
9403
|
+
return z42.toJSONSchema(schema, {
|
|
9404
|
+
target: "draft-7"
|
|
9405
|
+
});
|
|
9406
|
+
}
|
|
9407
|
+
return (0, import_zod_to_json_schema.zodToJsonSchema)(schema);
|
|
9408
|
+
}
|
|
9409
|
+
|
|
9410
|
+
// src/wrappers/ai-sdk/tool-serialization.ts
|
|
9411
|
+
function isZodSchema(value) {
|
|
9412
|
+
return value != null && typeof value === "object" && "_def" in value && typeof value._def === "object";
|
|
9413
|
+
}
|
|
9414
|
+
function serializeZodSchema(schema) {
|
|
9415
|
+
try {
|
|
9416
|
+
return zodToJsonSchema(schema);
|
|
9417
|
+
} catch {
|
|
9418
|
+
return {
|
|
9419
|
+
type: "object",
|
|
9420
|
+
description: "Zod schema (conversion failed)"
|
|
9421
|
+
};
|
|
9422
|
+
}
|
|
9423
|
+
}
|
|
9424
|
+
function serializeTool(tool) {
|
|
9425
|
+
if (!tool || typeof tool !== "object") {
|
|
9426
|
+
return tool;
|
|
9427
|
+
}
|
|
9428
|
+
const serialized = { ...tool };
|
|
9429
|
+
if (isZodSchema(serialized.inputSchema)) {
|
|
9430
|
+
serialized.inputSchema = serializeZodSchema(serialized.inputSchema);
|
|
9431
|
+
}
|
|
9432
|
+
if (isZodSchema(serialized.parameters)) {
|
|
9433
|
+
serialized.parameters = serializeZodSchema(serialized.parameters);
|
|
9434
|
+
}
|
|
9435
|
+
if ("execute" in serialized) {
|
|
9436
|
+
delete serialized.execute;
|
|
9437
|
+
}
|
|
9438
|
+
if ("render" in serialized) {
|
|
9439
|
+
delete serialized.render;
|
|
9440
|
+
}
|
|
9441
|
+
return serialized;
|
|
9442
|
+
}
|
|
9443
|
+
function serializeAISDKToolsForLogging(tools) {
|
|
9444
|
+
if (!tools || typeof tools !== "object") {
|
|
9445
|
+
return tools;
|
|
9446
|
+
}
|
|
9447
|
+
if (Array.isArray(tools)) {
|
|
9448
|
+
return tools.map(serializeTool);
|
|
9449
|
+
}
|
|
9450
|
+
const serialized = {};
|
|
9451
|
+
for (const [key, tool] of Object.entries(tools)) {
|
|
9452
|
+
serialized[key] = serializeTool(tool);
|
|
9453
|
+
}
|
|
9454
|
+
return serialized;
|
|
9455
|
+
}
|
|
9456
|
+
|
|
9212
9457
|
// src/instrumentation/plugins/ai-sdk-channels.ts
|
|
9213
9458
|
var aiSDKChannels = defineChannels("ai", {
|
|
9214
9459
|
generateText: channel({
|
|
@@ -9219,6 +9464,10 @@ var aiSDKChannels = defineChannels("ai", {
|
|
|
9219
9464
|
channelName: "streamText",
|
|
9220
9465
|
kind: "async"
|
|
9221
9466
|
}),
|
|
9467
|
+
streamTextSync: channel({
|
|
9468
|
+
channelName: "streamText.sync",
|
|
9469
|
+
kind: "sync-stream"
|
|
9470
|
+
}),
|
|
9222
9471
|
generateObject: channel({
|
|
9223
9472
|
channelName: "generateObject",
|
|
9224
9473
|
kind: "async"
|
|
@@ -9227,6 +9476,10 @@ var aiSDKChannels = defineChannels("ai", {
|
|
|
9227
9476
|
channelName: "streamObject",
|
|
9228
9477
|
kind: "async"
|
|
9229
9478
|
}),
|
|
9479
|
+
streamObjectSync: channel({
|
|
9480
|
+
channelName: "streamObject.sync",
|
|
9481
|
+
kind: "sync-stream"
|
|
9482
|
+
}),
|
|
9230
9483
|
agentGenerate: channel({
|
|
9231
9484
|
channelName: "Agent.generate",
|
|
9232
9485
|
kind: "async"
|
|
@@ -9234,6 +9487,14 @@ var aiSDKChannels = defineChannels("ai", {
|
|
|
9234
9487
|
agentStream: channel({
|
|
9235
9488
|
channelName: "Agent.stream",
|
|
9236
9489
|
kind: "async"
|
|
9490
|
+
}),
|
|
9491
|
+
toolLoopAgentGenerate: channel({
|
|
9492
|
+
channelName: "ToolLoopAgent.generate",
|
|
9493
|
+
kind: "async"
|
|
9494
|
+
}),
|
|
9495
|
+
toolLoopAgentStream: channel({
|
|
9496
|
+
channelName: "ToolLoopAgent.stream",
|
|
9497
|
+
kind: "async"
|
|
9237
9498
|
})
|
|
9238
9499
|
});
|
|
9239
9500
|
|
|
@@ -9252,6 +9513,8 @@ var DEFAULT_DENY_OUTPUT_PATHS = [
|
|
|
9252
9513
|
"steps[].response.body",
|
|
9253
9514
|
"steps[].response.headers"
|
|
9254
9515
|
];
|
|
9516
|
+
var AUTO_PATCHED_MODEL = Symbol.for("braintrust.ai-sdk.auto-patched-model");
|
|
9517
|
+
var AUTO_PATCHED_TOOL = Symbol.for("braintrust.ai-sdk.auto-patched-tool");
|
|
9255
9518
|
var AISDKPlugin = class extends BasePlugin {
|
|
9256
9519
|
config;
|
|
9257
9520
|
constructor(config = {}) {
|
|
@@ -9270,22 +9533,12 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
9270
9533
|
traceStreamingChannel(aiSDKChannels.generateText, {
|
|
9271
9534
|
name: "generateText",
|
|
9272
9535
|
type: "llm" /* LLM */,
|
|
9273
|
-
extractInput: ([params]) =>
|
|
9274
|
-
|
|
9275
|
-
|
|
9276
|
-
metadata: extractMetadataFromParams(params)
|
|
9277
|
-
};
|
|
9278
|
-
},
|
|
9279
|
-
extractOutput: (result) => {
|
|
9536
|
+
extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
|
|
9537
|
+
extractOutput: (result, endEvent) => {
|
|
9538
|
+
finalizeAISDKChildTracing(endEvent);
|
|
9280
9539
|
return processAISDKOutput(result, denyOutputPaths);
|
|
9281
9540
|
},
|
|
9282
|
-
extractMetrics: (result,
|
|
9283
|
-
const metrics = extractTokenMetrics(result);
|
|
9284
|
-
if (startTime) {
|
|
9285
|
-
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
9286
|
-
}
|
|
9287
|
-
return metrics;
|
|
9288
|
-
},
|
|
9541
|
+
extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
|
|
9289
9542
|
aggregateChunks: aggregateAISDKChunks
|
|
9290
9543
|
})
|
|
9291
9544
|
);
|
|
@@ -9293,45 +9546,43 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
9293
9546
|
traceStreamingChannel(aiSDKChannels.streamText, {
|
|
9294
9547
|
name: "streamText",
|
|
9295
9548
|
type: "llm" /* LLM */,
|
|
9296
|
-
extractInput: ([params]) =>
|
|
9297
|
-
|
|
9298
|
-
|
|
9299
|
-
|
|
9300
|
-
|
|
9301
|
-
|
|
9302
|
-
|
|
9303
|
-
|
|
9304
|
-
|
|
9305
|
-
|
|
9306
|
-
|
|
9307
|
-
|
|
9308
|
-
|
|
9309
|
-
|
|
9310
|
-
|
|
9311
|
-
|
|
9312
|
-
|
|
9549
|
+
extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
|
|
9550
|
+
extractOutput: (result) => processAISDKOutput(result, denyOutputPaths),
|
|
9551
|
+
extractMetrics: (result, startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent, startTime),
|
|
9552
|
+
aggregateChunks: aggregateAISDKChunks,
|
|
9553
|
+
patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
|
|
9554
|
+
denyOutputPaths,
|
|
9555
|
+
endEvent,
|
|
9556
|
+
result,
|
|
9557
|
+
span,
|
|
9558
|
+
startTime
|
|
9559
|
+
})
|
|
9560
|
+
})
|
|
9561
|
+
);
|
|
9562
|
+
this.unsubscribers.push(
|
|
9563
|
+
traceSyncStreamChannel(aiSDKChannels.streamTextSync, {
|
|
9564
|
+
name: "streamText",
|
|
9565
|
+
type: "llm" /* LLM */,
|
|
9566
|
+
extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
|
|
9567
|
+
patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
|
|
9568
|
+
denyOutputPaths,
|
|
9569
|
+
endEvent,
|
|
9570
|
+
result,
|
|
9571
|
+
span,
|
|
9572
|
+
startTime
|
|
9573
|
+
})
|
|
9313
9574
|
})
|
|
9314
9575
|
);
|
|
9315
9576
|
this.unsubscribers.push(
|
|
9316
9577
|
traceStreamingChannel(aiSDKChannels.generateObject, {
|
|
9317
9578
|
name: "generateObject",
|
|
9318
9579
|
type: "llm" /* LLM */,
|
|
9319
|
-
extractInput: ([params]) =>
|
|
9320
|
-
|
|
9321
|
-
|
|
9322
|
-
metadata: extractMetadataFromParams(params)
|
|
9323
|
-
};
|
|
9324
|
-
},
|
|
9325
|
-
extractOutput: (result) => {
|
|
9580
|
+
extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
|
|
9581
|
+
extractOutput: (result, endEvent) => {
|
|
9582
|
+
finalizeAISDKChildTracing(endEvent);
|
|
9326
9583
|
return processAISDKOutput(result, denyOutputPaths);
|
|
9327
9584
|
},
|
|
9328
|
-
extractMetrics: (result,
|
|
9329
|
-
const metrics = extractTokenMetrics(result);
|
|
9330
|
-
if (startTime) {
|
|
9331
|
-
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
9332
|
-
}
|
|
9333
|
-
return metrics;
|
|
9334
|
-
},
|
|
9585
|
+
extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
|
|
9335
9586
|
aggregateChunks: aggregateAISDKChunks
|
|
9336
9587
|
})
|
|
9337
9588
|
);
|
|
@@ -9339,45 +9590,43 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
9339
9590
|
traceStreamingChannel(aiSDKChannels.streamObject, {
|
|
9340
9591
|
name: "streamObject",
|
|
9341
9592
|
type: "llm" /* LLM */,
|
|
9342
|
-
extractInput: ([params]) =>
|
|
9343
|
-
|
|
9344
|
-
|
|
9345
|
-
|
|
9346
|
-
|
|
9347
|
-
|
|
9348
|
-
|
|
9349
|
-
|
|
9350
|
-
|
|
9351
|
-
|
|
9352
|
-
|
|
9353
|
-
|
|
9354
|
-
|
|
9355
|
-
|
|
9356
|
-
|
|
9357
|
-
|
|
9358
|
-
|
|
9593
|
+
extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
|
|
9594
|
+
extractOutput: (result) => processAISDKOutput(result, denyOutputPaths),
|
|
9595
|
+
extractMetrics: (result, startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent, startTime),
|
|
9596
|
+
aggregateChunks: aggregateAISDKChunks,
|
|
9597
|
+
patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
|
|
9598
|
+
denyOutputPaths,
|
|
9599
|
+
endEvent,
|
|
9600
|
+
result,
|
|
9601
|
+
span,
|
|
9602
|
+
startTime
|
|
9603
|
+
})
|
|
9604
|
+
})
|
|
9605
|
+
);
|
|
9606
|
+
this.unsubscribers.push(
|
|
9607
|
+
traceSyncStreamChannel(aiSDKChannels.streamObjectSync, {
|
|
9608
|
+
name: "streamObject",
|
|
9609
|
+
type: "llm" /* LLM */,
|
|
9610
|
+
extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
|
|
9611
|
+
patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
|
|
9612
|
+
denyOutputPaths,
|
|
9613
|
+
endEvent,
|
|
9614
|
+
result,
|
|
9615
|
+
span,
|
|
9616
|
+
startTime
|
|
9617
|
+
})
|
|
9359
9618
|
})
|
|
9360
9619
|
);
|
|
9361
9620
|
this.unsubscribers.push(
|
|
9362
9621
|
traceStreamingChannel(aiSDKChannels.agentGenerate, {
|
|
9363
9622
|
name: "Agent.generate",
|
|
9364
9623
|
type: "llm" /* LLM */,
|
|
9365
|
-
extractInput: ([params]) =>
|
|
9366
|
-
|
|
9367
|
-
|
|
9368
|
-
metadata: extractMetadataFromParams(params)
|
|
9369
|
-
};
|
|
9370
|
-
},
|
|
9371
|
-
extractOutput: (result) => {
|
|
9624
|
+
extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
|
|
9625
|
+
extractOutput: (result, endEvent) => {
|
|
9626
|
+
finalizeAISDKChildTracing(endEvent);
|
|
9372
9627
|
return processAISDKOutput(result, denyOutputPaths);
|
|
9373
9628
|
},
|
|
9374
|
-
extractMetrics: (result,
|
|
9375
|
-
const metrics = extractTokenMetrics(result);
|
|
9376
|
-
if (startTime) {
|
|
9377
|
-
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
9378
|
-
}
|
|
9379
|
-
return metrics;
|
|
9380
|
-
},
|
|
9629
|
+
extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
|
|
9381
9630
|
aggregateChunks: aggregateAISDKChunks
|
|
9382
9631
|
})
|
|
9383
9632
|
);
|
|
@@ -9385,88 +9634,506 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
9385
9634
|
traceStreamingChannel(aiSDKChannels.agentStream, {
|
|
9386
9635
|
name: "Agent.stream",
|
|
9387
9636
|
type: "llm" /* LLM */,
|
|
9388
|
-
extractInput: ([params]) =>
|
|
9389
|
-
|
|
9390
|
-
|
|
9391
|
-
|
|
9392
|
-
|
|
9393
|
-
|
|
9394
|
-
|
|
9637
|
+
extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
|
|
9638
|
+
extractOutput: (result) => processAISDKOutput(result, denyOutputPaths),
|
|
9639
|
+
extractMetrics: (result, startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent, startTime),
|
|
9640
|
+
aggregateChunks: aggregateAISDKChunks,
|
|
9641
|
+
patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
|
|
9642
|
+
denyOutputPaths,
|
|
9643
|
+
endEvent,
|
|
9644
|
+
result,
|
|
9645
|
+
span,
|
|
9646
|
+
startTime
|
|
9647
|
+
})
|
|
9648
|
+
})
|
|
9649
|
+
);
|
|
9650
|
+
this.unsubscribers.push(
|
|
9651
|
+
traceStreamingChannel(aiSDKChannels.toolLoopAgentGenerate, {
|
|
9652
|
+
name: "ToolLoopAgent.generate",
|
|
9653
|
+
type: "llm" /* LLM */,
|
|
9654
|
+
extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
|
|
9655
|
+
extractOutput: (result, endEvent) => {
|
|
9656
|
+
finalizeAISDKChildTracing(endEvent);
|
|
9395
9657
|
return processAISDKOutput(result, denyOutputPaths);
|
|
9396
9658
|
},
|
|
9397
|
-
extractMetrics: (result,
|
|
9398
|
-
const metrics = extractTokenMetrics(result);
|
|
9399
|
-
if (startTime) {
|
|
9400
|
-
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
9401
|
-
}
|
|
9402
|
-
return metrics;
|
|
9403
|
-
},
|
|
9659
|
+
extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
|
|
9404
9660
|
aggregateChunks: aggregateAISDKChunks
|
|
9405
9661
|
})
|
|
9406
9662
|
);
|
|
9663
|
+
this.unsubscribers.push(
|
|
9664
|
+
traceStreamingChannel(aiSDKChannels.toolLoopAgentStream, {
|
|
9665
|
+
name: "ToolLoopAgent.stream",
|
|
9666
|
+
type: "llm" /* LLM */,
|
|
9667
|
+
extractInput: ([params], event, span) => prepareAISDKInput(params, event, span, denyOutputPaths),
|
|
9668
|
+
extractOutput: (result) => processAISDKOutput(result, denyOutputPaths),
|
|
9669
|
+
extractMetrics: (result, startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent, startTime),
|
|
9670
|
+
aggregateChunks: aggregateAISDKChunks,
|
|
9671
|
+
patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
|
|
9672
|
+
denyOutputPaths,
|
|
9673
|
+
endEvent,
|
|
9674
|
+
result,
|
|
9675
|
+
span,
|
|
9676
|
+
startTime
|
|
9677
|
+
})
|
|
9678
|
+
})
|
|
9679
|
+
);
|
|
9407
9680
|
}
|
|
9408
9681
|
};
|
|
9409
9682
|
function processAISDKInput(params) {
|
|
9410
9683
|
if (!params) return params;
|
|
9411
|
-
|
|
9684
|
+
const input = processInputAttachments(params);
|
|
9685
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) {
|
|
9686
|
+
return input;
|
|
9687
|
+
}
|
|
9688
|
+
const { tools: _tools, ...rest } = input;
|
|
9689
|
+
return rest;
|
|
9690
|
+
}
|
|
9691
|
+
function prepareAISDKInput(params, event, span, denyOutputPaths) {
|
|
9692
|
+
const input = processAISDKInput(params);
|
|
9693
|
+
const metadata = extractMetadataFromParams(params, event.self);
|
|
9694
|
+
const childTracing = prepareAISDKChildTracing(
|
|
9695
|
+
params,
|
|
9696
|
+
event.self,
|
|
9697
|
+
span,
|
|
9698
|
+
denyOutputPaths
|
|
9699
|
+
);
|
|
9700
|
+
event.__braintrust_ai_sdk_model_wrapped = childTracing.modelWrapped;
|
|
9701
|
+
if (childTracing.cleanup) {
|
|
9702
|
+
event.__braintrust_ai_sdk_cleanup = childTracing.cleanup;
|
|
9703
|
+
}
|
|
9704
|
+
return {
|
|
9705
|
+
input,
|
|
9706
|
+
metadata
|
|
9707
|
+
};
|
|
9708
|
+
}
|
|
9709
|
+
function extractTopLevelAISDKMetrics(result, event, startTime) {
|
|
9710
|
+
const metrics = hasModelChildTracing(event) ? {} : extractTokenMetrics(result);
|
|
9711
|
+
if (startTime) {
|
|
9712
|
+
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
9713
|
+
}
|
|
9714
|
+
return metrics;
|
|
9715
|
+
}
|
|
9716
|
+
function hasModelChildTracing(event) {
|
|
9717
|
+
return event?.__braintrust_ai_sdk_model_wrapped === true;
|
|
9412
9718
|
}
|
|
9413
|
-
function extractMetadataFromParams(params) {
|
|
9719
|
+
function extractMetadataFromParams(params, self) {
|
|
9414
9720
|
const metadata = {
|
|
9415
9721
|
braintrust: {
|
|
9416
9722
|
integration_name: "ai-sdk",
|
|
9417
9723
|
sdk_language: "typescript"
|
|
9418
9724
|
}
|
|
9419
9725
|
};
|
|
9420
|
-
const
|
|
9726
|
+
const agentModel = 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;
|
|
9727
|
+
const { model, provider } = serializeModelWithProvider(
|
|
9728
|
+
params.model ?? agentModel
|
|
9729
|
+
);
|
|
9421
9730
|
if (model) {
|
|
9422
9731
|
metadata.model = model;
|
|
9423
9732
|
}
|
|
9424
9733
|
if (provider) {
|
|
9425
9734
|
metadata.provider = provider;
|
|
9426
9735
|
}
|
|
9736
|
+
const tools = serializeAISDKToolsForLogging(params.tools);
|
|
9737
|
+
if (tools) {
|
|
9738
|
+
metadata.tools = tools;
|
|
9739
|
+
}
|
|
9427
9740
|
return metadata;
|
|
9428
9741
|
}
|
|
9429
|
-
function
|
|
9430
|
-
|
|
9431
|
-
const
|
|
9432
|
-
const
|
|
9433
|
-
|
|
9434
|
-
|
|
9435
|
-
|
|
9436
|
-
|
|
9437
|
-
|
|
9438
|
-
if (!usage && result) {
|
|
9439
|
-
try {
|
|
9440
|
-
if ("totalUsage" in result && typeof result.totalUsage !== "function") {
|
|
9441
|
-
usage = result.totalUsage;
|
|
9442
|
-
} else if ("usage" in result && typeof result.usage !== "function") {
|
|
9443
|
-
usage = result.usage;
|
|
9444
|
-
}
|
|
9445
|
-
} catch {
|
|
9742
|
+
function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths) {
|
|
9743
|
+
const cleanup = [];
|
|
9744
|
+
const patchedModels = /* @__PURE__ */ new WeakSet();
|
|
9745
|
+
const patchedTools = /* @__PURE__ */ new WeakSet();
|
|
9746
|
+
let modelWrapped = false;
|
|
9747
|
+
const patchModel = (model) => {
|
|
9748
|
+
const resolvedModel = resolveAISDKModel(model);
|
|
9749
|
+
if (!resolvedModel || typeof resolvedModel !== "object" || typeof resolvedModel.doGenerate !== "function" || patchedModels.has(resolvedModel) || resolvedModel[AUTO_PATCHED_MODEL]) {
|
|
9750
|
+
return;
|
|
9446
9751
|
}
|
|
9447
|
-
|
|
9448
|
-
|
|
9449
|
-
|
|
9450
|
-
|
|
9451
|
-
|
|
9452
|
-
|
|
9453
|
-
|
|
9454
|
-
|
|
9455
|
-
|
|
9456
|
-
|
|
9457
|
-
|
|
9458
|
-
|
|
9459
|
-
|
|
9460
|
-
|
|
9461
|
-
|
|
9462
|
-
|
|
9463
|
-
|
|
9464
|
-
|
|
9465
|
-
|
|
9466
|
-
|
|
9467
|
-
|
|
9468
|
-
|
|
9469
|
-
|
|
9752
|
+
patchedModels.add(resolvedModel);
|
|
9753
|
+
resolvedModel[AUTO_PATCHED_MODEL] = true;
|
|
9754
|
+
modelWrapped = true;
|
|
9755
|
+
const originalDoGenerate = resolvedModel.doGenerate;
|
|
9756
|
+
const originalDoStream = resolvedModel.doStream;
|
|
9757
|
+
const baseMetadata = buildAISDKChildMetadata(resolvedModel);
|
|
9758
|
+
resolvedModel.doGenerate = async function doGeneratePatched(options) {
|
|
9759
|
+
return parentSpan.traced(
|
|
9760
|
+
async (span) => {
|
|
9761
|
+
const result = await Reflect.apply(
|
|
9762
|
+
originalDoGenerate,
|
|
9763
|
+
resolvedModel,
|
|
9764
|
+
[options]
|
|
9765
|
+
);
|
|
9766
|
+
span.log({
|
|
9767
|
+
output: processAISDKOutput(result, denyOutputPaths),
|
|
9768
|
+
metrics: extractTokenMetrics(result),
|
|
9769
|
+
...buildResolvedMetadataPayload(result)
|
|
9770
|
+
});
|
|
9771
|
+
return result;
|
|
9772
|
+
},
|
|
9773
|
+
{
|
|
9774
|
+
name: "doGenerate",
|
|
9775
|
+
spanAttributes: {
|
|
9776
|
+
type: "llm" /* LLM */
|
|
9777
|
+
},
|
|
9778
|
+
event: {
|
|
9779
|
+
input: processAISDKInput(options),
|
|
9780
|
+
metadata: baseMetadata
|
|
9781
|
+
}
|
|
9782
|
+
}
|
|
9783
|
+
);
|
|
9784
|
+
};
|
|
9785
|
+
if (originalDoStream) {
|
|
9786
|
+
resolvedModel.doStream = async function doStreamPatched(options) {
|
|
9787
|
+
const span = parentSpan.startSpan({
|
|
9788
|
+
name: "doStream",
|
|
9789
|
+
spanAttributes: {
|
|
9790
|
+
type: "llm" /* LLM */
|
|
9791
|
+
},
|
|
9792
|
+
event: {
|
|
9793
|
+
input: processAISDKInput(options),
|
|
9794
|
+
metadata: baseMetadata
|
|
9795
|
+
}
|
|
9796
|
+
});
|
|
9797
|
+
const result = await withCurrent(
|
|
9798
|
+
span,
|
|
9799
|
+
() => Reflect.apply(originalDoStream, resolvedModel, [options])
|
|
9800
|
+
);
|
|
9801
|
+
const output = {};
|
|
9802
|
+
let text = "";
|
|
9803
|
+
let reasoning = "";
|
|
9804
|
+
const toolCalls = [];
|
|
9805
|
+
let object = void 0;
|
|
9806
|
+
const transformStream = new TransformStream({
|
|
9807
|
+
transform(chunk, controller) {
|
|
9808
|
+
switch (chunk.type) {
|
|
9809
|
+
case "text-delta":
|
|
9810
|
+
text += extractTextDelta(chunk);
|
|
9811
|
+
break;
|
|
9812
|
+
case "reasoning-delta":
|
|
9813
|
+
if (chunk.delta) {
|
|
9814
|
+
reasoning += chunk.delta;
|
|
9815
|
+
} else if (chunk.text) {
|
|
9816
|
+
reasoning += chunk.text;
|
|
9817
|
+
}
|
|
9818
|
+
break;
|
|
9819
|
+
case "tool-call":
|
|
9820
|
+
toolCalls.push(chunk);
|
|
9821
|
+
break;
|
|
9822
|
+
case "object":
|
|
9823
|
+
object = chunk.object;
|
|
9824
|
+
break;
|
|
9825
|
+
case "raw":
|
|
9826
|
+
if (chunk.rawValue) {
|
|
9827
|
+
const rawVal = chunk.rawValue;
|
|
9828
|
+
if (rawVal.delta?.content) {
|
|
9829
|
+
text += rawVal.delta.content;
|
|
9830
|
+
} else if (rawVal.choices?.[0]?.delta?.content) {
|
|
9831
|
+
text += rawVal.choices[0].delta.content;
|
|
9832
|
+
} else if (typeof rawVal.text === "string") {
|
|
9833
|
+
text += rawVal.text;
|
|
9834
|
+
} else if (typeof rawVal.content === "string") {
|
|
9835
|
+
text += rawVal.content;
|
|
9836
|
+
}
|
|
9837
|
+
}
|
|
9838
|
+
break;
|
|
9839
|
+
case "finish":
|
|
9840
|
+
output.text = text;
|
|
9841
|
+
output.reasoning = reasoning;
|
|
9842
|
+
output.toolCalls = toolCalls;
|
|
9843
|
+
output.finishReason = chunk.finishReason;
|
|
9844
|
+
output.usage = chunk.usage;
|
|
9845
|
+
if (object !== void 0) {
|
|
9846
|
+
output.object = object;
|
|
9847
|
+
}
|
|
9848
|
+
span.log({
|
|
9849
|
+
output: processAISDKOutput(
|
|
9850
|
+
output,
|
|
9851
|
+
denyOutputPaths
|
|
9852
|
+
),
|
|
9853
|
+
metrics: extractTokenMetrics(output),
|
|
9854
|
+
...buildResolvedMetadataPayload(output)
|
|
9855
|
+
});
|
|
9856
|
+
span.end();
|
|
9857
|
+
break;
|
|
9858
|
+
}
|
|
9859
|
+
controller.enqueue(chunk);
|
|
9860
|
+
}
|
|
9861
|
+
});
|
|
9862
|
+
return {
|
|
9863
|
+
...result,
|
|
9864
|
+
stream: result.stream.pipeThrough(transformStream)
|
|
9865
|
+
};
|
|
9866
|
+
};
|
|
9867
|
+
}
|
|
9868
|
+
cleanup.push(() => {
|
|
9869
|
+
resolvedModel.doGenerate = originalDoGenerate;
|
|
9870
|
+
if (originalDoStream) {
|
|
9871
|
+
resolvedModel.doStream = originalDoStream;
|
|
9872
|
+
}
|
|
9873
|
+
delete resolvedModel[AUTO_PATCHED_MODEL];
|
|
9874
|
+
});
|
|
9875
|
+
};
|
|
9876
|
+
const patchTool = (tool, name) => {
|
|
9877
|
+
if (tool == null || typeof tool !== "object" || !("execute" in tool) || typeof tool.execute !== "function" || patchedTools.has(tool) || tool[AUTO_PATCHED_TOOL]) {
|
|
9878
|
+
return;
|
|
9879
|
+
}
|
|
9880
|
+
patchedTools.add(tool);
|
|
9881
|
+
tool[AUTO_PATCHED_TOOL] = true;
|
|
9882
|
+
const originalExecute = tool.execute;
|
|
9883
|
+
tool.execute = function executePatched(...args) {
|
|
9884
|
+
const result = Reflect.apply(originalExecute, this, args);
|
|
9885
|
+
if (isAsyncGenerator(result)) {
|
|
9886
|
+
return (async function* () {
|
|
9887
|
+
const span = parentSpan.startSpan({
|
|
9888
|
+
name,
|
|
9889
|
+
spanAttributes: {
|
|
9890
|
+
type: "tool" /* TOOL */
|
|
9891
|
+
}
|
|
9892
|
+
});
|
|
9893
|
+
span.log({ input: args.length === 1 ? args[0] : args });
|
|
9894
|
+
try {
|
|
9895
|
+
let lastValue;
|
|
9896
|
+
for await (const value of result) {
|
|
9897
|
+
lastValue = value;
|
|
9898
|
+
yield value;
|
|
9899
|
+
}
|
|
9900
|
+
span.log({ output: lastValue });
|
|
9901
|
+
} catch (error) {
|
|
9902
|
+
span.log({
|
|
9903
|
+
error: error instanceof Error ? error.message : String(error)
|
|
9904
|
+
});
|
|
9905
|
+
throw error;
|
|
9906
|
+
} finally {
|
|
9907
|
+
span.end();
|
|
9908
|
+
}
|
|
9909
|
+
})();
|
|
9910
|
+
}
|
|
9911
|
+
return parentSpan.traced(
|
|
9912
|
+
async (span) => {
|
|
9913
|
+
span.log({ input: args.length === 1 ? args[0] : args });
|
|
9914
|
+
const awaitedResult = await result;
|
|
9915
|
+
span.log({ output: awaitedResult });
|
|
9916
|
+
return awaitedResult;
|
|
9917
|
+
},
|
|
9918
|
+
{
|
|
9919
|
+
name,
|
|
9920
|
+
spanAttributes: {
|
|
9921
|
+
type: "tool" /* TOOL */
|
|
9922
|
+
}
|
|
9923
|
+
}
|
|
9924
|
+
);
|
|
9925
|
+
};
|
|
9926
|
+
cleanup.push(() => {
|
|
9927
|
+
tool.execute = originalExecute;
|
|
9928
|
+
delete tool[AUTO_PATCHED_TOOL];
|
|
9929
|
+
});
|
|
9930
|
+
};
|
|
9931
|
+
const patchTools = (tools) => {
|
|
9932
|
+
if (!tools) {
|
|
9933
|
+
return;
|
|
9934
|
+
}
|
|
9935
|
+
const inferName = (tool, fallback) => tool && (tool.name || tool.toolName || tool.id) || fallback;
|
|
9936
|
+
if (Array.isArray(tools)) {
|
|
9937
|
+
tools.forEach(
|
|
9938
|
+
(tool, index) => patchTool(tool, inferName(tool, `tool[${index}]`))
|
|
9939
|
+
);
|
|
9940
|
+
return;
|
|
9941
|
+
}
|
|
9942
|
+
for (const [key, tool] of Object.entries(tools)) {
|
|
9943
|
+
patchTool(tool, key);
|
|
9944
|
+
}
|
|
9945
|
+
};
|
|
9946
|
+
if (params && typeof params === "object") {
|
|
9947
|
+
patchModel(params.model);
|
|
9948
|
+
patchTools(params.tools);
|
|
9949
|
+
}
|
|
9950
|
+
if (self && typeof self === "object") {
|
|
9951
|
+
const selfRecord = self;
|
|
9952
|
+
if (selfRecord.model !== void 0) {
|
|
9953
|
+
patchModel(selfRecord.model);
|
|
9954
|
+
}
|
|
9955
|
+
if (selfRecord.settings && typeof selfRecord.settings === "object") {
|
|
9956
|
+
if (selfRecord.settings.model !== void 0) {
|
|
9957
|
+
patchModel(selfRecord.settings.model);
|
|
9958
|
+
}
|
|
9959
|
+
if (selfRecord.settings.tools !== void 0) {
|
|
9960
|
+
patchTools(selfRecord.settings.tools);
|
|
9961
|
+
}
|
|
9962
|
+
}
|
|
9963
|
+
}
|
|
9964
|
+
return {
|
|
9965
|
+
cleanup: cleanup.length > 0 ? () => {
|
|
9966
|
+
while (cleanup.length > 0) {
|
|
9967
|
+
cleanup.pop()?.();
|
|
9968
|
+
}
|
|
9969
|
+
} : void 0,
|
|
9970
|
+
modelWrapped
|
|
9971
|
+
};
|
|
9972
|
+
}
|
|
9973
|
+
function finalizeAISDKChildTracing(event) {
|
|
9974
|
+
const cleanup = event?.__braintrust_ai_sdk_cleanup;
|
|
9975
|
+
if (event && typeof cleanup === "function") {
|
|
9976
|
+
cleanup();
|
|
9977
|
+
delete event.__braintrust_ai_sdk_cleanup;
|
|
9978
|
+
}
|
|
9979
|
+
}
|
|
9980
|
+
function patchAISDKStreamingResult(args) {
|
|
9981
|
+
const { denyOutputPaths, endEvent, result, span, startTime } = args;
|
|
9982
|
+
if (!result || typeof result !== "object") {
|
|
9983
|
+
return false;
|
|
9984
|
+
}
|
|
9985
|
+
const resultRecord = result;
|
|
9986
|
+
if (!isReadableStreamLike(resultRecord.baseStream)) {
|
|
9987
|
+
return false;
|
|
9988
|
+
}
|
|
9989
|
+
let firstChunkTime;
|
|
9990
|
+
const wrappedBaseStream = resultRecord.baseStream.pipeThrough(
|
|
9991
|
+
new TransformStream({
|
|
9992
|
+
transform(chunk, controller) {
|
|
9993
|
+
if (firstChunkTime === void 0) {
|
|
9994
|
+
firstChunkTime = getCurrentUnixTimestamp();
|
|
9995
|
+
}
|
|
9996
|
+
controller.enqueue(chunk);
|
|
9997
|
+
},
|
|
9998
|
+
async flush() {
|
|
9999
|
+
const metrics = extractTopLevelAISDKMetrics(result, endEvent);
|
|
10000
|
+
if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
|
|
10001
|
+
metrics.time_to_first_token = firstChunkTime - startTime;
|
|
10002
|
+
}
|
|
10003
|
+
const output = await processAISDKStreamingOutput(
|
|
10004
|
+
result,
|
|
10005
|
+
denyOutputPaths
|
|
10006
|
+
);
|
|
10007
|
+
const metadata = buildResolvedMetadataPayload(result).metadata;
|
|
10008
|
+
span.log({
|
|
10009
|
+
output,
|
|
10010
|
+
...metadata ? { metadata } : {},
|
|
10011
|
+
metrics
|
|
10012
|
+
});
|
|
10013
|
+
finalizeAISDKChildTracing(endEvent);
|
|
10014
|
+
span.end();
|
|
10015
|
+
}
|
|
10016
|
+
})
|
|
10017
|
+
);
|
|
10018
|
+
Object.defineProperty(resultRecord, "baseStream", {
|
|
10019
|
+
configurable: true,
|
|
10020
|
+
enumerable: true,
|
|
10021
|
+
value: wrappedBaseStream,
|
|
10022
|
+
writable: true
|
|
10023
|
+
});
|
|
10024
|
+
return true;
|
|
10025
|
+
}
|
|
10026
|
+
function isReadableStreamLike(value) {
|
|
10027
|
+
return value != null && typeof value === "object" && typeof value.pipeThrough === "function";
|
|
10028
|
+
}
|
|
10029
|
+
async function processAISDKStreamingOutput(result, denyOutputPaths) {
|
|
10030
|
+
const output = processAISDKOutput(result, denyOutputPaths);
|
|
10031
|
+
if (!output || typeof output !== "object") {
|
|
10032
|
+
return output;
|
|
10033
|
+
}
|
|
10034
|
+
const outputRecord = output;
|
|
10035
|
+
try {
|
|
10036
|
+
if ("text" in result && typeof result.text === "string") {
|
|
10037
|
+
outputRecord.text = result.text;
|
|
10038
|
+
}
|
|
10039
|
+
} catch {
|
|
10040
|
+
}
|
|
10041
|
+
try {
|
|
10042
|
+
if ("object" in result) {
|
|
10043
|
+
const resolvedObject = await Promise.resolve(result.object);
|
|
10044
|
+
if (resolvedObject !== void 0) {
|
|
10045
|
+
outputRecord.object = resolvedObject;
|
|
10046
|
+
}
|
|
10047
|
+
}
|
|
10048
|
+
} catch {
|
|
10049
|
+
}
|
|
10050
|
+
return outputRecord;
|
|
10051
|
+
}
|
|
10052
|
+
function buildAISDKChildMetadata(model) {
|
|
10053
|
+
const { model: modelId, provider } = serializeModelWithProvider(model);
|
|
10054
|
+
return {
|
|
10055
|
+
...modelId ? { model: modelId } : {},
|
|
10056
|
+
...provider ? { provider } : {},
|
|
10057
|
+
braintrust: {
|
|
10058
|
+
integration_name: "ai-sdk",
|
|
10059
|
+
sdk_language: "typescript"
|
|
10060
|
+
}
|
|
10061
|
+
};
|
|
10062
|
+
}
|
|
10063
|
+
function buildResolvedMetadataPayload(result) {
|
|
10064
|
+
const gatewayInfo = extractGatewayRoutingInfo(result);
|
|
10065
|
+
const metadata = {};
|
|
10066
|
+
if (gatewayInfo?.provider) {
|
|
10067
|
+
metadata.provider = gatewayInfo.provider;
|
|
10068
|
+
}
|
|
10069
|
+
if (gatewayInfo?.model) {
|
|
10070
|
+
metadata.model = gatewayInfo.model;
|
|
10071
|
+
}
|
|
10072
|
+
if (result.finishReason !== void 0) {
|
|
10073
|
+
metadata.finish_reason = result.finishReason;
|
|
10074
|
+
}
|
|
10075
|
+
return Object.keys(metadata).length > 0 ? { metadata } : {};
|
|
10076
|
+
}
|
|
10077
|
+
function resolveAISDKModel(model) {
|
|
10078
|
+
if (typeof model !== "string") {
|
|
10079
|
+
return model;
|
|
10080
|
+
}
|
|
10081
|
+
const provider = globalThis.AI_SDK_DEFAULT_PROVIDER ?? null;
|
|
10082
|
+
if (provider && typeof provider.languageModel === "function") {
|
|
10083
|
+
return provider.languageModel(model);
|
|
10084
|
+
}
|
|
10085
|
+
return model;
|
|
10086
|
+
}
|
|
10087
|
+
function extractTextDelta(chunk) {
|
|
10088
|
+
if (typeof chunk.textDelta === "string") return chunk.textDelta;
|
|
10089
|
+
if (typeof chunk.delta === "string") return chunk.delta;
|
|
10090
|
+
if (typeof chunk.text === "string") return chunk.text;
|
|
10091
|
+
if (typeof chunk.content === "string") return chunk.content;
|
|
10092
|
+
return "";
|
|
10093
|
+
}
|
|
10094
|
+
function isAsyncGenerator(value) {
|
|
10095
|
+
return value != null && typeof value === "object" && typeof value[Symbol.asyncIterator] === "function" && typeof value.next === "function" && typeof value.return === "function" && typeof value.throw === "function";
|
|
10096
|
+
}
|
|
10097
|
+
function processAISDKOutput(output, denyOutputPaths) {
|
|
10098
|
+
if (!output) return output;
|
|
10099
|
+
const merged = extractSerializableOutputFields(output);
|
|
10100
|
+
return normalizeAISDKLoggedOutput(omit(merged, denyOutputPaths));
|
|
10101
|
+
}
|
|
10102
|
+
function extractTokenMetrics(result) {
|
|
10103
|
+
const metrics = {};
|
|
10104
|
+
let usage = result?.totalUsage || result?.usage;
|
|
10105
|
+
if (!usage && result) {
|
|
10106
|
+
try {
|
|
10107
|
+
if ("totalUsage" in result && typeof result.totalUsage !== "function") {
|
|
10108
|
+
usage = result.totalUsage;
|
|
10109
|
+
} else if ("usage" in result && typeof result.usage !== "function") {
|
|
10110
|
+
usage = result.usage;
|
|
10111
|
+
}
|
|
10112
|
+
} catch {
|
|
10113
|
+
}
|
|
10114
|
+
}
|
|
10115
|
+
if (!usage) {
|
|
10116
|
+
return metrics;
|
|
10117
|
+
}
|
|
10118
|
+
const promptTokens = firstNumber(
|
|
10119
|
+
usage.inputTokens?.total,
|
|
10120
|
+
usage.inputTokens,
|
|
10121
|
+
usage.promptTokens,
|
|
10122
|
+
usage.prompt_tokens
|
|
10123
|
+
);
|
|
10124
|
+
if (promptTokens !== void 0) {
|
|
10125
|
+
metrics.prompt_tokens = promptTokens;
|
|
10126
|
+
}
|
|
10127
|
+
const completionTokens = firstNumber(
|
|
10128
|
+
usage.outputTokens?.total,
|
|
10129
|
+
usage.outputTokens,
|
|
10130
|
+
usage.completionTokens,
|
|
10131
|
+
usage.completion_tokens
|
|
10132
|
+
);
|
|
10133
|
+
if (completionTokens !== void 0) {
|
|
10134
|
+
metrics.completion_tokens = completionTokens;
|
|
10135
|
+
}
|
|
10136
|
+
const totalTokens = firstNumber(
|
|
9470
10137
|
usage.totalTokens,
|
|
9471
10138
|
usage.tokens,
|
|
9472
10139
|
usage.total_tokens
|
|
@@ -9480,12 +10147,14 @@ function extractTokenMetrics(result) {
|
|
|
9480
10147
|
}
|
|
9481
10148
|
return metrics;
|
|
9482
10149
|
}
|
|
9483
|
-
function aggregateAISDKChunks(chunks) {
|
|
10150
|
+
function aggregateAISDKChunks(chunks, _result, endEvent) {
|
|
9484
10151
|
const lastChunk = chunks[chunks.length - 1];
|
|
9485
10152
|
const output = {};
|
|
9486
10153
|
let metrics = {};
|
|
10154
|
+
let metadata;
|
|
9487
10155
|
if (lastChunk) {
|
|
9488
|
-
metrics = extractTokenMetrics(lastChunk);
|
|
10156
|
+
metrics = hasModelChildTracing(endEvent) ? {} : extractTokenMetrics(lastChunk);
|
|
10157
|
+
metadata = buildResolvedMetadataPayload(lastChunk).metadata;
|
|
9489
10158
|
if (lastChunk.text !== void 0) {
|
|
9490
10159
|
output.text = lastChunk.text;
|
|
9491
10160
|
}
|
|
@@ -9499,7 +10168,8 @@ function aggregateAISDKChunks(chunks) {
|
|
|
9499
10168
|
output.toolCalls = lastChunk.toolCalls;
|
|
9500
10169
|
}
|
|
9501
10170
|
}
|
|
9502
|
-
|
|
10171
|
+
finalizeAISDKChildTracing(endEvent);
|
|
10172
|
+
return { output, metrics, metadata };
|
|
9503
10173
|
}
|
|
9504
10174
|
function extractGetterValues(obj) {
|
|
9505
10175
|
const getterValues = {};
|
|
@@ -9519,7 +10189,7 @@ function extractGetterValues(obj) {
|
|
|
9519
10189
|
];
|
|
9520
10190
|
for (const name of getterNames) {
|
|
9521
10191
|
try {
|
|
9522
|
-
if (obj && name in obj &&
|
|
10192
|
+
if (obj && name in obj && isSerializableOutputValue(obj[name])) {
|
|
9523
10193
|
getterValues[name] = obj[name];
|
|
9524
10194
|
}
|
|
9525
10195
|
} catch {
|
|
@@ -9527,6 +10197,47 @@ function extractGetterValues(obj) {
|
|
|
9527
10197
|
}
|
|
9528
10198
|
return getterValues;
|
|
9529
10199
|
}
|
|
10200
|
+
function extractSerializableOutputFields(output) {
|
|
10201
|
+
const serialized = {};
|
|
10202
|
+
const directFieldNames = [
|
|
10203
|
+
"steps",
|
|
10204
|
+
"request",
|
|
10205
|
+
"responseMessages",
|
|
10206
|
+
"warnings",
|
|
10207
|
+
"rawResponse",
|
|
10208
|
+
"response",
|
|
10209
|
+
"providerMetadata",
|
|
10210
|
+
"experimental_providerMetadata"
|
|
10211
|
+
];
|
|
10212
|
+
for (const name of directFieldNames) {
|
|
10213
|
+
try {
|
|
10214
|
+
const value = output?.[name];
|
|
10215
|
+
if (isSerializableOutputValue(value)) {
|
|
10216
|
+
serialized[name] = value;
|
|
10217
|
+
}
|
|
10218
|
+
} catch {
|
|
10219
|
+
}
|
|
10220
|
+
}
|
|
10221
|
+
return {
|
|
10222
|
+
...serialized,
|
|
10223
|
+
...extractGetterValues(output)
|
|
10224
|
+
};
|
|
10225
|
+
}
|
|
10226
|
+
function isSerializableOutputValue(value) {
|
|
10227
|
+
if (typeof value === "function") {
|
|
10228
|
+
return false;
|
|
10229
|
+
}
|
|
10230
|
+
if (value && typeof value === "object" && typeof value.then === "function") {
|
|
10231
|
+
return false;
|
|
10232
|
+
}
|
|
10233
|
+
if (value && typeof value === "object" && typeof value.getReader === "function") {
|
|
10234
|
+
return false;
|
|
10235
|
+
}
|
|
10236
|
+
if (value && typeof value === "object" && typeof value[Symbol.asyncIterator] === "function") {
|
|
10237
|
+
return false;
|
|
10238
|
+
}
|
|
10239
|
+
return true;
|
|
10240
|
+
}
|
|
9530
10241
|
function serializeModelWithProvider(model) {
|
|
9531
10242
|
const modelId = typeof model === "string" ? model : model?.modelId;
|
|
9532
10243
|
const explicitProvider = typeof model === "object" ? model?.provider : void 0;
|
|
@@ -9552,6 +10263,25 @@ function parseGatewayModelString(modelString) {
|
|
|
9552
10263
|
}
|
|
9553
10264
|
return { model: modelString };
|
|
9554
10265
|
}
|
|
10266
|
+
function extractGatewayRoutingInfo(result) {
|
|
10267
|
+
if (result?.steps && Array.isArray(result.steps) && result.steps.length > 0) {
|
|
10268
|
+
const routing2 = result.steps[0]?.providerMetadata?.gateway?.routing;
|
|
10269
|
+
if (routing2) {
|
|
10270
|
+
return {
|
|
10271
|
+
provider: routing2.resolvedProvider || routing2.finalProvider,
|
|
10272
|
+
model: routing2.resolvedProviderApiModelId
|
|
10273
|
+
};
|
|
10274
|
+
}
|
|
10275
|
+
}
|
|
10276
|
+
const routing = result?.providerMetadata?.gateway?.routing;
|
|
10277
|
+
if (routing) {
|
|
10278
|
+
return {
|
|
10279
|
+
provider: routing.resolvedProvider || routing.finalProvider,
|
|
10280
|
+
model: routing.resolvedProviderApiModelId
|
|
10281
|
+
};
|
|
10282
|
+
}
|
|
10283
|
+
return null;
|
|
10284
|
+
}
|
|
9555
10285
|
function extractCostFromResult(result) {
|
|
9556
10286
|
if (result?.steps && Array.isArray(result.steps) && result.steps.length > 0) {
|
|
9557
10287
|
let totalCost = 0;
|
|
@@ -10282,47 +11012,1069 @@ function tryToDict(obj) {
|
|
|
10282
11012
|
return null;
|
|
10283
11013
|
}
|
|
10284
11014
|
|
|
10285
|
-
// src/instrumentation/
|
|
10286
|
-
var
|
|
10287
|
-
|
|
10288
|
-
|
|
10289
|
-
|
|
10290
|
-
|
|
10291
|
-
|
|
10292
|
-
|
|
10293
|
-
|
|
10294
|
-
|
|
10295
|
-
|
|
11015
|
+
// src/instrumentation/plugins/openrouter-channels.ts
|
|
11016
|
+
var openRouterChannels = defineChannels("@openrouter/sdk", {
|
|
11017
|
+
chatSend: channel({
|
|
11018
|
+
channelName: "chat.send",
|
|
11019
|
+
kind: "async"
|
|
11020
|
+
}),
|
|
11021
|
+
embeddingsGenerate: channel({
|
|
11022
|
+
channelName: "embeddings.generate",
|
|
11023
|
+
kind: "async"
|
|
11024
|
+
}),
|
|
11025
|
+
betaResponsesSend: channel({
|
|
11026
|
+
channelName: "beta.responses.send",
|
|
11027
|
+
kind: "async"
|
|
11028
|
+
}),
|
|
11029
|
+
callModel: channel({
|
|
11030
|
+
channelName: "callModel",
|
|
11031
|
+
kind: "sync-stream"
|
|
11032
|
+
}),
|
|
11033
|
+
toolExecute: channel({
|
|
11034
|
+
channelName: "tool.execute",
|
|
11035
|
+
kind: "async"
|
|
11036
|
+
})
|
|
11037
|
+
});
|
|
11038
|
+
|
|
11039
|
+
// src/openrouter-utils.ts
|
|
11040
|
+
var TOKEN_NAME_MAP2 = {
|
|
11041
|
+
promptTokens: "prompt_tokens",
|
|
11042
|
+
inputTokens: "prompt_tokens",
|
|
11043
|
+
completionTokens: "completion_tokens",
|
|
11044
|
+
outputTokens: "completion_tokens",
|
|
11045
|
+
totalTokens: "tokens",
|
|
11046
|
+
prompt_tokens: "prompt_tokens",
|
|
11047
|
+
input_tokens: "prompt_tokens",
|
|
11048
|
+
completion_tokens: "completion_tokens",
|
|
11049
|
+
output_tokens: "completion_tokens",
|
|
11050
|
+
total_tokens: "tokens"
|
|
11051
|
+
};
|
|
11052
|
+
var TOKEN_DETAIL_PREFIX_MAP = {
|
|
11053
|
+
promptTokensDetails: "prompt",
|
|
11054
|
+
inputTokensDetails: "prompt",
|
|
11055
|
+
completionTokensDetails: "completion",
|
|
11056
|
+
outputTokensDetails: "completion",
|
|
11057
|
+
costDetails: "cost",
|
|
11058
|
+
prompt_tokens_details: "prompt",
|
|
11059
|
+
input_tokens_details: "prompt",
|
|
11060
|
+
completion_tokens_details: "completion",
|
|
11061
|
+
output_tokens_details: "completion",
|
|
11062
|
+
cost_details: "cost"
|
|
11063
|
+
};
|
|
11064
|
+
function camelToSnake(value) {
|
|
11065
|
+
return value.replace(/[A-Z]/g, (match) => `_${match.toLowerCase()}`);
|
|
11066
|
+
}
|
|
11067
|
+
function parseOpenRouterMetricsFromUsage(usage) {
|
|
11068
|
+
if (!isObject(usage)) {
|
|
11069
|
+
return {};
|
|
10296
11070
|
}
|
|
10297
|
-
|
|
10298
|
-
|
|
10299
|
-
if (
|
|
10300
|
-
|
|
10301
|
-
|
|
10302
|
-
}
|
|
10303
|
-
if (integrations.anthropic !== false) {
|
|
10304
|
-
this.anthropicPlugin = new AnthropicPlugin();
|
|
10305
|
-
this.anthropicPlugin.enable();
|
|
11071
|
+
const metrics = {};
|
|
11072
|
+
for (const [name, value] of Object.entries(usage)) {
|
|
11073
|
+
if (typeof value === "number") {
|
|
11074
|
+
metrics[TOKEN_NAME_MAP2[name] || camelToSnake(name)] = value;
|
|
11075
|
+
continue;
|
|
10306
11076
|
}
|
|
10307
|
-
if (
|
|
10308
|
-
|
|
10309
|
-
this.aiSDKPlugin.enable();
|
|
11077
|
+
if (!isObject(value)) {
|
|
11078
|
+
continue;
|
|
10310
11079
|
}
|
|
10311
|
-
|
|
10312
|
-
|
|
10313
|
-
|
|
11080
|
+
const prefix = TOKEN_DETAIL_PREFIX_MAP[name];
|
|
11081
|
+
if (!prefix) {
|
|
11082
|
+
continue;
|
|
10314
11083
|
}
|
|
10315
|
-
|
|
10316
|
-
|
|
10317
|
-
|
|
11084
|
+
for (const [nestedName, nestedValue] of Object.entries(value)) {
|
|
11085
|
+
if (typeof nestedValue !== "number") {
|
|
11086
|
+
continue;
|
|
11087
|
+
}
|
|
11088
|
+
metrics[`${prefix}_${camelToSnake(nestedName)}`] = nestedValue;
|
|
10318
11089
|
}
|
|
10319
11090
|
}
|
|
10320
|
-
|
|
10321
|
-
|
|
10322
|
-
|
|
10323
|
-
|
|
10324
|
-
|
|
10325
|
-
|
|
11091
|
+
return metrics;
|
|
11092
|
+
}
|
|
11093
|
+
function extractOpenRouterUsageMetadata(usage) {
|
|
11094
|
+
if (!isObject(usage)) {
|
|
11095
|
+
return void 0;
|
|
11096
|
+
}
|
|
11097
|
+
const metadata = {};
|
|
11098
|
+
if (typeof usage.isByok === "boolean") {
|
|
11099
|
+
metadata.is_byok = usage.isByok;
|
|
11100
|
+
} else if (typeof usage.is_byok === "boolean") {
|
|
11101
|
+
metadata.is_byok = usage.is_byok;
|
|
11102
|
+
}
|
|
11103
|
+
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
11104
|
+
}
|
|
11105
|
+
|
|
11106
|
+
// src/openrouter-logging.ts
|
|
11107
|
+
var OMITTED_OPENROUTER_KEYS = /* @__PURE__ */ new Set([
|
|
11108
|
+
"execute",
|
|
11109
|
+
"render",
|
|
11110
|
+
"nextTurnParams",
|
|
11111
|
+
"requireApproval"
|
|
11112
|
+
]);
|
|
11113
|
+
function parseOpenRouterModelString(model) {
|
|
11114
|
+
if (typeof model !== "string") {
|
|
11115
|
+
return { model };
|
|
11116
|
+
}
|
|
11117
|
+
const slashIndex = model.indexOf("/");
|
|
11118
|
+
if (slashIndex > 0 && slashIndex < model.length - 1) {
|
|
11119
|
+
return {
|
|
11120
|
+
provider: model.substring(0, slashIndex),
|
|
11121
|
+
model: model.substring(slashIndex + 1)
|
|
11122
|
+
};
|
|
11123
|
+
}
|
|
11124
|
+
return { model };
|
|
11125
|
+
}
|
|
11126
|
+
function isZodSchema2(value) {
|
|
11127
|
+
return value != null && typeof value === "object" && "_def" in value && typeof value._def === "object";
|
|
11128
|
+
}
|
|
11129
|
+
function serializeZodSchema2(schema) {
|
|
11130
|
+
try {
|
|
11131
|
+
return zodToJsonSchema(schema);
|
|
11132
|
+
} catch {
|
|
11133
|
+
return {
|
|
11134
|
+
type: "object",
|
|
11135
|
+
description: "Zod schema (conversion failed)"
|
|
11136
|
+
};
|
|
11137
|
+
}
|
|
11138
|
+
}
|
|
11139
|
+
function serializeOpenRouterTool(tool) {
|
|
11140
|
+
if (!isObject(tool)) {
|
|
11141
|
+
return tool;
|
|
11142
|
+
}
|
|
11143
|
+
const serialized = {};
|
|
11144
|
+
for (const [key, value] of Object.entries(tool)) {
|
|
11145
|
+
if (OMITTED_OPENROUTER_KEYS.has(key)) {
|
|
11146
|
+
continue;
|
|
11147
|
+
}
|
|
11148
|
+
if (key === "function" && isObject(value)) {
|
|
11149
|
+
serialized.function = sanitizeOpenRouterLoggedValue(value);
|
|
11150
|
+
continue;
|
|
11151
|
+
}
|
|
11152
|
+
serialized[key] = sanitizeOpenRouterLoggedValue(value);
|
|
11153
|
+
}
|
|
11154
|
+
return serialized;
|
|
11155
|
+
}
|
|
11156
|
+
function serializeOpenRouterToolsForLogging(tools) {
|
|
11157
|
+
if (!Array.isArray(tools)) {
|
|
11158
|
+
return void 0;
|
|
11159
|
+
}
|
|
11160
|
+
return tools.map((tool) => serializeOpenRouterTool(tool));
|
|
11161
|
+
}
|
|
11162
|
+
function sanitizeOpenRouterLoggedValue(value) {
|
|
11163
|
+
if (isZodSchema2(value)) {
|
|
11164
|
+
return serializeZodSchema2(value);
|
|
11165
|
+
}
|
|
11166
|
+
if (typeof value === "function") {
|
|
11167
|
+
return "[Function]";
|
|
11168
|
+
}
|
|
11169
|
+
if (Array.isArray(value)) {
|
|
11170
|
+
return value.map((entry) => sanitizeOpenRouterLoggedValue(entry));
|
|
11171
|
+
}
|
|
11172
|
+
if (!isObject(value)) {
|
|
11173
|
+
return value;
|
|
11174
|
+
}
|
|
11175
|
+
const sanitized = {};
|
|
11176
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
11177
|
+
if (OMITTED_OPENROUTER_KEYS.has(key)) {
|
|
11178
|
+
continue;
|
|
11179
|
+
}
|
|
11180
|
+
if (key === "tools" && Array.isArray(entry)) {
|
|
11181
|
+
sanitized.tools = serializeOpenRouterToolsForLogging(entry);
|
|
11182
|
+
continue;
|
|
11183
|
+
}
|
|
11184
|
+
sanitized[key] = sanitizeOpenRouterLoggedValue(entry);
|
|
11185
|
+
}
|
|
11186
|
+
return sanitized;
|
|
11187
|
+
}
|
|
11188
|
+
function buildOpenRouterMetadata(metadata, httpReferer, xTitle) {
|
|
11189
|
+
const sanitized = sanitizeOpenRouterLoggedValue(metadata);
|
|
11190
|
+
const metadataRecord = isObject(sanitized) ? sanitized : {};
|
|
11191
|
+
const { model, provider: providerRouting, ...rest } = metadataRecord;
|
|
11192
|
+
const normalizedModel = parseOpenRouterModelString(model);
|
|
11193
|
+
return {
|
|
11194
|
+
...rest,
|
|
11195
|
+
...normalizedModel.model !== void 0 ? { model: normalizedModel.model } : {},
|
|
11196
|
+
...providerRouting !== void 0 ? { providerRouting } : {},
|
|
11197
|
+
...httpReferer !== void 0 ? { httpReferer } : {},
|
|
11198
|
+
...xTitle !== void 0 ? { xTitle } : {},
|
|
11199
|
+
provider: normalizedModel.provider || "openrouter"
|
|
11200
|
+
};
|
|
11201
|
+
}
|
|
11202
|
+
function buildOpenRouterEmbeddingMetadata(metadata, httpReferer, xTitle) {
|
|
11203
|
+
const normalized = buildOpenRouterMetadata(metadata, httpReferer, xTitle);
|
|
11204
|
+
return typeof normalized.model === "string" ? {
|
|
11205
|
+
...normalized,
|
|
11206
|
+
embedding_model: normalized.model
|
|
11207
|
+
} : normalized;
|
|
11208
|
+
}
|
|
11209
|
+
function extractOpenRouterCallModelInput(request) {
|
|
11210
|
+
return isObject(request) && "input" in request ? sanitizeOpenRouterLoggedValue(request.input) : void 0;
|
|
11211
|
+
}
|
|
11212
|
+
function extractOpenRouterCallModelMetadata(request) {
|
|
11213
|
+
if (!isObject(request)) {
|
|
11214
|
+
return { provider: "openrouter" };
|
|
11215
|
+
}
|
|
11216
|
+
const { input: _input, ...metadata } = request;
|
|
11217
|
+
return buildOpenRouterMetadata(metadata, void 0, void 0);
|
|
11218
|
+
}
|
|
11219
|
+
function extractOpenRouterResponseMetadata(result) {
|
|
11220
|
+
if (!isObject(result)) {
|
|
11221
|
+
return void 0;
|
|
11222
|
+
}
|
|
11223
|
+
const { output: _output, data: _data, usage, ...metadata } = result;
|
|
11224
|
+
const sanitized = sanitizeOpenRouterLoggedValue(metadata);
|
|
11225
|
+
const metadataRecord = isObject(sanitized) ? sanitized : {};
|
|
11226
|
+
const { model, provider, ...rest } = metadataRecord;
|
|
11227
|
+
const normalizedModel = parseOpenRouterModelString(model);
|
|
11228
|
+
const normalizedProvider = (typeof provider === "string" ? provider : void 0) || normalizedModel.provider;
|
|
11229
|
+
const usageMetadata = extractOpenRouterUsageMetadata(usage);
|
|
11230
|
+
const combined = {
|
|
11231
|
+
...rest,
|
|
11232
|
+
...normalizedModel.model !== void 0 ? { model: normalizedModel.model } : {},
|
|
11233
|
+
...usageMetadata || {},
|
|
11234
|
+
...normalizedProvider !== void 0 ? { provider: normalizedProvider } : {}
|
|
11235
|
+
};
|
|
11236
|
+
return Object.keys(combined).length > 0 ? combined : void 0;
|
|
11237
|
+
}
|
|
11238
|
+
function extractOpenRouterResponseOutput(response, fallbackOutput) {
|
|
11239
|
+
if (isObject(response) && "output" in response && response.output !== void 0) {
|
|
11240
|
+
return sanitizeOpenRouterLoggedValue(response.output);
|
|
11241
|
+
}
|
|
11242
|
+
if (fallbackOutput !== void 0) {
|
|
11243
|
+
return sanitizeOpenRouterLoggedValue(fallbackOutput);
|
|
11244
|
+
}
|
|
11245
|
+
return void 0;
|
|
11246
|
+
}
|
|
11247
|
+
|
|
11248
|
+
// src/openrouter-tool-wrapping.ts
|
|
11249
|
+
var OPENROUTER_WRAPPED_TOOL = Symbol("braintrust.openrouter.wrappedTool");
|
|
11250
|
+
var OPENROUTER_WRAPPED_CALL_MODEL_RESULT = Symbol(
|
|
11251
|
+
"braintrust.openrouter.wrappedCallModelResult"
|
|
11252
|
+
);
|
|
11253
|
+
var OPENROUTER_CALL_MODEL_STREAM_METHODS = [
|
|
11254
|
+
"getFullResponsesStream",
|
|
11255
|
+
"getItemsStream",
|
|
11256
|
+
"getNewMessagesStream",
|
|
11257
|
+
"getReasoningStream",
|
|
11258
|
+
"getTextStream",
|
|
11259
|
+
"getToolCallsStream",
|
|
11260
|
+
"getToolStream"
|
|
11261
|
+
];
|
|
11262
|
+
var OPENROUTER_CALL_MODEL_CONTEXT_METHODS = [
|
|
11263
|
+
"cancel",
|
|
11264
|
+
"getPendingToolCalls",
|
|
11265
|
+
"getState",
|
|
11266
|
+
"getToolCalls",
|
|
11267
|
+
"requiresApproval"
|
|
11268
|
+
];
|
|
11269
|
+
function patchOpenRouterCallModelRequestTools(request) {
|
|
11270
|
+
if (!Array.isArray(request.tools) || request.tools.length === 0) {
|
|
11271
|
+
return void 0;
|
|
11272
|
+
}
|
|
11273
|
+
const originalTools = request.tools;
|
|
11274
|
+
const wrappedTools = originalTools.map((tool) => wrapOpenRouterTool(tool));
|
|
11275
|
+
const didPatch = wrappedTools.some(
|
|
11276
|
+
(tool, index) => tool !== originalTools[index]
|
|
11277
|
+
);
|
|
11278
|
+
if (!didPatch) {
|
|
11279
|
+
return void 0;
|
|
11280
|
+
}
|
|
11281
|
+
request.tools = wrappedTools;
|
|
11282
|
+
return () => {
|
|
11283
|
+
request.tools = originalTools;
|
|
11284
|
+
};
|
|
11285
|
+
}
|
|
11286
|
+
function patchOpenRouterCallModelResult(span, result, request) {
|
|
11287
|
+
if (!isObject(result) || isWrappedCallModelResult(result)) {
|
|
11288
|
+
return false;
|
|
11289
|
+
}
|
|
11290
|
+
const resultLike = result;
|
|
11291
|
+
const hasInstrumentableMethod = typeof resultLike.getResponse === "function" || typeof resultLike.getText === "function" || OPENROUTER_CALL_MODEL_STREAM_METHODS.some(
|
|
11292
|
+
(methodName) => typeof resultLike[methodName] === "function"
|
|
11293
|
+
);
|
|
11294
|
+
if (!hasInstrumentableMethod) {
|
|
11295
|
+
return false;
|
|
11296
|
+
}
|
|
11297
|
+
Object.defineProperty(resultLike, OPENROUTER_WRAPPED_CALL_MODEL_RESULT, {
|
|
11298
|
+
value: true,
|
|
11299
|
+
enumerable: false,
|
|
11300
|
+
configurable: false
|
|
11301
|
+
});
|
|
11302
|
+
const originalGetResponse = typeof resultLike.getResponse === "function" ? resultLike.getResponse.bind(resultLike) : void 0;
|
|
11303
|
+
const originalGetInitialResponse = typeof resultLike.getInitialResponse === "function" ? resultLike.getInitialResponse.bind(resultLike) : void 0;
|
|
11304
|
+
const originalMakeFollowupRequest = typeof resultLike.makeFollowupRequest === "function" ? resultLike.makeFollowupRequest.bind(resultLike) : void 0;
|
|
11305
|
+
let ended = false;
|
|
11306
|
+
let tracedTurnCount = 0;
|
|
11307
|
+
const endSpanWithResult = async (response, fallbackOutput) => {
|
|
11308
|
+
if (ended) {
|
|
11309
|
+
return;
|
|
11310
|
+
}
|
|
11311
|
+
ended = true;
|
|
11312
|
+
const finalResponse = getFinalOpenRouterCallModelResponse(
|
|
11313
|
+
resultLike,
|
|
11314
|
+
response
|
|
11315
|
+
);
|
|
11316
|
+
if (finalResponse) {
|
|
11317
|
+
const rounds = getOpenRouterCallModelRounds(resultLike);
|
|
11318
|
+
const metadata = extractOpenRouterCallModelResultMetadata(
|
|
11319
|
+
finalResponse,
|
|
11320
|
+
rounds.length + 1
|
|
11321
|
+
);
|
|
11322
|
+
span.log({
|
|
11323
|
+
output: extractOpenRouterResponseOutput(finalResponse, fallbackOutput),
|
|
11324
|
+
...metadata ? { metadata } : {},
|
|
11325
|
+
metrics: aggregateOpenRouterCallModelMetrics(rounds, finalResponse)
|
|
11326
|
+
});
|
|
11327
|
+
span.end();
|
|
11328
|
+
return;
|
|
11329
|
+
}
|
|
11330
|
+
if (fallbackOutput !== void 0) {
|
|
11331
|
+
span.log({
|
|
11332
|
+
output: fallbackOutput
|
|
11333
|
+
});
|
|
11334
|
+
}
|
|
11335
|
+
span.end();
|
|
11336
|
+
};
|
|
11337
|
+
const endSpanWithError = (error) => {
|
|
11338
|
+
if (ended) {
|
|
11339
|
+
return;
|
|
11340
|
+
}
|
|
11341
|
+
ended = true;
|
|
11342
|
+
span.log({
|
|
11343
|
+
error: normalizeError(error).message
|
|
11344
|
+
});
|
|
11345
|
+
span.end();
|
|
11346
|
+
};
|
|
11347
|
+
const finalizeFromResponse = async (fallbackOutput) => {
|
|
11348
|
+
if (!originalGetResponse) {
|
|
11349
|
+
await endSpanWithResult(void 0, fallbackOutput);
|
|
11350
|
+
return;
|
|
11351
|
+
}
|
|
11352
|
+
try {
|
|
11353
|
+
await endSpanWithResult(await originalGetResponse(), fallbackOutput);
|
|
11354
|
+
} catch {
|
|
11355
|
+
await endSpanWithResult(void 0, fallbackOutput);
|
|
11356
|
+
}
|
|
11357
|
+
};
|
|
11358
|
+
if (originalGetResponse) {
|
|
11359
|
+
resultLike.getResponse = async (...args) => {
|
|
11360
|
+
return await withCurrent(span, async () => {
|
|
11361
|
+
try {
|
|
11362
|
+
const response = await originalGetResponse(...args);
|
|
11363
|
+
await endSpanWithResult(response);
|
|
11364
|
+
return response;
|
|
11365
|
+
} catch (error) {
|
|
11366
|
+
endSpanWithError(error);
|
|
11367
|
+
throw error;
|
|
11368
|
+
}
|
|
11369
|
+
});
|
|
11370
|
+
};
|
|
11371
|
+
}
|
|
11372
|
+
if (typeof resultLike.getText === "function") {
|
|
11373
|
+
const originalGetText = resultLike.getText.bind(resultLike);
|
|
11374
|
+
resultLike.getText = async (...args) => {
|
|
11375
|
+
return await withCurrent(span, async () => {
|
|
11376
|
+
try {
|
|
11377
|
+
const text = await originalGetText(...args);
|
|
11378
|
+
await finalizeFromResponse(text);
|
|
11379
|
+
return text;
|
|
11380
|
+
} catch (error) {
|
|
11381
|
+
endSpanWithError(error);
|
|
11382
|
+
throw error;
|
|
11383
|
+
}
|
|
11384
|
+
});
|
|
11385
|
+
};
|
|
11386
|
+
}
|
|
11387
|
+
for (const methodName of OPENROUTER_CALL_MODEL_CONTEXT_METHODS) {
|
|
11388
|
+
if (typeof resultLike[methodName] !== "function") {
|
|
11389
|
+
continue;
|
|
11390
|
+
}
|
|
11391
|
+
const originalMethod = resultLike[methodName];
|
|
11392
|
+
resultLike[methodName] = async (...args) => {
|
|
11393
|
+
return await withCurrent(span, async () => {
|
|
11394
|
+
return await originalMethod.apply(resultLike, args);
|
|
11395
|
+
});
|
|
11396
|
+
};
|
|
11397
|
+
}
|
|
11398
|
+
for (const methodName of OPENROUTER_CALL_MODEL_STREAM_METHODS) {
|
|
11399
|
+
if (typeof resultLike[methodName] !== "function") {
|
|
11400
|
+
continue;
|
|
11401
|
+
}
|
|
11402
|
+
const originalMethod = resultLike[methodName];
|
|
11403
|
+
resultLike[methodName] = (...args) => {
|
|
11404
|
+
const stream = withCurrent(
|
|
11405
|
+
span,
|
|
11406
|
+
() => originalMethod.apply(resultLike, args)
|
|
11407
|
+
);
|
|
11408
|
+
if (!isAsyncIterable2(stream)) {
|
|
11409
|
+
return stream;
|
|
11410
|
+
}
|
|
11411
|
+
return wrapAsyncIterableWithSpan({
|
|
11412
|
+
finalize: finalizeFromResponse,
|
|
11413
|
+
iteratorFactory: () => stream[Symbol.asyncIterator](),
|
|
11414
|
+
onError: endSpanWithError,
|
|
11415
|
+
span
|
|
11416
|
+
});
|
|
11417
|
+
};
|
|
11418
|
+
}
|
|
11419
|
+
if (originalGetInitialResponse) {
|
|
11420
|
+
let initialTurnTraced = false;
|
|
11421
|
+
resultLike.getInitialResponse = async (...args) => {
|
|
11422
|
+
if (initialTurnTraced) {
|
|
11423
|
+
return await withCurrent(span, async () => {
|
|
11424
|
+
return await originalGetInitialResponse(...args);
|
|
11425
|
+
});
|
|
11426
|
+
}
|
|
11427
|
+
initialTurnTraced = true;
|
|
11428
|
+
const resolvedRequest = getOpenRouterResolvedRequest(resultLike, request);
|
|
11429
|
+
const childSpan = startOpenRouterCallModelTurnSpan({
|
|
11430
|
+
request: resolvedRequest,
|
|
11431
|
+
step: tracedTurnCount + 1,
|
|
11432
|
+
stepType: tracedTurnCount === 0 ? "initial" : "continue"
|
|
11433
|
+
});
|
|
11434
|
+
return await withCurrent(childSpan, async () => {
|
|
11435
|
+
try {
|
|
11436
|
+
const response = await originalGetInitialResponse(...args);
|
|
11437
|
+
tracedTurnCount++;
|
|
11438
|
+
finishOpenRouterCallModelTurnSpan({
|
|
11439
|
+
response,
|
|
11440
|
+
step: tracedTurnCount,
|
|
11441
|
+
stepType: tracedTurnCount === 1 ? "initial" : "continue",
|
|
11442
|
+
span: childSpan
|
|
11443
|
+
});
|
|
11444
|
+
return response;
|
|
11445
|
+
} catch (error) {
|
|
11446
|
+
childSpan.log({
|
|
11447
|
+
error: normalizeError(error).message
|
|
11448
|
+
});
|
|
11449
|
+
childSpan.end();
|
|
11450
|
+
throw error;
|
|
11451
|
+
}
|
|
11452
|
+
});
|
|
11453
|
+
};
|
|
11454
|
+
}
|
|
11455
|
+
if (originalMakeFollowupRequest) {
|
|
11456
|
+
resultLike.makeFollowupRequest = async (...args) => {
|
|
11457
|
+
const currentResponse = args[0];
|
|
11458
|
+
const toolResults = Array.isArray(args[1]) ? args[1] : [];
|
|
11459
|
+
const resolvedRequest = getOpenRouterResolvedRequest(resultLike, request);
|
|
11460
|
+
const followupRequest = buildOpenRouterFollowupRequest(
|
|
11461
|
+
resolvedRequest,
|
|
11462
|
+
currentResponse,
|
|
11463
|
+
toolResults
|
|
11464
|
+
);
|
|
11465
|
+
const childSpan = startOpenRouterCallModelTurnSpan({
|
|
11466
|
+
request: followupRequest,
|
|
11467
|
+
step: tracedTurnCount + 1,
|
|
11468
|
+
stepType: "continue"
|
|
11469
|
+
});
|
|
11470
|
+
return await withCurrent(childSpan, async () => {
|
|
11471
|
+
try {
|
|
11472
|
+
const response = await originalMakeFollowupRequest(...args);
|
|
11473
|
+
tracedTurnCount++;
|
|
11474
|
+
finishOpenRouterCallModelTurnSpan({
|
|
11475
|
+
response,
|
|
11476
|
+
step: tracedTurnCount,
|
|
11477
|
+
stepType: "continue",
|
|
11478
|
+
span: childSpan
|
|
11479
|
+
});
|
|
11480
|
+
return response;
|
|
11481
|
+
} catch (error) {
|
|
11482
|
+
childSpan.log({
|
|
11483
|
+
error: normalizeError(error).message
|
|
11484
|
+
});
|
|
11485
|
+
childSpan.end();
|
|
11486
|
+
throw error;
|
|
11487
|
+
}
|
|
11488
|
+
});
|
|
11489
|
+
};
|
|
11490
|
+
}
|
|
11491
|
+
return true;
|
|
11492
|
+
}
|
|
11493
|
+
function wrapOpenRouterTool(tool) {
|
|
11494
|
+
if (isWrappedTool(tool) || !tool.function || typeof tool.function !== "object" || typeof tool.function.execute !== "function") {
|
|
11495
|
+
return tool;
|
|
11496
|
+
}
|
|
11497
|
+
const toolName = tool.function.name || "tool";
|
|
11498
|
+
const originalExecute = tool.function.execute;
|
|
11499
|
+
const wrappedTool = {
|
|
11500
|
+
...tool,
|
|
11501
|
+
function: {
|
|
11502
|
+
...tool.function,
|
|
11503
|
+
execute(...args) {
|
|
11504
|
+
return traceToolExecution({
|
|
11505
|
+
args,
|
|
11506
|
+
execute: () => Reflect.apply(originalExecute, this, args),
|
|
11507
|
+
toolCallId: getToolCallId(args[1]),
|
|
11508
|
+
toolName
|
|
11509
|
+
});
|
|
11510
|
+
}
|
|
11511
|
+
}
|
|
11512
|
+
};
|
|
11513
|
+
Object.defineProperty(wrappedTool, OPENROUTER_WRAPPED_TOOL, {
|
|
11514
|
+
value: true,
|
|
11515
|
+
enumerable: false,
|
|
11516
|
+
configurable: false
|
|
11517
|
+
});
|
|
11518
|
+
return wrappedTool;
|
|
11519
|
+
}
|
|
11520
|
+
function isWrappedTool(tool) {
|
|
11521
|
+
return Boolean(tool[OPENROUTER_WRAPPED_TOOL]);
|
|
11522
|
+
}
|
|
11523
|
+
function isWrappedCallModelResult(value) {
|
|
11524
|
+
return Boolean(
|
|
11525
|
+
isObject(value) && value[OPENROUTER_WRAPPED_CALL_MODEL_RESULT]
|
|
11526
|
+
);
|
|
11527
|
+
}
|
|
11528
|
+
function traceToolExecution(args) {
|
|
11529
|
+
const tracingChannel = openRouterChannels.toolExecute.tracingChannel();
|
|
11530
|
+
const input = args.args.length > 0 ? args.args[0] : void 0;
|
|
11531
|
+
const event = {
|
|
11532
|
+
arguments: [input],
|
|
11533
|
+
span_info: {
|
|
11534
|
+
name: args.toolName
|
|
11535
|
+
},
|
|
11536
|
+
toolCallId: args.toolCallId,
|
|
11537
|
+
toolName: args.toolName
|
|
11538
|
+
};
|
|
11539
|
+
tracingChannel.start.publish(event);
|
|
11540
|
+
try {
|
|
11541
|
+
const result = args.execute();
|
|
11542
|
+
return publishToolResult(tracingChannel, event, result);
|
|
11543
|
+
} catch (error) {
|
|
11544
|
+
event.error = normalizeError(error);
|
|
11545
|
+
tracingChannel.error.publish(event);
|
|
11546
|
+
throw error;
|
|
11547
|
+
}
|
|
11548
|
+
}
|
|
11549
|
+
function publishToolResult(tracingChannel, event, result) {
|
|
11550
|
+
if (isPromiseLike(result)) {
|
|
11551
|
+
return result.then(
|
|
11552
|
+
(resolved) => {
|
|
11553
|
+
event.result = resolved;
|
|
11554
|
+
tracingChannel.asyncEnd.publish(event);
|
|
11555
|
+
return resolved;
|
|
11556
|
+
},
|
|
11557
|
+
(error) => {
|
|
11558
|
+
event.error = normalizeError(error);
|
|
11559
|
+
tracingChannel.error.publish(event);
|
|
11560
|
+
throw error;
|
|
11561
|
+
}
|
|
11562
|
+
);
|
|
11563
|
+
}
|
|
11564
|
+
event.result = result;
|
|
11565
|
+
tracingChannel.asyncEnd.publish(event);
|
|
11566
|
+
return result;
|
|
11567
|
+
}
|
|
11568
|
+
function getToolCallId(context) {
|
|
11569
|
+
const toolContext = context;
|
|
11570
|
+
return typeof toolContext?.toolCall?.id === "string" ? toolContext.toolCall.id : void 0;
|
|
11571
|
+
}
|
|
11572
|
+
function extractOpenRouterCallModelResultMetadata(response, turnCount) {
|
|
11573
|
+
const combined = {
|
|
11574
|
+
...extractOpenRouterResponseMetadata(response) || {},
|
|
11575
|
+
...turnCount !== void 0 ? { turn_count: turnCount } : {}
|
|
11576
|
+
};
|
|
11577
|
+
return Object.keys(combined).length > 0 ? combined : void 0;
|
|
11578
|
+
}
|
|
11579
|
+
function getFinalOpenRouterCallModelResponse(result, response) {
|
|
11580
|
+
if (isObject(response)) {
|
|
11581
|
+
return response;
|
|
11582
|
+
}
|
|
11583
|
+
return isObject(result.finalResponse) ? result.finalResponse : void 0;
|
|
11584
|
+
}
|
|
11585
|
+
function getOpenRouterCallModelRounds(result) {
|
|
11586
|
+
if (!Array.isArray(result.allToolExecutionRounds)) {
|
|
11587
|
+
return [];
|
|
11588
|
+
}
|
|
11589
|
+
return result.allToolExecutionRounds.filter((round) => isObject(round)).map((round) => ({
|
|
11590
|
+
response: isObject(round.response) ? round.response : void 0,
|
|
11591
|
+
round: typeof round.round === "number" ? round.round : void 0,
|
|
11592
|
+
toolResults: Array.isArray(round.toolResults) ? round.toolResults : []
|
|
11593
|
+
})).filter((round) => round.response !== void 0);
|
|
11594
|
+
}
|
|
11595
|
+
function aggregateOpenRouterCallModelMetrics(rounds, finalResponse) {
|
|
11596
|
+
const metrics = {};
|
|
11597
|
+
const responses = [
|
|
11598
|
+
...rounds.map((round) => round.response).filter(isObject),
|
|
11599
|
+
finalResponse
|
|
11600
|
+
];
|
|
11601
|
+
for (const response of responses) {
|
|
11602
|
+
const responseMetrics = parseOpenRouterMetricsFromUsage(response.usage);
|
|
11603
|
+
for (const [name, value] of Object.entries(responseMetrics)) {
|
|
11604
|
+
metrics[name] = (metrics[name] || 0) + value;
|
|
11605
|
+
}
|
|
11606
|
+
}
|
|
11607
|
+
return metrics;
|
|
11608
|
+
}
|
|
11609
|
+
function buildNextOpenRouterCallModelInput(currentInput, response, toolResults) {
|
|
11610
|
+
const normalizedInput = Array.isArray(currentInput) ? [...currentInput] : currentInput === void 0 ? [] : [currentInput];
|
|
11611
|
+
const responseOutput = Array.isArray(response.output) ? response.output : response.output === void 0 ? [] : [response.output];
|
|
11612
|
+
return [...normalizedInput, ...responseOutput, ...toolResults].map(
|
|
11613
|
+
(entry) => sanitizeOpenRouterLoggedValue(entry)
|
|
11614
|
+
);
|
|
11615
|
+
}
|
|
11616
|
+
function startOpenRouterCallModelTurnSpan(args) {
|
|
11617
|
+
const requestRecord = isObject(args.request) ? args.request : void 0;
|
|
11618
|
+
const metadata = requestRecord ? extractOpenRouterCallModelMetadata(requestRecord) : { provider: "openrouter" };
|
|
11619
|
+
if (isObject(metadata) && "tools" in metadata) {
|
|
11620
|
+
delete metadata.tools;
|
|
11621
|
+
}
|
|
11622
|
+
return startSpan({
|
|
11623
|
+
name: "openrouter.beta.responses.send",
|
|
11624
|
+
spanAttributes: {
|
|
11625
|
+
type: "llm" /* LLM */
|
|
11626
|
+
},
|
|
11627
|
+
event: {
|
|
11628
|
+
input: requestRecord ? extractOpenRouterCallModelInput(requestRecord) : void 0,
|
|
11629
|
+
metadata: {
|
|
11630
|
+
...metadata,
|
|
11631
|
+
step: args.step,
|
|
11632
|
+
step_type: args.stepType
|
|
11633
|
+
}
|
|
11634
|
+
}
|
|
11635
|
+
});
|
|
11636
|
+
}
|
|
11637
|
+
function finishOpenRouterCallModelTurnSpan(args) {
|
|
11638
|
+
if (!isObject(args.response)) {
|
|
11639
|
+
args.span.end();
|
|
11640
|
+
return;
|
|
11641
|
+
}
|
|
11642
|
+
args.span.log({
|
|
11643
|
+
output: extractOpenRouterResponseOutput(args.response),
|
|
11644
|
+
...extractOpenRouterResponseMetadata(args.response) ? {
|
|
11645
|
+
metadata: {
|
|
11646
|
+
...extractOpenRouterResponseMetadata(args.response),
|
|
11647
|
+
...args.step !== void 0 ? { step: args.step } : {},
|
|
11648
|
+
...args.stepType ? { step_type: args.stepType } : {}
|
|
11649
|
+
}
|
|
11650
|
+
} : {},
|
|
11651
|
+
metrics: parseOpenRouterMetricsFromUsage(args.response.usage)
|
|
11652
|
+
});
|
|
11653
|
+
args.span.end();
|
|
11654
|
+
}
|
|
11655
|
+
function getOpenRouterResolvedRequest(result, request) {
|
|
11656
|
+
if (isObject(result.resolvedRequest)) {
|
|
11657
|
+
return result.resolvedRequest;
|
|
11658
|
+
}
|
|
11659
|
+
return request;
|
|
11660
|
+
}
|
|
11661
|
+
function buildOpenRouterFollowupRequest(request, currentResponse, toolResults) {
|
|
11662
|
+
if (!request) {
|
|
11663
|
+
return void 0;
|
|
11664
|
+
}
|
|
11665
|
+
return {
|
|
11666
|
+
...request,
|
|
11667
|
+
input: buildNextOpenRouterCallModelInput(
|
|
11668
|
+
extractOpenRouterCallModelInput(request),
|
|
11669
|
+
isObject(currentResponse) ? currentResponse : {},
|
|
11670
|
+
toolResults
|
|
11671
|
+
),
|
|
11672
|
+
stream: false
|
|
11673
|
+
};
|
|
11674
|
+
}
|
|
11675
|
+
function wrapAsyncIterableWithSpan(args) {
|
|
11676
|
+
return {
|
|
11677
|
+
[Symbol.asyncIterator]() {
|
|
11678
|
+
const iterator = args.iteratorFactory();
|
|
11679
|
+
return {
|
|
11680
|
+
next(value) {
|
|
11681
|
+
return withCurrent(
|
|
11682
|
+
args.span,
|
|
11683
|
+
() => value === void 0 ? iterator.next() : iterator.next(value)
|
|
11684
|
+
).then(
|
|
11685
|
+
async (result) => {
|
|
11686
|
+
if (result.done) {
|
|
11687
|
+
await args.finalize();
|
|
11688
|
+
}
|
|
11689
|
+
return result;
|
|
11690
|
+
},
|
|
11691
|
+
(error) => {
|
|
11692
|
+
args.onError(error);
|
|
11693
|
+
throw error;
|
|
11694
|
+
}
|
|
11695
|
+
);
|
|
11696
|
+
},
|
|
11697
|
+
return(value) {
|
|
11698
|
+
if (typeof iterator.return !== "function") {
|
|
11699
|
+
return args.finalize().then(() => ({
|
|
11700
|
+
done: true,
|
|
11701
|
+
value
|
|
11702
|
+
}));
|
|
11703
|
+
}
|
|
11704
|
+
return withCurrent(args.span, () => iterator.return(value)).then(
|
|
11705
|
+
async (result) => {
|
|
11706
|
+
await args.finalize();
|
|
11707
|
+
return result;
|
|
11708
|
+
},
|
|
11709
|
+
(error) => {
|
|
11710
|
+
args.onError(error);
|
|
11711
|
+
throw error;
|
|
11712
|
+
}
|
|
11713
|
+
);
|
|
11714
|
+
},
|
|
11715
|
+
throw(error) {
|
|
11716
|
+
args.onError(error);
|
|
11717
|
+
if (typeof iterator.throw !== "function") {
|
|
11718
|
+
return Promise.reject(error);
|
|
11719
|
+
}
|
|
11720
|
+
return withCurrent(args.span, () => iterator.throw(error));
|
|
11721
|
+
},
|
|
11722
|
+
[Symbol.asyncIterator]() {
|
|
11723
|
+
return this;
|
|
11724
|
+
}
|
|
11725
|
+
};
|
|
11726
|
+
}
|
|
11727
|
+
};
|
|
11728
|
+
}
|
|
11729
|
+
function isAsyncIterable2(value) {
|
|
11730
|
+
return !!value && (typeof value === "object" || typeof value === "function") && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
|
|
11731
|
+
}
|
|
11732
|
+
function isPromiseLike(value) {
|
|
11733
|
+
return !!value && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function";
|
|
11734
|
+
}
|
|
11735
|
+
function normalizeError(error) {
|
|
11736
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
11737
|
+
}
|
|
11738
|
+
|
|
11739
|
+
// src/instrumentation/plugins/openrouter-plugin.ts
|
|
11740
|
+
var OpenRouterPlugin = class extends BasePlugin {
|
|
11741
|
+
onEnable() {
|
|
11742
|
+
this.subscribeToOpenRouterChannels();
|
|
11743
|
+
}
|
|
11744
|
+
onDisable() {
|
|
11745
|
+
this.unsubscribers = unsubscribeAll(this.unsubscribers);
|
|
11746
|
+
}
|
|
11747
|
+
subscribeToOpenRouterChannels() {
|
|
11748
|
+
this.unsubscribers.push(
|
|
11749
|
+
traceStreamingChannel(openRouterChannels.chatSend, {
|
|
11750
|
+
name: "openrouter.chat.send",
|
|
11751
|
+
type: "llm" /* LLM */,
|
|
11752
|
+
extractInput: (args) => {
|
|
11753
|
+
const request = getOpenRouterRequestArg(args);
|
|
11754
|
+
const chatGenerationParams = isObject(request?.chatGenerationParams) ? request.chatGenerationParams : {};
|
|
11755
|
+
const httpReferer = request?.httpReferer;
|
|
11756
|
+
const xTitle = request?.xTitle;
|
|
11757
|
+
const { messages, ...metadata } = chatGenerationParams;
|
|
11758
|
+
return {
|
|
11759
|
+
input: messages,
|
|
11760
|
+
metadata: buildOpenRouterMetadata(metadata, httpReferer, xTitle)
|
|
11761
|
+
};
|
|
11762
|
+
},
|
|
11763
|
+
extractOutput: (result) => {
|
|
11764
|
+
return isObject(result) ? result.choices : void 0;
|
|
11765
|
+
},
|
|
11766
|
+
extractMetrics: (result, startTime) => {
|
|
11767
|
+
const metrics = parseOpenRouterMetricsFromUsage(result?.usage);
|
|
11768
|
+
if (startTime) {
|
|
11769
|
+
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
11770
|
+
}
|
|
11771
|
+
return metrics;
|
|
11772
|
+
},
|
|
11773
|
+
aggregateChunks: aggregateOpenRouterChatChunks
|
|
11774
|
+
})
|
|
11775
|
+
);
|
|
11776
|
+
this.unsubscribers.push(
|
|
11777
|
+
traceAsyncChannel(openRouterChannels.embeddingsGenerate, {
|
|
11778
|
+
name: "openrouter.embeddings.generate",
|
|
11779
|
+
type: "llm" /* LLM */,
|
|
11780
|
+
extractInput: (args) => {
|
|
11781
|
+
const request = getOpenRouterRequestArg(args);
|
|
11782
|
+
const requestBody = isObject(request?.requestBody) ? request.requestBody : {};
|
|
11783
|
+
const httpReferer = request?.httpReferer;
|
|
11784
|
+
const xTitle = request?.xTitle;
|
|
11785
|
+
const { input, ...metadata } = requestBody;
|
|
11786
|
+
return {
|
|
11787
|
+
input,
|
|
11788
|
+
metadata: buildOpenRouterEmbeddingMetadata(
|
|
11789
|
+
metadata,
|
|
11790
|
+
httpReferer,
|
|
11791
|
+
xTitle
|
|
11792
|
+
)
|
|
11793
|
+
};
|
|
11794
|
+
},
|
|
11795
|
+
extractOutput: (result) => {
|
|
11796
|
+
if (!isObject(result)) {
|
|
11797
|
+
return void 0;
|
|
11798
|
+
}
|
|
11799
|
+
const embedding = result.data?.[0]?.embedding;
|
|
11800
|
+
return Array.isArray(embedding) ? { embedding_length: embedding.length } : void 0;
|
|
11801
|
+
},
|
|
11802
|
+
extractMetadata: (result) => {
|
|
11803
|
+
if (!isObject(result)) {
|
|
11804
|
+
return void 0;
|
|
11805
|
+
}
|
|
11806
|
+
return extractOpenRouterResponseMetadata(result);
|
|
11807
|
+
},
|
|
11808
|
+
extractMetrics: (result) => {
|
|
11809
|
+
return isObject(result) ? parseOpenRouterMetricsFromUsage(result.usage) : {};
|
|
11810
|
+
}
|
|
11811
|
+
})
|
|
11812
|
+
);
|
|
11813
|
+
this.unsubscribers.push(
|
|
11814
|
+
traceStreamingChannel(openRouterChannels.betaResponsesSend, {
|
|
11815
|
+
name: "openrouter.beta.responses.send",
|
|
11816
|
+
type: "llm" /* LLM */,
|
|
11817
|
+
extractInput: (args) => {
|
|
11818
|
+
const request = getOpenRouterRequestArg(args);
|
|
11819
|
+
const openResponsesRequest = isObject(request?.openResponsesRequest) ? request.openResponsesRequest : {};
|
|
11820
|
+
const httpReferer = request?.httpReferer;
|
|
11821
|
+
const xTitle = request?.xTitle;
|
|
11822
|
+
const { input, ...metadata } = openResponsesRequest;
|
|
11823
|
+
return {
|
|
11824
|
+
input,
|
|
11825
|
+
metadata: buildOpenRouterMetadata(metadata, httpReferer, xTitle)
|
|
11826
|
+
};
|
|
11827
|
+
},
|
|
11828
|
+
extractOutput: (result) => extractOpenRouterResponseOutput(result),
|
|
11829
|
+
extractMetadata: (result) => extractOpenRouterResponseMetadata(result),
|
|
11830
|
+
extractMetrics: (result, startTime) => {
|
|
11831
|
+
const metrics = parseOpenRouterMetricsFromUsage(result?.usage);
|
|
11832
|
+
if (startTime) {
|
|
11833
|
+
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
11834
|
+
}
|
|
11835
|
+
return metrics;
|
|
11836
|
+
},
|
|
11837
|
+
aggregateChunks: aggregateOpenRouterResponseStreamEvents
|
|
11838
|
+
})
|
|
11839
|
+
);
|
|
11840
|
+
this.unsubscribers.push(
|
|
11841
|
+
traceSyncStreamChannel(openRouterChannels.callModel, {
|
|
11842
|
+
name: "openrouter.callModel",
|
|
11843
|
+
type: "llm" /* LLM */,
|
|
11844
|
+
extractInput: (args) => {
|
|
11845
|
+
const request = getOpenRouterCallModelRequestArg(args);
|
|
11846
|
+
return {
|
|
11847
|
+
input: request ? extractOpenRouterCallModelInput(request) : void 0,
|
|
11848
|
+
metadata: request ? extractOpenRouterCallModelMetadata(request) : { provider: "openrouter" }
|
|
11849
|
+
};
|
|
11850
|
+
},
|
|
11851
|
+
patchResult: ({ endEvent, result, span }) => {
|
|
11852
|
+
return patchOpenRouterCallModelResult(
|
|
11853
|
+
span,
|
|
11854
|
+
result,
|
|
11855
|
+
getOpenRouterCallModelRequestArg(endEvent.arguments)
|
|
11856
|
+
);
|
|
11857
|
+
}
|
|
11858
|
+
})
|
|
11859
|
+
);
|
|
11860
|
+
this.unsubscribers.push(
|
|
11861
|
+
traceStreamingChannel(openRouterChannels.toolExecute, {
|
|
11862
|
+
name: "openrouter.tool",
|
|
11863
|
+
type: "tool" /* TOOL */,
|
|
11864
|
+
extractInput: (args, event) => ({
|
|
11865
|
+
input: args[0],
|
|
11866
|
+
metadata: {
|
|
11867
|
+
provider: "openrouter",
|
|
11868
|
+
tool_name: event.toolName,
|
|
11869
|
+
...event.toolCallId ? { tool_call_id: event.toolCallId } : {}
|
|
11870
|
+
}
|
|
11871
|
+
}),
|
|
11872
|
+
extractOutput: (result) => result,
|
|
11873
|
+
extractMetrics: () => ({}),
|
|
11874
|
+
aggregateChunks: (chunks) => ({
|
|
11875
|
+
output: chunks.length > 0 ? chunks[chunks.length - 1] : void 0,
|
|
11876
|
+
metrics: {}
|
|
11877
|
+
})
|
|
11878
|
+
})
|
|
11879
|
+
);
|
|
11880
|
+
const callModelChannel = openRouterChannels.callModel.tracingChannel();
|
|
11881
|
+
const callModelHandlers = {
|
|
11882
|
+
start: (event) => {
|
|
11883
|
+
const request = getOpenRouterCallModelRequestArg(event.arguments);
|
|
11884
|
+
if (!request) {
|
|
11885
|
+
return;
|
|
11886
|
+
}
|
|
11887
|
+
patchOpenRouterCallModelRequestTools(request);
|
|
11888
|
+
}
|
|
11889
|
+
};
|
|
11890
|
+
callModelChannel.subscribe(callModelHandlers);
|
|
11891
|
+
this.unsubscribers.push(() => {
|
|
11892
|
+
callModelChannel.unsubscribe(callModelHandlers);
|
|
11893
|
+
});
|
|
11894
|
+
}
|
|
11895
|
+
};
|
|
11896
|
+
function normalizeArgs(args) {
|
|
11897
|
+
if (Array.isArray(args)) {
|
|
11898
|
+
return args;
|
|
11899
|
+
}
|
|
11900
|
+
if (isArrayLike(args)) {
|
|
11901
|
+
return Array.from(args);
|
|
11902
|
+
}
|
|
11903
|
+
return [args];
|
|
11904
|
+
}
|
|
11905
|
+
function isArrayLike(value) {
|
|
11906
|
+
return isObject(value) && "length" in value && typeof value.length === "number" && Number.isInteger(value.length) && value.length >= 0;
|
|
11907
|
+
}
|
|
11908
|
+
function getOpenRouterRequestArg(args) {
|
|
11909
|
+
const normalizedArgs = normalizeArgs(args);
|
|
11910
|
+
const keyedCandidate = normalizedArgs.find(
|
|
11911
|
+
(arg) => isObject(arg) && ("chatGenerationParams" in arg || "requestBody" in arg || "openResponsesRequest" in arg)
|
|
11912
|
+
);
|
|
11913
|
+
if (isObject(keyedCandidate)) {
|
|
11914
|
+
return keyedCandidate;
|
|
11915
|
+
}
|
|
11916
|
+
const firstObjectArg = normalizedArgs.find((arg) => isObject(arg));
|
|
11917
|
+
return isObject(firstObjectArg) ? firstObjectArg : void 0;
|
|
11918
|
+
}
|
|
11919
|
+
function getOpenRouterCallModelRequestArg(args) {
|
|
11920
|
+
const firstObjectArg = normalizeArgs(args).find((arg) => isObject(arg));
|
|
11921
|
+
return isObject(firstObjectArg) ? firstObjectArg : void 0;
|
|
11922
|
+
}
|
|
11923
|
+
function aggregateOpenRouterChatChunks(chunks) {
|
|
11924
|
+
let role;
|
|
11925
|
+
let content = "";
|
|
11926
|
+
let toolCalls;
|
|
11927
|
+
let finishReason;
|
|
11928
|
+
let metrics = {};
|
|
11929
|
+
for (const chunk of chunks) {
|
|
11930
|
+
metrics = {
|
|
11931
|
+
...metrics,
|
|
11932
|
+
...parseOpenRouterMetricsFromUsage(chunk?.usage)
|
|
11933
|
+
};
|
|
11934
|
+
const choice = chunk?.choices?.[0];
|
|
11935
|
+
const delta = choice?.delta;
|
|
11936
|
+
if (!delta) {
|
|
11937
|
+
if (choice?.finish_reason !== void 0) {
|
|
11938
|
+
finishReason = choice.finish_reason;
|
|
11939
|
+
}
|
|
11940
|
+
continue;
|
|
11941
|
+
}
|
|
11942
|
+
if (!role && delta.role) {
|
|
11943
|
+
role = delta.role;
|
|
11944
|
+
}
|
|
11945
|
+
if (typeof delta.content === "string") {
|
|
11946
|
+
content += delta.content;
|
|
11947
|
+
}
|
|
11948
|
+
const choiceFinishReason = choice?.finishReason ?? choice?.finish_reason ?? void 0;
|
|
11949
|
+
const deltaFinishReason = delta.finishReason ?? delta.finish_reason ?? void 0;
|
|
11950
|
+
if (choiceFinishReason !== void 0) {
|
|
11951
|
+
finishReason = choiceFinishReason;
|
|
11952
|
+
} else if (deltaFinishReason !== void 0) {
|
|
11953
|
+
finishReason = deltaFinishReason;
|
|
11954
|
+
}
|
|
11955
|
+
const toolCallDeltas = Array.isArray(delta.toolCalls) ? delta.toolCalls : Array.isArray(delta.tool_calls) ? delta.tool_calls : void 0;
|
|
11956
|
+
if (!toolCallDeltas) {
|
|
11957
|
+
continue;
|
|
11958
|
+
}
|
|
11959
|
+
for (const toolDelta of toolCallDeltas) {
|
|
11960
|
+
if (!toolDelta?.function) {
|
|
11961
|
+
continue;
|
|
11962
|
+
}
|
|
11963
|
+
const toolIndex = toolDelta.index ?? 0;
|
|
11964
|
+
const existingToolCall = toolCalls?.[toolIndex];
|
|
11965
|
+
if (!existingToolCall || toolDelta.id && existingToolCall.id !== void 0 && existingToolCall.id !== toolDelta.id) {
|
|
11966
|
+
const nextToolCalls = [...toolCalls || []];
|
|
11967
|
+
nextToolCalls[toolIndex] = {
|
|
11968
|
+
index: toolIndex,
|
|
11969
|
+
id: toolDelta.id,
|
|
11970
|
+
type: toolDelta.type,
|
|
11971
|
+
function: {
|
|
11972
|
+
name: toolDelta.function.name,
|
|
11973
|
+
arguments: toolDelta.function.arguments || ""
|
|
11974
|
+
}
|
|
11975
|
+
};
|
|
11976
|
+
toolCalls = nextToolCalls;
|
|
11977
|
+
continue;
|
|
11978
|
+
}
|
|
11979
|
+
const current = existingToolCall;
|
|
11980
|
+
if (toolDelta.id && !current.id) {
|
|
11981
|
+
current.id = toolDelta.id;
|
|
11982
|
+
}
|
|
11983
|
+
if (toolDelta.type && !current.type) {
|
|
11984
|
+
current.type = toolDelta.type;
|
|
11985
|
+
}
|
|
11986
|
+
if (toolDelta.function.name && !current.function.name) {
|
|
11987
|
+
current.function.name = toolDelta.function.name;
|
|
11988
|
+
}
|
|
11989
|
+
current.function.arguments += toolDelta.function.arguments || "";
|
|
11990
|
+
}
|
|
11991
|
+
}
|
|
11992
|
+
return {
|
|
11993
|
+
output: [
|
|
11994
|
+
{
|
|
11995
|
+
index: 0,
|
|
11996
|
+
message: {
|
|
11997
|
+
role,
|
|
11998
|
+
content: content || void 0,
|
|
11999
|
+
...toolCalls ? { tool_calls: toolCalls } : {}
|
|
12000
|
+
},
|
|
12001
|
+
logprobs: null,
|
|
12002
|
+
finish_reason: finishReason
|
|
12003
|
+
}
|
|
12004
|
+
],
|
|
12005
|
+
metrics
|
|
12006
|
+
};
|
|
12007
|
+
}
|
|
12008
|
+
function aggregateOpenRouterResponseStreamEvents(chunks) {
|
|
12009
|
+
let finalResponse;
|
|
12010
|
+
for (const chunk of chunks) {
|
|
12011
|
+
const response = chunk?.response;
|
|
12012
|
+
if (!response) {
|
|
12013
|
+
continue;
|
|
12014
|
+
}
|
|
12015
|
+
if (chunk.type === "response.completed" || chunk.type === "response.incomplete" || chunk.type === "response.failed") {
|
|
12016
|
+
finalResponse = response;
|
|
12017
|
+
}
|
|
12018
|
+
}
|
|
12019
|
+
if (!finalResponse) {
|
|
12020
|
+
return {
|
|
12021
|
+
output: void 0,
|
|
12022
|
+
metrics: {}
|
|
12023
|
+
};
|
|
12024
|
+
}
|
|
12025
|
+
return {
|
|
12026
|
+
output: extractOpenRouterResponseOutput(finalResponse),
|
|
12027
|
+
metrics: parseOpenRouterMetricsFromUsage(finalResponse.usage),
|
|
12028
|
+
...extractOpenRouterResponseMetadata(finalResponse) ? { metadata: extractOpenRouterResponseMetadata(finalResponse) } : {}
|
|
12029
|
+
};
|
|
12030
|
+
}
|
|
12031
|
+
|
|
12032
|
+
// src/instrumentation/braintrust-plugin.ts
|
|
12033
|
+
var BraintrustPlugin = class extends BasePlugin {
|
|
12034
|
+
config;
|
|
12035
|
+
openaiPlugin = null;
|
|
12036
|
+
anthropicPlugin = null;
|
|
12037
|
+
aiSDKPlugin = null;
|
|
12038
|
+
claudeAgentSDKPlugin = null;
|
|
12039
|
+
googleGenAIPlugin = null;
|
|
12040
|
+
openRouterPlugin = null;
|
|
12041
|
+
constructor(config = {}) {
|
|
12042
|
+
super();
|
|
12043
|
+
this.config = config;
|
|
12044
|
+
}
|
|
12045
|
+
onEnable() {
|
|
12046
|
+
const integrations = this.config.integrations || {};
|
|
12047
|
+
if (integrations.openai !== false) {
|
|
12048
|
+
this.openaiPlugin = new OpenAIPlugin();
|
|
12049
|
+
this.openaiPlugin.enable();
|
|
12050
|
+
}
|
|
12051
|
+
if (integrations.anthropic !== false) {
|
|
12052
|
+
this.anthropicPlugin = new AnthropicPlugin();
|
|
12053
|
+
this.anthropicPlugin.enable();
|
|
12054
|
+
}
|
|
12055
|
+
if (integrations.aisdk !== false && integrations.vercel !== false) {
|
|
12056
|
+
this.aiSDKPlugin = new AISDKPlugin();
|
|
12057
|
+
this.aiSDKPlugin.enable();
|
|
12058
|
+
}
|
|
12059
|
+
if (integrations.claudeAgentSDK !== false) {
|
|
12060
|
+
this.claudeAgentSDKPlugin = new ClaudeAgentSDKPlugin();
|
|
12061
|
+
this.claudeAgentSDKPlugin.enable();
|
|
12062
|
+
}
|
|
12063
|
+
if (integrations.googleGenAI !== false && integrations.google !== false) {
|
|
12064
|
+
this.googleGenAIPlugin = new GoogleGenAIPlugin();
|
|
12065
|
+
this.googleGenAIPlugin.enable();
|
|
12066
|
+
}
|
|
12067
|
+
if (integrations.openrouter !== false) {
|
|
12068
|
+
this.openRouterPlugin = new OpenRouterPlugin();
|
|
12069
|
+
this.openRouterPlugin.enable();
|
|
12070
|
+
}
|
|
12071
|
+
}
|
|
12072
|
+
onDisable() {
|
|
12073
|
+
if (this.openaiPlugin) {
|
|
12074
|
+
this.openaiPlugin.disable();
|
|
12075
|
+
this.openaiPlugin = null;
|
|
12076
|
+
}
|
|
12077
|
+
if (this.anthropicPlugin) {
|
|
10326
12078
|
this.anthropicPlugin.disable();
|
|
10327
12079
|
this.anthropicPlugin = null;
|
|
10328
12080
|
}
|
|
@@ -10338,6 +12090,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
10338
12090
|
this.googleGenAIPlugin.disable();
|
|
10339
12091
|
this.googleGenAIPlugin = null;
|
|
10340
12092
|
}
|
|
12093
|
+
if (this.openRouterPlugin) {
|
|
12094
|
+
this.openRouterPlugin.disable();
|
|
12095
|
+
this.openRouterPlugin = null;
|
|
12096
|
+
}
|
|
10341
12097
|
}
|
|
10342
12098
|
};
|
|
10343
12099
|
|
|
@@ -10409,7 +12165,8 @@ var PluginRegistry = class {
|
|
|
10409
12165
|
vercel: true,
|
|
10410
12166
|
aisdk: true,
|
|
10411
12167
|
google: true,
|
|
10412
|
-
claudeAgentSDK: true
|
|
12168
|
+
claudeAgentSDK: true,
|
|
12169
|
+
openrouter: true
|
|
10413
12170
|
};
|
|
10414
12171
|
}
|
|
10415
12172
|
/**
|