braintrust 3.3.0 → 3.4.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/README.md +52 -67
- package/dev/dist/index.d.mts +53 -9
- package/dev/dist/index.d.ts +53 -9
- package/dev/dist/index.js +1839 -1298
- package/dev/dist/index.mjs +1503 -962
- package/dist/auto-instrumentations/bundler/esbuild.cjs +270 -23
- package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
- package/dist/auto-instrumentations/bundler/rollup.cjs +270 -23
- package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
- package/dist/auto-instrumentations/bundler/vite.cjs +270 -23
- package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
- package/dist/auto-instrumentations/bundler/webpack.cjs +270 -23
- package/dist/auto-instrumentations/bundler/webpack.mjs +2 -2
- package/dist/auto-instrumentations/{chunk-OLOPGWTJ.mjs → chunk-D5ZPIUEL.mjs} +1 -1
- package/dist/auto-instrumentations/chunk-LVWWLUMN.mjs +535 -0
- package/dist/auto-instrumentations/hook.mjs +306 -23
- package/dist/auto-instrumentations/index.cjs +270 -23
- package/dist/auto-instrumentations/index.d.mts +5 -5
- package/dist/auto-instrumentations/index.d.ts +5 -5
- package/dist/auto-instrumentations/index.mjs +1 -1
- package/dist/auto-instrumentations/loader/esm-hook.mjs +7 -8
- package/dist/browser.d.mts +474 -47
- package/dist/browser.d.ts +474 -47
- package/dist/browser.js +2258 -2095
- package/dist/browser.mjs +2258 -2095
- package/dist/cli.js +1817 -1232
- package/dist/edge-light.d.mts +1 -1
- package/dist/edge-light.d.ts +1 -1
- package/dist/edge-light.js +2188 -2027
- package/dist/edge-light.mjs +2188 -2027
- package/dist/index.d.mts +474 -47
- package/dist/index.d.ts +474 -47
- package/dist/index.js +2576 -2415
- package/dist/index.mjs +2259 -2098
- package/dist/instrumentation/index.d.mts +16 -22
- package/dist/instrumentation/index.d.ts +16 -22
- package/dist/instrumentation/index.js +1558 -1068
- package/dist/instrumentation/index.mjs +1558 -1068
- package/dist/workerd.d.mts +1 -1
- package/dist/workerd.d.ts +1 -1
- package/dist/workerd.js +2188 -2027
- package/dist/workerd.mjs +2188 -2027
- package/package.json +6 -3
- package/dist/auto-instrumentations/chunk-KVX7OFPD.mjs +0 -288
|
@@ -39,8 +39,55 @@ __export(index_exports, {
|
|
|
39
39
|
});
|
|
40
40
|
module.exports = __toCommonJS(index_exports);
|
|
41
41
|
|
|
42
|
-
// src/
|
|
43
|
-
var
|
|
42
|
+
// src/isomorph.ts
|
|
43
|
+
var DefaultAsyncLocalStorage = class {
|
|
44
|
+
constructor() {
|
|
45
|
+
}
|
|
46
|
+
enterWith(_) {
|
|
47
|
+
}
|
|
48
|
+
run(_, callback) {
|
|
49
|
+
return callback();
|
|
50
|
+
}
|
|
51
|
+
getStore() {
|
|
52
|
+
return void 0;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
var DefaultTracingChannel = class {
|
|
56
|
+
hasSubscribers = false;
|
|
57
|
+
subscribe(_handlers) {
|
|
58
|
+
}
|
|
59
|
+
unsubscribe(_handlers) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
63
|
+
traceSync(fn, _message, thisArg, ...args) {
|
|
64
|
+
return fn.apply(thisArg, args);
|
|
65
|
+
}
|
|
66
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
67
|
+
tracePromise(fn, _message, thisArg, ...args) {
|
|
68
|
+
return Promise.resolve(fn.apply(thisArg, args));
|
|
69
|
+
}
|
|
70
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
71
|
+
traceCallback(fn, _position, _message, thisArg, ...args) {
|
|
72
|
+
return fn.apply(thisArg, args);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
var iso = {
|
|
76
|
+
buildType: "unknown",
|
|
77
|
+
// Will be set by configureBrowser() or configureNode()
|
|
78
|
+
getRepoInfo: async (_settings) => void 0,
|
|
79
|
+
getPastNAncestors: async () => [],
|
|
80
|
+
getEnv: (_name) => void 0,
|
|
81
|
+
getCallerLocation: () => void 0,
|
|
82
|
+
newAsyncLocalStorage: () => new DefaultAsyncLocalStorage(),
|
|
83
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
84
|
+
newTracingChannel: (_nameOrChannels) => new DefaultTracingChannel(),
|
|
85
|
+
processOn: (_0, _1) => {
|
|
86
|
+
},
|
|
87
|
+
basename: (filepath) => filepath.split(/[\\/]/).pop() || filepath,
|
|
88
|
+
writeln: (text) => console.log(text)
|
|
89
|
+
};
|
|
90
|
+
var isomorph_default = iso;
|
|
44
91
|
|
|
45
92
|
// src/instrumentation/core/stream-patcher.ts
|
|
46
93
|
function isAsyncIterable(value) {
|
|
@@ -57,7 +104,7 @@ function patchStreamIfNeeded(stream, options) {
|
|
|
57
104
|
return stream;
|
|
58
105
|
}
|
|
59
106
|
const originalIteratorFn = stream[Symbol.asyncIterator];
|
|
60
|
-
if (originalIteratorFn
|
|
107
|
+
if ("__braintrust_patched" in originalIteratorFn && originalIteratorFn["__braintrust_patched"]) {
|
|
61
108
|
return stream;
|
|
62
109
|
}
|
|
63
110
|
try {
|
|
@@ -98,7 +145,10 @@ function patchStreamIfNeeded(stream, options) {
|
|
|
98
145
|
completed = true;
|
|
99
146
|
if (options.onError) {
|
|
100
147
|
try {
|
|
101
|
-
options.onError(
|
|
148
|
+
options.onError(
|
|
149
|
+
error instanceof Error ? error : new Error(String(error)),
|
|
150
|
+
chunks
|
|
151
|
+
);
|
|
102
152
|
} catch (handlerError) {
|
|
103
153
|
console.error("Error in stream onError handler:", handlerError);
|
|
104
154
|
}
|
|
@@ -126,7 +176,8 @@ function patchStreamIfNeeded(stream, options) {
|
|
|
126
176
|
iterator.throw = async function(...args) {
|
|
127
177
|
if (!completed) {
|
|
128
178
|
completed = true;
|
|
129
|
-
const
|
|
179
|
+
const rawError = args[0];
|
|
180
|
+
const error = rawError instanceof Error ? rawError : new Error(String(rawError));
|
|
130
181
|
if (options.onError) {
|
|
131
182
|
try {
|
|
132
183
|
options.onError(error, chunks);
|
|
@@ -140,7 +191,9 @@ function patchStreamIfNeeded(stream, options) {
|
|
|
140
191
|
}
|
|
141
192
|
return iterator;
|
|
142
193
|
};
|
|
143
|
-
patchedIteratorFn
|
|
194
|
+
Object.defineProperty(patchedIteratorFn, "__braintrust_patched", {
|
|
195
|
+
value: true
|
|
196
|
+
});
|
|
144
197
|
stream[Symbol.asyncIterator] = patchedIteratorFn;
|
|
145
198
|
return stream;
|
|
146
199
|
} catch (error) {
|
|
@@ -152,6 +205,111 @@ function patchStreamIfNeeded(stream, options) {
|
|
|
152
205
|
// src/logger.ts
|
|
153
206
|
var import_uuid2 = require("uuid");
|
|
154
207
|
|
|
208
|
+
// src/debug-logger.ts
|
|
209
|
+
var PREFIX = "[braintrust]";
|
|
210
|
+
var DEBUG_LOG_LEVEL_SYMBOL = Symbol.for("braintrust-debug-log-level");
|
|
211
|
+
var LOG_LEVEL_PRIORITY = {
|
|
212
|
+
error: 0,
|
|
213
|
+
warn: 1,
|
|
214
|
+
info: 2,
|
|
215
|
+
debug: 3
|
|
216
|
+
};
|
|
217
|
+
var hasWarnedAboutInvalidEnvValue = false;
|
|
218
|
+
var debugLogStateResolver = void 0;
|
|
219
|
+
function warnInvalidEnvValue(value) {
|
|
220
|
+
if (hasWarnedAboutInvalidEnvValue) {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
hasWarnedAboutInvalidEnvValue = true;
|
|
224
|
+
console.warn(
|
|
225
|
+
PREFIX,
|
|
226
|
+
`Invalid BRAINTRUST_DEBUG_LOG_LEVEL value "${value}". Expected "error", "warn", "info", or "debug".`
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
function normalizeDebugLogLevelOption(option) {
|
|
230
|
+
if (option === false) {
|
|
231
|
+
return void 0;
|
|
232
|
+
}
|
|
233
|
+
if (option === "error" || option === "warn" || option === "info" || option === "debug") {
|
|
234
|
+
return option;
|
|
235
|
+
}
|
|
236
|
+
throw new Error(
|
|
237
|
+
`Invalid debugLogLevel value "${option}". Expected false, "error", "warn", "info", or "debug".`
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
function parseDebugLogLevelEnv(value) {
|
|
241
|
+
if (!value) {
|
|
242
|
+
return void 0;
|
|
243
|
+
}
|
|
244
|
+
if (value === "error" || value === "warn" || value === "info" || value === "debug") {
|
|
245
|
+
return value;
|
|
246
|
+
}
|
|
247
|
+
warnInvalidEnvValue(value);
|
|
248
|
+
return void 0;
|
|
249
|
+
}
|
|
250
|
+
function getEnvDebugLogLevel() {
|
|
251
|
+
return parseDebugLogLevelEnv(isomorph_default.getEnv("BRAINTRUST_DEBUG_LOG_LEVEL"));
|
|
252
|
+
}
|
|
253
|
+
function setGlobalDebugLogLevel(level) {
|
|
254
|
+
globalThis[DEBUG_LOG_LEVEL_SYMBOL] = level;
|
|
255
|
+
}
|
|
256
|
+
function setDebugLogStateResolver(resolver) {
|
|
257
|
+
debugLogStateResolver = resolver;
|
|
258
|
+
}
|
|
259
|
+
function resolveDebugLogLevel(state) {
|
|
260
|
+
const stateLevel = state?.getDebugLogLevel?.();
|
|
261
|
+
const hasStateOverride = state?.hasDebugLogLevelOverride?.() ?? false;
|
|
262
|
+
if (hasStateOverride) {
|
|
263
|
+
return stateLevel;
|
|
264
|
+
}
|
|
265
|
+
const globalLevel = (
|
|
266
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
267
|
+
globalThis[DEBUG_LOG_LEVEL_SYMBOL]
|
|
268
|
+
);
|
|
269
|
+
if (globalLevel !== void 0) {
|
|
270
|
+
return globalLevel === false ? void 0 : globalLevel;
|
|
271
|
+
}
|
|
272
|
+
return getEnvDebugLogLevel();
|
|
273
|
+
}
|
|
274
|
+
function emit(method, state, args) {
|
|
275
|
+
const level = resolveDebugLogLevel(state);
|
|
276
|
+
if (!level || LOG_LEVEL_PRIORITY[method] > LOG_LEVEL_PRIORITY[level]) {
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
if (method === "info") {
|
|
280
|
+
console.log(PREFIX, ...args);
|
|
281
|
+
} else if (method === "debug") {
|
|
282
|
+
console.debug(PREFIX, ...args);
|
|
283
|
+
} else if (method === "warn") {
|
|
284
|
+
console.warn(PREFIX, ...args);
|
|
285
|
+
} else {
|
|
286
|
+
console.error(PREFIX, ...args);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
function createDebugLogger(state) {
|
|
290
|
+
const resolveState = () => state ?? debugLogStateResolver?.();
|
|
291
|
+
return {
|
|
292
|
+
info(...args) {
|
|
293
|
+
emit("info", resolveState(), args);
|
|
294
|
+
},
|
|
295
|
+
debug(...args) {
|
|
296
|
+
emit("debug", resolveState(), args);
|
|
297
|
+
},
|
|
298
|
+
warn(...args) {
|
|
299
|
+
emit("warn", resolveState(), args);
|
|
300
|
+
},
|
|
301
|
+
error(...args) {
|
|
302
|
+
emit("error", resolveState(), args);
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
var debugLogger = {
|
|
307
|
+
...createDebugLogger(),
|
|
308
|
+
forState(state) {
|
|
309
|
+
return createDebugLogger(state);
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
|
|
155
313
|
// src/queue.ts
|
|
156
314
|
var DEFAULT_QUEUE_SIZE = 15e3;
|
|
157
315
|
var Queue = class {
|
|
@@ -160,7 +318,7 @@ var Queue = class {
|
|
|
160
318
|
enforceSizeLimit = false;
|
|
161
319
|
constructor(maxSize) {
|
|
162
320
|
if (maxSize < 1) {
|
|
163
|
-
|
|
321
|
+
debugLogger.warn(
|
|
164
322
|
`maxSize ${maxSize} is <1, using default ${DEFAULT_QUEUE_SIZE}`
|
|
165
323
|
);
|
|
166
324
|
maxSize = DEFAULT_QUEUE_SIZE;
|
|
@@ -3500,34 +3658,6 @@ function devNullWritableStream() {
|
|
|
3500
3658
|
});
|
|
3501
3659
|
}
|
|
3502
3660
|
|
|
3503
|
-
// src/isomorph.ts
|
|
3504
|
-
var DefaultAsyncLocalStorage = class {
|
|
3505
|
-
constructor() {
|
|
3506
|
-
}
|
|
3507
|
-
enterWith(_) {
|
|
3508
|
-
}
|
|
3509
|
-
run(_, callback) {
|
|
3510
|
-
return callback();
|
|
3511
|
-
}
|
|
3512
|
-
getStore() {
|
|
3513
|
-
return void 0;
|
|
3514
|
-
}
|
|
3515
|
-
};
|
|
3516
|
-
var iso = {
|
|
3517
|
-
buildType: "unknown",
|
|
3518
|
-
// Will be set by configureBrowser() or configureNode()
|
|
3519
|
-
getRepoInfo: async (_settings) => void 0,
|
|
3520
|
-
getPastNAncestors: async () => [],
|
|
3521
|
-
getEnv: (_name) => void 0,
|
|
3522
|
-
getCallerLocation: () => void 0,
|
|
3523
|
-
newAsyncLocalStorage: () => new DefaultAsyncLocalStorage(),
|
|
3524
|
-
processOn: (_0, _1) => {
|
|
3525
|
-
},
|
|
3526
|
-
basename: (filepath) => filepath.split(/[\\/]/).pop() || filepath,
|
|
3527
|
-
writeln: (text) => console.log(text)
|
|
3528
|
-
};
|
|
3529
|
-
var isomorph_default = iso;
|
|
3530
|
-
|
|
3531
3661
|
// src/prompt-cache/disk-cache.ts
|
|
3532
3662
|
function canUseDiskCache() {
|
|
3533
3663
|
return !!(isomorph_default.hash && isomorph_default.gunzip && isomorph_default.gzip && isomorph_default.stat && isomorph_default.readFile && isomorph_default.writeFile && isomorph_default.utimes && isomorph_default.readdir && isomorph_default.mkdir && isomorph_default.unlink && isomorph_default.homedir);
|
|
@@ -4231,7 +4361,10 @@ var loginSchema = import_v38.z.strictObject({
|
|
|
4231
4361
|
proxyUrl: import_v38.z.string(),
|
|
4232
4362
|
loginToken: import_v38.z.string(),
|
|
4233
4363
|
orgId: import_v38.z.string().nullish(),
|
|
4234
|
-
gitMetadataSettings: GitMetadataSettings.nullish()
|
|
4364
|
+
gitMetadataSettings: GitMetadataSettings.nullish(),
|
|
4365
|
+
debugLogLevel: import_v38.z.enum(["error", "warn", "info", "debug"]).optional(),
|
|
4366
|
+
// Distinguishes explicit false from unset so env fallback stays disabled after deserialization.
|
|
4367
|
+
debugLogLevelDisabled: import_v38.z.boolean().optional()
|
|
4235
4368
|
});
|
|
4236
4369
|
var stateNonce = 0;
|
|
4237
4370
|
var BraintrustState = class _BraintrustState {
|
|
@@ -4252,6 +4385,16 @@ var BraintrustState = class _BraintrustState {
|
|
|
4252
4385
|
this._bgLogger = new SyncLazyValue(
|
|
4253
4386
|
() => new HTTPBackgroundLogger(new LazyValue(defaultGetLogConn), loginParams)
|
|
4254
4387
|
);
|
|
4388
|
+
if (loginParams.debugLogLevel !== void 0) {
|
|
4389
|
+
this.debugLogLevelConfigured = true;
|
|
4390
|
+
this.debugLogLevel = normalizeDebugLogLevelOption(
|
|
4391
|
+
loginParams.debugLogLevel
|
|
4392
|
+
);
|
|
4393
|
+
setGlobalDebugLogLevel(this.debugLogLevel ?? false);
|
|
4394
|
+
} else {
|
|
4395
|
+
this.debugLogLevel = getEnvDebugLogLevel();
|
|
4396
|
+
setGlobalDebugLogLevel(void 0);
|
|
4397
|
+
}
|
|
4255
4398
|
this.resetLoginInfo();
|
|
4256
4399
|
const memoryCache = new LRUCache({
|
|
4257
4400
|
max: Number(isomorph_default.getEnv("BRAINTRUST_PROMPT_CACHE_MEMORY_MAX")) ?? 1 << 10
|
|
@@ -4296,6 +4439,8 @@ var BraintrustState = class _BraintrustState {
|
|
|
4296
4439
|
proxyUrl = null;
|
|
4297
4440
|
loggedIn = false;
|
|
4298
4441
|
gitMetadataSettings;
|
|
4442
|
+
debugLogLevel;
|
|
4443
|
+
debugLogLevelConfigured = false;
|
|
4299
4444
|
fetch = globalThis.fetch;
|
|
4300
4445
|
_appConn = null;
|
|
4301
4446
|
_apiConn = null;
|
|
@@ -4361,6 +4506,11 @@ var BraintrustState = class _BraintrustState {
|
|
|
4361
4506
|
this.proxyUrl = other.proxyUrl;
|
|
4362
4507
|
this.loggedIn = other.loggedIn;
|
|
4363
4508
|
this.gitMetadataSettings = other.gitMetadataSettings;
|
|
4509
|
+
this.debugLogLevel = other.debugLogLevel;
|
|
4510
|
+
this.debugLogLevelConfigured = other.debugLogLevelConfigured;
|
|
4511
|
+
setGlobalDebugLogLevel(
|
|
4512
|
+
this.debugLogLevelConfigured ? this.debugLogLevel ?? false : void 0
|
|
4513
|
+
);
|
|
4364
4514
|
this._appConn = other._appConn;
|
|
4365
4515
|
this._apiConn = other._apiConn;
|
|
4366
4516
|
this.loginReplaceApiConn(this.apiConn());
|
|
@@ -4385,7 +4535,9 @@ var BraintrustState = class _BraintrustState {
|
|
|
4385
4535
|
orgName: this.orgName,
|
|
4386
4536
|
apiUrl: this.apiUrl,
|
|
4387
4537
|
proxyUrl: this.proxyUrl,
|
|
4388
|
-
gitMetadataSettings: this.gitMetadataSettings
|
|
4538
|
+
gitMetadataSettings: this.gitMetadataSettings,
|
|
4539
|
+
...this.debugLogLevel ? { debugLogLevel: this.debugLogLevel } : {},
|
|
4540
|
+
...this.debugLogLevelConfigured && !this.debugLogLevel ? { debugLogLevelDisabled: true } : {}
|
|
4389
4541
|
};
|
|
4390
4542
|
}
|
|
4391
4543
|
static deserialize(serialized, opts) {
|
|
@@ -4412,6 +4564,10 @@ var BraintrustState = class _BraintrustState {
|
|
|
4412
4564
|
state.proxyConn().set_token(state.loginToken);
|
|
4413
4565
|
}
|
|
4414
4566
|
state.loggedIn = true;
|
|
4567
|
+
state.debugLogLevelConfigured = "debugLogLevel" in serializedParsed.data || !!serializedParsed.data.debugLogLevelDisabled;
|
|
4568
|
+
setGlobalDebugLogLevel(
|
|
4569
|
+
state.debugLogLevelConfigured ? state.debugLogLevel ?? false : void 0
|
|
4570
|
+
);
|
|
4415
4571
|
state.loginReplaceApiConn(state.apiConn());
|
|
4416
4572
|
return state;
|
|
4417
4573
|
}
|
|
@@ -4424,7 +4580,22 @@ var BraintrustState = class _BraintrustState {
|
|
|
4424
4580
|
setMaskingFunction(maskingFunction) {
|
|
4425
4581
|
this.bgLogger().setMaskingFunction(maskingFunction);
|
|
4426
4582
|
}
|
|
4583
|
+
setDebugLogLevel(option) {
|
|
4584
|
+
if (option === void 0) {
|
|
4585
|
+
return;
|
|
4586
|
+
}
|
|
4587
|
+
this.debugLogLevelConfigured = true;
|
|
4588
|
+
this.debugLogLevel = normalizeDebugLogLevelOption(option);
|
|
4589
|
+
setGlobalDebugLogLevel(this.debugLogLevel ?? false);
|
|
4590
|
+
}
|
|
4591
|
+
getDebugLogLevel() {
|
|
4592
|
+
return this.debugLogLevel;
|
|
4593
|
+
}
|
|
4594
|
+
hasDebugLogLevelOverride() {
|
|
4595
|
+
return this.debugLogLevelConfigured;
|
|
4596
|
+
}
|
|
4427
4597
|
async login(loginParams) {
|
|
4598
|
+
this.setDebugLogLevel(loginParams.debugLogLevel);
|
|
4428
4599
|
if (this.apiUrl && !loginParams.forceLogin) {
|
|
4429
4600
|
return;
|
|
4430
4601
|
}
|
|
@@ -4522,6 +4693,7 @@ var BraintrustState = class _BraintrustState {
|
|
|
4522
4693
|
};
|
|
4523
4694
|
var _globalState;
|
|
4524
4695
|
var _internalGetGlobalState = () => _globalState;
|
|
4696
|
+
setDebugLogStateResolver(() => _internalGetGlobalState());
|
|
4525
4697
|
var FailedHTTPResponse = class extends Error {
|
|
4526
4698
|
status;
|
|
4527
4699
|
text;
|
|
@@ -4636,7 +4808,7 @@ var HTTPConnection = class _HTTPConnection {
|
|
|
4636
4808
|
return await resp.json();
|
|
4637
4809
|
} catch (e) {
|
|
4638
4810
|
if (i < tries - 1) {
|
|
4639
|
-
|
|
4811
|
+
debugLogger.debug(
|
|
4640
4812
|
`Retrying API request ${object_type} ${JSON.stringify(args)} ${e.status} ${e.text}`
|
|
4641
4813
|
);
|
|
4642
4814
|
continue;
|
|
@@ -4848,7 +5020,7 @@ with a Blob/ArrayBuffer, or run the program on Node.js.`
|
|
|
4848
5020
|
try {
|
|
4849
5021
|
statSync(data);
|
|
4850
5022
|
} catch (e) {
|
|
4851
|
-
|
|
5023
|
+
debugLogger.warn(`Failed to read file: ${e}`);
|
|
4852
5024
|
}
|
|
4853
5025
|
}
|
|
4854
5026
|
};
|
|
@@ -5560,7 +5732,7 @@ var HTTPBackgroundLogger = class _HTTPBackgroundLogger {
|
|
|
5560
5732
|
this.queueDropLoggingPeriod = queueDropLoggingPeriodEnv;
|
|
5561
5733
|
}
|
|
5562
5734
|
if (isomorph_default.getEnv("BRAINTRUST_LOG_FLUSH_CHUNK_SIZE")) {
|
|
5563
|
-
|
|
5735
|
+
debugLogger.warn(
|
|
5564
5736
|
"BRAINTRUST_LOG_FLUSH_CHUNK_SIZE is deprecated and no longer has any effect. Log flushing now sends all items at once and batches them automatically. This environment variable will be removed in a future major release."
|
|
5565
5737
|
);
|
|
5566
5738
|
}
|
|
@@ -5622,7 +5794,10 @@ var HTTPBackgroundLogger = class _HTTPBackgroundLogger {
|
|
|
5622
5794
|
const versionInfo = await conn.get_json("version");
|
|
5623
5795
|
serverLimit = import_v38.z.object({ logs3_payload_max_bytes: import_v38.z.number().nullish() }).parse(versionInfo).logs3_payload_max_bytes ?? null;
|
|
5624
5796
|
} catch (e) {
|
|
5625
|
-
|
|
5797
|
+
debugLogger.warn(
|
|
5798
|
+
"Failed to fetch version info for payload limit:",
|
|
5799
|
+
e
|
|
5800
|
+
);
|
|
5626
5801
|
}
|
|
5627
5802
|
const validServerLimit = serverLimit !== null && serverLimit > 0 ? serverLimit : null;
|
|
5628
5803
|
const canUseOverflow = validServerLimit !== null;
|
|
@@ -5766,16 +5941,16 @@ var HTTPBackgroundLogger = class _HTTPBackgroundLogger {
|
|
|
5766
5941
|
if (isRetrying) {
|
|
5767
5942
|
errmsg += ". Retrying";
|
|
5768
5943
|
}
|
|
5769
|
-
|
|
5944
|
+
debugLogger.warn(errmsg);
|
|
5770
5945
|
if (!isRetrying) {
|
|
5771
|
-
|
|
5946
|
+
debugLogger.warn(
|
|
5772
5947
|
`Failed to construct log records to flush after ${this.numTries} attempts. Dropping batch`
|
|
5773
5948
|
);
|
|
5774
5949
|
throw e;
|
|
5775
5950
|
} else {
|
|
5776
|
-
|
|
5951
|
+
debugLogger.warn(e);
|
|
5777
5952
|
const sleepTimeS = BACKGROUND_LOGGER_BASE_SLEEP_TIME_S * 2 ** i;
|
|
5778
|
-
|
|
5953
|
+
debugLogger.info(`Sleeping for ${sleepTimeS}s`);
|
|
5779
5954
|
await new Promise(
|
|
5780
5955
|
(resolve) => setTimeout(resolve, sleepTimeS * 1e3)
|
|
5781
5956
|
);
|
|
@@ -5876,15 +6051,15 @@ Error: ${errorText}`;
|
|
|
5876
6051
|
this.logFailedPayloadsDir();
|
|
5877
6052
|
}
|
|
5878
6053
|
if (!isRetrying) {
|
|
5879
|
-
|
|
6054
|
+
debugLogger.warn(
|
|
5880
6055
|
`log request failed after ${this.numTries} retries. Dropping batch`
|
|
5881
6056
|
);
|
|
5882
6057
|
throw new Error(errMsg);
|
|
5883
6058
|
} else {
|
|
5884
|
-
|
|
6059
|
+
debugLogger.warn(errMsg);
|
|
5885
6060
|
if (isRetrying) {
|
|
5886
6061
|
const sleepTimeS = BACKGROUND_LOGGER_BASE_SLEEP_TIME_S * 2 ** i;
|
|
5887
|
-
|
|
6062
|
+
debugLogger.info(`Sleeping for ${sleepTimeS}s`);
|
|
5888
6063
|
await new Promise(
|
|
5889
6064
|
(resolve) => setTimeout(resolve, sleepTimeS * 1e3)
|
|
5890
6065
|
);
|
|
@@ -5899,7 +6074,7 @@ Error: ${errorText}`;
|
|
|
5899
6074
|
this.queueDropLoggingState.numDropped += numItems;
|
|
5900
6075
|
const timeNow = getCurrentUnixTimestamp();
|
|
5901
6076
|
if (timeNow - this.queueDropLoggingState.lastLoggedTimestamp > this.queueDropLoggingPeriod) {
|
|
5902
|
-
|
|
6077
|
+
debugLogger.warn(
|
|
5903
6078
|
`Dropped ${this.queueDropLoggingState.numDropped} elements due to full queue`
|
|
5904
6079
|
);
|
|
5905
6080
|
if (this.failedPublishPayloadsDir) {
|
|
@@ -5931,7 +6106,7 @@ Error: ${errorText}`;
|
|
|
5931
6106
|
await _HTTPBackgroundLogger.writePayloadToDir({ payloadDir, payload });
|
|
5932
6107
|
}
|
|
5933
6108
|
} catch (e) {
|
|
5934
|
-
|
|
6109
|
+
debugLogger.error(e);
|
|
5935
6110
|
}
|
|
5936
6111
|
}
|
|
5937
6112
|
static async writePayloadToDir({
|
|
@@ -5939,7 +6114,7 @@ Error: ${errorText}`;
|
|
|
5939
6114
|
payload
|
|
5940
6115
|
}) {
|
|
5941
6116
|
if (!(isomorph_default.pathJoin && isomorph_default.mkdir && isomorph_default.writeFile)) {
|
|
5942
|
-
|
|
6117
|
+
debugLogger.warn(
|
|
5943
6118
|
"Cannot dump payloads: filesystem-operations not supported on this platform"
|
|
5944
6119
|
);
|
|
5945
6120
|
return;
|
|
@@ -5952,7 +6127,7 @@ Error: ${errorText}`;
|
|
|
5952
6127
|
await isomorph_default.mkdir(payloadDir, { recursive: true });
|
|
5953
6128
|
await isomorph_default.writeFile(payloadFile, payload);
|
|
5954
6129
|
} catch (e) {
|
|
5955
|
-
|
|
6130
|
+
debugLogger.error(
|
|
5956
6131
|
`Failed to write failed payload to output file ${payloadFile}:
|
|
5957
6132
|
`,
|
|
5958
6133
|
e
|
|
@@ -5983,7 +6158,9 @@ Error: ${errorText}`;
|
|
|
5983
6158
|
}
|
|
5984
6159
|
}
|
|
5985
6160
|
logFailedPayloadsDir() {
|
|
5986
|
-
|
|
6161
|
+
debugLogger.warn(
|
|
6162
|
+
`Logging failed payloads to ${this.failedPublishPayloadsDir}`
|
|
6163
|
+
);
|
|
5987
6164
|
}
|
|
5988
6165
|
// Should only be called by BraintrustState.
|
|
5989
6166
|
internalReplaceApiConn(apiConn) {
|
|
@@ -6394,7 +6571,14 @@ var ObjectFetcher = class {
|
|
|
6394
6571
|
async *fetchRecordsFromApi(batchSize) {
|
|
6395
6572
|
const state = await this.getState();
|
|
6396
6573
|
const objectId = await this.id;
|
|
6397
|
-
const
|
|
6574
|
+
const batchLimit = batchSize ?? DEFAULT_FETCH_BATCH_SIZE;
|
|
6575
|
+
const internalLimit = this._internal_btql?.limit;
|
|
6576
|
+
const limit = batchSize !== void 0 ? batchSize : internalLimit ?? batchLimit;
|
|
6577
|
+
const internalBtqlWithoutReservedQueryKeys = Object.fromEntries(
|
|
6578
|
+
Object.entries(this._internal_btql ?? {}).filter(
|
|
6579
|
+
([key]) => key !== "cursor" && key !== "limit" && key !== "select" && key !== "from"
|
|
6580
|
+
)
|
|
6581
|
+
);
|
|
6398
6582
|
let cursor = void 0;
|
|
6399
6583
|
let iterations = 0;
|
|
6400
6584
|
while (true) {
|
|
@@ -6402,7 +6586,6 @@ var ObjectFetcher = class {
|
|
|
6402
6586
|
`btql`,
|
|
6403
6587
|
{
|
|
6404
6588
|
query: {
|
|
6405
|
-
...this._internal_btql,
|
|
6406
6589
|
select: [
|
|
6407
6590
|
{
|
|
6408
6591
|
op: "star"
|
|
@@ -6422,7 +6605,8 @@ var ObjectFetcher = class {
|
|
|
6422
6605
|
]
|
|
6423
6606
|
},
|
|
6424
6607
|
cursor,
|
|
6425
|
-
limit
|
|
6608
|
+
limit,
|
|
6609
|
+
...internalBtqlWithoutReservedQueryKeys
|
|
6426
6610
|
},
|
|
6427
6611
|
use_columnstore: false,
|
|
6428
6612
|
brainstore_realtime: true,
|
|
@@ -6695,7 +6879,7 @@ var Experiment2 = class extends ObjectFetcher {
|
|
|
6695
6879
|
scores = results["scores"];
|
|
6696
6880
|
metrics = results["metrics"];
|
|
6697
6881
|
} catch (e) {
|
|
6698
|
-
|
|
6882
|
+
debugLogger.forState(state).warn(
|
|
6699
6883
|
`Failed to fetch experiment scores and metrics: ${e}
|
|
6700
6884
|
|
|
6701
6885
|
View complete results in Braintrust or run experiment.summarize() again.`
|
|
@@ -6772,7 +6956,7 @@ View complete results in Braintrust or run experiment.summarize() again.`
|
|
|
6772
6956
|
* @deprecated This function is deprecated. You can simply remove it from your code.
|
|
6773
6957
|
*/
|
|
6774
6958
|
async close() {
|
|
6775
|
-
|
|
6959
|
+
debugLogger.forState(this.state).warn(
|
|
6776
6960
|
"close is deprecated and will be removed in a future version of braintrust. It is now a no-op and can be removed"
|
|
6777
6961
|
);
|
|
6778
6962
|
return this.id;
|
|
@@ -6929,8 +7113,8 @@ var SpanImpl = class _SpanImpl {
|
|
|
6929
7113
|
...serializableInternalData,
|
|
6930
7114
|
[IS_MERGE_FIELD]: this.isMerge
|
|
6931
7115
|
});
|
|
6932
|
-
if (partialRecord.metrics?.end) {
|
|
6933
|
-
this.loggedEndTime = partialRecord.metrics
|
|
7116
|
+
if (typeof partialRecord.metrics?.end === "number") {
|
|
7117
|
+
this.loggedEndTime = partialRecord.metrics.end;
|
|
6934
7118
|
}
|
|
6935
7119
|
if (this.parentObjectType === 1 /* EXPERIMENT */) {
|
|
6936
7120
|
const cachedSpan = {
|
|
@@ -7165,7 +7349,7 @@ var Dataset2 = class extends ObjectFetcher {
|
|
|
7165
7349
|
constructor(state, lazyMetadata, pinnedVersion, legacy, _internal_btql) {
|
|
7166
7350
|
const isLegacyDataset = legacy ?? DEFAULT_IS_LEGACY_DATASET;
|
|
7167
7351
|
if (isLegacyDataset) {
|
|
7168
|
-
|
|
7352
|
+
debugLogger.forState(state).warn(
|
|
7169
7353
|
`Records will be fetched from this dataset in the legacy format, with the "expected" field renamed to "output". Please update your code to use "expected", and use \`braintrust.initDataset()\` with \`{ useOutput: false }\`, which will become the default in a future version of Braintrust.`
|
|
7170
7354
|
);
|
|
7171
7355
|
}
|
|
@@ -7396,7 +7580,7 @@ var Dataset2 = class extends ObjectFetcher {
|
|
|
7396
7580
|
* @deprecated This function is deprecated. You can simply remove it from your code.
|
|
7397
7581
|
*/
|
|
7398
7582
|
async close() {
|
|
7399
|
-
|
|
7583
|
+
debugLogger.forState(this.state).warn(
|
|
7400
7584
|
"close is deprecated and will be removed in a future version of braintrust. It is now a no-op and can be removed"
|
|
7401
7585
|
);
|
|
7402
7586
|
return this.id;
|
|
@@ -7407,6 +7591,49 @@ var Dataset2 = class extends ObjectFetcher {
|
|
|
7407
7591
|
};
|
|
7408
7592
|
var TEST_API_KEY = "___TEST_API_KEY__THIS_IS_NOT_REAL___";
|
|
7409
7593
|
|
|
7594
|
+
// src/instrumentation/core/channel-tracing-utils.ts
|
|
7595
|
+
function hasChannelSpanInfo(value) {
|
|
7596
|
+
return isObject(value) && isObject(value.span_info);
|
|
7597
|
+
}
|
|
7598
|
+
function getChannelSpanInfo(event) {
|
|
7599
|
+
if (isObject(event.span_info)) {
|
|
7600
|
+
return event.span_info;
|
|
7601
|
+
}
|
|
7602
|
+
const firstArg = event.arguments?.[0];
|
|
7603
|
+
if (hasChannelSpanInfo(firstArg)) {
|
|
7604
|
+
return firstArg.span_info;
|
|
7605
|
+
}
|
|
7606
|
+
return void 0;
|
|
7607
|
+
}
|
|
7608
|
+
function buildStartSpanArgs(config, event) {
|
|
7609
|
+
const spanInfo = getChannelSpanInfo(event);
|
|
7610
|
+
const spanAttributes = {
|
|
7611
|
+
type: config.type
|
|
7612
|
+
};
|
|
7613
|
+
if (isObject(spanInfo?.spanAttributes)) {
|
|
7614
|
+
mergeDicts(spanAttributes, spanInfo.spanAttributes);
|
|
7615
|
+
}
|
|
7616
|
+
return {
|
|
7617
|
+
name: typeof spanInfo?.name === "string" && spanInfo.name ? spanInfo.name : config.name,
|
|
7618
|
+
spanAttributes,
|
|
7619
|
+
spanInfoMetadata: isObject(spanInfo?.metadata) ? spanInfo.metadata : void 0
|
|
7620
|
+
};
|
|
7621
|
+
}
|
|
7622
|
+
function mergeInputMetadata(metadata, spanInfoMetadata) {
|
|
7623
|
+
if (!spanInfoMetadata) {
|
|
7624
|
+
return isObject(metadata) ? (
|
|
7625
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
7626
|
+
metadata
|
|
7627
|
+
) : void 0;
|
|
7628
|
+
}
|
|
7629
|
+
const mergedMetadata = {};
|
|
7630
|
+
mergeDicts(mergedMetadata, spanInfoMetadata);
|
|
7631
|
+
if (isObject(metadata)) {
|
|
7632
|
+
mergeDicts(mergedMetadata, metadata);
|
|
7633
|
+
}
|
|
7634
|
+
return mergedMetadata;
|
|
7635
|
+
}
|
|
7636
|
+
|
|
7410
7637
|
// src/instrumentation/core/plugin.ts
|
|
7411
7638
|
var BasePlugin = class {
|
|
7412
7639
|
enabled = false;
|
|
@@ -7438,23 +7665,25 @@ var BasePlugin = class {
|
|
|
7438
7665
|
* @param handlers - Event handlers
|
|
7439
7666
|
*/
|
|
7440
7667
|
subscribe(channelName, handlers) {
|
|
7441
|
-
const
|
|
7442
|
-
|
|
7668
|
+
const channel2 = isomorph_default.newTracingChannel(channelName);
|
|
7669
|
+
channel2.subscribe(handlers);
|
|
7443
7670
|
}
|
|
7444
7671
|
/**
|
|
7445
7672
|
* Subscribe to a channel for async methods (non-streaming).
|
|
7446
7673
|
* Creates a span and logs input/output/metrics.
|
|
7447
7674
|
*/
|
|
7448
7675
|
subscribeToChannel(channelName, config) {
|
|
7449
|
-
const
|
|
7676
|
+
const channel2 = isomorph_default.newTracingChannel(channelName);
|
|
7450
7677
|
const spans = /* @__PURE__ */ new WeakMap();
|
|
7451
7678
|
const handlers = {
|
|
7452
7679
|
start: (event) => {
|
|
7680
|
+
const { name, spanAttributes, spanInfoMetadata } = buildStartSpanArgs(
|
|
7681
|
+
config,
|
|
7682
|
+
event
|
|
7683
|
+
);
|
|
7453
7684
|
const span = startSpan({
|
|
7454
|
-
name
|
|
7455
|
-
spanAttributes
|
|
7456
|
-
type: config.type
|
|
7457
|
-
}
|
|
7685
|
+
name,
|
|
7686
|
+
spanAttributes
|
|
7458
7687
|
});
|
|
7459
7688
|
const startTime = getCurrentUnixTimestamp();
|
|
7460
7689
|
spans.set(event, { span, startTime });
|
|
@@ -7462,7 +7691,7 @@ var BasePlugin = class {
|
|
|
7462
7691
|
const { input, metadata } = config.extractInput(event.arguments);
|
|
7463
7692
|
span.log({
|
|
7464
7693
|
input,
|
|
7465
|
-
metadata
|
|
7694
|
+
metadata: mergeInputMetadata(metadata, spanInfoMetadata)
|
|
7466
7695
|
});
|
|
7467
7696
|
} catch (error) {
|
|
7468
7697
|
console.error(`Error extracting input for ${channelName}:`, error);
|
|
@@ -7475,10 +7704,12 @@ var BasePlugin = class {
|
|
|
7475
7704
|
}
|
|
7476
7705
|
const { span, startTime } = spanData;
|
|
7477
7706
|
try {
|
|
7478
|
-
const output = config.extractOutput(event.result);
|
|
7479
|
-
const metrics = config.extractMetrics(event.result, startTime);
|
|
7707
|
+
const output = config.extractOutput(event.result, event);
|
|
7708
|
+
const metrics = config.extractMetrics(event.result, startTime, event);
|
|
7709
|
+
const metadata = config.extractMetadata?.(event.result, event);
|
|
7480
7710
|
span.log({
|
|
7481
7711
|
output,
|
|
7712
|
+
...metadata !== void 0 ? { metadata } : {},
|
|
7482
7713
|
metrics
|
|
7483
7714
|
});
|
|
7484
7715
|
} catch (error) {
|
|
@@ -7501,9 +7732,9 @@ var BasePlugin = class {
|
|
|
7501
7732
|
spans.delete(event);
|
|
7502
7733
|
}
|
|
7503
7734
|
};
|
|
7504
|
-
|
|
7735
|
+
channel2.subscribe(handlers);
|
|
7505
7736
|
this.unsubscribers.push(() => {
|
|
7506
|
-
|
|
7737
|
+
channel2.unsubscribe(handlers);
|
|
7507
7738
|
});
|
|
7508
7739
|
}
|
|
7509
7740
|
/**
|
|
@@ -7511,15 +7742,17 @@ var BasePlugin = class {
|
|
|
7511
7742
|
* Handles both streaming and non-streaming responses.
|
|
7512
7743
|
*/
|
|
7513
7744
|
subscribeToStreamingChannel(channelName, config) {
|
|
7514
|
-
const
|
|
7745
|
+
const channel2 = isomorph_default.newTracingChannel(channelName);
|
|
7515
7746
|
const spans = /* @__PURE__ */ new WeakMap();
|
|
7516
7747
|
const handlers = {
|
|
7517
7748
|
start: (event) => {
|
|
7749
|
+
const { name, spanAttributes, spanInfoMetadata } = buildStartSpanArgs(
|
|
7750
|
+
config,
|
|
7751
|
+
event
|
|
7752
|
+
);
|
|
7518
7753
|
const span = startSpan({
|
|
7519
|
-
name
|
|
7520
|
-
spanAttributes
|
|
7521
|
-
type: config.type
|
|
7522
|
-
}
|
|
7754
|
+
name,
|
|
7755
|
+
spanAttributes
|
|
7523
7756
|
});
|
|
7524
7757
|
const startTime = getCurrentUnixTimestamp();
|
|
7525
7758
|
spans.set(event, { span, startTime });
|
|
@@ -7527,7 +7760,7 @@ var BasePlugin = class {
|
|
|
7527
7760
|
const { input, metadata } = config.extractInput(event.arguments);
|
|
7528
7761
|
span.log({
|
|
7529
7762
|
input,
|
|
7530
|
-
metadata
|
|
7763
|
+
metadata: mergeInputMetadata(metadata, spanInfoMetadata)
|
|
7531
7764
|
});
|
|
7532
7765
|
} catch (error) {
|
|
7533
7766
|
console.error(`Error extracting input for ${channelName}:`, error);
|
|
@@ -7540,24 +7773,39 @@ var BasePlugin = class {
|
|
|
7540
7773
|
}
|
|
7541
7774
|
const { span, startTime } = spanData;
|
|
7542
7775
|
if (isAsyncIterable(event.result)) {
|
|
7776
|
+
let firstChunkTime;
|
|
7543
7777
|
patchStreamIfNeeded(event.result, {
|
|
7778
|
+
onChunk: () => {
|
|
7779
|
+
if (firstChunkTime === void 0) {
|
|
7780
|
+
firstChunkTime = getCurrentUnixTimestamp();
|
|
7781
|
+
}
|
|
7782
|
+
},
|
|
7544
7783
|
onComplete: (chunks) => {
|
|
7545
7784
|
try {
|
|
7546
7785
|
let output;
|
|
7547
7786
|
let metrics;
|
|
7787
|
+
let metadata;
|
|
7548
7788
|
if (config.aggregateChunks) {
|
|
7549
|
-
const aggregated = config.aggregateChunks(
|
|
7789
|
+
const aggregated = config.aggregateChunks(
|
|
7790
|
+
chunks,
|
|
7791
|
+
event.result,
|
|
7792
|
+
event
|
|
7793
|
+
);
|
|
7550
7794
|
output = aggregated.output;
|
|
7551
7795
|
metrics = aggregated.metrics;
|
|
7796
|
+
metadata = aggregated.metadata;
|
|
7552
7797
|
} else {
|
|
7553
|
-
output = config.extractOutput(chunks);
|
|
7554
|
-
metrics = config.extractMetrics(chunks, startTime);
|
|
7798
|
+
output = config.extractOutput(chunks, event);
|
|
7799
|
+
metrics = config.extractMetrics(chunks, startTime, event);
|
|
7555
7800
|
}
|
|
7556
|
-
if (
|
|
7801
|
+
if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
|
|
7802
|
+
metrics.time_to_first_token = firstChunkTime - startTime;
|
|
7803
|
+
} else if (metrics.time_to_first_token === void 0 && chunks.length > 0) {
|
|
7557
7804
|
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
7558
7805
|
}
|
|
7559
7806
|
span.log({
|
|
7560
7807
|
output,
|
|
7808
|
+
...metadata !== void 0 ? { metadata } : {},
|
|
7561
7809
|
metrics
|
|
7562
7810
|
});
|
|
7563
7811
|
} catch (error) {
|
|
@@ -7578,10 +7826,16 @@ var BasePlugin = class {
|
|
|
7578
7826
|
});
|
|
7579
7827
|
} else {
|
|
7580
7828
|
try {
|
|
7581
|
-
const output = config.extractOutput(event.result);
|
|
7582
|
-
const
|
|
7829
|
+
const output = config.extractOutput(event.result, event);
|
|
7830
|
+
const metadata = config.extractMetadata ? config.extractMetadata(event.result, event) : void 0;
|
|
7831
|
+
const metrics = config.extractMetrics(
|
|
7832
|
+
event.result,
|
|
7833
|
+
startTime,
|
|
7834
|
+
event
|
|
7835
|
+
);
|
|
7583
7836
|
span.log({
|
|
7584
7837
|
output,
|
|
7838
|
+
...metadata !== void 0 ? { metadata } : {},
|
|
7585
7839
|
metrics
|
|
7586
7840
|
});
|
|
7587
7841
|
} catch (error) {
|
|
@@ -7605,9 +7859,9 @@ var BasePlugin = class {
|
|
|
7605
7859
|
spans.delete(event);
|
|
7606
7860
|
}
|
|
7607
7861
|
};
|
|
7608
|
-
|
|
7862
|
+
channel2.subscribe(handlers);
|
|
7609
7863
|
this.unsubscribers.push(() => {
|
|
7610
|
-
|
|
7864
|
+
channel2.unsubscribe(handlers);
|
|
7611
7865
|
});
|
|
7612
7866
|
}
|
|
7613
7867
|
/**
|
|
@@ -7615,15 +7869,17 @@ var BasePlugin = class {
|
|
|
7615
7869
|
* Used for methods like beta.chat.completions.stream() and responses.stream().
|
|
7616
7870
|
*/
|
|
7617
7871
|
subscribeToSyncStreamChannel(channelName, config) {
|
|
7618
|
-
const
|
|
7872
|
+
const channel2 = isomorph_default.newTracingChannel(channelName);
|
|
7619
7873
|
const spans = /* @__PURE__ */ new WeakMap();
|
|
7620
7874
|
const handlers = {
|
|
7621
7875
|
start: (event) => {
|
|
7876
|
+
const { name, spanAttributes, spanInfoMetadata } = buildStartSpanArgs(
|
|
7877
|
+
config,
|
|
7878
|
+
event
|
|
7879
|
+
);
|
|
7622
7880
|
const span = startSpan({
|
|
7623
|
-
name
|
|
7624
|
-
spanAttributes
|
|
7625
|
-
type: config.type
|
|
7626
|
-
}
|
|
7881
|
+
name,
|
|
7882
|
+
spanAttributes
|
|
7627
7883
|
});
|
|
7628
7884
|
const startTime = getCurrentUnixTimestamp();
|
|
7629
7885
|
spans.set(event, { span, startTime });
|
|
@@ -7631,7 +7887,7 @@ var BasePlugin = class {
|
|
|
7631
7887
|
const { input, metadata } = config.extractInput(event.arguments);
|
|
7632
7888
|
span.log({
|
|
7633
7889
|
input,
|
|
7634
|
-
metadata
|
|
7890
|
+
metadata: mergeInputMetadata(metadata, spanInfoMetadata)
|
|
7635
7891
|
});
|
|
7636
7892
|
} catch (error) {
|
|
7637
7893
|
console.error(`Error extracting input for ${channelName}:`, error);
|
|
@@ -7715,9 +7971,9 @@ var BasePlugin = class {
|
|
|
7715
7971
|
spans.delete(event);
|
|
7716
7972
|
}
|
|
7717
7973
|
};
|
|
7718
|
-
|
|
7974
|
+
channel2.subscribe(handlers);
|
|
7719
7975
|
this.unsubscribers.push(() => {
|
|
7720
|
-
|
|
7976
|
+
channel2.unsubscribe(handlers);
|
|
7721
7977
|
});
|
|
7722
7978
|
}
|
|
7723
7979
|
};
|
|
@@ -7740,149 +7996,635 @@ function isValidChannelName(channelName) {
|
|
|
7740
7996
|
return /^braintrust:[^:]+:.+$/.test(channelName);
|
|
7741
7997
|
}
|
|
7742
7998
|
|
|
7743
|
-
// src/
|
|
7744
|
-
function
|
|
7745
|
-
|
|
7746
|
-
"image/png": "png",
|
|
7747
|
-
"image/jpeg": "jpg",
|
|
7748
|
-
"image/gif": "gif",
|
|
7749
|
-
"image/webp": "webp",
|
|
7750
|
-
"image/svg+xml": "svg",
|
|
7751
|
-
"audio/mpeg": "mp3",
|
|
7752
|
-
"audio/wav": "wav",
|
|
7753
|
-
"audio/ogg": "ogg",
|
|
7754
|
-
"video/mp4": "mp4",
|
|
7755
|
-
"video/webm": "webm",
|
|
7756
|
-
"application/pdf": "pdf",
|
|
7757
|
-
"application/json": "json",
|
|
7758
|
-
"text/plain": "txt",
|
|
7759
|
-
"text/html": "html",
|
|
7760
|
-
"text/csv": "csv"
|
|
7761
|
-
};
|
|
7762
|
-
return extensionMap[mediaType] || "bin";
|
|
7999
|
+
// src/instrumentation/core/channel-tracing.ts
|
|
8000
|
+
function isSyncStreamLike(value) {
|
|
8001
|
+
return !!value && typeof value === "object" && typeof value.on === "function";
|
|
7763
8002
|
}
|
|
7764
|
-
function
|
|
8003
|
+
function hasChoices(value) {
|
|
8004
|
+
return !!value && typeof value === "object" && "choices" in value;
|
|
8005
|
+
}
|
|
8006
|
+
function normalizeMetadata(metadata) {
|
|
8007
|
+
return isObject(metadata) ? metadata : void 0;
|
|
8008
|
+
}
|
|
8009
|
+
function startSpanForEvent(config, event, channelName) {
|
|
8010
|
+
const { name, spanAttributes, spanInfoMetadata } = buildStartSpanArgs(
|
|
8011
|
+
config,
|
|
8012
|
+
event
|
|
8013
|
+
);
|
|
8014
|
+
const span = startSpan({
|
|
8015
|
+
name,
|
|
8016
|
+
spanAttributes
|
|
8017
|
+
});
|
|
8018
|
+
const startTime = getCurrentUnixTimestamp();
|
|
7765
8019
|
try {
|
|
7766
|
-
|
|
7767
|
-
|
|
7768
|
-
|
|
7769
|
-
|
|
7770
|
-
|
|
7771
|
-
|
|
7772
|
-
|
|
7773
|
-
for (let i = 0; i < binaryString.length; i++) {
|
|
7774
|
-
bytes[i] = binaryString.charCodeAt(i);
|
|
7775
|
-
}
|
|
7776
|
-
return new Blob([bytes], { type: mediaType });
|
|
7777
|
-
}
|
|
7778
|
-
} else if (data.startsWith("http://") || data.startsWith("https://")) {
|
|
7779
|
-
return null;
|
|
7780
|
-
} else {
|
|
7781
|
-
const binaryString = atob(data);
|
|
7782
|
-
const bytes = new Uint8Array(binaryString.length);
|
|
7783
|
-
for (let i = 0; i < binaryString.length; i++) {
|
|
7784
|
-
bytes[i] = binaryString.charCodeAt(i);
|
|
7785
|
-
}
|
|
7786
|
-
return new Blob([bytes], { type: mediaType });
|
|
7787
|
-
}
|
|
7788
|
-
} else if (data instanceof Uint8Array) {
|
|
7789
|
-
return new Blob([data], { type: mediaType });
|
|
7790
|
-
} else if (data instanceof ArrayBuffer) {
|
|
7791
|
-
return new Blob([data], { type: mediaType });
|
|
7792
|
-
} else if (typeof Buffer !== "undefined" && data instanceof Buffer) {
|
|
7793
|
-
return new Blob([data], { type: mediaType });
|
|
7794
|
-
}
|
|
7795
|
-
} catch {
|
|
7796
|
-
return null;
|
|
8020
|
+
const { input, metadata } = config.extractInput(event.arguments);
|
|
8021
|
+
span.log({
|
|
8022
|
+
input,
|
|
8023
|
+
metadata: mergeInputMetadata(metadata, spanInfoMetadata)
|
|
8024
|
+
});
|
|
8025
|
+
} catch (error) {
|
|
8026
|
+
console.error(`Error extracting input for ${channelName}:`, error);
|
|
7797
8027
|
}
|
|
7798
|
-
return
|
|
8028
|
+
return { span, startTime };
|
|
7799
8029
|
}
|
|
7800
|
-
function
|
|
7801
|
-
|
|
7802
|
-
|
|
8030
|
+
function logErrorAndEnd(states, event) {
|
|
8031
|
+
const spanData = states.get(event);
|
|
8032
|
+
if (!spanData) {
|
|
8033
|
+
return;
|
|
7803
8034
|
}
|
|
7804
|
-
|
|
7805
|
-
|
|
7806
|
-
|
|
7807
|
-
|
|
7808
|
-
|
|
7809
|
-
|
|
7810
|
-
|
|
7811
|
-
|
|
7812
|
-
|
|
7813
|
-
|
|
7814
|
-
|
|
7815
|
-
|
|
7816
|
-
|
|
7817
|
-
|
|
7818
|
-
|
|
7819
|
-
|
|
7820
|
-
|
|
7821
|
-
|
|
7822
|
-
|
|
7823
|
-
|
|
7824
|
-
|
|
7825
|
-
|
|
7826
|
-
|
|
7827
|
-
|
|
7828
|
-
return
|
|
7829
|
-
...part,
|
|
7830
|
-
image: attachment
|
|
7831
|
-
};
|
|
8035
|
+
spanData.span.log({
|
|
8036
|
+
error: event.error.message
|
|
8037
|
+
});
|
|
8038
|
+
spanData.span.end();
|
|
8039
|
+
states.delete(event);
|
|
8040
|
+
}
|
|
8041
|
+
function traceAsyncChannel(channel2, config) {
|
|
8042
|
+
const tracingChannel = channel2.tracingChannel();
|
|
8043
|
+
const states = /* @__PURE__ */ new WeakMap();
|
|
8044
|
+
const channelName = channel2.channelName;
|
|
8045
|
+
const handlers = {
|
|
8046
|
+
start: (event) => {
|
|
8047
|
+
states.set(
|
|
8048
|
+
event,
|
|
8049
|
+
startSpanForEvent(
|
|
8050
|
+
config,
|
|
8051
|
+
event,
|
|
8052
|
+
channelName
|
|
8053
|
+
)
|
|
8054
|
+
);
|
|
8055
|
+
},
|
|
8056
|
+
asyncEnd: (event) => {
|
|
8057
|
+
const spanData = states.get(event);
|
|
8058
|
+
if (!spanData) {
|
|
8059
|
+
return;
|
|
7832
8060
|
}
|
|
7833
|
-
|
|
7834
|
-
|
|
7835
|
-
|
|
7836
|
-
|
|
7837
|
-
|
|
7838
|
-
|
|
7839
|
-
|
|
7840
|
-
const
|
|
7841
|
-
|
|
7842
|
-
|
|
7843
|
-
|
|
8061
|
+
const asyncEndEvent = event;
|
|
8062
|
+
const { span, startTime } = spanData;
|
|
8063
|
+
try {
|
|
8064
|
+
const output = config.extractOutput(
|
|
8065
|
+
asyncEndEvent.result,
|
|
8066
|
+
asyncEndEvent
|
|
8067
|
+
);
|
|
8068
|
+
const metrics = config.extractMetrics(
|
|
8069
|
+
asyncEndEvent.result,
|
|
8070
|
+
startTime,
|
|
8071
|
+
asyncEndEvent
|
|
8072
|
+
);
|
|
8073
|
+
const metadata = config.extractMetadata?.(
|
|
8074
|
+
asyncEndEvent.result,
|
|
8075
|
+
asyncEndEvent
|
|
8076
|
+
);
|
|
8077
|
+
span.log({
|
|
8078
|
+
output,
|
|
8079
|
+
...normalizeMetadata(metadata) !== void 0 ? { metadata: normalizeMetadata(metadata) } : {},
|
|
8080
|
+
metrics
|
|
7844
8081
|
});
|
|
7845
|
-
|
|
7846
|
-
|
|
7847
|
-
|
|
7848
|
-
|
|
8082
|
+
} catch (error) {
|
|
8083
|
+
console.error(`Error extracting output for ${channelName}:`, error);
|
|
8084
|
+
} finally {
|
|
8085
|
+
span.end();
|
|
8086
|
+
states.delete(event);
|
|
7849
8087
|
}
|
|
8088
|
+
},
|
|
8089
|
+
error: (event) => {
|
|
8090
|
+
logErrorAndEnd(states, event);
|
|
7850
8091
|
}
|
|
7851
|
-
return part;
|
|
7852
8092
|
};
|
|
7853
|
-
|
|
7854
|
-
|
|
7855
|
-
|
|
7856
|
-
}
|
|
7857
|
-
if (Array.isArray(message.content)) {
|
|
7858
|
-
return {
|
|
7859
|
-
...message,
|
|
7860
|
-
content: message.content.map(processContentPart)
|
|
7861
|
-
};
|
|
7862
|
-
}
|
|
7863
|
-
return message;
|
|
8093
|
+
tracingChannel.subscribe(handlers);
|
|
8094
|
+
return () => {
|
|
8095
|
+
tracingChannel.unsubscribe(handlers);
|
|
7864
8096
|
};
|
|
7865
|
-
if (Array.isArray(input)) {
|
|
7866
|
-
return input.map(processMessage);
|
|
7867
|
-
} else if (typeof input === "object" && input.content) {
|
|
7868
|
-
return processMessage(input);
|
|
7869
|
-
}
|
|
7870
|
-
return input;
|
|
7871
8097
|
}
|
|
7872
|
-
|
|
7873
|
-
|
|
7874
|
-
|
|
7875
|
-
|
|
8098
|
+
function traceStreamingChannel(channel2, config) {
|
|
8099
|
+
const tracingChannel = channel2.tracingChannel();
|
|
8100
|
+
const states = /* @__PURE__ */ new WeakMap();
|
|
8101
|
+
const channelName = channel2.channelName;
|
|
8102
|
+
const handlers = {
|
|
8103
|
+
start: (event) => {
|
|
8104
|
+
states.set(
|
|
8105
|
+
event,
|
|
8106
|
+
startSpanForEvent(
|
|
8107
|
+
config,
|
|
8108
|
+
event,
|
|
8109
|
+
channelName
|
|
8110
|
+
)
|
|
8111
|
+
);
|
|
8112
|
+
},
|
|
8113
|
+
asyncEnd: (event) => {
|
|
8114
|
+
const spanData = states.get(event);
|
|
8115
|
+
if (!spanData) {
|
|
8116
|
+
return;
|
|
8117
|
+
}
|
|
8118
|
+
const asyncEndEvent = event;
|
|
8119
|
+
const { span, startTime } = spanData;
|
|
8120
|
+
if (isAsyncIterable(asyncEndEvent.result)) {
|
|
8121
|
+
let firstChunkTime;
|
|
8122
|
+
patchStreamIfNeeded(asyncEndEvent.result, {
|
|
8123
|
+
onChunk: () => {
|
|
8124
|
+
if (firstChunkTime === void 0) {
|
|
8125
|
+
firstChunkTime = getCurrentUnixTimestamp();
|
|
8126
|
+
}
|
|
8127
|
+
},
|
|
8128
|
+
onComplete: (chunks) => {
|
|
8129
|
+
try {
|
|
8130
|
+
let output;
|
|
8131
|
+
let metrics;
|
|
8132
|
+
let metadata;
|
|
8133
|
+
if (config.aggregateChunks) {
|
|
8134
|
+
const aggregated = config.aggregateChunks(
|
|
8135
|
+
chunks,
|
|
8136
|
+
asyncEndEvent.result,
|
|
8137
|
+
asyncEndEvent,
|
|
8138
|
+
startTime
|
|
8139
|
+
);
|
|
8140
|
+
output = aggregated.output;
|
|
8141
|
+
metrics = aggregated.metrics;
|
|
8142
|
+
metadata = aggregated.metadata;
|
|
8143
|
+
} else {
|
|
8144
|
+
output = config.extractOutput(
|
|
8145
|
+
chunks,
|
|
8146
|
+
asyncEndEvent
|
|
8147
|
+
);
|
|
8148
|
+
metrics = config.extractMetrics(
|
|
8149
|
+
chunks,
|
|
8150
|
+
startTime,
|
|
8151
|
+
asyncEndEvent
|
|
8152
|
+
);
|
|
8153
|
+
}
|
|
8154
|
+
if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
|
|
8155
|
+
metrics.time_to_first_token = firstChunkTime - startTime;
|
|
8156
|
+
} else if (metrics.time_to_first_token === void 0 && chunks.length > 0) {
|
|
8157
|
+
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
8158
|
+
}
|
|
8159
|
+
span.log({
|
|
8160
|
+
output,
|
|
8161
|
+
...metadata !== void 0 ? { metadata } : {},
|
|
8162
|
+
metrics
|
|
8163
|
+
});
|
|
8164
|
+
} catch (error) {
|
|
8165
|
+
console.error(
|
|
8166
|
+
`Error extracting output for ${channelName}:`,
|
|
8167
|
+
error
|
|
8168
|
+
);
|
|
8169
|
+
} finally {
|
|
8170
|
+
span.end();
|
|
8171
|
+
states.delete(event);
|
|
8172
|
+
}
|
|
8173
|
+
},
|
|
8174
|
+
onError: (error) => {
|
|
8175
|
+
span.log({
|
|
8176
|
+
error: error.message
|
|
8177
|
+
});
|
|
8178
|
+
span.end();
|
|
8179
|
+
states.delete(event);
|
|
8180
|
+
}
|
|
8181
|
+
});
|
|
8182
|
+
return;
|
|
8183
|
+
}
|
|
8184
|
+
try {
|
|
8185
|
+
const output = config.extractOutput(
|
|
8186
|
+
asyncEndEvent.result,
|
|
8187
|
+
asyncEndEvent
|
|
8188
|
+
);
|
|
8189
|
+
const metrics = config.extractMetrics(
|
|
8190
|
+
asyncEndEvent.result,
|
|
8191
|
+
startTime,
|
|
8192
|
+
asyncEndEvent
|
|
8193
|
+
);
|
|
8194
|
+
const metadata = config.extractMetadata?.(
|
|
8195
|
+
asyncEndEvent.result,
|
|
8196
|
+
asyncEndEvent
|
|
8197
|
+
);
|
|
8198
|
+
span.log({
|
|
8199
|
+
output,
|
|
8200
|
+
...normalizeMetadata(metadata) !== void 0 ? { metadata: normalizeMetadata(metadata) } : {},
|
|
8201
|
+
metrics
|
|
8202
|
+
});
|
|
8203
|
+
} catch (error) {
|
|
8204
|
+
console.error(`Error extracting output for ${channelName}:`, error);
|
|
8205
|
+
} finally {
|
|
8206
|
+
span.end();
|
|
8207
|
+
states.delete(event);
|
|
8208
|
+
}
|
|
8209
|
+
},
|
|
8210
|
+
error: (event) => {
|
|
8211
|
+
logErrorAndEnd(states, event);
|
|
8212
|
+
}
|
|
8213
|
+
};
|
|
8214
|
+
tracingChannel.subscribe(handlers);
|
|
8215
|
+
return () => {
|
|
8216
|
+
tracingChannel.unsubscribe(handlers);
|
|
8217
|
+
};
|
|
8218
|
+
}
|
|
8219
|
+
function traceSyncStreamChannel(channel2, config) {
|
|
8220
|
+
const tracingChannel = channel2.tracingChannel();
|
|
8221
|
+
const states = /* @__PURE__ */ new WeakMap();
|
|
8222
|
+
const channelName = channel2.channelName;
|
|
8223
|
+
const handlers = {
|
|
8224
|
+
start: (event) => {
|
|
8225
|
+
states.set(
|
|
8226
|
+
event,
|
|
8227
|
+
startSpanForEvent(
|
|
8228
|
+
config,
|
|
8229
|
+
event,
|
|
8230
|
+
channelName
|
|
8231
|
+
)
|
|
8232
|
+
);
|
|
8233
|
+
},
|
|
8234
|
+
end: (event) => {
|
|
8235
|
+
const spanData = states.get(event);
|
|
8236
|
+
if (!spanData) {
|
|
8237
|
+
return;
|
|
8238
|
+
}
|
|
8239
|
+
const { span, startTime } = spanData;
|
|
8240
|
+
const resultEvent = event;
|
|
8241
|
+
const stream = resultEvent.result;
|
|
8242
|
+
if (!isSyncStreamLike(stream)) {
|
|
8243
|
+
span.end();
|
|
8244
|
+
states.delete(event);
|
|
8245
|
+
return;
|
|
8246
|
+
}
|
|
8247
|
+
let first = true;
|
|
8248
|
+
stream.on("chunk", () => {
|
|
8249
|
+
if (first) {
|
|
8250
|
+
span.log({
|
|
8251
|
+
metrics: {
|
|
8252
|
+
time_to_first_token: getCurrentUnixTimestamp() - startTime
|
|
8253
|
+
}
|
|
8254
|
+
});
|
|
8255
|
+
first = false;
|
|
8256
|
+
}
|
|
8257
|
+
});
|
|
8258
|
+
stream.on("chatCompletion", (completion) => {
|
|
8259
|
+
try {
|
|
8260
|
+
if (hasChoices(completion)) {
|
|
8261
|
+
span.log({
|
|
8262
|
+
output: completion.choices
|
|
8263
|
+
});
|
|
8264
|
+
}
|
|
8265
|
+
} catch (error) {
|
|
8266
|
+
console.error(
|
|
8267
|
+
`Error extracting chatCompletion for ${channelName}:`,
|
|
8268
|
+
error
|
|
8269
|
+
);
|
|
8270
|
+
}
|
|
8271
|
+
});
|
|
8272
|
+
stream.on("event", (streamEvent) => {
|
|
8273
|
+
if (!config.extractFromEvent) {
|
|
8274
|
+
return;
|
|
8275
|
+
}
|
|
8276
|
+
try {
|
|
8277
|
+
if (first) {
|
|
8278
|
+
span.log({
|
|
8279
|
+
metrics: {
|
|
8280
|
+
time_to_first_token: getCurrentUnixTimestamp() - startTime
|
|
8281
|
+
}
|
|
8282
|
+
});
|
|
8283
|
+
first = false;
|
|
8284
|
+
}
|
|
8285
|
+
const extracted = config.extractFromEvent(streamEvent);
|
|
8286
|
+
if (extracted && Object.keys(extracted).length > 0) {
|
|
8287
|
+
span.log(extracted);
|
|
8288
|
+
}
|
|
8289
|
+
} catch (error) {
|
|
8290
|
+
console.error(`Error extracting event for ${channelName}:`, error);
|
|
8291
|
+
}
|
|
8292
|
+
});
|
|
8293
|
+
stream.on("end", () => {
|
|
8294
|
+
span.end();
|
|
8295
|
+
states.delete(event);
|
|
8296
|
+
});
|
|
8297
|
+
stream.on("error", (error) => {
|
|
8298
|
+
span.log({
|
|
8299
|
+
error: error.message
|
|
8300
|
+
});
|
|
8301
|
+
span.end();
|
|
8302
|
+
states.delete(event);
|
|
8303
|
+
});
|
|
8304
|
+
},
|
|
8305
|
+
error: (event) => {
|
|
8306
|
+
logErrorAndEnd(states, event);
|
|
8307
|
+
}
|
|
8308
|
+
};
|
|
8309
|
+
tracingChannel.subscribe(handlers);
|
|
8310
|
+
return () => {
|
|
8311
|
+
tracingChannel.unsubscribe(handlers);
|
|
8312
|
+
};
|
|
8313
|
+
}
|
|
8314
|
+
function unsubscribeAll(unsubscribers) {
|
|
8315
|
+
for (const unsubscribe of unsubscribers) {
|
|
8316
|
+
unsubscribe();
|
|
8317
|
+
}
|
|
8318
|
+
return [];
|
|
8319
|
+
}
|
|
8320
|
+
|
|
8321
|
+
// src/wrappers/attachment-utils.ts
|
|
8322
|
+
function getExtensionFromMediaType(mediaType) {
|
|
8323
|
+
const extensionMap = {
|
|
8324
|
+
"image/png": "png",
|
|
8325
|
+
"image/jpeg": "jpg",
|
|
8326
|
+
"image/gif": "gif",
|
|
8327
|
+
"image/webp": "webp",
|
|
8328
|
+
"image/svg+xml": "svg",
|
|
8329
|
+
"audio/mpeg": "mp3",
|
|
8330
|
+
"audio/wav": "wav",
|
|
8331
|
+
"audio/ogg": "ogg",
|
|
8332
|
+
"video/mp4": "mp4",
|
|
8333
|
+
"video/webm": "webm",
|
|
8334
|
+
"application/pdf": "pdf",
|
|
8335
|
+
"application/json": "json",
|
|
8336
|
+
"text/plain": "txt",
|
|
8337
|
+
"text/html": "html",
|
|
8338
|
+
"text/csv": "csv"
|
|
8339
|
+
};
|
|
8340
|
+
return extensionMap[mediaType] || "bin";
|
|
8341
|
+
}
|
|
8342
|
+
function convertDataToBlob(data, mediaType) {
|
|
8343
|
+
try {
|
|
8344
|
+
if (typeof data === "string") {
|
|
8345
|
+
if (data.startsWith("data:")) {
|
|
8346
|
+
const base64Match = data.match(/^data:[^;]+;base64,(.+)$/);
|
|
8347
|
+
if (base64Match) {
|
|
8348
|
+
const base64 = base64Match[1];
|
|
8349
|
+
const binaryString = atob(base64);
|
|
8350
|
+
const bytes = new Uint8Array(binaryString.length);
|
|
8351
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
8352
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
8353
|
+
}
|
|
8354
|
+
return new Blob([bytes], { type: mediaType });
|
|
8355
|
+
}
|
|
8356
|
+
} else if (data.startsWith("http://") || data.startsWith("https://")) {
|
|
8357
|
+
return null;
|
|
8358
|
+
} else {
|
|
8359
|
+
const binaryString = atob(data);
|
|
8360
|
+
const bytes = new Uint8Array(binaryString.length);
|
|
8361
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
8362
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
8363
|
+
}
|
|
8364
|
+
return new Blob([bytes], { type: mediaType });
|
|
8365
|
+
}
|
|
8366
|
+
} else if (data instanceof Uint8Array) {
|
|
8367
|
+
return new Blob([data], { type: mediaType });
|
|
8368
|
+
} else if (data instanceof ArrayBuffer) {
|
|
8369
|
+
return new Blob([data], { type: mediaType });
|
|
8370
|
+
} else if (typeof Buffer !== "undefined" && data instanceof Buffer) {
|
|
8371
|
+
return new Blob([data], { type: mediaType });
|
|
8372
|
+
}
|
|
8373
|
+
} catch {
|
|
8374
|
+
return null;
|
|
8375
|
+
}
|
|
8376
|
+
return null;
|
|
8377
|
+
}
|
|
8378
|
+
function processInputAttachments(input) {
|
|
8379
|
+
if (!input) {
|
|
8380
|
+
return input;
|
|
8381
|
+
}
|
|
8382
|
+
let attachmentIndex = 0;
|
|
8383
|
+
const inferMediaTypeFromDataUrl = (value, fallback) => {
|
|
8384
|
+
const mediaTypeMatch = value.match(/^data:([^;]+);/);
|
|
8385
|
+
return mediaTypeMatch?.[1] || fallback;
|
|
8386
|
+
};
|
|
8387
|
+
const toAttachment = (value, mediaType, filename) => {
|
|
8388
|
+
const blob = convertDataToBlob(value, mediaType);
|
|
8389
|
+
if (!blob) {
|
|
8390
|
+
return null;
|
|
8391
|
+
}
|
|
8392
|
+
return new Attachment({
|
|
8393
|
+
data: blob,
|
|
8394
|
+
filename,
|
|
8395
|
+
contentType: mediaType
|
|
8396
|
+
});
|
|
8397
|
+
};
|
|
8398
|
+
const processNode = (node) => {
|
|
8399
|
+
if (Array.isArray(node)) {
|
|
8400
|
+
return node.map(processNode);
|
|
8401
|
+
}
|
|
8402
|
+
if (!node || typeof node !== "object") {
|
|
8403
|
+
return node;
|
|
8404
|
+
}
|
|
8405
|
+
if (node.type === "image_url" && node.image_url && typeof node.image_url === "object" && typeof node.image_url.url === "string" && node.image_url.url.startsWith("data:")) {
|
|
8406
|
+
const mediaType = inferMediaTypeFromDataUrl(
|
|
8407
|
+
node.image_url.url,
|
|
8408
|
+
"image/png"
|
|
8409
|
+
);
|
|
8410
|
+
const filename = `image.${getExtensionFromMediaType(mediaType)}`;
|
|
8411
|
+
const attachment = toAttachment(node.image_url.url, mediaType, filename);
|
|
8412
|
+
if (attachment) {
|
|
8413
|
+
return {
|
|
8414
|
+
...node,
|
|
8415
|
+
image_url: {
|
|
8416
|
+
...node.image_url,
|
|
8417
|
+
url: attachment
|
|
8418
|
+
}
|
|
8419
|
+
};
|
|
8420
|
+
}
|
|
8421
|
+
}
|
|
8422
|
+
if (node.type === "file" && node.file && typeof node.file === "object" && typeof node.file.file_data === "string" && node.file.file_data.startsWith("data:")) {
|
|
8423
|
+
const mediaType = inferMediaTypeFromDataUrl(
|
|
8424
|
+
node.file.file_data,
|
|
8425
|
+
"application/octet-stream"
|
|
8426
|
+
);
|
|
8427
|
+
const filename = typeof node.file.filename === "string" && node.file.filename ? node.file.filename : `document.${getExtensionFromMediaType(mediaType)}`;
|
|
8428
|
+
const attachment = toAttachment(node.file.file_data, mediaType, filename);
|
|
8429
|
+
if (attachment) {
|
|
8430
|
+
return {
|
|
8431
|
+
...node,
|
|
8432
|
+
file: {
|
|
8433
|
+
...node.file,
|
|
8434
|
+
file_data: attachment
|
|
8435
|
+
}
|
|
8436
|
+
};
|
|
8437
|
+
}
|
|
8438
|
+
}
|
|
8439
|
+
if (node.type === "image" && node.image) {
|
|
8440
|
+
let mediaType = "image/png";
|
|
8441
|
+
if (typeof node.image === "string" && node.image.startsWith("data:")) {
|
|
8442
|
+
mediaType = inferMediaTypeFromDataUrl(node.image, mediaType);
|
|
8443
|
+
} else if (node.mediaType) {
|
|
8444
|
+
mediaType = node.mediaType;
|
|
8445
|
+
}
|
|
8446
|
+
const filename = `input_image_${attachmentIndex}.${getExtensionFromMediaType(mediaType)}`;
|
|
8447
|
+
const attachment = toAttachment(node.image, mediaType, filename);
|
|
8448
|
+
if (attachment) {
|
|
8449
|
+
attachmentIndex++;
|
|
8450
|
+
return {
|
|
8451
|
+
...node,
|
|
8452
|
+
image: attachment
|
|
8453
|
+
};
|
|
8454
|
+
}
|
|
8455
|
+
}
|
|
8456
|
+
if (node.type === "file" && node.data) {
|
|
8457
|
+
const mediaType = node.mediaType || "application/octet-stream";
|
|
8458
|
+
const filename = node.filename || `input_file_${attachmentIndex}.${getExtensionFromMediaType(mediaType)}`;
|
|
8459
|
+
const attachment = toAttachment(node.data, mediaType, filename);
|
|
8460
|
+
if (attachment) {
|
|
8461
|
+
attachmentIndex++;
|
|
8462
|
+
return {
|
|
8463
|
+
...node,
|
|
8464
|
+
data: attachment
|
|
8465
|
+
};
|
|
8466
|
+
}
|
|
8467
|
+
}
|
|
8468
|
+
const processed = {};
|
|
8469
|
+
for (const [key, value] of Object.entries(node)) {
|
|
8470
|
+
processed[key] = processNode(value);
|
|
8471
|
+
}
|
|
8472
|
+
return processed;
|
|
8473
|
+
};
|
|
8474
|
+
if (Array.isArray(input)) {
|
|
8475
|
+
return input.map(processNode);
|
|
8476
|
+
}
|
|
8477
|
+
return processNode(input);
|
|
8478
|
+
}
|
|
8479
|
+
|
|
8480
|
+
// src/instrumentation/core/channel-definitions.ts
|
|
8481
|
+
function channel(spec) {
|
|
8482
|
+
return spec;
|
|
8483
|
+
}
|
|
8484
|
+
function defineChannels(pkg, channels) {
|
|
8485
|
+
return Object.fromEntries(
|
|
8486
|
+
Object.entries(channels).map(([key, spec]) => {
|
|
8487
|
+
const fullChannelName = `orchestrion:${pkg}:${spec.channelName}`;
|
|
8488
|
+
if (spec.kind === "async") {
|
|
8489
|
+
const asyncSpec = spec;
|
|
8490
|
+
const tracingChannel2 = () => isomorph_default.newTracingChannel(
|
|
8491
|
+
fullChannelName
|
|
8492
|
+
);
|
|
8493
|
+
return [
|
|
8494
|
+
key,
|
|
8495
|
+
{
|
|
8496
|
+
...asyncSpec,
|
|
8497
|
+
tracingChannel: tracingChannel2,
|
|
8498
|
+
tracePromise: (fn, context) => tracingChannel2().tracePromise(
|
|
8499
|
+
fn,
|
|
8500
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
8501
|
+
context
|
|
8502
|
+
)
|
|
8503
|
+
}
|
|
8504
|
+
];
|
|
8505
|
+
}
|
|
8506
|
+
const syncSpec = spec;
|
|
8507
|
+
const tracingChannel = () => isomorph_default.newTracingChannel(
|
|
8508
|
+
fullChannelName
|
|
8509
|
+
);
|
|
8510
|
+
return [
|
|
8511
|
+
key,
|
|
8512
|
+
{
|
|
8513
|
+
...syncSpec,
|
|
8514
|
+
tracingChannel,
|
|
8515
|
+
traceSync: (fn, context) => tracingChannel().traceSync(
|
|
8516
|
+
fn,
|
|
8517
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
8518
|
+
context
|
|
8519
|
+
)
|
|
8520
|
+
}
|
|
8521
|
+
];
|
|
8522
|
+
})
|
|
8523
|
+
);
|
|
8524
|
+
}
|
|
8525
|
+
|
|
8526
|
+
// src/instrumentation/plugins/openai-channels.ts
|
|
8527
|
+
var openAIChannels = defineChannels("openai", {
|
|
8528
|
+
chatCompletionsCreate: channel({
|
|
8529
|
+
channelName: "chat.completions.create",
|
|
8530
|
+
kind: "async"
|
|
8531
|
+
}),
|
|
8532
|
+
embeddingsCreate: channel({
|
|
8533
|
+
channelName: "embeddings.create",
|
|
8534
|
+
kind: "async"
|
|
8535
|
+
}),
|
|
8536
|
+
betaChatCompletionsParse: channel({
|
|
8537
|
+
channelName: "beta.chat.completions.parse",
|
|
8538
|
+
kind: "async"
|
|
8539
|
+
}),
|
|
8540
|
+
betaChatCompletionsStream: channel({
|
|
8541
|
+
channelName: "beta.chat.completions.stream",
|
|
8542
|
+
kind: "sync-stream"
|
|
8543
|
+
}),
|
|
8544
|
+
moderationsCreate: channel({
|
|
8545
|
+
channelName: "moderations.create",
|
|
8546
|
+
kind: "async"
|
|
8547
|
+
}),
|
|
8548
|
+
responsesCreate: channel({
|
|
8549
|
+
channelName: "responses.create",
|
|
8550
|
+
kind: "async"
|
|
8551
|
+
}),
|
|
8552
|
+
responsesStream: channel({
|
|
8553
|
+
channelName: "responses.stream",
|
|
8554
|
+
kind: "sync-stream"
|
|
8555
|
+
}),
|
|
8556
|
+
responsesParse: channel({
|
|
8557
|
+
channelName: "responses.parse",
|
|
8558
|
+
kind: "async"
|
|
8559
|
+
})
|
|
8560
|
+
});
|
|
8561
|
+
|
|
8562
|
+
// src/openai-utils.ts
|
|
8563
|
+
var BRAINTRUST_CACHED_STREAM_METRIC = "__braintrust_cached_metric";
|
|
8564
|
+
var LEGACY_CACHED_HEADER = "x-cached";
|
|
8565
|
+
var X_CACHED_HEADER = "x-bt-cached";
|
|
8566
|
+
var TOKEN_NAME_MAP = {
|
|
8567
|
+
input_tokens: "prompt_tokens",
|
|
8568
|
+
output_tokens: "completion_tokens",
|
|
8569
|
+
total_tokens: "tokens"
|
|
8570
|
+
};
|
|
8571
|
+
var TOKEN_PREFIX_MAP = {
|
|
8572
|
+
input: "prompt",
|
|
8573
|
+
output: "completion"
|
|
8574
|
+
};
|
|
8575
|
+
function parseMetricsFromUsage(usage) {
|
|
8576
|
+
if (!usage) {
|
|
8577
|
+
return {};
|
|
8578
|
+
}
|
|
8579
|
+
const metrics = {};
|
|
8580
|
+
for (const [oaiName, value] of Object.entries(usage)) {
|
|
8581
|
+
if (typeof value === "number") {
|
|
8582
|
+
const metricName = TOKEN_NAME_MAP[oaiName] || oaiName;
|
|
8583
|
+
metrics[metricName] = value;
|
|
8584
|
+
continue;
|
|
8585
|
+
}
|
|
8586
|
+
if (!oaiName.endsWith("_tokens_details") || !isObject(value)) {
|
|
8587
|
+
continue;
|
|
8588
|
+
}
|
|
8589
|
+
const rawPrefix = oaiName.slice(0, -"_tokens_details".length);
|
|
8590
|
+
const prefix = TOKEN_PREFIX_MAP[rawPrefix] || rawPrefix;
|
|
8591
|
+
for (const [key, nestedValue] of Object.entries(value)) {
|
|
8592
|
+
if (typeof nestedValue !== "number") {
|
|
8593
|
+
continue;
|
|
8594
|
+
}
|
|
8595
|
+
metrics[`${prefix}_${key}`] = nestedValue;
|
|
8596
|
+
}
|
|
8597
|
+
}
|
|
8598
|
+
return metrics;
|
|
8599
|
+
}
|
|
8600
|
+
function parseCachedHeader(value) {
|
|
8601
|
+
if (!value) {
|
|
8602
|
+
return void 0;
|
|
8603
|
+
}
|
|
8604
|
+
return ["true", "hit"].includes(value.toLowerCase()) ? 1 : 0;
|
|
8605
|
+
}
|
|
8606
|
+
function getCachedMetricFromHeaders(headers) {
|
|
8607
|
+
if (!headers || typeof headers.get !== "function") {
|
|
8608
|
+
return void 0;
|
|
8609
|
+
}
|
|
8610
|
+
const cachedHeader = headers.get(X_CACHED_HEADER);
|
|
8611
|
+
if (cachedHeader) {
|
|
8612
|
+
return parseCachedHeader(cachedHeader);
|
|
8613
|
+
}
|
|
8614
|
+
return parseCachedHeader(headers.get(LEGACY_CACHED_HEADER));
|
|
8615
|
+
}
|
|
8616
|
+
|
|
8617
|
+
// src/instrumentation/plugins/openai-plugin.ts
|
|
8618
|
+
var OpenAIPlugin = class extends BasePlugin {
|
|
8619
|
+
constructor() {
|
|
7876
8620
|
super();
|
|
7877
8621
|
}
|
|
7878
8622
|
onEnable() {
|
|
7879
|
-
this.
|
|
7880
|
-
|
|
7881
|
-
{
|
|
8623
|
+
this.unsubscribers.push(
|
|
8624
|
+
traceStreamingChannel(openAIChannels.chatCompletionsCreate, {
|
|
7882
8625
|
name: "Chat Completion",
|
|
7883
8626
|
type: "llm" /* LLM */,
|
|
7884
|
-
extractInput: (
|
|
7885
|
-
const params = args[0] || {};
|
|
8627
|
+
extractInput: ([params]) => {
|
|
7886
8628
|
const { messages, ...metadata } = params;
|
|
7887
8629
|
return {
|
|
7888
8630
|
input: processInputAttachments(messages),
|
|
@@ -7892,41 +8634,49 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
7892
8634
|
extractOutput: (result) => {
|
|
7893
8635
|
return result?.choices;
|
|
7894
8636
|
},
|
|
7895
|
-
extractMetrics: (result, startTime) => {
|
|
7896
|
-
const metrics =
|
|
8637
|
+
extractMetrics: (result, startTime, endEvent) => {
|
|
8638
|
+
const metrics = withCachedMetric(
|
|
8639
|
+
parseMetricsFromUsage(result?.usage),
|
|
8640
|
+
result,
|
|
8641
|
+
endEvent
|
|
8642
|
+
);
|
|
7897
8643
|
if (startTime) {
|
|
7898
8644
|
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
7899
8645
|
}
|
|
7900
8646
|
return metrics;
|
|
7901
8647
|
},
|
|
7902
8648
|
aggregateChunks: aggregateChatCompletionChunks
|
|
7903
|
-
}
|
|
8649
|
+
})
|
|
7904
8650
|
);
|
|
7905
|
-
this.
|
|
7906
|
-
|
|
7907
|
-
|
|
7908
|
-
|
|
7909
|
-
|
|
7910
|
-
|
|
7911
|
-
|
|
7912
|
-
|
|
7913
|
-
|
|
7914
|
-
|
|
7915
|
-
|
|
7916
|
-
|
|
7917
|
-
|
|
7918
|
-
|
|
7919
|
-
|
|
7920
|
-
|
|
7921
|
-
|
|
7922
|
-
|
|
7923
|
-
|
|
7924
|
-
|
|
7925
|
-
|
|
8651
|
+
this.unsubscribers.push(
|
|
8652
|
+
traceAsyncChannel(openAIChannels.embeddingsCreate, {
|
|
8653
|
+
name: "Embedding",
|
|
8654
|
+
type: "llm" /* LLM */,
|
|
8655
|
+
extractInput: ([params]) => {
|
|
8656
|
+
const { input, ...metadata } = params;
|
|
8657
|
+
return {
|
|
8658
|
+
input,
|
|
8659
|
+
metadata: { ...metadata, provider: "openai" }
|
|
8660
|
+
};
|
|
8661
|
+
},
|
|
8662
|
+
extractOutput: (result) => {
|
|
8663
|
+
const embedding = result?.data?.[0]?.embedding;
|
|
8664
|
+
return Array.isArray(embedding) ? { embedding_length: embedding.length } : void 0;
|
|
8665
|
+
},
|
|
8666
|
+
extractMetrics: (result, _startTime, endEvent) => {
|
|
8667
|
+
return withCachedMetric(
|
|
8668
|
+
parseMetricsFromUsage(result?.usage),
|
|
8669
|
+
result,
|
|
8670
|
+
endEvent
|
|
8671
|
+
);
|
|
8672
|
+
}
|
|
8673
|
+
})
|
|
8674
|
+
);
|
|
8675
|
+
this.unsubscribers.push(
|
|
8676
|
+
traceStreamingChannel(openAIChannels.betaChatCompletionsParse, {
|
|
7926
8677
|
name: "Chat Completion",
|
|
7927
8678
|
type: "llm" /* LLM */,
|
|
7928
|
-
extractInput: (
|
|
7929
|
-
const params = args[0] || {};
|
|
8679
|
+
extractInput: ([params]) => {
|
|
7930
8680
|
const { messages, ...metadata } = params;
|
|
7931
8681
|
return {
|
|
7932
8682
|
input: processInputAttachments(messages),
|
|
@@ -7936,164 +8686,196 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
7936
8686
|
extractOutput: (result) => {
|
|
7937
8687
|
return result?.choices;
|
|
7938
8688
|
},
|
|
7939
|
-
extractMetrics: (result, startTime) => {
|
|
7940
|
-
const metrics =
|
|
8689
|
+
extractMetrics: (result, startTime, endEvent) => {
|
|
8690
|
+
const metrics = withCachedMetric(
|
|
8691
|
+
parseMetricsFromUsage(result?.usage),
|
|
8692
|
+
result,
|
|
8693
|
+
endEvent
|
|
8694
|
+
);
|
|
7941
8695
|
if (startTime) {
|
|
7942
8696
|
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
7943
8697
|
}
|
|
7944
8698
|
return metrics;
|
|
7945
8699
|
},
|
|
7946
8700
|
aggregateChunks: aggregateChatCompletionChunks
|
|
7947
|
-
}
|
|
8701
|
+
})
|
|
7948
8702
|
);
|
|
7949
|
-
this.
|
|
7950
|
-
|
|
7951
|
-
{
|
|
8703
|
+
this.unsubscribers.push(
|
|
8704
|
+
traceSyncStreamChannel(openAIChannels.betaChatCompletionsStream, {
|
|
7952
8705
|
name: "Chat Completion",
|
|
7953
8706
|
type: "llm" /* LLM */,
|
|
7954
|
-
extractInput: (
|
|
7955
|
-
const params = args[0] || {};
|
|
8707
|
+
extractInput: ([params]) => {
|
|
7956
8708
|
const { messages, ...metadata } = params;
|
|
7957
8709
|
return {
|
|
7958
8710
|
input: processInputAttachments(messages),
|
|
7959
8711
|
metadata: { ...metadata, provider: "openai" }
|
|
7960
8712
|
};
|
|
7961
8713
|
}
|
|
7962
|
-
}
|
|
8714
|
+
})
|
|
7963
8715
|
);
|
|
7964
|
-
this.
|
|
7965
|
-
|
|
7966
|
-
|
|
7967
|
-
|
|
7968
|
-
|
|
7969
|
-
|
|
7970
|
-
|
|
7971
|
-
|
|
7972
|
-
|
|
7973
|
-
|
|
7974
|
-
|
|
7975
|
-
|
|
7976
|
-
|
|
7977
|
-
|
|
7978
|
-
|
|
7979
|
-
|
|
7980
|
-
|
|
7981
|
-
|
|
7982
|
-
|
|
7983
|
-
|
|
7984
|
-
type: "llm" /* LLM */,
|
|
7985
|
-
extractInput: (args) => {
|
|
7986
|
-
const params = args[0] || {};
|
|
7987
|
-
const { input, ...metadata } = params;
|
|
7988
|
-
return {
|
|
7989
|
-
input: processInputAttachments(input),
|
|
7990
|
-
metadata: { ...metadata, provider: "openai" }
|
|
7991
|
-
};
|
|
7992
|
-
},
|
|
7993
|
-
extractOutput: (result) => {
|
|
7994
|
-
return processImagesInOutput(result?.output);
|
|
7995
|
-
},
|
|
7996
|
-
extractMetrics: (result, startTime) => {
|
|
7997
|
-
const metrics = parseMetricsFromUsage(result?.usage);
|
|
7998
|
-
if (startTime) {
|
|
7999
|
-
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
8000
|
-
}
|
|
8001
|
-
return metrics;
|
|
8002
|
-
}
|
|
8003
|
-
});
|
|
8004
|
-
this.subscribeToSyncStreamChannel("orchestrion:openai:responses.stream", {
|
|
8005
|
-
name: "openai.responses.stream",
|
|
8006
|
-
type: "llm" /* LLM */,
|
|
8007
|
-
extractInput: (args) => {
|
|
8008
|
-
const params = args[0] || {};
|
|
8009
|
-
const { input, ...metadata } = params;
|
|
8010
|
-
return {
|
|
8011
|
-
input: processInputAttachments(input),
|
|
8012
|
-
metadata: { ...metadata, provider: "openai" }
|
|
8013
|
-
};
|
|
8014
|
-
},
|
|
8015
|
-
extractFromEvent: (event) => {
|
|
8016
|
-
if (!event || !event.type || !event.response) {
|
|
8017
|
-
return {};
|
|
8716
|
+
this.unsubscribers.push(
|
|
8717
|
+
traceAsyncChannel(openAIChannels.moderationsCreate, {
|
|
8718
|
+
name: "Moderation",
|
|
8719
|
+
type: "llm" /* LLM */,
|
|
8720
|
+
extractInput: ([params]) => {
|
|
8721
|
+
const { input, ...metadata } = params;
|
|
8722
|
+
return {
|
|
8723
|
+
input,
|
|
8724
|
+
metadata: { ...metadata, provider: "openai" }
|
|
8725
|
+
};
|
|
8726
|
+
},
|
|
8727
|
+
extractOutput: (result) => {
|
|
8728
|
+
return result?.results;
|
|
8729
|
+
},
|
|
8730
|
+
extractMetrics: (result, _startTime, endEvent) => {
|
|
8731
|
+
return withCachedMetric(
|
|
8732
|
+
parseMetricsFromUsage(result?.usage),
|
|
8733
|
+
result,
|
|
8734
|
+
endEvent
|
|
8735
|
+
);
|
|
8018
8736
|
}
|
|
8019
|
-
|
|
8020
|
-
|
|
8737
|
+
})
|
|
8738
|
+
);
|
|
8739
|
+
this.unsubscribers.push(
|
|
8740
|
+
traceStreamingChannel(openAIChannels.responsesCreate, {
|
|
8741
|
+
name: "openai.responses.create",
|
|
8742
|
+
type: "llm" /* LLM */,
|
|
8743
|
+
extractInput: ([params]) => {
|
|
8744
|
+
const { input, ...metadata } = params;
|
|
8745
|
+
return {
|
|
8746
|
+
input: processInputAttachments(input),
|
|
8747
|
+
metadata: { ...metadata, provider: "openai" }
|
|
8748
|
+
};
|
|
8749
|
+
},
|
|
8750
|
+
extractOutput: (result) => {
|
|
8751
|
+
return processImagesInOutput(result?.output);
|
|
8752
|
+
},
|
|
8753
|
+
extractMetadata: (result) => {
|
|
8754
|
+
if (!result) {
|
|
8755
|
+
return void 0;
|
|
8756
|
+
}
|
|
8757
|
+
const { output: _output, usage: _usage, ...metadata } = result;
|
|
8758
|
+
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
8759
|
+
},
|
|
8760
|
+
extractMetrics: (result, startTime, endEvent) => {
|
|
8761
|
+
const metrics = withCachedMetric(
|
|
8762
|
+
parseMetricsFromUsage(result?.usage),
|
|
8763
|
+
result,
|
|
8764
|
+
endEvent
|
|
8765
|
+
);
|
|
8766
|
+
if (startTime) {
|
|
8767
|
+
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
8768
|
+
}
|
|
8769
|
+
return metrics;
|
|
8770
|
+
},
|
|
8771
|
+
aggregateChunks: aggregateResponseStreamEvents
|
|
8772
|
+
})
|
|
8773
|
+
);
|
|
8774
|
+
this.unsubscribers.push(
|
|
8775
|
+
traceSyncStreamChannel(openAIChannels.responsesStream, {
|
|
8776
|
+
name: "openai.responses.create",
|
|
8777
|
+
type: "llm" /* LLM */,
|
|
8778
|
+
extractInput: ([params]) => {
|
|
8779
|
+
const { input, ...metadata } = params;
|
|
8780
|
+
return {
|
|
8781
|
+
input: processInputAttachments(input),
|
|
8782
|
+
metadata: { ...metadata, provider: "openai" }
|
|
8783
|
+
};
|
|
8784
|
+
},
|
|
8785
|
+
extractFromEvent: (event) => {
|
|
8786
|
+
if (event.type !== "response.completed" || !event.response) {
|
|
8787
|
+
return {};
|
|
8788
|
+
}
|
|
8789
|
+
const response = event.response;
|
|
8021
8790
|
const data = {};
|
|
8022
|
-
if (response
|
|
8791
|
+
if (response.output !== void 0) {
|
|
8023
8792
|
data.output = processImagesInOutput(response.output);
|
|
8024
8793
|
}
|
|
8025
|
-
|
|
8026
|
-
|
|
8027
|
-
|
|
8028
|
-
data.metadata = metadata;
|
|
8029
|
-
}
|
|
8794
|
+
const { usage: _usage, output: _output, ...metadata } = response;
|
|
8795
|
+
if (Object.keys(metadata).length > 0) {
|
|
8796
|
+
data.metadata = metadata;
|
|
8030
8797
|
}
|
|
8031
|
-
data.metrics = parseMetricsFromUsage(response
|
|
8798
|
+
data.metrics = parseMetricsFromUsage(response.usage);
|
|
8032
8799
|
return data;
|
|
8033
8800
|
}
|
|
8034
|
-
|
|
8035
|
-
|
|
8036
|
-
|
|
8037
|
-
|
|
8038
|
-
|
|
8039
|
-
|
|
8040
|
-
|
|
8041
|
-
|
|
8042
|
-
|
|
8043
|
-
|
|
8044
|
-
|
|
8045
|
-
|
|
8046
|
-
}
|
|
8047
|
-
|
|
8048
|
-
|
|
8049
|
-
|
|
8050
|
-
|
|
8051
|
-
|
|
8052
|
-
|
|
8053
|
-
|
|
8054
|
-
|
|
8055
|
-
|
|
8056
|
-
|
|
8057
|
-
|
|
8058
|
-
|
|
8801
|
+
})
|
|
8802
|
+
);
|
|
8803
|
+
this.unsubscribers.push(
|
|
8804
|
+
traceStreamingChannel(openAIChannels.responsesParse, {
|
|
8805
|
+
name: "openai.responses.parse",
|
|
8806
|
+
type: "llm" /* LLM */,
|
|
8807
|
+
extractInput: ([params]) => {
|
|
8808
|
+
const { input, ...metadata } = params;
|
|
8809
|
+
return {
|
|
8810
|
+
input: processInputAttachments(input),
|
|
8811
|
+
metadata: { ...metadata, provider: "openai" }
|
|
8812
|
+
};
|
|
8813
|
+
},
|
|
8814
|
+
extractOutput: (result) => {
|
|
8815
|
+
return processImagesInOutput(result?.output);
|
|
8816
|
+
},
|
|
8817
|
+
extractMetadata: (result) => {
|
|
8818
|
+
if (!result) {
|
|
8819
|
+
return void 0;
|
|
8820
|
+
}
|
|
8821
|
+
const { output: _output, usage: _usage, ...metadata } = result;
|
|
8822
|
+
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
8823
|
+
},
|
|
8824
|
+
extractMetrics: (result, startTime, endEvent) => {
|
|
8825
|
+
const metrics = withCachedMetric(
|
|
8826
|
+
parseMetricsFromUsage(result?.usage),
|
|
8827
|
+
result,
|
|
8828
|
+
endEvent
|
|
8829
|
+
);
|
|
8830
|
+
if (startTime) {
|
|
8831
|
+
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
8832
|
+
}
|
|
8833
|
+
return metrics;
|
|
8834
|
+
},
|
|
8835
|
+
aggregateChunks: aggregateResponseStreamEvents
|
|
8836
|
+
})
|
|
8837
|
+
);
|
|
8059
8838
|
}
|
|
8060
8839
|
onDisable() {
|
|
8840
|
+
this.unsubscribers = unsubscribeAll(this.unsubscribers);
|
|
8061
8841
|
}
|
|
8062
8842
|
};
|
|
8063
|
-
|
|
8064
|
-
|
|
8065
|
-
|
|
8066
|
-
total_tokens: "tokens"
|
|
8067
|
-
};
|
|
8068
|
-
var TOKEN_PREFIX_MAP = {
|
|
8069
|
-
input: "prompt",
|
|
8070
|
-
output: "completion"
|
|
8071
|
-
};
|
|
8072
|
-
function parseMetricsFromUsage(usage) {
|
|
8073
|
-
if (!usage) {
|
|
8074
|
-
return {};
|
|
8843
|
+
function getCachedMetricFromEndEvent(endEvent) {
|
|
8844
|
+
if (!isObject(endEvent)) {
|
|
8845
|
+
return void 0;
|
|
8075
8846
|
}
|
|
8076
|
-
const
|
|
8077
|
-
|
|
8078
|
-
|
|
8079
|
-
const metricName = TOKEN_NAME_MAP[oai_name] || oai_name;
|
|
8080
|
-
metrics[metricName] = value;
|
|
8081
|
-
} else if (oai_name.endsWith("_tokens_details")) {
|
|
8082
|
-
if (!isObject(value)) {
|
|
8083
|
-
continue;
|
|
8084
|
-
}
|
|
8085
|
-
const rawPrefix = oai_name.slice(0, -"_tokens_details".length);
|
|
8086
|
-
const prefix = TOKEN_PREFIX_MAP[rawPrefix] || rawPrefix;
|
|
8087
|
-
for (const [key, n] of Object.entries(value)) {
|
|
8088
|
-
if (typeof n !== "number") {
|
|
8089
|
-
continue;
|
|
8090
|
-
}
|
|
8091
|
-
const metricName = `${prefix}_${key}`;
|
|
8092
|
-
metrics[metricName] = n;
|
|
8093
|
-
}
|
|
8094
|
-
}
|
|
8847
|
+
const response = endEvent.response;
|
|
8848
|
+
if (!isObject(response)) {
|
|
8849
|
+
return void 0;
|
|
8095
8850
|
}
|
|
8096
|
-
|
|
8851
|
+
const headers = response.headers;
|
|
8852
|
+
if (!headers || typeof headers.get !== "function") {
|
|
8853
|
+
return void 0;
|
|
8854
|
+
}
|
|
8855
|
+
return getCachedMetricFromHeaders(headers);
|
|
8856
|
+
}
|
|
8857
|
+
function withCachedMetric(metrics, result, endEvent) {
|
|
8858
|
+
if (metrics.cached !== void 0) {
|
|
8859
|
+
return metrics;
|
|
8860
|
+
}
|
|
8861
|
+
const cachedFromEvent = getCachedMetricFromEndEvent(endEvent);
|
|
8862
|
+
if (cachedFromEvent !== void 0) {
|
|
8863
|
+
return {
|
|
8864
|
+
...metrics,
|
|
8865
|
+
cached: cachedFromEvent
|
|
8866
|
+
};
|
|
8867
|
+
}
|
|
8868
|
+
if (!isObject(result)) {
|
|
8869
|
+
return metrics;
|
|
8870
|
+
}
|
|
8871
|
+
const cached = result[BRAINTRUST_CACHED_STREAM_METRIC];
|
|
8872
|
+
if (typeof cached !== "number") {
|
|
8873
|
+
return metrics;
|
|
8874
|
+
}
|
|
8875
|
+
return {
|
|
8876
|
+
...metrics,
|
|
8877
|
+
cached
|
|
8878
|
+
};
|
|
8097
8879
|
}
|
|
8098
8880
|
function processImagesInOutput(output) {
|
|
8099
8881
|
if (Array.isArray(output)) {
|
|
@@ -8124,7 +8906,7 @@ function processImagesInOutput(output) {
|
|
|
8124
8906
|
}
|
|
8125
8907
|
return output;
|
|
8126
8908
|
}
|
|
8127
|
-
function aggregateChatCompletionChunks(chunks) {
|
|
8909
|
+
function aggregateChatCompletionChunks(chunks, streamResult, endEvent) {
|
|
8128
8910
|
let role = void 0;
|
|
8129
8911
|
let content = void 0;
|
|
8130
8912
|
let tool_calls = void 0;
|
|
@@ -8166,6 +8948,7 @@ function aggregateChatCompletionChunks(chunks) {
|
|
|
8166
8948
|
}
|
|
8167
8949
|
}
|
|
8168
8950
|
}
|
|
8951
|
+
metrics = withCachedMetric(metrics, streamResult, endEvent);
|
|
8169
8952
|
return {
|
|
8170
8953
|
metrics,
|
|
8171
8954
|
output: [
|
|
@@ -8182,9 +8965,33 @@ function aggregateChatCompletionChunks(chunks) {
|
|
|
8182
8965
|
]
|
|
8183
8966
|
};
|
|
8184
8967
|
}
|
|
8185
|
-
|
|
8186
|
-
|
|
8187
|
-
|
|
8968
|
+
function aggregateResponseStreamEvents(chunks, _streamResult, endEvent) {
|
|
8969
|
+
let output = void 0;
|
|
8970
|
+
let metrics = {};
|
|
8971
|
+
let metadata = void 0;
|
|
8972
|
+
for (const chunk of chunks) {
|
|
8973
|
+
if (!chunk || !chunk.type || !chunk.response) {
|
|
8974
|
+
continue;
|
|
8975
|
+
}
|
|
8976
|
+
if (chunk.type !== "response.completed") {
|
|
8977
|
+
continue;
|
|
8978
|
+
}
|
|
8979
|
+
const response = chunk.response;
|
|
8980
|
+
if (response?.output !== void 0) {
|
|
8981
|
+
output = processImagesInOutput(response.output);
|
|
8982
|
+
}
|
|
8983
|
+
const { usage: _usage, output: _output, ...rest } = response || {};
|
|
8984
|
+
if (Object.keys(rest).length > 0) {
|
|
8985
|
+
metadata = rest;
|
|
8986
|
+
}
|
|
8987
|
+
metrics = parseMetricsFromUsage(response?.usage);
|
|
8988
|
+
}
|
|
8989
|
+
return {
|
|
8990
|
+
output,
|
|
8991
|
+
metrics: withCachedMetric(metrics, void 0, endEvent),
|
|
8992
|
+
...metadata !== void 0 ? { metadata } : {}
|
|
8993
|
+
};
|
|
8994
|
+
}
|
|
8188
8995
|
|
|
8189
8996
|
// src/wrappers/anthropic-tokens-util.ts
|
|
8190
8997
|
function finalizeAnthropicTokens(metrics) {
|
|
@@ -8205,216 +9012,76 @@ function extractAnthropicCacheTokens(cacheReadTokens = 0, cacheCreationTokens =
|
|
|
8205
9012
|
}
|
|
8206
9013
|
return cacheTokens;
|
|
8207
9014
|
}
|
|
8208
|
-
|
|
8209
|
-
// src/instrumentation/plugins/anthropic-
|
|
8210
|
-
var
|
|
8211
|
-
|
|
8212
|
-
|
|
8213
|
-
|
|
8214
|
-
}
|
|
8215
|
-
|
|
8216
|
-
|
|
8217
|
-
|
|
8218
|
-
|
|
8219
|
-
|
|
8220
|
-
|
|
8221
|
-
|
|
8222
|
-
|
|
8223
|
-
|
|
8224
|
-
|
|
8225
|
-
|
|
8226
|
-
|
|
8227
|
-
|
|
8228
|
-
|
|
8229
|
-
|
|
8230
|
-
|
|
8231
|
-
|
|
8232
|
-
|
|
8233
|
-
|
|
8234
|
-
|
|
8235
|
-
|
|
8236
|
-
|
|
8237
|
-
|
|
8238
|
-
|
|
8239
|
-
|
|
8240
|
-
|
|
8241
|
-
|
|
8242
|
-
|
|
8243
|
-
return
|
|
8244
|
-
|
|
8245
|
-
|
|
8246
|
-
|
|
8247
|
-
|
|
8248
|
-
|
|
8249
|
-
const metas = ["stop_reason", "stop_sequence"];
|
|
8250
|
-
for (const m of metas) {
|
|
8251
|
-
if (result?.[m] !== void 0) {
|
|
8252
|
-
metadata[m] = result[m];
|
|
8253
|
-
}
|
|
8254
|
-
}
|
|
8255
|
-
return metadata;
|
|
8256
|
-
},
|
|
8257
|
-
aggregateChunks: aggregateAnthropicStreamChunks,
|
|
8258
|
-
isStreaming: (args) => {
|
|
8259
|
-
return args[0]?.stream === true;
|
|
8260
|
-
}
|
|
8261
|
-
});
|
|
8262
|
-
this.subscribeToStreamingChannel(
|
|
8263
|
-
"orchestrion:anthropic:beta.messages.create",
|
|
8264
|
-
{
|
|
8265
|
-
name: "anthropic.beta.messages.create",
|
|
8266
|
-
type: "llm" /* LLM */,
|
|
8267
|
-
extractInput: (args) => {
|
|
8268
|
-
const params = args[0] || {};
|
|
8269
|
-
const input = coalesceInput(params.messages || [], params.system);
|
|
8270
|
-
const metadata = filterFrom(params, ["messages", "system"]);
|
|
8271
|
-
return {
|
|
8272
|
-
input: processAttachmentsInInput(input),
|
|
8273
|
-
metadata: { ...metadata, provider: "anthropic" }
|
|
8274
|
-
};
|
|
8275
|
-
},
|
|
8276
|
-
extractOutput: (result) => {
|
|
8277
|
-
return result ? { role: result.role, content: result.content } : null;
|
|
8278
|
-
},
|
|
8279
|
-
extractMetrics: (result, startTime) => {
|
|
8280
|
-
const metrics = parseMetricsFromUsage2(result?.usage);
|
|
8281
|
-
if (startTime) {
|
|
8282
|
-
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
8283
|
-
}
|
|
8284
|
-
const finalized = finalizeAnthropicTokens(metrics);
|
|
8285
|
-
return Object.fromEntries(
|
|
8286
|
-
Object.entries(finalized).filter(([, v]) => v !== void 0)
|
|
8287
|
-
);
|
|
8288
|
-
},
|
|
8289
|
-
extractMetadata: (result) => {
|
|
8290
|
-
const metadata = {};
|
|
8291
|
-
const metas = ["stop_reason", "stop_sequence"];
|
|
8292
|
-
for (const m of metas) {
|
|
8293
|
-
if (result?.[m] !== void 0) {
|
|
8294
|
-
metadata[m] = result[m];
|
|
8295
|
-
}
|
|
8296
|
-
}
|
|
8297
|
-
return metadata;
|
|
8298
|
-
},
|
|
8299
|
-
aggregateChunks: aggregateAnthropicStreamChunks,
|
|
8300
|
-
isStreaming: (args) => {
|
|
8301
|
-
return args[0]?.stream === true;
|
|
8302
|
-
}
|
|
8303
|
-
}
|
|
8304
|
-
);
|
|
8305
|
-
}
|
|
8306
|
-
/**
|
|
8307
|
-
* Subscribe to a channel for async methods that may return streams.
|
|
8308
|
-
* Handles both streaming and non-streaming responses based on the stream parameter.
|
|
8309
|
-
*/
|
|
8310
|
-
subscribeToStreamingChannel(channelName, config) {
|
|
8311
|
-
const channel = (0, import_dc_browser2.tracingChannel)(channelName);
|
|
8312
|
-
const spans = /* @__PURE__ */ new WeakMap();
|
|
8313
|
-
const handlers = {
|
|
8314
|
-
start: (event) => {
|
|
8315
|
-
const span = startSpan({
|
|
8316
|
-
name: config.name,
|
|
8317
|
-
spanAttributes: {
|
|
8318
|
-
type: config.type
|
|
8319
|
-
}
|
|
8320
|
-
});
|
|
8321
|
-
const startTime = getCurrentUnixTimestamp();
|
|
8322
|
-
spans.set(event, { span, startTime });
|
|
8323
|
-
try {
|
|
8324
|
-
const { input, metadata } = config.extractInput(event.arguments);
|
|
8325
|
-
span.log({
|
|
8326
|
-
input,
|
|
8327
|
-
metadata
|
|
8328
|
-
});
|
|
8329
|
-
} catch (error) {
|
|
8330
|
-
console.error(`Error extracting input for ${channelName}:`, error);
|
|
8331
|
-
}
|
|
8332
|
-
},
|
|
8333
|
-
asyncEnd: (event) => {
|
|
8334
|
-
const spanData = spans.get(event);
|
|
8335
|
-
if (!spanData) {
|
|
8336
|
-
return;
|
|
8337
|
-
}
|
|
8338
|
-
const { span, startTime } = spanData;
|
|
8339
|
-
const isStreaming = config.isStreaming ? config.isStreaming(event.arguments) : isAsyncIterable(event.result);
|
|
8340
|
-
if (isStreaming && isAsyncIterable(event.result)) {
|
|
8341
|
-
patchStreamIfNeeded(event.result, {
|
|
8342
|
-
onComplete: (chunks) => {
|
|
8343
|
-
try {
|
|
8344
|
-
let output;
|
|
8345
|
-
let metrics;
|
|
8346
|
-
let metadata = {};
|
|
8347
|
-
if (config.aggregateChunks) {
|
|
8348
|
-
const aggregated = config.aggregateChunks(chunks);
|
|
8349
|
-
output = aggregated.output;
|
|
8350
|
-
metrics = aggregated.metrics;
|
|
8351
|
-
metadata = aggregated.metadata || {};
|
|
8352
|
-
} else {
|
|
8353
|
-
output = config.extractOutput(chunks);
|
|
8354
|
-
metrics = config.extractMetrics(chunks, startTime);
|
|
8355
|
-
if (config.extractMetadata) {
|
|
8356
|
-
metadata = config.extractMetadata(chunks);
|
|
8357
|
-
}
|
|
8358
|
-
}
|
|
8359
|
-
if (!metrics.time_to_first_token && chunks.length > 0) {
|
|
8360
|
-
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
8361
|
-
}
|
|
8362
|
-
span.log({
|
|
8363
|
-
output,
|
|
8364
|
-
metrics,
|
|
8365
|
-
metadata
|
|
8366
|
-
});
|
|
8367
|
-
} catch (error) {
|
|
8368
|
-
console.error(
|
|
8369
|
-
`Error extracting output for ${channelName}:`,
|
|
8370
|
-
error
|
|
8371
|
-
);
|
|
8372
|
-
} finally {
|
|
8373
|
-
span.end();
|
|
8374
|
-
}
|
|
8375
|
-
},
|
|
8376
|
-
onError: (error) => {
|
|
8377
|
-
span.log({
|
|
8378
|
-
error: error.message
|
|
8379
|
-
});
|
|
8380
|
-
span.end();
|
|
8381
|
-
}
|
|
8382
|
-
});
|
|
8383
|
-
} else {
|
|
8384
|
-
try {
|
|
8385
|
-
const output = config.extractOutput(event.result);
|
|
8386
|
-
const metrics = config.extractMetrics(event.result, startTime);
|
|
8387
|
-
const metadata = config.extractMetadata ? config.extractMetadata(event.result) : {};
|
|
8388
|
-
span.log({
|
|
8389
|
-
output,
|
|
8390
|
-
metrics,
|
|
8391
|
-
metadata
|
|
8392
|
-
});
|
|
8393
|
-
} catch (error) {
|
|
8394
|
-
console.error(`Error extracting output for ${channelName}:`, error);
|
|
8395
|
-
} finally {
|
|
8396
|
-
span.end();
|
|
8397
|
-
spans.delete(event);
|
|
8398
|
-
}
|
|
9015
|
+
|
|
9016
|
+
// src/instrumentation/plugins/anthropic-channels.ts
|
|
9017
|
+
var anthropicChannels = defineChannels("@anthropic-ai/sdk", {
|
|
9018
|
+
messagesCreate: channel({
|
|
9019
|
+
channelName: "messages.create",
|
|
9020
|
+
kind: "async"
|
|
9021
|
+
}),
|
|
9022
|
+
betaMessagesCreate: channel({
|
|
9023
|
+
channelName: "beta.messages.create",
|
|
9024
|
+
kind: "async"
|
|
9025
|
+
})
|
|
9026
|
+
});
|
|
9027
|
+
|
|
9028
|
+
// src/instrumentation/plugins/anthropic-plugin.ts
|
|
9029
|
+
var AnthropicPlugin = class extends BasePlugin {
|
|
9030
|
+
onEnable() {
|
|
9031
|
+
this.subscribeToAnthropicChannels();
|
|
9032
|
+
}
|
|
9033
|
+
onDisable() {
|
|
9034
|
+
this.unsubscribers = unsubscribeAll(this.unsubscribers);
|
|
9035
|
+
}
|
|
9036
|
+
subscribeToAnthropicChannels() {
|
|
9037
|
+
const anthropicConfig = {
|
|
9038
|
+
name: "anthropic.messages.create",
|
|
9039
|
+
type: "llm" /* LLM */,
|
|
9040
|
+
extractInput: (args) => {
|
|
9041
|
+
const params = args[0] || {};
|
|
9042
|
+
const input = coalesceInput(params.messages || [], params.system);
|
|
9043
|
+
const metadata = filterFrom(params, ["messages", "system"]);
|
|
9044
|
+
return {
|
|
9045
|
+
input: processAttachmentsInInput(input),
|
|
9046
|
+
metadata: { ...metadata, provider: "anthropic" }
|
|
9047
|
+
};
|
|
9048
|
+
},
|
|
9049
|
+
extractOutput: (message) => {
|
|
9050
|
+
return message ? { role: message.role, content: message.content } : null;
|
|
9051
|
+
},
|
|
9052
|
+
extractMetrics: (message, startTime) => {
|
|
9053
|
+
const metrics = parseMetricsFromUsage2(message?.usage);
|
|
9054
|
+
if (startTime) {
|
|
9055
|
+
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
8399
9056
|
}
|
|
9057
|
+
const finalized = finalizeAnthropicTokens(metrics);
|
|
9058
|
+
return Object.fromEntries(
|
|
9059
|
+
Object.entries(finalized).filter(
|
|
9060
|
+
(entry) => entry[1] !== void 0
|
|
9061
|
+
)
|
|
9062
|
+
);
|
|
8400
9063
|
},
|
|
8401
|
-
|
|
8402
|
-
const
|
|
8403
|
-
|
|
8404
|
-
|
|
9064
|
+
extractMetadata: (message) => {
|
|
9065
|
+
const metadata = {};
|
|
9066
|
+
const metas = ["stop_reason", "stop_sequence"];
|
|
9067
|
+
for (const m of metas) {
|
|
9068
|
+
if (message?.[m] !== void 0) {
|
|
9069
|
+
metadata[m] = message[m];
|
|
9070
|
+
}
|
|
8405
9071
|
}
|
|
8406
|
-
|
|
8407
|
-
|
|
8408
|
-
|
|
8409
|
-
});
|
|
8410
|
-
span.end();
|
|
8411
|
-
spans.delete(event);
|
|
8412
|
-
}
|
|
9072
|
+
return metadata;
|
|
9073
|
+
},
|
|
9074
|
+
aggregateChunks: (chunks) => aggregateAnthropicStreamChunks(chunks)
|
|
8413
9075
|
};
|
|
8414
|
-
|
|
8415
|
-
|
|
8416
|
-
|
|
8417
|
-
|
|
9076
|
+
this.unsubscribers.push(
|
|
9077
|
+
traceStreamingChannel(anthropicChannels.messagesCreate, anthropicConfig)
|
|
9078
|
+
);
|
|
9079
|
+
this.unsubscribers.push(
|
|
9080
|
+
traceStreamingChannel(anthropicChannels.betaMessagesCreate, {
|
|
9081
|
+
...anthropicConfig,
|
|
9082
|
+
name: "anthropic.beta.messages.create"
|
|
9083
|
+
})
|
|
9084
|
+
);
|
|
8418
9085
|
}
|
|
8419
9086
|
};
|
|
8420
9087
|
function parseMetricsFromUsage2(usage) {
|
|
@@ -8438,29 +9105,29 @@ function aggregateAnthropicStreamChunks(chunks) {
|
|
|
8438
9105
|
const deltas = [];
|
|
8439
9106
|
let metrics = {};
|
|
8440
9107
|
let metadata = {};
|
|
8441
|
-
for (const
|
|
8442
|
-
switch (
|
|
9108
|
+
for (const event of chunks) {
|
|
9109
|
+
switch (event?.type) {
|
|
8443
9110
|
case "message_start":
|
|
8444
|
-
if (
|
|
8445
|
-
const initialMetrics = parseMetricsFromUsage2(
|
|
9111
|
+
if (event.message?.usage) {
|
|
9112
|
+
const initialMetrics = parseMetricsFromUsage2(event.message.usage);
|
|
8446
9113
|
metrics = { ...metrics, ...initialMetrics };
|
|
8447
9114
|
}
|
|
8448
9115
|
break;
|
|
8449
9116
|
case "content_block_delta":
|
|
8450
|
-
if (
|
|
8451
|
-
const text =
|
|
9117
|
+
if (event.delta?.type === "text_delta") {
|
|
9118
|
+
const text = event.delta.text;
|
|
8452
9119
|
if (text) {
|
|
8453
9120
|
deltas.push(text);
|
|
8454
9121
|
}
|
|
8455
9122
|
}
|
|
8456
9123
|
break;
|
|
8457
9124
|
case "message_delta":
|
|
8458
|
-
if (
|
|
8459
|
-
const finalMetrics = parseMetricsFromUsage2(
|
|
9125
|
+
if (event.usage) {
|
|
9126
|
+
const finalMetrics = parseMetricsFromUsage2(event.usage);
|
|
8460
9127
|
metrics = { ...metrics, ...finalMetrics };
|
|
8461
9128
|
}
|
|
8462
|
-
if (
|
|
8463
|
-
metadata = { ...metadata, ...
|
|
9129
|
+
if (event.delta) {
|
|
9130
|
+
metadata = { ...metadata, ...event.delta };
|
|
8464
9131
|
}
|
|
8465
9132
|
break;
|
|
8466
9133
|
}
|
|
@@ -8468,7 +9135,9 @@ function aggregateAnthropicStreamChunks(chunks) {
|
|
|
8468
9135
|
const output = deltas.join("");
|
|
8469
9136
|
const finalized = finalizeAnthropicTokens(metrics);
|
|
8470
9137
|
const filteredMetrics = Object.fromEntries(
|
|
8471
|
-
Object.entries(finalized).filter(
|
|
9138
|
+
Object.entries(finalized).filter(
|
|
9139
|
+
(entry) => entry[1] !== void 0
|
|
9140
|
+
)
|
|
8472
9141
|
);
|
|
8473
9142
|
return {
|
|
8474
9143
|
output,
|
|
@@ -8476,6 +9145,9 @@ function aggregateAnthropicStreamChunks(chunks) {
|
|
|
8476
9145
|
metadata
|
|
8477
9146
|
};
|
|
8478
9147
|
}
|
|
9148
|
+
function isAnthropicBase64ContentBlock(input) {
|
|
9149
|
+
return (input.type === "image" || input.type === "document") && isObject(input.source) && input.source.type === "base64";
|
|
9150
|
+
}
|
|
8479
9151
|
function convertBase64ToAttachment(source, contentType) {
|
|
8480
9152
|
const mediaType = typeof source.media_type === "string" ? source.media_type : "image/png";
|
|
8481
9153
|
const base64Data = source.data;
|
|
@@ -8499,14 +9171,14 @@ function convertBase64ToAttachment(source, contentType) {
|
|
|
8499
9171
|
data: attachment
|
|
8500
9172
|
};
|
|
8501
9173
|
}
|
|
8502
|
-
return source;
|
|
9174
|
+
return { ...source };
|
|
8503
9175
|
}
|
|
8504
9176
|
function processAttachmentsInInput(input) {
|
|
8505
9177
|
if (Array.isArray(input)) {
|
|
8506
9178
|
return input.map(processAttachmentsInInput);
|
|
8507
9179
|
}
|
|
8508
9180
|
if (isObject(input)) {
|
|
8509
|
-
if ((input
|
|
9181
|
+
if (isAnthropicBase64ContentBlock(input)) {
|
|
8510
9182
|
return {
|
|
8511
9183
|
...input,
|
|
8512
9184
|
source: convertBase64ToAttachment(input.source, input.type)
|
|
@@ -8537,8 +9209,35 @@ function filterFrom(obj, fieldsToRemove) {
|
|
|
8537
9209
|
return result;
|
|
8538
9210
|
}
|
|
8539
9211
|
|
|
9212
|
+
// src/instrumentation/plugins/ai-sdk-channels.ts
|
|
9213
|
+
var aiSDKChannels = defineChannels("ai", {
|
|
9214
|
+
generateText: channel({
|
|
9215
|
+
channelName: "generateText",
|
|
9216
|
+
kind: "async"
|
|
9217
|
+
}),
|
|
9218
|
+
streamText: channel({
|
|
9219
|
+
channelName: "streamText",
|
|
9220
|
+
kind: "async"
|
|
9221
|
+
}),
|
|
9222
|
+
generateObject: channel({
|
|
9223
|
+
channelName: "generateObject",
|
|
9224
|
+
kind: "async"
|
|
9225
|
+
}),
|
|
9226
|
+
streamObject: channel({
|
|
9227
|
+
channelName: "streamObject",
|
|
9228
|
+
kind: "async"
|
|
9229
|
+
}),
|
|
9230
|
+
agentGenerate: channel({
|
|
9231
|
+
channelName: "Agent.generate",
|
|
9232
|
+
kind: "async"
|
|
9233
|
+
}),
|
|
9234
|
+
agentStream: channel({
|
|
9235
|
+
channelName: "Agent.stream",
|
|
9236
|
+
kind: "async"
|
|
9237
|
+
})
|
|
9238
|
+
});
|
|
9239
|
+
|
|
8540
9240
|
// src/instrumentation/plugins/ai-sdk-plugin.ts
|
|
8541
|
-
var import_dc_browser3 = require("dc-browser");
|
|
8542
9241
|
var DEFAULT_DENY_OUTPUT_PATHS = [
|
|
8543
9242
|
// v3
|
|
8544
9243
|
"roundtrips[].request.body",
|
|
@@ -8554,7 +9253,6 @@ var DEFAULT_DENY_OUTPUT_PATHS = [
|
|
|
8554
9253
|
"steps[].response.headers"
|
|
8555
9254
|
];
|
|
8556
9255
|
var AISDKPlugin = class extends BasePlugin {
|
|
8557
|
-
unsubscribers = [];
|
|
8558
9256
|
config;
|
|
8559
9257
|
constructor(config = {}) {
|
|
8560
9258
|
super();
|
|
@@ -8564,249 +9262,148 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
8564
9262
|
this.subscribeToAISDK();
|
|
8565
9263
|
}
|
|
8566
9264
|
onDisable() {
|
|
8567
|
-
|
|
8568
|
-
unsubscribe();
|
|
8569
|
-
}
|
|
8570
|
-
this.unsubscribers = [];
|
|
9265
|
+
this.unsubscribers = unsubscribeAll(this.unsubscribers);
|
|
8571
9266
|
}
|
|
8572
9267
|
subscribeToAISDK() {
|
|
8573
9268
|
const denyOutputPaths = this.config.denyOutputPaths || DEFAULT_DENY_OUTPUT_PATHS;
|
|
8574
|
-
this.
|
|
8575
|
-
|
|
8576
|
-
|
|
8577
|
-
|
|
8578
|
-
|
|
8579
|
-
|
|
8580
|
-
|
|
8581
|
-
|
|
8582
|
-
|
|
8583
|
-
|
|
8584
|
-
|
|
8585
|
-
|
|
8586
|
-
|
|
8587
|
-
|
|
8588
|
-
|
|
8589
|
-
|
|
8590
|
-
|
|
8591
|
-
}
|
|
8592
|
-
return metrics;
|
|
8593
|
-
},
|
|
8594
|
-
aggregateChunks: aggregateAISDKChunks
|
|
8595
|
-
});
|
|
8596
|
-
this.subscribeToStreamingChannel("orchestrion:ai-sdk:streamText", {
|
|
8597
|
-
name: "streamText",
|
|
8598
|
-
type: "llm" /* LLM */,
|
|
8599
|
-
extractInput: (args) => {
|
|
8600
|
-
const params = args[0] || {};
|
|
8601
|
-
return {
|
|
8602
|
-
input: processAISDKInput(params),
|
|
8603
|
-
metadata: extractMetadataFromParams(params)
|
|
8604
|
-
};
|
|
8605
|
-
},
|
|
8606
|
-
extractOutput: (result) => {
|
|
8607
|
-
return processAISDKOutput(result, denyOutputPaths);
|
|
8608
|
-
},
|
|
8609
|
-
extractMetrics: (result, startTime) => {
|
|
8610
|
-
const metrics = extractTokenMetrics(result);
|
|
8611
|
-
if (startTime) {
|
|
8612
|
-
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
8613
|
-
}
|
|
8614
|
-
return metrics;
|
|
8615
|
-
},
|
|
8616
|
-
aggregateChunks: aggregateAISDKChunks
|
|
8617
|
-
});
|
|
8618
|
-
this.subscribeToStreamingChannel("orchestrion:ai-sdk:generateObject", {
|
|
8619
|
-
name: "generateObject",
|
|
8620
|
-
type: "llm" /* LLM */,
|
|
8621
|
-
extractInput: (args) => {
|
|
8622
|
-
const params = args[0] || {};
|
|
8623
|
-
return {
|
|
8624
|
-
input: processAISDKInput(params),
|
|
8625
|
-
metadata: extractMetadataFromParams(params)
|
|
8626
|
-
};
|
|
8627
|
-
},
|
|
8628
|
-
extractOutput: (result) => {
|
|
8629
|
-
return processAISDKOutput(result, denyOutputPaths);
|
|
8630
|
-
},
|
|
8631
|
-
extractMetrics: (result, startTime) => {
|
|
8632
|
-
const metrics = extractTokenMetrics(result);
|
|
8633
|
-
if (startTime) {
|
|
8634
|
-
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
8635
|
-
}
|
|
8636
|
-
return metrics;
|
|
8637
|
-
},
|
|
8638
|
-
aggregateChunks: aggregateAISDKChunks
|
|
8639
|
-
});
|
|
8640
|
-
this.subscribeToStreamingChannel("orchestrion:ai-sdk:streamObject", {
|
|
8641
|
-
name: "streamObject",
|
|
8642
|
-
type: "llm" /* LLM */,
|
|
8643
|
-
extractInput: (args) => {
|
|
8644
|
-
const params = args[0] || {};
|
|
8645
|
-
return {
|
|
8646
|
-
input: processAISDKInput(params),
|
|
8647
|
-
metadata: extractMetadataFromParams(params)
|
|
8648
|
-
};
|
|
8649
|
-
},
|
|
8650
|
-
extractOutput: (result) => {
|
|
8651
|
-
return processAISDKOutput(result, denyOutputPaths);
|
|
8652
|
-
},
|
|
8653
|
-
extractMetrics: (result, startTime) => {
|
|
8654
|
-
const metrics = extractTokenMetrics(result);
|
|
8655
|
-
if (startTime) {
|
|
8656
|
-
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
8657
|
-
}
|
|
8658
|
-
return metrics;
|
|
8659
|
-
},
|
|
8660
|
-
aggregateChunks: aggregateAISDKChunks
|
|
8661
|
-
});
|
|
8662
|
-
this.subscribeToStreamingChannel("orchestrion:ai-sdk:Agent.generate", {
|
|
8663
|
-
name: "Agent.generate",
|
|
8664
|
-
type: "llm" /* LLM */,
|
|
8665
|
-
extractInput: (args) => {
|
|
8666
|
-
const params = args[0] || {};
|
|
8667
|
-
return {
|
|
8668
|
-
input: processAISDKInput(params),
|
|
8669
|
-
metadata: extractMetadataFromParams(params)
|
|
8670
|
-
};
|
|
8671
|
-
},
|
|
8672
|
-
extractOutput: (result) => {
|
|
8673
|
-
return processAISDKOutput(result, denyOutputPaths);
|
|
8674
|
-
},
|
|
8675
|
-
extractMetrics: (result, startTime) => {
|
|
8676
|
-
const metrics = extractTokenMetrics(result);
|
|
8677
|
-
if (startTime) {
|
|
8678
|
-
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
8679
|
-
}
|
|
8680
|
-
return metrics;
|
|
8681
|
-
},
|
|
8682
|
-
aggregateChunks: aggregateAISDKChunks
|
|
8683
|
-
});
|
|
8684
|
-
this.subscribeToStreamingChannel("orchestrion:ai-sdk:Agent.stream", {
|
|
8685
|
-
name: "Agent.stream",
|
|
8686
|
-
type: "llm" /* LLM */,
|
|
8687
|
-
extractInput: (args) => {
|
|
8688
|
-
const params = args[0] || {};
|
|
8689
|
-
return {
|
|
8690
|
-
input: processAISDKInput(params),
|
|
8691
|
-
metadata: extractMetadataFromParams(params)
|
|
8692
|
-
};
|
|
8693
|
-
},
|
|
8694
|
-
extractOutput: (result) => {
|
|
8695
|
-
return processAISDKOutput(result, denyOutputPaths);
|
|
8696
|
-
},
|
|
8697
|
-
extractMetrics: (result, startTime) => {
|
|
8698
|
-
const metrics = extractTokenMetrics(result);
|
|
8699
|
-
if (startTime) {
|
|
8700
|
-
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
8701
|
-
}
|
|
8702
|
-
return metrics;
|
|
8703
|
-
},
|
|
8704
|
-
aggregateChunks: aggregateAISDKChunks
|
|
8705
|
-
});
|
|
8706
|
-
}
|
|
8707
|
-
/**
|
|
8708
|
-
* Subscribe to a channel for async methods that may return streams.
|
|
8709
|
-
* Handles both streaming and non-streaming responses.
|
|
8710
|
-
*/
|
|
8711
|
-
subscribeToStreamingChannel(channelName, config) {
|
|
8712
|
-
const channel = (0, import_dc_browser3.tracingChannel)(channelName);
|
|
8713
|
-
const spans = /* @__PURE__ */ new WeakMap();
|
|
8714
|
-
const handlers = {
|
|
8715
|
-
start: (event) => {
|
|
8716
|
-
const span = startSpan({
|
|
8717
|
-
name: config.name,
|
|
8718
|
-
spanAttributes: {
|
|
8719
|
-
type: config.type
|
|
9269
|
+
this.unsubscribers.push(
|
|
9270
|
+
traceStreamingChannel(aiSDKChannels.generateText, {
|
|
9271
|
+
name: "generateText",
|
|
9272
|
+
type: "llm" /* LLM */,
|
|
9273
|
+
extractInput: ([params]) => {
|
|
9274
|
+
return {
|
|
9275
|
+
input: processAISDKInput(params),
|
|
9276
|
+
metadata: extractMetadataFromParams(params)
|
|
9277
|
+
};
|
|
9278
|
+
},
|
|
9279
|
+
extractOutput: (result) => {
|
|
9280
|
+
return processAISDKOutput(result, denyOutputPaths);
|
|
9281
|
+
},
|
|
9282
|
+
extractMetrics: (result, startTime) => {
|
|
9283
|
+
const metrics = extractTokenMetrics(result);
|
|
9284
|
+
if (startTime) {
|
|
9285
|
+
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
8720
9286
|
}
|
|
8721
|
-
|
|
8722
|
-
|
|
8723
|
-
|
|
8724
|
-
|
|
8725
|
-
|
|
8726
|
-
|
|
8727
|
-
|
|
8728
|
-
|
|
8729
|
-
|
|
8730
|
-
|
|
8731
|
-
|
|
8732
|
-
|
|
8733
|
-
|
|
8734
|
-
|
|
8735
|
-
|
|
8736
|
-
|
|
8737
|
-
return;
|
|
8738
|
-
}
|
|
8739
|
-
|
|
8740
|
-
|
|
8741
|
-
|
|
8742
|
-
|
|
8743
|
-
|
|
8744
|
-
|
|
8745
|
-
|
|
8746
|
-
|
|
8747
|
-
|
|
8748
|
-
|
|
8749
|
-
|
|
8750
|
-
|
|
8751
|
-
|
|
8752
|
-
|
|
8753
|
-
|
|
8754
|
-
|
|
8755
|
-
|
|
8756
|
-
|
|
8757
|
-
|
|
8758
|
-
|
|
8759
|
-
|
|
8760
|
-
|
|
8761
|
-
|
|
8762
|
-
|
|
8763
|
-
|
|
8764
|
-
|
|
8765
|
-
|
|
8766
|
-
|
|
8767
|
-
|
|
8768
|
-
|
|
8769
|
-
|
|
8770
|
-
|
|
8771
|
-
|
|
8772
|
-
|
|
8773
|
-
|
|
8774
|
-
|
|
8775
|
-
|
|
8776
|
-
|
|
8777
|
-
|
|
8778
|
-
|
|
8779
|
-
|
|
8780
|
-
|
|
8781
|
-
|
|
8782
|
-
|
|
8783
|
-
|
|
8784
|
-
|
|
8785
|
-
|
|
8786
|
-
|
|
8787
|
-
|
|
8788
|
-
|
|
8789
|
-
spans.delete(event);
|
|
9287
|
+
return metrics;
|
|
9288
|
+
},
|
|
9289
|
+
aggregateChunks: aggregateAISDKChunks
|
|
9290
|
+
})
|
|
9291
|
+
);
|
|
9292
|
+
this.unsubscribers.push(
|
|
9293
|
+
traceStreamingChannel(aiSDKChannels.streamText, {
|
|
9294
|
+
name: "streamText",
|
|
9295
|
+
type: "llm" /* LLM */,
|
|
9296
|
+
extractInput: ([params]) => {
|
|
9297
|
+
return {
|
|
9298
|
+
input: processAISDKInput(params),
|
|
9299
|
+
metadata: extractMetadataFromParams(params)
|
|
9300
|
+
};
|
|
9301
|
+
},
|
|
9302
|
+
extractOutput: (result) => {
|
|
9303
|
+
return processAISDKOutput(result, denyOutputPaths);
|
|
9304
|
+
},
|
|
9305
|
+
extractMetrics: (result, startTime) => {
|
|
9306
|
+
const metrics = extractTokenMetrics(result);
|
|
9307
|
+
if (startTime) {
|
|
9308
|
+
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
9309
|
+
}
|
|
9310
|
+
return metrics;
|
|
9311
|
+
},
|
|
9312
|
+
aggregateChunks: aggregateAISDKChunks
|
|
9313
|
+
})
|
|
9314
|
+
);
|
|
9315
|
+
this.unsubscribers.push(
|
|
9316
|
+
traceStreamingChannel(aiSDKChannels.generateObject, {
|
|
9317
|
+
name: "generateObject",
|
|
9318
|
+
type: "llm" /* LLM */,
|
|
9319
|
+
extractInput: ([params]) => {
|
|
9320
|
+
return {
|
|
9321
|
+
input: processAISDKInput(params),
|
|
9322
|
+
metadata: extractMetadataFromParams(params)
|
|
9323
|
+
};
|
|
9324
|
+
},
|
|
9325
|
+
extractOutput: (result) => {
|
|
9326
|
+
return processAISDKOutput(result, denyOutputPaths);
|
|
9327
|
+
},
|
|
9328
|
+
extractMetrics: (result, startTime) => {
|
|
9329
|
+
const metrics = extractTokenMetrics(result);
|
|
9330
|
+
if (startTime) {
|
|
9331
|
+
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
9332
|
+
}
|
|
9333
|
+
return metrics;
|
|
9334
|
+
},
|
|
9335
|
+
aggregateChunks: aggregateAISDKChunks
|
|
9336
|
+
})
|
|
9337
|
+
);
|
|
9338
|
+
this.unsubscribers.push(
|
|
9339
|
+
traceStreamingChannel(aiSDKChannels.streamObject, {
|
|
9340
|
+
name: "streamObject",
|
|
9341
|
+
type: "llm" /* LLM */,
|
|
9342
|
+
extractInput: ([params]) => {
|
|
9343
|
+
return {
|
|
9344
|
+
input: processAISDKInput(params),
|
|
9345
|
+
metadata: extractMetadataFromParams(params)
|
|
9346
|
+
};
|
|
9347
|
+
},
|
|
9348
|
+
extractOutput: (result) => {
|
|
9349
|
+
return processAISDKOutput(result, denyOutputPaths);
|
|
9350
|
+
},
|
|
9351
|
+
extractMetrics: (result, startTime) => {
|
|
9352
|
+
const metrics = extractTokenMetrics(result);
|
|
9353
|
+
if (startTime) {
|
|
9354
|
+
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
8790
9355
|
}
|
|
8791
|
-
|
|
8792
|
-
|
|
8793
|
-
|
|
8794
|
-
|
|
8795
|
-
|
|
8796
|
-
|
|
8797
|
-
|
|
8798
|
-
|
|
8799
|
-
|
|
8800
|
-
|
|
8801
|
-
|
|
8802
|
-
|
|
8803
|
-
|
|
8804
|
-
|
|
8805
|
-
|
|
8806
|
-
|
|
8807
|
-
|
|
8808
|
-
|
|
8809
|
-
|
|
9356
|
+
return metrics;
|
|
9357
|
+
},
|
|
9358
|
+
aggregateChunks: aggregateAISDKChunks
|
|
9359
|
+
})
|
|
9360
|
+
);
|
|
9361
|
+
this.unsubscribers.push(
|
|
9362
|
+
traceStreamingChannel(aiSDKChannels.agentGenerate, {
|
|
9363
|
+
name: "Agent.generate",
|
|
9364
|
+
type: "llm" /* LLM */,
|
|
9365
|
+
extractInput: ([params]) => {
|
|
9366
|
+
return {
|
|
9367
|
+
input: processAISDKInput(params),
|
|
9368
|
+
metadata: extractMetadataFromParams(params)
|
|
9369
|
+
};
|
|
9370
|
+
},
|
|
9371
|
+
extractOutput: (result) => {
|
|
9372
|
+
return processAISDKOutput(result, denyOutputPaths);
|
|
9373
|
+
},
|
|
9374
|
+
extractMetrics: (result, startTime) => {
|
|
9375
|
+
const metrics = extractTokenMetrics(result);
|
|
9376
|
+
if (startTime) {
|
|
9377
|
+
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
9378
|
+
}
|
|
9379
|
+
return metrics;
|
|
9380
|
+
},
|
|
9381
|
+
aggregateChunks: aggregateAISDKChunks
|
|
9382
|
+
})
|
|
9383
|
+
);
|
|
9384
|
+
this.unsubscribers.push(
|
|
9385
|
+
traceStreamingChannel(aiSDKChannels.agentStream, {
|
|
9386
|
+
name: "Agent.stream",
|
|
9387
|
+
type: "llm" /* LLM */,
|
|
9388
|
+
extractInput: ([params]) => {
|
|
9389
|
+
return {
|
|
9390
|
+
input: processAISDKInput(params),
|
|
9391
|
+
metadata: extractMetadataFromParams(params)
|
|
9392
|
+
};
|
|
9393
|
+
},
|
|
9394
|
+
extractOutput: (result) => {
|
|
9395
|
+
return processAISDKOutput(result, denyOutputPaths);
|
|
9396
|
+
},
|
|
9397
|
+
extractMetrics: (result, startTime) => {
|
|
9398
|
+
const metrics = extractTokenMetrics(result);
|
|
9399
|
+
if (startTime) {
|
|
9400
|
+
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
9401
|
+
}
|
|
9402
|
+
return metrics;
|
|
9403
|
+
},
|
|
9404
|
+
aggregateChunks: aggregateAISDKChunks
|
|
9405
|
+
})
|
|
9406
|
+
);
|
|
8810
9407
|
}
|
|
8811
9408
|
};
|
|
8812
9409
|
function processAISDKInput(params) {
|
|
@@ -9048,7 +9645,10 @@ function omitAtPath(obj, keys) {
|
|
|
9048
9645
|
if (Array.isArray(obj)) {
|
|
9049
9646
|
obj.forEach((item) => {
|
|
9050
9647
|
if (remainingKeys.length > 0) {
|
|
9051
|
-
omitAtPath(
|
|
9648
|
+
omitAtPath(
|
|
9649
|
+
item,
|
|
9650
|
+
remainingKeys
|
|
9651
|
+
);
|
|
9052
9652
|
}
|
|
9053
9653
|
});
|
|
9054
9654
|
}
|
|
@@ -9058,7 +9658,10 @@ function omitAtPath(obj, keys) {
|
|
|
9058
9658
|
}
|
|
9059
9659
|
} else {
|
|
9060
9660
|
if (obj && typeof obj === "object" && firstKey in obj) {
|
|
9061
|
-
omitAtPath(
|
|
9661
|
+
omitAtPath(
|
|
9662
|
+
obj[firstKey],
|
|
9663
|
+
remainingKeys
|
|
9664
|
+
);
|
|
9062
9665
|
}
|
|
9063
9666
|
}
|
|
9064
9667
|
}
|
|
@@ -9071,8 +9674,18 @@ function omit(obj, paths) {
|
|
|
9071
9674
|
return result;
|
|
9072
9675
|
}
|
|
9073
9676
|
|
|
9677
|
+
// src/instrumentation/plugins/claude-agent-sdk-channels.ts
|
|
9678
|
+
var claudeAgentSDKChannels = defineChannels(
|
|
9679
|
+
"@anthropic-ai/claude-agent-sdk",
|
|
9680
|
+
{
|
|
9681
|
+
query: channel({
|
|
9682
|
+
channelName: "query",
|
|
9683
|
+
kind: "async"
|
|
9684
|
+
})
|
|
9685
|
+
}
|
|
9686
|
+
);
|
|
9687
|
+
|
|
9074
9688
|
// src/instrumentation/plugins/claude-agent-sdk-plugin.ts
|
|
9075
|
-
var import_dc_browser4 = require("dc-browser");
|
|
9076
9689
|
function filterSerializableOptions(options) {
|
|
9077
9690
|
const allowedKeys = [
|
|
9078
9691
|
"model",
|
|
@@ -9156,7 +9769,9 @@ async function createLLMSpanForMessages(messages, prompt, conversationHistory, o
|
|
|
9156
9769
|
const input = buildLLMInput(prompt, conversationHistory);
|
|
9157
9770
|
const outputs = messages.map(
|
|
9158
9771
|
(m) => m.message?.content && m.message?.role ? { content: m.message.content, role: m.message.role } : void 0
|
|
9159
|
-
).filter(
|
|
9772
|
+
).filter(
|
|
9773
|
+
(c) => c !== void 0
|
|
9774
|
+
);
|
|
9160
9775
|
const span = startSpan({
|
|
9161
9776
|
name: "anthropic.messages.create",
|
|
9162
9777
|
spanAttributes: {
|
|
@@ -9175,7 +9790,6 @@ async function createLLMSpanForMessages(messages, prompt, conversationHistory, o
|
|
|
9175
9790
|
return lastMessage.message?.content && lastMessage.message?.role ? { content: lastMessage.message.content, role: lastMessage.message.role } : void 0;
|
|
9176
9791
|
}
|
|
9177
9792
|
var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
9178
|
-
unsubscribers = [];
|
|
9179
9793
|
onEnable() {
|
|
9180
9794
|
this.subscribeToQuery();
|
|
9181
9795
|
}
|
|
@@ -9191,12 +9805,13 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
9191
9805
|
* and individual LLM calls.
|
|
9192
9806
|
*/
|
|
9193
9807
|
subscribeToQuery() {
|
|
9194
|
-
const
|
|
9808
|
+
const channel2 = claudeAgentSDKChannels.query.tracingChannel();
|
|
9195
9809
|
const spans = /* @__PURE__ */ new WeakMap();
|
|
9196
9810
|
const handlers = {
|
|
9197
9811
|
start: (event) => {
|
|
9198
|
-
const params = event.arguments[0]
|
|
9199
|
-
const
|
|
9812
|
+
const params = event.arguments[0];
|
|
9813
|
+
const prompt = params?.prompt;
|
|
9814
|
+
const options = params?.options ?? {};
|
|
9200
9815
|
const span = startSpan({
|
|
9201
9816
|
name: "Claude Agent",
|
|
9202
9817
|
spanAttributes: {
|
|
@@ -9208,7 +9823,7 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
9208
9823
|
span.log({
|
|
9209
9824
|
input: typeof prompt === "string" ? prompt : {
|
|
9210
9825
|
type: "streaming",
|
|
9211
|
-
description: "AsyncIterable<
|
|
9826
|
+
description: "AsyncIterable<ClaudeAgentSDKMessage>"
|
|
9212
9827
|
},
|
|
9213
9828
|
metadata: filterSerializableOptions(options)
|
|
9214
9829
|
});
|
|
@@ -9230,12 +9845,19 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
9230
9845
|
if (!spanData) {
|
|
9231
9846
|
return;
|
|
9232
9847
|
}
|
|
9233
|
-
|
|
9234
|
-
|
|
9848
|
+
const eventResult = event.result;
|
|
9849
|
+
if (eventResult === void 0) {
|
|
9850
|
+
spanData.span.end();
|
|
9851
|
+
spans.delete(event);
|
|
9852
|
+
return;
|
|
9853
|
+
}
|
|
9854
|
+
if (isAsyncIterable(eventResult)) {
|
|
9855
|
+
patchStreamIfNeeded(eventResult, {
|
|
9235
9856
|
onChunk: async (message) => {
|
|
9236
9857
|
const currentTime = getCurrentUnixTimestamp();
|
|
9237
9858
|
const params = event.arguments[0];
|
|
9238
|
-
const
|
|
9859
|
+
const prompt = params?.prompt;
|
|
9860
|
+
const options = params?.options ?? {};
|
|
9239
9861
|
const messageId = message.message?.id;
|
|
9240
9862
|
if (messageId && messageId !== spanData.currentMessageId) {
|
|
9241
9863
|
if (spanData.currentMessages.length > 0) {
|
|
@@ -9294,7 +9916,8 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
9294
9916
|
onComplete: async () => {
|
|
9295
9917
|
try {
|
|
9296
9918
|
const params = event.arguments[0];
|
|
9297
|
-
const
|
|
9919
|
+
const prompt = params?.prompt;
|
|
9920
|
+
const options = params?.options ?? {};
|
|
9298
9921
|
if (spanData.currentMessages.length > 0) {
|
|
9299
9922
|
const finalMessage = await createLLMSpanForMessages(
|
|
9300
9923
|
spanData.currentMessages,
|
|
@@ -9332,7 +9955,7 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
9332
9955
|
} else {
|
|
9333
9956
|
try {
|
|
9334
9957
|
spanData.span.log({
|
|
9335
|
-
output:
|
|
9958
|
+
output: eventResult
|
|
9336
9959
|
});
|
|
9337
9960
|
} catch (error) {
|
|
9338
9961
|
console.error(
|
|
@@ -9347,7 +9970,7 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
9347
9970
|
},
|
|
9348
9971
|
error: (event) => {
|
|
9349
9972
|
const spanData = spans.get(event);
|
|
9350
|
-
if (!spanData) {
|
|
9973
|
+
if (!spanData || !event.error) {
|
|
9351
9974
|
return;
|
|
9352
9975
|
}
|
|
9353
9976
|
const { span } = spanData;
|
|
@@ -9358,53 +9981,39 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
9358
9981
|
spans.delete(event);
|
|
9359
9982
|
}
|
|
9360
9983
|
};
|
|
9361
|
-
|
|
9984
|
+
channel2.subscribe(handlers);
|
|
9362
9985
|
this.unsubscribers.push(() => {
|
|
9363
|
-
|
|
9986
|
+
channel2.unsubscribe(handlers);
|
|
9364
9987
|
});
|
|
9365
9988
|
}
|
|
9366
9989
|
};
|
|
9367
9990
|
|
|
9991
|
+
// src/instrumentation/plugins/google-genai-channels.ts
|
|
9992
|
+
var googleGenAIChannels = defineChannels("@google/genai", {
|
|
9993
|
+
generateContent: channel({
|
|
9994
|
+
channelName: "models.generateContent",
|
|
9995
|
+
kind: "async"
|
|
9996
|
+
}),
|
|
9997
|
+
generateContentStream: channel({
|
|
9998
|
+
channelName: "models.generateContentStream",
|
|
9999
|
+
kind: "async"
|
|
10000
|
+
})
|
|
10001
|
+
});
|
|
10002
|
+
|
|
9368
10003
|
// src/instrumentation/plugins/google-genai-plugin.ts
|
|
9369
|
-
var import_dc_browser5 = require("dc-browser");
|
|
9370
10004
|
var GoogleGenAIPlugin = class extends BasePlugin {
|
|
9371
|
-
unsubscribers = [];
|
|
9372
10005
|
onEnable() {
|
|
9373
10006
|
this.subscribeToGoogleGenAIChannels();
|
|
9374
10007
|
}
|
|
9375
10008
|
onDisable() {
|
|
9376
|
-
|
|
9377
|
-
unsubscribe();
|
|
9378
|
-
}
|
|
9379
|
-
this.unsubscribers = [];
|
|
10009
|
+
this.unsubscribers = unsubscribeAll(this.unsubscribers);
|
|
9380
10010
|
}
|
|
9381
10011
|
subscribeToGoogleGenAIChannels() {
|
|
9382
|
-
this.
|
|
9383
|
-
|
|
9384
|
-
|
|
9385
|
-
extractInput: (args) => {
|
|
9386
|
-
const params = args[0] || {};
|
|
9387
|
-
const input = serializeInput(params);
|
|
9388
|
-
const metadata = extractMetadata(params);
|
|
9389
|
-
return {
|
|
9390
|
-
input,
|
|
9391
|
-
metadata: { ...metadata, provider: "google-genai" }
|
|
9392
|
-
};
|
|
9393
|
-
},
|
|
9394
|
-
extractOutput: (result) => {
|
|
9395
|
-
return result;
|
|
9396
|
-
},
|
|
9397
|
-
extractMetrics: (result, startTime) => {
|
|
9398
|
-
return extractGenerateContentMetrics(result, startTime);
|
|
9399
|
-
}
|
|
9400
|
-
});
|
|
9401
|
-
this.subscribeToGoogleStreamingChannel(
|
|
9402
|
-
"orchestrion:google-genai:models.generateContentStream",
|
|
9403
|
-
{
|
|
9404
|
-
name: "google-genai.generateContentStream",
|
|
10012
|
+
this.unsubscribers.push(
|
|
10013
|
+
traceAsyncChannel(googleGenAIChannels.generateContent, {
|
|
10014
|
+
name: "google-genai.generateContent",
|
|
9405
10015
|
type: "llm" /* LLM */,
|
|
9406
|
-
extractInput: (
|
|
9407
|
-
const params = args[0] || {};
|
|
10016
|
+
extractInput: ([params]) => {
|
|
9408
10017
|
const input = serializeInput(params);
|
|
9409
10018
|
const metadata = extractMetadata(params);
|
|
9410
10019
|
return {
|
|
@@ -9412,150 +10021,37 @@ var GoogleGenAIPlugin = class extends BasePlugin {
|
|
|
9412
10021
|
metadata: { ...metadata, provider: "google-genai" }
|
|
9413
10022
|
};
|
|
9414
10023
|
},
|
|
9415
|
-
|
|
9416
|
-
|
|
9417
|
-
|
|
9418
|
-
|
|
9419
|
-
|
|
9420
|
-
const channel = (0, import_dc_browser5.tracingChannel)(channelName);
|
|
9421
|
-
const spans = /* @__PURE__ */ new WeakMap();
|
|
9422
|
-
const handlers = {
|
|
9423
|
-
start: (event) => {
|
|
9424
|
-
const span = startSpan({
|
|
9425
|
-
name: config.name,
|
|
9426
|
-
spanAttributes: {
|
|
9427
|
-
type: config.type
|
|
9428
|
-
}
|
|
9429
|
-
});
|
|
9430
|
-
const startTime = getCurrentUnixTimestamp();
|
|
9431
|
-
spans.set(event, { span, startTime });
|
|
9432
|
-
try {
|
|
9433
|
-
const { input, metadata } = config.extractInput(event.arguments);
|
|
9434
|
-
span.log({
|
|
9435
|
-
input,
|
|
9436
|
-
metadata
|
|
9437
|
-
});
|
|
9438
|
-
} catch (error) {
|
|
9439
|
-
console.error(`Error extracting input for ${channelName}:`, error);
|
|
9440
|
-
}
|
|
9441
|
-
},
|
|
9442
|
-
asyncEnd: (event) => {
|
|
9443
|
-
const spanData = spans.get(event);
|
|
9444
|
-
if (!spanData) {
|
|
9445
|
-
return;
|
|
9446
|
-
}
|
|
9447
|
-
const { span, startTime } = spanData;
|
|
9448
|
-
try {
|
|
9449
|
-
const output = config.extractOutput(event.result);
|
|
9450
|
-
const metrics = config.extractMetrics(event.result, startTime);
|
|
9451
|
-
span.log({
|
|
9452
|
-
output,
|
|
9453
|
-
metrics
|
|
9454
|
-
});
|
|
9455
|
-
} catch (error) {
|
|
9456
|
-
console.error(`Error extracting output for ${channelName}:`, error);
|
|
9457
|
-
} finally {
|
|
9458
|
-
span.end();
|
|
9459
|
-
spans.delete(event);
|
|
9460
|
-
}
|
|
9461
|
-
},
|
|
9462
|
-
error: (event) => {
|
|
9463
|
-
const spanData = spans.get(event);
|
|
9464
|
-
if (!spanData) {
|
|
9465
|
-
return;
|
|
10024
|
+
extractOutput: (result) => {
|
|
10025
|
+
return result;
|
|
10026
|
+
},
|
|
10027
|
+
extractMetrics: (result, startTime) => {
|
|
10028
|
+
return extractGenerateContentMetrics(result, startTime);
|
|
9466
10029
|
}
|
|
9467
|
-
|
|
9468
|
-
|
|
9469
|
-
|
|
9470
|
-
|
|
9471
|
-
|
|
9472
|
-
|
|
9473
|
-
|
|
9474
|
-
|
|
9475
|
-
|
|
9476
|
-
|
|
9477
|
-
channel.unsubscribe(handlers);
|
|
9478
|
-
});
|
|
9479
|
-
}
|
|
9480
|
-
subscribeToGoogleStreamingChannel(channelName, config) {
|
|
9481
|
-
const channel = (0, import_dc_browser5.tracingChannel)(channelName);
|
|
9482
|
-
const spans = /* @__PURE__ */ new WeakMap();
|
|
9483
|
-
const handlers = {
|
|
9484
|
-
start: (event) => {
|
|
9485
|
-
const span = startSpan({
|
|
9486
|
-
name: config.name,
|
|
9487
|
-
spanAttributes: {
|
|
9488
|
-
type: config.type
|
|
9489
|
-
}
|
|
9490
|
-
});
|
|
9491
|
-
const startTime = getCurrentUnixTimestamp();
|
|
9492
|
-
spans.set(event, { span, startTime });
|
|
9493
|
-
try {
|
|
9494
|
-
const { input, metadata } = config.extractInput(event.arguments);
|
|
9495
|
-
span.log({
|
|
10030
|
+
})
|
|
10031
|
+
);
|
|
10032
|
+
this.unsubscribers.push(
|
|
10033
|
+
traceStreamingChannel(googleGenAIChannels.generateContentStream, {
|
|
10034
|
+
name: "google-genai.generateContentStream",
|
|
10035
|
+
type: "llm" /* LLM */,
|
|
10036
|
+
extractInput: ([params]) => {
|
|
10037
|
+
const input = serializeInput(params);
|
|
10038
|
+
const metadata = extractMetadata(params);
|
|
10039
|
+
return {
|
|
9496
10040
|
input,
|
|
9497
|
-
metadata
|
|
9498
|
-
}
|
|
9499
|
-
}
|
|
9500
|
-
|
|
9501
|
-
|
|
9502
|
-
|
|
9503
|
-
|
|
9504
|
-
|
|
9505
|
-
|
|
9506
|
-
|
|
9507
|
-
|
|
9508
|
-
const { span, startTime } = spanData;
|
|
9509
|
-
if (isAsyncIterable(event.result)) {
|
|
9510
|
-
patchStreamIfNeeded(event.result, {
|
|
9511
|
-
onComplete: (chunks) => {
|
|
9512
|
-
try {
|
|
9513
|
-
const { output, metrics } = config.aggregateChunks(
|
|
9514
|
-
chunks,
|
|
9515
|
-
startTime
|
|
9516
|
-
);
|
|
9517
|
-
span.log({
|
|
9518
|
-
output,
|
|
9519
|
-
metrics
|
|
9520
|
-
});
|
|
9521
|
-
} catch (error) {
|
|
9522
|
-
console.error(
|
|
9523
|
-
`Error extracting output for ${channelName}:`,
|
|
9524
|
-
error
|
|
9525
|
-
);
|
|
9526
|
-
} finally {
|
|
9527
|
-
span.end();
|
|
9528
|
-
}
|
|
9529
|
-
},
|
|
9530
|
-
onError: (error) => {
|
|
9531
|
-
span.log({
|
|
9532
|
-
error: error.message
|
|
9533
|
-
});
|
|
9534
|
-
span.end();
|
|
9535
|
-
}
|
|
9536
|
-
});
|
|
9537
|
-
} else {
|
|
9538
|
-
span.end();
|
|
9539
|
-
spans.delete(event);
|
|
9540
|
-
}
|
|
9541
|
-
},
|
|
9542
|
-
error: (event) => {
|
|
9543
|
-
const spanData = spans.get(event);
|
|
9544
|
-
if (!spanData) {
|
|
9545
|
-
return;
|
|
10041
|
+
metadata: { ...metadata, provider: "google-genai" }
|
|
10042
|
+
};
|
|
10043
|
+
},
|
|
10044
|
+
extractOutput: (result) => {
|
|
10045
|
+
return result;
|
|
10046
|
+
},
|
|
10047
|
+
extractMetrics: () => {
|
|
10048
|
+
return {};
|
|
10049
|
+
},
|
|
10050
|
+
aggregateChunks: (chunks, _result, _endEvent, startTime) => {
|
|
10051
|
+
return aggregateGenerateContentChunks(chunks, startTime);
|
|
9546
10052
|
}
|
|
9547
|
-
|
|
9548
|
-
|
|
9549
|
-
error: event.error.message
|
|
9550
|
-
});
|
|
9551
|
-
span.end();
|
|
9552
|
-
spans.delete(event);
|
|
9553
|
-
}
|
|
9554
|
-
};
|
|
9555
|
-
channel.subscribe(handlers);
|
|
9556
|
-
this.unsubscribers.push(() => {
|
|
9557
|
-
channel.unsubscribe(handlers);
|
|
9558
|
-
});
|
|
10053
|
+
})
|
|
10054
|
+
);
|
|
9559
10055
|
}
|
|
9560
10056
|
};
|
|
9561
10057
|
function serializeInput(params) {
|
|
@@ -9611,8 +10107,12 @@ function serializePart(part) {
|
|
|
9611
10107
|
const buffer = typeof data === "string" ? typeof Buffer !== "undefined" ? Buffer.from(data, "base64") : new Uint8Array(
|
|
9612
10108
|
atob(data).split("").map((c) => c.charCodeAt(0))
|
|
9613
10109
|
) : typeof Buffer !== "undefined" ? Buffer.from(data) : new Uint8Array(data);
|
|
10110
|
+
const arrayBuffer = buffer instanceof Uint8Array ? buffer.buffer.slice(
|
|
10111
|
+
buffer.byteOffset,
|
|
10112
|
+
buffer.byteOffset + buffer.byteLength
|
|
10113
|
+
) : buffer;
|
|
9614
10114
|
const attachment = new Attachment({
|
|
9615
|
-
data:
|
|
10115
|
+
data: arrayBuffer,
|
|
9616
10116
|
filename,
|
|
9617
10117
|
contentType: mimeType || "application/octet-stream"
|
|
9618
10118
|
});
|
|
@@ -9661,33 +10161,36 @@ function extractGenerateContentMetrics(response, startTime) {
|
|
|
9661
10161
|
const end = getCurrentUnixTimestamp();
|
|
9662
10162
|
metrics.duration = end - startTime;
|
|
9663
10163
|
}
|
|
9664
|
-
if (response
|
|
9665
|
-
|
|
9666
|
-
if (usage.promptTokenCount !== void 0) {
|
|
9667
|
-
metrics.prompt_tokens = usage.promptTokenCount;
|
|
9668
|
-
}
|
|
9669
|
-
if (usage.candidatesTokenCount !== void 0) {
|
|
9670
|
-
metrics.completion_tokens = usage.candidatesTokenCount;
|
|
9671
|
-
}
|
|
9672
|
-
if (usage.totalTokenCount !== void 0) {
|
|
9673
|
-
metrics.tokens = usage.totalTokenCount;
|
|
9674
|
-
}
|
|
9675
|
-
if (usage.cachedContentTokenCount !== void 0) {
|
|
9676
|
-
metrics.prompt_cached_tokens = usage.cachedContentTokenCount;
|
|
9677
|
-
}
|
|
9678
|
-
if (usage.thoughtsTokenCount !== void 0) {
|
|
9679
|
-
metrics.completion_reasoning_tokens = usage.thoughtsTokenCount;
|
|
9680
|
-
}
|
|
10164
|
+
if (response?.usageMetadata) {
|
|
10165
|
+
populateUsageMetrics(metrics, response.usageMetadata);
|
|
9681
10166
|
}
|
|
9682
10167
|
return metrics;
|
|
9683
10168
|
}
|
|
10169
|
+
function populateUsageMetrics(metrics, usage) {
|
|
10170
|
+
if (usage.promptTokenCount !== void 0) {
|
|
10171
|
+
metrics.prompt_tokens = usage.promptTokenCount;
|
|
10172
|
+
}
|
|
10173
|
+
if (usage.candidatesTokenCount !== void 0) {
|
|
10174
|
+
metrics.completion_tokens = usage.candidatesTokenCount;
|
|
10175
|
+
}
|
|
10176
|
+
if (usage.totalTokenCount !== void 0) {
|
|
10177
|
+
metrics.tokens = usage.totalTokenCount;
|
|
10178
|
+
}
|
|
10179
|
+
if (usage.cachedContentTokenCount !== void 0) {
|
|
10180
|
+
metrics.prompt_cached_tokens = usage.cachedContentTokenCount;
|
|
10181
|
+
}
|
|
10182
|
+
if (usage.thoughtsTokenCount !== void 0) {
|
|
10183
|
+
metrics.completion_reasoning_tokens = usage.thoughtsTokenCount;
|
|
10184
|
+
}
|
|
10185
|
+
}
|
|
9684
10186
|
function aggregateGenerateContentChunks(chunks, startTime) {
|
|
9685
|
-
const
|
|
9686
|
-
|
|
9687
|
-
|
|
9688
|
-
|
|
10187
|
+
const metrics = {};
|
|
10188
|
+
if (startTime !== void 0) {
|
|
10189
|
+
const end = getCurrentUnixTimestamp();
|
|
10190
|
+
metrics.duration = end - startTime;
|
|
10191
|
+
}
|
|
9689
10192
|
let firstTokenTime = null;
|
|
9690
|
-
if (chunks.length > 0 && firstTokenTime === null) {
|
|
10193
|
+
if (chunks.length > 0 && firstTokenTime === null && startTime !== void 0) {
|
|
9691
10194
|
firstTokenTime = getCurrentUnixTimestamp();
|
|
9692
10195
|
metrics.time_to_first_token = firstTokenTime - startTime;
|
|
9693
10196
|
}
|
|
@@ -9758,21 +10261,7 @@ function aggregateGenerateContentChunks(chunks, startTime) {
|
|
|
9758
10261
|
}
|
|
9759
10262
|
if (usageMetadata) {
|
|
9760
10263
|
output.usageMetadata = usageMetadata;
|
|
9761
|
-
|
|
9762
|
-
metrics.prompt_tokens = usageMetadata.promptTokenCount;
|
|
9763
|
-
}
|
|
9764
|
-
if (usageMetadata.candidatesTokenCount !== void 0) {
|
|
9765
|
-
metrics.completion_tokens = usageMetadata.candidatesTokenCount;
|
|
9766
|
-
}
|
|
9767
|
-
if (usageMetadata.totalTokenCount !== void 0) {
|
|
9768
|
-
metrics.tokens = usageMetadata.totalTokenCount;
|
|
9769
|
-
}
|
|
9770
|
-
if (usageMetadata.cachedContentTokenCount !== void 0) {
|
|
9771
|
-
metrics.prompt_cached_tokens = usageMetadata.cachedContentTokenCount;
|
|
9772
|
-
}
|
|
9773
|
-
if (usageMetadata.thoughtsTokenCount !== void 0) {
|
|
9774
|
-
metrics.completion_reasoning_tokens = usageMetadata.thoughtsTokenCount;
|
|
9775
|
-
}
|
|
10264
|
+
populateUsageMetrics(metrics, usageMetadata);
|
|
9776
10265
|
}
|
|
9777
10266
|
if (text) {
|
|
9778
10267
|
output.text = text;
|
|
@@ -9784,7 +10273,8 @@ function tryToDict(obj) {
|
|
|
9784
10273
|
return null;
|
|
9785
10274
|
}
|
|
9786
10275
|
if (typeof obj === "object") {
|
|
9787
|
-
if (
|
|
10276
|
+
if ("toJSON" in obj && // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
10277
|
+
typeof obj.toJSON === "function") {
|
|
9788
10278
|
return obj.toJSON();
|
|
9789
10279
|
}
|
|
9790
10280
|
return obj;
|