braintrust 3.7.0 → 3.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/dev/dist/index.d.mts +144 -2
- package/dev/dist/index.d.ts +144 -2
- package/dev/dist/index.js +3322 -799
- package/dev/dist/index.mjs +3214 -691
- package/dist/auto-instrumentations/bundler/esbuild.cjs +377 -13
- package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
- package/dist/auto-instrumentations/bundler/rollup.cjs +377 -13
- package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
- package/dist/auto-instrumentations/bundler/vite.cjs +377 -13
- package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
- package/dist/auto-instrumentations/bundler/webpack-loader.cjs +377 -13
- package/dist/auto-instrumentations/bundler/webpack-loader.d.ts +11 -9
- package/dist/auto-instrumentations/bundler/webpack.cjs +377 -13
- package/dist/auto-instrumentations/bundler/webpack.mjs +2 -2
- package/dist/auto-instrumentations/{chunk-EVUKFMHG.mjs → chunk-ITP7RAUY.mjs} +21 -3
- package/dist/auto-instrumentations/{chunk-ZK2IYER2.mjs → chunk-MD7W27YH.mjs} +5 -1
- package/dist/auto-instrumentations/{chunk-AKEXR4AL.mjs → chunk-OLBMPZXE.mjs} +378 -14
- package/dist/auto-instrumentations/{chunk-VLEJ5AEK.mjs → chunk-P5YLNB2A.mjs} +21 -3
- package/dist/auto-instrumentations/hook.mjs +393 -19
- package/dist/auto-instrumentations/index.cjs +379 -13
- package/dist/auto-instrumentations/index.d.mts +5 -1
- package/dist/auto-instrumentations/index.d.ts +5 -1
- package/dist/auto-instrumentations/index.mjs +5 -1
- package/dist/auto-instrumentations/loader/cjs-patch.cjs +34 -6
- package/dist/auto-instrumentations/loader/cjs-patch.d.mts +1 -0
- package/dist/auto-instrumentations/loader/cjs-patch.d.ts +1 -0
- package/dist/auto-instrumentations/loader/cjs-patch.mjs +15 -5
- package/dist/auto-instrumentations/loader/esm-hook.mjs +8 -3
- package/dist/auto-instrumentations/loader/get-package-version.cjs +20 -2
- package/dist/auto-instrumentations/loader/get-package-version.mjs +1 -1
- package/dist/browser.d.mts +199 -44
- package/dist/browser.d.ts +199 -44
- package/dist/browser.js +7086 -6747
- package/dist/browser.mjs +7086 -6747
- package/dist/cli.js +3200 -677
- package/dist/edge-light.d.mts +1 -1
- package/dist/edge-light.d.ts +1 -1
- package/dist/edge-light.js +12645 -12215
- package/dist/edge-light.mjs +12645 -12215
- package/dist/index.d.mts +199 -44
- package/dist/index.d.ts +199 -44
- package/dist/index.js +7173 -6834
- package/dist/index.mjs +7022 -6683
- package/dist/instrumentation/index.d.mts +7 -0
- package/dist/instrumentation/index.d.ts +7 -0
- package/dist/instrumentation/index.js +3170 -669
- package/dist/instrumentation/index.mjs +3170 -669
- package/dist/workerd.d.mts +1 -1
- package/dist/workerd.d.ts +1 -1
- package/dist/workerd.js +12645 -12215
- package/dist/workerd.mjs +12645 -12215
- package/package.json +45 -45
package/dist/cli.js
CHANGED
|
@@ -1232,7 +1232,7 @@ var require_package = __commonJS({
|
|
|
1232
1232
|
"package.json"(exports2, module2) {
|
|
1233
1233
|
module2.exports = {
|
|
1234
1234
|
name: "braintrust",
|
|
1235
|
-
version: "3.
|
|
1235
|
+
version: "3.8.0",
|
|
1236
1236
|
description: "SDK for integrating Braintrust",
|
|
1237
1237
|
repository: {
|
|
1238
1238
|
type: "git",
|
|
@@ -1346,7 +1346,7 @@ var require_package = __commonJS({
|
|
|
1346
1346
|
"check:typings": "tsc --noEmit",
|
|
1347
1347
|
watch: "tsup --watch",
|
|
1348
1348
|
clean: "rm -r dist/* && rm -r dev/dist/*",
|
|
1349
|
-
docs: "
|
|
1349
|
+
docs: "typedoc --options typedoc.json src/node/index.ts",
|
|
1350
1350
|
test: 'vitest run --exclude "src/wrappers/**/*.test.ts" --exclude "src/otel/**/*.test.ts" --exclude "smoke/**/*.test.ts" --exclude "src/zod/**/*.test.ts" --exclude "tests/api-compatibility/**"',
|
|
1351
1351
|
"test:core": "pnpm prune && pnpm test",
|
|
1352
1352
|
"test:checks": "pnpm run test:core && pnpm run test:vitest",
|
|
@@ -1374,8 +1374,8 @@ var require_package = __commonJS({
|
|
|
1374
1374
|
"test:claude-agent-sdk": "pnpm --filter @braintrust/claude-agent-sdk-tests test",
|
|
1375
1375
|
"test:vitest": "pnpm --filter @braintrust/vitest-wrapper-tests test",
|
|
1376
1376
|
"test:output": "tsx scripts/test-output.ts --with-comparison --with-metrics --with-progress",
|
|
1377
|
-
bench: "
|
|
1378
|
-
"publish:validate": "./scripts/validate-release.sh && pnpm install --frozen-lockfile && pnpm run build &&
|
|
1377
|
+
bench: "tsx src/queue.bench.ts",
|
|
1378
|
+
"publish:validate": "./scripts/validate-release.sh && pnpm install --frozen-lockfile && pnpm run build && pnpm publish",
|
|
1379
1379
|
lint: "eslint .",
|
|
1380
1380
|
"fix:lint": "eslint --fix .",
|
|
1381
1381
|
playground: "tsx playground.ts",
|
|
@@ -1425,7 +1425,7 @@ var require_package = __commonJS({
|
|
|
1425
1425
|
typescript: "5.4.4",
|
|
1426
1426
|
vite: "^6.4.1",
|
|
1427
1427
|
"vite-tsconfig-paths": "^4.3.2",
|
|
1428
|
-
vitest: "^4.1.
|
|
1428
|
+
vitest: "^4.1.2",
|
|
1429
1429
|
webpack: "^5.97.1",
|
|
1430
1430
|
zod: "^3.25.34"
|
|
1431
1431
|
},
|
|
@@ -1561,7 +1561,7 @@ var DefaultTracingChannel = class {
|
|
|
1561
1561
|
}
|
|
1562
1562
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1563
1563
|
tracePromise(fn, _message, thisArg, ...args) {
|
|
1564
|
-
return
|
|
1564
|
+
return fn.apply(thisArg, args);
|
|
1565
1565
|
}
|
|
1566
1566
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1567
1567
|
traceCallback(fn, _position, _message, thisArg, ...args) {
|
|
@@ -1581,6 +1581,7 @@ var iso = {
|
|
|
1581
1581
|
processOn: (_0, _1) => {
|
|
1582
1582
|
},
|
|
1583
1583
|
basename: (filepath) => filepath.split(/[\\/]/).pop() || filepath,
|
|
1584
|
+
// eslint-disable-next-line no-restricted-properties -- preserving intentional console usage.
|
|
1584
1585
|
writeln: (text) => console.log(text)
|
|
1585
1586
|
};
|
|
1586
1587
|
var isomorph_default = iso;
|
|
@@ -3072,6 +3073,15 @@ var InternalAbortError = class extends Error {
|
|
|
3072
3073
|
this.name = "InternalAbortError";
|
|
3073
3074
|
}
|
|
3074
3075
|
};
|
|
3076
|
+
function filterFrom(record, keys) {
|
|
3077
|
+
const out = {};
|
|
3078
|
+
for (const k of Object.keys(record)) {
|
|
3079
|
+
if (!keys.includes(k)) {
|
|
3080
|
+
out[k] = record[k];
|
|
3081
|
+
}
|
|
3082
|
+
}
|
|
3083
|
+
return out;
|
|
3084
|
+
}
|
|
3075
3085
|
|
|
3076
3086
|
// src/generated_types.ts
|
|
3077
3087
|
var import_v36 = require("zod/v3");
|
|
@@ -3283,6 +3293,16 @@ var NullableSavedFunctionId = import_v36.z.union([
|
|
|
3283
3293
|
}),
|
|
3284
3294
|
import_v36.z.null()
|
|
3285
3295
|
]);
|
|
3296
|
+
var TopicMapGenerationSettings = import_v36.z.object({
|
|
3297
|
+
algorithm: import_v36.z.enum(["hdbscan", "kmeans"]),
|
|
3298
|
+
dimension_reduction: import_v36.z.enum(["umap", "pca", "none"]),
|
|
3299
|
+
sample_size: import_v36.z.number().int().gt(0).optional(),
|
|
3300
|
+
n_clusters: import_v36.z.number().int().gt(0).optional(),
|
|
3301
|
+
min_cluster_size: import_v36.z.number().int().gt(0).optional(),
|
|
3302
|
+
min_samples: import_v36.z.number().int().gt(0).optional(),
|
|
3303
|
+
hierarchy_threshold: import_v36.z.number().int().gt(0).optional(),
|
|
3304
|
+
naming_model: import_v36.z.string().optional()
|
|
3305
|
+
});
|
|
3286
3306
|
var TopicMapData = import_v36.z.object({
|
|
3287
3307
|
type: import_v36.z.literal("topic_map"),
|
|
3288
3308
|
source_facet: import_v36.z.string(),
|
|
@@ -3290,6 +3310,7 @@ var TopicMapData = import_v36.z.object({
|
|
|
3290
3310
|
bundle_key: import_v36.z.string().optional(),
|
|
3291
3311
|
report_key: import_v36.z.string().optional(),
|
|
3292
3312
|
topic_names: import_v36.z.record(import_v36.z.string()).optional(),
|
|
3313
|
+
generation_settings: TopicMapGenerationSettings.optional(),
|
|
3293
3314
|
distance_threshold: import_v36.z.number().optional()
|
|
3294
3315
|
});
|
|
3295
3316
|
var BatchedFacetData = import_v36.z.object({
|
|
@@ -3514,6 +3535,7 @@ var Dataset = import_v36.z.object({
|
|
|
3514
3535
|
created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
|
|
3515
3536
|
deleted_at: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
|
|
3516
3537
|
user_id: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
|
|
3538
|
+
tags: import_v36.z.union([import_v36.z.array(import_v36.z.string()), import_v36.z.null()]).optional(),
|
|
3517
3539
|
metadata: import_v36.z.union([import_v36.z.object({}).partial().passthrough(), import_v36.z.null()]).optional(),
|
|
3518
3540
|
url_slug: import_v36.z.string()
|
|
3519
3541
|
});
|
|
@@ -3596,6 +3618,14 @@ var DatasetEvent = import_v36.z.object({
|
|
|
3596
3618
|
import_v36.z.null()
|
|
3597
3619
|
]).optional()
|
|
3598
3620
|
});
|
|
3621
|
+
var DatasetSnapshot = import_v36.z.object({
|
|
3622
|
+
id: import_v36.z.string().uuid(),
|
|
3623
|
+
dataset_id: import_v36.z.string().uuid(),
|
|
3624
|
+
name: import_v36.z.string(),
|
|
3625
|
+
description: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]),
|
|
3626
|
+
xact_id: import_v36.z.string(),
|
|
3627
|
+
created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()])
|
|
3628
|
+
});
|
|
3599
3629
|
var EnvVar = import_v36.z.object({
|
|
3600
3630
|
id: import_v36.z.string().uuid(),
|
|
3601
3631
|
object_type: import_v36.z.enum(["organization", "project", "function"]),
|
|
@@ -4354,6 +4384,8 @@ var TopicAutomationConfig = import_v36.z.object({
|
|
|
4354
4384
|
scope: import_v36.z.union([SpanScope, TraceScope, GroupScope, import_v36.z.null()]).optional(),
|
|
4355
4385
|
data_scope: TopicAutomationDataScope.optional(),
|
|
4356
4386
|
btql_filter: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
|
|
4387
|
+
rerun_seconds: import_v36.z.union([import_v36.z.number(), import_v36.z.null()]).optional(),
|
|
4388
|
+
relabel_overlap_seconds: import_v36.z.union([import_v36.z.number(), import_v36.z.null()]).optional(),
|
|
4357
4389
|
backfill_time_range: import_v36.z.union([
|
|
4358
4390
|
import_v36.z.string(),
|
|
4359
4391
|
import_v36.z.object({ from: import_v36.z.string(), to: import_v36.z.string() }),
|
|
@@ -4690,7 +4722,8 @@ var User = import_v36.z.object({
|
|
|
4690
4722
|
family_name: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
|
|
4691
4723
|
email: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
|
|
4692
4724
|
avatar_url: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
|
|
4693
|
-
created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional()
|
|
4725
|
+
created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
|
|
4726
|
+
last_active_at: import_v36.z.union([import_v36.z.number(), import_v36.z.null()]).optional()
|
|
4694
4727
|
});
|
|
4695
4728
|
var ViewDataSearch = import_v36.z.union([
|
|
4696
4729
|
import_v36.z.object({
|
|
@@ -5848,6 +5881,15 @@ var BRAINTRUST_CURRENT_SPAN_STORE = Symbol.for(
|
|
|
5848
5881
|
"braintrust.currentSpanStore"
|
|
5849
5882
|
);
|
|
5850
5883
|
var ContextManager = class {
|
|
5884
|
+
/**
|
|
5885
|
+
* Returns the value to store in the ALS bound to a TracingChannel's start event.
|
|
5886
|
+
* In default mode this is the Span itself; in OTEL mode it is the OTEL Context
|
|
5887
|
+
* containing the span so that OTEL's own ALS stores a proper Context object.
|
|
5888
|
+
*/
|
|
5889
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5890
|
+
wrapSpanForStore(span) {
|
|
5891
|
+
return span;
|
|
5892
|
+
}
|
|
5851
5893
|
};
|
|
5852
5894
|
var BraintrustContextManager = class extends ContextManager {
|
|
5853
5895
|
_currentSpan;
|
|
@@ -11599,7 +11641,28 @@ function validateParametersWithJsonSchema(parameters, schema) {
|
|
|
11599
11641
|
}).join(", ");
|
|
11600
11642
|
throw Error(`Invalid parameters: ${errorMessages}`);
|
|
11601
11643
|
}
|
|
11602
|
-
return parameters;
|
|
11644
|
+
return rehydrateRemoteParameters(parameters, schema);
|
|
11645
|
+
}
|
|
11646
|
+
function rehydrateRemoteParameters(parameters, schema) {
|
|
11647
|
+
const schemaProperties = schema.properties;
|
|
11648
|
+
if (typeof schemaProperties !== "object" || schemaProperties === null) {
|
|
11649
|
+
return parameters;
|
|
11650
|
+
}
|
|
11651
|
+
return Object.fromEntries(
|
|
11652
|
+
Object.entries(parameters).map(([name, value]) => {
|
|
11653
|
+
const propertySchema = Reflect.get(schemaProperties, name);
|
|
11654
|
+
if (typeof propertySchema !== "object" || propertySchema === null) {
|
|
11655
|
+
return [name, value];
|
|
11656
|
+
}
|
|
11657
|
+
if (Reflect.get(propertySchema, "x-bt-type") === "prompt") {
|
|
11658
|
+
return [
|
|
11659
|
+
name,
|
|
11660
|
+
Prompt2.fromPromptData(name, PromptData.parse(value))
|
|
11661
|
+
];
|
|
11662
|
+
}
|
|
11663
|
+
return [name, value];
|
|
11664
|
+
})
|
|
11665
|
+
);
|
|
11603
11666
|
}
|
|
11604
11667
|
|
|
11605
11668
|
// src/framework.ts
|
|
@@ -12947,7 +13010,7 @@ function patchStreamIfNeeded(stream, options) {
|
|
|
12947
13010
|
if (!completed) {
|
|
12948
13011
|
completed = true;
|
|
12949
13012
|
try {
|
|
12950
|
-
options.onComplete(chunks);
|
|
13013
|
+
await options.onComplete(chunks);
|
|
12951
13014
|
} catch (error2) {
|
|
12952
13015
|
console.error("Error in stream onComplete handler:", error2);
|
|
12953
13016
|
}
|
|
@@ -12959,7 +13022,7 @@ function patchStreamIfNeeded(stream, options) {
|
|
|
12959
13022
|
chunks.push(chunk);
|
|
12960
13023
|
if (options.onChunk) {
|
|
12961
13024
|
try {
|
|
12962
|
-
options.onChunk(chunk);
|
|
13025
|
+
await options.onChunk(chunk);
|
|
12963
13026
|
} catch (error2) {
|
|
12964
13027
|
console.error("Error in stream onChunk handler:", error2);
|
|
12965
13028
|
}
|
|
@@ -12972,7 +13035,7 @@ function patchStreamIfNeeded(stream, options) {
|
|
|
12972
13035
|
completed = true;
|
|
12973
13036
|
if (options.onError) {
|
|
12974
13037
|
try {
|
|
12975
|
-
options.onError(
|
|
13038
|
+
await options.onError(
|
|
12976
13039
|
error2 instanceof Error ? error2 : new Error(String(error2)),
|
|
12977
13040
|
chunks
|
|
12978
13041
|
);
|
|
@@ -12990,7 +13053,7 @@ function patchStreamIfNeeded(stream, options) {
|
|
|
12990
13053
|
if (!completed) {
|
|
12991
13054
|
completed = true;
|
|
12992
13055
|
try {
|
|
12993
|
-
options.onComplete(chunks);
|
|
13056
|
+
await options.onComplete(chunks);
|
|
12994
13057
|
} catch (error2) {
|
|
12995
13058
|
console.error("Error in stream onComplete handler:", error2);
|
|
12996
13059
|
}
|
|
@@ -13007,7 +13070,7 @@ function patchStreamIfNeeded(stream, options) {
|
|
|
13007
13070
|
const error2 = rawError instanceof Error ? rawError : new Error(String(rawError));
|
|
13008
13071
|
if (options.onError) {
|
|
13009
13072
|
try {
|
|
13010
|
-
options.onError(error2, chunks);
|
|
13073
|
+
await options.onError(error2, chunks);
|
|
13011
13074
|
} catch (handlerError) {
|
|
13012
13075
|
console.error("Error in stream onError handler:", handlerError);
|
|
13013
13076
|
}
|
|
@@ -13464,18 +13527,22 @@ function ensureSpanStateForEvent(states, config3, event, channelName) {
|
|
|
13464
13527
|
function bindCurrentSpanStoreToStart(tracingChannel2, states, config3, channelName) {
|
|
13465
13528
|
const state = _internalGetGlobalState();
|
|
13466
13529
|
const startChannel = tracingChannel2.start;
|
|
13467
|
-
const
|
|
13530
|
+
const contextManager = state?.contextManager;
|
|
13531
|
+
const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
|
|
13468
13532
|
if (!currentSpanStore || !startChannel) {
|
|
13469
13533
|
return void 0;
|
|
13470
13534
|
}
|
|
13471
13535
|
startChannel.bindStore(
|
|
13472
13536
|
currentSpanStore,
|
|
13473
|
-
(event) =>
|
|
13474
|
-
|
|
13475
|
-
|
|
13476
|
-
|
|
13477
|
-
|
|
13478
|
-
|
|
13537
|
+
(event) => {
|
|
13538
|
+
const span = ensureSpanStateForEvent(
|
|
13539
|
+
states,
|
|
13540
|
+
config3,
|
|
13541
|
+
event,
|
|
13542
|
+
channelName
|
|
13543
|
+
).span;
|
|
13544
|
+
return contextManager.wrapSpanForStore(span);
|
|
13545
|
+
}
|
|
13479
13546
|
);
|
|
13480
13547
|
return () => {
|
|
13481
13548
|
startChannel.unbindStore(currentSpanStore);
|
|
@@ -13492,6 +13559,26 @@ function logErrorAndEnd(states, event) {
|
|
|
13492
13559
|
spanData.span.end();
|
|
13493
13560
|
states.delete(event);
|
|
13494
13561
|
}
|
|
13562
|
+
function runStreamingCompletionHook(args) {
|
|
13563
|
+
if (!args.config.onComplete) {
|
|
13564
|
+
return;
|
|
13565
|
+
}
|
|
13566
|
+
try {
|
|
13567
|
+
args.config.onComplete({
|
|
13568
|
+
channelName: args.channelName,
|
|
13569
|
+
...args.chunks ? { chunks: args.chunks } : {},
|
|
13570
|
+
endEvent: args.endEvent,
|
|
13571
|
+
...args.metadata !== void 0 ? { metadata: args.metadata } : {},
|
|
13572
|
+
metrics: args.metrics,
|
|
13573
|
+
output: args.output,
|
|
13574
|
+
result: args.result,
|
|
13575
|
+
span: args.span,
|
|
13576
|
+
startTime: args.startTime
|
|
13577
|
+
});
|
|
13578
|
+
} catch (error2) {
|
|
13579
|
+
console.error(`Error in onComplete hook for ${args.channelName}:`, error2);
|
|
13580
|
+
}
|
|
13581
|
+
}
|
|
13495
13582
|
function traceAsyncChannel(channel2, config3) {
|
|
13496
13583
|
const tracingChannel2 = channel2.tracingChannel();
|
|
13497
13584
|
const states = /* @__PURE__ */ new WeakMap();
|
|
@@ -13619,6 +13706,18 @@ function traceStreamingChannel(channel2, config3) {
|
|
|
13619
13706
|
} else if (metrics.time_to_first_token === void 0 && chunks.length > 0) {
|
|
13620
13707
|
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
13621
13708
|
}
|
|
13709
|
+
runStreamingCompletionHook({
|
|
13710
|
+
channelName,
|
|
13711
|
+
chunks,
|
|
13712
|
+
config: config3,
|
|
13713
|
+
endEvent: asyncEndEvent,
|
|
13714
|
+
...metadata !== void 0 ? { metadata } : {},
|
|
13715
|
+
metrics,
|
|
13716
|
+
output,
|
|
13717
|
+
result: asyncEndEvent.result,
|
|
13718
|
+
span,
|
|
13719
|
+
startTime
|
|
13720
|
+
});
|
|
13622
13721
|
span.log({
|
|
13623
13722
|
output,
|
|
13624
13723
|
...metadata !== void 0 ? { metadata } : {},
|
|
@@ -13668,6 +13767,17 @@ function traceStreamingChannel(channel2, config3) {
|
|
|
13668
13767
|
asyncEndEvent.result,
|
|
13669
13768
|
asyncEndEvent
|
|
13670
13769
|
);
|
|
13770
|
+
runStreamingCompletionHook({
|
|
13771
|
+
channelName,
|
|
13772
|
+
config: config3,
|
|
13773
|
+
endEvent: asyncEndEvent,
|
|
13774
|
+
...normalizeMetadata(metadata) !== void 0 ? { metadata: normalizeMetadata(metadata) } : {},
|
|
13775
|
+
metrics,
|
|
13776
|
+
output,
|
|
13777
|
+
result: asyncEndEvent.result,
|
|
13778
|
+
span,
|
|
13779
|
+
startTime
|
|
13780
|
+
});
|
|
13671
13781
|
span.log({
|
|
13672
13782
|
output,
|
|
13673
13783
|
...normalizeMetadata(metadata) !== void 0 ? { metadata: normalizeMetadata(metadata) } : {},
|
|
@@ -13716,51 +13826,28 @@ function traceSyncStreamChannel(channel2, config3) {
|
|
|
13716
13826
|
}
|
|
13717
13827
|
const { span, startTime } = spanData;
|
|
13718
13828
|
const endEvent = event;
|
|
13719
|
-
|
|
13720
|
-
|
|
13721
|
-
|
|
13722
|
-
|
|
13723
|
-
|
|
13724
|
-
|
|
13725
|
-
|
|
13726
|
-
|
|
13727
|
-
|
|
13728
|
-
|
|
13729
|
-
|
|
13730
|
-
|
|
13731
|
-
|
|
13732
|
-
return;
|
|
13733
|
-
}
|
|
13734
|
-
let first = true;
|
|
13735
|
-
stream.on("chunk", () => {
|
|
13736
|
-
if (first) {
|
|
13737
|
-
span.log({
|
|
13738
|
-
metrics: {
|
|
13739
|
-
time_to_first_token: getCurrentUnixTimestamp() - startTime
|
|
13740
|
-
}
|
|
13741
|
-
});
|
|
13742
|
-
first = false;
|
|
13743
|
-
}
|
|
13744
|
-
});
|
|
13745
|
-
stream.on("chatCompletion", (completion) => {
|
|
13746
|
-
try {
|
|
13747
|
-
if (hasChoices(completion)) {
|
|
13748
|
-
span.log({
|
|
13749
|
-
output: completion.choices
|
|
13750
|
-
});
|
|
13751
|
-
}
|
|
13752
|
-
} catch (error2) {
|
|
13753
|
-
console.error(
|
|
13754
|
-
`Error extracting chatCompletion for ${channelName}:`,
|
|
13755
|
-
error2
|
|
13756
|
-
);
|
|
13829
|
+
const handleResolvedResult = (result) => {
|
|
13830
|
+
const resolvedEndEvent = {
|
|
13831
|
+
...endEvent,
|
|
13832
|
+
result
|
|
13833
|
+
};
|
|
13834
|
+
if (config3.patchResult?.({
|
|
13835
|
+
channelName,
|
|
13836
|
+
endEvent: resolvedEndEvent,
|
|
13837
|
+
result,
|
|
13838
|
+
span,
|
|
13839
|
+
startTime
|
|
13840
|
+
})) {
|
|
13841
|
+
return;
|
|
13757
13842
|
}
|
|
13758
|
-
|
|
13759
|
-
|
|
13760
|
-
|
|
13843
|
+
const stream = result;
|
|
13844
|
+
if (!isSyncStreamLike(stream)) {
|
|
13845
|
+
span.end();
|
|
13846
|
+
states.delete(event);
|
|
13761
13847
|
return;
|
|
13762
13848
|
}
|
|
13763
|
-
|
|
13849
|
+
let first = true;
|
|
13850
|
+
stream.on("chunk", () => {
|
|
13764
13851
|
if (first) {
|
|
13765
13852
|
span.log({
|
|
13766
13853
|
metrics: {
|
|
@@ -13769,25 +13856,55 @@ function traceSyncStreamChannel(channel2, config3) {
|
|
|
13769
13856
|
});
|
|
13770
13857
|
first = false;
|
|
13771
13858
|
}
|
|
13772
|
-
|
|
13773
|
-
|
|
13774
|
-
|
|
13859
|
+
});
|
|
13860
|
+
stream.on("chatCompletion", (completion) => {
|
|
13861
|
+
try {
|
|
13862
|
+
if (hasChoices(completion)) {
|
|
13863
|
+
span.log({
|
|
13864
|
+
output: completion.choices
|
|
13865
|
+
});
|
|
13866
|
+
}
|
|
13867
|
+
} catch (error2) {
|
|
13868
|
+
console.error(
|
|
13869
|
+
`Error extracting chatCompletion for ${channelName}:`,
|
|
13870
|
+
error2
|
|
13871
|
+
);
|
|
13872
|
+
}
|
|
13873
|
+
});
|
|
13874
|
+
stream.on("event", (streamEvent) => {
|
|
13875
|
+
if (!config3.extractFromEvent) {
|
|
13876
|
+
return;
|
|
13877
|
+
}
|
|
13878
|
+
try {
|
|
13879
|
+
if (first) {
|
|
13880
|
+
span.log({
|
|
13881
|
+
metrics: {
|
|
13882
|
+
time_to_first_token: getCurrentUnixTimestamp() - startTime
|
|
13883
|
+
}
|
|
13884
|
+
});
|
|
13885
|
+
first = false;
|
|
13886
|
+
}
|
|
13887
|
+
const extracted = config3.extractFromEvent(streamEvent);
|
|
13888
|
+
if (extracted && Object.keys(extracted).length > 0) {
|
|
13889
|
+
span.log(extracted);
|
|
13890
|
+
}
|
|
13891
|
+
} catch (error2) {
|
|
13892
|
+
console.error(`Error extracting event for ${channelName}:`, error2);
|
|
13775
13893
|
}
|
|
13776
|
-
} catch (error2) {
|
|
13777
|
-
console.error(`Error extracting event for ${channelName}:`, error2);
|
|
13778
|
-
}
|
|
13779
|
-
});
|
|
13780
|
-
stream.on("end", () => {
|
|
13781
|
-
span.end();
|
|
13782
|
-
states.delete(event);
|
|
13783
|
-
});
|
|
13784
|
-
stream.on("error", (error2) => {
|
|
13785
|
-
span.log({
|
|
13786
|
-
error: error2.message
|
|
13787
13894
|
});
|
|
13788
|
-
|
|
13789
|
-
|
|
13790
|
-
|
|
13895
|
+
stream.on("end", () => {
|
|
13896
|
+
span.end();
|
|
13897
|
+
states.delete(event);
|
|
13898
|
+
});
|
|
13899
|
+
stream.on("error", (error2) => {
|
|
13900
|
+
span.log({
|
|
13901
|
+
error: error2.message
|
|
13902
|
+
});
|
|
13903
|
+
span.end();
|
|
13904
|
+
states.delete(event);
|
|
13905
|
+
});
|
|
13906
|
+
};
|
|
13907
|
+
handleResolvedResult(endEvent.result);
|
|
13791
13908
|
},
|
|
13792
13909
|
error: (event) => {
|
|
13793
13910
|
logErrorAndEnd(states, event);
|
|
@@ -14044,6 +14161,10 @@ var openAIChannels = defineChannels("openai", {
|
|
|
14044
14161
|
responsesParse: channel({
|
|
14045
14162
|
channelName: "responses.parse",
|
|
14046
14163
|
kind: "async"
|
|
14164
|
+
}),
|
|
14165
|
+
responsesCompact: channel({
|
|
14166
|
+
channelName: "responses.compact",
|
|
14167
|
+
kind: "async"
|
|
14047
14168
|
})
|
|
14048
14169
|
});
|
|
14049
14170
|
|
|
@@ -14323,6 +14444,40 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
14323
14444
|
aggregateChunks: aggregateResponseStreamEvents
|
|
14324
14445
|
})
|
|
14325
14446
|
);
|
|
14447
|
+
this.unsubscribers.push(
|
|
14448
|
+
traceAsyncChannel(openAIChannels.responsesCompact, {
|
|
14449
|
+
name: "openai.responses.compact",
|
|
14450
|
+
type: "llm" /* LLM */,
|
|
14451
|
+
extractInput: ([params]) => {
|
|
14452
|
+
const { input, ...metadata } = params;
|
|
14453
|
+
return {
|
|
14454
|
+
input: processInputAttachments(input),
|
|
14455
|
+
metadata: { ...metadata, provider: "openai" }
|
|
14456
|
+
};
|
|
14457
|
+
},
|
|
14458
|
+
extractOutput: (result) => {
|
|
14459
|
+
return processImagesInOutput(result?.output);
|
|
14460
|
+
},
|
|
14461
|
+
extractMetadata: (result) => {
|
|
14462
|
+
if (!result) {
|
|
14463
|
+
return void 0;
|
|
14464
|
+
}
|
|
14465
|
+
const { output: _output, usage: _usage, ...metadata } = result;
|
|
14466
|
+
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
14467
|
+
},
|
|
14468
|
+
extractMetrics: (result, startTime, endEvent) => {
|
|
14469
|
+
const metrics = withCachedMetric(
|
|
14470
|
+
parseMetricsFromUsage(result?.usage),
|
|
14471
|
+
result,
|
|
14472
|
+
endEvent
|
|
14473
|
+
);
|
|
14474
|
+
if (startTime) {
|
|
14475
|
+
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
14476
|
+
}
|
|
14477
|
+
return metrics;
|
|
14478
|
+
}
|
|
14479
|
+
})
|
|
14480
|
+
);
|
|
14326
14481
|
}
|
|
14327
14482
|
onDisable() {
|
|
14328
14483
|
this.unsubscribers = unsubscribeAll(this.unsubscribers);
|
|
@@ -14610,28 +14765,40 @@ function aggregateAnthropicStreamChunks(chunks) {
|
|
|
14610
14765
|
case "content_block_start":
|
|
14611
14766
|
if (event.content_block) {
|
|
14612
14767
|
contentBlocks[event.index] = event.content_block;
|
|
14613
|
-
contentBlockDeltas[event.index] = [];
|
|
14768
|
+
contentBlockDeltas[event.index] = { textDeltas: [], citations: [] };
|
|
14614
14769
|
}
|
|
14615
14770
|
break;
|
|
14616
|
-
case "content_block_delta":
|
|
14617
|
-
|
|
14618
|
-
|
|
14771
|
+
case "content_block_delta": {
|
|
14772
|
+
const acc = contentBlockDeltas[event.index];
|
|
14773
|
+
const delta = event.delta;
|
|
14774
|
+
if (!delta) break;
|
|
14775
|
+
if (delta.type === "text_delta" && "text" in delta) {
|
|
14776
|
+
const text = delta.text;
|
|
14619
14777
|
if (text) {
|
|
14620
|
-
if (
|
|
14621
|
-
|
|
14622
|
-
contentBlockDeltas[event.index].push(text);
|
|
14778
|
+
if (acc !== void 0) {
|
|
14779
|
+
acc.textDeltas.push(text);
|
|
14623
14780
|
} else {
|
|
14624
14781
|
fallbackTextDeltas.push(text);
|
|
14625
14782
|
}
|
|
14626
14783
|
}
|
|
14627
|
-
} else if (
|
|
14628
|
-
const partialJson =
|
|
14629
|
-
if (partialJson) {
|
|
14630
|
-
|
|
14631
|
-
|
|
14784
|
+
} else if (delta.type === "input_json_delta" && "partial_json" in delta) {
|
|
14785
|
+
const partialJson = delta.partial_json;
|
|
14786
|
+
if (partialJson && acc !== void 0) {
|
|
14787
|
+
acc.textDeltas.push(partialJson);
|
|
14788
|
+
}
|
|
14789
|
+
} else if (delta.type === "thinking_delta" && "thinking" in delta) {
|
|
14790
|
+
const thinking = delta.thinking;
|
|
14791
|
+
if (thinking && acc !== void 0) {
|
|
14792
|
+
acc.textDeltas.push(thinking);
|
|
14793
|
+
}
|
|
14794
|
+
} else if (delta.type === "citations_delta" && "citation" in delta) {
|
|
14795
|
+
const citation = delta.citation;
|
|
14796
|
+
if (citation && acc !== void 0) {
|
|
14797
|
+
acc.citations.push(citation);
|
|
14632
14798
|
}
|
|
14633
14799
|
}
|
|
14634
14800
|
break;
|
|
14801
|
+
}
|
|
14635
14802
|
case "content_block_stop":
|
|
14636
14803
|
finalizeContentBlock(
|
|
14637
14804
|
event.index,
|
|
@@ -14657,7 +14824,7 @@ function aggregateAnthropicStreamChunks(chunks) {
|
|
|
14657
14824
|
})).filter(({ block }) => block !== void 0).sort((left, right) => left.index - right.index).map(({ block }) => block);
|
|
14658
14825
|
let output = fallbackTextDeltas.join("");
|
|
14659
14826
|
if (orderedContent.length > 0) {
|
|
14660
|
-
if (orderedContent.every(isTextContentBlock)) {
|
|
14827
|
+
if (orderedContent.every(isTextContentBlock) && orderedContent.every((block) => !block.citations?.length)) {
|
|
14661
14828
|
output = orderedContent.map((block) => block.text).join("");
|
|
14662
14829
|
} else {
|
|
14663
14830
|
output = {
|
|
@@ -14683,7 +14850,8 @@ function finalizeContentBlock(index, contentBlocks, contentBlockDeltas, fallback
|
|
|
14683
14850
|
if (!contentBlock) {
|
|
14684
14851
|
return;
|
|
14685
14852
|
}
|
|
14686
|
-
const
|
|
14853
|
+
const acc = contentBlockDeltas[index];
|
|
14854
|
+
const text = acc?.textDeltas.join("") ?? "";
|
|
14687
14855
|
if (isToolUseContentBlock(contentBlock)) {
|
|
14688
14856
|
if (!text) {
|
|
14689
14857
|
return;
|
|
@@ -14700,20 +14868,28 @@ function finalizeContentBlock(index, contentBlocks, contentBlockDeltas, fallback
|
|
|
14700
14868
|
return;
|
|
14701
14869
|
}
|
|
14702
14870
|
if (isTextContentBlock(contentBlock)) {
|
|
14871
|
+
if (!text) {
|
|
14872
|
+
delete contentBlocks[index];
|
|
14873
|
+
return;
|
|
14874
|
+
}
|
|
14875
|
+
const updated = { ...contentBlock, text };
|
|
14876
|
+
if (acc?.citations.length) {
|
|
14877
|
+
updated.citations = acc.citations;
|
|
14878
|
+
}
|
|
14879
|
+
contentBlocks[index] = updated;
|
|
14880
|
+
return;
|
|
14881
|
+
}
|
|
14882
|
+
if (isThinkingContentBlock(contentBlock)) {
|
|
14703
14883
|
if (!text) {
|
|
14704
14884
|
delete contentBlocks[index];
|
|
14705
14885
|
return;
|
|
14706
14886
|
}
|
|
14707
14887
|
contentBlocks[index] = {
|
|
14708
14888
|
...contentBlock,
|
|
14709
|
-
text
|
|
14889
|
+
thinking: text
|
|
14710
14890
|
};
|
|
14711
14891
|
return;
|
|
14712
14892
|
}
|
|
14713
|
-
if (text) {
|
|
14714
|
-
fallbackTextDeltas.push(text);
|
|
14715
|
-
}
|
|
14716
|
-
delete contentBlocks[index];
|
|
14717
14893
|
}
|
|
14718
14894
|
function isTextContentBlock(contentBlock) {
|
|
14719
14895
|
return contentBlock.type === "text";
|
|
@@ -14721,6 +14897,9 @@ function isTextContentBlock(contentBlock) {
|
|
|
14721
14897
|
function isToolUseContentBlock(contentBlock) {
|
|
14722
14898
|
return contentBlock.type === "tool_use";
|
|
14723
14899
|
}
|
|
14900
|
+
function isThinkingContentBlock(contentBlock) {
|
|
14901
|
+
return contentBlock.type === "thinking";
|
|
14902
|
+
}
|
|
14724
14903
|
function isAnthropicBase64ContentBlock(input) {
|
|
14725
14904
|
return (input.type === "image" || input.type === "document") && isObject(input.source) && input.source.type === "base64";
|
|
14726
14905
|
}
|
|
@@ -14775,15 +14954,6 @@ function coalesceInput(messages, system) {
|
|
|
14775
14954
|
}
|
|
14776
14955
|
return input;
|
|
14777
14956
|
}
|
|
14778
|
-
function filterFrom(obj, fieldsToRemove) {
|
|
14779
|
-
const result = {};
|
|
14780
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
14781
|
-
if (!fieldsToRemove.includes(key)) {
|
|
14782
|
-
result[key] = value;
|
|
14783
|
-
}
|
|
14784
|
-
}
|
|
14785
|
-
return result;
|
|
14786
|
-
}
|
|
14787
14957
|
|
|
14788
14958
|
// src/wrappers/ai-sdk/normalize-logged-output.ts
|
|
14789
14959
|
var REMOVE_NORMALIZED_VALUE = Symbol("braintrust.ai-sdk.remove-normalized");
|
|
@@ -14913,6 +15083,16 @@ var aiSDKChannels = defineChannels("ai", {
|
|
|
14913
15083
|
channelName: "streamObject.sync",
|
|
14914
15084
|
kind: "sync-stream"
|
|
14915
15085
|
}),
|
|
15086
|
+
embed: channel(
|
|
15087
|
+
{
|
|
15088
|
+
channelName: "embed",
|
|
15089
|
+
kind: "async"
|
|
15090
|
+
}
|
|
15091
|
+
),
|
|
15092
|
+
embedMany: channel({
|
|
15093
|
+
channelName: "embedMany",
|
|
15094
|
+
kind: "async"
|
|
15095
|
+
}),
|
|
14916
15096
|
agentGenerate: channel({
|
|
14917
15097
|
channelName: "Agent.generate",
|
|
14918
15098
|
kind: "async"
|
|
@@ -14921,6 +15101,10 @@ var aiSDKChannels = defineChannels("ai", {
|
|
|
14921
15101
|
channelName: "Agent.stream",
|
|
14922
15102
|
kind: "async"
|
|
14923
15103
|
}),
|
|
15104
|
+
agentStreamSync: channel({
|
|
15105
|
+
channelName: "Agent.stream.sync",
|
|
15106
|
+
kind: "sync-stream"
|
|
15107
|
+
}),
|
|
14924
15108
|
toolLoopAgentGenerate: channel({
|
|
14925
15109
|
channelName: "ToolLoopAgent.generate",
|
|
14926
15110
|
kind: "async"
|
|
@@ -14948,6 +15132,9 @@ var DEFAULT_DENY_OUTPUT_PATHS = [
|
|
|
14948
15132
|
];
|
|
14949
15133
|
var AUTO_PATCHED_MODEL = Symbol.for("braintrust.ai-sdk.auto-patched-model");
|
|
14950
15134
|
var AUTO_PATCHED_TOOL = Symbol.for("braintrust.ai-sdk.auto-patched-tool");
|
|
15135
|
+
var RUNTIME_DENY_OUTPUT_PATHS = Symbol.for(
|
|
15136
|
+
"braintrust.ai-sdk.deny-output-paths"
|
|
15137
|
+
);
|
|
14951
15138
|
var AISDKPlugin = class extends BasePlugin {
|
|
14952
15139
|
config;
|
|
14953
15140
|
constructor(config3 = {}) {
|
|
@@ -14966,10 +15153,13 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
14966
15153
|
traceStreamingChannel(aiSDKChannels.generateText, {
|
|
14967
15154
|
name: "generateText",
|
|
14968
15155
|
type: "llm" /* LLM */,
|
|
14969
|
-
extractInput: ([params], event, span) =>
|
|
15156
|
+
extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
|
|
14970
15157
|
extractOutput: (result, endEvent) => {
|
|
14971
15158
|
finalizeAISDKChildTracing(endEvent);
|
|
14972
|
-
return processAISDKOutput(
|
|
15159
|
+
return processAISDKOutput(
|
|
15160
|
+
result,
|
|
15161
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
15162
|
+
);
|
|
14973
15163
|
},
|
|
14974
15164
|
extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
|
|
14975
15165
|
aggregateChunks: aggregateAISDKChunks
|
|
@@ -14979,12 +15169,15 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
14979
15169
|
traceStreamingChannel(aiSDKChannels.streamText, {
|
|
14980
15170
|
name: "streamText",
|
|
14981
15171
|
type: "llm" /* LLM */,
|
|
14982
|
-
extractInput: ([params], event, span) =>
|
|
14983
|
-
extractOutput: (result) => processAISDKOutput(
|
|
15172
|
+
extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
|
|
15173
|
+
extractOutput: (result, endEvent) => processAISDKOutput(
|
|
15174
|
+
result,
|
|
15175
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
15176
|
+
),
|
|
14984
15177
|
extractMetrics: (result, startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent, startTime),
|
|
14985
15178
|
aggregateChunks: aggregateAISDKChunks,
|
|
14986
15179
|
patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
|
|
14987
|
-
denyOutputPaths,
|
|
15180
|
+
defaultDenyOutputPaths: denyOutputPaths,
|
|
14988
15181
|
endEvent,
|
|
14989
15182
|
result,
|
|
14990
15183
|
span,
|
|
@@ -14996,9 +15189,9 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
14996
15189
|
traceSyncStreamChannel(aiSDKChannels.streamTextSync, {
|
|
14997
15190
|
name: "streamText",
|
|
14998
15191
|
type: "llm" /* LLM */,
|
|
14999
|
-
extractInput: ([params], event, span) =>
|
|
15192
|
+
extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
|
|
15000
15193
|
patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
|
|
15001
|
-
denyOutputPaths,
|
|
15194
|
+
defaultDenyOutputPaths: denyOutputPaths,
|
|
15002
15195
|
endEvent,
|
|
15003
15196
|
result,
|
|
15004
15197
|
span,
|
|
@@ -15010,10 +15203,13 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
15010
15203
|
traceStreamingChannel(aiSDKChannels.generateObject, {
|
|
15011
15204
|
name: "generateObject",
|
|
15012
15205
|
type: "llm" /* LLM */,
|
|
15013
|
-
extractInput: ([params], event, span) =>
|
|
15206
|
+
extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
|
|
15014
15207
|
extractOutput: (result, endEvent) => {
|
|
15015
15208
|
finalizeAISDKChildTracing(endEvent);
|
|
15016
|
-
return processAISDKOutput(
|
|
15209
|
+
return processAISDKOutput(
|
|
15210
|
+
result,
|
|
15211
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
15212
|
+
);
|
|
15017
15213
|
},
|
|
15018
15214
|
extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
|
|
15019
15215
|
aggregateChunks: aggregateAISDKChunks
|
|
@@ -15023,12 +15219,15 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
15023
15219
|
traceStreamingChannel(aiSDKChannels.streamObject, {
|
|
15024
15220
|
name: "streamObject",
|
|
15025
15221
|
type: "llm" /* LLM */,
|
|
15026
|
-
extractInput: ([params], event, span) =>
|
|
15027
|
-
extractOutput: (result) => processAISDKOutput(
|
|
15222
|
+
extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
|
|
15223
|
+
extractOutput: (result, endEvent) => processAISDKOutput(
|
|
15224
|
+
result,
|
|
15225
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
15226
|
+
),
|
|
15028
15227
|
extractMetrics: (result, startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent, startTime),
|
|
15029
15228
|
aggregateChunks: aggregateAISDKChunks,
|
|
15030
15229
|
patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
|
|
15031
|
-
denyOutputPaths,
|
|
15230
|
+
defaultDenyOutputPaths: denyOutputPaths,
|
|
15032
15231
|
endEvent,
|
|
15033
15232
|
result,
|
|
15034
15233
|
span,
|
|
@@ -15040,9 +15239,9 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
15040
15239
|
traceSyncStreamChannel(aiSDKChannels.streamObjectSync, {
|
|
15041
15240
|
name: "streamObject",
|
|
15042
15241
|
type: "llm" /* LLM */,
|
|
15043
|
-
extractInput: ([params], event, span) =>
|
|
15242
|
+
extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
|
|
15044
15243
|
patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
|
|
15045
|
-
denyOutputPaths,
|
|
15244
|
+
defaultDenyOutputPaths: denyOutputPaths,
|
|
15046
15245
|
endEvent,
|
|
15047
15246
|
result,
|
|
15048
15247
|
span,
|
|
@@ -15050,14 +15249,41 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
15050
15249
|
})
|
|
15051
15250
|
})
|
|
15052
15251
|
);
|
|
15252
|
+
this.unsubscribers.push(
|
|
15253
|
+
traceAsyncChannel(aiSDKChannels.embed, {
|
|
15254
|
+
name: "embed",
|
|
15255
|
+
type: "llm" /* LLM */,
|
|
15256
|
+
extractInput: ([params], event) => prepareAISDKEmbedInput(params, event.self),
|
|
15257
|
+
extractOutput: (result, endEvent) => processAISDKEmbeddingOutput(
|
|
15258
|
+
result,
|
|
15259
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
15260
|
+
),
|
|
15261
|
+
extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent)
|
|
15262
|
+
})
|
|
15263
|
+
);
|
|
15264
|
+
this.unsubscribers.push(
|
|
15265
|
+
traceAsyncChannel(aiSDKChannels.embedMany, {
|
|
15266
|
+
name: "embedMany",
|
|
15267
|
+
type: "llm" /* LLM */,
|
|
15268
|
+
extractInput: ([params], event) => prepareAISDKEmbedInput(params, event.self),
|
|
15269
|
+
extractOutput: (result, endEvent) => processAISDKEmbeddingOutput(
|
|
15270
|
+
result,
|
|
15271
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
15272
|
+
),
|
|
15273
|
+
extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent)
|
|
15274
|
+
})
|
|
15275
|
+
);
|
|
15053
15276
|
this.unsubscribers.push(
|
|
15054
15277
|
traceStreamingChannel(aiSDKChannels.agentGenerate, {
|
|
15055
15278
|
name: "Agent.generate",
|
|
15056
15279
|
type: "llm" /* LLM */,
|
|
15057
|
-
extractInput: ([params], event, span) =>
|
|
15280
|
+
extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
|
|
15058
15281
|
extractOutput: (result, endEvent) => {
|
|
15059
15282
|
finalizeAISDKChildTracing(endEvent);
|
|
15060
|
-
return processAISDKOutput(
|
|
15283
|
+
return processAISDKOutput(
|
|
15284
|
+
result,
|
|
15285
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
15286
|
+
);
|
|
15061
15287
|
},
|
|
15062
15288
|
extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
|
|
15063
15289
|
aggregateChunks: aggregateAISDKChunks
|
|
@@ -15067,12 +15293,29 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
15067
15293
|
traceStreamingChannel(aiSDKChannels.agentStream, {
|
|
15068
15294
|
name: "Agent.stream",
|
|
15069
15295
|
type: "llm" /* LLM */,
|
|
15070
|
-
extractInput: ([params], event, span) =>
|
|
15071
|
-
extractOutput: (result) => processAISDKOutput(
|
|
15296
|
+
extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
|
|
15297
|
+
extractOutput: (result, endEvent) => processAISDKOutput(
|
|
15298
|
+
result,
|
|
15299
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
15300
|
+
),
|
|
15072
15301
|
extractMetrics: (result, startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent, startTime),
|
|
15073
15302
|
aggregateChunks: aggregateAISDKChunks,
|
|
15074
15303
|
patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
|
|
15075
|
-
denyOutputPaths,
|
|
15304
|
+
defaultDenyOutputPaths: denyOutputPaths,
|
|
15305
|
+
endEvent,
|
|
15306
|
+
result,
|
|
15307
|
+
span,
|
|
15308
|
+
startTime
|
|
15309
|
+
})
|
|
15310
|
+
})
|
|
15311
|
+
);
|
|
15312
|
+
this.unsubscribers.push(
|
|
15313
|
+
traceSyncStreamChannel(aiSDKChannels.agentStreamSync, {
|
|
15314
|
+
name: "Agent.stream",
|
|
15315
|
+
type: "llm" /* LLM */,
|
|
15316
|
+
extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
|
|
15317
|
+
patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
|
|
15318
|
+
defaultDenyOutputPaths: denyOutputPaths,
|
|
15076
15319
|
endEvent,
|
|
15077
15320
|
result,
|
|
15078
15321
|
span,
|
|
@@ -15084,10 +15327,13 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
15084
15327
|
traceStreamingChannel(aiSDKChannels.toolLoopAgentGenerate, {
|
|
15085
15328
|
name: "ToolLoopAgent.generate",
|
|
15086
15329
|
type: "llm" /* LLM */,
|
|
15087
|
-
extractInput: ([params], event, span) =>
|
|
15330
|
+
extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
|
|
15088
15331
|
extractOutput: (result, endEvent) => {
|
|
15089
15332
|
finalizeAISDKChildTracing(endEvent);
|
|
15090
|
-
return processAISDKOutput(
|
|
15333
|
+
return processAISDKOutput(
|
|
15334
|
+
result,
|
|
15335
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
15336
|
+
);
|
|
15091
15337
|
},
|
|
15092
15338
|
extractMetrics: (result, _startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent),
|
|
15093
15339
|
aggregateChunks: aggregateAISDKChunks
|
|
@@ -15097,12 +15343,15 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
15097
15343
|
traceStreamingChannel(aiSDKChannels.toolLoopAgentStream, {
|
|
15098
15344
|
name: "ToolLoopAgent.stream",
|
|
15099
15345
|
type: "llm" /* LLM */,
|
|
15100
|
-
extractInput: ([params], event, span) =>
|
|
15101
|
-
extractOutput: (result) => processAISDKOutput(
|
|
15346
|
+
extractInput: ([params], event, span) => prepareAISDKCallInput(params, event, span, denyOutputPaths),
|
|
15347
|
+
extractOutput: (result, endEvent) => processAISDKOutput(
|
|
15348
|
+
result,
|
|
15349
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
15350
|
+
),
|
|
15102
15351
|
extractMetrics: (result, startTime, endEvent) => extractTopLevelAISDKMetrics(result, endEvent, startTime),
|
|
15103
15352
|
aggregateChunks: aggregateAISDKChunks,
|
|
15104
15353
|
patchResult: ({ endEvent, result, span, startTime }) => patchAISDKStreamingResult({
|
|
15105
|
-
denyOutputPaths,
|
|
15354
|
+
defaultDenyOutputPaths: denyOutputPaths,
|
|
15106
15355
|
endEvent,
|
|
15107
15356
|
result,
|
|
15108
15357
|
span,
|
|
@@ -15112,75 +15361,391 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
15112
15361
|
);
|
|
15113
15362
|
}
|
|
15114
15363
|
};
|
|
15115
|
-
function
|
|
15116
|
-
if (
|
|
15117
|
-
|
|
15118
|
-
if (!input || typeof input !== "object" || Array.isArray(input)) {
|
|
15119
|
-
return input;
|
|
15364
|
+
function resolveDenyOutputPaths(event, defaultDenyOutputPaths) {
|
|
15365
|
+
if (Array.isArray(event?.denyOutputPaths)) {
|
|
15366
|
+
return event.denyOutputPaths;
|
|
15120
15367
|
}
|
|
15121
|
-
const
|
|
15122
|
-
|
|
15123
|
-
|
|
15124
|
-
function prepareAISDKInput(params, event, span, denyOutputPaths) {
|
|
15125
|
-
const input = processAISDKInput(params);
|
|
15126
|
-
const metadata = extractMetadataFromParams(params, event.self);
|
|
15127
|
-
const childTracing = prepareAISDKChildTracing(
|
|
15128
|
-
params,
|
|
15129
|
-
event.self,
|
|
15130
|
-
span,
|
|
15131
|
-
denyOutputPaths
|
|
15132
|
-
);
|
|
15133
|
-
event.__braintrust_ai_sdk_model_wrapped = childTracing.modelWrapped;
|
|
15134
|
-
if (childTracing.cleanup) {
|
|
15135
|
-
event.__braintrust_ai_sdk_cleanup = childTracing.cleanup;
|
|
15368
|
+
const firstArgument = event?.arguments && event.arguments.length > 0 ? event.arguments[0] : void 0;
|
|
15369
|
+
if (!firstArgument || typeof firstArgument !== "object") {
|
|
15370
|
+
return defaultDenyOutputPaths;
|
|
15136
15371
|
}
|
|
15137
|
-
|
|
15138
|
-
|
|
15139
|
-
|
|
15140
|
-
};
|
|
15141
|
-
}
|
|
15142
|
-
function extractTopLevelAISDKMetrics(result, event, startTime) {
|
|
15143
|
-
const metrics = hasModelChildTracing(event) ? {} : extractTokenMetrics(result);
|
|
15144
|
-
if (startTime) {
|
|
15145
|
-
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
15372
|
+
const runtimeDenyOutputPaths = firstArgument[RUNTIME_DENY_OUTPUT_PATHS];
|
|
15373
|
+
if (Array.isArray(runtimeDenyOutputPaths) && runtimeDenyOutputPaths.every((path8) => typeof path8 === "string")) {
|
|
15374
|
+
return runtimeDenyOutputPaths;
|
|
15146
15375
|
}
|
|
15147
|
-
return
|
|
15148
|
-
}
|
|
15149
|
-
function hasModelChildTracing(event) {
|
|
15150
|
-
return event?.__braintrust_ai_sdk_model_wrapped === true;
|
|
15376
|
+
return defaultDenyOutputPaths;
|
|
15151
15377
|
}
|
|
15152
|
-
|
|
15153
|
-
|
|
15154
|
-
|
|
15155
|
-
|
|
15156
|
-
|
|
15157
|
-
|
|
15158
|
-
}
|
|
15159
|
-
|
|
15160
|
-
|
|
15161
|
-
|
|
15162
|
-
|
|
15163
|
-
|
|
15164
|
-
|
|
15165
|
-
|
|
15166
|
-
if (
|
|
15378
|
+
var isZodSchema2 = (value) => {
|
|
15379
|
+
return value != null && typeof value === "object" && "_def" in value && typeof value._def === "object";
|
|
15380
|
+
};
|
|
15381
|
+
var serializeZodSchema2 = (schema) => {
|
|
15382
|
+
try {
|
|
15383
|
+
return zodToJsonSchema(schema);
|
|
15384
|
+
} catch {
|
|
15385
|
+
return {
|
|
15386
|
+
type: "object",
|
|
15387
|
+
description: "Zod schema (conversion failed)"
|
|
15388
|
+
};
|
|
15389
|
+
}
|
|
15390
|
+
};
|
|
15391
|
+
var isOutputObject = (value) => {
|
|
15392
|
+
if (value == null || typeof value !== "object") {
|
|
15393
|
+
return false;
|
|
15394
|
+
}
|
|
15395
|
+
const output = value;
|
|
15396
|
+
if (!("responseFormat" in output)) {
|
|
15397
|
+
return false;
|
|
15398
|
+
}
|
|
15399
|
+
if (output.type === "object" || output.type === "text") {
|
|
15400
|
+
return true;
|
|
15401
|
+
}
|
|
15402
|
+
if (typeof output.responseFormat === "function" || typeof output.responseFormat === "object") {
|
|
15403
|
+
return true;
|
|
15404
|
+
}
|
|
15405
|
+
return false;
|
|
15406
|
+
};
|
|
15407
|
+
var serializeOutputObject = (output, model) => {
|
|
15408
|
+
try {
|
|
15409
|
+
const result = {
|
|
15410
|
+
response_format: null
|
|
15411
|
+
};
|
|
15412
|
+
if (output.type) {
|
|
15413
|
+
result.type = output.type;
|
|
15414
|
+
}
|
|
15415
|
+
let responseFormat;
|
|
15416
|
+
if (typeof output.responseFormat === "function") {
|
|
15417
|
+
const mockModelForSchema = {
|
|
15418
|
+
supportsStructuredOutputs: true,
|
|
15419
|
+
...model && typeof model === "object" ? model : {}
|
|
15420
|
+
};
|
|
15421
|
+
responseFormat = output.responseFormat({ model: mockModelForSchema });
|
|
15422
|
+
} else if (output.responseFormat != null && typeof output.responseFormat === "object") {
|
|
15423
|
+
responseFormat = output.responseFormat;
|
|
15424
|
+
}
|
|
15425
|
+
if (responseFormat) {
|
|
15426
|
+
if (typeof responseFormat.then === "function") {
|
|
15427
|
+
result.response_format = Promise.resolve(responseFormat).then(
|
|
15428
|
+
(resolved) => {
|
|
15429
|
+
if (resolved.schema && isZodSchema2(resolved.schema)) {
|
|
15430
|
+
return {
|
|
15431
|
+
...resolved,
|
|
15432
|
+
schema: serializeZodSchema2(resolved.schema)
|
|
15433
|
+
};
|
|
15434
|
+
}
|
|
15435
|
+
return resolved;
|
|
15436
|
+
}
|
|
15437
|
+
);
|
|
15438
|
+
} else {
|
|
15439
|
+
const syncResponseFormat = responseFormat;
|
|
15440
|
+
if (syncResponseFormat.schema && isZodSchema2(syncResponseFormat.schema)) {
|
|
15441
|
+
responseFormat = {
|
|
15442
|
+
...syncResponseFormat,
|
|
15443
|
+
schema: serializeZodSchema2(syncResponseFormat.schema)
|
|
15444
|
+
};
|
|
15445
|
+
}
|
|
15446
|
+
result.response_format = responseFormat;
|
|
15447
|
+
}
|
|
15448
|
+
}
|
|
15449
|
+
return result;
|
|
15450
|
+
} catch {
|
|
15451
|
+
return {
|
|
15452
|
+
response_format: null
|
|
15453
|
+
};
|
|
15454
|
+
}
|
|
15455
|
+
};
|
|
15456
|
+
var processInputAttachmentsSync = (input) => {
|
|
15457
|
+
if (!input) return { input };
|
|
15458
|
+
const processed = { ...input };
|
|
15459
|
+
if (input.messages && Array.isArray(input.messages)) {
|
|
15460
|
+
processed.messages = input.messages.map(processMessage);
|
|
15461
|
+
}
|
|
15462
|
+
if (input.prompt && typeof input.prompt === "object") {
|
|
15463
|
+
if (Array.isArray(input.prompt)) {
|
|
15464
|
+
processed.prompt = input.prompt.map(processMessage);
|
|
15465
|
+
} else {
|
|
15466
|
+
processed.prompt = processPromptContent(input.prompt);
|
|
15467
|
+
}
|
|
15468
|
+
}
|
|
15469
|
+
if (input.schema && isZodSchema2(input.schema)) {
|
|
15470
|
+
processed.schema = serializeZodSchema2(input.schema);
|
|
15471
|
+
}
|
|
15472
|
+
if (input.callOptionsSchema && isZodSchema2(input.callOptionsSchema)) {
|
|
15473
|
+
processed.callOptionsSchema = serializeZodSchema2(input.callOptionsSchema);
|
|
15474
|
+
}
|
|
15475
|
+
if (input.tools) {
|
|
15476
|
+
processed.tools = serializeAISDKToolsForLogging(input.tools);
|
|
15477
|
+
}
|
|
15478
|
+
let outputPromise;
|
|
15479
|
+
if (input.output && isOutputObject(input.output)) {
|
|
15480
|
+
const serialized = serializeOutputObject(input.output, input.model);
|
|
15481
|
+
if (serialized.response_format && typeof serialized.response_format.then === "function") {
|
|
15482
|
+
processed.output = { ...serialized, response_format: {} };
|
|
15483
|
+
outputPromise = serialized.response_format.then(
|
|
15484
|
+
(resolvedFormat) => ({
|
|
15485
|
+
output: { ...serialized, response_format: resolvedFormat }
|
|
15486
|
+
})
|
|
15487
|
+
);
|
|
15488
|
+
} else {
|
|
15489
|
+
processed.output = serialized;
|
|
15490
|
+
}
|
|
15491
|
+
}
|
|
15492
|
+
if ("prepareCall" in processed && typeof processed.prepareCall === "function") {
|
|
15493
|
+
processed.prepareCall = "[Function]";
|
|
15494
|
+
}
|
|
15495
|
+
return { input: processed, outputPromise };
|
|
15496
|
+
};
|
|
15497
|
+
var processMessage = (message) => {
|
|
15498
|
+
if (!message || typeof message !== "object") return message;
|
|
15499
|
+
if (Array.isArray(message.content)) {
|
|
15500
|
+
return {
|
|
15501
|
+
...message,
|
|
15502
|
+
content: message.content.map(processContentPart)
|
|
15503
|
+
};
|
|
15504
|
+
}
|
|
15505
|
+
if (typeof message.content === "object" && message.content !== null) {
|
|
15506
|
+
return {
|
|
15507
|
+
...message,
|
|
15508
|
+
content: processContentPart(message.content)
|
|
15509
|
+
};
|
|
15510
|
+
}
|
|
15511
|
+
return message;
|
|
15512
|
+
};
|
|
15513
|
+
var processPromptContent = (prompt) => {
|
|
15514
|
+
if (Array.isArray(prompt)) {
|
|
15515
|
+
return prompt.map(processContentPart);
|
|
15516
|
+
}
|
|
15517
|
+
if (prompt.content) {
|
|
15518
|
+
if (Array.isArray(prompt.content)) {
|
|
15519
|
+
return {
|
|
15520
|
+
...prompt,
|
|
15521
|
+
content: prompt.content.map(processContentPart)
|
|
15522
|
+
};
|
|
15523
|
+
} else if (typeof prompt.content === "object") {
|
|
15524
|
+
return {
|
|
15525
|
+
...prompt,
|
|
15526
|
+
content: processContentPart(prompt.content)
|
|
15527
|
+
};
|
|
15528
|
+
}
|
|
15529
|
+
}
|
|
15530
|
+
return prompt;
|
|
15531
|
+
};
|
|
15532
|
+
var processContentPart = (part) => {
|
|
15533
|
+
if (!part || typeof part !== "object") return part;
|
|
15534
|
+
try {
|
|
15535
|
+
if (part.type === "image" && part.image) {
|
|
15536
|
+
const imageAttachment = convertImageToAttachment(
|
|
15537
|
+
part.image,
|
|
15538
|
+
part.mimeType || part.mediaType
|
|
15539
|
+
);
|
|
15540
|
+
if (imageAttachment) {
|
|
15541
|
+
return {
|
|
15542
|
+
...part,
|
|
15543
|
+
image: imageAttachment
|
|
15544
|
+
};
|
|
15545
|
+
}
|
|
15546
|
+
}
|
|
15547
|
+
if (part.type === "file" && part.data && (part.mimeType || part.mediaType)) {
|
|
15548
|
+
const fileAttachment = convertDataToAttachment(
|
|
15549
|
+
part.data,
|
|
15550
|
+
part.mimeType || part.mediaType,
|
|
15551
|
+
part.name || part.filename
|
|
15552
|
+
);
|
|
15553
|
+
if (fileAttachment) {
|
|
15554
|
+
return {
|
|
15555
|
+
...part,
|
|
15556
|
+
data: fileAttachment
|
|
15557
|
+
};
|
|
15558
|
+
}
|
|
15559
|
+
}
|
|
15560
|
+
if (part.type === "image_url" && part.image_url) {
|
|
15561
|
+
if (typeof part.image_url === "object" && part.image_url.url) {
|
|
15562
|
+
const imageAttachment = convertImageToAttachment(part.image_url.url);
|
|
15563
|
+
if (imageAttachment) {
|
|
15564
|
+
return {
|
|
15565
|
+
...part,
|
|
15566
|
+
image_url: {
|
|
15567
|
+
...part.image_url,
|
|
15568
|
+
url: imageAttachment
|
|
15569
|
+
}
|
|
15570
|
+
};
|
|
15571
|
+
}
|
|
15572
|
+
}
|
|
15573
|
+
}
|
|
15574
|
+
} catch (error2) {
|
|
15575
|
+
console.warn("Error processing content part:", error2);
|
|
15576
|
+
}
|
|
15577
|
+
return part;
|
|
15578
|
+
};
|
|
15579
|
+
var convertImageToAttachment = (image, explicitMimeType) => {
|
|
15580
|
+
try {
|
|
15581
|
+
if (typeof image === "string" && image.startsWith("data:")) {
|
|
15582
|
+
const [mimeTypeSection, base64Data] = image.split(",");
|
|
15583
|
+
const mimeType = mimeTypeSection.match(/data:(.*?);/)?.[1];
|
|
15584
|
+
if (mimeType && base64Data) {
|
|
15585
|
+
const blob = convertDataToBlob(base64Data, mimeType);
|
|
15586
|
+
if (blob) {
|
|
15587
|
+
return new Attachment({
|
|
15588
|
+
data: blob,
|
|
15589
|
+
filename: `image.${getExtensionFromMediaType(mimeType)}`,
|
|
15590
|
+
contentType: mimeType
|
|
15591
|
+
});
|
|
15592
|
+
}
|
|
15593
|
+
}
|
|
15594
|
+
}
|
|
15595
|
+
if (explicitMimeType) {
|
|
15596
|
+
if (image instanceof Uint8Array) {
|
|
15597
|
+
return new Attachment({
|
|
15598
|
+
data: new Blob([image], { type: explicitMimeType }),
|
|
15599
|
+
filename: `image.${getExtensionFromMediaType(explicitMimeType)}`,
|
|
15600
|
+
contentType: explicitMimeType
|
|
15601
|
+
});
|
|
15602
|
+
}
|
|
15603
|
+
if (typeof Buffer !== "undefined" && Buffer.isBuffer(image)) {
|
|
15604
|
+
return new Attachment({
|
|
15605
|
+
data: new Blob([image], { type: explicitMimeType }),
|
|
15606
|
+
filename: `image.${getExtensionFromMediaType(explicitMimeType)}`,
|
|
15607
|
+
contentType: explicitMimeType
|
|
15608
|
+
});
|
|
15609
|
+
}
|
|
15610
|
+
}
|
|
15611
|
+
if (image instanceof Blob && image.type) {
|
|
15612
|
+
return new Attachment({
|
|
15613
|
+
data: image,
|
|
15614
|
+
filename: `image.${getExtensionFromMediaType(image.type)}`,
|
|
15615
|
+
contentType: image.type
|
|
15616
|
+
});
|
|
15617
|
+
}
|
|
15618
|
+
if (image instanceof Attachment) {
|
|
15619
|
+
return image;
|
|
15620
|
+
}
|
|
15621
|
+
} catch (error2) {
|
|
15622
|
+
console.warn("Error converting image to attachment:", error2);
|
|
15623
|
+
}
|
|
15624
|
+
return null;
|
|
15625
|
+
};
|
|
15626
|
+
var convertDataToAttachment = (data, mimeType, filename) => {
|
|
15627
|
+
if (!mimeType) return null;
|
|
15628
|
+
try {
|
|
15629
|
+
let blob = null;
|
|
15630
|
+
if (typeof data === "string" && data.startsWith("data:")) {
|
|
15631
|
+
const [, base64Data] = data.split(",");
|
|
15632
|
+
if (base64Data) {
|
|
15633
|
+
blob = convertDataToBlob(base64Data, mimeType);
|
|
15634
|
+
}
|
|
15635
|
+
} else if (typeof data === "string" && data.length > 0) {
|
|
15636
|
+
blob = convertDataToBlob(data, mimeType);
|
|
15637
|
+
} else if (data instanceof Uint8Array) {
|
|
15638
|
+
blob = new Blob([data], { type: mimeType });
|
|
15639
|
+
} else if (typeof Buffer !== "undefined" && Buffer.isBuffer(data)) {
|
|
15640
|
+
blob = new Blob([data], { type: mimeType });
|
|
15641
|
+
} else if (data instanceof Blob) {
|
|
15642
|
+
blob = data;
|
|
15643
|
+
}
|
|
15644
|
+
if (blob) {
|
|
15645
|
+
return new Attachment({
|
|
15646
|
+
data: blob,
|
|
15647
|
+
filename: filename || `file.${getExtensionFromMediaType(mimeType)}`,
|
|
15648
|
+
contentType: mimeType
|
|
15649
|
+
});
|
|
15650
|
+
}
|
|
15651
|
+
} catch (error2) {
|
|
15652
|
+
console.warn("Error converting data to attachment:", error2);
|
|
15653
|
+
}
|
|
15654
|
+
return null;
|
|
15655
|
+
};
|
|
15656
|
+
function processAISDKCallInput(params) {
|
|
15657
|
+
return processInputAttachmentsSync(params);
|
|
15658
|
+
}
|
|
15659
|
+
function prepareAISDKCallInput(params, event, span, defaultDenyOutputPaths) {
|
|
15660
|
+
const { input, outputPromise } = processAISDKCallInput(params);
|
|
15661
|
+
if (outputPromise && input && typeof input === "object") {
|
|
15662
|
+
outputPromise.then((resolvedData) => {
|
|
15663
|
+
span.log({
|
|
15664
|
+
input: {
|
|
15665
|
+
...input,
|
|
15666
|
+
...resolvedData
|
|
15667
|
+
}
|
|
15668
|
+
});
|
|
15669
|
+
}).catch(() => {
|
|
15670
|
+
});
|
|
15671
|
+
}
|
|
15672
|
+
const metadata = extractMetadataFromCallParams(params, event.self);
|
|
15673
|
+
const childTracing = prepareAISDKChildTracing(
|
|
15674
|
+
params,
|
|
15675
|
+
event.self,
|
|
15676
|
+
span,
|
|
15677
|
+
defaultDenyOutputPaths,
|
|
15678
|
+
event.aiSDK
|
|
15679
|
+
);
|
|
15680
|
+
event.modelWrapped = childTracing.modelWrapped;
|
|
15681
|
+
if (childTracing.cleanup) {
|
|
15682
|
+
event.__braintrust_ai_sdk_cleanup = childTracing.cleanup;
|
|
15683
|
+
}
|
|
15684
|
+
return {
|
|
15685
|
+
input,
|
|
15686
|
+
metadata
|
|
15687
|
+
};
|
|
15688
|
+
}
|
|
15689
|
+
function prepareAISDKEmbedInput(params, self) {
|
|
15690
|
+
return {
|
|
15691
|
+
input: { ...params },
|
|
15692
|
+
metadata: extractMetadataFromEmbedParams(params, self)
|
|
15693
|
+
};
|
|
15694
|
+
}
|
|
15695
|
+
function extractTopLevelAISDKMetrics(result, event, startTime) {
|
|
15696
|
+
const metrics = hasModelChildTracing(event) ? {} : extractTokenMetrics(result);
|
|
15697
|
+
if (startTime) {
|
|
15698
|
+
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
15699
|
+
}
|
|
15700
|
+
return metrics;
|
|
15701
|
+
}
|
|
15702
|
+
function hasModelChildTracing(event) {
|
|
15703
|
+
return event?.modelWrapped === true || event?.__braintrust_ai_sdk_model_wrapped === true;
|
|
15704
|
+
}
|
|
15705
|
+
function createAISDKIntegrationMetadata() {
|
|
15706
|
+
return {
|
|
15707
|
+
braintrust: {
|
|
15708
|
+
integration_name: "ai-sdk",
|
|
15709
|
+
sdk_language: "typescript"
|
|
15710
|
+
}
|
|
15711
|
+
};
|
|
15712
|
+
}
|
|
15713
|
+
function resolveModelFromSelf(self) {
|
|
15714
|
+
return self && typeof self === "object" && "model" in self && self.model ? self.model : self && typeof self === "object" && "settings" in self && self.settings?.model ? self.settings?.model : void 0;
|
|
15715
|
+
}
|
|
15716
|
+
function extractBaseMetadata(model, self) {
|
|
15717
|
+
const metadata = createAISDKIntegrationMetadata();
|
|
15718
|
+
const { model: modelId, provider } = serializeModelWithProvider(
|
|
15719
|
+
model ?? resolveModelFromSelf(self)
|
|
15720
|
+
);
|
|
15721
|
+
if (modelId) {
|
|
15722
|
+
metadata.model = modelId;
|
|
15723
|
+
}
|
|
15724
|
+
if (provider) {
|
|
15167
15725
|
metadata.provider = provider;
|
|
15168
15726
|
}
|
|
15727
|
+
return metadata;
|
|
15728
|
+
}
|
|
15729
|
+
function extractMetadataFromCallParams(params, self) {
|
|
15730
|
+
const metadata = extractBaseMetadata(params.model, self);
|
|
15169
15731
|
const tools = serializeAISDKToolsForLogging(params.tools);
|
|
15170
15732
|
if (tools) {
|
|
15171
15733
|
metadata.tools = tools;
|
|
15172
15734
|
}
|
|
15173
15735
|
return metadata;
|
|
15174
15736
|
}
|
|
15175
|
-
function
|
|
15737
|
+
function extractMetadataFromEmbedParams(params, self) {
|
|
15738
|
+
return extractBaseMetadata(params.model, self);
|
|
15739
|
+
}
|
|
15740
|
+
function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiSDK) {
|
|
15176
15741
|
const cleanup = [];
|
|
15177
15742
|
const patchedModels = /* @__PURE__ */ new WeakSet();
|
|
15178
15743
|
const patchedTools = /* @__PURE__ */ new WeakSet();
|
|
15179
15744
|
let modelWrapped = false;
|
|
15180
15745
|
const patchModel = (model) => {
|
|
15181
|
-
const resolvedModel = resolveAISDKModel(model);
|
|
15746
|
+
const resolvedModel = resolveAISDKModel(model, aiSDK);
|
|
15182
15747
|
if (!resolvedModel || typeof resolvedModel !== "object" || typeof resolvedModel.doGenerate !== "function" || patchedModels.has(resolvedModel) || resolvedModel[AUTO_PATCHED_MODEL]) {
|
|
15183
|
-
return;
|
|
15748
|
+
return resolvedModel;
|
|
15184
15749
|
}
|
|
15185
15750
|
patchedModels.add(resolvedModel);
|
|
15186
15751
|
resolvedModel[AUTO_PATCHED_MODEL] = true;
|
|
@@ -15209,7 +15774,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths) {
|
|
|
15209
15774
|
type: "llm" /* LLM */
|
|
15210
15775
|
},
|
|
15211
15776
|
event: {
|
|
15212
|
-
input:
|
|
15777
|
+
input: processAISDKCallInput(options).input,
|
|
15213
15778
|
metadata: baseMetadata
|
|
15214
15779
|
}
|
|
15215
15780
|
}
|
|
@@ -15223,7 +15788,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths) {
|
|
|
15223
15788
|
type: "llm" /* LLM */
|
|
15224
15789
|
},
|
|
15225
15790
|
event: {
|
|
15226
|
-
input:
|
|
15791
|
+
input: processAISDKCallInput(options).input,
|
|
15227
15792
|
metadata: baseMetadata
|
|
15228
15793
|
}
|
|
15229
15794
|
});
|
|
@@ -15231,6 +15796,8 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths) {
|
|
|
15231
15796
|
span,
|
|
15232
15797
|
() => Reflect.apply(originalDoStream, resolvedModel, [options])
|
|
15233
15798
|
);
|
|
15799
|
+
const streamStartTime = getCurrentUnixTimestamp();
|
|
15800
|
+
let firstChunkTime;
|
|
15234
15801
|
const output = {};
|
|
15235
15802
|
let text = "";
|
|
15236
15803
|
let reasoning = "";
|
|
@@ -15238,6 +15805,9 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths) {
|
|
|
15238
15805
|
let object = void 0;
|
|
15239
15806
|
const transformStream = new TransformStream({
|
|
15240
15807
|
transform(chunk, controller) {
|
|
15808
|
+
if (firstChunkTime === void 0) {
|
|
15809
|
+
firstChunkTime = getCurrentUnixTimestamp();
|
|
15810
|
+
}
|
|
15241
15811
|
switch (chunk.type) {
|
|
15242
15812
|
case "text-delta":
|
|
15243
15813
|
text += extractTextDelta(chunk);
|
|
@@ -15278,12 +15848,19 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths) {
|
|
|
15278
15848
|
if (object !== void 0) {
|
|
15279
15849
|
output.object = object;
|
|
15280
15850
|
}
|
|
15851
|
+
const metrics = extractTokenMetrics(output);
|
|
15852
|
+
if (firstChunkTime !== void 0) {
|
|
15853
|
+
metrics.time_to_first_token = Math.max(
|
|
15854
|
+
firstChunkTime - streamStartTime,
|
|
15855
|
+
1e-6
|
|
15856
|
+
);
|
|
15857
|
+
}
|
|
15281
15858
|
span.log({
|
|
15282
15859
|
output: processAISDKOutput(
|
|
15283
15860
|
output,
|
|
15284
15861
|
denyOutputPaths
|
|
15285
15862
|
),
|
|
15286
|
-
metrics
|
|
15863
|
+
metrics,
|
|
15287
15864
|
...buildResolvedMetadataPayload(output)
|
|
15288
15865
|
});
|
|
15289
15866
|
span.end();
|
|
@@ -15305,6 +15882,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths) {
|
|
|
15305
15882
|
}
|
|
15306
15883
|
delete resolvedModel[AUTO_PATCHED_MODEL];
|
|
15307
15884
|
});
|
|
15885
|
+
return resolvedModel;
|
|
15308
15886
|
};
|
|
15309
15887
|
const patchTool = (tool, name) => {
|
|
15310
15888
|
if (tool == null || typeof tool !== "object" || !("execute" in tool) || typeof tool.execute !== "function" || patchedTools.has(tool) || tool[AUTO_PATCHED_TOOL]) {
|
|
@@ -15377,17 +15955,26 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths) {
|
|
|
15377
15955
|
}
|
|
15378
15956
|
};
|
|
15379
15957
|
if (params && typeof params === "object") {
|
|
15380
|
-
patchModel(params.model);
|
|
15958
|
+
const patchedParamModel = patchModel(params.model);
|
|
15959
|
+
if (typeof params.model === "string" && patchedParamModel && typeof patchedParamModel === "object") {
|
|
15960
|
+
params.model = patchedParamModel;
|
|
15961
|
+
}
|
|
15381
15962
|
patchTools(params.tools);
|
|
15382
15963
|
}
|
|
15383
15964
|
if (self && typeof self === "object") {
|
|
15384
15965
|
const selfRecord = self;
|
|
15385
15966
|
if (selfRecord.model !== void 0) {
|
|
15386
|
-
patchModel(selfRecord.model);
|
|
15967
|
+
const patchedSelfModel = patchModel(selfRecord.model);
|
|
15968
|
+
if (typeof selfRecord.model === "string" && patchedSelfModel && typeof patchedSelfModel === "object") {
|
|
15969
|
+
selfRecord.model = patchedSelfModel;
|
|
15970
|
+
}
|
|
15387
15971
|
}
|
|
15388
15972
|
if (selfRecord.settings && typeof selfRecord.settings === "object") {
|
|
15389
15973
|
if (selfRecord.settings.model !== void 0) {
|
|
15390
|
-
patchModel(selfRecord.settings.model);
|
|
15974
|
+
const patchedSettingsModel = patchModel(selfRecord.settings.model);
|
|
15975
|
+
if (typeof selfRecord.settings.model === "string" && patchedSettingsModel && typeof patchedSettingsModel === "object") {
|
|
15976
|
+
selfRecord.settings.model = patchedSettingsModel;
|
|
15977
|
+
}
|
|
15391
15978
|
}
|
|
15392
15979
|
if (selfRecord.settings.tools !== void 0) {
|
|
15393
15980
|
patchTools(selfRecord.settings.tools);
|
|
@@ -15411,63 +15998,178 @@ function finalizeAISDKChildTracing(event) {
|
|
|
15411
15998
|
}
|
|
15412
15999
|
}
|
|
15413
16000
|
function patchAISDKStreamingResult(args) {
|
|
15414
|
-
const {
|
|
16001
|
+
const { defaultDenyOutputPaths, endEvent, result, span, startTime } = args;
|
|
15415
16002
|
if (!result || typeof result !== "object") {
|
|
15416
16003
|
return false;
|
|
15417
16004
|
}
|
|
15418
16005
|
const resultRecord = result;
|
|
15419
|
-
|
|
16006
|
+
attachKnownResultPromiseHandlers(resultRecord);
|
|
16007
|
+
if (isReadableStreamLike(resultRecord.baseStream)) {
|
|
16008
|
+
let firstChunkTime2;
|
|
16009
|
+
const wrappedBaseStream = resultRecord.baseStream.pipeThrough(
|
|
16010
|
+
new TransformStream({
|
|
16011
|
+
transform(chunk, controller) {
|
|
16012
|
+
if (firstChunkTime2 === void 0) {
|
|
16013
|
+
firstChunkTime2 = getCurrentUnixTimestamp();
|
|
16014
|
+
}
|
|
16015
|
+
controller.enqueue(chunk);
|
|
16016
|
+
},
|
|
16017
|
+
async flush() {
|
|
16018
|
+
const metrics = extractTopLevelAISDKMetrics(result, endEvent);
|
|
16019
|
+
if (metrics.time_to_first_token === void 0 && firstChunkTime2 !== void 0) {
|
|
16020
|
+
metrics.time_to_first_token = firstChunkTime2 - startTime;
|
|
16021
|
+
}
|
|
16022
|
+
const output = await processAISDKStreamingOutput(
|
|
16023
|
+
result,
|
|
16024
|
+
resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
|
|
16025
|
+
);
|
|
16026
|
+
const metadata = buildResolvedMetadataPayload(result).metadata;
|
|
16027
|
+
span.log({
|
|
16028
|
+
output,
|
|
16029
|
+
...metadata ? { metadata } : {},
|
|
16030
|
+
metrics
|
|
16031
|
+
});
|
|
16032
|
+
finalizeAISDKChildTracing(endEvent);
|
|
16033
|
+
span.end();
|
|
16034
|
+
}
|
|
16035
|
+
})
|
|
16036
|
+
);
|
|
16037
|
+
Object.defineProperty(resultRecord, "baseStream", {
|
|
16038
|
+
configurable: true,
|
|
16039
|
+
enumerable: true,
|
|
16040
|
+
value: wrappedBaseStream,
|
|
16041
|
+
writable: true
|
|
16042
|
+
});
|
|
16043
|
+
return true;
|
|
16044
|
+
}
|
|
16045
|
+
const streamField = findAsyncIterableField(resultRecord, [
|
|
16046
|
+
"partialObjectStream",
|
|
16047
|
+
"textStream",
|
|
16048
|
+
"fullStream",
|
|
16049
|
+
"stream"
|
|
16050
|
+
]);
|
|
16051
|
+
if (!streamField) {
|
|
15420
16052
|
return false;
|
|
15421
16053
|
}
|
|
15422
16054
|
let firstChunkTime;
|
|
15423
|
-
const
|
|
15424
|
-
|
|
15425
|
-
|
|
15426
|
-
|
|
15427
|
-
firstChunkTime = getCurrentUnixTimestamp();
|
|
15428
|
-
}
|
|
15429
|
-
controller.enqueue(chunk);
|
|
15430
|
-
},
|
|
15431
|
-
async flush() {
|
|
15432
|
-
const metrics = extractTopLevelAISDKMetrics(result, endEvent);
|
|
15433
|
-
if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
|
|
15434
|
-
metrics.time_to_first_token = firstChunkTime - startTime;
|
|
15435
|
-
}
|
|
15436
|
-
const output = await processAISDKStreamingOutput(
|
|
15437
|
-
result,
|
|
15438
|
-
denyOutputPaths
|
|
15439
|
-
);
|
|
15440
|
-
const metadata = buildResolvedMetadataPayload(result).metadata;
|
|
15441
|
-
span.log({
|
|
15442
|
-
output,
|
|
15443
|
-
...metadata ? { metadata } : {},
|
|
15444
|
-
metrics
|
|
15445
|
-
});
|
|
15446
|
-
finalizeAISDKChildTracing(endEvent);
|
|
15447
|
-
span.end();
|
|
16055
|
+
const wrappedStream = createPatchedAsyncIterable(streamField.stream, {
|
|
16056
|
+
onChunk: () => {
|
|
16057
|
+
if (firstChunkTime === void 0) {
|
|
16058
|
+
firstChunkTime = getCurrentUnixTimestamp();
|
|
15448
16059
|
}
|
|
15449
|
-
}
|
|
15450
|
-
|
|
15451
|
-
|
|
16060
|
+
},
|
|
16061
|
+
onComplete: async () => {
|
|
16062
|
+
const metrics = extractTopLevelAISDKMetrics(result, endEvent);
|
|
16063
|
+
if (metrics.time_to_first_token === void 0 && firstChunkTime !== void 0) {
|
|
16064
|
+
metrics.time_to_first_token = firstChunkTime - startTime;
|
|
16065
|
+
}
|
|
16066
|
+
const output = await processAISDKStreamingOutput(
|
|
16067
|
+
result,
|
|
16068
|
+
resolveDenyOutputPaths(endEvent, defaultDenyOutputPaths)
|
|
16069
|
+
);
|
|
16070
|
+
const metadata = buildResolvedMetadataPayload(result).metadata;
|
|
16071
|
+
span.log({
|
|
16072
|
+
output,
|
|
16073
|
+
...metadata ? { metadata } : {},
|
|
16074
|
+
metrics
|
|
16075
|
+
});
|
|
16076
|
+
finalizeAISDKChildTracing(endEvent);
|
|
16077
|
+
span.end();
|
|
16078
|
+
},
|
|
16079
|
+
onError: (error2) => {
|
|
16080
|
+
span.log({
|
|
16081
|
+
error: error2.message
|
|
16082
|
+
});
|
|
16083
|
+
finalizeAISDKChildTracing(endEvent);
|
|
16084
|
+
span.end();
|
|
16085
|
+
}
|
|
16086
|
+
});
|
|
16087
|
+
Object.defineProperty(resultRecord, streamField.field, {
|
|
15452
16088
|
configurable: true,
|
|
15453
16089
|
enumerable: true,
|
|
15454
|
-
value:
|
|
16090
|
+
value: wrappedStream,
|
|
15455
16091
|
writable: true
|
|
15456
16092
|
});
|
|
15457
16093
|
return true;
|
|
15458
16094
|
}
|
|
16095
|
+
function attachKnownResultPromiseHandlers(result) {
|
|
16096
|
+
const promiseLikeFields = [
|
|
16097
|
+
"content",
|
|
16098
|
+
"text",
|
|
16099
|
+
"object",
|
|
16100
|
+
"value",
|
|
16101
|
+
"values",
|
|
16102
|
+
"finishReason",
|
|
16103
|
+
"embedding",
|
|
16104
|
+
"embeddings",
|
|
16105
|
+
"usage",
|
|
16106
|
+
"totalUsage",
|
|
16107
|
+
"responses",
|
|
16108
|
+
"steps"
|
|
16109
|
+
];
|
|
16110
|
+
for (const field of promiseLikeFields) {
|
|
16111
|
+
try {
|
|
16112
|
+
if (!(field in result)) {
|
|
16113
|
+
continue;
|
|
16114
|
+
}
|
|
16115
|
+
const value = result[field];
|
|
16116
|
+
if (isPromiseLike(value)) {
|
|
16117
|
+
void Promise.resolve(value).catch(() => {
|
|
16118
|
+
});
|
|
16119
|
+
}
|
|
16120
|
+
} catch {
|
|
16121
|
+
}
|
|
16122
|
+
}
|
|
16123
|
+
}
|
|
15459
16124
|
function isReadableStreamLike(value) {
|
|
15460
16125
|
return value != null && typeof value === "object" && typeof value.pipeThrough === "function";
|
|
15461
16126
|
}
|
|
16127
|
+
function isAsyncIterableLike(value) {
|
|
16128
|
+
return value != null && typeof value === "object" && typeof value[Symbol.asyncIterator] === "function";
|
|
16129
|
+
}
|
|
16130
|
+
function findAsyncIterableField(result, candidateFields) {
|
|
16131
|
+
for (const field of candidateFields) {
|
|
16132
|
+
try {
|
|
16133
|
+
const stream = result[field];
|
|
16134
|
+
if (isAsyncIterableLike(stream)) {
|
|
16135
|
+
return { field, stream };
|
|
16136
|
+
}
|
|
16137
|
+
} catch {
|
|
16138
|
+
}
|
|
16139
|
+
}
|
|
16140
|
+
return null;
|
|
16141
|
+
}
|
|
16142
|
+
function createPatchedAsyncIterable(stream, hooks) {
|
|
16143
|
+
return {
|
|
16144
|
+
async *[Symbol.asyncIterator]() {
|
|
16145
|
+
try {
|
|
16146
|
+
for await (const chunk of stream) {
|
|
16147
|
+
hooks.onChunk(chunk);
|
|
16148
|
+
yield chunk;
|
|
16149
|
+
}
|
|
16150
|
+
await hooks.onComplete();
|
|
16151
|
+
} catch (error2) {
|
|
16152
|
+
hooks.onError(
|
|
16153
|
+
error2 instanceof Error ? error2 : new Error(String(error2))
|
|
16154
|
+
);
|
|
16155
|
+
throw error2;
|
|
16156
|
+
}
|
|
16157
|
+
}
|
|
16158
|
+
};
|
|
16159
|
+
}
|
|
15462
16160
|
async function processAISDKStreamingOutput(result, denyOutputPaths) {
|
|
15463
16161
|
const output = processAISDKOutput(result, denyOutputPaths);
|
|
15464
16162
|
if (!output || typeof output !== "object") {
|
|
15465
16163
|
return output;
|
|
15466
16164
|
}
|
|
15467
16165
|
const outputRecord = output;
|
|
16166
|
+
const isObjectStreamingResult = result != null && typeof result === "object" && "partialObjectStream" in result;
|
|
15468
16167
|
try {
|
|
15469
|
-
if ("text" in result
|
|
15470
|
-
|
|
16168
|
+
if (!isObjectStreamingResult && "text" in result) {
|
|
16169
|
+
const resolvedText = await Promise.resolve(result.text);
|
|
16170
|
+
if (typeof resolvedText === "string") {
|
|
16171
|
+
outputRecord.text = resolvedText;
|
|
16172
|
+
}
|
|
15471
16173
|
}
|
|
15472
16174
|
} catch {
|
|
15473
16175
|
}
|
|
@@ -15480,6 +16182,15 @@ async function processAISDKStreamingOutput(result, denyOutputPaths) {
|
|
|
15480
16182
|
}
|
|
15481
16183
|
} catch {
|
|
15482
16184
|
}
|
|
16185
|
+
try {
|
|
16186
|
+
if ("finishReason" in result) {
|
|
16187
|
+
const resolvedFinishReason = await Promise.resolve(result.finishReason);
|
|
16188
|
+
if (resolvedFinishReason !== void 0) {
|
|
16189
|
+
outputRecord.finishReason = resolvedFinishReason;
|
|
16190
|
+
}
|
|
16191
|
+
}
|
|
16192
|
+
} catch {
|
|
16193
|
+
}
|
|
15483
16194
|
return outputRecord;
|
|
15484
16195
|
}
|
|
15485
16196
|
function buildAISDKChildMetadata(model) {
|
|
@@ -15502,16 +16213,25 @@ function buildResolvedMetadataPayload(result) {
|
|
|
15502
16213
|
if (gatewayInfo?.model) {
|
|
15503
16214
|
metadata.model = gatewayInfo.model;
|
|
15504
16215
|
}
|
|
15505
|
-
|
|
15506
|
-
|
|
15507
|
-
|
|
15508
|
-
|
|
16216
|
+
let finishReason;
|
|
16217
|
+
try {
|
|
16218
|
+
finishReason = result.finishReason;
|
|
16219
|
+
} catch {
|
|
16220
|
+
finishReason = void 0;
|
|
16221
|
+
}
|
|
16222
|
+
if (isPromiseLike(finishReason)) {
|
|
16223
|
+
void Promise.resolve(finishReason).catch(() => {
|
|
16224
|
+
});
|
|
16225
|
+
} else if (finishReason !== void 0) {
|
|
16226
|
+
metadata.finish_reason = finishReason;
|
|
16227
|
+
}
|
|
16228
|
+
return Object.keys(metadata).length > 0 ? { metadata } : {};
|
|
15509
16229
|
}
|
|
15510
|
-
function resolveAISDKModel(model) {
|
|
16230
|
+
function resolveAISDKModel(model, aiSDK) {
|
|
15511
16231
|
if (typeof model !== "string") {
|
|
15512
16232
|
return model;
|
|
15513
16233
|
}
|
|
15514
|
-
const provider = globalThis.AI_SDK_DEFAULT_PROVIDER ?? null;
|
|
16234
|
+
const provider = globalThis.AI_SDK_DEFAULT_PROVIDER ?? aiSDK?.gateway ?? null;
|
|
15515
16235
|
if (provider && typeof provider.languageModel === "function") {
|
|
15516
16236
|
return provider.languageModel(model);
|
|
15517
16237
|
}
|
|
@@ -15532,17 +16252,49 @@ function processAISDKOutput(output, denyOutputPaths) {
|
|
|
15532
16252
|
const merged = extractSerializableOutputFields(output);
|
|
15533
16253
|
return normalizeAISDKLoggedOutput(omit(merged, denyOutputPaths));
|
|
15534
16254
|
}
|
|
16255
|
+
function processAISDKEmbeddingOutput(output, denyOutputPaths) {
|
|
16256
|
+
if (!output || typeof output !== "object") {
|
|
16257
|
+
return output;
|
|
16258
|
+
}
|
|
16259
|
+
const summarized = {};
|
|
16260
|
+
const whitelistedFields = [
|
|
16261
|
+
"usage",
|
|
16262
|
+
"totalUsage",
|
|
16263
|
+
"warnings",
|
|
16264
|
+
"providerMetadata",
|
|
16265
|
+
"experimental_providerMetadata"
|
|
16266
|
+
];
|
|
16267
|
+
for (const field of whitelistedFields) {
|
|
16268
|
+
const value = safeSerializableFieldRead(output, field);
|
|
16269
|
+
if (value !== void 0 && isSerializableOutputValue(value)) {
|
|
16270
|
+
summarized[field] = value;
|
|
16271
|
+
}
|
|
16272
|
+
}
|
|
16273
|
+
const embedding = safeSerializableFieldRead(output, "embedding");
|
|
16274
|
+
if (Array.isArray(embedding)) {
|
|
16275
|
+
summarized.embedding_length = embedding.length;
|
|
16276
|
+
}
|
|
16277
|
+
const embeddings = safeSerializableFieldRead(output, "embeddings");
|
|
16278
|
+
if (Array.isArray(embeddings)) {
|
|
16279
|
+
summarized.embedding_count = embeddings.length;
|
|
16280
|
+
const firstEmbedding = embeddings.find((item) => Array.isArray(item));
|
|
16281
|
+
if (Array.isArray(firstEmbedding)) {
|
|
16282
|
+
summarized.embedding_length = firstEmbedding.length;
|
|
16283
|
+
}
|
|
16284
|
+
}
|
|
16285
|
+
return normalizeAISDKLoggedOutput(omit(summarized, denyOutputPaths));
|
|
16286
|
+
}
|
|
15535
16287
|
function extractTokenMetrics(result) {
|
|
15536
16288
|
const metrics = {};
|
|
15537
|
-
let usage
|
|
15538
|
-
|
|
15539
|
-
|
|
15540
|
-
|
|
15541
|
-
|
|
15542
|
-
|
|
15543
|
-
|
|
15544
|
-
|
|
15545
|
-
|
|
16289
|
+
let usage;
|
|
16290
|
+
const totalUsageValue = safeResultFieldRead(result, "totalUsage");
|
|
16291
|
+
if (totalUsageValue !== void 0 && !isPromiseLike(totalUsageValue)) {
|
|
16292
|
+
usage = totalUsageValue;
|
|
16293
|
+
}
|
|
16294
|
+
if (!usage) {
|
|
16295
|
+
const usageValue = safeResultFieldRead(result, "usage");
|
|
16296
|
+
if (usageValue !== void 0 && !isPromiseLike(usageValue)) {
|
|
16297
|
+
usage = usageValue;
|
|
15546
16298
|
}
|
|
15547
16299
|
}
|
|
15548
16300
|
if (!usage) {
|
|
@@ -15580,6 +16332,22 @@ function extractTokenMetrics(result) {
|
|
|
15580
16332
|
}
|
|
15581
16333
|
return metrics;
|
|
15582
16334
|
}
|
|
16335
|
+
function safeResultFieldRead(result, field) {
|
|
16336
|
+
return safeSerializableFieldRead(result, field);
|
|
16337
|
+
}
|
|
16338
|
+
function safeSerializableFieldRead(obj, field) {
|
|
16339
|
+
try {
|
|
16340
|
+
const value = obj?.[field];
|
|
16341
|
+
if (isPromiseLike(value)) {
|
|
16342
|
+
void Promise.resolve(value).catch(() => {
|
|
16343
|
+
});
|
|
16344
|
+
return void 0;
|
|
16345
|
+
}
|
|
16346
|
+
return value;
|
|
16347
|
+
} catch {
|
|
16348
|
+
return void 0;
|
|
16349
|
+
}
|
|
16350
|
+
}
|
|
15583
16351
|
function aggregateAISDKChunks(chunks, _result, endEvent) {
|
|
15584
16352
|
const lastChunk = chunks[chunks.length - 1];
|
|
15585
16353
|
const output = {};
|
|
@@ -15588,17 +16356,21 @@ function aggregateAISDKChunks(chunks, _result, endEvent) {
|
|
|
15588
16356
|
if (lastChunk) {
|
|
15589
16357
|
metrics = hasModelChildTracing(endEvent) ? {} : extractTokenMetrics(lastChunk);
|
|
15590
16358
|
metadata = buildResolvedMetadataPayload(lastChunk).metadata;
|
|
15591
|
-
|
|
15592
|
-
|
|
16359
|
+
const text = safeSerializableFieldRead(lastChunk, "text");
|
|
16360
|
+
if (text !== void 0) {
|
|
16361
|
+
output.text = text;
|
|
15593
16362
|
}
|
|
15594
|
-
|
|
15595
|
-
|
|
16363
|
+
const objectValue = safeSerializableFieldRead(lastChunk, "object");
|
|
16364
|
+
if (objectValue !== void 0) {
|
|
16365
|
+
output.object = objectValue;
|
|
15596
16366
|
}
|
|
15597
|
-
|
|
15598
|
-
|
|
16367
|
+
const finishReason = safeSerializableFieldRead(lastChunk, "finishReason");
|
|
16368
|
+
if (finishReason !== void 0) {
|
|
16369
|
+
output.finishReason = finishReason;
|
|
15599
16370
|
}
|
|
15600
|
-
|
|
15601
|
-
|
|
16371
|
+
const toolCalls = safeSerializableFieldRead(lastChunk, "toolCalls");
|
|
16372
|
+
if (toolCalls !== void 0) {
|
|
16373
|
+
output.toolCalls = toolCalls;
|
|
15602
16374
|
}
|
|
15603
16375
|
}
|
|
15604
16376
|
finalizeAISDKChildTracing(endEvent);
|
|
@@ -15607,14 +16379,20 @@ function aggregateAISDKChunks(chunks, _result, endEvent) {
|
|
|
15607
16379
|
function extractGetterValues(obj) {
|
|
15608
16380
|
const getterValues = {};
|
|
15609
16381
|
const getterNames = [
|
|
16382
|
+
"content",
|
|
15610
16383
|
"text",
|
|
15611
16384
|
"object",
|
|
16385
|
+
"value",
|
|
16386
|
+
"values",
|
|
16387
|
+
"embedding",
|
|
16388
|
+
"embeddings",
|
|
15612
16389
|
"finishReason",
|
|
15613
16390
|
"usage",
|
|
15614
16391
|
"totalUsage",
|
|
15615
16392
|
"toolCalls",
|
|
15616
16393
|
"toolResults",
|
|
15617
16394
|
"warnings",
|
|
16395
|
+
"responses",
|
|
15618
16396
|
"experimental_providerMetadata",
|
|
15619
16397
|
"providerMetadata",
|
|
15620
16398
|
"rawResponse",
|
|
@@ -15622,8 +16400,17 @@ function extractGetterValues(obj) {
|
|
|
15622
16400
|
];
|
|
15623
16401
|
for (const name of getterNames) {
|
|
15624
16402
|
try {
|
|
15625
|
-
if (obj
|
|
15626
|
-
|
|
16403
|
+
if (!obj || !(name in obj)) {
|
|
16404
|
+
continue;
|
|
16405
|
+
}
|
|
16406
|
+
const value = obj[name];
|
|
16407
|
+
if (isPromiseLike(value)) {
|
|
16408
|
+
void Promise.resolve(value).catch(() => {
|
|
16409
|
+
});
|
|
16410
|
+
continue;
|
|
16411
|
+
}
|
|
16412
|
+
if (isSerializableOutputValue(value)) {
|
|
16413
|
+
getterValues[name] = value;
|
|
15627
16414
|
}
|
|
15628
16415
|
} catch {
|
|
15629
16416
|
}
|
|
@@ -15645,6 +16432,11 @@ function extractSerializableOutputFields(output) {
|
|
|
15645
16432
|
for (const name of directFieldNames) {
|
|
15646
16433
|
try {
|
|
15647
16434
|
const value = output?.[name];
|
|
16435
|
+
if (isPromiseLike(value)) {
|
|
16436
|
+
void Promise.resolve(value).catch(() => {
|
|
16437
|
+
});
|
|
16438
|
+
continue;
|
|
16439
|
+
}
|
|
15648
16440
|
if (isSerializableOutputValue(value)) {
|
|
15649
16441
|
serialized[name] = value;
|
|
15650
16442
|
}
|
|
@@ -15656,6 +16448,9 @@ function extractSerializableOutputFields(output) {
|
|
|
15656
16448
|
...extractGetterValues(output)
|
|
15657
16449
|
};
|
|
15658
16450
|
}
|
|
16451
|
+
function isPromiseLike(value) {
|
|
16452
|
+
return value != null && typeof value === "object" && typeof value.then === "function";
|
|
16453
|
+
}
|
|
15659
16454
|
function isSerializableOutputValue(value) {
|
|
15660
16455
|
if (typeof value === "function") {
|
|
15661
16456
|
return false;
|
|
@@ -15697,8 +16492,9 @@ function parseGatewayModelString(modelString) {
|
|
|
15697
16492
|
return { model: modelString };
|
|
15698
16493
|
}
|
|
15699
16494
|
function extractGatewayRoutingInfo(result) {
|
|
15700
|
-
|
|
15701
|
-
|
|
16495
|
+
const steps = safeSerializableFieldRead(result, "steps");
|
|
16496
|
+
if (Array.isArray(steps) && steps.length > 0) {
|
|
16497
|
+
const routing2 = steps[0]?.providerMetadata?.gateway?.routing;
|
|
15702
16498
|
if (routing2) {
|
|
15703
16499
|
return {
|
|
15704
16500
|
provider: routing2.resolvedProvider || routing2.finalProvider,
|
|
@@ -15706,7 +16502,11 @@ function extractGatewayRoutingInfo(result) {
|
|
|
15706
16502
|
};
|
|
15707
16503
|
}
|
|
15708
16504
|
}
|
|
15709
|
-
const
|
|
16505
|
+
const providerMetadata = safeSerializableFieldRead(
|
|
16506
|
+
result,
|
|
16507
|
+
"providerMetadata"
|
|
16508
|
+
);
|
|
16509
|
+
const routing = providerMetadata?.gateway?.routing;
|
|
15710
16510
|
if (routing) {
|
|
15711
16511
|
return {
|
|
15712
16512
|
provider: routing.resolvedProvider || routing.finalProvider,
|
|
@@ -15716,10 +16516,11 @@ function extractGatewayRoutingInfo(result) {
|
|
|
15716
16516
|
return null;
|
|
15717
16517
|
}
|
|
15718
16518
|
function extractCostFromResult(result) {
|
|
15719
|
-
|
|
16519
|
+
const steps = safeSerializableFieldRead(result, "steps");
|
|
16520
|
+
if (Array.isArray(steps) && steps.length > 0) {
|
|
15720
16521
|
let totalCost = 0;
|
|
15721
16522
|
let foundCost = false;
|
|
15722
|
-
for (const step of
|
|
16523
|
+
for (const step of steps) {
|
|
15723
16524
|
const gateway2 = step?.providerMetadata?.gateway;
|
|
15724
16525
|
const stepCost = parseGatewayCost(gateway2?.cost) || parseGatewayCost(gateway2?.marketCost);
|
|
15725
16526
|
if (stepCost !== void 0 && stepCost > 0) {
|
|
@@ -15731,7 +16532,11 @@ function extractCostFromResult(result) {
|
|
|
15731
16532
|
return totalCost;
|
|
15732
16533
|
}
|
|
15733
16534
|
}
|
|
15734
|
-
const
|
|
16535
|
+
const providerMetadata = safeSerializableFieldRead(
|
|
16536
|
+
result,
|
|
16537
|
+
"providerMetadata"
|
|
16538
|
+
);
|
|
16539
|
+
const gateway = providerMetadata?.gateway;
|
|
15735
16540
|
const directCost = parseGatewayCost(gateway?.cost) || parseGatewayCost(gateway?.marketCost);
|
|
15736
16541
|
if (directCost !== void 0 && directCost > 0) {
|
|
15737
16542
|
return directCost;
|
|
@@ -15848,7 +16653,307 @@ var claudeAgentSDKChannels = defineChannels(
|
|
|
15848
16653
|
}
|
|
15849
16654
|
);
|
|
15850
16655
|
|
|
16656
|
+
// src/instrumentation/plugins/claude-agent-sdk-instrumentation-constants.ts
|
|
16657
|
+
var CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION = "__braintrust_skip_local_tool_hooks";
|
|
16658
|
+
|
|
16659
|
+
// src/instrumentation/plugins/claude-agent-sdk-local-tool-context.ts
|
|
16660
|
+
var LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED = Symbol.for(
|
|
16661
|
+
"braintrust.claude_agent_sdk.local_tool_context_async_iterator_patched"
|
|
16662
|
+
);
|
|
16663
|
+
function createLocalToolContextStore() {
|
|
16664
|
+
const maybeIsoWithAsyncLocalStorage = isomorph_default;
|
|
16665
|
+
if (typeof maybeIsoWithAsyncLocalStorage.newAsyncLocalStorage === "function") {
|
|
16666
|
+
return maybeIsoWithAsyncLocalStorage.newAsyncLocalStorage();
|
|
16667
|
+
}
|
|
16668
|
+
let currentStore;
|
|
16669
|
+
return {
|
|
16670
|
+
enterWith(store) {
|
|
16671
|
+
currentStore = store;
|
|
16672
|
+
},
|
|
16673
|
+
getStore() {
|
|
16674
|
+
return currentStore;
|
|
16675
|
+
},
|
|
16676
|
+
run(store, callback) {
|
|
16677
|
+
const previousStore = currentStore;
|
|
16678
|
+
currentStore = store;
|
|
16679
|
+
try {
|
|
16680
|
+
return callback();
|
|
16681
|
+
} finally {
|
|
16682
|
+
currentStore = previousStore;
|
|
16683
|
+
}
|
|
16684
|
+
}
|
|
16685
|
+
};
|
|
16686
|
+
}
|
|
16687
|
+
var localToolContextStore = createLocalToolContextStore();
|
|
16688
|
+
var fallbackLocalToolParentResolver;
|
|
16689
|
+
function createClaudeLocalToolContext() {
|
|
16690
|
+
return {};
|
|
16691
|
+
}
|
|
16692
|
+
function runWithClaudeLocalToolContext(callback, context2) {
|
|
16693
|
+
return localToolContextStore.run(
|
|
16694
|
+
context2 ?? createClaudeLocalToolContext(),
|
|
16695
|
+
callback
|
|
16696
|
+
);
|
|
16697
|
+
}
|
|
16698
|
+
function ensureClaudeLocalToolContext() {
|
|
16699
|
+
const existing = localToolContextStore.getStore();
|
|
16700
|
+
if (existing) {
|
|
16701
|
+
return existing;
|
|
16702
|
+
}
|
|
16703
|
+
const created = {};
|
|
16704
|
+
localToolContextStore.enterWith(created);
|
|
16705
|
+
return created;
|
|
16706
|
+
}
|
|
16707
|
+
function setClaudeLocalToolParentResolver(resolver) {
|
|
16708
|
+
fallbackLocalToolParentResolver = resolver;
|
|
16709
|
+
const context2 = ensureClaudeLocalToolContext();
|
|
16710
|
+
if (!context2) {
|
|
16711
|
+
return;
|
|
16712
|
+
}
|
|
16713
|
+
context2.resolveLocalToolParent = resolver;
|
|
16714
|
+
}
|
|
16715
|
+
function getClaudeLocalToolParentResolver() {
|
|
16716
|
+
return localToolContextStore.getStore()?.resolveLocalToolParent ?? fallbackLocalToolParentResolver;
|
|
16717
|
+
}
|
|
16718
|
+
function isAsyncIterable4(value) {
|
|
16719
|
+
return value !== null && typeof value === "object" && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
|
|
16720
|
+
}
|
|
16721
|
+
function bindClaudeLocalToolContextToAsyncIterable(result, localToolContext) {
|
|
16722
|
+
if (!isAsyncIterable4(result) || Object.isFrozen(result) || Object.isSealed(result)) {
|
|
16723
|
+
return result;
|
|
16724
|
+
}
|
|
16725
|
+
const stream = result;
|
|
16726
|
+
const originalAsyncIterator = stream[Symbol.asyncIterator];
|
|
16727
|
+
if (originalAsyncIterator[LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED]) {
|
|
16728
|
+
return result;
|
|
16729
|
+
}
|
|
16730
|
+
const patchedAsyncIterator = function() {
|
|
16731
|
+
return runWithClaudeLocalToolContext(() => {
|
|
16732
|
+
const iterator = Reflect.apply(originalAsyncIterator, this, []);
|
|
16733
|
+
if (!iterator || typeof iterator !== "object") {
|
|
16734
|
+
return iterator;
|
|
16735
|
+
}
|
|
16736
|
+
const patchMethod = (methodName) => {
|
|
16737
|
+
const originalMethod = Reflect.get(iterator, methodName);
|
|
16738
|
+
if (typeof originalMethod !== "function") {
|
|
16739
|
+
return;
|
|
16740
|
+
}
|
|
16741
|
+
Reflect.set(
|
|
16742
|
+
iterator,
|
|
16743
|
+
methodName,
|
|
16744
|
+
(...args) => runWithClaudeLocalToolContext(
|
|
16745
|
+
() => Reflect.apply(
|
|
16746
|
+
originalMethod,
|
|
16747
|
+
iterator,
|
|
16748
|
+
args
|
|
16749
|
+
),
|
|
16750
|
+
localToolContext
|
|
16751
|
+
)
|
|
16752
|
+
);
|
|
16753
|
+
};
|
|
16754
|
+
patchMethod("next");
|
|
16755
|
+
patchMethod("return");
|
|
16756
|
+
patchMethod("throw");
|
|
16757
|
+
return iterator;
|
|
16758
|
+
}, localToolContext);
|
|
16759
|
+
};
|
|
16760
|
+
Object.defineProperty(
|
|
16761
|
+
patchedAsyncIterator,
|
|
16762
|
+
LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED,
|
|
16763
|
+
{
|
|
16764
|
+
configurable: false,
|
|
16765
|
+
enumerable: false,
|
|
16766
|
+
value: true,
|
|
16767
|
+
writable: false
|
|
16768
|
+
}
|
|
16769
|
+
);
|
|
16770
|
+
Reflect.set(stream, Symbol.asyncIterator, patchedAsyncIterator);
|
|
16771
|
+
return result;
|
|
16772
|
+
}
|
|
16773
|
+
|
|
16774
|
+
// src/instrumentation/plugins/claude-agent-sdk-local-tool-spans.ts
|
|
16775
|
+
var LOCAL_TOOL_HANDLER_WRAPPED = Symbol.for(
|
|
16776
|
+
"braintrust.claude_agent_sdk.local_tool_handler_wrapped"
|
|
16777
|
+
);
|
|
16778
|
+
function toErrorMessage(error2) {
|
|
16779
|
+
return error2 instanceof Error ? error2.message : String(error2);
|
|
16780
|
+
}
|
|
16781
|
+
function isPromiseLike2(value) {
|
|
16782
|
+
return value !== null && typeof value === "object" && "then" in value && typeof value.then === "function";
|
|
16783
|
+
}
|
|
16784
|
+
function getToolUseIdFromExtra(extra) {
|
|
16785
|
+
if (!extra || typeof extra !== "object" || !("_meta" in extra)) {
|
|
16786
|
+
return void 0;
|
|
16787
|
+
}
|
|
16788
|
+
const meta = Reflect.get(extra, "_meta");
|
|
16789
|
+
if (!meta || typeof meta !== "object") {
|
|
16790
|
+
return void 0;
|
|
16791
|
+
}
|
|
16792
|
+
const toolUseId = Reflect.get(meta, "claudecode/toolUseId");
|
|
16793
|
+
return typeof toolUseId === "string" ? toolUseId : void 0;
|
|
16794
|
+
}
|
|
16795
|
+
function wrapLocalClaudeToolHandler(handler, getMetadata) {
|
|
16796
|
+
if (handler[LOCAL_TOOL_HANDLER_WRAPPED]) {
|
|
16797
|
+
return handler;
|
|
16798
|
+
}
|
|
16799
|
+
const wrappedHandler = function wrappedLocalToolHandler(...handlerArgs) {
|
|
16800
|
+
const metadata = getMetadata();
|
|
16801
|
+
const rawToolName = metadata.serverName ? `mcp__${metadata.serverName}__${metadata.toolName}` : metadata.toolName;
|
|
16802
|
+
const toolUseId = getToolUseIdFromExtra(handlerArgs[1]);
|
|
16803
|
+
const localToolParentResolver = getClaudeLocalToolParentResolver();
|
|
16804
|
+
const spanName = metadata.serverName ? `tool: ${metadata.serverName}/${metadata.toolName}` : `tool: ${metadata.toolName}`;
|
|
16805
|
+
const runWithResolvedParent = async () => {
|
|
16806
|
+
const parent = toolUseId && localToolParentResolver ? await localToolParentResolver(toolUseId).catch(() => void 0) : void 0;
|
|
16807
|
+
const span = startSpan({
|
|
16808
|
+
event: {
|
|
16809
|
+
input: handlerArgs[0],
|
|
16810
|
+
metadata: {
|
|
16811
|
+
"claude_agent_sdk.raw_tool_name": rawToolName,
|
|
16812
|
+
"gen_ai.tool.name": metadata.toolName,
|
|
16813
|
+
...toolUseId && { "gen_ai.tool.call.id": toolUseId },
|
|
16814
|
+
...metadata.serverName && {
|
|
16815
|
+
"mcp.server": metadata.serverName
|
|
16816
|
+
}
|
|
16817
|
+
}
|
|
16818
|
+
},
|
|
16819
|
+
name: spanName,
|
|
16820
|
+
...parent && { parent },
|
|
16821
|
+
spanAttributes: { type: "tool" /* TOOL */ }
|
|
16822
|
+
});
|
|
16823
|
+
const runHandler = () => Reflect.apply(handler, this, handlerArgs);
|
|
16824
|
+
const finalizeSuccess = (result) => {
|
|
16825
|
+
span.log({ output: result });
|
|
16826
|
+
span.end();
|
|
16827
|
+
return result;
|
|
16828
|
+
};
|
|
16829
|
+
const finalizeError = (error2) => {
|
|
16830
|
+
span.log({ error: toErrorMessage(error2) });
|
|
16831
|
+
span.end();
|
|
16832
|
+
throw error2;
|
|
16833
|
+
};
|
|
16834
|
+
return withCurrent(span, () => {
|
|
16835
|
+
try {
|
|
16836
|
+
const result = runHandler();
|
|
16837
|
+
if (isPromiseLike2(result)) {
|
|
16838
|
+
return result.then(finalizeSuccess, finalizeError);
|
|
16839
|
+
}
|
|
16840
|
+
return finalizeSuccess(result);
|
|
16841
|
+
} catch (error2) {
|
|
16842
|
+
return finalizeError(error2);
|
|
16843
|
+
}
|
|
16844
|
+
});
|
|
16845
|
+
};
|
|
16846
|
+
return runWithResolvedParent();
|
|
16847
|
+
};
|
|
16848
|
+
Object.defineProperty(wrappedHandler, LOCAL_TOOL_HANDLER_WRAPPED, {
|
|
16849
|
+
configurable: false,
|
|
16850
|
+
enumerable: false,
|
|
16851
|
+
value: true,
|
|
16852
|
+
writable: false
|
|
16853
|
+
});
|
|
16854
|
+
return wrappedHandler;
|
|
16855
|
+
}
|
|
16856
|
+
function getRegisteredTools(instance) {
|
|
16857
|
+
if (!instance || typeof instance !== "object") {
|
|
16858
|
+
return void 0;
|
|
16859
|
+
}
|
|
16860
|
+
if (!("_registeredTools" in instance)) {
|
|
16861
|
+
return void 0;
|
|
16862
|
+
}
|
|
16863
|
+
const registeredTools = Reflect.get(instance, "_registeredTools");
|
|
16864
|
+
if (registeredTools instanceof Map) {
|
|
16865
|
+
return registeredTools;
|
|
16866
|
+
}
|
|
16867
|
+
if (registeredTools && typeof registeredTools === "object") {
|
|
16868
|
+
return registeredTools;
|
|
16869
|
+
}
|
|
16870
|
+
return void 0;
|
|
16871
|
+
}
|
|
16872
|
+
function wrapLocalMcpServerToolHandlers(serverName, serverConfig) {
|
|
16873
|
+
if (!serverConfig || typeof serverConfig !== "object") {
|
|
16874
|
+
return false;
|
|
16875
|
+
}
|
|
16876
|
+
if (!("instance" in serverConfig)) {
|
|
16877
|
+
return false;
|
|
16878
|
+
}
|
|
16879
|
+
const instance = Reflect.get(serverConfig, "instance");
|
|
16880
|
+
const registeredTools = getRegisteredTools(instance);
|
|
16881
|
+
if (!registeredTools) {
|
|
16882
|
+
return false;
|
|
16883
|
+
}
|
|
16884
|
+
let wrappedAny = false;
|
|
16885
|
+
const wrapHandler = (toolName, registration) => {
|
|
16886
|
+
if (!registration || typeof registration !== "object") {
|
|
16887
|
+
return;
|
|
16888
|
+
}
|
|
16889
|
+
const handler = Reflect.get(registration, "handler");
|
|
16890
|
+
if (typeof handler !== "function") {
|
|
16891
|
+
return;
|
|
16892
|
+
}
|
|
16893
|
+
const wrappedHandler = wrapLocalClaudeToolHandler(handler, () => ({
|
|
16894
|
+
serverName,
|
|
16895
|
+
toolName
|
|
16896
|
+
}));
|
|
16897
|
+
if (wrappedHandler !== handler) {
|
|
16898
|
+
Reflect.set(registration, "handler", wrappedHandler);
|
|
16899
|
+
wrappedAny = true;
|
|
16900
|
+
}
|
|
16901
|
+
};
|
|
16902
|
+
if (registeredTools instanceof Map) {
|
|
16903
|
+
for (const [toolName, registration] of registeredTools.entries()) {
|
|
16904
|
+
wrapHandler(toolName, registration);
|
|
16905
|
+
}
|
|
16906
|
+
return wrappedAny;
|
|
16907
|
+
}
|
|
16908
|
+
for (const [toolName, registration] of Object.entries(registeredTools)) {
|
|
16909
|
+
wrapHandler(toolName, registration);
|
|
16910
|
+
}
|
|
16911
|
+
return wrappedAny;
|
|
16912
|
+
}
|
|
16913
|
+
function collectLocalMcpServerToolHookNames(serverName, serverConfig) {
|
|
16914
|
+
const toolNames = /* @__PURE__ */ new Set();
|
|
16915
|
+
if (!serverConfig || typeof serverConfig !== "object") {
|
|
16916
|
+
return toolNames;
|
|
16917
|
+
}
|
|
16918
|
+
if ("instance" in serverConfig) {
|
|
16919
|
+
const instance = Reflect.get(serverConfig, "instance");
|
|
16920
|
+
const registeredTools = getRegisteredTools(instance);
|
|
16921
|
+
if (registeredTools instanceof Map) {
|
|
16922
|
+
for (const toolName of registeredTools.keys()) {
|
|
16923
|
+
toolNames.add(toolName);
|
|
16924
|
+
toolNames.add(`mcp__${serverName}__${toolName}`);
|
|
16925
|
+
}
|
|
16926
|
+
} else if (registeredTools) {
|
|
16927
|
+
for (const toolName of Object.keys(registeredTools)) {
|
|
16928
|
+
toolNames.add(toolName);
|
|
16929
|
+
toolNames.add(`mcp__${serverName}__${toolName}`);
|
|
16930
|
+
}
|
|
16931
|
+
}
|
|
16932
|
+
}
|
|
16933
|
+
if ("tools" in serverConfig) {
|
|
16934
|
+
const rawTools = Reflect.get(serverConfig, "tools");
|
|
16935
|
+
if (Array.isArray(rawTools)) {
|
|
16936
|
+
for (const tool of rawTools) {
|
|
16937
|
+
if (!tool || typeof tool !== "object") {
|
|
16938
|
+
continue;
|
|
16939
|
+
}
|
|
16940
|
+
const toolName = Reflect.get(tool, "name");
|
|
16941
|
+
if (typeof toolName !== "string") {
|
|
16942
|
+
continue;
|
|
16943
|
+
}
|
|
16944
|
+
toolNames.add(toolName);
|
|
16945
|
+
toolNames.add(`mcp__${serverName}__${toolName}`);
|
|
16946
|
+
}
|
|
16947
|
+
}
|
|
16948
|
+
}
|
|
16949
|
+
return toolNames;
|
|
16950
|
+
}
|
|
16951
|
+
|
|
15851
16952
|
// src/instrumentation/plugins/claude-agent-sdk-plugin.ts
|
|
16953
|
+
var ROOT_LLM_PARENT_KEY = "__root__";
|
|
16954
|
+
function llmParentKey(parentToolUseId) {
|
|
16955
|
+
return parentToolUseId ?? ROOT_LLM_PARENT_KEY;
|
|
16956
|
+
}
|
|
15852
16957
|
function isSubAgentToolName(toolName) {
|
|
15853
16958
|
return toolName === "Agent" || toolName === "Task";
|
|
15854
16959
|
}
|
|
@@ -15934,7 +17039,7 @@ function buildLLMInput(prompt, conversationHistory, capturedPromptMessages) {
|
|
|
15934
17039
|
function formatCapturedMessages(messages) {
|
|
15935
17040
|
return messages.length > 0 ? messages : [];
|
|
15936
17041
|
}
|
|
15937
|
-
async function createLLMSpanForMessages(messages, prompt, conversationHistory, options, startTime, capturedPromptMessages, parentSpan) {
|
|
17042
|
+
async function createLLMSpanForMessages(messages, prompt, conversationHistory, options, startTime, capturedPromptMessages, parentSpan, existingSpan) {
|
|
15938
17043
|
if (messages.length === 0) {
|
|
15939
17044
|
return void 0;
|
|
15940
17045
|
}
|
|
@@ -15954,7 +17059,7 @@ async function createLLMSpanForMessages(messages, prompt, conversationHistory, o
|
|
|
15954
17059
|
).filter(
|
|
15955
17060
|
(c) => c !== void 0
|
|
15956
17061
|
);
|
|
15957
|
-
const span = startSpan({
|
|
17062
|
+
const span = existingSpan ?? startSpan({
|
|
15958
17063
|
name: "anthropic.messages.create",
|
|
15959
17064
|
parent: parentSpan,
|
|
15960
17065
|
spanAttributes: {
|
|
@@ -15968,8 +17073,13 @@ async function createLLMSpanForMessages(messages, prompt, conversationHistory, o
|
|
|
15968
17073
|
metrics: usage,
|
|
15969
17074
|
output: outputs
|
|
15970
17075
|
});
|
|
17076
|
+
const spanExport = await span.export();
|
|
15971
17077
|
await span.end();
|
|
15972
|
-
|
|
17078
|
+
const finalMessage = lastMessage.message?.content && lastMessage.message?.role ? { content: lastMessage.message.content, role: lastMessage.message.role } : void 0;
|
|
17079
|
+
return {
|
|
17080
|
+
finalMessage,
|
|
17081
|
+
spanExport
|
|
17082
|
+
};
|
|
15973
17083
|
}
|
|
15974
17084
|
function getMcpServerMetadata(serverName, mcpServers) {
|
|
15975
17085
|
if (!serverName || !mcpServers) {
|
|
@@ -16013,11 +17123,51 @@ function parseToolName(rawToolName) {
|
|
|
16013
17123
|
toolName: rawToolName
|
|
16014
17124
|
};
|
|
16015
17125
|
}
|
|
16016
|
-
function
|
|
17126
|
+
function isLocalToolUse(rawToolName, mcpServers) {
|
|
17127
|
+
const parsed = parseToolName(rawToolName);
|
|
17128
|
+
if (!parsed.mcpServer || !mcpServers) {
|
|
17129
|
+
return false;
|
|
17130
|
+
}
|
|
17131
|
+
const serverConfig = mcpServers[parsed.mcpServer];
|
|
17132
|
+
if (!serverConfig || typeof serverConfig !== "object") {
|
|
17133
|
+
return false;
|
|
17134
|
+
}
|
|
17135
|
+
return serverConfig.type === "sdk" || "transport" in serverConfig;
|
|
17136
|
+
}
|
|
17137
|
+
function prepareLocalToolHandlersInMcpServers(mcpServers) {
|
|
17138
|
+
const localToolHookNames = /* @__PURE__ */ new Set();
|
|
17139
|
+
if (!mcpServers) {
|
|
17140
|
+
return {
|
|
17141
|
+
hasLocalToolHandlers: false,
|
|
17142
|
+
localToolHookNames
|
|
17143
|
+
};
|
|
17144
|
+
}
|
|
17145
|
+
let hasLocalToolHandlers = false;
|
|
17146
|
+
for (const [serverName, serverConfig] of Object.entries(mcpServers)) {
|
|
17147
|
+
const toolNames = collectLocalMcpServerToolHookNames(
|
|
17148
|
+
serverName,
|
|
17149
|
+
serverConfig
|
|
17150
|
+
);
|
|
17151
|
+
for (const toolName of toolNames) {
|
|
17152
|
+
localToolHookNames.add(toolName);
|
|
17153
|
+
}
|
|
17154
|
+
if (toolNames.size > 0) {
|
|
17155
|
+
hasLocalToolHandlers = true;
|
|
17156
|
+
}
|
|
17157
|
+
if (wrapLocalMcpServerToolHandlers(serverName, serverConfig)) {
|
|
17158
|
+
hasLocalToolHandlers = true;
|
|
17159
|
+
}
|
|
17160
|
+
}
|
|
17161
|
+
return { hasLocalToolHandlers, localToolHookNames };
|
|
17162
|
+
}
|
|
17163
|
+
function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers, localToolHookNames, skipLocalToolHooks, subAgentSpans, endedSubAgentSpans) {
|
|
16017
17164
|
const preToolUse = async (input, toolUseID) => {
|
|
16018
17165
|
if (input.hook_event_name !== "PreToolUse" || !toolUseID) {
|
|
16019
17166
|
return {};
|
|
16020
17167
|
}
|
|
17168
|
+
if (skipLocalToolHooks && (isLocalToolUse(input.tool_name, mcpServers) || localToolHookNames.has(input.tool_name))) {
|
|
17169
|
+
return {};
|
|
17170
|
+
}
|
|
16021
17171
|
if (isSubAgentToolName(input.tool_name)) {
|
|
16022
17172
|
return {};
|
|
16023
17173
|
}
|
|
@@ -16046,6 +17196,9 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
|
|
|
16046
17196
|
if (input.hook_event_name !== "PostToolUse" || !toolUseID) {
|
|
16047
17197
|
return {};
|
|
16048
17198
|
}
|
|
17199
|
+
if (skipLocalToolHooks && (isLocalToolUse(input.tool_name, mcpServers) || localToolHookNames.has(input.tool_name))) {
|
|
17200
|
+
return {};
|
|
17201
|
+
}
|
|
16049
17202
|
const subAgentSpan = subAgentSpans.get(toolUseID);
|
|
16050
17203
|
if (subAgentSpan) {
|
|
16051
17204
|
try {
|
|
@@ -16086,6 +17239,9 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
|
|
|
16086
17239
|
if (input.hook_event_name !== "PostToolUseFailure" || !toolUseID) {
|
|
16087
17240
|
return {};
|
|
16088
17241
|
}
|
|
17242
|
+
if (skipLocalToolHooks && (isLocalToolUse(input.tool_name, mcpServers) || localToolHookNames.has(input.tool_name))) {
|
|
17243
|
+
return {};
|
|
17244
|
+
}
|
|
16089
17245
|
const subAgentSpan = subAgentSpans.get(toolUseID);
|
|
16090
17246
|
if (subAgentSpan) {
|
|
16091
17247
|
try {
|
|
@@ -16120,11 +17276,13 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
|
|
|
16120
17276
|
};
|
|
16121
17277
|
return { postToolUse, postToolUseFailure, preToolUse };
|
|
16122
17278
|
}
|
|
16123
|
-
function injectTracingHooks(options, resolveParentSpan, activeToolSpans, subAgentSpans, endedSubAgentSpans) {
|
|
17279
|
+
function injectTracingHooks(options, resolveParentSpan, activeToolSpans, localToolHookNames, skipLocalToolHooks, subAgentSpans, endedSubAgentSpans) {
|
|
16124
17280
|
const { preToolUse, postToolUse, postToolUseFailure } = createToolTracingHooks(
|
|
16125
17281
|
resolveParentSpan,
|
|
16126
17282
|
activeToolSpans,
|
|
16127
17283
|
options.mcpServers,
|
|
17284
|
+
localToolHookNames,
|
|
17285
|
+
skipLocalToolHooks,
|
|
16128
17286
|
subAgentSpans,
|
|
16129
17287
|
endedSubAgentSpans
|
|
16130
17288
|
);
|
|
@@ -16155,6 +17313,7 @@ async function finalizeCurrentMessageGroup(state) {
|
|
|
16155
17313
|
return;
|
|
16156
17314
|
}
|
|
16157
17315
|
const parentToolUseId = state.currentMessages[0]?.parent_tool_use_id ?? null;
|
|
17316
|
+
const parentKey = llmParentKey(parentToolUseId);
|
|
16158
17317
|
let parentSpan = await state.span.export();
|
|
16159
17318
|
if (parentToolUseId) {
|
|
16160
17319
|
const subAgentSpan = state.subAgentSpans.get(parentToolUseId);
|
|
@@ -16162,17 +17321,30 @@ async function finalizeCurrentMessageGroup(state) {
|
|
|
16162
17321
|
parentSpan = await subAgentSpan.export();
|
|
16163
17322
|
}
|
|
16164
17323
|
}
|
|
16165
|
-
const
|
|
17324
|
+
const existingLlmSpan = state.activeLlmSpansByParentToolUse.get(parentKey);
|
|
17325
|
+
const llmSpanResult = await createLLMSpanForMessages(
|
|
16166
17326
|
state.currentMessages,
|
|
16167
17327
|
state.originalPrompt,
|
|
16168
17328
|
state.finalResults,
|
|
16169
17329
|
state.options,
|
|
16170
17330
|
state.currentMessageStartTime,
|
|
16171
17331
|
state.capturedPromptMessages,
|
|
16172
|
-
parentSpan
|
|
17332
|
+
parentSpan,
|
|
17333
|
+
existingLlmSpan
|
|
16173
17334
|
);
|
|
16174
|
-
|
|
16175
|
-
|
|
17335
|
+
state.activeLlmSpansByParentToolUse.delete(parentKey);
|
|
17336
|
+
if (llmSpanResult) {
|
|
17337
|
+
if (parentToolUseId) {
|
|
17338
|
+
state.latestLlmParentBySubAgentToolUse.set(
|
|
17339
|
+
parentToolUseId,
|
|
17340
|
+
llmSpanResult.spanExport
|
|
17341
|
+
);
|
|
17342
|
+
} else {
|
|
17343
|
+
state.latestRootLlmParentRef.value = llmSpanResult.spanExport;
|
|
17344
|
+
}
|
|
17345
|
+
if (llmSpanResult.finalMessage) {
|
|
17346
|
+
state.finalResults.push(llmSpanResult.finalMessage);
|
|
17347
|
+
}
|
|
16176
17348
|
}
|
|
16177
17349
|
const lastMessage = state.currentMessages[state.currentMessages.length - 1];
|
|
16178
17350
|
if (lastMessage?.message?.usage) {
|
|
@@ -16240,6 +17412,29 @@ async function handleStreamMessage(state, message) {
|
|
|
16240
17412
|
state.currentMessageStartTime = getCurrentUnixTimestamp();
|
|
16241
17413
|
}
|
|
16242
17414
|
if (message.type === "assistant" && message.message?.usage) {
|
|
17415
|
+
const parentToolUseId = message.parent_tool_use_id ?? null;
|
|
17416
|
+
const parentKey = llmParentKey(parentToolUseId);
|
|
17417
|
+
if (!state.activeLlmSpansByParentToolUse.has(parentKey)) {
|
|
17418
|
+
let llmParentSpan = await state.span.export();
|
|
17419
|
+
if (parentToolUseId) {
|
|
17420
|
+
const subAgentSpan = await ensureSubAgentSpan(
|
|
17421
|
+
state.pendingSubAgentNames,
|
|
17422
|
+
state.span,
|
|
17423
|
+
state.subAgentSpans,
|
|
17424
|
+
parentToolUseId
|
|
17425
|
+
);
|
|
17426
|
+
llmParentSpan = await subAgentSpan.export();
|
|
17427
|
+
}
|
|
17428
|
+
const llmSpan = startSpan({
|
|
17429
|
+
name: "anthropic.messages.create",
|
|
17430
|
+
parent: llmParentSpan,
|
|
17431
|
+
spanAttributes: {
|
|
17432
|
+
type: "llm" /* LLM */
|
|
17433
|
+
},
|
|
17434
|
+
startTime: state.currentMessageStartTime
|
|
17435
|
+
});
|
|
17436
|
+
state.activeLlmSpansByParentToolUse.set(parentKey, llmSpan);
|
|
17437
|
+
}
|
|
16243
17438
|
state.currentMessages.push(message);
|
|
16244
17439
|
}
|
|
16245
17440
|
if (message.type !== "result" || !message.usage) {
|
|
@@ -16300,6 +17495,10 @@ async function finalizeQuerySpan(state) {
|
|
|
16300
17495
|
}
|
|
16301
17496
|
}
|
|
16302
17497
|
} finally {
|
|
17498
|
+
for (const llmSpan of state.activeLlmSpansByParentToolUse.values()) {
|
|
17499
|
+
llmSpan.end();
|
|
17500
|
+
}
|
|
17501
|
+
state.activeLlmSpansByParentToolUse.clear();
|
|
16303
17502
|
for (const [id, subAgentSpan] of state.subAgentSpans) {
|
|
16304
17503
|
if (!state.endedSubAgentSpans.has(id)) {
|
|
16305
17504
|
subAgentSpan.end();
|
|
@@ -16365,26 +17564,51 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
16365
17564
|
console.error("Error extracting input for Claude Agent SDK:", error2);
|
|
16366
17565
|
}
|
|
16367
17566
|
const activeToolSpans = /* @__PURE__ */ new Map();
|
|
17567
|
+
const activeLlmSpansByParentToolUse = /* @__PURE__ */ new Map();
|
|
16368
17568
|
const subAgentSpans = /* @__PURE__ */ new Map();
|
|
16369
17569
|
const endedSubAgentSpans = /* @__PURE__ */ new Set();
|
|
16370
17570
|
const toolUseToParent = /* @__PURE__ */ new Map();
|
|
17571
|
+
const latestLlmParentBySubAgentToolUse = /* @__PURE__ */ new Map();
|
|
17572
|
+
const latestRootLlmParentRef = {
|
|
17573
|
+
value: void 0
|
|
17574
|
+
};
|
|
16371
17575
|
const pendingSubAgentNames = /* @__PURE__ */ new Map();
|
|
17576
|
+
const localToolContext = createClaudeLocalToolContext();
|
|
17577
|
+
const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
|
|
17578
|
+
const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
|
|
17579
|
+
const resolveToolUseParentSpan = async (toolUseID) => {
|
|
17580
|
+
const parentToolUseId = toolUseToParent.get(toolUseID) ?? null;
|
|
17581
|
+
const parentKey = llmParentKey(parentToolUseId);
|
|
17582
|
+
const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
|
|
17583
|
+
if (activeLlmSpan) {
|
|
17584
|
+
return activeLlmSpan.export();
|
|
17585
|
+
}
|
|
17586
|
+
if (parentToolUseId) {
|
|
17587
|
+
const parentLlm = latestLlmParentBySubAgentToolUse.get(parentToolUseId);
|
|
17588
|
+
if (parentLlm) {
|
|
17589
|
+
return parentLlm;
|
|
17590
|
+
}
|
|
17591
|
+
const subAgentSpan = await ensureSubAgentSpan(
|
|
17592
|
+
pendingSubAgentNames,
|
|
17593
|
+
span,
|
|
17594
|
+
subAgentSpans,
|
|
17595
|
+
parentToolUseId
|
|
17596
|
+
);
|
|
17597
|
+
return subAgentSpan.export();
|
|
17598
|
+
}
|
|
17599
|
+
if (latestRootLlmParentRef.value) {
|
|
17600
|
+
return latestRootLlmParentRef.value;
|
|
17601
|
+
}
|
|
17602
|
+
return span.export();
|
|
17603
|
+
};
|
|
17604
|
+
localToolContext.resolveLocalToolParent = resolveToolUseParentSpan;
|
|
17605
|
+
setClaudeLocalToolParentResolver(resolveToolUseParentSpan);
|
|
16372
17606
|
const optionsWithHooks = injectTracingHooks(
|
|
16373
17607
|
options,
|
|
16374
|
-
|
|
16375
|
-
const parentToolUseId = toolUseToParent.get(toolUseID);
|
|
16376
|
-
if (parentToolUseId) {
|
|
16377
|
-
const subAgentSpan = await ensureSubAgentSpan(
|
|
16378
|
-
pendingSubAgentNames,
|
|
16379
|
-
span,
|
|
16380
|
-
subAgentSpans,
|
|
16381
|
-
parentToolUseId
|
|
16382
|
-
);
|
|
16383
|
-
return subAgentSpan.export();
|
|
16384
|
-
}
|
|
16385
|
-
return span.export();
|
|
16386
|
-
},
|
|
17608
|
+
resolveToolUseParentSpan,
|
|
16387
17609
|
activeToolSpans,
|
|
17610
|
+
localToolHookNames,
|
|
17611
|
+
skipLocalToolHooks,
|
|
16388
17612
|
subAgentSpans,
|
|
16389
17613
|
endedSubAgentSpans
|
|
16390
17614
|
);
|
|
@@ -16392,6 +17616,7 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
16392
17616
|
event.arguments[0] = params;
|
|
16393
17617
|
spans.set(event, {
|
|
16394
17618
|
accumulatedOutputTokens: 0,
|
|
17619
|
+
activeLlmSpansByParentToolUse,
|
|
16395
17620
|
activeToolSpans,
|
|
16396
17621
|
capturedPromptMessages,
|
|
16397
17622
|
currentMessageId: void 0,
|
|
@@ -16407,7 +17632,10 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
16407
17632
|
promptStarted: () => promptStarted,
|
|
16408
17633
|
span,
|
|
16409
17634
|
subAgentSpans,
|
|
16410
|
-
|
|
17635
|
+
latestLlmParentBySubAgentToolUse,
|
|
17636
|
+
latestRootLlmParentRef,
|
|
17637
|
+
toolUseToParent,
|
|
17638
|
+
localToolContext
|
|
16411
17639
|
});
|
|
16412
17640
|
},
|
|
16413
17641
|
end: (event) => {
|
|
@@ -16415,7 +17643,10 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
16415
17643
|
if (!state) {
|
|
16416
17644
|
return;
|
|
16417
17645
|
}
|
|
16418
|
-
const eventResult =
|
|
17646
|
+
const eventResult = bindClaudeLocalToolContextToAsyncIterable(
|
|
17647
|
+
event.result,
|
|
17648
|
+
state.localToolContext
|
|
17649
|
+
);
|
|
16419
17650
|
if (eventResult === void 0) {
|
|
16420
17651
|
state.span.end();
|
|
16421
17652
|
spans.delete(event);
|
|
@@ -16432,20 +17663,16 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
16432
17663
|
);
|
|
16433
17664
|
});
|
|
16434
17665
|
},
|
|
16435
|
-
onComplete: () => {
|
|
16436
|
-
|
|
16437
|
-
|
|
16438
|
-
|
|
16439
|
-
|
|
16440
|
-
|
|
16441
|
-
void state.processing.then(() => {
|
|
16442
|
-
state.span.log({
|
|
16443
|
-
error: error2.message
|
|
16444
|
-
});
|
|
16445
|
-
}).then(() => finalizeQuerySpan(state)).finally(() => {
|
|
16446
|
-
spans.delete(event);
|
|
17666
|
+
onComplete: () => state.processing.then(() => finalizeQuerySpan(state)).finally(() => {
|
|
17667
|
+
spans.delete(event);
|
|
17668
|
+
}),
|
|
17669
|
+
onError: (error2) => state.processing.then(() => {
|
|
17670
|
+
state.span.log({
|
|
17671
|
+
error: error2.message
|
|
16447
17672
|
});
|
|
16448
|
-
}
|
|
17673
|
+
}).then(() => finalizeQuerySpan(state)).finally(() => {
|
|
17674
|
+
spans.delete(event);
|
|
17675
|
+
})
|
|
16449
17676
|
});
|
|
16450
17677
|
return;
|
|
16451
17678
|
}
|
|
@@ -16593,12 +17820,14 @@ var GoogleGenAIPlugin = class extends BasePlugin {
|
|
|
16593
17820
|
const params = event.arguments[0];
|
|
16594
17821
|
streamEvent.googleGenAIInput = serializeInput(params);
|
|
16595
17822
|
streamEvent.googleGenAIMetadata = extractMetadata(params);
|
|
17823
|
+
streamEvent.googleGenAIStartTime = getCurrentUnixTimestamp();
|
|
16596
17824
|
},
|
|
16597
17825
|
asyncEnd: (event) => {
|
|
16598
17826
|
const streamEvent = event;
|
|
16599
17827
|
patchGoogleGenAIStreamingResult({
|
|
16600
17828
|
input: streamEvent.googleGenAIInput,
|
|
16601
17829
|
metadata: streamEvent.googleGenAIMetadata,
|
|
17830
|
+
startTime: streamEvent.googleGenAIStartTime,
|
|
16602
17831
|
result: streamEvent.result
|
|
16603
17832
|
});
|
|
16604
17833
|
},
|
|
@@ -16622,19 +17851,20 @@ function ensureSpanState(states, event, create) {
|
|
|
16622
17851
|
}
|
|
16623
17852
|
function bindCurrentSpanStoreToStart2(tracingChannel2, states, create) {
|
|
16624
17853
|
const state = _internalGetGlobalState();
|
|
17854
|
+
const contextManager = state?.contextManager;
|
|
16625
17855
|
const startChannel = tracingChannel2.start;
|
|
16626
|
-
const currentSpanStore =
|
|
17856
|
+
const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
|
|
16627
17857
|
if (!startChannel?.bindStore || !currentSpanStore) {
|
|
16628
17858
|
return void 0;
|
|
16629
17859
|
}
|
|
16630
|
-
startChannel.bindStore(
|
|
16631
|
-
|
|
16632
|
-
(event) => ensureSpanState(
|
|
17860
|
+
startChannel.bindStore(currentSpanStore, (event) => {
|
|
17861
|
+
const span = ensureSpanState(
|
|
16633
17862
|
states,
|
|
16634
17863
|
event,
|
|
16635
17864
|
() => create(event)
|
|
16636
|
-
).span
|
|
16637
|
-
|
|
17865
|
+
).span;
|
|
17866
|
+
return contextManager.wrapSpanForStore(span);
|
|
17867
|
+
});
|
|
16638
17868
|
return () => {
|
|
16639
17869
|
startChannel.unbindStore?.(currentSpanStore);
|
|
16640
17870
|
};
|
|
@@ -16651,7 +17881,7 @@ function logErrorAndEndSpan(states, event) {
|
|
|
16651
17881
|
states.delete(event);
|
|
16652
17882
|
}
|
|
16653
17883
|
function patchGoogleGenAIStreamingResult(args) {
|
|
16654
|
-
const { input, metadata, result } = args;
|
|
17884
|
+
const { input, metadata, result, startTime } = args;
|
|
16655
17885
|
if (!input || !metadata || !result || typeof result !== "object" || typeof result.next !== "function") {
|
|
16656
17886
|
return false;
|
|
16657
17887
|
}
|
|
@@ -16659,7 +17889,7 @@ function patchGoogleGenAIStreamingResult(args) {
|
|
|
16659
17889
|
let firstTokenTime = null;
|
|
16660
17890
|
let finalized = false;
|
|
16661
17891
|
let span = null;
|
|
16662
|
-
|
|
17892
|
+
const requestStartTime = startTime ?? getCurrentUnixTimestamp();
|
|
16663
17893
|
const ensureSpan = () => {
|
|
16664
17894
|
if (!span) {
|
|
16665
17895
|
span = startSpan({
|
|
@@ -16672,7 +17902,6 @@ function patchGoogleGenAIStreamingResult(args) {
|
|
|
16672
17902
|
metadata
|
|
16673
17903
|
}
|
|
16674
17904
|
});
|
|
16675
|
-
startTime = getCurrentUnixTimestamp();
|
|
16676
17905
|
}
|
|
16677
17906
|
return span;
|
|
16678
17907
|
};
|
|
@@ -16726,11 +17955,11 @@ function patchGoogleGenAIStreamingResult(args) {
|
|
|
16726
17955
|
}
|
|
16727
17956
|
chunks.push(nextResult.value);
|
|
16728
17957
|
}
|
|
16729
|
-
if (nextResult.done
|
|
17958
|
+
if (nextResult.done) {
|
|
16730
17959
|
finalize({
|
|
16731
17960
|
result: aggregateGenerateContentChunks(
|
|
16732
17961
|
chunks,
|
|
16733
|
-
|
|
17962
|
+
requestStartTime,
|
|
16734
17963
|
firstTokenTime
|
|
16735
17964
|
)
|
|
16736
17965
|
});
|
|
@@ -16750,13 +17979,13 @@ function patchGoogleGenAIStreamingResult(args) {
|
|
|
16750
17979
|
...returnArgs
|
|
16751
17980
|
);
|
|
16752
17981
|
} finally {
|
|
16753
|
-
if (
|
|
17982
|
+
if (chunks.length > 0) {
|
|
16754
17983
|
finalize({
|
|
16755
|
-
result:
|
|
17984
|
+
result: aggregateGenerateContentChunks(
|
|
16756
17985
|
chunks,
|
|
16757
|
-
|
|
17986
|
+
requestStartTime,
|
|
16758
17987
|
firstTokenTime
|
|
16759
|
-
)
|
|
17988
|
+
)
|
|
16760
17989
|
});
|
|
16761
17990
|
} else {
|
|
16762
17991
|
finalize({});
|
|
@@ -17030,41 +18259,156 @@ function tryToDict(obj) {
|
|
|
17030
18259
|
return null;
|
|
17031
18260
|
}
|
|
17032
18261
|
|
|
17033
|
-
// src/instrumentation/plugins/openrouter-channels.ts
|
|
17034
|
-
var
|
|
17035
|
-
chatSend: channel({
|
|
17036
|
-
channelName: "chat.send",
|
|
17037
|
-
kind: "async"
|
|
17038
|
-
}),
|
|
17039
|
-
embeddingsGenerate: channel({
|
|
17040
|
-
channelName: "embeddings.generate",
|
|
17041
|
-
kind: "async"
|
|
17042
|
-
}),
|
|
17043
|
-
betaResponsesSend: channel({
|
|
17044
|
-
channelName: "beta.responses.send",
|
|
17045
|
-
kind: "async"
|
|
17046
|
-
}),
|
|
18262
|
+
// src/instrumentation/plugins/openrouter-agent-channels.ts
|
|
18263
|
+
var openRouterAgentChannels = defineChannels("@openrouter/agent", {
|
|
17047
18264
|
callModel: channel({
|
|
17048
18265
|
channelName: "callModel",
|
|
17049
18266
|
kind: "sync-stream"
|
|
17050
18267
|
}),
|
|
18268
|
+
callModelTurn: channel({
|
|
18269
|
+
channelName: "callModel.turn",
|
|
18270
|
+
kind: "async"
|
|
18271
|
+
}),
|
|
17051
18272
|
toolExecute: channel({
|
|
17052
18273
|
channelName: "tool.execute",
|
|
17053
18274
|
kind: "async"
|
|
17054
18275
|
})
|
|
17055
18276
|
});
|
|
17056
18277
|
|
|
17057
|
-
// src/openrouter-
|
|
17058
|
-
var
|
|
17059
|
-
|
|
17060
|
-
|
|
17061
|
-
|
|
17062
|
-
|
|
17063
|
-
|
|
17064
|
-
|
|
17065
|
-
|
|
17066
|
-
|
|
17067
|
-
|
|
18278
|
+
// src/instrumentation/plugins/openrouter-agent-plugin.ts
|
|
18279
|
+
var OpenRouterAgentPlugin = class extends BasePlugin {
|
|
18280
|
+
onEnable() {
|
|
18281
|
+
this.subscribeToOpenRouterAgentChannels();
|
|
18282
|
+
}
|
|
18283
|
+
onDisable() {
|
|
18284
|
+
this.unsubscribers = unsubscribeAll(this.unsubscribers);
|
|
18285
|
+
}
|
|
18286
|
+
subscribeToOpenRouterAgentChannels() {
|
|
18287
|
+
this.unsubscribers.push(
|
|
18288
|
+
traceSyncStreamChannel(openRouterAgentChannels.callModel, {
|
|
18289
|
+
name: "openrouter.callModel",
|
|
18290
|
+
type: "llm" /* LLM */,
|
|
18291
|
+
extractInput: (args) => {
|
|
18292
|
+
const request = getOpenRouterCallModelRequestArg(args);
|
|
18293
|
+
return {
|
|
18294
|
+
input: request ? extractOpenRouterCallModelInput(request) : void 0,
|
|
18295
|
+
metadata: request ? extractOpenRouterCallModelMetadata(request) : { provider: "openrouter" }
|
|
18296
|
+
};
|
|
18297
|
+
},
|
|
18298
|
+
patchResult: ({ endEvent, result, span }) => {
|
|
18299
|
+
return patchOpenRouterCallModelResult({
|
|
18300
|
+
request: getOpenRouterCallModelRequestArg(endEvent.arguments),
|
|
18301
|
+
result,
|
|
18302
|
+
span
|
|
18303
|
+
});
|
|
18304
|
+
}
|
|
18305
|
+
})
|
|
18306
|
+
);
|
|
18307
|
+
this.unsubscribers.push(
|
|
18308
|
+
traceAsyncChannel(openRouterAgentChannels.callModelTurn, {
|
|
18309
|
+
name: "openrouter.beta.responses.send",
|
|
18310
|
+
type: "llm" /* LLM */,
|
|
18311
|
+
extractInput: (args, event) => {
|
|
18312
|
+
const request = getOpenRouterCallModelRequestArg(args);
|
|
18313
|
+
const metadata = request ? extractOpenRouterCallModelMetadata(request) : { provider: "openrouter" };
|
|
18314
|
+
if (isObject(metadata) && "tools" in metadata) {
|
|
18315
|
+
delete metadata.tools;
|
|
18316
|
+
}
|
|
18317
|
+
return {
|
|
18318
|
+
input: request ? extractOpenRouterCallModelInput(request) : void 0,
|
|
18319
|
+
metadata: {
|
|
18320
|
+
...metadata,
|
|
18321
|
+
step: event.step,
|
|
18322
|
+
step_type: event.stepType
|
|
18323
|
+
}
|
|
18324
|
+
};
|
|
18325
|
+
},
|
|
18326
|
+
extractOutput: (result) => extractOpenRouterResponseOutput(result),
|
|
18327
|
+
extractMetadata: (result, event) => {
|
|
18328
|
+
if (!isObject(result)) {
|
|
18329
|
+
return {
|
|
18330
|
+
step: event?.step,
|
|
18331
|
+
step_type: event?.stepType
|
|
18332
|
+
};
|
|
18333
|
+
}
|
|
18334
|
+
return {
|
|
18335
|
+
...extractOpenRouterResponseMetadata(result) || {},
|
|
18336
|
+
...event?.step !== void 0 ? { step: event.step } : {},
|
|
18337
|
+
...event?.stepType ? { step_type: event.stepType } : {}
|
|
18338
|
+
};
|
|
18339
|
+
},
|
|
18340
|
+
extractMetrics: (result) => isObject(result) ? parseOpenRouterMetricsFromUsage(result.usage) : {}
|
|
18341
|
+
})
|
|
18342
|
+
);
|
|
18343
|
+
this.unsubscribers.push(
|
|
18344
|
+
traceStreamingChannel(openRouterAgentChannels.toolExecute, {
|
|
18345
|
+
name: "openrouter.tool",
|
|
18346
|
+
type: "tool" /* TOOL */,
|
|
18347
|
+
extractInput: (args, event) => ({
|
|
18348
|
+
input: args[0],
|
|
18349
|
+
metadata: {
|
|
18350
|
+
provider: "openrouter",
|
|
18351
|
+
tool_name: event.toolName,
|
|
18352
|
+
...event.toolCallId ? { tool_call_id: event.toolCallId } : {}
|
|
18353
|
+
}
|
|
18354
|
+
}),
|
|
18355
|
+
extractOutput: (result) => result,
|
|
18356
|
+
extractMetrics: () => ({}),
|
|
18357
|
+
aggregateChunks: (chunks) => ({
|
|
18358
|
+
output: chunks.length > 0 ? chunks[chunks.length - 1] : void 0,
|
|
18359
|
+
metrics: {}
|
|
18360
|
+
})
|
|
18361
|
+
})
|
|
18362
|
+
);
|
|
18363
|
+
const callModelChannel = openRouterAgentChannels.callModel.tracingChannel();
|
|
18364
|
+
const callModelHandlers = {
|
|
18365
|
+
start: (event) => {
|
|
18366
|
+
const request = getOpenRouterCallModelRequestArg(event.arguments);
|
|
18367
|
+
if (!request) {
|
|
18368
|
+
return;
|
|
18369
|
+
}
|
|
18370
|
+
patchOpenRouterCallModelRequestTools(request);
|
|
18371
|
+
}
|
|
18372
|
+
};
|
|
18373
|
+
callModelChannel.subscribe(callModelHandlers);
|
|
18374
|
+
this.unsubscribers.push(() => {
|
|
18375
|
+
callModelChannel.unsubscribe(callModelHandlers);
|
|
18376
|
+
});
|
|
18377
|
+
}
|
|
18378
|
+
};
|
|
18379
|
+
function normalizeArgs(args) {
|
|
18380
|
+
if (Array.isArray(args)) {
|
|
18381
|
+
return args;
|
|
18382
|
+
}
|
|
18383
|
+
if (isArrayLike2(args)) {
|
|
18384
|
+
return Array.from(args);
|
|
18385
|
+
}
|
|
18386
|
+
return [args];
|
|
18387
|
+
}
|
|
18388
|
+
function isArrayLike2(value) {
|
|
18389
|
+
return isObject(value) && "length" in value && typeof value.length === "number" && Number.isInteger(value.length) && value.length >= 0;
|
|
18390
|
+
}
|
|
18391
|
+
function getOpenRouterCallModelRequestArg(args) {
|
|
18392
|
+
const normalizedArgs = normalizeArgs(args);
|
|
18393
|
+
const keyedRequestArg = normalizedArgs.find(
|
|
18394
|
+
(arg) => isObject(arg) && ("input" in arg || "model" in arg || "tools" in arg)
|
|
18395
|
+
);
|
|
18396
|
+
if (isObject(keyedRequestArg)) {
|
|
18397
|
+
return keyedRequestArg;
|
|
18398
|
+
}
|
|
18399
|
+
const firstObjectArg = normalizedArgs.find((arg) => isObject(arg));
|
|
18400
|
+
return isObject(firstObjectArg) ? firstObjectArg : void 0;
|
|
18401
|
+
}
|
|
18402
|
+
var TOKEN_NAME_MAP2 = {
|
|
18403
|
+
promptTokens: "prompt_tokens",
|
|
18404
|
+
inputTokens: "prompt_tokens",
|
|
18405
|
+
completionTokens: "completion_tokens",
|
|
18406
|
+
outputTokens: "completion_tokens",
|
|
18407
|
+
totalTokens: "tokens",
|
|
18408
|
+
prompt_tokens: "prompt_tokens",
|
|
18409
|
+
input_tokens: "prompt_tokens",
|
|
18410
|
+
completion_tokens: "completion_tokens",
|
|
18411
|
+
output_tokens: "completion_tokens",
|
|
17068
18412
|
total_tokens: "tokens"
|
|
17069
18413
|
};
|
|
17070
18414
|
var TOKEN_DETAIL_PREFIX_MAP = {
|
|
@@ -17120,8 +18464,6 @@ function extractOpenRouterUsageMetadata(usage) {
|
|
|
17120
18464
|
}
|
|
17121
18465
|
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
17122
18466
|
}
|
|
17123
|
-
|
|
17124
|
-
// src/openrouter-logging.ts
|
|
17125
18467
|
var OMITTED_OPENROUTER_KEYS = /* @__PURE__ */ new Set([
|
|
17126
18468
|
"execute",
|
|
17127
18469
|
"render",
|
|
@@ -17141,10 +18483,10 @@ function parseOpenRouterModelString(model) {
|
|
|
17141
18483
|
}
|
|
17142
18484
|
return { model };
|
|
17143
18485
|
}
|
|
17144
|
-
function
|
|
18486
|
+
function isZodSchema3(value) {
|
|
17145
18487
|
return value != null && typeof value === "object" && "_def" in value && typeof value._def === "object";
|
|
17146
18488
|
}
|
|
17147
|
-
function
|
|
18489
|
+
function serializeZodSchema3(schema) {
|
|
17148
18490
|
try {
|
|
17149
18491
|
return zodToJsonSchema(schema);
|
|
17150
18492
|
} catch {
|
|
@@ -17178,8 +18520,8 @@ function serializeOpenRouterToolsForLogging(tools) {
|
|
|
17178
18520
|
return tools.map((tool) => serializeOpenRouterTool(tool));
|
|
17179
18521
|
}
|
|
17180
18522
|
function sanitizeOpenRouterLoggedValue(value) {
|
|
17181
|
-
if (
|
|
17182
|
-
return
|
|
18523
|
+
if (isZodSchema3(value)) {
|
|
18524
|
+
return serializeZodSchema3(value);
|
|
17183
18525
|
}
|
|
17184
18526
|
if (typeof value === "function") {
|
|
17185
18527
|
return "[Function]";
|
|
@@ -17203,7 +18545,7 @@ function sanitizeOpenRouterLoggedValue(value) {
|
|
|
17203
18545
|
}
|
|
17204
18546
|
return sanitized;
|
|
17205
18547
|
}
|
|
17206
|
-
function buildOpenRouterMetadata(metadata, httpReferer, xTitle) {
|
|
18548
|
+
function buildOpenRouterMetadata(metadata, httpReferer, appTitle, appCategories, xTitle) {
|
|
17207
18549
|
const sanitized = sanitizeOpenRouterLoggedValue(metadata);
|
|
17208
18550
|
const metadataRecord = isObject(sanitized) ? sanitized : {};
|
|
17209
18551
|
const { model, provider: providerRouting, ...rest } = metadataRecord;
|
|
@@ -17213,17 +18555,12 @@ function buildOpenRouterMetadata(metadata, httpReferer, xTitle) {
|
|
|
17213
18555
|
...normalizedModel.model !== void 0 ? { model: normalizedModel.model } : {},
|
|
17214
18556
|
...providerRouting !== void 0 ? { providerRouting } : {},
|
|
17215
18557
|
...httpReferer !== void 0 ? { httpReferer } : {},
|
|
18558
|
+
...appTitle !== void 0 ? { appTitle } : {},
|
|
18559
|
+
...appCategories !== void 0 ? { appCategories } : {},
|
|
17216
18560
|
...xTitle !== void 0 ? { xTitle } : {},
|
|
17217
18561
|
provider: normalizedModel.provider || "openrouter"
|
|
17218
18562
|
};
|
|
17219
18563
|
}
|
|
17220
|
-
function buildOpenRouterEmbeddingMetadata(metadata, httpReferer, xTitle) {
|
|
17221
|
-
const normalized = buildOpenRouterMetadata(metadata, httpReferer, xTitle);
|
|
17222
|
-
return typeof normalized.model === "string" ? {
|
|
17223
|
-
...normalized,
|
|
17224
|
-
embedding_model: normalized.model
|
|
17225
|
-
} : normalized;
|
|
17226
|
-
}
|
|
17227
18564
|
function extractOpenRouterCallModelInput(request) {
|
|
17228
18565
|
return isObject(request) && "input" in request ? sanitizeOpenRouterLoggedValue(request.input) : void 0;
|
|
17229
18566
|
}
|
|
@@ -17232,7 +18569,13 @@ function extractOpenRouterCallModelMetadata(request) {
|
|
|
17232
18569
|
return { provider: "openrouter" };
|
|
17233
18570
|
}
|
|
17234
18571
|
const { input: _input, ...metadata } = request;
|
|
17235
|
-
return buildOpenRouterMetadata(
|
|
18572
|
+
return buildOpenRouterMetadata(
|
|
18573
|
+
metadata,
|
|
18574
|
+
void 0,
|
|
18575
|
+
void 0,
|
|
18576
|
+
void 0,
|
|
18577
|
+
void 0
|
|
18578
|
+
);
|
|
17236
18579
|
}
|
|
17237
18580
|
function extractOpenRouterResponseMetadata(result) {
|
|
17238
18581
|
if (!isObject(result)) {
|
|
@@ -17262,9 +18605,101 @@ function extractOpenRouterResponseOutput(response, fallbackOutput) {
|
|
|
17262
18605
|
}
|
|
17263
18606
|
return void 0;
|
|
17264
18607
|
}
|
|
17265
|
-
|
|
17266
|
-
// src/openrouter-tool-wrapping.ts
|
|
17267
18608
|
var OPENROUTER_WRAPPED_TOOL = Symbol("braintrust.openrouter.wrappedTool");
|
|
18609
|
+
function patchOpenRouterCallModelRequestTools(request) {
|
|
18610
|
+
if (!Array.isArray(request.tools) || request.tools.length === 0) {
|
|
18611
|
+
return void 0;
|
|
18612
|
+
}
|
|
18613
|
+
const originalTools = request.tools;
|
|
18614
|
+
const wrappedTools = originalTools.map((tool) => wrapOpenRouterTool(tool));
|
|
18615
|
+
const didPatch = wrappedTools.some(
|
|
18616
|
+
(tool, index) => tool !== originalTools[index]
|
|
18617
|
+
);
|
|
18618
|
+
if (!didPatch) {
|
|
18619
|
+
return void 0;
|
|
18620
|
+
}
|
|
18621
|
+
request.tools = wrappedTools;
|
|
18622
|
+
return () => {
|
|
18623
|
+
request.tools = originalTools;
|
|
18624
|
+
};
|
|
18625
|
+
}
|
|
18626
|
+
function wrapOpenRouterTool(tool) {
|
|
18627
|
+
if (isWrappedTool(tool) || !tool.function || typeof tool.function !== "object" || typeof tool.function.execute !== "function") {
|
|
18628
|
+
return tool;
|
|
18629
|
+
}
|
|
18630
|
+
const toolName = tool.function.name || "tool";
|
|
18631
|
+
const originalExecute = tool.function.execute;
|
|
18632
|
+
const wrappedTool = {
|
|
18633
|
+
...tool,
|
|
18634
|
+
function: {
|
|
18635
|
+
...tool.function,
|
|
18636
|
+
execute(...args) {
|
|
18637
|
+
return traceToolExecution({
|
|
18638
|
+
args,
|
|
18639
|
+
execute: () => Reflect.apply(originalExecute, this, args),
|
|
18640
|
+
toolCallId: getToolCallId(args[1]),
|
|
18641
|
+
toolName
|
|
18642
|
+
});
|
|
18643
|
+
}
|
|
18644
|
+
}
|
|
18645
|
+
};
|
|
18646
|
+
Object.defineProperty(wrappedTool, OPENROUTER_WRAPPED_TOOL, {
|
|
18647
|
+
value: true,
|
|
18648
|
+
enumerable: false,
|
|
18649
|
+
configurable: false
|
|
18650
|
+
});
|
|
18651
|
+
return wrappedTool;
|
|
18652
|
+
}
|
|
18653
|
+
function isWrappedTool(tool) {
|
|
18654
|
+
return Boolean(tool[OPENROUTER_WRAPPED_TOOL]);
|
|
18655
|
+
}
|
|
18656
|
+
function traceToolExecution(args) {
|
|
18657
|
+
const tracingChannel2 = openRouterAgentChannels.toolExecute.tracingChannel();
|
|
18658
|
+
const input = args.args.length > 0 ? args.args[0] : void 0;
|
|
18659
|
+
const event = {
|
|
18660
|
+
arguments: [input],
|
|
18661
|
+
span_info: {
|
|
18662
|
+
name: args.toolName
|
|
18663
|
+
},
|
|
18664
|
+
toolCallId: args.toolCallId,
|
|
18665
|
+
toolName: args.toolName
|
|
18666
|
+
};
|
|
18667
|
+
tracingChannel2.start.publish(event);
|
|
18668
|
+
try {
|
|
18669
|
+
const result = args.execute();
|
|
18670
|
+
return publishToolResult(tracingChannel2, event, result);
|
|
18671
|
+
} catch (error2) {
|
|
18672
|
+
event.error = normalizeError(error2);
|
|
18673
|
+
tracingChannel2.error.publish(event);
|
|
18674
|
+
throw error2;
|
|
18675
|
+
}
|
|
18676
|
+
}
|
|
18677
|
+
function publishToolResult(tracingChannel2, event, result) {
|
|
18678
|
+
if (isPromiseLike3(result)) {
|
|
18679
|
+
return result.then(
|
|
18680
|
+
(resolved) => {
|
|
18681
|
+
event.result = resolved;
|
|
18682
|
+
tracingChannel2.asyncEnd.publish(event);
|
|
18683
|
+
return resolved;
|
|
18684
|
+
},
|
|
18685
|
+
(error2) => {
|
|
18686
|
+
event.error = normalizeError(error2);
|
|
18687
|
+
tracingChannel2.error.publish(event);
|
|
18688
|
+
throw error2;
|
|
18689
|
+
}
|
|
18690
|
+
);
|
|
18691
|
+
}
|
|
18692
|
+
event.result = result;
|
|
18693
|
+
tracingChannel2.asyncEnd.publish(event);
|
|
18694
|
+
return result;
|
|
18695
|
+
}
|
|
18696
|
+
function getToolCallId(context2) {
|
|
18697
|
+
const toolContext = context2;
|
|
18698
|
+
return typeof toolContext?.toolCall?.id === "string" ? toolContext.toolCall.id : void 0;
|
|
18699
|
+
}
|
|
18700
|
+
function isPromiseLike3(value) {
|
|
18701
|
+
return !!value && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function";
|
|
18702
|
+
}
|
|
17268
18703
|
var OPENROUTER_WRAPPED_CALL_MODEL_RESULT = Symbol(
|
|
17269
18704
|
"braintrust.openrouter.wrappedCallModelResult"
|
|
17270
18705
|
);
|
|
@@ -17284,24 +18719,8 @@ var OPENROUTER_CALL_MODEL_CONTEXT_METHODS = [
|
|
|
17284
18719
|
"getToolCalls",
|
|
17285
18720
|
"requiresApproval"
|
|
17286
18721
|
];
|
|
17287
|
-
function
|
|
17288
|
-
|
|
17289
|
-
return void 0;
|
|
17290
|
-
}
|
|
17291
|
-
const originalTools = request.tools;
|
|
17292
|
-
const wrappedTools = originalTools.map((tool) => wrapOpenRouterTool(tool));
|
|
17293
|
-
const didPatch = wrappedTools.some(
|
|
17294
|
-
(tool, index) => tool !== originalTools[index]
|
|
17295
|
-
);
|
|
17296
|
-
if (!didPatch) {
|
|
17297
|
-
return void 0;
|
|
17298
|
-
}
|
|
17299
|
-
request.tools = wrappedTools;
|
|
17300
|
-
return () => {
|
|
17301
|
-
request.tools = originalTools;
|
|
17302
|
-
};
|
|
17303
|
-
}
|
|
17304
|
-
function patchOpenRouterCallModelResult(span, result, request) {
|
|
18722
|
+
function patchOpenRouterCallModelResult(args) {
|
|
18723
|
+
const { request, result, span } = args;
|
|
17305
18724
|
if (!isObject(result) || isWrappedCallModelResult(result)) {
|
|
17306
18725
|
return false;
|
|
17307
18726
|
}
|
|
@@ -17374,10 +18793,10 @@ function patchOpenRouterCallModelResult(span, result, request) {
|
|
|
17374
18793
|
}
|
|
17375
18794
|
};
|
|
17376
18795
|
if (originalGetResponse) {
|
|
17377
|
-
resultLike.getResponse = async (...
|
|
18796
|
+
resultLike.getResponse = async (...args2) => {
|
|
17378
18797
|
return await withCurrent(span, async () => {
|
|
17379
18798
|
try {
|
|
17380
|
-
const response = await originalGetResponse(...
|
|
18799
|
+
const response = await originalGetResponse(...args2);
|
|
17381
18800
|
await endSpanWithResult(response);
|
|
17382
18801
|
return response;
|
|
17383
18802
|
} catch (error2) {
|
|
@@ -17389,10 +18808,10 @@ function patchOpenRouterCallModelResult(span, result, request) {
|
|
|
17389
18808
|
}
|
|
17390
18809
|
if (typeof resultLike.getText === "function") {
|
|
17391
18810
|
const originalGetText = resultLike.getText.bind(resultLike);
|
|
17392
|
-
resultLike.getText = async (...
|
|
18811
|
+
resultLike.getText = async (...args2) => {
|
|
17393
18812
|
return await withCurrent(span, async () => {
|
|
17394
18813
|
try {
|
|
17395
|
-
const text = await originalGetText(...
|
|
18814
|
+
const text = await originalGetText(...args2);
|
|
17396
18815
|
await finalizeFromResponse(text);
|
|
17397
18816
|
return text;
|
|
17398
18817
|
} catch (error2) {
|
|
@@ -17407,9 +18826,9 @@ function patchOpenRouterCallModelResult(span, result, request) {
|
|
|
17407
18826
|
continue;
|
|
17408
18827
|
}
|
|
17409
18828
|
const originalMethod = resultLike[methodName];
|
|
17410
|
-
resultLike[methodName] = async (...
|
|
18829
|
+
resultLike[methodName] = async (...args2) => {
|
|
17411
18830
|
return await withCurrent(span, async () => {
|
|
17412
|
-
return await originalMethod.apply(resultLike,
|
|
18831
|
+
return await originalMethod.apply(resultLike, args2);
|
|
17413
18832
|
});
|
|
17414
18833
|
};
|
|
17415
18834
|
}
|
|
@@ -17418,12 +18837,12 @@ function patchOpenRouterCallModelResult(span, result, request) {
|
|
|
17418
18837
|
continue;
|
|
17419
18838
|
}
|
|
17420
18839
|
const originalMethod = resultLike[methodName];
|
|
17421
|
-
resultLike[methodName] = (...
|
|
18840
|
+
resultLike[methodName] = (...args2) => {
|
|
17422
18841
|
const stream = withCurrent(
|
|
17423
18842
|
span,
|
|
17424
|
-
() => originalMethod.apply(resultLike,
|
|
18843
|
+
() => originalMethod.apply(resultLike, args2)
|
|
17425
18844
|
);
|
|
17426
|
-
if (!
|
|
18845
|
+
if (!isAsyncIterable5(stream)) {
|
|
17427
18846
|
return stream;
|
|
17428
18847
|
}
|
|
17429
18848
|
return wrapAsyncIterableWithSpan({
|
|
@@ -17436,157 +18855,70 @@ function patchOpenRouterCallModelResult(span, result, request) {
|
|
|
17436
18855
|
}
|
|
17437
18856
|
if (originalGetInitialResponse) {
|
|
17438
18857
|
let initialTurnTraced = false;
|
|
17439
|
-
resultLike.getInitialResponse = async (...
|
|
18858
|
+
resultLike.getInitialResponse = async (...args2) => {
|
|
17440
18859
|
if (initialTurnTraced) {
|
|
17441
18860
|
return await withCurrent(span, async () => {
|
|
17442
|
-
return await originalGetInitialResponse(...
|
|
18861
|
+
return await originalGetInitialResponse(...args2);
|
|
17443
18862
|
});
|
|
17444
18863
|
}
|
|
17445
18864
|
initialTurnTraced = true;
|
|
17446
|
-
const
|
|
17447
|
-
const
|
|
17448
|
-
|
|
17449
|
-
|
|
17450
|
-
|
|
17451
|
-
});
|
|
17452
|
-
return await withCurrent(childSpan, async () => {
|
|
17453
|
-
try {
|
|
17454
|
-
const response = await originalGetInitialResponse(...args);
|
|
18865
|
+
const step = tracedTurnCount + 1;
|
|
18866
|
+
const stepType = tracedTurnCount === 0 ? "initial" : "continue";
|
|
18867
|
+
const response = await traceOpenRouterCallModelTurn({
|
|
18868
|
+
fn: async () => {
|
|
18869
|
+
const nextResponse = await originalGetInitialResponse(...args2);
|
|
17455
18870
|
tracedTurnCount++;
|
|
17456
|
-
|
|
17457
|
-
|
|
17458
|
-
|
|
17459
|
-
|
|
17460
|
-
|
|
17461
|
-
|
|
17462
|
-
return response;
|
|
17463
|
-
} catch (error2) {
|
|
17464
|
-
childSpan.log({
|
|
17465
|
-
error: normalizeError(error2).message
|
|
17466
|
-
});
|
|
17467
|
-
childSpan.end();
|
|
17468
|
-
throw error2;
|
|
17469
|
-
}
|
|
18871
|
+
return nextResponse;
|
|
18872
|
+
},
|
|
18873
|
+
parentSpan: span,
|
|
18874
|
+
request: getOpenRouterResolvedRequest(resultLike, request),
|
|
18875
|
+
step,
|
|
18876
|
+
stepType
|
|
17470
18877
|
});
|
|
18878
|
+
return response;
|
|
17471
18879
|
};
|
|
17472
18880
|
}
|
|
17473
18881
|
if (originalMakeFollowupRequest) {
|
|
17474
|
-
resultLike.makeFollowupRequest = async (...
|
|
17475
|
-
const currentResponse =
|
|
17476
|
-
const toolResults = Array.isArray(
|
|
17477
|
-
const
|
|
17478
|
-
const
|
|
17479
|
-
|
|
17480
|
-
|
|
17481
|
-
toolResults
|
|
17482
|
-
);
|
|
17483
|
-
const childSpan = startOpenRouterCallModelTurnSpan({
|
|
17484
|
-
request: followupRequest,
|
|
17485
|
-
step: tracedTurnCount + 1,
|
|
17486
|
-
stepType: "continue"
|
|
17487
|
-
});
|
|
17488
|
-
return await withCurrent(childSpan, async () => {
|
|
17489
|
-
try {
|
|
17490
|
-
const response = await originalMakeFollowupRequest(...args);
|
|
18882
|
+
resultLike.makeFollowupRequest = async (...args2) => {
|
|
18883
|
+
const currentResponse = args2[0];
|
|
18884
|
+
const toolResults = Array.isArray(args2[1]) ? args2[1] : [];
|
|
18885
|
+
const step = tracedTurnCount + 1;
|
|
18886
|
+
const response = await traceOpenRouterCallModelTurn({
|
|
18887
|
+
fn: async () => {
|
|
18888
|
+
const nextResponse = await originalMakeFollowupRequest(...args2);
|
|
17491
18889
|
tracedTurnCount++;
|
|
17492
|
-
|
|
17493
|
-
|
|
17494
|
-
|
|
17495
|
-
|
|
17496
|
-
|
|
17497
|
-
|
|
17498
|
-
|
|
17499
|
-
|
|
17500
|
-
|
|
17501
|
-
|
|
17502
|
-
});
|
|
17503
|
-
childSpan.end();
|
|
17504
|
-
throw error2;
|
|
17505
|
-
}
|
|
18890
|
+
return nextResponse;
|
|
18891
|
+
},
|
|
18892
|
+
parentSpan: span,
|
|
18893
|
+
request: buildOpenRouterFollowupRequest(
|
|
18894
|
+
getOpenRouterResolvedRequest(resultLike, request),
|
|
18895
|
+
currentResponse,
|
|
18896
|
+
toolResults
|
|
18897
|
+
),
|
|
18898
|
+
step,
|
|
18899
|
+
stepType: "continue"
|
|
17506
18900
|
});
|
|
18901
|
+
return response;
|
|
17507
18902
|
};
|
|
17508
18903
|
}
|
|
17509
18904
|
return true;
|
|
17510
18905
|
}
|
|
17511
|
-
function
|
|
17512
|
-
|
|
17513
|
-
|
|
17514
|
-
|
|
17515
|
-
|
|
17516
|
-
const originalExecute = tool.function.execute;
|
|
17517
|
-
const wrappedTool = {
|
|
17518
|
-
...tool,
|
|
17519
|
-
function: {
|
|
17520
|
-
...tool.function,
|
|
17521
|
-
execute(...args) {
|
|
17522
|
-
return traceToolExecution({
|
|
17523
|
-
args,
|
|
17524
|
-
execute: () => Reflect.apply(originalExecute, this, args),
|
|
17525
|
-
toolCallId: getToolCallId(args[1]),
|
|
17526
|
-
toolName
|
|
17527
|
-
});
|
|
17528
|
-
}
|
|
17529
|
-
}
|
|
18906
|
+
async function traceOpenRouterCallModelTurn(args) {
|
|
18907
|
+
const context2 = {
|
|
18908
|
+
arguments: [args.request],
|
|
18909
|
+
step: args.step,
|
|
18910
|
+
stepType: args.stepType
|
|
17530
18911
|
};
|
|
17531
|
-
|
|
17532
|
-
|
|
17533
|
-
|
|
17534
|
-
|
|
17535
|
-
});
|
|
17536
|
-
return wrappedTool;
|
|
17537
|
-
}
|
|
17538
|
-
function isWrappedTool(tool) {
|
|
17539
|
-
return Boolean(tool[OPENROUTER_WRAPPED_TOOL]);
|
|
18912
|
+
return await withCurrent(
|
|
18913
|
+
args.parentSpan,
|
|
18914
|
+
() => openRouterAgentChannels.callModelTurn.tracePromise(args.fn, context2)
|
|
18915
|
+
);
|
|
17540
18916
|
}
|
|
17541
18917
|
function isWrappedCallModelResult(value) {
|
|
17542
18918
|
return Boolean(
|
|
17543
18919
|
isObject(value) && value[OPENROUTER_WRAPPED_CALL_MODEL_RESULT]
|
|
17544
18920
|
);
|
|
17545
18921
|
}
|
|
17546
|
-
function traceToolExecution(args) {
|
|
17547
|
-
const tracingChannel2 = openRouterChannels.toolExecute.tracingChannel();
|
|
17548
|
-
const input = args.args.length > 0 ? args.args[0] : void 0;
|
|
17549
|
-
const event = {
|
|
17550
|
-
arguments: [input],
|
|
17551
|
-
span_info: {
|
|
17552
|
-
name: args.toolName
|
|
17553
|
-
},
|
|
17554
|
-
toolCallId: args.toolCallId,
|
|
17555
|
-
toolName: args.toolName
|
|
17556
|
-
};
|
|
17557
|
-
tracingChannel2.start.publish(event);
|
|
17558
|
-
try {
|
|
17559
|
-
const result = args.execute();
|
|
17560
|
-
return publishToolResult(tracingChannel2, event, result);
|
|
17561
|
-
} catch (error2) {
|
|
17562
|
-
event.error = normalizeError(error2);
|
|
17563
|
-
tracingChannel2.error.publish(event);
|
|
17564
|
-
throw error2;
|
|
17565
|
-
}
|
|
17566
|
-
}
|
|
17567
|
-
function publishToolResult(tracingChannel2, event, result) {
|
|
17568
|
-
if (isPromiseLike(result)) {
|
|
17569
|
-
return result.then(
|
|
17570
|
-
(resolved) => {
|
|
17571
|
-
event.result = resolved;
|
|
17572
|
-
tracingChannel2.asyncEnd.publish(event);
|
|
17573
|
-
return resolved;
|
|
17574
|
-
},
|
|
17575
|
-
(error2) => {
|
|
17576
|
-
event.error = normalizeError(error2);
|
|
17577
|
-
tracingChannel2.error.publish(event);
|
|
17578
|
-
throw error2;
|
|
17579
|
-
}
|
|
17580
|
-
);
|
|
17581
|
-
}
|
|
17582
|
-
event.result = result;
|
|
17583
|
-
tracingChannel2.asyncEnd.publish(event);
|
|
17584
|
-
return result;
|
|
17585
|
-
}
|
|
17586
|
-
function getToolCallId(context2) {
|
|
17587
|
-
const toolContext = context2;
|
|
17588
|
-
return typeof toolContext?.toolCall?.id === "string" ? toolContext.toolCall.id : void 0;
|
|
17589
|
-
}
|
|
17590
18922
|
function extractOpenRouterCallModelResultMetadata(response, turnCount) {
|
|
17591
18923
|
const combined = {
|
|
17592
18924
|
...extractOpenRouterResponseMetadata(response) || {},
|
|
@@ -17631,45 +18963,6 @@ function buildNextOpenRouterCallModelInput(currentInput, response, toolResults)
|
|
|
17631
18963
|
(entry) => sanitizeOpenRouterLoggedValue(entry)
|
|
17632
18964
|
);
|
|
17633
18965
|
}
|
|
17634
|
-
function startOpenRouterCallModelTurnSpan(args) {
|
|
17635
|
-
const requestRecord = isObject(args.request) ? args.request : void 0;
|
|
17636
|
-
const metadata = requestRecord ? extractOpenRouterCallModelMetadata(requestRecord) : { provider: "openrouter" };
|
|
17637
|
-
if (isObject(metadata) && "tools" in metadata) {
|
|
17638
|
-
delete metadata.tools;
|
|
17639
|
-
}
|
|
17640
|
-
return startSpan({
|
|
17641
|
-
name: "openrouter.beta.responses.send",
|
|
17642
|
-
spanAttributes: {
|
|
17643
|
-
type: "llm" /* LLM */
|
|
17644
|
-
},
|
|
17645
|
-
event: {
|
|
17646
|
-
input: requestRecord ? extractOpenRouterCallModelInput(requestRecord) : void 0,
|
|
17647
|
-
metadata: {
|
|
17648
|
-
...metadata,
|
|
17649
|
-
step: args.step,
|
|
17650
|
-
step_type: args.stepType
|
|
17651
|
-
}
|
|
17652
|
-
}
|
|
17653
|
-
});
|
|
17654
|
-
}
|
|
17655
|
-
function finishOpenRouterCallModelTurnSpan(args) {
|
|
17656
|
-
if (!isObject(args.response)) {
|
|
17657
|
-
args.span.end();
|
|
17658
|
-
return;
|
|
17659
|
-
}
|
|
17660
|
-
args.span.log({
|
|
17661
|
-
output: extractOpenRouterResponseOutput(args.response),
|
|
17662
|
-
...extractOpenRouterResponseMetadata(args.response) ? {
|
|
17663
|
-
metadata: {
|
|
17664
|
-
...extractOpenRouterResponseMetadata(args.response),
|
|
17665
|
-
...args.step !== void 0 ? { step: args.step } : {},
|
|
17666
|
-
...args.stepType ? { step_type: args.stepType } : {}
|
|
17667
|
-
}
|
|
17668
|
-
} : {},
|
|
17669
|
-
metrics: parseOpenRouterMetricsFromUsage(args.response.usage)
|
|
17670
|
-
});
|
|
17671
|
-
args.span.end();
|
|
17672
|
-
}
|
|
17673
18966
|
function getOpenRouterResolvedRequest(result, request) {
|
|
17674
18967
|
if (isObject(result.resolvedRequest)) {
|
|
17675
18968
|
return result.resolvedRequest;
|
|
@@ -17744,16 +19037,41 @@ function wrapAsyncIterableWithSpan(args) {
|
|
|
17744
19037
|
}
|
|
17745
19038
|
};
|
|
17746
19039
|
}
|
|
17747
|
-
function
|
|
19040
|
+
function isAsyncIterable5(value) {
|
|
17748
19041
|
return !!value && (typeof value === "object" || typeof value === "function") && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
|
|
17749
19042
|
}
|
|
17750
|
-
function isPromiseLike(value) {
|
|
17751
|
-
return !!value && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function";
|
|
17752
|
-
}
|
|
17753
19043
|
function normalizeError(error2) {
|
|
17754
19044
|
return error2 instanceof Error ? error2 : new Error(String(error2));
|
|
17755
19045
|
}
|
|
17756
19046
|
|
|
19047
|
+
// src/instrumentation/plugins/openrouter-channels.ts
|
|
19048
|
+
var openRouterChannels = defineChannels("@openrouter/sdk", {
|
|
19049
|
+
chatSend: channel({
|
|
19050
|
+
channelName: "chat.send",
|
|
19051
|
+
kind: "async"
|
|
19052
|
+
}),
|
|
19053
|
+
embeddingsGenerate: channel({
|
|
19054
|
+
channelName: "embeddings.generate",
|
|
19055
|
+
kind: "async"
|
|
19056
|
+
}),
|
|
19057
|
+
betaResponsesSend: channel({
|
|
19058
|
+
channelName: "beta.responses.send",
|
|
19059
|
+
kind: "async"
|
|
19060
|
+
}),
|
|
19061
|
+
callModel: channel({
|
|
19062
|
+
channelName: "callModel",
|
|
19063
|
+
kind: "sync-stream"
|
|
19064
|
+
}),
|
|
19065
|
+
callModelTurn: channel({
|
|
19066
|
+
channelName: "callModel.turn",
|
|
19067
|
+
kind: "async"
|
|
19068
|
+
}),
|
|
19069
|
+
toolExecute: channel({
|
|
19070
|
+
channelName: "tool.execute",
|
|
19071
|
+
kind: "async"
|
|
19072
|
+
})
|
|
19073
|
+
});
|
|
19074
|
+
|
|
17757
19075
|
// src/instrumentation/plugins/openrouter-plugin.ts
|
|
17758
19076
|
var OpenRouterPlugin = class extends BasePlugin {
|
|
17759
19077
|
onEnable() {
|
|
@@ -17775,14 +19093,14 @@ var OpenRouterPlugin = class extends BasePlugin {
|
|
|
17775
19093
|
const { messages, ...metadata } = chatGenerationParams;
|
|
17776
19094
|
return {
|
|
17777
19095
|
input: messages,
|
|
17778
|
-
metadata:
|
|
19096
|
+
metadata: buildOpenRouterMetadata2(metadata, httpReferer, xTitle)
|
|
17779
19097
|
};
|
|
17780
19098
|
},
|
|
17781
19099
|
extractOutput: (result) => {
|
|
17782
19100
|
return isObject(result) ? result.choices : void 0;
|
|
17783
19101
|
},
|
|
17784
19102
|
extractMetrics: (result, startTime) => {
|
|
17785
|
-
const metrics =
|
|
19103
|
+
const metrics = parseOpenRouterMetricsFromUsage2(result?.usage);
|
|
17786
19104
|
if (startTime) {
|
|
17787
19105
|
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
17788
19106
|
}
|
|
@@ -17821,10 +19139,10 @@ var OpenRouterPlugin = class extends BasePlugin {
|
|
|
17821
19139
|
if (!isObject(result)) {
|
|
17822
19140
|
return void 0;
|
|
17823
19141
|
}
|
|
17824
|
-
return
|
|
19142
|
+
return extractOpenRouterResponseMetadata2(result);
|
|
17825
19143
|
},
|
|
17826
19144
|
extractMetrics: (result) => {
|
|
17827
|
-
return isObject(result) ?
|
|
19145
|
+
return isObject(result) ? parseOpenRouterMetricsFromUsage2(result.usage) : {};
|
|
17828
19146
|
}
|
|
17829
19147
|
})
|
|
17830
19148
|
);
|
|
@@ -17840,13 +19158,13 @@ var OpenRouterPlugin = class extends BasePlugin {
|
|
|
17840
19158
|
const { input, ...metadata } = openResponsesRequest;
|
|
17841
19159
|
return {
|
|
17842
19160
|
input,
|
|
17843
|
-
metadata:
|
|
19161
|
+
metadata: buildOpenRouterMetadata2(metadata, httpReferer, xTitle)
|
|
17844
19162
|
};
|
|
17845
19163
|
},
|
|
17846
|
-
extractOutput: (result) =>
|
|
17847
|
-
extractMetadata: (result) =>
|
|
19164
|
+
extractOutput: (result) => extractOpenRouterResponseOutput2(result),
|
|
19165
|
+
extractMetadata: (result) => extractOpenRouterResponseMetadata2(result),
|
|
17848
19166
|
extractMetrics: (result, startTime) => {
|
|
17849
|
-
const metrics =
|
|
19167
|
+
const metrics = parseOpenRouterMetricsFromUsage2(result?.usage);
|
|
17850
19168
|
if (startTime) {
|
|
17851
19169
|
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
17852
19170
|
}
|
|
@@ -17860,21 +19178,57 @@ var OpenRouterPlugin = class extends BasePlugin {
|
|
|
17860
19178
|
name: "openrouter.callModel",
|
|
17861
19179
|
type: "llm" /* LLM */,
|
|
17862
19180
|
extractInput: (args) => {
|
|
17863
|
-
const request =
|
|
19181
|
+
const request = getOpenRouterCallModelRequestArg2(args);
|
|
17864
19182
|
return {
|
|
17865
|
-
input: request ?
|
|
17866
|
-
metadata: request ?
|
|
19183
|
+
input: request ? extractOpenRouterCallModelInput2(request) : void 0,
|
|
19184
|
+
metadata: request ? extractOpenRouterCallModelMetadata2(request) : { provider: "openrouter" }
|
|
17867
19185
|
};
|
|
17868
19186
|
},
|
|
17869
19187
|
patchResult: ({ endEvent, result, span }) => {
|
|
17870
|
-
return
|
|
17871
|
-
|
|
19188
|
+
return patchOpenRouterCallModelResult2({
|
|
19189
|
+
request: getOpenRouterCallModelRequestArg2(endEvent.arguments),
|
|
17872
19190
|
result,
|
|
17873
|
-
|
|
17874
|
-
);
|
|
19191
|
+
span
|
|
19192
|
+
});
|
|
17875
19193
|
}
|
|
17876
19194
|
})
|
|
17877
19195
|
);
|
|
19196
|
+
this.unsubscribers.push(
|
|
19197
|
+
traceAsyncChannel(openRouterChannels.callModelTurn, {
|
|
19198
|
+
name: "openrouter.beta.responses.send",
|
|
19199
|
+
type: "llm" /* LLM */,
|
|
19200
|
+
extractInput: (args, event) => {
|
|
19201
|
+
const request = getOpenRouterCallModelRequestArg2(args);
|
|
19202
|
+
const metadata = request ? extractOpenRouterCallModelMetadata2(request) : { provider: "openrouter" };
|
|
19203
|
+
if (isObject(metadata) && "tools" in metadata) {
|
|
19204
|
+
delete metadata.tools;
|
|
19205
|
+
}
|
|
19206
|
+
return {
|
|
19207
|
+
input: request ? extractOpenRouterCallModelInput2(request) : void 0,
|
|
19208
|
+
metadata: {
|
|
19209
|
+
...metadata,
|
|
19210
|
+
step: event.step,
|
|
19211
|
+
step_type: event.stepType
|
|
19212
|
+
}
|
|
19213
|
+
};
|
|
19214
|
+
},
|
|
19215
|
+
extractOutput: (result) => extractOpenRouterResponseOutput2(result),
|
|
19216
|
+
extractMetadata: (result, event) => {
|
|
19217
|
+
if (!isObject(result)) {
|
|
19218
|
+
return {
|
|
19219
|
+
step: event?.step,
|
|
19220
|
+
step_type: event?.stepType
|
|
19221
|
+
};
|
|
19222
|
+
}
|
|
19223
|
+
return {
|
|
19224
|
+
...extractOpenRouterResponseMetadata2(result) || {},
|
|
19225
|
+
...event?.step !== void 0 ? { step: event.step } : {},
|
|
19226
|
+
...event?.stepType ? { step_type: event.stepType } : {}
|
|
19227
|
+
};
|
|
19228
|
+
},
|
|
19229
|
+
extractMetrics: (result) => isObject(result) ? parseOpenRouterMetricsFromUsage2(result.usage) : {}
|
|
19230
|
+
})
|
|
19231
|
+
);
|
|
17878
19232
|
this.unsubscribers.push(
|
|
17879
19233
|
traceStreamingChannel(openRouterChannels.toolExecute, {
|
|
17880
19234
|
name: "openrouter.tool",
|
|
@@ -17895,155 +19249,1303 @@ var OpenRouterPlugin = class extends BasePlugin {
|
|
|
17895
19249
|
})
|
|
17896
19250
|
})
|
|
17897
19251
|
);
|
|
17898
|
-
const callModelChannel = openRouterChannels.callModel.tracingChannel();
|
|
17899
|
-
const callModelHandlers = {
|
|
17900
|
-
start: (event) => {
|
|
17901
|
-
const request =
|
|
17902
|
-
if (!request) {
|
|
17903
|
-
return;
|
|
17904
|
-
}
|
|
17905
|
-
|
|
17906
|
-
}
|
|
17907
|
-
};
|
|
17908
|
-
callModelChannel.subscribe(callModelHandlers);
|
|
17909
|
-
this.unsubscribers.push(() => {
|
|
17910
|
-
callModelChannel.unsubscribe(callModelHandlers);
|
|
17911
|
-
});
|
|
19252
|
+
const callModelChannel = openRouterChannels.callModel.tracingChannel();
|
|
19253
|
+
const callModelHandlers = {
|
|
19254
|
+
start: (event) => {
|
|
19255
|
+
const request = getOpenRouterCallModelRequestArg2(event.arguments);
|
|
19256
|
+
if (!request) {
|
|
19257
|
+
return;
|
|
19258
|
+
}
|
|
19259
|
+
patchOpenRouterCallModelRequestTools2(request);
|
|
19260
|
+
}
|
|
19261
|
+
};
|
|
19262
|
+
callModelChannel.subscribe(callModelHandlers);
|
|
19263
|
+
this.unsubscribers.push(() => {
|
|
19264
|
+
callModelChannel.unsubscribe(callModelHandlers);
|
|
19265
|
+
});
|
|
19266
|
+
}
|
|
19267
|
+
};
|
|
19268
|
+
function normalizeArgs2(args) {
|
|
19269
|
+
if (Array.isArray(args)) {
|
|
19270
|
+
return args;
|
|
19271
|
+
}
|
|
19272
|
+
if (isArrayLike3(args)) {
|
|
19273
|
+
return Array.from(args);
|
|
19274
|
+
}
|
|
19275
|
+
return [args];
|
|
19276
|
+
}
|
|
19277
|
+
function isArrayLike3(value) {
|
|
19278
|
+
return isObject(value) && "length" in value && typeof value.length === "number" && Number.isInteger(value.length) && value.length >= 0;
|
|
19279
|
+
}
|
|
19280
|
+
function getOpenRouterRequestArg(args) {
|
|
19281
|
+
const normalizedArgs = normalizeArgs2(args);
|
|
19282
|
+
const keyedCandidate = normalizedArgs.find(
|
|
19283
|
+
(arg) => isObject(arg) && ("chatGenerationParams" in arg || "requestBody" in arg || "openResponsesRequest" in arg)
|
|
19284
|
+
);
|
|
19285
|
+
if (isObject(keyedCandidate)) {
|
|
19286
|
+
return keyedCandidate;
|
|
19287
|
+
}
|
|
19288
|
+
const firstObjectArg = normalizedArgs.find((arg) => isObject(arg));
|
|
19289
|
+
return isObject(firstObjectArg) ? firstObjectArg : void 0;
|
|
19290
|
+
}
|
|
19291
|
+
function getOpenRouterCallModelRequestArg2(args) {
|
|
19292
|
+
const firstObjectArg = normalizeArgs2(args).find((arg) => isObject(arg));
|
|
19293
|
+
return isObject(firstObjectArg) ? firstObjectArg : void 0;
|
|
19294
|
+
}
|
|
19295
|
+
var TOKEN_NAME_MAP3 = {
|
|
19296
|
+
promptTokens: "prompt_tokens",
|
|
19297
|
+
inputTokens: "prompt_tokens",
|
|
19298
|
+
completionTokens: "completion_tokens",
|
|
19299
|
+
outputTokens: "completion_tokens",
|
|
19300
|
+
totalTokens: "tokens",
|
|
19301
|
+
prompt_tokens: "prompt_tokens",
|
|
19302
|
+
input_tokens: "prompt_tokens",
|
|
19303
|
+
completion_tokens: "completion_tokens",
|
|
19304
|
+
output_tokens: "completion_tokens",
|
|
19305
|
+
total_tokens: "tokens"
|
|
19306
|
+
};
|
|
19307
|
+
var TOKEN_DETAIL_PREFIX_MAP2 = {
|
|
19308
|
+
promptTokensDetails: "prompt",
|
|
19309
|
+
inputTokensDetails: "prompt",
|
|
19310
|
+
completionTokensDetails: "completion",
|
|
19311
|
+
outputTokensDetails: "completion",
|
|
19312
|
+
costDetails: "cost",
|
|
19313
|
+
prompt_tokens_details: "prompt",
|
|
19314
|
+
input_tokens_details: "prompt",
|
|
19315
|
+
completion_tokens_details: "completion",
|
|
19316
|
+
output_tokens_details: "completion",
|
|
19317
|
+
cost_details: "cost"
|
|
19318
|
+
};
|
|
19319
|
+
function camelToSnake2(value) {
|
|
19320
|
+
return value.replace(/[A-Z]/g, (match) => `_${match.toLowerCase()}`);
|
|
19321
|
+
}
|
|
19322
|
+
function parseOpenRouterMetricsFromUsage2(usage) {
|
|
19323
|
+
if (!isObject(usage)) {
|
|
19324
|
+
return {};
|
|
19325
|
+
}
|
|
19326
|
+
const metrics = {};
|
|
19327
|
+
for (const [name, value] of Object.entries(usage)) {
|
|
19328
|
+
if (typeof value === "number") {
|
|
19329
|
+
metrics[TOKEN_NAME_MAP3[name] || camelToSnake2(name)] = value;
|
|
19330
|
+
continue;
|
|
19331
|
+
}
|
|
19332
|
+
if (!isObject(value)) {
|
|
19333
|
+
continue;
|
|
19334
|
+
}
|
|
19335
|
+
const prefix = TOKEN_DETAIL_PREFIX_MAP2[name];
|
|
19336
|
+
if (!prefix) {
|
|
19337
|
+
continue;
|
|
19338
|
+
}
|
|
19339
|
+
for (const [nestedName, nestedValue] of Object.entries(value)) {
|
|
19340
|
+
if (typeof nestedValue !== "number") {
|
|
19341
|
+
continue;
|
|
19342
|
+
}
|
|
19343
|
+
metrics[`${prefix}_${camelToSnake2(nestedName)}`] = nestedValue;
|
|
19344
|
+
}
|
|
19345
|
+
}
|
|
19346
|
+
return metrics;
|
|
19347
|
+
}
|
|
19348
|
+
function extractOpenRouterUsageMetadata2(usage) {
|
|
19349
|
+
if (!isObject(usage)) {
|
|
19350
|
+
return void 0;
|
|
19351
|
+
}
|
|
19352
|
+
const metadata = {};
|
|
19353
|
+
if (typeof usage.isByok === "boolean") {
|
|
19354
|
+
metadata.is_byok = usage.isByok;
|
|
19355
|
+
} else if (typeof usage.is_byok === "boolean") {
|
|
19356
|
+
metadata.is_byok = usage.is_byok;
|
|
19357
|
+
}
|
|
19358
|
+
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
19359
|
+
}
|
|
19360
|
+
var OMITTED_OPENROUTER_KEYS2 = /* @__PURE__ */ new Set([
|
|
19361
|
+
"execute",
|
|
19362
|
+
"render",
|
|
19363
|
+
"nextTurnParams",
|
|
19364
|
+
"requireApproval"
|
|
19365
|
+
]);
|
|
19366
|
+
function parseOpenRouterModelString2(model) {
|
|
19367
|
+
if (typeof model !== "string") {
|
|
19368
|
+
return { model };
|
|
19369
|
+
}
|
|
19370
|
+
const slashIndex = model.indexOf("/");
|
|
19371
|
+
if (slashIndex > 0 && slashIndex < model.length - 1) {
|
|
19372
|
+
return {
|
|
19373
|
+
provider: model.substring(0, slashIndex),
|
|
19374
|
+
model: model.substring(slashIndex + 1)
|
|
19375
|
+
};
|
|
19376
|
+
}
|
|
19377
|
+
return { model };
|
|
19378
|
+
}
|
|
19379
|
+
function isZodSchema4(value) {
|
|
19380
|
+
return value != null && typeof value === "object" && "_def" in value && typeof value._def === "object";
|
|
19381
|
+
}
|
|
19382
|
+
function serializeZodSchema4(schema) {
|
|
19383
|
+
try {
|
|
19384
|
+
return zodToJsonSchema(schema);
|
|
19385
|
+
} catch {
|
|
19386
|
+
return {
|
|
19387
|
+
type: "object",
|
|
19388
|
+
description: "Zod schema (conversion failed)"
|
|
19389
|
+
};
|
|
19390
|
+
}
|
|
19391
|
+
}
|
|
19392
|
+
function serializeOpenRouterTool2(tool) {
|
|
19393
|
+
if (!isObject(tool)) {
|
|
19394
|
+
return tool;
|
|
19395
|
+
}
|
|
19396
|
+
const serialized = {};
|
|
19397
|
+
for (const [key, value] of Object.entries(tool)) {
|
|
19398
|
+
if (OMITTED_OPENROUTER_KEYS2.has(key)) {
|
|
19399
|
+
continue;
|
|
19400
|
+
}
|
|
19401
|
+
if (key === "function" && isObject(value)) {
|
|
19402
|
+
serialized.function = sanitizeOpenRouterLoggedValue2(value);
|
|
19403
|
+
continue;
|
|
19404
|
+
}
|
|
19405
|
+
serialized[key] = sanitizeOpenRouterLoggedValue2(value);
|
|
19406
|
+
}
|
|
19407
|
+
return serialized;
|
|
19408
|
+
}
|
|
19409
|
+
function serializeOpenRouterToolsForLogging2(tools) {
|
|
19410
|
+
if (!Array.isArray(tools)) {
|
|
19411
|
+
return void 0;
|
|
19412
|
+
}
|
|
19413
|
+
return tools.map((tool) => serializeOpenRouterTool2(tool));
|
|
19414
|
+
}
|
|
19415
|
+
function sanitizeOpenRouterLoggedValue2(value) {
|
|
19416
|
+
if (isZodSchema4(value)) {
|
|
19417
|
+
return serializeZodSchema4(value);
|
|
19418
|
+
}
|
|
19419
|
+
if (typeof value === "function") {
|
|
19420
|
+
return "[Function]";
|
|
19421
|
+
}
|
|
19422
|
+
if (Array.isArray(value)) {
|
|
19423
|
+
return value.map((entry) => sanitizeOpenRouterLoggedValue2(entry));
|
|
19424
|
+
}
|
|
19425
|
+
if (!isObject(value)) {
|
|
19426
|
+
return value;
|
|
19427
|
+
}
|
|
19428
|
+
const sanitized = {};
|
|
19429
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
19430
|
+
if (OMITTED_OPENROUTER_KEYS2.has(key)) {
|
|
19431
|
+
continue;
|
|
19432
|
+
}
|
|
19433
|
+
if (key === "tools" && Array.isArray(entry)) {
|
|
19434
|
+
sanitized.tools = serializeOpenRouterToolsForLogging2(entry);
|
|
19435
|
+
continue;
|
|
19436
|
+
}
|
|
19437
|
+
sanitized[key] = sanitizeOpenRouterLoggedValue2(entry);
|
|
19438
|
+
}
|
|
19439
|
+
return sanitized;
|
|
19440
|
+
}
|
|
19441
|
+
function buildOpenRouterMetadata2(metadata, httpReferer, xTitle) {
|
|
19442
|
+
const sanitized = sanitizeOpenRouterLoggedValue2(metadata);
|
|
19443
|
+
const metadataRecord = isObject(sanitized) ? sanitized : {};
|
|
19444
|
+
const { model, provider: providerRouting, ...rest } = metadataRecord;
|
|
19445
|
+
const normalizedModel = parseOpenRouterModelString2(model);
|
|
19446
|
+
return {
|
|
19447
|
+
...rest,
|
|
19448
|
+
...normalizedModel.model !== void 0 ? { model: normalizedModel.model } : {},
|
|
19449
|
+
...providerRouting !== void 0 ? { providerRouting } : {},
|
|
19450
|
+
...httpReferer !== void 0 ? { httpReferer } : {},
|
|
19451
|
+
...xTitle !== void 0 ? { xTitle } : {},
|
|
19452
|
+
provider: normalizedModel.provider || "openrouter"
|
|
19453
|
+
};
|
|
19454
|
+
}
|
|
19455
|
+
function buildOpenRouterEmbeddingMetadata(metadata, httpReferer, xTitle) {
|
|
19456
|
+
const normalized = buildOpenRouterMetadata2(metadata, httpReferer, xTitle);
|
|
19457
|
+
return typeof normalized.model === "string" ? {
|
|
19458
|
+
...normalized,
|
|
19459
|
+
embedding_model: normalized.model
|
|
19460
|
+
} : normalized;
|
|
19461
|
+
}
|
|
19462
|
+
function extractOpenRouterCallModelInput2(request) {
|
|
19463
|
+
return isObject(request) && "input" in request ? sanitizeOpenRouterLoggedValue2(request.input) : void 0;
|
|
19464
|
+
}
|
|
19465
|
+
function extractOpenRouterCallModelMetadata2(request) {
|
|
19466
|
+
if (!isObject(request)) {
|
|
19467
|
+
return { provider: "openrouter" };
|
|
19468
|
+
}
|
|
19469
|
+
const { input: _input, ...metadata } = request;
|
|
19470
|
+
return buildOpenRouterMetadata2(metadata, void 0, void 0);
|
|
19471
|
+
}
|
|
19472
|
+
function extractOpenRouterResponseMetadata2(result) {
|
|
19473
|
+
if (!isObject(result)) {
|
|
19474
|
+
return void 0;
|
|
19475
|
+
}
|
|
19476
|
+
const { output: _output, data: _data, usage, ...metadata } = result;
|
|
19477
|
+
const sanitized = sanitizeOpenRouterLoggedValue2(metadata);
|
|
19478
|
+
const metadataRecord = isObject(sanitized) ? sanitized : {};
|
|
19479
|
+
const { model, provider, ...rest } = metadataRecord;
|
|
19480
|
+
const normalizedModel = parseOpenRouterModelString2(model);
|
|
19481
|
+
const normalizedProvider = (typeof provider === "string" ? provider : void 0) || normalizedModel.provider;
|
|
19482
|
+
const usageMetadata = extractOpenRouterUsageMetadata2(usage);
|
|
19483
|
+
const combined = {
|
|
19484
|
+
...rest,
|
|
19485
|
+
...normalizedModel.model !== void 0 ? { model: normalizedModel.model } : {},
|
|
19486
|
+
...usageMetadata || {},
|
|
19487
|
+
...normalizedProvider !== void 0 ? { provider: normalizedProvider } : {}
|
|
19488
|
+
};
|
|
19489
|
+
return Object.keys(combined).length > 0 ? combined : void 0;
|
|
19490
|
+
}
|
|
19491
|
+
function extractOpenRouterResponseOutput2(response, fallbackOutput) {
|
|
19492
|
+
if (isObject(response) && "output" in response && response.output !== void 0) {
|
|
19493
|
+
return sanitizeOpenRouterLoggedValue2(response.output);
|
|
19494
|
+
}
|
|
19495
|
+
if (fallbackOutput !== void 0) {
|
|
19496
|
+
return sanitizeOpenRouterLoggedValue2(fallbackOutput);
|
|
19497
|
+
}
|
|
19498
|
+
return void 0;
|
|
19499
|
+
}
|
|
19500
|
+
var OPENROUTER_WRAPPED_TOOL2 = Symbol("braintrust.openrouter.wrappedTool");
|
|
19501
|
+
function patchOpenRouterCallModelRequestTools2(request) {
|
|
19502
|
+
if (!Array.isArray(request.tools) || request.tools.length === 0) {
|
|
19503
|
+
return void 0;
|
|
19504
|
+
}
|
|
19505
|
+
const originalTools = request.tools;
|
|
19506
|
+
const wrappedTools = originalTools.map((tool) => wrapOpenRouterTool2(tool));
|
|
19507
|
+
const didPatch = wrappedTools.some(
|
|
19508
|
+
(tool, index) => tool !== originalTools[index]
|
|
19509
|
+
);
|
|
19510
|
+
if (!didPatch) {
|
|
19511
|
+
return void 0;
|
|
19512
|
+
}
|
|
19513
|
+
request.tools = wrappedTools;
|
|
19514
|
+
return () => {
|
|
19515
|
+
request.tools = originalTools;
|
|
19516
|
+
};
|
|
19517
|
+
}
|
|
19518
|
+
function wrapOpenRouterTool2(tool) {
|
|
19519
|
+
if (isWrappedTool2(tool) || !tool.function || typeof tool.function !== "object" || typeof tool.function.execute !== "function") {
|
|
19520
|
+
return tool;
|
|
19521
|
+
}
|
|
19522
|
+
const toolName = tool.function.name || "tool";
|
|
19523
|
+
const originalExecute = tool.function.execute;
|
|
19524
|
+
const wrappedTool = {
|
|
19525
|
+
...tool,
|
|
19526
|
+
function: {
|
|
19527
|
+
...tool.function,
|
|
19528
|
+
execute(...args) {
|
|
19529
|
+
return traceToolExecution2({
|
|
19530
|
+
args,
|
|
19531
|
+
execute: () => Reflect.apply(originalExecute, this, args),
|
|
19532
|
+
toolCallId: getToolCallId2(args[1]),
|
|
19533
|
+
toolName
|
|
19534
|
+
});
|
|
19535
|
+
}
|
|
19536
|
+
}
|
|
19537
|
+
};
|
|
19538
|
+
Object.defineProperty(wrappedTool, OPENROUTER_WRAPPED_TOOL2, {
|
|
19539
|
+
value: true,
|
|
19540
|
+
enumerable: false,
|
|
19541
|
+
configurable: false
|
|
19542
|
+
});
|
|
19543
|
+
return wrappedTool;
|
|
19544
|
+
}
|
|
19545
|
+
function isWrappedTool2(tool) {
|
|
19546
|
+
return Boolean(tool[OPENROUTER_WRAPPED_TOOL2]);
|
|
19547
|
+
}
|
|
19548
|
+
function traceToolExecution2(args) {
|
|
19549
|
+
const tracingChannel2 = openRouterChannels.toolExecute.tracingChannel();
|
|
19550
|
+
const input = args.args.length > 0 ? args.args[0] : void 0;
|
|
19551
|
+
const event = {
|
|
19552
|
+
arguments: [input],
|
|
19553
|
+
span_info: {
|
|
19554
|
+
name: args.toolName
|
|
19555
|
+
},
|
|
19556
|
+
toolCallId: args.toolCallId,
|
|
19557
|
+
toolName: args.toolName
|
|
19558
|
+
};
|
|
19559
|
+
tracingChannel2.start.publish(event);
|
|
19560
|
+
try {
|
|
19561
|
+
const result = args.execute();
|
|
19562
|
+
return publishToolResult2(tracingChannel2, event, result);
|
|
19563
|
+
} catch (error2) {
|
|
19564
|
+
event.error = normalizeError2(error2);
|
|
19565
|
+
tracingChannel2.error.publish(event);
|
|
19566
|
+
throw error2;
|
|
19567
|
+
}
|
|
19568
|
+
}
|
|
19569
|
+
function publishToolResult2(tracingChannel2, event, result) {
|
|
19570
|
+
if (isPromiseLike4(result)) {
|
|
19571
|
+
return result.then(
|
|
19572
|
+
(resolved) => {
|
|
19573
|
+
event.result = resolved;
|
|
19574
|
+
tracingChannel2.asyncEnd.publish(event);
|
|
19575
|
+
return resolved;
|
|
19576
|
+
},
|
|
19577
|
+
(error2) => {
|
|
19578
|
+
event.error = normalizeError2(error2);
|
|
19579
|
+
tracingChannel2.error.publish(event);
|
|
19580
|
+
throw error2;
|
|
19581
|
+
}
|
|
19582
|
+
);
|
|
19583
|
+
}
|
|
19584
|
+
event.result = result;
|
|
19585
|
+
tracingChannel2.asyncEnd.publish(event);
|
|
19586
|
+
return result;
|
|
19587
|
+
}
|
|
19588
|
+
function getToolCallId2(context2) {
|
|
19589
|
+
const toolContext = context2;
|
|
19590
|
+
return typeof toolContext?.toolCall?.id === "string" ? toolContext.toolCall.id : void 0;
|
|
19591
|
+
}
|
|
19592
|
+
function isPromiseLike4(value) {
|
|
19593
|
+
return !!value && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function";
|
|
19594
|
+
}
|
|
19595
|
+
function aggregateOpenRouterChatChunks(chunks) {
|
|
19596
|
+
let role;
|
|
19597
|
+
let content = "";
|
|
19598
|
+
let toolCalls;
|
|
19599
|
+
let finishReason;
|
|
19600
|
+
let metrics = {};
|
|
19601
|
+
for (const chunk of chunks) {
|
|
19602
|
+
metrics = {
|
|
19603
|
+
...metrics,
|
|
19604
|
+
...parseOpenRouterMetricsFromUsage2(chunk?.usage)
|
|
19605
|
+
};
|
|
19606
|
+
const choice = chunk?.choices?.[0];
|
|
19607
|
+
const delta = choice?.delta;
|
|
19608
|
+
if (!delta) {
|
|
19609
|
+
if (choice?.finish_reason !== void 0) {
|
|
19610
|
+
finishReason = choice.finish_reason;
|
|
19611
|
+
}
|
|
19612
|
+
continue;
|
|
19613
|
+
}
|
|
19614
|
+
if (!role && delta.role) {
|
|
19615
|
+
role = delta.role;
|
|
19616
|
+
}
|
|
19617
|
+
if (typeof delta.content === "string") {
|
|
19618
|
+
content += delta.content;
|
|
19619
|
+
}
|
|
19620
|
+
const choiceFinishReason = choice?.finishReason ?? choice?.finish_reason ?? void 0;
|
|
19621
|
+
const deltaFinishReason = delta.finishReason ?? delta.finish_reason ?? void 0;
|
|
19622
|
+
if (choiceFinishReason !== void 0) {
|
|
19623
|
+
finishReason = choiceFinishReason;
|
|
19624
|
+
} else if (deltaFinishReason !== void 0) {
|
|
19625
|
+
finishReason = deltaFinishReason;
|
|
19626
|
+
}
|
|
19627
|
+
const toolCallDeltas = Array.isArray(delta.toolCalls) ? delta.toolCalls : Array.isArray(delta.tool_calls) ? delta.tool_calls : void 0;
|
|
19628
|
+
if (!toolCallDeltas) {
|
|
19629
|
+
continue;
|
|
19630
|
+
}
|
|
19631
|
+
for (const toolDelta of toolCallDeltas) {
|
|
19632
|
+
if (!toolDelta?.function) {
|
|
19633
|
+
continue;
|
|
19634
|
+
}
|
|
19635
|
+
const toolIndex = toolDelta.index ?? 0;
|
|
19636
|
+
const existingToolCall = toolCalls?.[toolIndex];
|
|
19637
|
+
if (!existingToolCall || toolDelta.id && existingToolCall.id !== void 0 && existingToolCall.id !== toolDelta.id) {
|
|
19638
|
+
const nextToolCalls = [...toolCalls || []];
|
|
19639
|
+
nextToolCalls[toolIndex] = {
|
|
19640
|
+
index: toolIndex,
|
|
19641
|
+
id: toolDelta.id,
|
|
19642
|
+
type: toolDelta.type,
|
|
19643
|
+
function: {
|
|
19644
|
+
name: toolDelta.function.name,
|
|
19645
|
+
arguments: toolDelta.function.arguments || ""
|
|
19646
|
+
}
|
|
19647
|
+
};
|
|
19648
|
+
toolCalls = nextToolCalls;
|
|
19649
|
+
continue;
|
|
19650
|
+
}
|
|
19651
|
+
const current = existingToolCall;
|
|
19652
|
+
if (toolDelta.id && !current.id) {
|
|
19653
|
+
current.id = toolDelta.id;
|
|
19654
|
+
}
|
|
19655
|
+
if (toolDelta.type && !current.type) {
|
|
19656
|
+
current.type = toolDelta.type;
|
|
19657
|
+
}
|
|
19658
|
+
if (toolDelta.function.name && !current.function.name) {
|
|
19659
|
+
current.function.name = toolDelta.function.name;
|
|
19660
|
+
}
|
|
19661
|
+
current.function.arguments += toolDelta.function.arguments || "";
|
|
19662
|
+
}
|
|
19663
|
+
}
|
|
19664
|
+
return {
|
|
19665
|
+
output: [
|
|
19666
|
+
{
|
|
19667
|
+
index: 0,
|
|
19668
|
+
message: {
|
|
19669
|
+
role,
|
|
19670
|
+
content: content || void 0,
|
|
19671
|
+
...toolCalls ? { tool_calls: toolCalls } : {}
|
|
19672
|
+
},
|
|
19673
|
+
logprobs: null,
|
|
19674
|
+
finish_reason: finishReason
|
|
19675
|
+
}
|
|
19676
|
+
],
|
|
19677
|
+
metrics
|
|
19678
|
+
};
|
|
19679
|
+
}
|
|
19680
|
+
function aggregateOpenRouterResponseStreamEvents(chunks) {
|
|
19681
|
+
let finalResponse;
|
|
19682
|
+
for (const chunk of chunks) {
|
|
19683
|
+
const response = chunk?.response;
|
|
19684
|
+
if (!response) {
|
|
19685
|
+
continue;
|
|
19686
|
+
}
|
|
19687
|
+
if (chunk.type === "response.completed" || chunk.type === "response.incomplete" || chunk.type === "response.failed") {
|
|
19688
|
+
finalResponse = response;
|
|
19689
|
+
}
|
|
19690
|
+
}
|
|
19691
|
+
if (!finalResponse) {
|
|
19692
|
+
return {
|
|
19693
|
+
output: void 0,
|
|
19694
|
+
metrics: {}
|
|
19695
|
+
};
|
|
19696
|
+
}
|
|
19697
|
+
return {
|
|
19698
|
+
output: extractOpenRouterResponseOutput2(finalResponse),
|
|
19699
|
+
metrics: parseOpenRouterMetricsFromUsage2(finalResponse.usage),
|
|
19700
|
+
...extractOpenRouterResponseMetadata2(finalResponse) ? { metadata: extractOpenRouterResponseMetadata2(finalResponse) } : {}
|
|
19701
|
+
};
|
|
19702
|
+
}
|
|
19703
|
+
var OPENROUTER_WRAPPED_CALL_MODEL_RESULT2 = Symbol(
|
|
19704
|
+
"braintrust.openrouter.wrappedCallModelResult"
|
|
19705
|
+
);
|
|
19706
|
+
var OPENROUTER_CALL_MODEL_STREAM_METHODS2 = [
|
|
19707
|
+
"getFullResponsesStream",
|
|
19708
|
+
"getItemsStream",
|
|
19709
|
+
"getNewMessagesStream",
|
|
19710
|
+
"getReasoningStream",
|
|
19711
|
+
"getTextStream",
|
|
19712
|
+
"getToolCallsStream",
|
|
19713
|
+
"getToolStream"
|
|
19714
|
+
];
|
|
19715
|
+
var OPENROUTER_CALL_MODEL_CONTEXT_METHODS2 = [
|
|
19716
|
+
"cancel",
|
|
19717
|
+
"getPendingToolCalls",
|
|
19718
|
+
"getState",
|
|
19719
|
+
"getToolCalls",
|
|
19720
|
+
"requiresApproval"
|
|
19721
|
+
];
|
|
19722
|
+
function patchOpenRouterCallModelResult2(args) {
|
|
19723
|
+
const { request, result, span } = args;
|
|
19724
|
+
if (!isObject(result) || isWrappedCallModelResult2(result)) {
|
|
19725
|
+
return false;
|
|
19726
|
+
}
|
|
19727
|
+
const resultLike = result;
|
|
19728
|
+
const hasInstrumentableMethod = typeof resultLike.getResponse === "function" || typeof resultLike.getText === "function" || OPENROUTER_CALL_MODEL_STREAM_METHODS2.some(
|
|
19729
|
+
(methodName) => typeof resultLike[methodName] === "function"
|
|
19730
|
+
);
|
|
19731
|
+
if (!hasInstrumentableMethod) {
|
|
19732
|
+
return false;
|
|
19733
|
+
}
|
|
19734
|
+
Object.defineProperty(resultLike, OPENROUTER_WRAPPED_CALL_MODEL_RESULT2, {
|
|
19735
|
+
value: true,
|
|
19736
|
+
enumerable: false,
|
|
19737
|
+
configurable: false
|
|
19738
|
+
});
|
|
19739
|
+
const originalGetResponse = typeof resultLike.getResponse === "function" ? resultLike.getResponse.bind(resultLike) : void 0;
|
|
19740
|
+
const originalGetInitialResponse = typeof resultLike.getInitialResponse === "function" ? resultLike.getInitialResponse.bind(resultLike) : void 0;
|
|
19741
|
+
const originalMakeFollowupRequest = typeof resultLike.makeFollowupRequest === "function" ? resultLike.makeFollowupRequest.bind(resultLike) : void 0;
|
|
19742
|
+
let ended = false;
|
|
19743
|
+
let tracedTurnCount = 0;
|
|
19744
|
+
const endSpanWithResult = async (response, fallbackOutput) => {
|
|
19745
|
+
if (ended) {
|
|
19746
|
+
return;
|
|
19747
|
+
}
|
|
19748
|
+
ended = true;
|
|
19749
|
+
const finalResponse = getFinalOpenRouterCallModelResponse2(
|
|
19750
|
+
resultLike,
|
|
19751
|
+
response
|
|
19752
|
+
);
|
|
19753
|
+
if (finalResponse) {
|
|
19754
|
+
const rounds = getOpenRouterCallModelRounds2(resultLike);
|
|
19755
|
+
const metadata = extractOpenRouterCallModelResultMetadata2(
|
|
19756
|
+
finalResponse,
|
|
19757
|
+
rounds.length + 1
|
|
19758
|
+
);
|
|
19759
|
+
span.log({
|
|
19760
|
+
output: extractOpenRouterResponseOutput2(finalResponse, fallbackOutput),
|
|
19761
|
+
...metadata ? { metadata } : {},
|
|
19762
|
+
metrics: aggregateOpenRouterCallModelMetrics2(rounds, finalResponse)
|
|
19763
|
+
});
|
|
19764
|
+
span.end();
|
|
19765
|
+
return;
|
|
19766
|
+
}
|
|
19767
|
+
if (fallbackOutput !== void 0) {
|
|
19768
|
+
span.log({
|
|
19769
|
+
output: fallbackOutput
|
|
19770
|
+
});
|
|
19771
|
+
}
|
|
19772
|
+
span.end();
|
|
19773
|
+
};
|
|
19774
|
+
const endSpanWithError = (error2) => {
|
|
19775
|
+
if (ended) {
|
|
19776
|
+
return;
|
|
19777
|
+
}
|
|
19778
|
+
ended = true;
|
|
19779
|
+
span.log({
|
|
19780
|
+
error: normalizeError2(error2).message
|
|
19781
|
+
});
|
|
19782
|
+
span.end();
|
|
19783
|
+
};
|
|
19784
|
+
const finalizeFromResponse = async (fallbackOutput) => {
|
|
19785
|
+
if (!originalGetResponse) {
|
|
19786
|
+
await endSpanWithResult(void 0, fallbackOutput);
|
|
19787
|
+
return;
|
|
19788
|
+
}
|
|
19789
|
+
try {
|
|
19790
|
+
await endSpanWithResult(await originalGetResponse(), fallbackOutput);
|
|
19791
|
+
} catch {
|
|
19792
|
+
await endSpanWithResult(void 0, fallbackOutput);
|
|
19793
|
+
}
|
|
19794
|
+
};
|
|
19795
|
+
if (originalGetResponse) {
|
|
19796
|
+
resultLike.getResponse = async (...args2) => {
|
|
19797
|
+
return await withCurrent(span, async () => {
|
|
19798
|
+
try {
|
|
19799
|
+
const response = await originalGetResponse(...args2);
|
|
19800
|
+
await endSpanWithResult(response);
|
|
19801
|
+
return response;
|
|
19802
|
+
} catch (error2) {
|
|
19803
|
+
endSpanWithError(error2);
|
|
19804
|
+
throw error2;
|
|
19805
|
+
}
|
|
19806
|
+
});
|
|
19807
|
+
};
|
|
19808
|
+
}
|
|
19809
|
+
if (typeof resultLike.getText === "function") {
|
|
19810
|
+
const originalGetText = resultLike.getText.bind(resultLike);
|
|
19811
|
+
resultLike.getText = async (...args2) => {
|
|
19812
|
+
return await withCurrent(span, async () => {
|
|
19813
|
+
try {
|
|
19814
|
+
const text = await originalGetText(...args2);
|
|
19815
|
+
await finalizeFromResponse(text);
|
|
19816
|
+
return text;
|
|
19817
|
+
} catch (error2) {
|
|
19818
|
+
endSpanWithError(error2);
|
|
19819
|
+
throw error2;
|
|
19820
|
+
}
|
|
19821
|
+
});
|
|
19822
|
+
};
|
|
19823
|
+
}
|
|
19824
|
+
for (const methodName of OPENROUTER_CALL_MODEL_CONTEXT_METHODS2) {
|
|
19825
|
+
if (typeof resultLike[methodName] !== "function") {
|
|
19826
|
+
continue;
|
|
19827
|
+
}
|
|
19828
|
+
const originalMethod = resultLike[methodName];
|
|
19829
|
+
resultLike[methodName] = async (...args2) => {
|
|
19830
|
+
return await withCurrent(span, async () => {
|
|
19831
|
+
return await originalMethod.apply(resultLike, args2);
|
|
19832
|
+
});
|
|
19833
|
+
};
|
|
19834
|
+
}
|
|
19835
|
+
for (const methodName of OPENROUTER_CALL_MODEL_STREAM_METHODS2) {
|
|
19836
|
+
if (typeof resultLike[methodName] !== "function") {
|
|
19837
|
+
continue;
|
|
19838
|
+
}
|
|
19839
|
+
const originalMethod = resultLike[methodName];
|
|
19840
|
+
resultLike[methodName] = (...args2) => {
|
|
19841
|
+
const stream = withCurrent(
|
|
19842
|
+
span,
|
|
19843
|
+
() => originalMethod.apply(resultLike, args2)
|
|
19844
|
+
);
|
|
19845
|
+
if (!isAsyncIterable6(stream)) {
|
|
19846
|
+
return stream;
|
|
19847
|
+
}
|
|
19848
|
+
return wrapAsyncIterableWithSpan2({
|
|
19849
|
+
finalize: finalizeFromResponse,
|
|
19850
|
+
iteratorFactory: () => stream[Symbol.asyncIterator](),
|
|
19851
|
+
onError: endSpanWithError,
|
|
19852
|
+
span
|
|
19853
|
+
});
|
|
19854
|
+
};
|
|
19855
|
+
}
|
|
19856
|
+
if (originalGetInitialResponse) {
|
|
19857
|
+
let initialTurnTraced = false;
|
|
19858
|
+
resultLike.getInitialResponse = async (...args2) => {
|
|
19859
|
+
if (initialTurnTraced) {
|
|
19860
|
+
return await withCurrent(span, async () => {
|
|
19861
|
+
return await originalGetInitialResponse(...args2);
|
|
19862
|
+
});
|
|
19863
|
+
}
|
|
19864
|
+
initialTurnTraced = true;
|
|
19865
|
+
const step = tracedTurnCount + 1;
|
|
19866
|
+
const stepType = tracedTurnCount === 0 ? "initial" : "continue";
|
|
19867
|
+
const response = await traceOpenRouterCallModelTurn2({
|
|
19868
|
+
fn: async () => {
|
|
19869
|
+
const nextResponse = await originalGetInitialResponse(...args2);
|
|
19870
|
+
tracedTurnCount++;
|
|
19871
|
+
return nextResponse;
|
|
19872
|
+
},
|
|
19873
|
+
parentSpan: span,
|
|
19874
|
+
request: getOpenRouterResolvedRequest2(resultLike, request),
|
|
19875
|
+
step,
|
|
19876
|
+
stepType
|
|
19877
|
+
});
|
|
19878
|
+
return response;
|
|
19879
|
+
};
|
|
19880
|
+
}
|
|
19881
|
+
if (originalMakeFollowupRequest) {
|
|
19882
|
+
resultLike.makeFollowupRequest = async (...args2) => {
|
|
19883
|
+
const currentResponse = args2[0];
|
|
19884
|
+
const toolResults = Array.isArray(args2[1]) ? args2[1] : [];
|
|
19885
|
+
const step = tracedTurnCount + 1;
|
|
19886
|
+
const response = await traceOpenRouterCallModelTurn2({
|
|
19887
|
+
fn: async () => {
|
|
19888
|
+
const nextResponse = await originalMakeFollowupRequest(...args2);
|
|
19889
|
+
tracedTurnCount++;
|
|
19890
|
+
return nextResponse;
|
|
19891
|
+
},
|
|
19892
|
+
parentSpan: span,
|
|
19893
|
+
request: buildOpenRouterFollowupRequest2(
|
|
19894
|
+
getOpenRouterResolvedRequest2(resultLike, request),
|
|
19895
|
+
currentResponse,
|
|
19896
|
+
toolResults
|
|
19897
|
+
),
|
|
19898
|
+
step,
|
|
19899
|
+
stepType: "continue"
|
|
19900
|
+
});
|
|
19901
|
+
return response;
|
|
19902
|
+
};
|
|
19903
|
+
}
|
|
19904
|
+
return true;
|
|
19905
|
+
}
|
|
19906
|
+
async function traceOpenRouterCallModelTurn2(args) {
|
|
19907
|
+
const context2 = {
|
|
19908
|
+
arguments: [args.request],
|
|
19909
|
+
step: args.step,
|
|
19910
|
+
stepType: args.stepType
|
|
19911
|
+
};
|
|
19912
|
+
return await withCurrent(
|
|
19913
|
+
args.parentSpan,
|
|
19914
|
+
() => openRouterChannels.callModelTurn.tracePromise(args.fn, context2)
|
|
19915
|
+
);
|
|
19916
|
+
}
|
|
19917
|
+
function isWrappedCallModelResult2(value) {
|
|
19918
|
+
return Boolean(
|
|
19919
|
+
isObject(value) && value[OPENROUTER_WRAPPED_CALL_MODEL_RESULT2]
|
|
19920
|
+
);
|
|
19921
|
+
}
|
|
19922
|
+
function extractOpenRouterCallModelResultMetadata2(response, turnCount) {
|
|
19923
|
+
const combined = {
|
|
19924
|
+
...extractOpenRouterResponseMetadata2(response) || {},
|
|
19925
|
+
...turnCount !== void 0 ? { turn_count: turnCount } : {}
|
|
19926
|
+
};
|
|
19927
|
+
return Object.keys(combined).length > 0 ? combined : void 0;
|
|
19928
|
+
}
|
|
19929
|
+
function getFinalOpenRouterCallModelResponse2(result, response) {
|
|
19930
|
+
if (isObject(response)) {
|
|
19931
|
+
return response;
|
|
19932
|
+
}
|
|
19933
|
+
return isObject(result.finalResponse) ? result.finalResponse : void 0;
|
|
19934
|
+
}
|
|
19935
|
+
function getOpenRouterCallModelRounds2(result) {
|
|
19936
|
+
if (!Array.isArray(result.allToolExecutionRounds)) {
|
|
19937
|
+
return [];
|
|
19938
|
+
}
|
|
19939
|
+
return result.allToolExecutionRounds.filter((round) => isObject(round)).map((round) => ({
|
|
19940
|
+
response: isObject(round.response) ? round.response : void 0,
|
|
19941
|
+
round: typeof round.round === "number" ? round.round : void 0,
|
|
19942
|
+
toolResults: Array.isArray(round.toolResults) ? round.toolResults : []
|
|
19943
|
+
})).filter((round) => round.response !== void 0);
|
|
19944
|
+
}
|
|
19945
|
+
function aggregateOpenRouterCallModelMetrics2(rounds, finalResponse) {
|
|
19946
|
+
const metrics = {};
|
|
19947
|
+
const responses = [
|
|
19948
|
+
...rounds.map((round) => round.response).filter(isObject),
|
|
19949
|
+
finalResponse
|
|
19950
|
+
];
|
|
19951
|
+
for (const response of responses) {
|
|
19952
|
+
const responseMetrics = parseOpenRouterMetricsFromUsage2(response.usage);
|
|
19953
|
+
for (const [name, value] of Object.entries(responseMetrics)) {
|
|
19954
|
+
metrics[name] = (metrics[name] || 0) + value;
|
|
19955
|
+
}
|
|
19956
|
+
}
|
|
19957
|
+
return metrics;
|
|
19958
|
+
}
|
|
19959
|
+
function buildNextOpenRouterCallModelInput2(currentInput, response, toolResults) {
|
|
19960
|
+
const normalizedInput = Array.isArray(currentInput) ? [...currentInput] : currentInput === void 0 ? [] : [currentInput];
|
|
19961
|
+
const responseOutput = Array.isArray(response.output) ? response.output : response.output === void 0 ? [] : [response.output];
|
|
19962
|
+
return [...normalizedInput, ...responseOutput, ...toolResults].map(
|
|
19963
|
+
(entry) => sanitizeOpenRouterLoggedValue2(entry)
|
|
19964
|
+
);
|
|
19965
|
+
}
|
|
19966
|
+
function getOpenRouterResolvedRequest2(result, request) {
|
|
19967
|
+
if (isObject(result.resolvedRequest)) {
|
|
19968
|
+
return result.resolvedRequest;
|
|
19969
|
+
}
|
|
19970
|
+
return request;
|
|
19971
|
+
}
|
|
19972
|
+
function buildOpenRouterFollowupRequest2(request, currentResponse, toolResults) {
|
|
19973
|
+
if (!request) {
|
|
19974
|
+
return void 0;
|
|
19975
|
+
}
|
|
19976
|
+
return {
|
|
19977
|
+
...request,
|
|
19978
|
+
input: buildNextOpenRouterCallModelInput2(
|
|
19979
|
+
extractOpenRouterCallModelInput2(request),
|
|
19980
|
+
isObject(currentResponse) ? currentResponse : {},
|
|
19981
|
+
toolResults
|
|
19982
|
+
),
|
|
19983
|
+
stream: false
|
|
19984
|
+
};
|
|
19985
|
+
}
|
|
19986
|
+
function wrapAsyncIterableWithSpan2(args) {
|
|
19987
|
+
return {
|
|
19988
|
+
[Symbol.asyncIterator]() {
|
|
19989
|
+
const iterator = args.iteratorFactory();
|
|
19990
|
+
return {
|
|
19991
|
+
next(value) {
|
|
19992
|
+
return withCurrent(
|
|
19993
|
+
args.span,
|
|
19994
|
+
() => value === void 0 ? iterator.next() : iterator.next(value)
|
|
19995
|
+
).then(
|
|
19996
|
+
async (result) => {
|
|
19997
|
+
if (result.done) {
|
|
19998
|
+
await args.finalize();
|
|
19999
|
+
}
|
|
20000
|
+
return result;
|
|
20001
|
+
},
|
|
20002
|
+
(error2) => {
|
|
20003
|
+
args.onError(error2);
|
|
20004
|
+
throw error2;
|
|
20005
|
+
}
|
|
20006
|
+
);
|
|
20007
|
+
},
|
|
20008
|
+
return(value) {
|
|
20009
|
+
if (typeof iterator.return !== "function") {
|
|
20010
|
+
return args.finalize().then(() => ({
|
|
20011
|
+
done: true,
|
|
20012
|
+
value
|
|
20013
|
+
}));
|
|
20014
|
+
}
|
|
20015
|
+
return withCurrent(args.span, () => iterator.return(value)).then(
|
|
20016
|
+
async (result) => {
|
|
20017
|
+
await args.finalize();
|
|
20018
|
+
return result;
|
|
20019
|
+
},
|
|
20020
|
+
(error2) => {
|
|
20021
|
+
args.onError(error2);
|
|
20022
|
+
throw error2;
|
|
20023
|
+
}
|
|
20024
|
+
);
|
|
20025
|
+
},
|
|
20026
|
+
throw(error2) {
|
|
20027
|
+
args.onError(error2);
|
|
20028
|
+
if (typeof iterator.throw !== "function") {
|
|
20029
|
+
return Promise.reject(error2);
|
|
20030
|
+
}
|
|
20031
|
+
return withCurrent(args.span, () => iterator.throw(error2));
|
|
20032
|
+
},
|
|
20033
|
+
[Symbol.asyncIterator]() {
|
|
20034
|
+
return this;
|
|
20035
|
+
}
|
|
20036
|
+
};
|
|
20037
|
+
}
|
|
20038
|
+
};
|
|
20039
|
+
}
|
|
20040
|
+
function isAsyncIterable6(value) {
|
|
20041
|
+
return !!value && (typeof value === "object" || typeof value === "function") && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
|
|
20042
|
+
}
|
|
20043
|
+
function normalizeError2(error2) {
|
|
20044
|
+
return error2 instanceof Error ? error2 : new Error(String(error2));
|
|
20045
|
+
}
|
|
20046
|
+
|
|
20047
|
+
// src/instrumentation/plugins/mistral-channels.ts
|
|
20048
|
+
var mistralChannels = defineChannels("@mistralai/mistralai", {
|
|
20049
|
+
chatComplete: channel({
|
|
20050
|
+
channelName: "chat.complete",
|
|
20051
|
+
kind: "async"
|
|
20052
|
+
}),
|
|
20053
|
+
chatStream: channel({
|
|
20054
|
+
channelName: "chat.stream",
|
|
20055
|
+
kind: "async"
|
|
20056
|
+
}),
|
|
20057
|
+
embeddingsCreate: channel({
|
|
20058
|
+
channelName: "embeddings.create",
|
|
20059
|
+
kind: "async"
|
|
20060
|
+
}),
|
|
20061
|
+
fimComplete: channel({
|
|
20062
|
+
channelName: "fim.complete",
|
|
20063
|
+
kind: "async"
|
|
20064
|
+
}),
|
|
20065
|
+
fimStream: channel({
|
|
20066
|
+
channelName: "fim.stream",
|
|
20067
|
+
kind: "async"
|
|
20068
|
+
}),
|
|
20069
|
+
agentsComplete: channel({
|
|
20070
|
+
channelName: "agents.complete",
|
|
20071
|
+
kind: "async"
|
|
20072
|
+
}),
|
|
20073
|
+
agentsStream: channel({
|
|
20074
|
+
channelName: "agents.stream",
|
|
20075
|
+
kind: "async"
|
|
20076
|
+
})
|
|
20077
|
+
});
|
|
20078
|
+
|
|
20079
|
+
// src/instrumentation/plugins/mistral-plugin.ts
|
|
20080
|
+
var MistralPlugin = class extends BasePlugin {
|
|
20081
|
+
onEnable() {
|
|
20082
|
+
this.subscribeToMistralChannels();
|
|
20083
|
+
}
|
|
20084
|
+
onDisable() {
|
|
20085
|
+
this.unsubscribers = unsubscribeAll(this.unsubscribers);
|
|
20086
|
+
}
|
|
20087
|
+
subscribeToMistralChannels() {
|
|
20088
|
+
this.unsubscribers.push(
|
|
20089
|
+
traceStreamingChannel(mistralChannels.chatComplete, {
|
|
20090
|
+
name: "mistral.chat.complete",
|
|
20091
|
+
type: "llm" /* LLM */,
|
|
20092
|
+
extractInput: extractMessagesInputWithMetadata,
|
|
20093
|
+
extractOutput: (result) => {
|
|
20094
|
+
return result?.choices;
|
|
20095
|
+
},
|
|
20096
|
+
extractMetadata: (result) => extractMistralResponseMetadata(result),
|
|
20097
|
+
extractMetrics: (result, startTime) => extractMistralMetrics(result?.usage, startTime)
|
|
20098
|
+
})
|
|
20099
|
+
);
|
|
20100
|
+
this.unsubscribers.push(
|
|
20101
|
+
traceStreamingChannel(mistralChannels.chatStream, {
|
|
20102
|
+
name: "mistral.chat.stream",
|
|
20103
|
+
type: "llm" /* LLM */,
|
|
20104
|
+
extractInput: extractMessagesInputWithMetadata,
|
|
20105
|
+
extractOutput: extractMistralStreamOutput,
|
|
20106
|
+
extractMetadata: (result) => extractMistralResponseMetadata(result),
|
|
20107
|
+
extractMetrics: (result, startTime) => extractMistralStreamingMetrics(result, startTime),
|
|
20108
|
+
aggregateChunks: aggregateMistralStreamChunks
|
|
20109
|
+
})
|
|
20110
|
+
);
|
|
20111
|
+
this.unsubscribers.push(
|
|
20112
|
+
traceAsyncChannel(mistralChannels.embeddingsCreate, {
|
|
20113
|
+
name: "mistral.embeddings.create",
|
|
20114
|
+
type: "llm" /* LLM */,
|
|
20115
|
+
extractInput: extractEmbeddingInputWithMetadata,
|
|
20116
|
+
extractOutput: (result) => {
|
|
20117
|
+
const embedding = result?.data?.[0]?.embedding;
|
|
20118
|
+
return Array.isArray(embedding) ? { embedding_length: embedding.length } : void 0;
|
|
20119
|
+
},
|
|
20120
|
+
extractMetadata: (result) => extractMistralResponseMetadata(result),
|
|
20121
|
+
extractMetrics: (result) => parseMistralMetricsFromUsage(result?.usage)
|
|
20122
|
+
})
|
|
20123
|
+
);
|
|
20124
|
+
this.unsubscribers.push(
|
|
20125
|
+
traceStreamingChannel(mistralChannels.fimComplete, {
|
|
20126
|
+
name: "mistral.fim.complete",
|
|
20127
|
+
type: "llm" /* LLM */,
|
|
20128
|
+
extractInput: extractPromptInputWithMetadata,
|
|
20129
|
+
extractOutput: (result) => {
|
|
20130
|
+
return result?.choices;
|
|
20131
|
+
},
|
|
20132
|
+
extractMetadata: (result) => extractMistralResponseMetadata(result),
|
|
20133
|
+
extractMetrics: (result, startTime) => extractMistralMetrics(result?.usage, startTime)
|
|
20134
|
+
})
|
|
20135
|
+
);
|
|
20136
|
+
this.unsubscribers.push(
|
|
20137
|
+
traceStreamingChannel(mistralChannels.fimStream, {
|
|
20138
|
+
name: "mistral.fim.stream",
|
|
20139
|
+
type: "llm" /* LLM */,
|
|
20140
|
+
extractInput: extractPromptInputWithMetadata,
|
|
20141
|
+
extractOutput: extractMistralStreamOutput,
|
|
20142
|
+
extractMetadata: (result) => extractMistralResponseMetadata(result),
|
|
20143
|
+
extractMetrics: (result, startTime) => extractMistralStreamingMetrics(result, startTime),
|
|
20144
|
+
aggregateChunks: aggregateMistralStreamChunks
|
|
20145
|
+
})
|
|
20146
|
+
);
|
|
20147
|
+
this.unsubscribers.push(
|
|
20148
|
+
traceStreamingChannel(mistralChannels.agentsComplete, {
|
|
20149
|
+
name: "mistral.agents.complete",
|
|
20150
|
+
type: "llm" /* LLM */,
|
|
20151
|
+
extractInput: extractMessagesInputWithMetadata,
|
|
20152
|
+
extractOutput: (result) => {
|
|
20153
|
+
return result?.choices;
|
|
20154
|
+
},
|
|
20155
|
+
extractMetadata: (result) => extractMistralResponseMetadata(result),
|
|
20156
|
+
extractMetrics: (result, startTime) => extractMistralMetrics(result?.usage, startTime)
|
|
20157
|
+
})
|
|
20158
|
+
);
|
|
20159
|
+
this.unsubscribers.push(
|
|
20160
|
+
traceStreamingChannel(mistralChannels.agentsStream, {
|
|
20161
|
+
name: "mistral.agents.stream",
|
|
20162
|
+
type: "llm" /* LLM */,
|
|
20163
|
+
extractInput: extractMessagesInputWithMetadata,
|
|
20164
|
+
extractOutput: extractMistralStreamOutput,
|
|
20165
|
+
extractMetadata: (result) => extractMistralResponseMetadata(result),
|
|
20166
|
+
extractMetrics: (result, startTime) => extractMistralStreamingMetrics(result, startTime),
|
|
20167
|
+
aggregateChunks: aggregateMistralStreamChunks
|
|
20168
|
+
})
|
|
20169
|
+
);
|
|
17912
20170
|
}
|
|
17913
20171
|
};
|
|
17914
|
-
|
|
20172
|
+
var TOKEN_NAME_MAP4 = {
|
|
20173
|
+
promptTokens: "prompt_tokens",
|
|
20174
|
+
inputTokens: "prompt_tokens",
|
|
20175
|
+
completionTokens: "completion_tokens",
|
|
20176
|
+
outputTokens: "completion_tokens",
|
|
20177
|
+
totalTokens: "tokens",
|
|
20178
|
+
prompt_tokens: "prompt_tokens",
|
|
20179
|
+
input_tokens: "prompt_tokens",
|
|
20180
|
+
completion_tokens: "completion_tokens",
|
|
20181
|
+
output_tokens: "completion_tokens",
|
|
20182
|
+
total_tokens: "tokens",
|
|
20183
|
+
promptAudioSeconds: "prompt_audio_seconds",
|
|
20184
|
+
prompt_audio_seconds: "prompt_audio_seconds"
|
|
20185
|
+
};
|
|
20186
|
+
var TOKEN_DETAIL_PREFIX_MAP3 = {
|
|
20187
|
+
promptTokensDetails: "prompt",
|
|
20188
|
+
inputTokensDetails: "prompt",
|
|
20189
|
+
completionTokensDetails: "completion",
|
|
20190
|
+
outputTokensDetails: "completion",
|
|
20191
|
+
prompt_tokens_details: "prompt",
|
|
20192
|
+
input_tokens_details: "prompt",
|
|
20193
|
+
completion_tokens_details: "completion",
|
|
20194
|
+
output_tokens_details: "completion"
|
|
20195
|
+
};
|
|
20196
|
+
var MISTRAL_REQUEST_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
|
|
20197
|
+
"agentId",
|
|
20198
|
+
"agent_id",
|
|
20199
|
+
"encodingFormat",
|
|
20200
|
+
"encoding_format",
|
|
20201
|
+
"frequencyPenalty",
|
|
20202
|
+
"frequency_penalty",
|
|
20203
|
+
"maxTokens",
|
|
20204
|
+
"max_tokens",
|
|
20205
|
+
"model",
|
|
20206
|
+
"n",
|
|
20207
|
+
"presencePenalty",
|
|
20208
|
+
"presence_penalty",
|
|
20209
|
+
"randomSeed",
|
|
20210
|
+
"random_seed",
|
|
20211
|
+
"responseFormat",
|
|
20212
|
+
"response_format",
|
|
20213
|
+
"safePrompt",
|
|
20214
|
+
"safe_prompt",
|
|
20215
|
+
"stream",
|
|
20216
|
+
"stop",
|
|
20217
|
+
"temperature",
|
|
20218
|
+
"toolChoice",
|
|
20219
|
+
"tool_choice",
|
|
20220
|
+
"topP",
|
|
20221
|
+
"top_p"
|
|
20222
|
+
]);
|
|
20223
|
+
var MISTRAL_RESPONSE_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
|
|
20224
|
+
"agentId",
|
|
20225
|
+
"agent_id",
|
|
20226
|
+
"created",
|
|
20227
|
+
"id",
|
|
20228
|
+
"model",
|
|
20229
|
+
"object"
|
|
20230
|
+
]);
|
|
20231
|
+
function camelToSnake3(value) {
|
|
20232
|
+
return value.replace(/[A-Z]/g, (match) => `_${match.toLowerCase()}`);
|
|
20233
|
+
}
|
|
20234
|
+
function normalizeArgs3(args) {
|
|
17915
20235
|
if (Array.isArray(args)) {
|
|
17916
20236
|
return args;
|
|
17917
20237
|
}
|
|
17918
|
-
if (
|
|
20238
|
+
if (isArrayLike4(args)) {
|
|
17919
20239
|
return Array.from(args);
|
|
17920
20240
|
}
|
|
17921
20241
|
return [args];
|
|
17922
20242
|
}
|
|
17923
|
-
function
|
|
20243
|
+
function isArrayLike4(value) {
|
|
17924
20244
|
return isObject(value) && "length" in value && typeof value.length === "number" && Number.isInteger(value.length) && value.length >= 0;
|
|
17925
20245
|
}
|
|
17926
|
-
function
|
|
17927
|
-
const
|
|
17928
|
-
|
|
17929
|
-
|
|
20246
|
+
function getMistralRequestArg(args) {
|
|
20247
|
+
const firstObjectArg = normalizeArgs3(args).find((arg) => isObject(arg));
|
|
20248
|
+
return isObject(firstObjectArg) ? firstObjectArg : void 0;
|
|
20249
|
+
}
|
|
20250
|
+
function addMistralProviderMetadata(metadata) {
|
|
20251
|
+
return {
|
|
20252
|
+
...metadata,
|
|
20253
|
+
provider: "mistral"
|
|
20254
|
+
};
|
|
20255
|
+
}
|
|
20256
|
+
function pickAllowedMetadata(metadata, allowlist) {
|
|
20257
|
+
if (!metadata) {
|
|
20258
|
+
return {};
|
|
20259
|
+
}
|
|
20260
|
+
const picked = {};
|
|
20261
|
+
for (const key of allowlist) {
|
|
20262
|
+
const value = metadata[key];
|
|
20263
|
+
if (value !== void 0) {
|
|
20264
|
+
picked[key] = value;
|
|
20265
|
+
}
|
|
20266
|
+
}
|
|
20267
|
+
return picked;
|
|
20268
|
+
}
|
|
20269
|
+
function extractMistralRequestMetadata(metadata) {
|
|
20270
|
+
return pickAllowedMetadata(metadata, MISTRAL_REQUEST_METADATA_ALLOWLIST);
|
|
20271
|
+
}
|
|
20272
|
+
function isMistralChatCompletionChunk(value) {
|
|
20273
|
+
return isObject(value);
|
|
20274
|
+
}
|
|
20275
|
+
function isMistralChunkChoice(value) {
|
|
20276
|
+
return isObject(value);
|
|
20277
|
+
}
|
|
20278
|
+
function extractMessagesInputWithMetadata(args) {
|
|
20279
|
+
const params = getMistralRequestArg(args);
|
|
20280
|
+
const { messages, ...rawMetadata } = params || {};
|
|
20281
|
+
return {
|
|
20282
|
+
input: processInputAttachments(messages),
|
|
20283
|
+
metadata: addMistralProviderMetadata(
|
|
20284
|
+
extractMistralRequestMetadata(rawMetadata)
|
|
20285
|
+
)
|
|
20286
|
+
};
|
|
20287
|
+
}
|
|
20288
|
+
function extractEmbeddingInputWithMetadata(args) {
|
|
20289
|
+
const params = getMistralRequestArg(args);
|
|
20290
|
+
const { inputs, ...rawMetadata } = params || {};
|
|
20291
|
+
return {
|
|
20292
|
+
input: inputs,
|
|
20293
|
+
metadata: addMistralProviderMetadata(
|
|
20294
|
+
extractMistralRequestMetadata(rawMetadata)
|
|
20295
|
+
)
|
|
20296
|
+
};
|
|
20297
|
+
}
|
|
20298
|
+
function extractPromptInputWithMetadata(args) {
|
|
20299
|
+
const params = getMistralRequestArg(args);
|
|
20300
|
+
const { prompt, ...rawMetadata } = params || {};
|
|
20301
|
+
return {
|
|
20302
|
+
input: prompt,
|
|
20303
|
+
metadata: addMistralProviderMetadata(
|
|
20304
|
+
extractMistralRequestMetadata(rawMetadata)
|
|
20305
|
+
)
|
|
20306
|
+
};
|
|
20307
|
+
}
|
|
20308
|
+
function extractMistralResponseMetadata(result) {
|
|
20309
|
+
if (!isObject(result)) {
|
|
20310
|
+
return void 0;
|
|
20311
|
+
}
|
|
20312
|
+
const { choices: _choices, usage: _usage, data: _data, ...metadata } = result;
|
|
20313
|
+
const picked = pickAllowedMetadata(
|
|
20314
|
+
metadata,
|
|
20315
|
+
MISTRAL_RESPONSE_METADATA_ALLOWLIST
|
|
17930
20316
|
);
|
|
17931
|
-
|
|
17932
|
-
|
|
20317
|
+
return Object.keys(picked).length > 0 ? picked : void 0;
|
|
20318
|
+
}
|
|
20319
|
+
function extractMistralMetrics(usage, startTime) {
|
|
20320
|
+
const metrics = parseMistralMetricsFromUsage(usage);
|
|
20321
|
+
if (startTime) {
|
|
20322
|
+
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
17933
20323
|
}
|
|
17934
|
-
|
|
17935
|
-
return isObject(firstObjectArg) ? firstObjectArg : void 0;
|
|
20324
|
+
return metrics;
|
|
17936
20325
|
}
|
|
17937
|
-
function
|
|
17938
|
-
|
|
17939
|
-
return isObject(firstObjectArg) ? firstObjectArg : void 0;
|
|
20326
|
+
function extractMistralStreamOutput(result) {
|
|
20327
|
+
return isObject(result) ? result.choices : void 0;
|
|
17940
20328
|
}
|
|
17941
|
-
function
|
|
17942
|
-
|
|
17943
|
-
|
|
17944
|
-
|
|
17945
|
-
|
|
17946
|
-
|
|
17947
|
-
|
|
17948
|
-
|
|
17949
|
-
|
|
17950
|
-
|
|
17951
|
-
|
|
17952
|
-
|
|
17953
|
-
|
|
17954
|
-
|
|
17955
|
-
|
|
17956
|
-
|
|
20329
|
+
function extractMistralStreamingMetrics(result, startTime) {
|
|
20330
|
+
const metrics = isObject(result) ? parseMistralMetricsFromUsage(result.usage) : {};
|
|
20331
|
+
if (startTime) {
|
|
20332
|
+
metrics.time_to_first_token = getCurrentUnixTimestamp() - startTime;
|
|
20333
|
+
}
|
|
20334
|
+
return metrics;
|
|
20335
|
+
}
|
|
20336
|
+
function extractDeltaText(content) {
|
|
20337
|
+
if (typeof content === "string") {
|
|
20338
|
+
return content;
|
|
20339
|
+
}
|
|
20340
|
+
if (!Array.isArray(content)) {
|
|
20341
|
+
return void 0;
|
|
20342
|
+
}
|
|
20343
|
+
const textParts = content.map((part) => {
|
|
20344
|
+
if (!isObject(part) || part.type !== "text") {
|
|
20345
|
+
return "";
|
|
20346
|
+
}
|
|
20347
|
+
return typeof part.text === "string" ? part.text : "";
|
|
20348
|
+
}).filter((part) => part.length > 0);
|
|
20349
|
+
return textParts.length > 0 ? textParts.join("") : void 0;
|
|
20350
|
+
}
|
|
20351
|
+
function getDeltaToolCalls(delta) {
|
|
20352
|
+
const toolCalls = Array.isArray(delta.toolCalls) && delta.toolCalls || Array.isArray(delta.tool_calls) && delta.tool_calls || [];
|
|
20353
|
+
return toolCalls.filter((toolCall) => isObject(toolCall));
|
|
20354
|
+
}
|
|
20355
|
+
function getToolCallIndex(toolCall) {
|
|
20356
|
+
return typeof toolCall.index === "number" && toolCall.index >= 0 ? toolCall.index : void 0;
|
|
20357
|
+
}
|
|
20358
|
+
function createMergedToolCallDelta(delta) {
|
|
20359
|
+
return {
|
|
20360
|
+
...delta,
|
|
20361
|
+
function: {
|
|
20362
|
+
...delta.function,
|
|
20363
|
+
arguments: typeof delta.function?.arguments === "string" ? delta.function.arguments : ""
|
|
20364
|
+
}
|
|
20365
|
+
};
|
|
20366
|
+
}
|
|
20367
|
+
function mergeToolCallDeltaPair(current, delta) {
|
|
20368
|
+
const currentArguments = typeof current.function?.arguments === "string" ? current.function.arguments : "";
|
|
20369
|
+
const deltaArguments = typeof delta.function?.arguments === "string" ? delta.function.arguments : "";
|
|
20370
|
+
return {
|
|
20371
|
+
...current,
|
|
20372
|
+
...delta,
|
|
20373
|
+
function: {
|
|
20374
|
+
...current.function || {},
|
|
20375
|
+
...delta.function || {},
|
|
20376
|
+
arguments: `${currentArguments}${deltaArguments}`
|
|
20377
|
+
}
|
|
20378
|
+
};
|
|
20379
|
+
}
|
|
20380
|
+
function mergeToolCallDeltas(toolCalls, deltas) {
|
|
20381
|
+
if (deltas.length === 0) {
|
|
20382
|
+
return toolCalls;
|
|
20383
|
+
}
|
|
20384
|
+
const merged = toolCalls ? [...toolCalls] : [];
|
|
20385
|
+
const indexToPosition = /* @__PURE__ */ new Map();
|
|
20386
|
+
const idToPosition = /* @__PURE__ */ new Map();
|
|
20387
|
+
for (const [position, toolCall] of merged.entries()) {
|
|
20388
|
+
const index = getToolCallIndex(toolCall);
|
|
20389
|
+
if (index !== void 0 && !indexToPosition.has(index)) {
|
|
20390
|
+
indexToPosition.set(index, position);
|
|
20391
|
+
}
|
|
20392
|
+
if (typeof toolCall.id === "string" && !idToPosition.has(toolCall.id)) {
|
|
20393
|
+
idToPosition.set(toolCall.id, position);
|
|
20394
|
+
}
|
|
20395
|
+
}
|
|
20396
|
+
for (const delta of deltas) {
|
|
20397
|
+
const deltaIndex = getToolCallIndex(delta);
|
|
20398
|
+
const existingByIndex = deltaIndex !== void 0 ? indexToPosition.get(deltaIndex) : void 0;
|
|
20399
|
+
const existingById = typeof delta.id === "string" ? idToPosition.get(delta.id) : void 0;
|
|
20400
|
+
const existingPosition = existingByIndex ?? existingById;
|
|
20401
|
+
if (existingPosition === void 0) {
|
|
20402
|
+
const newToolCall = createMergedToolCallDelta(delta);
|
|
20403
|
+
merged.push(newToolCall);
|
|
20404
|
+
const newPosition = merged.length - 1;
|
|
20405
|
+
const newIndex = getToolCallIndex(newToolCall);
|
|
20406
|
+
if (newIndex !== void 0 && !indexToPosition.has(newIndex)) {
|
|
20407
|
+
indexToPosition.set(newIndex, newPosition);
|
|
20408
|
+
}
|
|
20409
|
+
if (typeof newToolCall.id === "string" && !idToPosition.has(newToolCall.id)) {
|
|
20410
|
+
idToPosition.set(newToolCall.id, newPosition);
|
|
17957
20411
|
}
|
|
17958
20412
|
continue;
|
|
17959
20413
|
}
|
|
17960
|
-
|
|
17961
|
-
|
|
20414
|
+
const mergedToolCall = mergeToolCallDeltaPair(
|
|
20415
|
+
merged[existingPosition],
|
|
20416
|
+
delta
|
|
20417
|
+
);
|
|
20418
|
+
merged[existingPosition] = mergedToolCall;
|
|
20419
|
+
const mergedIndex = getToolCallIndex(mergedToolCall);
|
|
20420
|
+
if (mergedIndex !== void 0 && !indexToPosition.has(mergedIndex)) {
|
|
20421
|
+
indexToPosition.set(mergedIndex, existingPosition);
|
|
17962
20422
|
}
|
|
17963
|
-
if (typeof
|
|
17964
|
-
|
|
20423
|
+
if (typeof mergedToolCall.id === "string" && !idToPosition.has(mergedToolCall.id)) {
|
|
20424
|
+
idToPosition.set(mergedToolCall.id, existingPosition);
|
|
17965
20425
|
}
|
|
17966
|
-
|
|
17967
|
-
|
|
17968
|
-
|
|
17969
|
-
|
|
17970
|
-
|
|
17971
|
-
|
|
20426
|
+
}
|
|
20427
|
+
return merged.length > 0 ? merged : void 0;
|
|
20428
|
+
}
|
|
20429
|
+
function getChoiceFinishReason(choice) {
|
|
20430
|
+
if (typeof choice.finishReason === "string" || choice.finishReason === null) {
|
|
20431
|
+
return choice.finishReason;
|
|
20432
|
+
}
|
|
20433
|
+
if (typeof choice.finish_reason === "string" || choice.finish_reason === null) {
|
|
20434
|
+
return choice.finish_reason;
|
|
20435
|
+
}
|
|
20436
|
+
return void 0;
|
|
20437
|
+
}
|
|
20438
|
+
function parseMistralMetricsFromUsage(usage) {
|
|
20439
|
+
if (!isObject(usage)) {
|
|
20440
|
+
return {};
|
|
20441
|
+
}
|
|
20442
|
+
const metrics = {};
|
|
20443
|
+
for (const [name, value] of Object.entries(usage)) {
|
|
20444
|
+
if (typeof value === "number") {
|
|
20445
|
+
metrics[TOKEN_NAME_MAP4[name] || camelToSnake3(name)] = value;
|
|
20446
|
+
continue;
|
|
17972
20447
|
}
|
|
17973
|
-
|
|
17974
|
-
if (!toolCallDeltas) {
|
|
20448
|
+
if (!isObject(value)) {
|
|
17975
20449
|
continue;
|
|
17976
20450
|
}
|
|
17977
|
-
|
|
17978
|
-
|
|
20451
|
+
const prefix = TOKEN_DETAIL_PREFIX_MAP3[name];
|
|
20452
|
+
if (!prefix) {
|
|
20453
|
+
continue;
|
|
20454
|
+
}
|
|
20455
|
+
for (const [nestedName, nestedValue] of Object.entries(value)) {
|
|
20456
|
+
if (typeof nestedValue !== "number") {
|
|
17979
20457
|
continue;
|
|
17980
20458
|
}
|
|
17981
|
-
|
|
17982
|
-
|
|
17983
|
-
|
|
17984
|
-
|
|
17985
|
-
|
|
17986
|
-
|
|
17987
|
-
|
|
17988
|
-
|
|
17989
|
-
|
|
17990
|
-
|
|
17991
|
-
|
|
17992
|
-
|
|
17993
|
-
|
|
17994
|
-
|
|
20459
|
+
metrics[`${prefix}_${camelToSnake3(nestedName)}`] = nestedValue;
|
|
20460
|
+
}
|
|
20461
|
+
}
|
|
20462
|
+
return metrics;
|
|
20463
|
+
}
|
|
20464
|
+
function aggregateMistralStreamChunks(chunks) {
|
|
20465
|
+
const choiceAccumulators = /* @__PURE__ */ new Map();
|
|
20466
|
+
const indexToAccumulatorKey = /* @__PURE__ */ new Map();
|
|
20467
|
+
const positionToAccumulatorKey = /* @__PURE__ */ new Map();
|
|
20468
|
+
let nextAccumulatorOrder = 0;
|
|
20469
|
+
let metrics = {};
|
|
20470
|
+
let metadata;
|
|
20471
|
+
for (const event of chunks) {
|
|
20472
|
+
const chunk = isMistralChatCompletionChunk(event?.data) ? event.data : void 0;
|
|
20473
|
+
if (!chunk) {
|
|
20474
|
+
continue;
|
|
20475
|
+
}
|
|
20476
|
+
if (isObject(chunk.usage)) {
|
|
20477
|
+
metrics = {
|
|
20478
|
+
...metrics,
|
|
20479
|
+
...parseMistralMetricsFromUsage(chunk.usage)
|
|
20480
|
+
};
|
|
20481
|
+
}
|
|
20482
|
+
const chunkMetadata = extractMistralResponseMetadata(chunk);
|
|
20483
|
+
if (chunkMetadata) {
|
|
20484
|
+
metadata = { ...metadata || {}, ...chunkMetadata };
|
|
20485
|
+
}
|
|
20486
|
+
for (const [choicePosition, rawChoice] of (chunk.choices || []).entries()) {
|
|
20487
|
+
if (!isMistralChunkChoice(rawChoice)) {
|
|
17995
20488
|
continue;
|
|
17996
20489
|
}
|
|
17997
|
-
const
|
|
17998
|
-
|
|
17999
|
-
|
|
20490
|
+
const choice = rawChoice;
|
|
20491
|
+
const choiceIndex = typeof choice.index === "number" && choice.index >= 0 ? choice.index : void 0;
|
|
20492
|
+
let accumulatorKey = choiceIndex !== void 0 ? indexToAccumulatorKey.get(choiceIndex) : void 0;
|
|
20493
|
+
if (!accumulatorKey) {
|
|
20494
|
+
accumulatorKey = positionToAccumulatorKey.get(choicePosition);
|
|
20495
|
+
}
|
|
20496
|
+
if (!accumulatorKey) {
|
|
20497
|
+
const initialIndex = choiceIndex ?? choicePosition;
|
|
20498
|
+
const keyPrefix = choiceIndex !== void 0 ? "index" : "position";
|
|
20499
|
+
accumulatorKey = `${keyPrefix}:${initialIndex}`;
|
|
20500
|
+
choiceAccumulators.set(accumulatorKey, {
|
|
20501
|
+
index: initialIndex,
|
|
20502
|
+
order: nextAccumulatorOrder++
|
|
20503
|
+
});
|
|
18000
20504
|
}
|
|
18001
|
-
|
|
18002
|
-
|
|
20505
|
+
const accumulator = choiceAccumulators.get(accumulatorKey);
|
|
20506
|
+
if (!accumulator) {
|
|
20507
|
+
continue;
|
|
18003
20508
|
}
|
|
18004
|
-
if (
|
|
18005
|
-
|
|
20509
|
+
if (choiceIndex !== void 0) {
|
|
20510
|
+
accumulator.index = choiceIndex;
|
|
20511
|
+
indexToAccumulatorKey.set(choiceIndex, accumulatorKey);
|
|
18006
20512
|
}
|
|
18007
|
-
|
|
18008
|
-
|
|
18009
|
-
|
|
18010
|
-
|
|
18011
|
-
|
|
18012
|
-
|
|
18013
|
-
|
|
18014
|
-
|
|
18015
|
-
|
|
18016
|
-
|
|
18017
|
-
|
|
18018
|
-
|
|
18019
|
-
|
|
18020
|
-
|
|
20513
|
+
positionToAccumulatorKey.set(choicePosition, accumulatorKey);
|
|
20514
|
+
const delta = isObject(choice.delta) ? choice.delta : void 0;
|
|
20515
|
+
if (delta) {
|
|
20516
|
+
if (!accumulator.role && typeof delta.role === "string") {
|
|
20517
|
+
accumulator.role = delta.role;
|
|
20518
|
+
}
|
|
20519
|
+
const deltaText = extractDeltaText(delta.content);
|
|
20520
|
+
if (deltaText) {
|
|
20521
|
+
accumulator.content = `${accumulator.content || ""}${deltaText}`;
|
|
20522
|
+
}
|
|
20523
|
+
accumulator.toolCalls = mergeToolCallDeltas(
|
|
20524
|
+
accumulator.toolCalls,
|
|
20525
|
+
getDeltaToolCalls(delta)
|
|
20526
|
+
);
|
|
20527
|
+
}
|
|
20528
|
+
const choiceFinishReason = getChoiceFinishReason(choice);
|
|
20529
|
+
if (choiceFinishReason !== void 0) {
|
|
20530
|
+
accumulator.finishReason = choiceFinishReason;
|
|
18021
20531
|
}
|
|
18022
|
-
],
|
|
18023
|
-
metrics
|
|
18024
|
-
};
|
|
18025
|
-
}
|
|
18026
|
-
function aggregateOpenRouterResponseStreamEvents(chunks) {
|
|
18027
|
-
let finalResponse;
|
|
18028
|
-
for (const chunk of chunks) {
|
|
18029
|
-
const response = chunk?.response;
|
|
18030
|
-
if (!response) {
|
|
18031
|
-
continue;
|
|
18032
|
-
}
|
|
18033
|
-
if (chunk.type === "response.completed" || chunk.type === "response.incomplete" || chunk.type === "response.failed") {
|
|
18034
|
-
finalResponse = response;
|
|
18035
20532
|
}
|
|
18036
20533
|
}
|
|
18037
|
-
|
|
18038
|
-
|
|
18039
|
-
|
|
18040
|
-
|
|
18041
|
-
|
|
18042
|
-
|
|
20534
|
+
const output = Array.from(choiceAccumulators.values()).sort(
|
|
20535
|
+
(left, right) => left.index === right.index ? left.order - right.order : left.index - right.index
|
|
20536
|
+
).map((choice) => ({
|
|
20537
|
+
index: choice.index,
|
|
20538
|
+
message: {
|
|
20539
|
+
...choice.role ? { role: choice.role } : {},
|
|
20540
|
+
content: choice.content ?? null,
|
|
20541
|
+
...choice.toolCalls ? { toolCalls: choice.toolCalls } : {}
|
|
20542
|
+
},
|
|
20543
|
+
...choice.finishReason !== void 0 ? { finishReason: choice.finishReason } : {}
|
|
20544
|
+
}));
|
|
18043
20545
|
return {
|
|
18044
|
-
output
|
|
18045
|
-
metrics
|
|
18046
|
-
...
|
|
20546
|
+
output,
|
|
20547
|
+
metrics,
|
|
20548
|
+
...metadata ? { metadata } : {}
|
|
18047
20549
|
};
|
|
18048
20550
|
}
|
|
18049
20551
|
|
|
@@ -18056,6 +20558,8 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
18056
20558
|
claudeAgentSDKPlugin = null;
|
|
18057
20559
|
googleGenAIPlugin = null;
|
|
18058
20560
|
openRouterPlugin = null;
|
|
20561
|
+
openRouterAgentPlugin = null;
|
|
20562
|
+
mistralPlugin = null;
|
|
18059
20563
|
constructor(config3 = {}) {
|
|
18060
20564
|
super();
|
|
18061
20565
|
this.config = config3;
|
|
@@ -18086,6 +20590,14 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
18086
20590
|
this.openRouterPlugin = new OpenRouterPlugin();
|
|
18087
20591
|
this.openRouterPlugin.enable();
|
|
18088
20592
|
}
|
|
20593
|
+
if (integrations.openrouterAgent !== false) {
|
|
20594
|
+
this.openRouterAgentPlugin = new OpenRouterAgentPlugin();
|
|
20595
|
+
this.openRouterAgentPlugin.enable();
|
|
20596
|
+
}
|
|
20597
|
+
if (integrations.mistral !== false) {
|
|
20598
|
+
this.mistralPlugin = new MistralPlugin();
|
|
20599
|
+
this.mistralPlugin.enable();
|
|
20600
|
+
}
|
|
18089
20601
|
}
|
|
18090
20602
|
onDisable() {
|
|
18091
20603
|
if (this.openaiPlugin) {
|
|
@@ -18112,6 +20624,14 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
18112
20624
|
this.openRouterPlugin.disable();
|
|
18113
20625
|
this.openRouterPlugin = null;
|
|
18114
20626
|
}
|
|
20627
|
+
if (this.openRouterAgentPlugin) {
|
|
20628
|
+
this.openRouterAgentPlugin.disable();
|
|
20629
|
+
this.openRouterAgentPlugin = null;
|
|
20630
|
+
}
|
|
20631
|
+
if (this.mistralPlugin) {
|
|
20632
|
+
this.mistralPlugin.disable();
|
|
20633
|
+
this.mistralPlugin = null;
|
|
20634
|
+
}
|
|
18115
20635
|
}
|
|
18116
20636
|
};
|
|
18117
20637
|
|
|
@@ -18184,7 +20704,9 @@ var PluginRegistry = class {
|
|
|
18184
20704
|
aisdk: true,
|
|
18185
20705
|
google: true,
|
|
18186
20706
|
claudeAgentSDK: true,
|
|
18187
|
-
openrouter: true
|
|
20707
|
+
openrouter: true,
|
|
20708
|
+
openrouterAgent: true,
|
|
20709
|
+
mistral: true
|
|
18188
20710
|
};
|
|
18189
20711
|
}
|
|
18190
20712
|
/**
|
|
@@ -18654,7 +21176,8 @@ var ScorerBuilder = class {
|
|
|
18654
21176
|
type: "llm_classifier",
|
|
18655
21177
|
use_cot: opts.useCot,
|
|
18656
21178
|
choice_scores: opts.choiceScores
|
|
18657
|
-
}
|
|
21179
|
+
},
|
|
21180
|
+
...opts.templateFormat ? { template_format: opts.templateFormat } : {}
|
|
18658
21181
|
};
|
|
18659
21182
|
const codePrompt = new CodePrompt(
|
|
18660
21183
|
this.project,
|
|
@@ -19967,7 +22490,7 @@ var parametersContainerSchema = import_v315.z.object({
|
|
|
19967
22490
|
var staticParametersContainerSchema = import_v315.z.object({
|
|
19968
22491
|
type: import_v315.z.literal("braintrust.staticParameters"),
|
|
19969
22492
|
schema: staticParametersSchema,
|
|
19970
|
-
source: import_v315.z.null()
|
|
22493
|
+
source: import_v315.z.null().nullish()
|
|
19971
22494
|
});
|
|
19972
22495
|
var serializedParametersContainerSchema = import_v315.z.union([
|
|
19973
22496
|
parametersContainerSchema,
|