braintrust 3.5.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 +4 -2
- package/dev/dist/index.d.ts +4 -2
- package/dev/dist/index.js +1353 -211
- package/dev/dist/index.mjs +1170 -28
- package/dist/auto-instrumentations/bundler/esbuild.cjs +81 -0
- package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
- package/dist/auto-instrumentations/bundler/rollup.cjs +81 -0
- package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
- package/dist/auto-instrumentations/bundler/vite.cjs +81 -0
- package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
- package/dist/auto-instrumentations/bundler/webpack.cjs +81 -0
- package/dist/auto-instrumentations/bundler/webpack.mjs +2 -2
- package/dist/auto-instrumentations/{chunk-DQTPSXJB.mjs → chunk-F7WAXFNM.mjs} +82 -1
- package/dist/auto-instrumentations/{chunk-F3TJZ3Z2.mjs → chunk-WOUC73KB.mjs} +3 -1
- package/dist/auto-instrumentations/hook.mjs +139 -49
- package/dist/auto-instrumentations/index.cjs +82 -0
- 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/browser.d.mts +17 -4
- package/dist/browser.d.ts +17 -4
- package/dist/browser.js +1479 -232
- package/dist/browser.mjs +1479 -232
- package/dist/cli.js +1162 -20
- package/dist/edge-light.d.mts +1 -1
- package/dist/edge-light.d.ts +1 -1
- package/dist/edge-light.js +1412 -222
- package/dist/edge-light.mjs +1412 -222
- package/dist/index.d.mts +30 -17
- package/dist/index.d.ts +30 -17
- package/dist/index.js +1763 -514
- package/dist/index.mjs +1458 -209
- package/dist/instrumentation/index.d.mts +3 -0
- package/dist/instrumentation/index.d.ts +3 -0
- package/dist/instrumentation/index.js +1102 -19
- package/dist/instrumentation/index.mjs +1102 -19
- package/dist/workerd.d.mts +1 -1
- package/dist/workerd.d.ts +1 -1
- package/dist/workerd.js +1412 -222
- package/dist/workerd.mjs +1412 -222
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -8,6 +8,64 @@ var __export = (target, all) => {
|
|
|
8
8
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
9
9
|
import * as diagnostics_channel from "node:diagnostics_channel";
|
|
10
10
|
import * as path from "node:path";
|
|
11
|
+
|
|
12
|
+
// src/auto-instrumentations/patch-tracing-channel.ts
|
|
13
|
+
function patchTracingChannel(tracingChannelFn) {
|
|
14
|
+
const dummyChannel = tracingChannelFn("__braintrust_probe__");
|
|
15
|
+
const TracingChannel = dummyChannel?.constructor;
|
|
16
|
+
if (!TracingChannel?.prototype) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
if (!Object.getOwnPropertyDescriptor(TracingChannel.prototype, "hasSubscribers")) {
|
|
20
|
+
Object.defineProperty(TracingChannel.prototype, "hasSubscribers", {
|
|
21
|
+
configurable: true,
|
|
22
|
+
enumerable: false,
|
|
23
|
+
get() {
|
|
24
|
+
return Boolean(
|
|
25
|
+
this.start?.hasSubscribers || this.end?.hasSubscribers || this.asyncStart?.hasSubscribers || this.asyncEnd?.hasSubscribers || this.error?.hasSubscribers
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
if (TracingChannel.prototype.tracePromise) {
|
|
31
|
+
TracingChannel.prototype.tracePromise = function(fn, context = {}, thisArg, ...args) {
|
|
32
|
+
const { start, end, asyncStart, asyncEnd, error } = this;
|
|
33
|
+
function reject2(err) {
|
|
34
|
+
context.error = err;
|
|
35
|
+
error?.publish(context);
|
|
36
|
+
asyncStart?.publish(context);
|
|
37
|
+
asyncEnd?.publish(context);
|
|
38
|
+
return Promise.reject(err);
|
|
39
|
+
}
|
|
40
|
+
function resolve(result) {
|
|
41
|
+
context.result = result;
|
|
42
|
+
asyncStart?.publish(context);
|
|
43
|
+
asyncEnd?.publish(context);
|
|
44
|
+
return result;
|
|
45
|
+
}
|
|
46
|
+
return start.runStores(context, () => {
|
|
47
|
+
try {
|
|
48
|
+
const result = Reflect.apply(fn, thisArg, args);
|
|
49
|
+
end?.publish(context);
|
|
50
|
+
if (result && (typeof result === "object" || typeof result === "function") && typeof result.then === "function") {
|
|
51
|
+
return result.then(resolve, reject2);
|
|
52
|
+
}
|
|
53
|
+
context.result = result;
|
|
54
|
+
asyncStart?.publish(context);
|
|
55
|
+
asyncEnd?.publish(context);
|
|
56
|
+
return result;
|
|
57
|
+
} catch (err) {
|
|
58
|
+
context.error = err;
|
|
59
|
+
error?.publish(context);
|
|
60
|
+
end?.publish(context);
|
|
61
|
+
throw err;
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// src/node/config.ts
|
|
11
69
|
import * as fs from "node:fs/promises";
|
|
12
70
|
import * as os from "node:os";
|
|
13
71
|
import * as fsSync from "node:fs";
|
|
@@ -4510,6 +4568,9 @@ var BRAINTRUST_ATTACHMENT = BraintrustAttachmentReference.shape.type.value;
|
|
|
4510
4568
|
var EXTERNAL_ATTACHMENT = ExternalAttachmentReference.shape.type.value;
|
|
4511
4569
|
var LOGS3_OVERFLOW_REFERENCE_TYPE = "logs3_overflow";
|
|
4512
4570
|
var BRAINTRUST_PARAMS = Object.keys(BraintrustModelParams.shape);
|
|
4571
|
+
var RESET_CONTEXT_MANAGER_STATE = Symbol.for(
|
|
4572
|
+
"braintrust.resetContextManagerState"
|
|
4573
|
+
);
|
|
4513
4574
|
var DEFAULT_MAX_REQUEST_SIZE = 6 * 1024 * 1024;
|
|
4514
4575
|
var parametersRowSchema = z8.object({
|
|
4515
4576
|
id: z8.string().uuid(),
|
|
@@ -4572,13 +4633,18 @@ function applyMaskingToField(maskingFunction, data, fieldName) {
|
|
|
4572
4633
|
return `ERROR: Failed to mask field '${fieldName}' - ${errorType}`;
|
|
4573
4634
|
}
|
|
4574
4635
|
}
|
|
4636
|
+
var BRAINTRUST_CURRENT_SPAN_STORE = Symbol.for(
|
|
4637
|
+
"braintrust.currentSpanStore"
|
|
4638
|
+
);
|
|
4575
4639
|
var ContextManager = class {
|
|
4576
4640
|
};
|
|
4577
4641
|
var BraintrustContextManager = class extends ContextManager {
|
|
4578
4642
|
_currentSpan;
|
|
4643
|
+
[BRAINTRUST_CURRENT_SPAN_STORE];
|
|
4579
4644
|
constructor() {
|
|
4580
4645
|
super();
|
|
4581
4646
|
this._currentSpan = isomorph_default.newAsyncLocalStorage();
|
|
4647
|
+
this[BRAINTRUST_CURRENT_SPAN_STORE] = this._currentSpan;
|
|
4582
4648
|
}
|
|
4583
4649
|
getParentSpanIds() {
|
|
4584
4650
|
const currentSpan2 = this._currentSpan.getStore();
|
|
@@ -4785,6 +4851,9 @@ var BraintrustState = class _BraintrustState {
|
|
|
4785
4851
|
resetIdGenState() {
|
|
4786
4852
|
this._idGenerator = null;
|
|
4787
4853
|
}
|
|
4854
|
+
[RESET_CONTEXT_MANAGER_STATE]() {
|
|
4855
|
+
this._contextManager = null;
|
|
4856
|
+
}
|
|
4788
4857
|
get idGenerator() {
|
|
4789
4858
|
if (this._idGenerator === null) {
|
|
4790
4859
|
this._idGenerator = getIdGenerator();
|
|
@@ -7120,11 +7189,7 @@ async function loadPrompt({
|
|
|
7120
7189
|
forceLogin,
|
|
7121
7190
|
state: stateArg
|
|
7122
7191
|
}) {
|
|
7123
|
-
|
|
7124
|
-
throw new Error(
|
|
7125
|
-
"Cannot specify both 'version' and 'environment' parameters. Please use only one (remove the other)."
|
|
7126
|
-
);
|
|
7127
|
-
}
|
|
7192
|
+
const versionOrEnvironment = version ? { version } : environment ? { environment } : {};
|
|
7128
7193
|
if (id) {
|
|
7129
7194
|
} else if (isEmpty2(projectName) && isEmpty2(projectId)) {
|
|
7130
7195
|
throw new Error("Must specify either projectName or projectId");
|
|
@@ -7142,10 +7207,7 @@ async function loadPrompt({
|
|
|
7142
7207
|
forceLogin
|
|
7143
7208
|
});
|
|
7144
7209
|
if (id) {
|
|
7145
|
-
response = await state.apiConn().get_json(`v1/prompt/${id}`,
|
|
7146
|
-
...version && { version },
|
|
7147
|
-
...environment && { environment }
|
|
7148
|
-
});
|
|
7210
|
+
response = await state.apiConn().get_json(`v1/prompt/${id}`, versionOrEnvironment);
|
|
7149
7211
|
if (response) {
|
|
7150
7212
|
response = { objects: [response] };
|
|
7151
7213
|
}
|
|
@@ -7154,12 +7216,11 @@ async function loadPrompt({
|
|
|
7154
7216
|
project_name: projectName,
|
|
7155
7217
|
project_id: projectId,
|
|
7156
7218
|
slug,
|
|
7157
|
-
|
|
7158
|
-
...environment && { environment }
|
|
7219
|
+
...versionOrEnvironment
|
|
7159
7220
|
});
|
|
7160
7221
|
}
|
|
7161
7222
|
} catch (e) {
|
|
7162
|
-
if (
|
|
7223
|
+
if (version || environment) {
|
|
7163
7224
|
throw new Error(`Prompt not found with specified parameters: ${e}`);
|
|
7164
7225
|
}
|
|
7165
7226
|
debugLogger.forState(state).warn("Failed to load prompt, attempting to fall back to cache:", e);
|
|
@@ -7237,11 +7298,7 @@ async function loadParameters({
|
|
|
7237
7298
|
forceLogin,
|
|
7238
7299
|
state: stateArg
|
|
7239
7300
|
}) {
|
|
7240
|
-
|
|
7241
|
-
throw new Error(
|
|
7242
|
-
"Cannot specify both 'version' and 'environment' parameters. Please use only one (remove the other)."
|
|
7243
|
-
);
|
|
7244
|
-
}
|
|
7301
|
+
const versionOrEnvironment = version ? { version } : environment ? { environment } : {};
|
|
7245
7302
|
if (id) {
|
|
7246
7303
|
} else if (isEmpty2(projectName) && isEmpty2(projectId)) {
|
|
7247
7304
|
throw new Error("Must specify either projectName or projectId");
|
|
@@ -7260,8 +7317,7 @@ async function loadParameters({
|
|
|
7260
7317
|
});
|
|
7261
7318
|
if (id) {
|
|
7262
7319
|
response = await state.apiConn().get_json(`v1/function/${id}`, {
|
|
7263
|
-
...
|
|
7264
|
-
...environment && { environment }
|
|
7320
|
+
...versionOrEnvironment
|
|
7265
7321
|
});
|
|
7266
7322
|
if (response) {
|
|
7267
7323
|
response = { objects: [response] };
|
|
@@ -7271,13 +7327,12 @@ async function loadParameters({
|
|
|
7271
7327
|
project_name: projectName,
|
|
7272
7328
|
project_id: projectId,
|
|
7273
7329
|
slug,
|
|
7274
|
-
version,
|
|
7275
7330
|
function_type: "parameters",
|
|
7276
|
-
...
|
|
7331
|
+
...versionOrEnvironment
|
|
7277
7332
|
});
|
|
7278
7333
|
}
|
|
7279
7334
|
} catch (e) {
|
|
7280
|
-
if (
|
|
7335
|
+
if (version || environment) {
|
|
7281
7336
|
throw new Error(`Parameters not found with specified parameters: ${e}`);
|
|
7282
7337
|
}
|
|
7283
7338
|
debugLogger.forState(state).warn("Failed to load parameters, attempting to fall back to cache:", e);
|
|
@@ -9527,6 +9582,8 @@ async function simulateLoginForTests() {
|
|
|
9527
9582
|
function simulateLogoutForTests() {
|
|
9528
9583
|
const state = _internalGetGlobalState();
|
|
9529
9584
|
state.resetLoginInfo();
|
|
9585
|
+
state.resetIdGenState();
|
|
9586
|
+
state[RESET_CONTEXT_MANAGER_STATE]();
|
|
9530
9587
|
state.appUrl = "https://www.braintrust.dev";
|
|
9531
9588
|
return state;
|
|
9532
9589
|
}
|
|
@@ -10140,6 +10197,36 @@ function startSpanForEvent(config, event, channelName) {
|
|
|
10140
10197
|
}
|
|
10141
10198
|
return { span, startTime };
|
|
10142
10199
|
}
|
|
10200
|
+
function ensureSpanStateForEvent(states, config, event, channelName) {
|
|
10201
|
+
const key = event;
|
|
10202
|
+
const existing = states.get(key);
|
|
10203
|
+
if (existing) {
|
|
10204
|
+
return existing;
|
|
10205
|
+
}
|
|
10206
|
+
const created = startSpanForEvent(config, event, channelName);
|
|
10207
|
+
states.set(key, created);
|
|
10208
|
+
return created;
|
|
10209
|
+
}
|
|
10210
|
+
function bindCurrentSpanStoreToStart(tracingChannel2, states, config, channelName) {
|
|
10211
|
+
const state = _internalGetGlobalState();
|
|
10212
|
+
const startChannel = tracingChannel2.start;
|
|
10213
|
+
const currentSpanStore = state?.contextManager ? state.contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
|
|
10214
|
+
if (!currentSpanStore || !startChannel) {
|
|
10215
|
+
return void 0;
|
|
10216
|
+
}
|
|
10217
|
+
startChannel.bindStore(
|
|
10218
|
+
currentSpanStore,
|
|
10219
|
+
(event) => ensureSpanStateForEvent(
|
|
10220
|
+
states,
|
|
10221
|
+
config,
|
|
10222
|
+
event,
|
|
10223
|
+
channelName
|
|
10224
|
+
).span
|
|
10225
|
+
);
|
|
10226
|
+
return () => {
|
|
10227
|
+
startChannel.unbindStore(currentSpanStore);
|
|
10228
|
+
};
|
|
10229
|
+
}
|
|
10143
10230
|
function logErrorAndEnd(states, event) {
|
|
10144
10231
|
const spanData = states.get(event);
|
|
10145
10232
|
if (!spanData) {
|
|
@@ -10155,15 +10242,19 @@ function traceAsyncChannel(channel2, config) {
|
|
|
10155
10242
|
const tracingChannel2 = channel2.tracingChannel();
|
|
10156
10243
|
const states = /* @__PURE__ */ new WeakMap();
|
|
10157
10244
|
const channelName = channel2.channelName;
|
|
10245
|
+
const unbindCurrentSpanStore = bindCurrentSpanStoreToStart(
|
|
10246
|
+
tracingChannel2,
|
|
10247
|
+
states,
|
|
10248
|
+
config,
|
|
10249
|
+
channelName
|
|
10250
|
+
);
|
|
10158
10251
|
const handlers = {
|
|
10159
10252
|
start: (event) => {
|
|
10160
|
-
|
|
10253
|
+
ensureSpanStateForEvent(
|
|
10254
|
+
states,
|
|
10255
|
+
config,
|
|
10161
10256
|
event,
|
|
10162
|
-
|
|
10163
|
-
config,
|
|
10164
|
-
event,
|
|
10165
|
-
channelName
|
|
10166
|
-
)
|
|
10257
|
+
channelName
|
|
10167
10258
|
);
|
|
10168
10259
|
},
|
|
10169
10260
|
asyncEnd: (event) => {
|
|
@@ -10205,6 +10296,7 @@ function traceAsyncChannel(channel2, config) {
|
|
|
10205
10296
|
};
|
|
10206
10297
|
tracingChannel2.subscribe(handlers);
|
|
10207
10298
|
return () => {
|
|
10299
|
+
unbindCurrentSpanStore?.();
|
|
10208
10300
|
tracingChannel2.unsubscribe(handlers);
|
|
10209
10301
|
};
|
|
10210
10302
|
}
|
|
@@ -10212,15 +10304,19 @@ function traceStreamingChannel(channel2, config) {
|
|
|
10212
10304
|
const tracingChannel2 = channel2.tracingChannel();
|
|
10213
10305
|
const states = /* @__PURE__ */ new WeakMap();
|
|
10214
10306
|
const channelName = channel2.channelName;
|
|
10307
|
+
const unbindCurrentSpanStore = bindCurrentSpanStoreToStart(
|
|
10308
|
+
tracingChannel2,
|
|
10309
|
+
states,
|
|
10310
|
+
config,
|
|
10311
|
+
channelName
|
|
10312
|
+
);
|
|
10215
10313
|
const handlers = {
|
|
10216
10314
|
start: (event) => {
|
|
10217
|
-
|
|
10315
|
+
ensureSpanStateForEvent(
|
|
10316
|
+
states,
|
|
10317
|
+
config,
|
|
10218
10318
|
event,
|
|
10219
|
-
|
|
10220
|
-
config,
|
|
10221
|
-
event,
|
|
10222
|
-
channelName
|
|
10223
|
-
)
|
|
10319
|
+
channelName
|
|
10224
10320
|
);
|
|
10225
10321
|
},
|
|
10226
10322
|
asyncEnd: (event) => {
|
|
@@ -10336,6 +10432,7 @@ function traceStreamingChannel(channel2, config) {
|
|
|
10336
10432
|
};
|
|
10337
10433
|
tracingChannel2.subscribe(handlers);
|
|
10338
10434
|
return () => {
|
|
10435
|
+
unbindCurrentSpanStore?.();
|
|
10339
10436
|
tracingChannel2.unsubscribe(handlers);
|
|
10340
10437
|
};
|
|
10341
10438
|
}
|
|
@@ -10343,15 +10440,19 @@ function traceSyncStreamChannel(channel2, config) {
|
|
|
10343
10440
|
const tracingChannel2 = channel2.tracingChannel();
|
|
10344
10441
|
const states = /* @__PURE__ */ new WeakMap();
|
|
10345
10442
|
const channelName = channel2.channelName;
|
|
10443
|
+
const unbindCurrentSpanStore = bindCurrentSpanStoreToStart(
|
|
10444
|
+
tracingChannel2,
|
|
10445
|
+
states,
|
|
10446
|
+
config,
|
|
10447
|
+
channelName
|
|
10448
|
+
);
|
|
10346
10449
|
const handlers = {
|
|
10347
10450
|
start: (event) => {
|
|
10348
|
-
|
|
10451
|
+
ensureSpanStateForEvent(
|
|
10452
|
+
states,
|
|
10453
|
+
config,
|
|
10349
10454
|
event,
|
|
10350
|
-
|
|
10351
|
-
config,
|
|
10352
|
-
event,
|
|
10353
|
-
channelName
|
|
10354
|
-
)
|
|
10455
|
+
channelName
|
|
10355
10456
|
);
|
|
10356
10457
|
},
|
|
10357
10458
|
end: (event) => {
|
|
@@ -10440,6 +10541,7 @@ function traceSyncStreamChannel(channel2, config) {
|
|
|
10440
10541
|
};
|
|
10441
10542
|
tracingChannel2.subscribe(handlers);
|
|
10442
10543
|
return () => {
|
|
10544
|
+
unbindCurrentSpanStore?.();
|
|
10443
10545
|
tracingChannel2.unsubscribe(handlers);
|
|
10444
10546
|
};
|
|
10445
10547
|
}
|
|
@@ -13001,166 +13103,1206 @@ function tryToDict(obj) {
|
|
|
13001
13103
|
return null;
|
|
13002
13104
|
}
|
|
13003
13105
|
|
|
13004
|
-
// src/instrumentation/
|
|
13005
|
-
var
|
|
13006
|
-
|
|
13007
|
-
|
|
13008
|
-
|
|
13009
|
-
|
|
13010
|
-
|
|
13011
|
-
|
|
13012
|
-
|
|
13013
|
-
|
|
13014
|
-
|
|
13106
|
+
// src/instrumentation/plugins/openrouter-channels.ts
|
|
13107
|
+
var openRouterChannels = defineChannels("@openrouter/sdk", {
|
|
13108
|
+
chatSend: channel({
|
|
13109
|
+
channelName: "chat.send",
|
|
13110
|
+
kind: "async"
|
|
13111
|
+
}),
|
|
13112
|
+
embeddingsGenerate: channel({
|
|
13113
|
+
channelName: "embeddings.generate",
|
|
13114
|
+
kind: "async"
|
|
13115
|
+
}),
|
|
13116
|
+
betaResponsesSend: channel({
|
|
13117
|
+
channelName: "beta.responses.send",
|
|
13118
|
+
kind: "async"
|
|
13119
|
+
}),
|
|
13120
|
+
callModel: channel({
|
|
13121
|
+
channelName: "callModel",
|
|
13122
|
+
kind: "sync-stream"
|
|
13123
|
+
}),
|
|
13124
|
+
toolExecute: channel({
|
|
13125
|
+
channelName: "tool.execute",
|
|
13126
|
+
kind: "async"
|
|
13127
|
+
})
|
|
13128
|
+
});
|
|
13129
|
+
|
|
13130
|
+
// src/openrouter-utils.ts
|
|
13131
|
+
var TOKEN_NAME_MAP2 = {
|
|
13132
|
+
promptTokens: "prompt_tokens",
|
|
13133
|
+
inputTokens: "prompt_tokens",
|
|
13134
|
+
completionTokens: "completion_tokens",
|
|
13135
|
+
outputTokens: "completion_tokens",
|
|
13136
|
+
totalTokens: "tokens",
|
|
13137
|
+
prompt_tokens: "prompt_tokens",
|
|
13138
|
+
input_tokens: "prompt_tokens",
|
|
13139
|
+
completion_tokens: "completion_tokens",
|
|
13140
|
+
output_tokens: "completion_tokens",
|
|
13141
|
+
total_tokens: "tokens"
|
|
13142
|
+
};
|
|
13143
|
+
var TOKEN_DETAIL_PREFIX_MAP = {
|
|
13144
|
+
promptTokensDetails: "prompt",
|
|
13145
|
+
inputTokensDetails: "prompt",
|
|
13146
|
+
completionTokensDetails: "completion",
|
|
13147
|
+
outputTokensDetails: "completion",
|
|
13148
|
+
costDetails: "cost",
|
|
13149
|
+
prompt_tokens_details: "prompt",
|
|
13150
|
+
input_tokens_details: "prompt",
|
|
13151
|
+
completion_tokens_details: "completion",
|
|
13152
|
+
output_tokens_details: "completion",
|
|
13153
|
+
cost_details: "cost"
|
|
13154
|
+
};
|
|
13155
|
+
function camelToSnake(value) {
|
|
13156
|
+
return value.replace(/[A-Z]/g, (match) => `_${match.toLowerCase()}`);
|
|
13157
|
+
}
|
|
13158
|
+
function parseOpenRouterMetricsFromUsage(usage) {
|
|
13159
|
+
if (!isObject(usage)) {
|
|
13160
|
+
return {};
|
|
13015
13161
|
}
|
|
13016
|
-
|
|
13017
|
-
|
|
13018
|
-
if (
|
|
13019
|
-
|
|
13020
|
-
|
|
13021
|
-
}
|
|
13022
|
-
if (integrations.anthropic !== false) {
|
|
13023
|
-
this.anthropicPlugin = new AnthropicPlugin();
|
|
13024
|
-
this.anthropicPlugin.enable();
|
|
13162
|
+
const metrics = {};
|
|
13163
|
+
for (const [name, value] of Object.entries(usage)) {
|
|
13164
|
+
if (typeof value === "number") {
|
|
13165
|
+
metrics[TOKEN_NAME_MAP2[name] || camelToSnake(name)] = value;
|
|
13166
|
+
continue;
|
|
13025
13167
|
}
|
|
13026
|
-
if (
|
|
13027
|
-
|
|
13028
|
-
this.aiSDKPlugin.enable();
|
|
13168
|
+
if (!isObject(value)) {
|
|
13169
|
+
continue;
|
|
13029
13170
|
}
|
|
13030
|
-
|
|
13031
|
-
|
|
13032
|
-
|
|
13171
|
+
const prefix = TOKEN_DETAIL_PREFIX_MAP[name];
|
|
13172
|
+
if (!prefix) {
|
|
13173
|
+
continue;
|
|
13033
13174
|
}
|
|
13034
|
-
|
|
13035
|
-
|
|
13036
|
-
|
|
13175
|
+
for (const [nestedName, nestedValue] of Object.entries(value)) {
|
|
13176
|
+
if (typeof nestedValue !== "number") {
|
|
13177
|
+
continue;
|
|
13178
|
+
}
|
|
13179
|
+
metrics[`${prefix}_${camelToSnake(nestedName)}`] = nestedValue;
|
|
13037
13180
|
}
|
|
13038
13181
|
}
|
|
13039
|
-
|
|
13040
|
-
|
|
13041
|
-
|
|
13042
|
-
|
|
13043
|
-
|
|
13044
|
-
if (this.anthropicPlugin) {
|
|
13045
|
-
this.anthropicPlugin.disable();
|
|
13046
|
-
this.anthropicPlugin = null;
|
|
13047
|
-
}
|
|
13048
|
-
if (this.aiSDKPlugin) {
|
|
13049
|
-
this.aiSDKPlugin.disable();
|
|
13050
|
-
this.aiSDKPlugin = null;
|
|
13051
|
-
}
|
|
13052
|
-
if (this.claudeAgentSDKPlugin) {
|
|
13053
|
-
this.claudeAgentSDKPlugin.disable();
|
|
13054
|
-
this.claudeAgentSDKPlugin = null;
|
|
13055
|
-
}
|
|
13056
|
-
if (this.googleGenAIPlugin) {
|
|
13057
|
-
this.googleGenAIPlugin.disable();
|
|
13058
|
-
this.googleGenAIPlugin = null;
|
|
13059
|
-
}
|
|
13182
|
+
return metrics;
|
|
13183
|
+
}
|
|
13184
|
+
function extractOpenRouterUsageMetadata(usage) {
|
|
13185
|
+
if (!isObject(usage)) {
|
|
13186
|
+
return void 0;
|
|
13060
13187
|
}
|
|
13061
|
-
};
|
|
13188
|
+
const metadata = {};
|
|
13189
|
+
if (typeof usage.isByok === "boolean") {
|
|
13190
|
+
metadata.is_byok = usage.isByok;
|
|
13191
|
+
} else if (typeof usage.is_byok === "boolean") {
|
|
13192
|
+
metadata.is_byok = usage.is_byok;
|
|
13193
|
+
}
|
|
13194
|
+
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
13195
|
+
}
|
|
13062
13196
|
|
|
13063
|
-
// src/
|
|
13064
|
-
var
|
|
13065
|
-
|
|
13066
|
-
|
|
13067
|
-
|
|
13068
|
-
|
|
13069
|
-
|
|
13070
|
-
|
|
13071
|
-
|
|
13072
|
-
|
|
13073
|
-
if (this.enabled) {
|
|
13074
|
-
console.warn(
|
|
13075
|
-
"Braintrust: Cannot configure instrumentation after it has been enabled. Call configureInstrumentation() before importing any AI SDKs."
|
|
13076
|
-
);
|
|
13077
|
-
return;
|
|
13078
|
-
}
|
|
13079
|
-
this.config = { ...this.config, ...config };
|
|
13197
|
+
// src/openrouter-logging.ts
|
|
13198
|
+
var OMITTED_OPENROUTER_KEYS = /* @__PURE__ */ new Set([
|
|
13199
|
+
"execute",
|
|
13200
|
+
"render",
|
|
13201
|
+
"nextTurnParams",
|
|
13202
|
+
"requireApproval"
|
|
13203
|
+
]);
|
|
13204
|
+
function parseOpenRouterModelString(model) {
|
|
13205
|
+
if (typeof model !== "string") {
|
|
13206
|
+
return { model };
|
|
13080
13207
|
}
|
|
13081
|
-
|
|
13082
|
-
|
|
13083
|
-
|
|
13084
|
-
|
|
13085
|
-
|
|
13086
|
-
if (this.enabled) {
|
|
13087
|
-
return;
|
|
13088
|
-
}
|
|
13089
|
-
this.enabled = true;
|
|
13090
|
-
const envConfig = this.readEnvConfig();
|
|
13091
|
-
const finalConfig = {
|
|
13092
|
-
integrations: {
|
|
13093
|
-
...this.getDefaultConfig(),
|
|
13094
|
-
...this.config.integrations,
|
|
13095
|
-
...envConfig.integrations
|
|
13096
|
-
}
|
|
13208
|
+
const slashIndex = model.indexOf("/");
|
|
13209
|
+
if (slashIndex > 0 && slashIndex < model.length - 1) {
|
|
13210
|
+
return {
|
|
13211
|
+
provider: model.substring(0, slashIndex),
|
|
13212
|
+
model: model.substring(slashIndex + 1)
|
|
13097
13213
|
};
|
|
13098
|
-
this.braintrustPlugin = new BraintrustPlugin(finalConfig);
|
|
13099
|
-
this.braintrustPlugin.enable();
|
|
13100
13214
|
}
|
|
13101
|
-
|
|
13102
|
-
|
|
13103
|
-
|
|
13104
|
-
|
|
13105
|
-
|
|
13106
|
-
|
|
13107
|
-
|
|
13215
|
+
return { model };
|
|
13216
|
+
}
|
|
13217
|
+
function isZodSchema2(value) {
|
|
13218
|
+
return value != null && typeof value === "object" && "_def" in value && typeof value._def === "object";
|
|
13219
|
+
}
|
|
13220
|
+
function serializeZodSchema2(schema) {
|
|
13221
|
+
try {
|
|
13222
|
+
return zodToJsonSchema(schema);
|
|
13223
|
+
} catch {
|
|
13224
|
+
return {
|
|
13225
|
+
type: "object",
|
|
13226
|
+
description: "Zod schema (conversion failed)"
|
|
13227
|
+
};
|
|
13228
|
+
}
|
|
13229
|
+
}
|
|
13230
|
+
function serializeOpenRouterTool(tool) {
|
|
13231
|
+
if (!isObject(tool)) {
|
|
13232
|
+
return tool;
|
|
13233
|
+
}
|
|
13234
|
+
const serialized = {};
|
|
13235
|
+
for (const [key, value] of Object.entries(tool)) {
|
|
13236
|
+
if (OMITTED_OPENROUTER_KEYS.has(key)) {
|
|
13237
|
+
continue;
|
|
13108
13238
|
}
|
|
13109
|
-
|
|
13110
|
-
|
|
13111
|
-
|
|
13112
|
-
this.braintrustPlugin = null;
|
|
13239
|
+
if (key === "function" && isObject(value)) {
|
|
13240
|
+
serialized.function = sanitizeOpenRouterLoggedValue(value);
|
|
13241
|
+
continue;
|
|
13113
13242
|
}
|
|
13243
|
+
serialized[key] = sanitizeOpenRouterLoggedValue(value);
|
|
13114
13244
|
}
|
|
13115
|
-
|
|
13116
|
-
|
|
13117
|
-
|
|
13118
|
-
|
|
13119
|
-
return
|
|
13245
|
+
return serialized;
|
|
13246
|
+
}
|
|
13247
|
+
function serializeOpenRouterToolsForLogging(tools) {
|
|
13248
|
+
if (!Array.isArray(tools)) {
|
|
13249
|
+
return void 0;
|
|
13120
13250
|
}
|
|
13121
|
-
|
|
13122
|
-
|
|
13123
|
-
|
|
13124
|
-
|
|
13125
|
-
return
|
|
13126
|
-
openai: true,
|
|
13127
|
-
anthropic: true,
|
|
13128
|
-
vercel: true,
|
|
13129
|
-
aisdk: true,
|
|
13130
|
-
google: true,
|
|
13131
|
-
claudeAgentSDK: true
|
|
13132
|
-
};
|
|
13251
|
+
return tools.map((tool) => serializeOpenRouterTool(tool));
|
|
13252
|
+
}
|
|
13253
|
+
function sanitizeOpenRouterLoggedValue(value) {
|
|
13254
|
+
if (isZodSchema2(value)) {
|
|
13255
|
+
return serializeZodSchema2(value);
|
|
13133
13256
|
}
|
|
13134
|
-
|
|
13135
|
-
|
|
13136
|
-
|
|
13137
|
-
|
|
13138
|
-
|
|
13139
|
-
|
|
13140
|
-
|
|
13141
|
-
|
|
13142
|
-
|
|
13143
|
-
|
|
13144
|
-
|
|
13145
|
-
|
|
13257
|
+
if (typeof value === "function") {
|
|
13258
|
+
return "[Function]";
|
|
13259
|
+
}
|
|
13260
|
+
if (Array.isArray(value)) {
|
|
13261
|
+
return value.map((entry) => sanitizeOpenRouterLoggedValue(entry));
|
|
13262
|
+
}
|
|
13263
|
+
if (!isObject(value)) {
|
|
13264
|
+
return value;
|
|
13265
|
+
}
|
|
13266
|
+
const sanitized = {};
|
|
13267
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
13268
|
+
if (OMITTED_OPENROUTER_KEYS.has(key)) {
|
|
13269
|
+
continue;
|
|
13146
13270
|
}
|
|
13147
|
-
|
|
13271
|
+
if (key === "tools" && Array.isArray(entry)) {
|
|
13272
|
+
sanitized.tools = serializeOpenRouterToolsForLogging(entry);
|
|
13273
|
+
continue;
|
|
13274
|
+
}
|
|
13275
|
+
sanitized[key] = sanitizeOpenRouterLoggedValue(entry);
|
|
13148
13276
|
}
|
|
13149
|
-
|
|
13150
|
-
var registry = new PluginRegistry();
|
|
13151
|
-
function configureInstrumentation(config) {
|
|
13152
|
-
registry.configure(config);
|
|
13277
|
+
return sanitized;
|
|
13153
13278
|
}
|
|
13154
|
-
|
|
13155
|
-
|
|
13156
|
-
|
|
13157
|
-
|
|
13158
|
-
|
|
13279
|
+
function buildOpenRouterMetadata(metadata, httpReferer, xTitle) {
|
|
13280
|
+
const sanitized = sanitizeOpenRouterLoggedValue(metadata);
|
|
13281
|
+
const metadataRecord = isObject(sanitized) ? sanitized : {};
|
|
13282
|
+
const { model, provider: providerRouting, ...rest } = metadataRecord;
|
|
13283
|
+
const normalizedModel = parseOpenRouterModelString(model);
|
|
13284
|
+
return {
|
|
13285
|
+
...rest,
|
|
13286
|
+
...normalizedModel.model !== void 0 ? { model: normalizedModel.model } : {},
|
|
13287
|
+
...providerRouting !== void 0 ? { providerRouting } : {},
|
|
13288
|
+
...httpReferer !== void 0 ? { httpReferer } : {},
|
|
13289
|
+
...xTitle !== void 0 ? { xTitle } : {},
|
|
13290
|
+
provider: normalizedModel.provider || "openrouter"
|
|
13291
|
+
};
|
|
13292
|
+
}
|
|
13293
|
+
function buildOpenRouterEmbeddingMetadata(metadata, httpReferer, xTitle) {
|
|
13294
|
+
const normalized = buildOpenRouterMetadata(metadata, httpReferer, xTitle);
|
|
13295
|
+
return typeof normalized.model === "string" ? {
|
|
13296
|
+
...normalized,
|
|
13297
|
+
embedding_model: normalized.model
|
|
13298
|
+
} : normalized;
|
|
13299
|
+
}
|
|
13300
|
+
function extractOpenRouterCallModelInput(request) {
|
|
13301
|
+
return isObject(request) && "input" in request ? sanitizeOpenRouterLoggedValue(request.input) : void 0;
|
|
13302
|
+
}
|
|
13303
|
+
function extractOpenRouterCallModelMetadata(request) {
|
|
13304
|
+
if (!isObject(request)) {
|
|
13305
|
+
return { provider: "openrouter" };
|
|
13306
|
+
}
|
|
13307
|
+
const { input: _input, ...metadata } = request;
|
|
13308
|
+
return buildOpenRouterMetadata(metadata, void 0, void 0);
|
|
13309
|
+
}
|
|
13310
|
+
function extractOpenRouterResponseMetadata(result) {
|
|
13311
|
+
if (!isObject(result)) {
|
|
13312
|
+
return void 0;
|
|
13313
|
+
}
|
|
13314
|
+
const { output: _output, data: _data, usage, ...metadata } = result;
|
|
13315
|
+
const sanitized = sanitizeOpenRouterLoggedValue(metadata);
|
|
13316
|
+
const metadataRecord = isObject(sanitized) ? sanitized : {};
|
|
13317
|
+
const { model, provider, ...rest } = metadataRecord;
|
|
13318
|
+
const normalizedModel = parseOpenRouterModelString(model);
|
|
13319
|
+
const normalizedProvider = (typeof provider === "string" ? provider : void 0) || normalizedModel.provider;
|
|
13320
|
+
const usageMetadata = extractOpenRouterUsageMetadata(usage);
|
|
13321
|
+
const combined = {
|
|
13322
|
+
...rest,
|
|
13323
|
+
...normalizedModel.model !== void 0 ? { model: normalizedModel.model } : {},
|
|
13324
|
+
...usageMetadata || {},
|
|
13325
|
+
...normalizedProvider !== void 0 ? { provider: normalizedProvider } : {}
|
|
13326
|
+
};
|
|
13327
|
+
return Object.keys(combined).length > 0 ? combined : void 0;
|
|
13328
|
+
}
|
|
13329
|
+
function extractOpenRouterResponseOutput(response, fallbackOutput) {
|
|
13330
|
+
if (isObject(response) && "output" in response && response.output !== void 0) {
|
|
13331
|
+
return sanitizeOpenRouterLoggedValue(response.output);
|
|
13332
|
+
}
|
|
13333
|
+
if (fallbackOutput !== void 0) {
|
|
13334
|
+
return sanitizeOpenRouterLoggedValue(fallbackOutput);
|
|
13335
|
+
}
|
|
13336
|
+
return void 0;
|
|
13337
|
+
}
|
|
13338
|
+
|
|
13339
|
+
// src/openrouter-tool-wrapping.ts
|
|
13340
|
+
var OPENROUTER_WRAPPED_TOOL = Symbol("braintrust.openrouter.wrappedTool");
|
|
13341
|
+
var OPENROUTER_WRAPPED_CALL_MODEL_RESULT = Symbol(
|
|
13342
|
+
"braintrust.openrouter.wrappedCallModelResult"
|
|
13343
|
+
);
|
|
13344
|
+
var OPENROUTER_CALL_MODEL_STREAM_METHODS = [
|
|
13345
|
+
"getFullResponsesStream",
|
|
13346
|
+
"getItemsStream",
|
|
13347
|
+
"getNewMessagesStream",
|
|
13348
|
+
"getReasoningStream",
|
|
13349
|
+
"getTextStream",
|
|
13350
|
+
"getToolCallsStream",
|
|
13351
|
+
"getToolStream"
|
|
13352
|
+
];
|
|
13353
|
+
var OPENROUTER_CALL_MODEL_CONTEXT_METHODS = [
|
|
13354
|
+
"cancel",
|
|
13355
|
+
"getPendingToolCalls",
|
|
13356
|
+
"getState",
|
|
13357
|
+
"getToolCalls",
|
|
13358
|
+
"requiresApproval"
|
|
13359
|
+
];
|
|
13360
|
+
function startOpenRouterCallModelSpan(request) {
|
|
13361
|
+
return startSpan({
|
|
13362
|
+
name: "openrouter.callModel",
|
|
13363
|
+
spanAttributes: {
|
|
13364
|
+
type: "llm" /* LLM */
|
|
13365
|
+
},
|
|
13366
|
+
event: {
|
|
13367
|
+
input: extractOpenRouterCallModelInput(request),
|
|
13368
|
+
metadata: extractOpenRouterCallModelMetadata(request)
|
|
13369
|
+
}
|
|
13370
|
+
});
|
|
13371
|
+
}
|
|
13372
|
+
function patchOpenRouterCallModelRequestTools(request) {
|
|
13373
|
+
if (!Array.isArray(request.tools) || request.tools.length === 0) {
|
|
13374
|
+
return void 0;
|
|
13375
|
+
}
|
|
13376
|
+
const originalTools = request.tools;
|
|
13377
|
+
const wrappedTools = originalTools.map((tool) => wrapOpenRouterTool(tool));
|
|
13378
|
+
const didPatch = wrappedTools.some(
|
|
13379
|
+
(tool, index) => tool !== originalTools[index]
|
|
13380
|
+
);
|
|
13381
|
+
if (!didPatch) {
|
|
13382
|
+
return void 0;
|
|
13383
|
+
}
|
|
13384
|
+
request.tools = wrappedTools;
|
|
13385
|
+
return () => {
|
|
13386
|
+
request.tools = originalTools;
|
|
13387
|
+
};
|
|
13388
|
+
}
|
|
13389
|
+
function patchOpenRouterCallModelResult(span, result, request) {
|
|
13390
|
+
if (!isObject(result) || isWrappedCallModelResult(result)) {
|
|
13391
|
+
return false;
|
|
13392
|
+
}
|
|
13393
|
+
const resultLike = result;
|
|
13394
|
+
const hasInstrumentableMethod = typeof resultLike.getResponse === "function" || typeof resultLike.getText === "function" || OPENROUTER_CALL_MODEL_STREAM_METHODS.some(
|
|
13395
|
+
(methodName) => typeof resultLike[methodName] === "function"
|
|
13396
|
+
);
|
|
13397
|
+
if (!hasInstrumentableMethod) {
|
|
13398
|
+
return false;
|
|
13399
|
+
}
|
|
13400
|
+
Object.defineProperty(resultLike, OPENROUTER_WRAPPED_CALL_MODEL_RESULT, {
|
|
13401
|
+
value: true,
|
|
13402
|
+
enumerable: false,
|
|
13403
|
+
configurable: false
|
|
13404
|
+
});
|
|
13405
|
+
const originalGetResponse = typeof resultLike.getResponse === "function" ? resultLike.getResponse.bind(resultLike) : void 0;
|
|
13406
|
+
const originalGetInitialResponse = typeof resultLike.getInitialResponse === "function" ? resultLike.getInitialResponse.bind(resultLike) : void 0;
|
|
13407
|
+
const originalMakeFollowupRequest = typeof resultLike.makeFollowupRequest === "function" ? resultLike.makeFollowupRequest.bind(resultLike) : void 0;
|
|
13408
|
+
let ended = false;
|
|
13409
|
+
let tracedTurnCount = 0;
|
|
13410
|
+
const endSpanWithResult = async (response, fallbackOutput) => {
|
|
13411
|
+
if (ended) {
|
|
13412
|
+
return;
|
|
13413
|
+
}
|
|
13414
|
+
ended = true;
|
|
13415
|
+
const finalResponse = getFinalOpenRouterCallModelResponse(
|
|
13416
|
+
resultLike,
|
|
13417
|
+
response
|
|
13418
|
+
);
|
|
13419
|
+
if (finalResponse) {
|
|
13420
|
+
const rounds = getOpenRouterCallModelRounds(resultLike);
|
|
13421
|
+
const metadata = extractOpenRouterCallModelResultMetadata(
|
|
13422
|
+
finalResponse,
|
|
13423
|
+
rounds.length + 1
|
|
13424
|
+
);
|
|
13425
|
+
span.log({
|
|
13426
|
+
output: extractOpenRouterResponseOutput(finalResponse, fallbackOutput),
|
|
13427
|
+
...metadata ? { metadata } : {},
|
|
13428
|
+
metrics: aggregateOpenRouterCallModelMetrics(rounds, finalResponse)
|
|
13429
|
+
});
|
|
13430
|
+
span.end();
|
|
13431
|
+
return;
|
|
13432
|
+
}
|
|
13433
|
+
if (fallbackOutput !== void 0) {
|
|
13434
|
+
span.log({
|
|
13435
|
+
output: fallbackOutput
|
|
13436
|
+
});
|
|
13437
|
+
}
|
|
13438
|
+
span.end();
|
|
13439
|
+
};
|
|
13440
|
+
const endSpanWithError = (error) => {
|
|
13441
|
+
if (ended) {
|
|
13442
|
+
return;
|
|
13443
|
+
}
|
|
13444
|
+
ended = true;
|
|
13445
|
+
span.log({
|
|
13446
|
+
error: normalizeError(error).message
|
|
13447
|
+
});
|
|
13448
|
+
span.end();
|
|
13449
|
+
};
|
|
13450
|
+
const finalizeFromResponse = async (fallbackOutput) => {
|
|
13451
|
+
if (!originalGetResponse) {
|
|
13452
|
+
await endSpanWithResult(void 0, fallbackOutput);
|
|
13453
|
+
return;
|
|
13454
|
+
}
|
|
13455
|
+
try {
|
|
13456
|
+
await endSpanWithResult(await originalGetResponse(), fallbackOutput);
|
|
13457
|
+
} catch {
|
|
13458
|
+
await endSpanWithResult(void 0, fallbackOutput);
|
|
13459
|
+
}
|
|
13460
|
+
};
|
|
13461
|
+
if (originalGetResponse) {
|
|
13462
|
+
resultLike.getResponse = async (...args) => {
|
|
13463
|
+
return await withCurrent(span, async () => {
|
|
13464
|
+
try {
|
|
13465
|
+
const response = await originalGetResponse(...args);
|
|
13466
|
+
await endSpanWithResult(response);
|
|
13467
|
+
return response;
|
|
13468
|
+
} catch (error) {
|
|
13469
|
+
endSpanWithError(error);
|
|
13470
|
+
throw error;
|
|
13471
|
+
}
|
|
13472
|
+
});
|
|
13473
|
+
};
|
|
13474
|
+
}
|
|
13475
|
+
if (typeof resultLike.getText === "function") {
|
|
13476
|
+
const originalGetText = resultLike.getText.bind(resultLike);
|
|
13477
|
+
resultLike.getText = async (...args) => {
|
|
13478
|
+
return await withCurrent(span, async () => {
|
|
13479
|
+
try {
|
|
13480
|
+
const text = await originalGetText(...args);
|
|
13481
|
+
await finalizeFromResponse(text);
|
|
13482
|
+
return text;
|
|
13483
|
+
} catch (error) {
|
|
13484
|
+
endSpanWithError(error);
|
|
13485
|
+
throw error;
|
|
13486
|
+
}
|
|
13487
|
+
});
|
|
13488
|
+
};
|
|
13489
|
+
}
|
|
13490
|
+
for (const methodName of OPENROUTER_CALL_MODEL_CONTEXT_METHODS) {
|
|
13491
|
+
if (typeof resultLike[methodName] !== "function") {
|
|
13492
|
+
continue;
|
|
13493
|
+
}
|
|
13494
|
+
const originalMethod = resultLike[methodName];
|
|
13495
|
+
resultLike[methodName] = async (...args) => {
|
|
13496
|
+
return await withCurrent(span, async () => {
|
|
13497
|
+
return await originalMethod.apply(resultLike, args);
|
|
13498
|
+
});
|
|
13499
|
+
};
|
|
13500
|
+
}
|
|
13501
|
+
for (const methodName of OPENROUTER_CALL_MODEL_STREAM_METHODS) {
|
|
13502
|
+
if (typeof resultLike[methodName] !== "function") {
|
|
13503
|
+
continue;
|
|
13504
|
+
}
|
|
13505
|
+
const originalMethod = resultLike[methodName];
|
|
13506
|
+
resultLike[methodName] = (...args) => {
|
|
13507
|
+
const stream = withCurrent(
|
|
13508
|
+
span,
|
|
13509
|
+
() => originalMethod.apply(resultLike, args)
|
|
13510
|
+
);
|
|
13511
|
+
if (!isAsyncIterable2(stream)) {
|
|
13512
|
+
return stream;
|
|
13513
|
+
}
|
|
13514
|
+
return wrapAsyncIterableWithSpan({
|
|
13515
|
+
finalize: finalizeFromResponse,
|
|
13516
|
+
iteratorFactory: () => stream[Symbol.asyncIterator](),
|
|
13517
|
+
onError: endSpanWithError,
|
|
13518
|
+
span
|
|
13519
|
+
});
|
|
13520
|
+
};
|
|
13521
|
+
}
|
|
13522
|
+
if (originalGetInitialResponse) {
|
|
13523
|
+
let initialTurnTraced = false;
|
|
13524
|
+
resultLike.getInitialResponse = async (...args) => {
|
|
13525
|
+
if (initialTurnTraced) {
|
|
13526
|
+
return await withCurrent(span, async () => {
|
|
13527
|
+
return await originalGetInitialResponse(...args);
|
|
13528
|
+
});
|
|
13529
|
+
}
|
|
13530
|
+
initialTurnTraced = true;
|
|
13531
|
+
const resolvedRequest = getOpenRouterResolvedRequest(resultLike, request);
|
|
13532
|
+
const childSpan = startOpenRouterCallModelTurnSpan({
|
|
13533
|
+
request: resolvedRequest,
|
|
13534
|
+
step: tracedTurnCount + 1,
|
|
13535
|
+
stepType: tracedTurnCount === 0 ? "initial" : "continue"
|
|
13536
|
+
});
|
|
13537
|
+
return await withCurrent(childSpan, async () => {
|
|
13538
|
+
try {
|
|
13539
|
+
const response = await originalGetInitialResponse(...args);
|
|
13540
|
+
tracedTurnCount++;
|
|
13541
|
+
finishOpenRouterCallModelTurnSpan({
|
|
13542
|
+
response,
|
|
13543
|
+
step: tracedTurnCount,
|
|
13544
|
+
stepType: tracedTurnCount === 1 ? "initial" : "continue",
|
|
13545
|
+
span: childSpan
|
|
13546
|
+
});
|
|
13547
|
+
return response;
|
|
13548
|
+
} catch (error) {
|
|
13549
|
+
childSpan.log({
|
|
13550
|
+
error: normalizeError(error).message
|
|
13551
|
+
});
|
|
13552
|
+
childSpan.end();
|
|
13553
|
+
throw error;
|
|
13554
|
+
}
|
|
13555
|
+
});
|
|
13556
|
+
};
|
|
13557
|
+
}
|
|
13558
|
+
if (originalMakeFollowupRequest) {
|
|
13559
|
+
resultLike.makeFollowupRequest = async (...args) => {
|
|
13560
|
+
const currentResponse = args[0];
|
|
13561
|
+
const toolResults = Array.isArray(args[1]) ? args[1] : [];
|
|
13562
|
+
const resolvedRequest = getOpenRouterResolvedRequest(resultLike, request);
|
|
13563
|
+
const followupRequest = buildOpenRouterFollowupRequest(
|
|
13564
|
+
resolvedRequest,
|
|
13565
|
+
currentResponse,
|
|
13566
|
+
toolResults
|
|
13567
|
+
);
|
|
13568
|
+
const childSpan = startOpenRouterCallModelTurnSpan({
|
|
13569
|
+
request: followupRequest,
|
|
13570
|
+
step: tracedTurnCount + 1,
|
|
13571
|
+
stepType: "continue"
|
|
13572
|
+
});
|
|
13573
|
+
return await withCurrent(childSpan, async () => {
|
|
13574
|
+
try {
|
|
13575
|
+
const response = await originalMakeFollowupRequest(...args);
|
|
13576
|
+
tracedTurnCount++;
|
|
13577
|
+
finishOpenRouterCallModelTurnSpan({
|
|
13578
|
+
response,
|
|
13579
|
+
step: tracedTurnCount,
|
|
13580
|
+
stepType: "continue",
|
|
13581
|
+
span: childSpan
|
|
13582
|
+
});
|
|
13583
|
+
return response;
|
|
13584
|
+
} catch (error) {
|
|
13585
|
+
childSpan.log({
|
|
13586
|
+
error: normalizeError(error).message
|
|
13587
|
+
});
|
|
13588
|
+
childSpan.end();
|
|
13589
|
+
throw error;
|
|
13590
|
+
}
|
|
13591
|
+
});
|
|
13592
|
+
};
|
|
13593
|
+
}
|
|
13594
|
+
return true;
|
|
13595
|
+
}
|
|
13596
|
+
function wrapOpenRouterTool(tool) {
|
|
13597
|
+
if (isWrappedTool(tool) || !tool.function || typeof tool.function !== "object" || typeof tool.function.execute !== "function") {
|
|
13598
|
+
return tool;
|
|
13599
|
+
}
|
|
13600
|
+
const toolName = tool.function.name || "tool";
|
|
13601
|
+
const originalExecute = tool.function.execute;
|
|
13602
|
+
const wrappedTool = {
|
|
13603
|
+
...tool,
|
|
13604
|
+
function: {
|
|
13605
|
+
...tool.function,
|
|
13606
|
+
execute(...args) {
|
|
13607
|
+
return traceToolExecution({
|
|
13608
|
+
args,
|
|
13609
|
+
execute: () => Reflect.apply(originalExecute, this, args),
|
|
13610
|
+
toolCallId: getToolCallId(args[1]),
|
|
13611
|
+
toolName
|
|
13612
|
+
});
|
|
13613
|
+
}
|
|
13614
|
+
}
|
|
13615
|
+
};
|
|
13616
|
+
Object.defineProperty(wrappedTool, OPENROUTER_WRAPPED_TOOL, {
|
|
13617
|
+
value: true,
|
|
13618
|
+
enumerable: false,
|
|
13619
|
+
configurable: false
|
|
13620
|
+
});
|
|
13621
|
+
return wrappedTool;
|
|
13622
|
+
}
|
|
13623
|
+
function isWrappedTool(tool) {
|
|
13624
|
+
return Boolean(tool[OPENROUTER_WRAPPED_TOOL]);
|
|
13625
|
+
}
|
|
13626
|
+
function isWrappedCallModelResult(value) {
|
|
13627
|
+
return Boolean(
|
|
13628
|
+
isObject(value) && value[OPENROUTER_WRAPPED_CALL_MODEL_RESULT]
|
|
13629
|
+
);
|
|
13630
|
+
}
|
|
13631
|
+
function traceToolExecution(args) {
|
|
13632
|
+
const tracingChannel2 = openRouterChannels.toolExecute.tracingChannel();
|
|
13633
|
+
const input = args.args.length > 0 ? args.args[0] : void 0;
|
|
13634
|
+
const event = {
|
|
13635
|
+
arguments: [input],
|
|
13636
|
+
span_info: {
|
|
13637
|
+
name: args.toolName
|
|
13638
|
+
},
|
|
13639
|
+
toolCallId: args.toolCallId,
|
|
13640
|
+
toolName: args.toolName
|
|
13641
|
+
};
|
|
13642
|
+
tracingChannel2.start.publish(event);
|
|
13643
|
+
try {
|
|
13644
|
+
const result = args.execute();
|
|
13645
|
+
return publishToolResult(tracingChannel2, event, result);
|
|
13646
|
+
} catch (error) {
|
|
13647
|
+
event.error = normalizeError(error);
|
|
13648
|
+
tracingChannel2.error.publish(event);
|
|
13649
|
+
throw error;
|
|
13650
|
+
}
|
|
13651
|
+
}
|
|
13652
|
+
function publishToolResult(tracingChannel2, event, result) {
|
|
13653
|
+
if (isPromiseLike(result)) {
|
|
13654
|
+
return result.then(
|
|
13655
|
+
(resolved) => {
|
|
13656
|
+
event.result = resolved;
|
|
13657
|
+
tracingChannel2.asyncEnd.publish(event);
|
|
13658
|
+
return resolved;
|
|
13659
|
+
},
|
|
13660
|
+
(error) => {
|
|
13661
|
+
event.error = normalizeError(error);
|
|
13662
|
+
tracingChannel2.error.publish(event);
|
|
13663
|
+
throw error;
|
|
13664
|
+
}
|
|
13665
|
+
);
|
|
13666
|
+
}
|
|
13667
|
+
event.result = result;
|
|
13668
|
+
tracingChannel2.asyncEnd.publish(event);
|
|
13669
|
+
return result;
|
|
13670
|
+
}
|
|
13671
|
+
function getToolCallId(context) {
|
|
13672
|
+
const toolContext = context;
|
|
13673
|
+
return typeof toolContext?.toolCall?.id === "string" ? toolContext.toolCall.id : void 0;
|
|
13674
|
+
}
|
|
13675
|
+
function extractOpenRouterCallModelResultMetadata(response, turnCount) {
|
|
13676
|
+
const combined = {
|
|
13677
|
+
...extractOpenRouterResponseMetadata(response) || {},
|
|
13678
|
+
...turnCount !== void 0 ? { turn_count: turnCount } : {}
|
|
13679
|
+
};
|
|
13680
|
+
return Object.keys(combined).length > 0 ? combined : void 0;
|
|
13681
|
+
}
|
|
13682
|
+
function getFinalOpenRouterCallModelResponse(result, response) {
|
|
13683
|
+
if (isObject(response)) {
|
|
13684
|
+
return response;
|
|
13685
|
+
}
|
|
13686
|
+
return isObject(result.finalResponse) ? result.finalResponse : void 0;
|
|
13687
|
+
}
|
|
13688
|
+
function getOpenRouterCallModelRounds(result) {
|
|
13689
|
+
if (!Array.isArray(result.allToolExecutionRounds)) {
|
|
13690
|
+
return [];
|
|
13691
|
+
}
|
|
13692
|
+
return result.allToolExecutionRounds.filter((round) => isObject(round)).map((round) => ({
|
|
13693
|
+
response: isObject(round.response) ? round.response : void 0,
|
|
13694
|
+
round: typeof round.round === "number" ? round.round : void 0,
|
|
13695
|
+
toolResults: Array.isArray(round.toolResults) ? round.toolResults : []
|
|
13696
|
+
})).filter((round) => round.response !== void 0);
|
|
13697
|
+
}
|
|
13698
|
+
function aggregateOpenRouterCallModelMetrics(rounds, finalResponse) {
|
|
13699
|
+
const metrics = {};
|
|
13700
|
+
const responses = [
|
|
13701
|
+
...rounds.map((round) => round.response).filter(isObject),
|
|
13702
|
+
finalResponse
|
|
13703
|
+
];
|
|
13704
|
+
for (const response of responses) {
|
|
13705
|
+
const responseMetrics = parseOpenRouterMetricsFromUsage(response.usage);
|
|
13706
|
+
for (const [name, value] of Object.entries(responseMetrics)) {
|
|
13707
|
+
metrics[name] = (metrics[name] || 0) + value;
|
|
13708
|
+
}
|
|
13709
|
+
}
|
|
13710
|
+
return metrics;
|
|
13711
|
+
}
|
|
13712
|
+
function buildNextOpenRouterCallModelInput(currentInput, response, toolResults) {
|
|
13713
|
+
const normalizedInput = Array.isArray(currentInput) ? [...currentInput] : currentInput === void 0 ? [] : [currentInput];
|
|
13714
|
+
const responseOutput = Array.isArray(response.output) ? response.output : response.output === void 0 ? [] : [response.output];
|
|
13715
|
+
return [...normalizedInput, ...responseOutput, ...toolResults].map(
|
|
13716
|
+
(entry) => sanitizeOpenRouterLoggedValue(entry)
|
|
13717
|
+
);
|
|
13718
|
+
}
|
|
13719
|
+
function startOpenRouterCallModelTurnSpan(args) {
|
|
13720
|
+
const requestRecord = isObject(args.request) ? args.request : void 0;
|
|
13721
|
+
const metadata = requestRecord ? extractOpenRouterCallModelMetadata(requestRecord) : { provider: "openrouter" };
|
|
13722
|
+
if (isObject(metadata) && "tools" in metadata) {
|
|
13723
|
+
delete metadata.tools;
|
|
13724
|
+
}
|
|
13725
|
+
return startSpan({
|
|
13726
|
+
name: "openrouter.beta.responses.send",
|
|
13727
|
+
spanAttributes: {
|
|
13728
|
+
type: "llm" /* LLM */
|
|
13729
|
+
},
|
|
13730
|
+
event: {
|
|
13731
|
+
input: requestRecord ? extractOpenRouterCallModelInput(requestRecord) : void 0,
|
|
13732
|
+
metadata: {
|
|
13733
|
+
...metadata,
|
|
13734
|
+
step: args.step,
|
|
13735
|
+
step_type: args.stepType
|
|
13736
|
+
}
|
|
13737
|
+
}
|
|
13738
|
+
});
|
|
13739
|
+
}
|
|
13740
|
+
function finishOpenRouterCallModelTurnSpan(args) {
|
|
13741
|
+
if (!isObject(args.response)) {
|
|
13742
|
+
args.span.end();
|
|
13743
|
+
return;
|
|
13744
|
+
}
|
|
13745
|
+
args.span.log({
|
|
13746
|
+
output: extractOpenRouterResponseOutput(args.response),
|
|
13747
|
+
...extractOpenRouterResponseMetadata(args.response) ? {
|
|
13748
|
+
metadata: {
|
|
13749
|
+
...extractOpenRouterResponseMetadata(args.response),
|
|
13750
|
+
...args.step !== void 0 ? { step: args.step } : {},
|
|
13751
|
+
...args.stepType ? { step_type: args.stepType } : {}
|
|
13752
|
+
}
|
|
13753
|
+
} : {},
|
|
13754
|
+
metrics: parseOpenRouterMetricsFromUsage(args.response.usage)
|
|
13755
|
+
});
|
|
13756
|
+
args.span.end();
|
|
13757
|
+
}
|
|
13758
|
+
function getOpenRouterResolvedRequest(result, request) {
|
|
13759
|
+
if (isObject(result.resolvedRequest)) {
|
|
13760
|
+
return result.resolvedRequest;
|
|
13761
|
+
}
|
|
13762
|
+
return request;
|
|
13763
|
+
}
|
|
13764
|
+
function buildOpenRouterFollowupRequest(request, currentResponse, toolResults) {
|
|
13765
|
+
if (!request) {
|
|
13766
|
+
return void 0;
|
|
13767
|
+
}
|
|
13768
|
+
return {
|
|
13769
|
+
...request,
|
|
13770
|
+
input: buildNextOpenRouterCallModelInput(
|
|
13771
|
+
extractOpenRouterCallModelInput(request),
|
|
13772
|
+
isObject(currentResponse) ? currentResponse : {},
|
|
13773
|
+
toolResults
|
|
13774
|
+
),
|
|
13775
|
+
stream: false
|
|
13776
|
+
};
|
|
13777
|
+
}
|
|
13778
|
+
function wrapAsyncIterableWithSpan(args) {
|
|
13779
|
+
return {
|
|
13780
|
+
[Symbol.asyncIterator]() {
|
|
13781
|
+
const iterator = args.iteratorFactory();
|
|
13782
|
+
return {
|
|
13783
|
+
next(value) {
|
|
13784
|
+
return withCurrent(
|
|
13785
|
+
args.span,
|
|
13786
|
+
() => value === void 0 ? iterator.next() : iterator.next(value)
|
|
13787
|
+
).then(
|
|
13788
|
+
async (result) => {
|
|
13789
|
+
if (result.done) {
|
|
13790
|
+
await args.finalize();
|
|
13791
|
+
}
|
|
13792
|
+
return result;
|
|
13793
|
+
},
|
|
13794
|
+
(error) => {
|
|
13795
|
+
args.onError(error);
|
|
13796
|
+
throw error;
|
|
13797
|
+
}
|
|
13798
|
+
);
|
|
13799
|
+
},
|
|
13800
|
+
return(value) {
|
|
13801
|
+
if (typeof iterator.return !== "function") {
|
|
13802
|
+
return args.finalize().then(() => ({
|
|
13803
|
+
done: true,
|
|
13804
|
+
value
|
|
13805
|
+
}));
|
|
13806
|
+
}
|
|
13807
|
+
return withCurrent(args.span, () => iterator.return(value)).then(
|
|
13808
|
+
async (result) => {
|
|
13809
|
+
await args.finalize();
|
|
13810
|
+
return result;
|
|
13811
|
+
},
|
|
13812
|
+
(error) => {
|
|
13813
|
+
args.onError(error);
|
|
13814
|
+
throw error;
|
|
13815
|
+
}
|
|
13816
|
+
);
|
|
13817
|
+
},
|
|
13818
|
+
throw(error) {
|
|
13819
|
+
args.onError(error);
|
|
13820
|
+
if (typeof iterator.throw !== "function") {
|
|
13821
|
+
return Promise.reject(error);
|
|
13822
|
+
}
|
|
13823
|
+
return withCurrent(args.span, () => iterator.throw(error));
|
|
13824
|
+
},
|
|
13825
|
+
[Symbol.asyncIterator]() {
|
|
13826
|
+
return this;
|
|
13827
|
+
}
|
|
13828
|
+
};
|
|
13829
|
+
}
|
|
13830
|
+
};
|
|
13831
|
+
}
|
|
13832
|
+
function isAsyncIterable2(value) {
|
|
13833
|
+
return !!value && (typeof value === "object" || typeof value === "function") && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
|
|
13834
|
+
}
|
|
13835
|
+
function isPromiseLike(value) {
|
|
13836
|
+
return !!value && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function";
|
|
13837
|
+
}
|
|
13838
|
+
function normalizeError(error) {
|
|
13839
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
13840
|
+
}
|
|
13841
|
+
|
|
13842
|
+
// src/instrumentation/plugins/openrouter-plugin.ts
|
|
13843
|
+
var OpenRouterPlugin = class extends BasePlugin {
|
|
13844
|
+
onEnable() {
|
|
13845
|
+
this.subscribeToOpenRouterChannels();
|
|
13846
|
+
}
|
|
13847
|
+
onDisable() {
|
|
13848
|
+
this.unsubscribers = unsubscribeAll(this.unsubscribers);
|
|
13849
|
+
}
|
|
13850
|
+
subscribeToOpenRouterChannels() {
|
|
13851
|
+
this.unsubscribers.push(
|
|
13852
|
+
traceStreamingChannel(openRouterChannels.chatSend, {
|
|
13853
|
+
name: "openrouter.chat.send",
|
|
13854
|
+
type: "llm" /* LLM */,
|
|
13855
|
+
extractInput: (args) => {
|
|
13856
|
+
const request = getOpenRouterRequestArg(args);
|
|
13857
|
+
const chatGenerationParams = isObject(request?.chatGenerationParams) ? request.chatGenerationParams : {};
|
|
13858
|
+
const httpReferer = request?.httpReferer;
|
|
13859
|
+
const xTitle = request?.xTitle;
|
|
13860
|
+
const { messages, ...metadata } = chatGenerationParams;
|
|
13861
|
+
return {
|
|
13862
|
+
input: messages,
|
|
13863
|
+
metadata: buildOpenRouterMetadata(metadata, httpReferer, xTitle)
|
|
13864
|
+
};
|
|
13865
|
+
},
|
|
13866
|
+
extractOutput: (result) => {
|
|
13867
|
+
return isObject(result) ? result.choices : void 0;
|
|
13868
|
+
},
|
|
13869
|
+
extractMetrics: (result, startTime) => {
|
|
13870
|
+
const metrics = parseOpenRouterMetricsFromUsage(result?.usage);
|
|
13871
|
+
if (startTime) {
|
|
13872
|
+
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
13873
|
+
}
|
|
13874
|
+
return metrics;
|
|
13875
|
+
},
|
|
13876
|
+
aggregateChunks: aggregateOpenRouterChatChunks
|
|
13877
|
+
})
|
|
13878
|
+
);
|
|
13879
|
+
this.unsubscribers.push(
|
|
13880
|
+
traceAsyncChannel(openRouterChannels.embeddingsGenerate, {
|
|
13881
|
+
name: "openrouter.embeddings.generate",
|
|
13882
|
+
type: "llm" /* LLM */,
|
|
13883
|
+
extractInput: (args) => {
|
|
13884
|
+
const request = getOpenRouterRequestArg(args);
|
|
13885
|
+
const requestBody = isObject(request?.requestBody) ? request.requestBody : {};
|
|
13886
|
+
const httpReferer = request?.httpReferer;
|
|
13887
|
+
const xTitle = request?.xTitle;
|
|
13888
|
+
const { input, ...metadata } = requestBody;
|
|
13889
|
+
return {
|
|
13890
|
+
input,
|
|
13891
|
+
metadata: buildOpenRouterEmbeddingMetadata(
|
|
13892
|
+
metadata,
|
|
13893
|
+
httpReferer,
|
|
13894
|
+
xTitle
|
|
13895
|
+
)
|
|
13896
|
+
};
|
|
13897
|
+
},
|
|
13898
|
+
extractOutput: (result) => {
|
|
13899
|
+
if (!isObject(result)) {
|
|
13900
|
+
return void 0;
|
|
13901
|
+
}
|
|
13902
|
+
const embedding = result.data?.[0]?.embedding;
|
|
13903
|
+
return Array.isArray(embedding) ? { embedding_length: embedding.length } : void 0;
|
|
13904
|
+
},
|
|
13905
|
+
extractMetadata: (result) => {
|
|
13906
|
+
if (!isObject(result)) {
|
|
13907
|
+
return void 0;
|
|
13908
|
+
}
|
|
13909
|
+
return extractOpenRouterResponseMetadata(result);
|
|
13910
|
+
},
|
|
13911
|
+
extractMetrics: (result) => {
|
|
13912
|
+
return isObject(result) ? parseOpenRouterMetricsFromUsage(result.usage) : {};
|
|
13913
|
+
}
|
|
13914
|
+
})
|
|
13915
|
+
);
|
|
13916
|
+
this.unsubscribers.push(
|
|
13917
|
+
traceStreamingChannel(openRouterChannels.betaResponsesSend, {
|
|
13918
|
+
name: "openrouter.beta.responses.send",
|
|
13919
|
+
type: "llm" /* LLM */,
|
|
13920
|
+
extractInput: (args) => {
|
|
13921
|
+
const request = getOpenRouterRequestArg(args);
|
|
13922
|
+
const openResponsesRequest = isObject(request?.openResponsesRequest) ? request.openResponsesRequest : {};
|
|
13923
|
+
const httpReferer = request?.httpReferer;
|
|
13924
|
+
const xTitle = request?.xTitle;
|
|
13925
|
+
const { input, ...metadata } = openResponsesRequest;
|
|
13926
|
+
return {
|
|
13927
|
+
input,
|
|
13928
|
+
metadata: buildOpenRouterMetadata(metadata, httpReferer, xTitle)
|
|
13929
|
+
};
|
|
13930
|
+
},
|
|
13931
|
+
extractOutput: (result) => extractOpenRouterResponseOutput(result),
|
|
13932
|
+
extractMetadata: (result) => extractOpenRouterResponseMetadata(result),
|
|
13933
|
+
extractMetrics: (result, startTime) => {
|
|
13934
|
+
const metrics = parseOpenRouterMetricsFromUsage(result?.usage);
|
|
13935
|
+
if (startTime) {
|
|
13936
|
+
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
13937
|
+
}
|
|
13938
|
+
return metrics;
|
|
13939
|
+
},
|
|
13940
|
+
aggregateChunks: aggregateOpenRouterResponseStreamEvents
|
|
13941
|
+
})
|
|
13942
|
+
);
|
|
13943
|
+
this.unsubscribers.push(
|
|
13944
|
+
traceSyncStreamChannel(openRouterChannels.callModel, {
|
|
13945
|
+
name: "openrouter.callModel",
|
|
13946
|
+
type: "llm" /* LLM */,
|
|
13947
|
+
extractInput: (args) => {
|
|
13948
|
+
const request = getOpenRouterCallModelRequestArg(args);
|
|
13949
|
+
return {
|
|
13950
|
+
input: request ? extractOpenRouterCallModelInput(request) : void 0,
|
|
13951
|
+
metadata: request ? extractOpenRouterCallModelMetadata(request) : { provider: "openrouter" }
|
|
13952
|
+
};
|
|
13953
|
+
},
|
|
13954
|
+
patchResult: ({ endEvent, result, span }) => {
|
|
13955
|
+
return patchOpenRouterCallModelResult(
|
|
13956
|
+
span,
|
|
13957
|
+
result,
|
|
13958
|
+
getOpenRouterCallModelRequestArg(endEvent.arguments)
|
|
13959
|
+
);
|
|
13960
|
+
}
|
|
13961
|
+
})
|
|
13962
|
+
);
|
|
13963
|
+
this.unsubscribers.push(
|
|
13964
|
+
traceStreamingChannel(openRouterChannels.toolExecute, {
|
|
13965
|
+
name: "openrouter.tool",
|
|
13966
|
+
type: "tool" /* TOOL */,
|
|
13967
|
+
extractInput: (args, event) => ({
|
|
13968
|
+
input: args[0],
|
|
13969
|
+
metadata: {
|
|
13970
|
+
provider: "openrouter",
|
|
13971
|
+
tool_name: event.toolName,
|
|
13972
|
+
...event.toolCallId ? { tool_call_id: event.toolCallId } : {}
|
|
13973
|
+
}
|
|
13974
|
+
}),
|
|
13975
|
+
extractOutput: (result) => result,
|
|
13976
|
+
extractMetrics: () => ({}),
|
|
13977
|
+
aggregateChunks: (chunks) => ({
|
|
13978
|
+
output: chunks.length > 0 ? chunks[chunks.length - 1] : void 0,
|
|
13979
|
+
metrics: {}
|
|
13980
|
+
})
|
|
13981
|
+
})
|
|
13982
|
+
);
|
|
13983
|
+
const callModelChannel = openRouterChannels.callModel.tracingChannel();
|
|
13984
|
+
const callModelHandlers = {
|
|
13985
|
+
start: (event) => {
|
|
13986
|
+
const request = getOpenRouterCallModelRequestArg(event.arguments);
|
|
13987
|
+
if (!request) {
|
|
13988
|
+
return;
|
|
13989
|
+
}
|
|
13990
|
+
patchOpenRouterCallModelRequestTools(request);
|
|
13991
|
+
}
|
|
13992
|
+
};
|
|
13993
|
+
callModelChannel.subscribe(callModelHandlers);
|
|
13994
|
+
this.unsubscribers.push(() => {
|
|
13995
|
+
callModelChannel.unsubscribe(callModelHandlers);
|
|
13996
|
+
});
|
|
13997
|
+
}
|
|
13998
|
+
};
|
|
13999
|
+
function normalizeArgs(args) {
|
|
14000
|
+
if (Array.isArray(args)) {
|
|
14001
|
+
return args;
|
|
14002
|
+
}
|
|
14003
|
+
if (isArrayLike(args)) {
|
|
14004
|
+
return Array.from(args);
|
|
14005
|
+
}
|
|
14006
|
+
return [args];
|
|
14007
|
+
}
|
|
14008
|
+
function isArrayLike(value) {
|
|
14009
|
+
return isObject(value) && "length" in value && typeof value.length === "number" && Number.isInteger(value.length) && value.length >= 0;
|
|
14010
|
+
}
|
|
14011
|
+
function getOpenRouterRequestArg(args) {
|
|
14012
|
+
const normalizedArgs = normalizeArgs(args);
|
|
14013
|
+
const keyedCandidate = normalizedArgs.find(
|
|
14014
|
+
(arg) => isObject(arg) && ("chatGenerationParams" in arg || "requestBody" in arg || "openResponsesRequest" in arg)
|
|
14015
|
+
);
|
|
14016
|
+
if (isObject(keyedCandidate)) {
|
|
14017
|
+
return keyedCandidate;
|
|
14018
|
+
}
|
|
14019
|
+
const firstObjectArg = normalizedArgs.find((arg) => isObject(arg));
|
|
14020
|
+
return isObject(firstObjectArg) ? firstObjectArg : void 0;
|
|
14021
|
+
}
|
|
14022
|
+
function getOpenRouterCallModelRequestArg(args) {
|
|
14023
|
+
const firstObjectArg = normalizeArgs(args).find((arg) => isObject(arg));
|
|
14024
|
+
return isObject(firstObjectArg) ? firstObjectArg : void 0;
|
|
14025
|
+
}
|
|
14026
|
+
function aggregateOpenRouterChatChunks(chunks) {
|
|
14027
|
+
let role;
|
|
14028
|
+
let content = "";
|
|
14029
|
+
let toolCalls;
|
|
14030
|
+
let finishReason;
|
|
14031
|
+
let metrics = {};
|
|
14032
|
+
for (const chunk of chunks) {
|
|
14033
|
+
metrics = {
|
|
14034
|
+
...metrics,
|
|
14035
|
+
...parseOpenRouterMetricsFromUsage(chunk?.usage)
|
|
14036
|
+
};
|
|
14037
|
+
const choice = chunk?.choices?.[0];
|
|
14038
|
+
const delta = choice?.delta;
|
|
14039
|
+
if (!delta) {
|
|
14040
|
+
if (choice?.finish_reason !== void 0) {
|
|
14041
|
+
finishReason = choice.finish_reason;
|
|
14042
|
+
}
|
|
14043
|
+
continue;
|
|
14044
|
+
}
|
|
14045
|
+
if (!role && delta.role) {
|
|
14046
|
+
role = delta.role;
|
|
14047
|
+
}
|
|
14048
|
+
if (typeof delta.content === "string") {
|
|
14049
|
+
content += delta.content;
|
|
14050
|
+
}
|
|
14051
|
+
const choiceFinishReason = choice?.finishReason ?? choice?.finish_reason ?? void 0;
|
|
14052
|
+
const deltaFinishReason = delta.finishReason ?? delta.finish_reason ?? void 0;
|
|
14053
|
+
if (choiceFinishReason !== void 0) {
|
|
14054
|
+
finishReason = choiceFinishReason;
|
|
14055
|
+
} else if (deltaFinishReason !== void 0) {
|
|
14056
|
+
finishReason = deltaFinishReason;
|
|
14057
|
+
}
|
|
14058
|
+
const toolCallDeltas = Array.isArray(delta.toolCalls) ? delta.toolCalls : Array.isArray(delta.tool_calls) ? delta.tool_calls : void 0;
|
|
14059
|
+
if (!toolCallDeltas) {
|
|
14060
|
+
continue;
|
|
14061
|
+
}
|
|
14062
|
+
for (const toolDelta of toolCallDeltas) {
|
|
14063
|
+
if (!toolDelta?.function) {
|
|
14064
|
+
continue;
|
|
14065
|
+
}
|
|
14066
|
+
const toolIndex = toolDelta.index ?? 0;
|
|
14067
|
+
const existingToolCall = toolCalls?.[toolIndex];
|
|
14068
|
+
if (!existingToolCall || toolDelta.id && existingToolCall.id !== void 0 && existingToolCall.id !== toolDelta.id) {
|
|
14069
|
+
const nextToolCalls = [...toolCalls || []];
|
|
14070
|
+
nextToolCalls[toolIndex] = {
|
|
14071
|
+
index: toolIndex,
|
|
14072
|
+
id: toolDelta.id,
|
|
14073
|
+
type: toolDelta.type,
|
|
14074
|
+
function: {
|
|
14075
|
+
name: toolDelta.function.name,
|
|
14076
|
+
arguments: toolDelta.function.arguments || ""
|
|
14077
|
+
}
|
|
14078
|
+
};
|
|
14079
|
+
toolCalls = nextToolCalls;
|
|
14080
|
+
continue;
|
|
14081
|
+
}
|
|
14082
|
+
const current = existingToolCall;
|
|
14083
|
+
if (toolDelta.id && !current.id) {
|
|
14084
|
+
current.id = toolDelta.id;
|
|
14085
|
+
}
|
|
14086
|
+
if (toolDelta.type && !current.type) {
|
|
14087
|
+
current.type = toolDelta.type;
|
|
14088
|
+
}
|
|
14089
|
+
if (toolDelta.function.name && !current.function.name) {
|
|
14090
|
+
current.function.name = toolDelta.function.name;
|
|
14091
|
+
}
|
|
14092
|
+
current.function.arguments += toolDelta.function.arguments || "";
|
|
14093
|
+
}
|
|
14094
|
+
}
|
|
14095
|
+
return {
|
|
14096
|
+
output: [
|
|
14097
|
+
{
|
|
14098
|
+
index: 0,
|
|
14099
|
+
message: {
|
|
14100
|
+
role,
|
|
14101
|
+
content: content || void 0,
|
|
14102
|
+
...toolCalls ? { tool_calls: toolCalls } : {}
|
|
14103
|
+
},
|
|
14104
|
+
logprobs: null,
|
|
14105
|
+
finish_reason: finishReason
|
|
14106
|
+
}
|
|
14107
|
+
],
|
|
14108
|
+
metrics
|
|
14109
|
+
};
|
|
14110
|
+
}
|
|
14111
|
+
function aggregateOpenRouterResponseStreamEvents(chunks) {
|
|
14112
|
+
let finalResponse;
|
|
14113
|
+
for (const chunk of chunks) {
|
|
14114
|
+
const response = chunk?.response;
|
|
14115
|
+
if (!response) {
|
|
14116
|
+
continue;
|
|
14117
|
+
}
|
|
14118
|
+
if (chunk.type === "response.completed" || chunk.type === "response.incomplete" || chunk.type === "response.failed") {
|
|
14119
|
+
finalResponse = response;
|
|
14120
|
+
}
|
|
14121
|
+
}
|
|
14122
|
+
if (!finalResponse) {
|
|
14123
|
+
return {
|
|
14124
|
+
output: void 0,
|
|
14125
|
+
metrics: {}
|
|
14126
|
+
};
|
|
14127
|
+
}
|
|
14128
|
+
return {
|
|
14129
|
+
output: extractOpenRouterResponseOutput(finalResponse),
|
|
14130
|
+
metrics: parseOpenRouterMetricsFromUsage(finalResponse.usage),
|
|
14131
|
+
...extractOpenRouterResponseMetadata(finalResponse) ? { metadata: extractOpenRouterResponseMetadata(finalResponse) } : {}
|
|
14132
|
+
};
|
|
14133
|
+
}
|
|
14134
|
+
|
|
14135
|
+
// src/instrumentation/braintrust-plugin.ts
|
|
14136
|
+
var BraintrustPlugin = class extends BasePlugin {
|
|
14137
|
+
config;
|
|
14138
|
+
openaiPlugin = null;
|
|
14139
|
+
anthropicPlugin = null;
|
|
14140
|
+
aiSDKPlugin = null;
|
|
14141
|
+
claudeAgentSDKPlugin = null;
|
|
14142
|
+
googleGenAIPlugin = null;
|
|
14143
|
+
openRouterPlugin = null;
|
|
14144
|
+
constructor(config = {}) {
|
|
14145
|
+
super();
|
|
14146
|
+
this.config = config;
|
|
14147
|
+
}
|
|
14148
|
+
onEnable() {
|
|
14149
|
+
const integrations = this.config.integrations || {};
|
|
14150
|
+
if (integrations.openai !== false) {
|
|
14151
|
+
this.openaiPlugin = new OpenAIPlugin();
|
|
14152
|
+
this.openaiPlugin.enable();
|
|
14153
|
+
}
|
|
14154
|
+
if (integrations.anthropic !== false) {
|
|
14155
|
+
this.anthropicPlugin = new AnthropicPlugin();
|
|
14156
|
+
this.anthropicPlugin.enable();
|
|
14157
|
+
}
|
|
14158
|
+
if (integrations.aisdk !== false && integrations.vercel !== false) {
|
|
14159
|
+
this.aiSDKPlugin = new AISDKPlugin();
|
|
14160
|
+
this.aiSDKPlugin.enable();
|
|
14161
|
+
}
|
|
14162
|
+
if (integrations.claudeAgentSDK !== false) {
|
|
14163
|
+
this.claudeAgentSDKPlugin = new ClaudeAgentSDKPlugin();
|
|
14164
|
+
this.claudeAgentSDKPlugin.enable();
|
|
14165
|
+
}
|
|
14166
|
+
if (integrations.googleGenAI !== false && integrations.google !== false) {
|
|
14167
|
+
this.googleGenAIPlugin = new GoogleGenAIPlugin();
|
|
14168
|
+
this.googleGenAIPlugin.enable();
|
|
14169
|
+
}
|
|
14170
|
+
if (integrations.openrouter !== false) {
|
|
14171
|
+
this.openRouterPlugin = new OpenRouterPlugin();
|
|
14172
|
+
this.openRouterPlugin.enable();
|
|
14173
|
+
}
|
|
14174
|
+
}
|
|
14175
|
+
onDisable() {
|
|
14176
|
+
if (this.openaiPlugin) {
|
|
14177
|
+
this.openaiPlugin.disable();
|
|
14178
|
+
this.openaiPlugin = null;
|
|
14179
|
+
}
|
|
14180
|
+
if (this.anthropicPlugin) {
|
|
14181
|
+
this.anthropicPlugin.disable();
|
|
14182
|
+
this.anthropicPlugin = null;
|
|
14183
|
+
}
|
|
14184
|
+
if (this.aiSDKPlugin) {
|
|
14185
|
+
this.aiSDKPlugin.disable();
|
|
14186
|
+
this.aiSDKPlugin = null;
|
|
14187
|
+
}
|
|
14188
|
+
if (this.claudeAgentSDKPlugin) {
|
|
14189
|
+
this.claudeAgentSDKPlugin.disable();
|
|
14190
|
+
this.claudeAgentSDKPlugin = null;
|
|
14191
|
+
}
|
|
14192
|
+
if (this.googleGenAIPlugin) {
|
|
14193
|
+
this.googleGenAIPlugin.disable();
|
|
14194
|
+
this.googleGenAIPlugin = null;
|
|
14195
|
+
}
|
|
14196
|
+
if (this.openRouterPlugin) {
|
|
14197
|
+
this.openRouterPlugin.disable();
|
|
14198
|
+
this.openRouterPlugin = null;
|
|
14199
|
+
}
|
|
14200
|
+
}
|
|
14201
|
+
};
|
|
14202
|
+
|
|
14203
|
+
// src/instrumentation/registry.ts
|
|
14204
|
+
var PluginRegistry = class {
|
|
14205
|
+
braintrustPlugin = null;
|
|
14206
|
+
config = {};
|
|
14207
|
+
enabled = false;
|
|
14208
|
+
/**
|
|
14209
|
+
* Configure which integrations should be enabled.
|
|
14210
|
+
* This must be called before any SDK imports to take effect.
|
|
14211
|
+
*/
|
|
14212
|
+
configure(config) {
|
|
14213
|
+
if (this.enabled) {
|
|
14214
|
+
console.warn(
|
|
14215
|
+
"Braintrust: Cannot configure instrumentation after it has been enabled. Call configureInstrumentation() before importing any AI SDKs."
|
|
14216
|
+
);
|
|
14217
|
+
return;
|
|
14218
|
+
}
|
|
14219
|
+
this.config = { ...this.config, ...config };
|
|
14220
|
+
}
|
|
14221
|
+
/**
|
|
14222
|
+
* Enable all configured plugins.
|
|
14223
|
+
* Called automatically when the library is loaded.
|
|
14224
|
+
*/
|
|
14225
|
+
enable() {
|
|
14226
|
+
if (this.enabled) {
|
|
14227
|
+
return;
|
|
14228
|
+
}
|
|
14229
|
+
this.enabled = true;
|
|
14230
|
+
const envConfig = this.readEnvConfig();
|
|
14231
|
+
const finalConfig = {
|
|
14232
|
+
integrations: {
|
|
14233
|
+
...this.getDefaultConfig(),
|
|
14234
|
+
...this.config.integrations,
|
|
14235
|
+
...envConfig.integrations
|
|
14236
|
+
}
|
|
14237
|
+
};
|
|
14238
|
+
this.braintrustPlugin = new BraintrustPlugin(finalConfig);
|
|
14239
|
+
this.braintrustPlugin.enable();
|
|
14240
|
+
}
|
|
14241
|
+
/**
|
|
14242
|
+
* Disable all plugins.
|
|
14243
|
+
* Primarily used for testing.
|
|
14244
|
+
*/
|
|
14245
|
+
disable() {
|
|
14246
|
+
if (!this.enabled) {
|
|
14247
|
+
return;
|
|
14248
|
+
}
|
|
14249
|
+
this.enabled = false;
|
|
14250
|
+
if (this.braintrustPlugin) {
|
|
14251
|
+
this.braintrustPlugin.disable();
|
|
14252
|
+
this.braintrustPlugin = null;
|
|
14253
|
+
}
|
|
14254
|
+
}
|
|
14255
|
+
/**
|
|
14256
|
+
* Check if instrumentation is enabled.
|
|
14257
|
+
*/
|
|
14258
|
+
isEnabled() {
|
|
14259
|
+
return this.enabled;
|
|
14260
|
+
}
|
|
14261
|
+
/**
|
|
14262
|
+
* Get default configuration (all integrations enabled).
|
|
14263
|
+
*/
|
|
14264
|
+
getDefaultConfig() {
|
|
14265
|
+
return {
|
|
14266
|
+
openai: true,
|
|
14267
|
+
anthropic: true,
|
|
14268
|
+
vercel: true,
|
|
14269
|
+
aisdk: true,
|
|
14270
|
+
google: true,
|
|
14271
|
+
claudeAgentSDK: true,
|
|
14272
|
+
openrouter: true
|
|
14273
|
+
};
|
|
14274
|
+
}
|
|
14275
|
+
/**
|
|
14276
|
+
* Read configuration from environment variables.
|
|
14277
|
+
* Supports: BRAINTRUST_DISABLE_INSTRUMENTATION=openai,anthropic,...
|
|
14278
|
+
*/
|
|
14279
|
+
readEnvConfig() {
|
|
14280
|
+
const integrations = {};
|
|
14281
|
+
const disabledList = isomorph_default.getEnv("BRAINTRUST_DISABLE_INSTRUMENTATION");
|
|
14282
|
+
if (disabledList) {
|
|
14283
|
+
const disabled = disabledList.split(",").map((s) => s.trim().toLowerCase()).filter((s) => s.length > 0);
|
|
14284
|
+
for (const sdk of disabled) {
|
|
14285
|
+
integrations[sdk] = false;
|
|
14286
|
+
}
|
|
14287
|
+
}
|
|
14288
|
+
return { integrations };
|
|
14289
|
+
}
|
|
14290
|
+
};
|
|
14291
|
+
var registry = new PluginRegistry();
|
|
14292
|
+
function configureInstrumentation(config) {
|
|
14293
|
+
registry.configure(config);
|
|
14294
|
+
}
|
|
14295
|
+
|
|
14296
|
+
// src/node/config.ts
|
|
14297
|
+
function configureNode() {
|
|
14298
|
+
isomorph_default.buildType = "node";
|
|
14299
|
+
isomorph_default.getRepoInfo = getRepoInfo;
|
|
13159
14300
|
isomorph_default.getPastNAncestors = getPastNAncestors;
|
|
13160
14301
|
isomorph_default.getEnv = (name) => process.env[name];
|
|
13161
14302
|
isomorph_default.getCallerLocation = getCallerLocation;
|
|
13162
14303
|
isomorph_default.newAsyncLocalStorage = () => new AsyncLocalStorage();
|
|
13163
14304
|
isomorph_default.newTracingChannel = (nameOrChannels) => diagnostics_channel.tracingChannel(nameOrChannels);
|
|
14305
|
+
patchTracingChannel(diagnostics_channel.tracingChannel);
|
|
13164
14306
|
isomorph_default.processOn = (event, handler) => {
|
|
13165
14307
|
process.on(event, handler);
|
|
13166
14308
|
};
|
|
@@ -13323,6 +14465,7 @@ __export(exports_exports, {
|
|
|
13323
14465
|
wrapMastraAgent: () => wrapMastraAgent,
|
|
13324
14466
|
wrapOpenAI: () => wrapOpenAI,
|
|
13325
14467
|
wrapOpenAIv4: () => wrapOpenAIv4,
|
|
14468
|
+
wrapOpenRouter: () => wrapOpenRouter,
|
|
13326
14469
|
wrapTraced: () => wrapTraced,
|
|
13327
14470
|
wrapVitest: () => wrapVitest
|
|
13328
14471
|
});
|
|
@@ -13653,7 +14796,7 @@ function wrapOpenAIv4(openai) {
|
|
|
13653
14796
|
return baseVal;
|
|
13654
14797
|
}
|
|
13655
14798
|
});
|
|
13656
|
-
const
|
|
14799
|
+
const chatProxy2 = new Proxy(typedOpenai.chat, {
|
|
13657
14800
|
get(target, name, receiver) {
|
|
13658
14801
|
if (name === "completions") {
|
|
13659
14802
|
return completionProxy;
|
|
@@ -13663,7 +14806,7 @@ function wrapOpenAIv4(openai) {
|
|
|
13663
14806
|
});
|
|
13664
14807
|
const embeddingProxy = createEndpointProxy(typedOpenai.embeddings, wrapEmbeddings);
|
|
13665
14808
|
const moderationProxy = createEndpointProxy(typedOpenai.moderations, wrapModerations);
|
|
13666
|
-
let
|
|
14809
|
+
let betaProxy3;
|
|
13667
14810
|
if (typedOpenai.beta?.chat?.completions?.stream) {
|
|
13668
14811
|
const betaChatCompletionProxy = new Proxy(
|
|
13669
14812
|
typedOpenai?.beta?.chat.completions,
|
|
@@ -13687,7 +14830,7 @@ function wrapOpenAIv4(openai) {
|
|
|
13687
14830
|
return Reflect.get(target, name, receiver);
|
|
13688
14831
|
}
|
|
13689
14832
|
});
|
|
13690
|
-
|
|
14833
|
+
betaProxy3 = new Proxy(typedOpenai.beta, {
|
|
13691
14834
|
get(target, name, receiver) {
|
|
13692
14835
|
if (name === "chat") {
|
|
13693
14836
|
return betaChatProxy;
|
|
@@ -13700,7 +14843,7 @@ function wrapOpenAIv4(openai) {
|
|
|
13700
14843
|
get(target, name, receiver) {
|
|
13701
14844
|
switch (name) {
|
|
13702
14845
|
case "chat":
|
|
13703
|
-
return
|
|
14846
|
+
return chatProxy2;
|
|
13704
14847
|
case "embeddings":
|
|
13705
14848
|
return embeddingProxy;
|
|
13706
14849
|
case "moderations":
|
|
@@ -13708,8 +14851,8 @@ function wrapOpenAIv4(openai) {
|
|
|
13708
14851
|
case "responses":
|
|
13709
14852
|
return responsesProxy(typedOpenai);
|
|
13710
14853
|
}
|
|
13711
|
-
if (name === "beta" &&
|
|
13712
|
-
return
|
|
14854
|
+
if (name === "beta" && betaProxy3) {
|
|
14855
|
+
return betaProxy3;
|
|
13713
14856
|
}
|
|
13714
14857
|
return Reflect.get(target, name, receiver);
|
|
13715
14858
|
}
|
|
@@ -14673,10 +15816,10 @@ function extractGatewayRoutingInfo2(result) {
|
|
|
14673
15816
|
}
|
|
14674
15817
|
return null;
|
|
14675
15818
|
}
|
|
14676
|
-
var
|
|
15819
|
+
var isZodSchema3 = (value) => {
|
|
14677
15820
|
return value != null && typeof value === "object" && "_def" in value && typeof value._def === "object";
|
|
14678
15821
|
};
|
|
14679
|
-
var
|
|
15822
|
+
var serializeZodSchema3 = (schema) => {
|
|
14680
15823
|
try {
|
|
14681
15824
|
return zodToJsonSchema(schema);
|
|
14682
15825
|
} catch {
|
|
@@ -14724,10 +15867,10 @@ var serializeOutputObject = (output, model) => {
|
|
|
14724
15867
|
if (typeof responseFormat.then === "function") {
|
|
14725
15868
|
result.response_format = Promise.resolve(responseFormat).then(
|
|
14726
15869
|
(resolved) => {
|
|
14727
|
-
if (resolved.schema &&
|
|
15870
|
+
if (resolved.schema && isZodSchema3(resolved.schema)) {
|
|
14728
15871
|
return {
|
|
14729
15872
|
...resolved,
|
|
14730
|
-
schema:
|
|
15873
|
+
schema: serializeZodSchema3(resolved.schema)
|
|
14731
15874
|
};
|
|
14732
15875
|
}
|
|
14733
15876
|
return resolved;
|
|
@@ -14735,10 +15878,10 @@ var serializeOutputObject = (output, model) => {
|
|
|
14735
15878
|
);
|
|
14736
15879
|
} else {
|
|
14737
15880
|
const syncResponseFormat = responseFormat;
|
|
14738
|
-
if (syncResponseFormat.schema &&
|
|
15881
|
+
if (syncResponseFormat.schema && isZodSchema3(syncResponseFormat.schema)) {
|
|
14739
15882
|
responseFormat = {
|
|
14740
15883
|
...syncResponseFormat,
|
|
14741
|
-
schema:
|
|
15884
|
+
schema: serializeZodSchema3(syncResponseFormat.schema)
|
|
14742
15885
|
};
|
|
14743
15886
|
}
|
|
14744
15887
|
result.response_format = responseFormat;
|
|
@@ -14764,11 +15907,11 @@ var processInputAttachmentsSync = (input) => {
|
|
|
14764
15907
|
processed.prompt = processPromptContent(input.prompt);
|
|
14765
15908
|
}
|
|
14766
15909
|
}
|
|
14767
|
-
if (input.schema &&
|
|
14768
|
-
processed.schema =
|
|
15910
|
+
if (input.schema && isZodSchema3(input.schema)) {
|
|
15911
|
+
processed.schema = serializeZodSchema3(input.schema);
|
|
14769
15912
|
}
|
|
14770
|
-
if (input.callOptionsSchema &&
|
|
14771
|
-
processed.callOptionsSchema =
|
|
15913
|
+
if (input.callOptionsSchema && isZodSchema3(input.callOptionsSchema)) {
|
|
15914
|
+
processed.callOptionsSchema = serializeZodSchema3(input.callOptionsSchema);
|
|
14772
15915
|
}
|
|
14773
15916
|
if (input.tools) {
|
|
14774
15917
|
processed.tools = serializeAISDKToolsForLogging(input.tools);
|
|
@@ -14805,11 +15948,11 @@ var processInputAttachments2 = async (input) => {
|
|
|
14805
15948
|
processed.prompt = processPromptContent(input.prompt);
|
|
14806
15949
|
}
|
|
14807
15950
|
}
|
|
14808
|
-
if (input.schema &&
|
|
14809
|
-
processed.schema =
|
|
15951
|
+
if (input.schema && isZodSchema3(input.schema)) {
|
|
15952
|
+
processed.schema = serializeZodSchema3(input.schema);
|
|
14810
15953
|
}
|
|
14811
|
-
if (input.callOptionsSchema &&
|
|
14812
|
-
processed.callOptionsSchema =
|
|
15954
|
+
if (input.callOptionsSchema && isZodSchema3(input.callOptionsSchema)) {
|
|
15955
|
+
processed.callOptionsSchema = serializeZodSchema3(input.callOptionsSchema);
|
|
14813
15956
|
}
|
|
14814
15957
|
if (input.tools) {
|
|
14815
15958
|
processed.tools = serializeAISDKToolsForLogging(input.tools);
|
|
@@ -15578,14 +16721,14 @@ function extractModelFromResult(result) {
|
|
|
15578
16721
|
function extractModelFromWrapGenerateCallback(model) {
|
|
15579
16722
|
return model?.modelId;
|
|
15580
16723
|
}
|
|
15581
|
-
function
|
|
16724
|
+
function camelToSnake2(str) {
|
|
15582
16725
|
return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
|
|
15583
16726
|
}
|
|
15584
16727
|
function extractModelParameters(params, excludeKeys) {
|
|
15585
16728
|
const modelParams = {};
|
|
15586
16729
|
for (const [key, value] of Object.entries(params)) {
|
|
15587
16730
|
if (value !== void 0 && !excludeKeys.has(key)) {
|
|
15588
|
-
const snakeKey =
|
|
16731
|
+
const snakeKey = camelToSnake2(key);
|
|
15589
16732
|
modelParams[snakeKey] = value;
|
|
15590
16733
|
}
|
|
15591
16734
|
}
|
|
@@ -16445,7 +17588,7 @@ function filterSerializableOptions2(options) {
|
|
|
16445
17588
|
}
|
|
16446
17589
|
return filtered;
|
|
16447
17590
|
}
|
|
16448
|
-
function
|
|
17591
|
+
function isAsyncIterable3(value) {
|
|
16449
17592
|
return value !== null && typeof value === "object" && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
|
|
16450
17593
|
}
|
|
16451
17594
|
function wrapClaudeAgentQuery(queryFn, defaultThis) {
|
|
@@ -16453,7 +17596,7 @@ function wrapClaudeAgentQuery(queryFn, defaultThis) {
|
|
|
16453
17596
|
apply(target, thisArg, argArray) {
|
|
16454
17597
|
const params = argArray[0] ?? {};
|
|
16455
17598
|
const { prompt, options = {} } = params;
|
|
16456
|
-
const promptIsAsyncIterable =
|
|
17599
|
+
const promptIsAsyncIterable = isAsyncIterable3(prompt);
|
|
16457
17600
|
let capturedPromptMessages;
|
|
16458
17601
|
let promptForQuery = prompt;
|
|
16459
17602
|
let promptStarted = false;
|
|
@@ -17302,6 +18445,111 @@ function tryToDict2(obj) {
|
|
|
17302
18445
|
return null;
|
|
17303
18446
|
}
|
|
17304
18447
|
|
|
18448
|
+
// src/wrappers/openrouter.ts
|
|
18449
|
+
function wrapOpenRouter(openrouter) {
|
|
18450
|
+
const or = openrouter;
|
|
18451
|
+
if (or && typeof or === "object" && ("chat" in or && typeof or.chat === "object" && or.chat && "send" in or.chat && "embeddings" in or && typeof or.embeddings === "object" && or.embeddings && "generate" in or.embeddings || "callModel" in or && typeof or.callModel === "function")) {
|
|
18452
|
+
return openRouterProxy(or);
|
|
18453
|
+
}
|
|
18454
|
+
console.warn("Unsupported OpenRouter library. Not wrapping.");
|
|
18455
|
+
return openrouter;
|
|
18456
|
+
}
|
|
18457
|
+
function openRouterProxy(openrouter) {
|
|
18458
|
+
return new Proxy(openrouter, {
|
|
18459
|
+
get(target, prop, receiver) {
|
|
18460
|
+
switch (prop) {
|
|
18461
|
+
case "chat":
|
|
18462
|
+
return target.chat ? chatProxy(target.chat) : target.chat;
|
|
18463
|
+
case "embeddings":
|
|
18464
|
+
return target.embeddings ? embeddingsProxy(target.embeddings) : target.embeddings;
|
|
18465
|
+
case "beta":
|
|
18466
|
+
return target.beta ? betaProxy2(target.beta) : target.beta;
|
|
18467
|
+
case "callModel":
|
|
18468
|
+
return typeof target.callModel === "function" ? wrapCallModel(target.callModel.bind(target)) : target.callModel;
|
|
18469
|
+
default:
|
|
18470
|
+
return Reflect.get(target, prop, receiver);
|
|
18471
|
+
}
|
|
18472
|
+
}
|
|
18473
|
+
});
|
|
18474
|
+
}
|
|
18475
|
+
function betaProxy2(beta) {
|
|
18476
|
+
return new Proxy(beta, {
|
|
18477
|
+
get(target, prop, receiver) {
|
|
18478
|
+
if (prop === "responses") {
|
|
18479
|
+
return target.responses ? responsesProxy2(target.responses) : void 0;
|
|
18480
|
+
}
|
|
18481
|
+
return Reflect.get(target, prop, receiver);
|
|
18482
|
+
}
|
|
18483
|
+
});
|
|
18484
|
+
}
|
|
18485
|
+
function chatProxy(chat) {
|
|
18486
|
+
return new Proxy(chat, {
|
|
18487
|
+
get(target, prop, receiver) {
|
|
18488
|
+
if (prop === "send") {
|
|
18489
|
+
return wrapChatSend(target.send.bind(target));
|
|
18490
|
+
}
|
|
18491
|
+
return Reflect.get(target, prop, receiver);
|
|
18492
|
+
}
|
|
18493
|
+
});
|
|
18494
|
+
}
|
|
18495
|
+
function embeddingsProxy(embeddings) {
|
|
18496
|
+
return new Proxy(embeddings, {
|
|
18497
|
+
get(target, prop, receiver) {
|
|
18498
|
+
if (prop === "generate") {
|
|
18499
|
+
return wrapEmbeddingsGenerate(target.generate.bind(target));
|
|
18500
|
+
}
|
|
18501
|
+
return Reflect.get(target, prop, receiver);
|
|
18502
|
+
}
|
|
18503
|
+
});
|
|
18504
|
+
}
|
|
18505
|
+
function responsesProxy2(responses) {
|
|
18506
|
+
return new Proxy(responses, {
|
|
18507
|
+
get(target, prop, receiver) {
|
|
18508
|
+
if (prop === "send") {
|
|
18509
|
+
return wrapResponsesSend(target.send.bind(target));
|
|
18510
|
+
}
|
|
18511
|
+
return Reflect.get(target, prop, receiver);
|
|
18512
|
+
}
|
|
18513
|
+
});
|
|
18514
|
+
}
|
|
18515
|
+
function wrapChatSend(send) {
|
|
18516
|
+
return (request, options) => openRouterChannels.chatSend.tracePromise(() => send(request, options), {
|
|
18517
|
+
arguments: [request]
|
|
18518
|
+
});
|
|
18519
|
+
}
|
|
18520
|
+
function wrapEmbeddingsGenerate(generate) {
|
|
18521
|
+
return (request, options) => openRouterChannels.embeddingsGenerate.tracePromise(
|
|
18522
|
+
() => generate(request, options),
|
|
18523
|
+
{ arguments: [request] }
|
|
18524
|
+
);
|
|
18525
|
+
}
|
|
18526
|
+
function wrapResponsesSend(send) {
|
|
18527
|
+
return (request, options) => openRouterChannels.betaResponsesSend.tracePromise(
|
|
18528
|
+
() => send(request, options),
|
|
18529
|
+
{ arguments: [request] }
|
|
18530
|
+
);
|
|
18531
|
+
}
|
|
18532
|
+
function wrapCallModel(callModel) {
|
|
18533
|
+
return (request, options) => {
|
|
18534
|
+
const patchedRequest = { ...request };
|
|
18535
|
+
patchOpenRouterCallModelRequestTools(patchedRequest);
|
|
18536
|
+
const span = startOpenRouterCallModelSpan(patchedRequest);
|
|
18537
|
+
try {
|
|
18538
|
+
const result = callModel(patchedRequest, options);
|
|
18539
|
+
if (!patchOpenRouterCallModelResult(span, result, patchedRequest)) {
|
|
18540
|
+
span.end();
|
|
18541
|
+
}
|
|
18542
|
+
return result;
|
|
18543
|
+
} catch (error) {
|
|
18544
|
+
span.log({
|
|
18545
|
+
error: error instanceof Error ? error.message : String(error)
|
|
18546
|
+
});
|
|
18547
|
+
span.end();
|
|
18548
|
+
throw error;
|
|
18549
|
+
}
|
|
18550
|
+
};
|
|
18551
|
+
}
|
|
18552
|
+
|
|
17305
18553
|
// src/wrappers/vitest/context-manager.ts
|
|
17306
18554
|
var VitestContextManager = class {
|
|
17307
18555
|
/**
|
|
@@ -18272,7 +19520,7 @@ function isAsync(fn) {
|
|
|
18272
19520
|
function isAsyncGenerator3(fn) {
|
|
18273
19521
|
return fn[Symbol.toStringTag] === "AsyncGenerator";
|
|
18274
19522
|
}
|
|
18275
|
-
function
|
|
19523
|
+
function isAsyncIterable4(obj) {
|
|
18276
19524
|
return typeof obj[Symbol.asyncIterator] === "function";
|
|
18277
19525
|
}
|
|
18278
19526
|
function wrapAsync(asyncFn) {
|
|
@@ -18322,7 +19570,7 @@ function _asyncMap(eachfn, arr, iteratee, callback) {
|
|
|
18322
19570
|
callback(err, results);
|
|
18323
19571
|
});
|
|
18324
19572
|
}
|
|
18325
|
-
function
|
|
19573
|
+
function isArrayLike2(value) {
|
|
18326
19574
|
return value && typeof value.length === "number" && value.length >= 0 && value.length % 1 === 0;
|
|
18327
19575
|
}
|
|
18328
19576
|
var breakLoop = {};
|
|
@@ -18370,7 +19618,7 @@ function createObjectIterator(obj) {
|
|
|
18370
19618
|
};
|
|
18371
19619
|
}
|
|
18372
19620
|
function createIterator(coll) {
|
|
18373
|
-
if (
|
|
19621
|
+
if (isArrayLike2(coll)) {
|
|
18374
19622
|
return createArrayIterator(coll);
|
|
18375
19623
|
}
|
|
18376
19624
|
var iterator = getIterator(coll);
|
|
@@ -18444,7 +19692,7 @@ var eachOfLimit$2 = (limit) => {
|
|
|
18444
19692
|
if (isAsyncGenerator3(obj)) {
|
|
18445
19693
|
return asyncEachOfLimit(obj, limit, iteratee, callback);
|
|
18446
19694
|
}
|
|
18447
|
-
if (
|
|
19695
|
+
if (isAsyncIterable4(obj)) {
|
|
18448
19696
|
return asyncEachOfLimit(obj[Symbol.asyncIterator](), limit, iteratee, callback);
|
|
18449
19697
|
}
|
|
18450
19698
|
var nextElem = createIterator(obj);
|
|
@@ -18516,7 +19764,7 @@ function eachOfGeneric(coll, iteratee, callback) {
|
|
|
18516
19764
|
return eachOfLimit$1(coll, Infinity, iteratee, callback);
|
|
18517
19765
|
}
|
|
18518
19766
|
function eachOf(coll, iteratee, callback) {
|
|
18519
|
-
var eachOfImplementation =
|
|
19767
|
+
var eachOfImplementation = isArrayLike2(coll) ? eachOfArrayLike : eachOfGeneric;
|
|
18520
19768
|
return eachOfImplementation(coll, wrapAsync(iteratee), callback);
|
|
18521
19769
|
}
|
|
18522
19770
|
var eachOf$1 = awaitify(eachOf, 3);
|
|
@@ -19031,7 +20279,7 @@ function filterGeneric(eachfn, coll, iteratee, callback) {
|
|
|
19031
20279
|
});
|
|
19032
20280
|
}
|
|
19033
20281
|
function _filter(eachfn, coll, iteratee, callback) {
|
|
19034
|
-
var filter2 =
|
|
20282
|
+
var filter2 = isArrayLike2(coll) ? filterArray : filterGeneric;
|
|
19035
20283
|
return filter2(eachfn, coll, wrapAsync(iteratee), callback);
|
|
19036
20284
|
}
|
|
19037
20285
|
function filter(coll, iteratee, callback) {
|
|
@@ -19106,7 +20354,7 @@ if (hasNextTick) {
|
|
|
19106
20354
|
}
|
|
19107
20355
|
var nextTick = wrap(_defer);
|
|
19108
20356
|
var _parallel = awaitify((eachfn, tasks, callback) => {
|
|
19109
|
-
var results =
|
|
20357
|
+
var results = isArrayLike2(tasks) ? [] : {};
|
|
19110
20358
|
eachfn(tasks, (task, key, taskCb) => {
|
|
19111
20359
|
wrapAsync(task)((err, ...result) => {
|
|
19112
20360
|
if (result.length < 2) {
|
|
@@ -19711,7 +20959,7 @@ function callEvaluatorData(data) {
|
|
|
19711
20959
|
baseExperiment
|
|
19712
20960
|
};
|
|
19713
20961
|
}
|
|
19714
|
-
function
|
|
20962
|
+
function isAsyncIterable5(value) {
|
|
19715
20963
|
return typeof value === "object" && value !== null && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
|
|
19716
20964
|
}
|
|
19717
20965
|
function isIterable(value) {
|
|
@@ -19935,7 +21183,7 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
|
|
|
19935
21183
|
}
|
|
19936
21184
|
const resolvedDataResult = dataResult instanceof Promise ? await dataResult : dataResult;
|
|
19937
21185
|
const dataIterable = (() => {
|
|
19938
|
-
if (
|
|
21186
|
+
if (isAsyncIterable5(resolvedDataResult)) {
|
|
19939
21187
|
return resolvedDataResult;
|
|
19940
21188
|
}
|
|
19941
21189
|
if (Array.isArray(resolvedDataResult) || isIterable(resolvedDataResult)) {
|
|
@@ -21144,6 +22392,7 @@ export {
|
|
|
21144
22392
|
wrapMastraAgent,
|
|
21145
22393
|
wrapOpenAI,
|
|
21146
22394
|
wrapOpenAIv4,
|
|
22395
|
+
wrapOpenRouter,
|
|
21147
22396
|
wrapTraced,
|
|
21148
22397
|
wrapVitest
|
|
21149
22398
|
};
|