braintrust 3.16.0 → 3.18.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/bin/bt +41 -0
- package/dev/dist/index.d.mts +13 -0
- package/dev/dist/index.d.ts +13 -0
- package/dev/dist/index.js +4300 -2199
- package/dev/dist/index.mjs +2211 -110
- package/dist/apply-auto-instrumentation.js +238 -186
- package/dist/apply-auto-instrumentation.mjs +68 -16
- package/dist/auto-instrumentations/bundler/esbuild.cjs +90 -15
- package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
- package/dist/auto-instrumentations/bundler/next.cjs +90 -15
- package/dist/auto-instrumentations/bundler/next.mjs +3 -3
- package/dist/auto-instrumentations/bundler/rollup.cjs +90 -15
- package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
- package/dist/auto-instrumentations/bundler/vite.cjs +90 -15
- package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
- package/dist/auto-instrumentations/bundler/webpack-loader.cjs +89 -14
- package/dist/auto-instrumentations/bundler/webpack.cjs +90 -15
- package/dist/auto-instrumentations/bundler/webpack.mjs +3 -3
- package/dist/auto-instrumentations/{chunk-VXJONZVX.mjs → chunk-GNUEZ2PE.mjs} +13 -3
- package/dist/auto-instrumentations/{chunk-CNQ7BUKN.mjs → chunk-MYCHHXOE.mjs} +1 -1
- package/dist/auto-instrumentations/{chunk-E5DUYJWK.mjs → chunk-ZYKZEMRT.mjs} +82 -15
- package/dist/auto-instrumentations/hook.mjs +102 -15
- package/dist/auto-instrumentations/index.cjs +84 -16
- package/dist/auto-instrumentations/index.d.mts +3 -1
- package/dist/auto-instrumentations/index.d.ts +3 -1
- package/dist/auto-instrumentations/index.mjs +5 -3
- package/dist/auto-instrumentations/loader/cjs-patch.cjs +1 -1
- package/dist/auto-instrumentations/loader/cjs-patch.mjs +1 -1
- package/dist/auto-instrumentations/loader/esm-hook.mjs +1 -1
- package/dist/browser.d.mts +177 -11
- package/dist/browser.d.ts +177 -11
- package/dist/browser.js +2296 -104
- package/dist/browser.mjs +2455 -263
- package/dist/{chunk-VMBQETG3.js → chunk-73IYIIOL.js} +28 -2
- package/dist/{chunk-O4ZIWXO3.mjs → chunk-BYFADLEZ.mjs} +27 -1
- package/dist/cli.js +2228 -113
- package/dist/edge-light.d.mts +1 -1
- package/dist/edge-light.d.ts +1 -1
- package/dist/edge-light.js +2296 -104
- package/dist/edge-light.mjs +2455 -263
- package/dist/index.d.mts +177 -11
- package/dist/index.d.ts +177 -11
- package/dist/index.js +3296 -1128
- package/dist/index.mjs +2272 -104
- package/dist/instrumentation/index.d.mts +3 -0
- package/dist/instrumentation/index.d.ts +3 -0
- package/dist/instrumentation/index.js +2171 -105
- package/dist/instrumentation/index.mjs +2171 -105
- package/dist/workerd.d.mts +1 -1
- package/dist/workerd.d.ts +1 -1
- package/dist/workerd.js +2296 -104
- package/dist/workerd.mjs +2455 -263
- package/package.json +19 -5
- package/scripts/bt-helper.js +139 -0
- package/scripts/install.js +153 -0
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.18.0",
|
|
1236
1236
|
description: "SDK for integrating Braintrust",
|
|
1237
1237
|
repository: {
|
|
1238
1238
|
type: "git",
|
|
@@ -1251,7 +1251,8 @@ var require_package = __commonJS({
|
|
|
1251
1251
|
"./dist/index.d.mts": "./dist/browser.d.mts"
|
|
1252
1252
|
},
|
|
1253
1253
|
bin: {
|
|
1254
|
-
braintrust: "./dist/cli.js"
|
|
1254
|
+
braintrust: "./dist/cli.js",
|
|
1255
|
+
bt: "./bin/bt"
|
|
1255
1256
|
},
|
|
1256
1257
|
exports: {
|
|
1257
1258
|
"./package.json": "./package.json",
|
|
@@ -1359,9 +1360,13 @@ var require_package = __commonJS({
|
|
|
1359
1360
|
files: [
|
|
1360
1361
|
"dist/**/*",
|
|
1361
1362
|
"dev/dist/**/*",
|
|
1362
|
-
"util/dist/**/*"
|
|
1363
|
+
"util/dist/**/*",
|
|
1364
|
+
"bin/bt",
|
|
1365
|
+
"scripts/bt-helper.js",
|
|
1366
|
+
"scripts/install.js"
|
|
1363
1367
|
],
|
|
1364
1368
|
scripts: {
|
|
1369
|
+
postinstall: "node ./scripts/install.js",
|
|
1365
1370
|
build: 'cross-env NODE_OPTIONS="--max-old-space-size=8192" tsup',
|
|
1366
1371
|
"check:typings": "tsc --noEmit",
|
|
1367
1372
|
watch: "tsup --watch",
|
|
@@ -1414,14 +1419,14 @@ var require_package = __commonJS({
|
|
|
1414
1419
|
"eslint-plugin-node-import": "^1.0.5",
|
|
1415
1420
|
openai: "6.25.0",
|
|
1416
1421
|
rollup: "^4.60.3",
|
|
1417
|
-
tar: "^7.5.
|
|
1422
|
+
tar: "^7.5.16",
|
|
1418
1423
|
tinybench: "^4.0.1",
|
|
1419
1424
|
tsup: "^8.5.1",
|
|
1420
1425
|
tsx: "^4.21.0",
|
|
1421
1426
|
typedoc: "^0.25.13",
|
|
1422
1427
|
"typedoc-plugin-markdown": "^3.17.1",
|
|
1423
1428
|
typescript: "5.4.4",
|
|
1424
|
-
vite: "^6.4.
|
|
1429
|
+
vite: "^6.4.3",
|
|
1425
1430
|
"vite-tsconfig-paths": "^4.3.2",
|
|
1426
1431
|
vitest: "4.1.5",
|
|
1427
1432
|
webpack: "^5.106.2",
|
|
@@ -1456,6 +1461,15 @@ var require_package = __commonJS({
|
|
|
1456
1461
|
peerDependencies: {
|
|
1457
1462
|
zod: "^3.25.34 || ^4.0"
|
|
1458
1463
|
},
|
|
1464
|
+
optionalDependencies: {
|
|
1465
|
+
"@braintrust/bt-darwin-arm64": "0.12.0",
|
|
1466
|
+
"@braintrust/bt-darwin-x64": "0.12.0",
|
|
1467
|
+
"@braintrust/bt-linux-arm64": "0.12.0",
|
|
1468
|
+
"@braintrust/bt-linux-x64": "0.12.0",
|
|
1469
|
+
"@braintrust/bt-linux-x64-musl": "0.12.0",
|
|
1470
|
+
"@braintrust/bt-win32-arm64": "0.12.0",
|
|
1471
|
+
"@braintrust/bt-win32-x64": "0.12.0"
|
|
1472
|
+
},
|
|
1459
1473
|
publishConfig: {
|
|
1460
1474
|
access: "public",
|
|
1461
1475
|
registry: "https://registry.npmjs.org/",
|
|
@@ -9119,6 +9133,10 @@ var Experiment2 = class extends ObjectFetcher {
|
|
|
9119
9133
|
return (await this.lazyMetadata.get()).project;
|
|
9120
9134
|
})();
|
|
9121
9135
|
}
|
|
9136
|
+
async _getBaseExperimentId() {
|
|
9137
|
+
const baseExperimentId = (await this.lazyMetadata.get()).experiment.fullInfo["base_exp_id"];
|
|
9138
|
+
return typeof baseExperimentId === "string" && baseExperimentId ? baseExperimentId : void 0;
|
|
9139
|
+
}
|
|
9122
9140
|
parentObjectType() {
|
|
9123
9141
|
return 1 /* EXPERIMENT */;
|
|
9124
9142
|
}
|
|
@@ -9259,6 +9277,14 @@ var Experiment2 = class extends ObjectFetcher {
|
|
|
9259
9277
|
comparisonExperimentId = baseExperiment.id;
|
|
9260
9278
|
comparisonExperimentName = baseExperiment.name;
|
|
9261
9279
|
}
|
|
9280
|
+
} else {
|
|
9281
|
+
try {
|
|
9282
|
+
const comparisonExperiment = await state.apiConn().get_json(`v1/experiment/${comparisonExperimentId}`);
|
|
9283
|
+
if (typeof comparisonExperiment["name"] === "string") {
|
|
9284
|
+
comparisonExperimentName = comparisonExperiment["name"];
|
|
9285
|
+
}
|
|
9286
|
+
} catch {
|
|
9287
|
+
}
|
|
9262
9288
|
}
|
|
9263
9289
|
try {
|
|
9264
9290
|
const results = await state.apiConn().get_json(
|
|
@@ -12243,6 +12269,13 @@ var EvalResultWithSummary = class {
|
|
|
12243
12269
|
};
|
|
12244
12270
|
}
|
|
12245
12271
|
};
|
|
12272
|
+
async function getPersistedBaseExperimentId(experiment) {
|
|
12273
|
+
try {
|
|
12274
|
+
return await experiment._getBaseExperimentId();
|
|
12275
|
+
} catch {
|
|
12276
|
+
return void 0;
|
|
12277
|
+
}
|
|
12278
|
+
}
|
|
12246
12279
|
function makeEvalName(projectName, experimentName) {
|
|
12247
12280
|
let out = projectName;
|
|
12248
12281
|
if (experimentName) {
|
|
@@ -12632,6 +12665,14 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
|
|
|
12632
12665
|
return;
|
|
12633
12666
|
}
|
|
12634
12667
|
const eventDataset = experiment ? experiment.dataset : Dataset2.isDataset(evaluator.data) ? evaluator.data : void 0;
|
|
12668
|
+
const inlineOrigin = datum.origin === void 0 ? void 0 : ObjectReference.parse(datum.origin);
|
|
12669
|
+
const origin = inlineOrigin ?? (eventDataset && datum.id && datum._xact_id ? {
|
|
12670
|
+
object_type: "dataset",
|
|
12671
|
+
object_id: await eventDataset.id,
|
|
12672
|
+
id: datum.id,
|
|
12673
|
+
created: datum.created,
|
|
12674
|
+
_xact_id: datum._xact_id
|
|
12675
|
+
} : void 0);
|
|
12635
12676
|
const baseEvent = {
|
|
12636
12677
|
name: "eval",
|
|
12637
12678
|
spanAttributes: {
|
|
@@ -12641,13 +12682,7 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
|
|
|
12641
12682
|
input: datum.input,
|
|
12642
12683
|
expected: "expected" in datum ? datum.expected : void 0,
|
|
12643
12684
|
tags: datum.tags,
|
|
12644
|
-
origin
|
|
12645
|
-
object_type: "dataset",
|
|
12646
|
-
object_id: await eventDataset.id,
|
|
12647
|
-
id: datum.id,
|
|
12648
|
-
created: datum.created,
|
|
12649
|
-
_xact_id: datum._xact_id
|
|
12650
|
-
} : void 0,
|
|
12685
|
+
origin,
|
|
12651
12686
|
...datum.upsert_id ? { id: datum.upsert_id } : {}
|
|
12652
12687
|
}
|
|
12653
12688
|
};
|
|
@@ -13004,8 +13039,10 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
|
|
|
13004
13039
|
collectedResults.length = 0;
|
|
13005
13040
|
}
|
|
13006
13041
|
}
|
|
13042
|
+
const comparisonExperimentId = experiment ? evaluator.baseExperimentId ?? await getPersistedBaseExperimentId(experiment) : void 0;
|
|
13007
13043
|
const summary = experiment ? await experiment.summarize({
|
|
13008
|
-
summarizeScores: evaluator.summarizeScores
|
|
13044
|
+
summarizeScores: evaluator.summarizeScores,
|
|
13045
|
+
...comparisonExperimentId !== void 0 ? { comparisonExperimentId } : {}
|
|
13009
13046
|
}) : buildLocalSummary(
|
|
13010
13047
|
evaluator,
|
|
13011
13048
|
collectResults ? collectedResults : [],
|
|
@@ -14273,6 +14310,64 @@ var BasePlugin = class {
|
|
|
14273
14310
|
}
|
|
14274
14311
|
};
|
|
14275
14312
|
|
|
14313
|
+
// src/instrumentation/auto-instrumentation-suppression.ts
|
|
14314
|
+
var autoInstrumentationSuppressionStore;
|
|
14315
|
+
function suppressionStore() {
|
|
14316
|
+
autoInstrumentationSuppressionStore ??= isomorph_default.newAsyncLocalStorage();
|
|
14317
|
+
return autoInstrumentationSuppressionStore;
|
|
14318
|
+
}
|
|
14319
|
+
function currentFrames() {
|
|
14320
|
+
return suppressionStore().getStore()?.frames ?? [];
|
|
14321
|
+
}
|
|
14322
|
+
function isAutoInstrumentationSuppressed() {
|
|
14323
|
+
const frames = currentFrames();
|
|
14324
|
+
return frames[frames.length - 1]?.mode === "suppress";
|
|
14325
|
+
}
|
|
14326
|
+
function runWithAutoInstrumentationSuppressed(callback) {
|
|
14327
|
+
const frame = {
|
|
14328
|
+
id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
|
|
14329
|
+
mode: "suppress"
|
|
14330
|
+
};
|
|
14331
|
+
return suppressionStore().run(
|
|
14332
|
+
{ frames: [...currentFrames(), frame] },
|
|
14333
|
+
callback
|
|
14334
|
+
);
|
|
14335
|
+
}
|
|
14336
|
+
function bindAutoInstrumentationSuppressionToStart(tracingChannel2) {
|
|
14337
|
+
const startChannel = tracingChannel2.start;
|
|
14338
|
+
if (!startChannel) {
|
|
14339
|
+
return void 0;
|
|
14340
|
+
}
|
|
14341
|
+
const store = suppressionStore();
|
|
14342
|
+
startChannel.bindStore(store, () => ({
|
|
14343
|
+
frames: [
|
|
14344
|
+
...currentFrames(),
|
|
14345
|
+
{
|
|
14346
|
+
id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
|
|
14347
|
+
mode: "suppress"
|
|
14348
|
+
}
|
|
14349
|
+
]
|
|
14350
|
+
}));
|
|
14351
|
+
return () => {
|
|
14352
|
+
startChannel.unbindStore(store);
|
|
14353
|
+
};
|
|
14354
|
+
}
|
|
14355
|
+
function enterAutoInstrumentationAllowed() {
|
|
14356
|
+
const frame = {
|
|
14357
|
+
id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-allow"),
|
|
14358
|
+
mode: "allow"
|
|
14359
|
+
};
|
|
14360
|
+
suppressionStore().enterWith({
|
|
14361
|
+
frames: [...currentFrames(), frame]
|
|
14362
|
+
});
|
|
14363
|
+
return () => {
|
|
14364
|
+
const frames = currentFrames().filter(
|
|
14365
|
+
(candidate) => candidate.id !== frame.id
|
|
14366
|
+
);
|
|
14367
|
+
suppressionStore().enterWith(frames.length > 0 ? { frames } : void 0);
|
|
14368
|
+
};
|
|
14369
|
+
}
|
|
14370
|
+
|
|
14276
14371
|
// src/instrumentation/core/channel-tracing.ts
|
|
14277
14372
|
function isSyncStreamLike(value) {
|
|
14278
14373
|
return !!value && typeof value === "object" && typeof value.on === "function";
|
|
@@ -14304,16 +14399,33 @@ function startSpanForEvent(config3, event, channelName) {
|
|
|
14304
14399
|
metadata: mergeInputMetadata(metadata, spanInfoMetadata)
|
|
14305
14400
|
});
|
|
14306
14401
|
} catch (error2) {
|
|
14307
|
-
|
|
14402
|
+
debugLogger.error(`Error extracting input for ${channelName}:`, error2);
|
|
14308
14403
|
}
|
|
14309
14404
|
return { span, startTime };
|
|
14310
14405
|
}
|
|
14406
|
+
function shouldTraceEvent(config3, event, channelName) {
|
|
14407
|
+
if (!config3.shouldTrace) {
|
|
14408
|
+
return true;
|
|
14409
|
+
}
|
|
14410
|
+
try {
|
|
14411
|
+
return config3.shouldTrace(event.arguments, event);
|
|
14412
|
+
} catch (error2) {
|
|
14413
|
+
debugLogger.error(
|
|
14414
|
+
`Error checking trace predicate for ${channelName}:`,
|
|
14415
|
+
error2
|
|
14416
|
+
);
|
|
14417
|
+
return true;
|
|
14418
|
+
}
|
|
14419
|
+
}
|
|
14311
14420
|
function ensureSpanStateForEvent(states, config3, event, channelName) {
|
|
14312
14421
|
const key = event;
|
|
14313
14422
|
const existing = states.get(key);
|
|
14314
14423
|
if (existing) {
|
|
14315
14424
|
return existing;
|
|
14316
14425
|
}
|
|
14426
|
+
if (!shouldTraceEvent(config3, event, channelName)) {
|
|
14427
|
+
return void 0;
|
|
14428
|
+
}
|
|
14317
14429
|
const created = startSpanForEvent(config3, event, channelName);
|
|
14318
14430
|
states.set(key, created);
|
|
14319
14431
|
return created;
|
|
@@ -14329,13 +14441,16 @@ function bindCurrentSpanStoreToStart(tracingChannel2, states, config3, channelNa
|
|
|
14329
14441
|
startChannel.bindStore(
|
|
14330
14442
|
currentSpanStore,
|
|
14331
14443
|
(event) => {
|
|
14332
|
-
|
|
14444
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
14445
|
+
return currentSpanStore.getStore();
|
|
14446
|
+
}
|
|
14447
|
+
const spanState = ensureSpanStateForEvent(
|
|
14333
14448
|
states,
|
|
14334
14449
|
config3,
|
|
14335
14450
|
event,
|
|
14336
14451
|
channelName
|
|
14337
|
-
)
|
|
14338
|
-
return contextManager.wrapSpanForStore(span);
|
|
14452
|
+
);
|
|
14453
|
+
return spanState ? contextManager.wrapSpanForStore(spanState.span) : currentSpanStore.getStore();
|
|
14339
14454
|
}
|
|
14340
14455
|
);
|
|
14341
14456
|
return () => {
|
|
@@ -14370,7 +14485,10 @@ function runStreamingCompletionHook(args) {
|
|
|
14370
14485
|
startTime: args.startTime
|
|
14371
14486
|
});
|
|
14372
14487
|
} catch (error2) {
|
|
14373
|
-
|
|
14488
|
+
debugLogger.error(
|
|
14489
|
+
`Error in onComplete hook for ${args.channelName}:`,
|
|
14490
|
+
error2
|
|
14491
|
+
);
|
|
14374
14492
|
}
|
|
14375
14493
|
}
|
|
14376
14494
|
function traceAsyncChannel(channel2, config3) {
|
|
@@ -14385,6 +14503,9 @@ function traceAsyncChannel(channel2, config3) {
|
|
|
14385
14503
|
);
|
|
14386
14504
|
const handlers = {
|
|
14387
14505
|
start: (event) => {
|
|
14506
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
14507
|
+
return;
|
|
14508
|
+
}
|
|
14388
14509
|
ensureSpanStateForEvent(
|
|
14389
14510
|
states,
|
|
14390
14511
|
config3,
|
|
@@ -14419,7 +14540,7 @@ function traceAsyncChannel(channel2, config3) {
|
|
|
14419
14540
|
metrics
|
|
14420
14541
|
});
|
|
14421
14542
|
} catch (error2) {
|
|
14422
|
-
|
|
14543
|
+
debugLogger.error(`Error extracting output for ${channelName}:`, error2);
|
|
14423
14544
|
} finally {
|
|
14424
14545
|
span.end();
|
|
14425
14546
|
states.delete(event);
|
|
@@ -14447,6 +14568,9 @@ function traceStreamingChannel(channel2, config3) {
|
|
|
14447
14568
|
);
|
|
14448
14569
|
const handlers = {
|
|
14449
14570
|
start: (event) => {
|
|
14571
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
14572
|
+
return;
|
|
14573
|
+
}
|
|
14450
14574
|
ensureSpanStateForEvent(
|
|
14451
14575
|
states,
|
|
14452
14576
|
config3,
|
|
@@ -14518,7 +14642,7 @@ function traceStreamingChannel(channel2, config3) {
|
|
|
14518
14642
|
metrics
|
|
14519
14643
|
});
|
|
14520
14644
|
} catch (error2) {
|
|
14521
|
-
|
|
14645
|
+
debugLogger.error(
|
|
14522
14646
|
`Error extracting output for ${channelName}:`,
|
|
14523
14647
|
error2
|
|
14524
14648
|
);
|
|
@@ -14578,7 +14702,7 @@ function traceStreamingChannel(channel2, config3) {
|
|
|
14578
14702
|
metrics
|
|
14579
14703
|
});
|
|
14580
14704
|
} catch (error2) {
|
|
14581
|
-
|
|
14705
|
+
debugLogger.error(`Error extracting output for ${channelName}:`, error2);
|
|
14582
14706
|
} finally {
|
|
14583
14707
|
span.end();
|
|
14584
14708
|
states.delete(event);
|
|
@@ -14606,6 +14730,9 @@ function traceSyncStreamChannel(channel2, config3) {
|
|
|
14606
14730
|
);
|
|
14607
14731
|
const handlers = {
|
|
14608
14732
|
start: (event) => {
|
|
14733
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
14734
|
+
return;
|
|
14735
|
+
}
|
|
14609
14736
|
ensureSpanStateForEvent(
|
|
14610
14737
|
states,
|
|
14611
14738
|
config3,
|
|
@@ -14659,7 +14786,7 @@ function traceSyncStreamChannel(channel2, config3) {
|
|
|
14659
14786
|
});
|
|
14660
14787
|
}
|
|
14661
14788
|
} catch (error2) {
|
|
14662
|
-
|
|
14789
|
+
debugLogger.error(
|
|
14663
14790
|
`Error extracting chatCompletion for ${channelName}:`,
|
|
14664
14791
|
error2
|
|
14665
14792
|
);
|
|
@@ -14683,7 +14810,10 @@ function traceSyncStreamChannel(channel2, config3) {
|
|
|
14683
14810
|
span.log(extracted);
|
|
14684
14811
|
}
|
|
14685
14812
|
} catch (error2) {
|
|
14686
|
-
|
|
14813
|
+
debugLogger.error(
|
|
14814
|
+
`Error extracting event for ${channelName}:`,
|
|
14815
|
+
error2
|
|
14816
|
+
);
|
|
14687
14817
|
}
|
|
14688
14818
|
});
|
|
14689
14819
|
stream.on("end", () => {
|
|
@@ -16212,6 +16342,9 @@ var AnthropicPlugin = class extends BasePlugin {
|
|
|
16212
16342
|
const states = /* @__PURE__ */ new WeakMap();
|
|
16213
16343
|
const handlers = {
|
|
16214
16344
|
start: (event) => {
|
|
16345
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
16346
|
+
return;
|
|
16347
|
+
}
|
|
16215
16348
|
const params = event.arguments[0] ?? {};
|
|
16216
16349
|
const span = startSpan({
|
|
16217
16350
|
name: "anthropic.beta.messages.toolRunner",
|
|
@@ -16941,6 +17074,520 @@ function serializeAISDKToolsForLogging(tools) {
|
|
|
16941
17074
|
return serialized;
|
|
16942
17075
|
}
|
|
16943
17076
|
|
|
17077
|
+
// src/wrappers/ai-sdk/telemetry.ts
|
|
17078
|
+
function braintrustAISDKTelemetry() {
|
|
17079
|
+
const operations = /* @__PURE__ */ new Map();
|
|
17080
|
+
const modelSpans = /* @__PURE__ */ new Map();
|
|
17081
|
+
const objectSpans = /* @__PURE__ */ new Map();
|
|
17082
|
+
const embedSpans = /* @__PURE__ */ new Map();
|
|
17083
|
+
const rerankSpans = /* @__PURE__ */ new Map();
|
|
17084
|
+
const toolSpans = /* @__PURE__ */ new Map();
|
|
17085
|
+
const runSafely = (name, callback) => {
|
|
17086
|
+
try {
|
|
17087
|
+
callback();
|
|
17088
|
+
} catch (error2) {
|
|
17089
|
+
console.error(`Error in Braintrust AI SDK telemetry ${name}:`, error2);
|
|
17090
|
+
}
|
|
17091
|
+
};
|
|
17092
|
+
const startChildSpan = (callId, name, type, event) => {
|
|
17093
|
+
const parent = operations.get(callId)?.span;
|
|
17094
|
+
const spanArgs = {
|
|
17095
|
+
name,
|
|
17096
|
+
spanAttributes: { type },
|
|
17097
|
+
...event ? { event } : {}
|
|
17098
|
+
};
|
|
17099
|
+
const span = parent ? parent.startSpan(spanArgs) : startSpan(spanArgs);
|
|
17100
|
+
const state = operations.get(callId);
|
|
17101
|
+
if (state && type === "llm" /* LLM */) {
|
|
17102
|
+
state.hadModelChild = true;
|
|
17103
|
+
}
|
|
17104
|
+
return span;
|
|
17105
|
+
};
|
|
17106
|
+
return {
|
|
17107
|
+
onStart(event) {
|
|
17108
|
+
runSafely("onStart", () => {
|
|
17109
|
+
const operationName = operationNameFromId(event.operationId);
|
|
17110
|
+
const span = startSpan({
|
|
17111
|
+
name: operationName,
|
|
17112
|
+
spanAttributes: { type: "function" /* FUNCTION */ }
|
|
17113
|
+
});
|
|
17114
|
+
operations.set(event.callId, {
|
|
17115
|
+
hadModelChild: false,
|
|
17116
|
+
operationName,
|
|
17117
|
+
span,
|
|
17118
|
+
startTime: getCurrentUnixTimestamp()
|
|
17119
|
+
});
|
|
17120
|
+
const metadata = metadataFromEvent(event);
|
|
17121
|
+
const logPayload = { metadata };
|
|
17122
|
+
if (shouldRecordInputs(event)) {
|
|
17123
|
+
const { input, outputPromise } = processAISDKCallInput(
|
|
17124
|
+
operationInput(event, operationName)
|
|
17125
|
+
);
|
|
17126
|
+
logPayload.input = input;
|
|
17127
|
+
if (outputPromise && input && typeof input === "object") {
|
|
17128
|
+
outputPromise.then((resolvedData) => {
|
|
17129
|
+
span.log({
|
|
17130
|
+
input: {
|
|
17131
|
+
...input,
|
|
17132
|
+
...resolvedData
|
|
17133
|
+
}
|
|
17134
|
+
});
|
|
17135
|
+
}).catch(() => {
|
|
17136
|
+
});
|
|
17137
|
+
}
|
|
17138
|
+
}
|
|
17139
|
+
span.log(logPayload);
|
|
17140
|
+
});
|
|
17141
|
+
},
|
|
17142
|
+
onLanguageModelCallStart(event) {
|
|
17143
|
+
runSafely("onLanguageModelCallStart", () => {
|
|
17144
|
+
const state = operations.get(event.callId);
|
|
17145
|
+
const openSpans = modelSpans.get(event.callId);
|
|
17146
|
+
if (openSpans) {
|
|
17147
|
+
for (const span2 of openSpans) {
|
|
17148
|
+
span2.end();
|
|
17149
|
+
}
|
|
17150
|
+
modelSpans.delete(event.callId);
|
|
17151
|
+
}
|
|
17152
|
+
const span = startChildSpan(
|
|
17153
|
+
event.callId,
|
|
17154
|
+
state?.operationName === "streamText" ? "doStream" : "doGenerate",
|
|
17155
|
+
"llm" /* LLM */,
|
|
17156
|
+
{
|
|
17157
|
+
...shouldRecordInputs(event) ? {
|
|
17158
|
+
input: processAISDKCallInput(
|
|
17159
|
+
operationInput(
|
|
17160
|
+
event,
|
|
17161
|
+
state?.operationName ?? "generateText"
|
|
17162
|
+
)
|
|
17163
|
+
).input
|
|
17164
|
+
} : {},
|
|
17165
|
+
metadata: metadataFromEvent(event)
|
|
17166
|
+
}
|
|
17167
|
+
);
|
|
17168
|
+
const spans = modelSpans.get(event.callId) ?? [];
|
|
17169
|
+
spans.push(span);
|
|
17170
|
+
modelSpans.set(event.callId, spans);
|
|
17171
|
+
});
|
|
17172
|
+
},
|
|
17173
|
+
onLanguageModelCallEnd(event) {
|
|
17174
|
+
runSafely("onLanguageModelCallEnd", () => {
|
|
17175
|
+
const span = shiftModelSpan(modelSpans, event.callId);
|
|
17176
|
+
if (!span) {
|
|
17177
|
+
return;
|
|
17178
|
+
}
|
|
17179
|
+
const result = {
|
|
17180
|
+
...event,
|
|
17181
|
+
response: event.responseId ? { id: event.responseId } : void 0
|
|
17182
|
+
};
|
|
17183
|
+
span.log({
|
|
17184
|
+
...shouldRecordOutputs(event) ? {
|
|
17185
|
+
output: processAISDKOutput(result, DEFAULT_DENY_OUTPUT_PATHS)
|
|
17186
|
+
} : {},
|
|
17187
|
+
metrics: extractTokenMetrics(result)
|
|
17188
|
+
});
|
|
17189
|
+
span.end();
|
|
17190
|
+
});
|
|
17191
|
+
},
|
|
17192
|
+
onObjectStepStart(event) {
|
|
17193
|
+
runSafely("onObjectStepStart", () => {
|
|
17194
|
+
const state = operations.get(event.callId);
|
|
17195
|
+
const openSpan = objectSpans.get(event.callId);
|
|
17196
|
+
if (openSpan) {
|
|
17197
|
+
openSpan.end();
|
|
17198
|
+
objectSpans.delete(event.callId);
|
|
17199
|
+
}
|
|
17200
|
+
const span = startChildSpan(
|
|
17201
|
+
event.callId,
|
|
17202
|
+
state?.operationName === "streamObject" ? "doStream" : "doGenerate",
|
|
17203
|
+
"llm" /* LLM */,
|
|
17204
|
+
{
|
|
17205
|
+
...shouldRecordInputs(event) ? {
|
|
17206
|
+
input: {
|
|
17207
|
+
prompt: event.promptMessages
|
|
17208
|
+
}
|
|
17209
|
+
} : {},
|
|
17210
|
+
metadata: metadataFromEvent(event)
|
|
17211
|
+
}
|
|
17212
|
+
);
|
|
17213
|
+
objectSpans.set(event.callId, span);
|
|
17214
|
+
});
|
|
17215
|
+
},
|
|
17216
|
+
onObjectStepFinish(event) {
|
|
17217
|
+
runSafely("onObjectStepFinish", () => {
|
|
17218
|
+
const span = objectSpans.get(event.callId);
|
|
17219
|
+
if (!span) {
|
|
17220
|
+
return;
|
|
17221
|
+
}
|
|
17222
|
+
const result = {
|
|
17223
|
+
...event,
|
|
17224
|
+
text: event.objectText
|
|
17225
|
+
};
|
|
17226
|
+
span.log({
|
|
17227
|
+
...shouldRecordOutputs(event) ? {
|
|
17228
|
+
output: processAISDKOutput(result, DEFAULT_DENY_OUTPUT_PATHS)
|
|
17229
|
+
} : {},
|
|
17230
|
+
metrics: extractTokenMetrics(result)
|
|
17231
|
+
});
|
|
17232
|
+
span.end();
|
|
17233
|
+
objectSpans.delete(event.callId);
|
|
17234
|
+
});
|
|
17235
|
+
},
|
|
17236
|
+
onEmbedStart(event) {
|
|
17237
|
+
runSafely("onEmbedStart", () => {
|
|
17238
|
+
const state = operations.get(event.callId);
|
|
17239
|
+
for (const [embedCallId, embedState] of embedSpans) {
|
|
17240
|
+
if (embedState.callId === event.callId && (state?.operationName === "embed" || embedState.values === event.values)) {
|
|
17241
|
+
embedState.span.end();
|
|
17242
|
+
embedSpans.delete(embedCallId);
|
|
17243
|
+
}
|
|
17244
|
+
}
|
|
17245
|
+
const span = startChildSpan(
|
|
17246
|
+
event.callId,
|
|
17247
|
+
"doEmbed",
|
|
17248
|
+
"llm" /* LLM */,
|
|
17249
|
+
{
|
|
17250
|
+
...shouldRecordInputs(event) ? {
|
|
17251
|
+
input: {
|
|
17252
|
+
values: event.values
|
|
17253
|
+
}
|
|
17254
|
+
} : {},
|
|
17255
|
+
metadata: metadataFromEvent(event)
|
|
17256
|
+
}
|
|
17257
|
+
);
|
|
17258
|
+
embedSpans.set(event.embedCallId, {
|
|
17259
|
+
callId: event.callId,
|
|
17260
|
+
span,
|
|
17261
|
+
values: event.values
|
|
17262
|
+
});
|
|
17263
|
+
});
|
|
17264
|
+
},
|
|
17265
|
+
onEmbedFinish(event) {
|
|
17266
|
+
runSafely("onEmbedFinish", () => {
|
|
17267
|
+
const state = embedSpans.get(event.embedCallId);
|
|
17268
|
+
if (!state) {
|
|
17269
|
+
return;
|
|
17270
|
+
}
|
|
17271
|
+
const result = {
|
|
17272
|
+
...event,
|
|
17273
|
+
embeddings: event.embeddings
|
|
17274
|
+
};
|
|
17275
|
+
state.span.log({
|
|
17276
|
+
...shouldRecordOutputs(event) ? {
|
|
17277
|
+
output: processAISDKEmbeddingOutput(
|
|
17278
|
+
result,
|
|
17279
|
+
DEFAULT_DENY_OUTPUT_PATHS
|
|
17280
|
+
)
|
|
17281
|
+
} : {},
|
|
17282
|
+
metrics: extractTokenMetrics(result)
|
|
17283
|
+
});
|
|
17284
|
+
state.span.end();
|
|
17285
|
+
embedSpans.delete(event.embedCallId);
|
|
17286
|
+
});
|
|
17287
|
+
},
|
|
17288
|
+
onRerankStart(event) {
|
|
17289
|
+
runSafely("onRerankStart", () => {
|
|
17290
|
+
const openSpan = rerankSpans.get(event.callId);
|
|
17291
|
+
if (openSpan) {
|
|
17292
|
+
openSpan.end();
|
|
17293
|
+
rerankSpans.delete(event.callId);
|
|
17294
|
+
}
|
|
17295
|
+
const span = startChildSpan(
|
|
17296
|
+
event.callId,
|
|
17297
|
+
"doRerank",
|
|
17298
|
+
"llm" /* LLM */,
|
|
17299
|
+
{
|
|
17300
|
+
...shouldRecordInputs(event) ? {
|
|
17301
|
+
input: {
|
|
17302
|
+
documents: event.documents,
|
|
17303
|
+
query: event.query,
|
|
17304
|
+
topN: event.topN
|
|
17305
|
+
}
|
|
17306
|
+
} : {},
|
|
17307
|
+
metadata: metadataFromEvent(event)
|
|
17308
|
+
}
|
|
17309
|
+
);
|
|
17310
|
+
rerankSpans.set(event.callId, span);
|
|
17311
|
+
});
|
|
17312
|
+
},
|
|
17313
|
+
onRerankFinish(event) {
|
|
17314
|
+
runSafely("onRerankFinish", () => {
|
|
17315
|
+
const span = rerankSpans.get(event.callId);
|
|
17316
|
+
if (!span) {
|
|
17317
|
+
return;
|
|
17318
|
+
}
|
|
17319
|
+
const result = {
|
|
17320
|
+
ranking: event.ranking?.map((entry) => ({
|
|
17321
|
+
originalIndex: entry.index,
|
|
17322
|
+
score: entry.relevanceScore
|
|
17323
|
+
}))
|
|
17324
|
+
};
|
|
17325
|
+
span.log({
|
|
17326
|
+
...shouldRecordOutputs(event) ? {
|
|
17327
|
+
output: processAISDKRerankOutput(
|
|
17328
|
+
result,
|
|
17329
|
+
DEFAULT_DENY_OUTPUT_PATHS
|
|
17330
|
+
)
|
|
17331
|
+
} : {}
|
|
17332
|
+
});
|
|
17333
|
+
span.end();
|
|
17334
|
+
rerankSpans.delete(event.callId);
|
|
17335
|
+
});
|
|
17336
|
+
},
|
|
17337
|
+
onToolExecutionStart(event) {
|
|
17338
|
+
runSafely("onToolExecutionStart", () => {
|
|
17339
|
+
const toolCallId = event.toolCall.toolCallId;
|
|
17340
|
+
if (!toolCallId) {
|
|
17341
|
+
return;
|
|
17342
|
+
}
|
|
17343
|
+
const span = startChildSpan(
|
|
17344
|
+
event.callId,
|
|
17345
|
+
event.toolCall.toolName || "tool",
|
|
17346
|
+
"tool" /* TOOL */,
|
|
17347
|
+
{
|
|
17348
|
+
...shouldRecordInputs(event) ? {
|
|
17349
|
+
input: event.toolCall.input
|
|
17350
|
+
} : {},
|
|
17351
|
+
metadata: {
|
|
17352
|
+
...createAISDKIntegrationMetadata(),
|
|
17353
|
+
toolCallId,
|
|
17354
|
+
...typeof event.toolCall.toolName === "string" ? { toolName: event.toolCall.toolName } : {}
|
|
17355
|
+
}
|
|
17356
|
+
}
|
|
17357
|
+
);
|
|
17358
|
+
toolSpans.set(toolCallId, { callId: event.callId, span });
|
|
17359
|
+
});
|
|
17360
|
+
},
|
|
17361
|
+
onToolExecutionEnd(event) {
|
|
17362
|
+
runSafely("onToolExecutionEnd", () => {
|
|
17363
|
+
const toolCallId = event.toolCall.toolCallId;
|
|
17364
|
+
const state = toolCallId ? toolSpans.get(toolCallId) : void 0;
|
|
17365
|
+
if (!toolCallId || !state) {
|
|
17366
|
+
return;
|
|
17367
|
+
}
|
|
17368
|
+
const toolOutput = event.toolOutput;
|
|
17369
|
+
if (toolOutput?.type === "tool-error") {
|
|
17370
|
+
state.span.log({
|
|
17371
|
+
error: toolOutput.error instanceof Error ? toolOutput.error.message : String(toolOutput?.error),
|
|
17372
|
+
metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } : {}
|
|
17373
|
+
});
|
|
17374
|
+
} else {
|
|
17375
|
+
state.span.log({
|
|
17376
|
+
...shouldRecordOutputs(event) ? { output: toolOutput?.output } : {},
|
|
17377
|
+
metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } : {}
|
|
17378
|
+
});
|
|
17379
|
+
}
|
|
17380
|
+
state.span.end();
|
|
17381
|
+
toolSpans.delete(toolCallId);
|
|
17382
|
+
});
|
|
17383
|
+
},
|
|
17384
|
+
onChunk(event) {
|
|
17385
|
+
runSafely("onChunk", () => {
|
|
17386
|
+
const callId = event.chunk?.callId;
|
|
17387
|
+
if (!callId) {
|
|
17388
|
+
return;
|
|
17389
|
+
}
|
|
17390
|
+
const state = operations.get(callId);
|
|
17391
|
+
if (!state || state.firstChunkTime !== void 0) {
|
|
17392
|
+
return;
|
|
17393
|
+
}
|
|
17394
|
+
state.firstChunkTime = getCurrentUnixTimestamp();
|
|
17395
|
+
});
|
|
17396
|
+
},
|
|
17397
|
+
onFinish(event) {
|
|
17398
|
+
runSafely("onFinish", () => {
|
|
17399
|
+
const state = operations.get(event.callId);
|
|
17400
|
+
if (!state) {
|
|
17401
|
+
return;
|
|
17402
|
+
}
|
|
17403
|
+
const result = finishResult(event, state.operationName);
|
|
17404
|
+
const metrics = state.hadModelChild ? {} : extractTokenMetrics(result);
|
|
17405
|
+
if (state.firstChunkTime !== void 0) {
|
|
17406
|
+
metrics.time_to_first_token = state.firstChunkTime - state.startTime;
|
|
17407
|
+
}
|
|
17408
|
+
state.span.log({
|
|
17409
|
+
...shouldRecordOutputs(event) ? {
|
|
17410
|
+
output: finishOutput(result, state.operationName)
|
|
17411
|
+
} : {},
|
|
17412
|
+
metrics
|
|
17413
|
+
});
|
|
17414
|
+
state.span.end();
|
|
17415
|
+
operations.delete(event.callId);
|
|
17416
|
+
});
|
|
17417
|
+
},
|
|
17418
|
+
onError(event) {
|
|
17419
|
+
runSafely("onError", () => {
|
|
17420
|
+
const errorEvent = isObject(event) ? event : {};
|
|
17421
|
+
const callId = typeof errorEvent.callId === "string" ? errorEvent.callId : void 0;
|
|
17422
|
+
if (!callId) {
|
|
17423
|
+
return;
|
|
17424
|
+
}
|
|
17425
|
+
const state = operations.get(callId);
|
|
17426
|
+
if (!state) {
|
|
17427
|
+
return;
|
|
17428
|
+
}
|
|
17429
|
+
const error2 = errorEvent.error ?? event;
|
|
17430
|
+
const openModelSpans = modelSpans.get(callId);
|
|
17431
|
+
if (openModelSpans) {
|
|
17432
|
+
for (const span of openModelSpans) {
|
|
17433
|
+
logError(span, error2);
|
|
17434
|
+
span.end();
|
|
17435
|
+
}
|
|
17436
|
+
modelSpans.delete(callId);
|
|
17437
|
+
}
|
|
17438
|
+
const openObjectSpan = objectSpans.get(callId);
|
|
17439
|
+
if (openObjectSpan) {
|
|
17440
|
+
logError(openObjectSpan, error2);
|
|
17441
|
+
openObjectSpan.end();
|
|
17442
|
+
objectSpans.delete(callId);
|
|
17443
|
+
}
|
|
17444
|
+
for (const [embedCallId, embedState] of embedSpans) {
|
|
17445
|
+
if (embedState.callId === callId) {
|
|
17446
|
+
logError(embedState.span, error2);
|
|
17447
|
+
embedState.span.end();
|
|
17448
|
+
embedSpans.delete(embedCallId);
|
|
17449
|
+
}
|
|
17450
|
+
}
|
|
17451
|
+
const openRerankSpan = rerankSpans.get(callId);
|
|
17452
|
+
if (openRerankSpan) {
|
|
17453
|
+
logError(openRerankSpan, error2);
|
|
17454
|
+
openRerankSpan.end();
|
|
17455
|
+
rerankSpans.delete(callId);
|
|
17456
|
+
}
|
|
17457
|
+
for (const [toolCallId, toolState] of toolSpans) {
|
|
17458
|
+
if (toolState.callId === callId) {
|
|
17459
|
+
logError(toolState.span, error2);
|
|
17460
|
+
toolState.span.end();
|
|
17461
|
+
toolSpans.delete(toolCallId);
|
|
17462
|
+
}
|
|
17463
|
+
}
|
|
17464
|
+
logError(state.span, error2);
|
|
17465
|
+
state.span.end();
|
|
17466
|
+
operations.delete(callId);
|
|
17467
|
+
});
|
|
17468
|
+
},
|
|
17469
|
+
executeTool({ toolCallId, execute }) {
|
|
17470
|
+
const state = toolSpans.get(toolCallId);
|
|
17471
|
+
return state ? withCurrent(state.span, () => execute()) : execute();
|
|
17472
|
+
}
|
|
17473
|
+
};
|
|
17474
|
+
}
|
|
17475
|
+
function shouldRecordInputs(event) {
|
|
17476
|
+
return event.recordInputs !== false;
|
|
17477
|
+
}
|
|
17478
|
+
function shouldRecordOutputs(event) {
|
|
17479
|
+
return event.recordOutputs !== false;
|
|
17480
|
+
}
|
|
17481
|
+
function operationNameFromId(operationId) {
|
|
17482
|
+
return operationId?.startsWith("ai.") ? operationId.slice("ai.".length) : operationId || "ai-sdk";
|
|
17483
|
+
}
|
|
17484
|
+
function modelFromEvent(event) {
|
|
17485
|
+
return event.modelId ? {
|
|
17486
|
+
modelId: event.modelId,
|
|
17487
|
+
...event.provider ? { provider: event.provider } : {}
|
|
17488
|
+
} : void 0;
|
|
17489
|
+
}
|
|
17490
|
+
function metadataFromEvent(event) {
|
|
17491
|
+
const metadata = createAISDKIntegrationMetadata();
|
|
17492
|
+
const { model, provider } = serializeModelWithProvider(modelFromEvent(event));
|
|
17493
|
+
if (model) {
|
|
17494
|
+
metadata.model = model;
|
|
17495
|
+
}
|
|
17496
|
+
if (provider) {
|
|
17497
|
+
metadata.provider = provider;
|
|
17498
|
+
}
|
|
17499
|
+
if (typeof event.functionId === "string") {
|
|
17500
|
+
metadata.functionId = event.functionId;
|
|
17501
|
+
}
|
|
17502
|
+
return metadata;
|
|
17503
|
+
}
|
|
17504
|
+
function operationInput(event, operationName) {
|
|
17505
|
+
if (operationName === "embed") {
|
|
17506
|
+
return {
|
|
17507
|
+
model: modelFromEvent(event),
|
|
17508
|
+
value: event.value
|
|
17509
|
+
};
|
|
17510
|
+
}
|
|
17511
|
+
if (operationName === "embedMany") {
|
|
17512
|
+
return {
|
|
17513
|
+
model: modelFromEvent(event),
|
|
17514
|
+
values: Array.isArray(event.value) ? event.value ?? [] : void 0
|
|
17515
|
+
};
|
|
17516
|
+
}
|
|
17517
|
+
if (operationName === "rerank") {
|
|
17518
|
+
return {
|
|
17519
|
+
model: modelFromEvent(event),
|
|
17520
|
+
documents: event.documents,
|
|
17521
|
+
query: event.query,
|
|
17522
|
+
topN: event.topN
|
|
17523
|
+
};
|
|
17524
|
+
}
|
|
17525
|
+
return {
|
|
17526
|
+
model: modelFromEvent(event),
|
|
17527
|
+
system: event.system,
|
|
17528
|
+
prompt: event.prompt,
|
|
17529
|
+
messages: event.messages,
|
|
17530
|
+
tools: event.tools,
|
|
17531
|
+
toolChoice: event.toolChoice,
|
|
17532
|
+
activeTools: event.activeTools,
|
|
17533
|
+
output: event.output,
|
|
17534
|
+
schema: event.schema,
|
|
17535
|
+
schemaName: event.schemaName,
|
|
17536
|
+
schemaDescription: event.schemaDescription,
|
|
17537
|
+
maxOutputTokens: event.maxOutputTokens,
|
|
17538
|
+
temperature: event.temperature,
|
|
17539
|
+
topP: event.topP,
|
|
17540
|
+
topK: event.topK,
|
|
17541
|
+
presencePenalty: event.presencePenalty,
|
|
17542
|
+
frequencyPenalty: event.frequencyPenalty,
|
|
17543
|
+
seed: event.seed,
|
|
17544
|
+
maxRetries: event.maxRetries,
|
|
17545
|
+
headers: event.headers,
|
|
17546
|
+
providerOptions: event.providerOptions
|
|
17547
|
+
};
|
|
17548
|
+
}
|
|
17549
|
+
function shiftModelSpan(modelSpans, callId) {
|
|
17550
|
+
const spans = modelSpans.get(callId);
|
|
17551
|
+
const span = spans?.shift();
|
|
17552
|
+
if (spans && spans.length === 0) {
|
|
17553
|
+
modelSpans.delete(callId);
|
|
17554
|
+
}
|
|
17555
|
+
return span;
|
|
17556
|
+
}
|
|
17557
|
+
function finishResult(event, operationName) {
|
|
17558
|
+
if (operationName === "embed") {
|
|
17559
|
+
return {
|
|
17560
|
+
...event,
|
|
17561
|
+
embedding: event.embedding
|
|
17562
|
+
};
|
|
17563
|
+
}
|
|
17564
|
+
if (operationName === "embedMany") {
|
|
17565
|
+
return {
|
|
17566
|
+
...event,
|
|
17567
|
+
embeddings: event.embedding
|
|
17568
|
+
};
|
|
17569
|
+
}
|
|
17570
|
+
if (operationName === "rerank") {
|
|
17571
|
+
return event;
|
|
17572
|
+
}
|
|
17573
|
+
return event;
|
|
17574
|
+
}
|
|
17575
|
+
function finishOutput(result, operationName) {
|
|
17576
|
+
if (operationName === "embed" || operationName === "embedMany") {
|
|
17577
|
+
return processAISDKEmbeddingOutput(
|
|
17578
|
+
result,
|
|
17579
|
+
DEFAULT_DENY_OUTPUT_PATHS
|
|
17580
|
+
);
|
|
17581
|
+
}
|
|
17582
|
+
if (operationName === "rerank") {
|
|
17583
|
+
return processAISDKRerankOutput(
|
|
17584
|
+
result,
|
|
17585
|
+
DEFAULT_DENY_OUTPUT_PATHS
|
|
17586
|
+
);
|
|
17587
|
+
}
|
|
17588
|
+
return processAISDKOutput(result, DEFAULT_DENY_OUTPUT_PATHS);
|
|
17589
|
+
}
|
|
17590
|
+
|
|
16944
17591
|
// src/instrumentation/plugins/ai-sdk-channels.ts
|
|
16945
17592
|
var aiSDKChannels = defineChannels("ai", {
|
|
16946
17593
|
generateText: channel({
|
|
@@ -17000,6 +17647,10 @@ var aiSDKChannels = defineChannels("ai", {
|
|
|
17000
17647
|
toolLoopAgentStream: channel({
|
|
17001
17648
|
channelName: "ToolLoopAgent.stream",
|
|
17002
17649
|
kind: "async"
|
|
17650
|
+
}),
|
|
17651
|
+
v7CreateTelemetryDispatcher: channel({
|
|
17652
|
+
channelName: "createTelemetryDispatcher",
|
|
17653
|
+
kind: "sync-stream"
|
|
17003
17654
|
})
|
|
17004
17655
|
});
|
|
17005
17656
|
|
|
@@ -17020,9 +17671,30 @@ var DEFAULT_DENY_OUTPUT_PATHS = [
|
|
|
17020
17671
|
];
|
|
17021
17672
|
var AUTO_PATCHED_MODEL = /* @__PURE__ */ Symbol.for("braintrust.ai-sdk.auto-patched-model");
|
|
17022
17673
|
var AUTO_PATCHED_TOOL = /* @__PURE__ */ Symbol.for("braintrust.ai-sdk.auto-patched-tool");
|
|
17674
|
+
var AUTO_PATCHED_V7_TELEMETRY_DISPATCHER = /* @__PURE__ */ Symbol.for(
|
|
17675
|
+
"braintrust.ai-sdk.v7.auto-patched-telemetry-dispatcher"
|
|
17676
|
+
);
|
|
17023
17677
|
var RUNTIME_DENY_OUTPUT_PATHS = /* @__PURE__ */ Symbol.for(
|
|
17024
17678
|
"braintrust.ai-sdk.deny-output-paths"
|
|
17025
17679
|
);
|
|
17680
|
+
var AI_SDK_V7_TELEMETRY_CALLBACKS = [
|
|
17681
|
+
"onStart",
|
|
17682
|
+
"onStepStart",
|
|
17683
|
+
"onLanguageModelCallStart",
|
|
17684
|
+
"onLanguageModelCallEnd",
|
|
17685
|
+
"onToolExecutionStart",
|
|
17686
|
+
"onToolExecutionEnd",
|
|
17687
|
+
"onChunk",
|
|
17688
|
+
"onStepFinish",
|
|
17689
|
+
"onObjectStepStart",
|
|
17690
|
+
"onObjectStepFinish",
|
|
17691
|
+
"onEmbedStart",
|
|
17692
|
+
"onEmbedFinish",
|
|
17693
|
+
"onRerankStart",
|
|
17694
|
+
"onRerankFinish",
|
|
17695
|
+
"onFinish",
|
|
17696
|
+
"onError"
|
|
17697
|
+
];
|
|
17026
17698
|
var AISDKPlugin = class extends BasePlugin {
|
|
17027
17699
|
config;
|
|
17028
17700
|
constructor(config3 = {}) {
|
|
@@ -17037,6 +17709,7 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
17037
17709
|
}
|
|
17038
17710
|
subscribeToAISDK() {
|
|
17039
17711
|
const denyOutputPaths = this.config.denyOutputPaths || DEFAULT_DENY_OUTPUT_PATHS;
|
|
17712
|
+
this.unsubscribers.push(subscribeToAISDKV7TelemetryDispatcher());
|
|
17040
17713
|
this.unsubscribers.push(
|
|
17041
17714
|
traceStreamingChannel(aiSDKChannels.generateText, {
|
|
17042
17715
|
name: "generateText",
|
|
@@ -17261,9 +17934,60 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
17261
17934
|
);
|
|
17262
17935
|
}
|
|
17263
17936
|
};
|
|
17264
|
-
function
|
|
17265
|
-
|
|
17266
|
-
|
|
17937
|
+
function subscribeToAISDKV7TelemetryDispatcher() {
|
|
17938
|
+
const channel2 = aiSDKChannels.v7CreateTelemetryDispatcher.tracingChannel();
|
|
17939
|
+
const telemetry = braintrustAISDKTelemetry();
|
|
17940
|
+
const handlers = {
|
|
17941
|
+
end: (event) => {
|
|
17942
|
+
const telemetryOptions = event.arguments?.[0]?.telemetry;
|
|
17943
|
+
if (telemetryOptions?.isEnabled === false) {
|
|
17944
|
+
return;
|
|
17945
|
+
}
|
|
17946
|
+
patchAISDKV7TelemetryDispatcher(event.result, telemetry);
|
|
17947
|
+
}
|
|
17948
|
+
};
|
|
17949
|
+
channel2.subscribe(handlers);
|
|
17950
|
+
return () => {
|
|
17951
|
+
channel2.unsubscribe(handlers);
|
|
17952
|
+
};
|
|
17953
|
+
}
|
|
17954
|
+
function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry) {
|
|
17955
|
+
if (!isObject(dispatcher)) {
|
|
17956
|
+
return;
|
|
17957
|
+
}
|
|
17958
|
+
const dispatcherRecord = dispatcher;
|
|
17959
|
+
if (dispatcherRecord[AUTO_PATCHED_V7_TELEMETRY_DISPATCHER]) {
|
|
17960
|
+
return;
|
|
17961
|
+
}
|
|
17962
|
+
dispatcherRecord[AUTO_PATCHED_V7_TELEMETRY_DISPATCHER] = true;
|
|
17963
|
+
for (const key of AI_SDK_V7_TELEMETRY_CALLBACKS) {
|
|
17964
|
+
const braintrustCallback = telemetry[key];
|
|
17965
|
+
if (typeof braintrustCallback !== "function") {
|
|
17966
|
+
continue;
|
|
17967
|
+
}
|
|
17968
|
+
const existingCallback = dispatcherRecord[key];
|
|
17969
|
+
dispatcherRecord[key] = (event) => {
|
|
17970
|
+
const existingResult = typeof existingCallback === "function" ? existingCallback.call(dispatcher, event) : void 0;
|
|
17971
|
+
const braintrustResult = braintrustCallback.call(telemetry, event);
|
|
17972
|
+
const pending = [existingResult, braintrustResult].filter(isPromiseLike);
|
|
17973
|
+
if (pending.length > 0) {
|
|
17974
|
+
return Promise.allSettled(pending).then(() => void 0);
|
|
17975
|
+
}
|
|
17976
|
+
};
|
|
17977
|
+
}
|
|
17978
|
+
const braintrustExecuteTool = telemetry.executeTool;
|
|
17979
|
+
if (typeof braintrustExecuteTool !== "function") {
|
|
17980
|
+
return;
|
|
17981
|
+
}
|
|
17982
|
+
const existingExecuteTool = dispatcherRecord.executeTool;
|
|
17983
|
+
dispatcherRecord.executeTool = (args) => braintrustExecuteTool.call(telemetry, {
|
|
17984
|
+
...args,
|
|
17985
|
+
execute: () => typeof existingExecuteTool === "function" ? existingExecuteTool.call(dispatcher, args) : args.execute()
|
|
17986
|
+
});
|
|
17987
|
+
}
|
|
17988
|
+
function resolveDenyOutputPaths(event, defaultDenyOutputPaths) {
|
|
17989
|
+
if (Array.isArray(event?.denyOutputPaths)) {
|
|
17990
|
+
return event.denyOutputPaths;
|
|
17267
17991
|
}
|
|
17268
17992
|
const firstArgument2 = event?.arguments && event.arguments.length > 0 ? event.arguments[0] : void 0;
|
|
17269
17993
|
if (!firstArgument2 || typeof firstArgument2 !== "object") {
|
|
@@ -17712,11 +18436,11 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
|
|
|
17712
18436
|
metadata: baseMetadata
|
|
17713
18437
|
}
|
|
17714
18438
|
});
|
|
18439
|
+
const streamStartTime = getCurrentUnixTimestamp();
|
|
17715
18440
|
const result = await withCurrent(
|
|
17716
18441
|
span,
|
|
17717
18442
|
() => Reflect.apply(originalDoStream, resolvedModel, [options])
|
|
17718
18443
|
);
|
|
17719
|
-
const streamStartTime = getCurrentUnixTimestamp();
|
|
17720
18444
|
let firstChunkTime;
|
|
17721
18445
|
const output = {};
|
|
17722
18446
|
let text = "";
|
|
@@ -17725,7 +18449,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
|
|
|
17725
18449
|
let object = void 0;
|
|
17726
18450
|
const transformStream = new TransformStream({
|
|
17727
18451
|
transform(chunk, controller) {
|
|
17728
|
-
if (firstChunkTime === void 0) {
|
|
18452
|
+
if (firstChunkTime === void 0 && isAISDKContentStreamChunk(chunk)) {
|
|
17729
18453
|
firstChunkTime = getCurrentUnixTimestamp();
|
|
17730
18454
|
}
|
|
17731
18455
|
switch (chunk.type) {
|
|
@@ -17917,6 +18641,78 @@ function finalizeAISDKChildTracing(event) {
|
|
|
17917
18641
|
delete event.__braintrust_ai_sdk_cleanup;
|
|
17918
18642
|
}
|
|
17919
18643
|
}
|
|
18644
|
+
function extractAISDKStreamPart(chunk) {
|
|
18645
|
+
if (!isObject(chunk) || !isObject(chunk.part)) {
|
|
18646
|
+
return chunk;
|
|
18647
|
+
}
|
|
18648
|
+
return chunk.part;
|
|
18649
|
+
}
|
|
18650
|
+
function stringContent(value) {
|
|
18651
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
18652
|
+
}
|
|
18653
|
+
function rawValueHasAISDKContent(value) {
|
|
18654
|
+
if (value === void 0 || value === null) {
|
|
18655
|
+
return false;
|
|
18656
|
+
}
|
|
18657
|
+
if (typeof value === "string") {
|
|
18658
|
+
return value.length > 0;
|
|
18659
|
+
}
|
|
18660
|
+
if (!isObject(value)) {
|
|
18661
|
+
return true;
|
|
18662
|
+
}
|
|
18663
|
+
const delta = value.delta;
|
|
18664
|
+
if (stringContent(value.content) || stringContent(value.text) || stringContent(value.delta) || stringContent(value.arguments) || stringContent(value.partial_json) || isObject(delta) && (stringContent(delta.content) || stringContent(delta.text) || stringContent(delta.arguments) || stringContent(delta.partial_json) || stringContent(delta.thinking)) || Array.isArray(value.choices) && value.choices.some((choice) => {
|
|
18665
|
+
if (!isObject(choice) || !isObject(choice.delta)) {
|
|
18666
|
+
return false;
|
|
18667
|
+
}
|
|
18668
|
+
const choiceDelta = choice.delta;
|
|
18669
|
+
if (stringContent(choiceDelta.content) || stringContent(choiceDelta.text)) {
|
|
18670
|
+
return true;
|
|
18671
|
+
}
|
|
18672
|
+
if (isObject(choiceDelta.function_call) && stringContent(choiceDelta.function_call.arguments)) {
|
|
18673
|
+
return true;
|
|
18674
|
+
}
|
|
18675
|
+
return Array.isArray(choiceDelta.tool_calls) && choiceDelta.tool_calls.some(
|
|
18676
|
+
(toolCall) => isObject(toolCall) && isObject(toolCall.function) && stringContent(toolCall.function.arguments)
|
|
18677
|
+
);
|
|
18678
|
+
})) {
|
|
18679
|
+
return true;
|
|
18680
|
+
}
|
|
18681
|
+
return false;
|
|
18682
|
+
}
|
|
18683
|
+
function isAISDKContentStreamChunk(chunk) {
|
|
18684
|
+
const part = extractAISDKStreamPart(chunk);
|
|
18685
|
+
if (typeof part === "string") {
|
|
18686
|
+
return part.length > 0;
|
|
18687
|
+
}
|
|
18688
|
+
if (!isObject(part) || typeof part.type !== "string") {
|
|
18689
|
+
return false;
|
|
18690
|
+
}
|
|
18691
|
+
switch (part.type) {
|
|
18692
|
+
case "text-delta":
|
|
18693
|
+
return stringContent(part.textDelta) !== void 0 || stringContent(part.delta) !== void 0 || stringContent(part.text) !== void 0 || stringContent(part.content) !== void 0;
|
|
18694
|
+
case "reasoning-delta":
|
|
18695
|
+
return stringContent(part.delta) !== void 0 || stringContent(part.text) !== void 0 || stringContent(part.content) !== void 0;
|
|
18696
|
+
case "tool-call":
|
|
18697
|
+
case "object":
|
|
18698
|
+
case "file":
|
|
18699
|
+
return true;
|
|
18700
|
+
case "tool-input-delta":
|
|
18701
|
+
case "tool-call-delta":
|
|
18702
|
+
return stringContent(part.argsTextDelta) !== void 0 || stringContent(part.inputTextDelta) !== void 0 || stringContent(part.delta) !== void 0 || stringContent(part.text) !== void 0 || stringContent(part.content) !== void 0;
|
|
18703
|
+
case "raw":
|
|
18704
|
+
return rawValueHasAISDKContent(part.rawValue);
|
|
18705
|
+
default:
|
|
18706
|
+
return false;
|
|
18707
|
+
}
|
|
18708
|
+
}
|
|
18709
|
+
function isAISDKContentAsyncIterableChunk(chunk) {
|
|
18710
|
+
if (isAISDKContentStreamChunk(chunk)) {
|
|
18711
|
+
return true;
|
|
18712
|
+
}
|
|
18713
|
+
const part = extractAISDKStreamPart(chunk);
|
|
18714
|
+
return isObject(part) && typeof part.type !== "string";
|
|
18715
|
+
}
|
|
17920
18716
|
function patchAISDKStreamingResult(args) {
|
|
17921
18717
|
const { defaultDenyOutputPaths, endEvent, result, span, startTime } = args;
|
|
17922
18718
|
if (!result || typeof result !== "object") {
|
|
@@ -17929,7 +18725,7 @@ function patchAISDKStreamingResult(args) {
|
|
|
17929
18725
|
const wrappedBaseStream = resultRecord.baseStream.pipeThrough(
|
|
17930
18726
|
new TransformStream({
|
|
17931
18727
|
transform(chunk, controller) {
|
|
17932
|
-
if (firstChunkTime2 === void 0) {
|
|
18728
|
+
if (firstChunkTime2 === void 0 && isAISDKContentStreamChunk(chunk)) {
|
|
17933
18729
|
firstChunkTime2 = getCurrentUnixTimestamp();
|
|
17934
18730
|
}
|
|
17935
18731
|
controller.enqueue(chunk);
|
|
@@ -17973,8 +18769,8 @@ function patchAISDKStreamingResult(args) {
|
|
|
17973
18769
|
}
|
|
17974
18770
|
let firstChunkTime;
|
|
17975
18771
|
const wrappedStream = createPatchedAsyncIterable(streamField.stream, {
|
|
17976
|
-
onChunk: () => {
|
|
17977
|
-
if (firstChunkTime === void 0) {
|
|
18772
|
+
onChunk: (chunk) => {
|
|
18773
|
+
if (firstChunkTime === void 0 && isAISDKContentAsyncIterableChunk(chunk)) {
|
|
17978
18774
|
firstChunkTime = getCurrentUnixTimestamp();
|
|
17979
18775
|
}
|
|
17980
18776
|
},
|
|
@@ -18946,15 +19742,17 @@ function collectLocalMcpServerToolHookNames(serverName, serverConfig) {
|
|
|
18946
19742
|
|
|
18947
19743
|
// src/instrumentation/plugins/claude-agent-sdk-plugin.ts
|
|
18948
19744
|
var ROOT_LLM_PARENT_KEY = "__root__";
|
|
19745
|
+
var SUB_AGENT_PROMPT_SOURCE_PRIORITY = {
|
|
19746
|
+
delegation: 0,
|
|
19747
|
+
lifecycle: 1,
|
|
19748
|
+
sidechain: 2
|
|
19749
|
+
};
|
|
18949
19750
|
function llmParentKey(parentToolUseId) {
|
|
18950
19751
|
return parentToolUseId ?? ROOT_LLM_PARENT_KEY;
|
|
18951
19752
|
}
|
|
18952
19753
|
function isSubAgentDelegationToolName(toolName) {
|
|
18953
19754
|
return toolName === "Agent" || toolName === "Task";
|
|
18954
19755
|
}
|
|
18955
|
-
function shouldParentToolAsTaskSibling(toolName) {
|
|
18956
|
-
return toolName === "Agent" || toolName === "Task" || toolName === "Bash";
|
|
18957
|
-
}
|
|
18958
19756
|
function filterSerializableOptions(options) {
|
|
18959
19757
|
const allowedKeys = [
|
|
18960
19758
|
"model",
|
|
@@ -19091,26 +19889,39 @@ function extractUsageFromMessage(message) {
|
|
|
19091
19889
|
}
|
|
19092
19890
|
return metrics;
|
|
19093
19891
|
}
|
|
19094
|
-
function buildLLMInput(
|
|
19095
|
-
const promptMessages = [];
|
|
19096
|
-
if (typeof prompt === "string") {
|
|
19097
|
-
promptMessages.push({ content: prompt, role: "user" });
|
|
19098
|
-
} else if (capturedPromptMessages && capturedPromptMessages.length > 0) {
|
|
19099
|
-
for (const msg of capturedPromptMessages) {
|
|
19100
|
-
const role = msg.message?.role;
|
|
19101
|
-
const content = msg.message?.content;
|
|
19102
|
-
if (role && content !== void 0) {
|
|
19103
|
-
promptMessages.push({ content, role });
|
|
19104
|
-
}
|
|
19105
|
-
}
|
|
19106
|
-
}
|
|
19892
|
+
function buildLLMInput(promptMessages, conversationHistory) {
|
|
19107
19893
|
const inputParts = [...promptMessages, ...conversationHistory];
|
|
19108
19894
|
return inputParts.length > 0 ? inputParts : void 0;
|
|
19109
19895
|
}
|
|
19896
|
+
function conversationMessageFromSDKMessage(message) {
|
|
19897
|
+
const role = message.message?.role;
|
|
19898
|
+
const content = message.message?.content;
|
|
19899
|
+
if (role && content !== void 0) {
|
|
19900
|
+
return { content, role };
|
|
19901
|
+
}
|
|
19902
|
+
return void 0;
|
|
19903
|
+
}
|
|
19904
|
+
function messageContentHasBlockType(message, blockType) {
|
|
19905
|
+
const content = message.message?.content;
|
|
19906
|
+
return Array.isArray(content) && content.some(
|
|
19907
|
+
(block) => typeof block === "object" && block !== null && "type" in block && block.type === blockType
|
|
19908
|
+
);
|
|
19909
|
+
}
|
|
19910
|
+
function buildRootPromptMessages(prompt, capturedPromptMessages) {
|
|
19911
|
+
if (typeof prompt === "string") {
|
|
19912
|
+
return [{ content: prompt, role: "user" }];
|
|
19913
|
+
}
|
|
19914
|
+
if (!capturedPromptMessages || capturedPromptMessages.length === 0) {
|
|
19915
|
+
return [];
|
|
19916
|
+
}
|
|
19917
|
+
return capturedPromptMessages.map(conversationMessageFromSDKMessage).filter(
|
|
19918
|
+
(message) => message !== void 0
|
|
19919
|
+
);
|
|
19920
|
+
}
|
|
19110
19921
|
function formatCapturedMessages(messages) {
|
|
19111
19922
|
return messages.length > 0 ? messages : [];
|
|
19112
19923
|
}
|
|
19113
|
-
async function createLLMSpanForMessages(messages,
|
|
19924
|
+
async function createLLMSpanForMessages(messages, promptMessages, conversationHistory, options, startTime, parentSpan, existingSpan) {
|
|
19114
19925
|
if (messages.length === 0) {
|
|
19115
19926
|
return void 0;
|
|
19116
19927
|
}
|
|
@@ -19120,11 +19931,7 @@ async function createLLMSpanForMessages(messages, prompt, conversationHistory, o
|
|
|
19120
19931
|
}
|
|
19121
19932
|
const model = lastMessage.message.model || options.model;
|
|
19122
19933
|
const usage = extractUsageFromMessage(lastMessage);
|
|
19123
|
-
const input = buildLLMInput(
|
|
19124
|
-
prompt,
|
|
19125
|
-
conversationHistory,
|
|
19126
|
-
capturedPromptMessages
|
|
19127
|
-
);
|
|
19934
|
+
const input = buildLLMInput(promptMessages, conversationHistory);
|
|
19128
19935
|
const outputs = messages.map(
|
|
19129
19936
|
(m) => m.message?.content && m.message?.role ? { content: m.message.content, role: m.message.role } : void 0
|
|
19130
19937
|
).filter(
|
|
@@ -19255,8 +20062,7 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
|
|
|
19255
20062
|
},
|
|
19256
20063
|
name: parsed.displayName,
|
|
19257
20064
|
parent: await resolveParentSpan(toolUseID, {
|
|
19258
|
-
agentId: input.agent_id
|
|
19259
|
-
preferTaskSiblingParent: shouldParentToolAsTaskSibling(parsed.toolName)
|
|
20065
|
+
agentId: input.agent_id
|
|
19260
20066
|
}),
|
|
19261
20067
|
spanAttributes: { type: "tool" /* TOOL */ }
|
|
19262
20068
|
});
|
|
@@ -19502,12 +20308,37 @@ function injectTracingHooks(options, resolveParentSpan, activeToolSpans, localTo
|
|
|
19502
20308
|
}
|
|
19503
20309
|
};
|
|
19504
20310
|
}
|
|
20311
|
+
function setSubAgentPromptMessages(state, parentToolUseId, promptMessages, source) {
|
|
20312
|
+
if (promptMessages.length === 0) {
|
|
20313
|
+
return;
|
|
20314
|
+
}
|
|
20315
|
+
const parentKey = llmParentKey(parentToolUseId);
|
|
20316
|
+
const sourcePriority = SUB_AGENT_PROMPT_SOURCE_PRIORITY[source];
|
|
20317
|
+
const currentPriority = state.promptSourcePriorityByParentKey.get(parentKey) ?? -1;
|
|
20318
|
+
if (sourcePriority > currentPriority) {
|
|
20319
|
+
state.promptMessagesByParentKey.set(parentKey, promptMessages);
|
|
20320
|
+
state.promptSourcePriorityByParentKey.set(parentKey, sourcePriority);
|
|
20321
|
+
}
|
|
20322
|
+
}
|
|
20323
|
+
function getConversationHistory(state, parentKey) {
|
|
20324
|
+
let conversationHistory = state.conversationHistoryByParentKey.get(parentKey);
|
|
20325
|
+
if (!conversationHistory) {
|
|
20326
|
+
conversationHistory = [];
|
|
20327
|
+
state.conversationHistoryByParentKey.set(parentKey, conversationHistory);
|
|
20328
|
+
}
|
|
20329
|
+
return conversationHistory;
|
|
20330
|
+
}
|
|
19505
20331
|
async function finalizeCurrentMessageGroup(state) {
|
|
19506
20332
|
if (state.currentMessages.length === 0) {
|
|
19507
20333
|
return;
|
|
19508
20334
|
}
|
|
19509
20335
|
const parentToolUseId = state.currentMessages[0]?.parent_tool_use_id ?? null;
|
|
19510
20336
|
const parentKey = llmParentKey(parentToolUseId);
|
|
20337
|
+
const conversationHistory = getConversationHistory(state, parentKey);
|
|
20338
|
+
const promptMessages = parentToolUseId ? state.promptMessagesByParentKey.get(parentKey) ?? [] : buildRootPromptMessages(
|
|
20339
|
+
state.originalPrompt,
|
|
20340
|
+
state.capturedPromptMessages
|
|
20341
|
+
);
|
|
19511
20342
|
let parentSpan = await state.span.export();
|
|
19512
20343
|
if (parentToolUseId) {
|
|
19513
20344
|
const subAgentSpan = state.subAgentSpans.get(parentToolUseId);
|
|
@@ -19518,11 +20349,10 @@ async function finalizeCurrentMessageGroup(state) {
|
|
|
19518
20349
|
const existingLlmSpan = state.activeLlmSpansByParentToolUse.get(parentKey);
|
|
19519
20350
|
const llmSpanResult = await createLLMSpanForMessages(
|
|
19520
20351
|
state.currentMessages,
|
|
19521
|
-
|
|
19522
|
-
|
|
20352
|
+
promptMessages,
|
|
20353
|
+
conversationHistory,
|
|
19523
20354
|
state.options,
|
|
19524
20355
|
state.currentMessageStartTime,
|
|
19525
|
-
state.capturedPromptMessages,
|
|
19526
20356
|
parentSpan,
|
|
19527
20357
|
existingLlmSpan
|
|
19528
20358
|
);
|
|
@@ -19536,6 +20366,7 @@ async function finalizeCurrentMessageGroup(state) {
|
|
|
19536
20366
|
state.latestRootLlmParentRef.value = llmSpanResult.spanExport;
|
|
19537
20367
|
}
|
|
19538
20368
|
if (llmSpanResult.finalMessage) {
|
|
20369
|
+
conversationHistory.push(llmSpanResult.finalMessage);
|
|
19539
20370
|
state.finalResults.push(llmSpanResult.finalMessage);
|
|
19540
20371
|
}
|
|
19541
20372
|
}
|
|
@@ -19563,6 +20394,15 @@ function maybeTrackToolUseContext(state, message) {
|
|
|
19563
20394
|
description: getStringProperty(block.input, "description"),
|
|
19564
20395
|
toolUseId: block.id
|
|
19565
20396
|
});
|
|
20397
|
+
const prompt = getStringProperty(block.input, "prompt");
|
|
20398
|
+
if (prompt) {
|
|
20399
|
+
setSubAgentPromptMessages(
|
|
20400
|
+
state,
|
|
20401
|
+
block.id,
|
|
20402
|
+
[{ content: prompt, role: "user" }],
|
|
20403
|
+
"delegation"
|
|
20404
|
+
);
|
|
20405
|
+
}
|
|
19566
20406
|
}
|
|
19567
20407
|
}
|
|
19568
20408
|
}
|
|
@@ -19681,6 +20521,14 @@ async function maybeHandleTaskLifecycleMessage(state, message) {
|
|
|
19681
20521
|
};
|
|
19682
20522
|
if (message.subtype === "task_started") {
|
|
19683
20523
|
const prompt = getStringProperty(message, "prompt");
|
|
20524
|
+
if (prompt) {
|
|
20525
|
+
setSubAgentPromptMessages(
|
|
20526
|
+
state,
|
|
20527
|
+
toolUseId,
|
|
20528
|
+
[{ content: prompt, role: "user" }],
|
|
20529
|
+
"lifecycle"
|
|
20530
|
+
);
|
|
20531
|
+
}
|
|
19684
20532
|
subAgentSpan.log({
|
|
19685
20533
|
input: prompt,
|
|
19686
20534
|
metadata
|
|
@@ -19731,6 +20579,28 @@ async function handleStreamMessage(state, message) {
|
|
|
19731
20579
|
return;
|
|
19732
20580
|
}
|
|
19733
20581
|
await maybeStartSubAgentSpan(state, message);
|
|
20582
|
+
const messageParentToolUseId = message.parent_tool_use_id;
|
|
20583
|
+
if (messageParentToolUseId && message.type === "user") {
|
|
20584
|
+
const conversationMessage = conversationMessageFromSDKMessage(message);
|
|
20585
|
+
if (conversationMessage?.role === "user") {
|
|
20586
|
+
await finalizeCurrentMessageGroup(state);
|
|
20587
|
+
const parentKey = llmParentKey(messageParentToolUseId);
|
|
20588
|
+
const conversationHistory = getConversationHistory(state, parentKey);
|
|
20589
|
+
const currentPromptSourcePriority = state.promptSourcePriorityByParentKey.get(parentKey) ?? -1;
|
|
20590
|
+
const canUseAsInitialSidechainPrompt = conversationHistory.length === 0 && currentPromptSourcePriority < SUB_AGENT_PROMPT_SOURCE_PRIORITY.sidechain && !messageContentHasBlockType(message, "tool_result");
|
|
20591
|
+
if (!canUseAsInitialSidechainPrompt) {
|
|
20592
|
+
conversationHistory.push(conversationMessage);
|
|
20593
|
+
return;
|
|
20594
|
+
}
|
|
20595
|
+
setSubAgentPromptMessages(
|
|
20596
|
+
state,
|
|
20597
|
+
messageParentToolUseId,
|
|
20598
|
+
[conversationMessage],
|
|
20599
|
+
"sidechain"
|
|
20600
|
+
);
|
|
20601
|
+
return;
|
|
20602
|
+
}
|
|
20603
|
+
}
|
|
19734
20604
|
const messageId = message.message?.id;
|
|
19735
20605
|
if (messageId && messageId !== state.currentMessageId) {
|
|
19736
20606
|
await finalizeCurrentMessageGroup(state);
|
|
@@ -19882,6 +20752,7 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
19882
20752
|
}
|
|
19883
20753
|
const activeToolSpans = /* @__PURE__ */ new Map();
|
|
19884
20754
|
const activeLlmSpansByParentToolUse = /* @__PURE__ */ new Map();
|
|
20755
|
+
const conversationHistoryByParentKey = /* @__PURE__ */ new Map();
|
|
19885
20756
|
const subAgentSpans = /* @__PURE__ */ new Map();
|
|
19886
20757
|
const endedSubAgentSpans = /* @__PURE__ */ new Set();
|
|
19887
20758
|
const toolUseToParent = /* @__PURE__ */ new Map();
|
|
@@ -19891,6 +20762,8 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
19891
20762
|
};
|
|
19892
20763
|
const subAgentDetailsByToolUseId = /* @__PURE__ */ new Map();
|
|
19893
20764
|
const taskIdToToolUseId = /* @__PURE__ */ new Map();
|
|
20765
|
+
const promptMessagesByParentKey = /* @__PURE__ */ new Map();
|
|
20766
|
+
const promptSourcePriorityByParentKey = /* @__PURE__ */ new Map();
|
|
19894
20767
|
const localToolContext = createClaudeLocalToolContext();
|
|
19895
20768
|
const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
|
|
19896
20769
|
const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
|
|
@@ -19899,38 +20772,19 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
19899
20772
|
const parentToolUseId = trackedParentToolUseId ?? (context2?.agentId ? taskIdToToolUseId.get(context2.agentId) ?? null : null);
|
|
19900
20773
|
const parentKey = llmParentKey(parentToolUseId);
|
|
19901
20774
|
const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
|
|
19902
|
-
|
|
19903
|
-
|
|
19904
|
-
|
|
19905
|
-
|
|
19906
|
-
|
|
19907
|
-
|
|
19908
|
-
|
|
19909
|
-
|
|
19910
|
-
|
|
19911
|
-
|
|
19912
|
-
|
|
19913
|
-
}
|
|
19914
|
-
if (parentToolUseId) {
|
|
19915
|
-
const subAgentSpan = await ensureSubAgentSpan(
|
|
19916
|
-
subAgentDetailsByToolUseId,
|
|
19917
|
-
span,
|
|
19918
|
-
activeToolSpans,
|
|
19919
|
-
subAgentSpans,
|
|
19920
|
-
parentToolUseId
|
|
19921
|
-
);
|
|
19922
|
-
return subAgentSpan.export();
|
|
19923
|
-
}
|
|
19924
|
-
return span.export();
|
|
19925
|
-
}
|
|
19926
|
-
if (activeLlmSpan) {
|
|
19927
|
-
return activeLlmSpan.export();
|
|
20775
|
+
const latestLlmParent = parentToolUseId ? latestLlmParentBySubAgentToolUse.get(parentToolUseId) : latestRootLlmParentRef.value;
|
|
20776
|
+
if (!activeLlmSpan && !latestLlmParent) {
|
|
20777
|
+
await ensureActiveLlmSpanForParentToolUse(
|
|
20778
|
+
span,
|
|
20779
|
+
activeLlmSpansByParentToolUse,
|
|
20780
|
+
subAgentDetailsByToolUseId,
|
|
20781
|
+
activeToolSpans,
|
|
20782
|
+
subAgentSpans,
|
|
20783
|
+
parentToolUseId,
|
|
20784
|
+
getCurrentUnixTimestamp()
|
|
20785
|
+
);
|
|
19928
20786
|
}
|
|
19929
20787
|
if (parentToolUseId) {
|
|
19930
|
-
const parentLlm = latestLlmParentBySubAgentToolUse.get(parentToolUseId);
|
|
19931
|
-
if (parentLlm) {
|
|
19932
|
-
return parentLlm;
|
|
19933
|
-
}
|
|
19934
20788
|
const subAgentSpan = await ensureSubAgentSpan(
|
|
19935
20789
|
subAgentDetailsByToolUseId,
|
|
19936
20790
|
span,
|
|
@@ -19940,9 +20794,6 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
19940
20794
|
);
|
|
19941
20795
|
return subAgentSpan.export();
|
|
19942
20796
|
}
|
|
19943
|
-
if (latestRootLlmParentRef.value) {
|
|
19944
|
-
return latestRootLlmParentRef.value;
|
|
19945
|
-
}
|
|
19946
20797
|
return span.export();
|
|
19947
20798
|
};
|
|
19948
20799
|
localToolContext.resolveLocalToolParent = resolveToolUseParentSpan;
|
|
@@ -19963,6 +20814,7 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
19963
20814
|
accumulatedOutputTokens: 0,
|
|
19964
20815
|
activeLlmSpansByParentToolUse,
|
|
19965
20816
|
activeToolSpans,
|
|
20817
|
+
conversationHistoryByParentKey,
|
|
19966
20818
|
capturedPromptMessages,
|
|
19967
20819
|
currentMessageId: void 0,
|
|
19968
20820
|
currentMessageStartTime: startTime,
|
|
@@ -19973,7 +20825,9 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
19973
20825
|
originalPrompt,
|
|
19974
20826
|
processing: Promise.resolve(),
|
|
19975
20827
|
promptDone,
|
|
20828
|
+
promptMessagesByParentKey,
|
|
19976
20829
|
promptStarted: () => promptStarted,
|
|
20830
|
+
promptSourcePriorityByParentKey,
|
|
19977
20831
|
span,
|
|
19978
20832
|
subAgentDetailsByToolUseId,
|
|
19979
20833
|
subAgentSpans,
|
|
@@ -21402,6 +22256,10 @@ var googleGenAIChannels = defineChannels("@google/genai", {
|
|
|
21402
22256
|
embedContent: channel({
|
|
21403
22257
|
channelName: "models.embedContent",
|
|
21404
22258
|
kind: "async"
|
|
22259
|
+
}),
|
|
22260
|
+
interactionsCreate: channel({
|
|
22261
|
+
channelName: "interactions.create",
|
|
22262
|
+
kind: "async"
|
|
21405
22263
|
})
|
|
21406
22264
|
});
|
|
21407
22265
|
|
|
@@ -21429,6 +22287,7 @@ var GoogleGenAIPlugin = class extends BasePlugin {
|
|
|
21429
22287
|
this.subscribeToGenerateContentChannel();
|
|
21430
22288
|
this.subscribeToGenerateContentStreamChannel();
|
|
21431
22289
|
this.subscribeToEmbedContentChannel();
|
|
22290
|
+
this.subscribeToInteractionsCreateChannel();
|
|
21432
22291
|
}
|
|
21433
22292
|
subscribeToGenerateContentChannel() {
|
|
21434
22293
|
const tracingChannel2 = googleGenAIChannels.generateContent.tracingChannel();
|
|
@@ -21601,7 +22460,30 @@ var GoogleGenAIPlugin = class extends BasePlugin {
|
|
|
21601
22460
|
tracingChannel2.unsubscribe(handlers);
|
|
21602
22461
|
});
|
|
21603
22462
|
}
|
|
22463
|
+
subscribeToInteractionsCreateChannel() {
|
|
22464
|
+
this.unsubscribers.push(
|
|
22465
|
+
traceStreamingChannel(
|
|
22466
|
+
googleGenAIChannels.interactionsCreate,
|
|
22467
|
+
{
|
|
22468
|
+
name: "create_interaction",
|
|
22469
|
+
shouldTrace: ([params]) => !isBackgroundInteractionCreate(params),
|
|
22470
|
+
type: "llm" /* LLM */,
|
|
22471
|
+
extractInput: ([params]) => ({
|
|
22472
|
+
input: serializeInteractionInput(params),
|
|
22473
|
+
metadata: extractInteractionMetadata(params)
|
|
22474
|
+
}),
|
|
22475
|
+
extractOutput: (result) => serializeInteractionValue(result),
|
|
22476
|
+
extractMetadata: (result) => extractInteractionResponseMetadata(result),
|
|
22477
|
+
extractMetrics: (result, startTime) => cleanMetrics3(extractInteractionMetrics(result, startTime)),
|
|
22478
|
+
aggregateChunks: (chunks, _result, _event, startTime) => aggregateInteractionEvents(chunks, startTime)
|
|
22479
|
+
}
|
|
22480
|
+
)
|
|
22481
|
+
);
|
|
22482
|
+
}
|
|
21604
22483
|
};
|
|
22484
|
+
function isBackgroundInteractionCreate(params) {
|
|
22485
|
+
return tryToDict(params)?.background === true;
|
|
22486
|
+
}
|
|
21605
22487
|
function ensureSpanState(states, event, create) {
|
|
21606
22488
|
const existing = states.get(event);
|
|
21607
22489
|
if (existing) {
|
|
@@ -21809,6 +22691,60 @@ function serializeEmbedContentInput(params) {
|
|
|
21809
22691
|
}
|
|
21810
22692
|
return input;
|
|
21811
22693
|
}
|
|
22694
|
+
function serializeInteractionInput(params) {
|
|
22695
|
+
const input = {
|
|
22696
|
+
input: serializeInteractionValue(params.input)
|
|
22697
|
+
};
|
|
22698
|
+
for (const key of [
|
|
22699
|
+
"model",
|
|
22700
|
+
"agent",
|
|
22701
|
+
"agent_config",
|
|
22702
|
+
"api_version",
|
|
22703
|
+
"background",
|
|
22704
|
+
"environment",
|
|
22705
|
+
"generation_config",
|
|
22706
|
+
"previous_interaction_id",
|
|
22707
|
+
"response_format",
|
|
22708
|
+
"response_mime_type",
|
|
22709
|
+
"response_modalities",
|
|
22710
|
+
"service_tier",
|
|
22711
|
+
"store",
|
|
22712
|
+
"stream",
|
|
22713
|
+
"system_instruction",
|
|
22714
|
+
"webhook_config"
|
|
22715
|
+
]) {
|
|
22716
|
+
const value = params[key];
|
|
22717
|
+
if (value !== void 0) {
|
|
22718
|
+
input[key] = serializeInteractionValue(value);
|
|
22719
|
+
}
|
|
22720
|
+
}
|
|
22721
|
+
return input;
|
|
22722
|
+
}
|
|
22723
|
+
function extractInteractionMetadata(params) {
|
|
22724
|
+
const metadata = {};
|
|
22725
|
+
for (const key of [
|
|
22726
|
+
"model",
|
|
22727
|
+
"agent",
|
|
22728
|
+
"agent_config",
|
|
22729
|
+
"generation_config",
|
|
22730
|
+
"system_instruction",
|
|
22731
|
+
"response_format",
|
|
22732
|
+
"response_mime_type",
|
|
22733
|
+
"response_modalities",
|
|
22734
|
+
"service_tier"
|
|
22735
|
+
]) {
|
|
22736
|
+
const value = params[key];
|
|
22737
|
+
if (value !== void 0) {
|
|
22738
|
+
metadata[key] = serializeInteractionValue(value);
|
|
22739
|
+
}
|
|
22740
|
+
}
|
|
22741
|
+
if (Array.isArray(params.tools)) {
|
|
22742
|
+
metadata.tools = params.tools.map(
|
|
22743
|
+
(tool) => serializeInteractionValue(tool)
|
|
22744
|
+
);
|
|
22745
|
+
}
|
|
22746
|
+
return metadata;
|
|
22747
|
+
}
|
|
21812
22748
|
function serializeContentCollection(contents) {
|
|
21813
22749
|
if (contents === null || contents === void 0) {
|
|
21814
22750
|
return null;
|
|
@@ -21839,21 +22775,8 @@ function serializePart(part) {
|
|
|
21839
22775
|
}
|
|
21840
22776
|
if (part.inlineData && part.inlineData.data) {
|
|
21841
22777
|
const { data, mimeType } = part.inlineData;
|
|
21842
|
-
|
|
21843
|
-
|
|
21844
|
-
const filename = `file.${extension}`;
|
|
21845
|
-
const buffer = typeof data === "string" ? typeof Buffer !== "undefined" ? Buffer.from(data, "base64") : new Uint8Array(
|
|
21846
|
-
atob(data).split("").map((c) => c.charCodeAt(0))
|
|
21847
|
-
) : typeof Buffer !== "undefined" ? Buffer.from(data) : new Uint8Array(data);
|
|
21848
|
-
const arrayBuffer = buffer instanceof Uint8Array ? buffer.buffer.slice(
|
|
21849
|
-
buffer.byteOffset,
|
|
21850
|
-
buffer.byteOffset + buffer.byteLength
|
|
21851
|
-
) : buffer;
|
|
21852
|
-
const attachment = new Attachment({
|
|
21853
|
-
data: arrayBuffer,
|
|
21854
|
-
filename,
|
|
21855
|
-
contentType: mimeType || "application/octet-stream"
|
|
21856
|
-
});
|
|
22778
|
+
const attachment = createAttachmentFromInlineData(data, mimeType);
|
|
22779
|
+
if (attachment) {
|
|
21857
22780
|
return {
|
|
21858
22781
|
image_url: { url: attachment }
|
|
21859
22782
|
};
|
|
@@ -21861,6 +22784,59 @@ function serializePart(part) {
|
|
|
21861
22784
|
}
|
|
21862
22785
|
return part;
|
|
21863
22786
|
}
|
|
22787
|
+
function serializeInteractionValue(value, seen = /* @__PURE__ */ new WeakSet()) {
|
|
22788
|
+
if (value === null || value === void 0 || typeof value !== "object") {
|
|
22789
|
+
return value;
|
|
22790
|
+
}
|
|
22791
|
+
if (Array.isArray(value)) {
|
|
22792
|
+
return value.map((item) => serializeInteractionValue(item, seen));
|
|
22793
|
+
}
|
|
22794
|
+
const dict = tryToDict(value);
|
|
22795
|
+
if (dict === null || dict === void 0 || typeof dict !== "object") {
|
|
22796
|
+
return dict;
|
|
22797
|
+
}
|
|
22798
|
+
if (Array.isArray(dict)) {
|
|
22799
|
+
return dict.map((item) => serializeInteractionValue(item, seen));
|
|
22800
|
+
}
|
|
22801
|
+
if (seen.has(dict)) {
|
|
22802
|
+
return "[Circular]";
|
|
22803
|
+
}
|
|
22804
|
+
seen.add(dict);
|
|
22805
|
+
try {
|
|
22806
|
+
const serialized = {};
|
|
22807
|
+
const mimeType = "mime_type" in dict && typeof dict.mime_type === "string" ? dict.mime_type : "mimeType" in dict && typeof dict.mimeType === "string" ? dict.mimeType : void 0;
|
|
22808
|
+
const attachment = mimeType && "data" in dict && dict.data !== void 0 ? createAttachmentFromInlineData(dict.data, mimeType) : null;
|
|
22809
|
+
for (const [key, entry] of Object.entries(dict)) {
|
|
22810
|
+
if (key === "data" && attachment) {
|
|
22811
|
+
serialized[key] = attachment;
|
|
22812
|
+
} else {
|
|
22813
|
+
serialized[key] = serializeInteractionValue(entry, seen);
|
|
22814
|
+
}
|
|
22815
|
+
}
|
|
22816
|
+
return serialized;
|
|
22817
|
+
} finally {
|
|
22818
|
+
seen.delete(dict);
|
|
22819
|
+
}
|
|
22820
|
+
}
|
|
22821
|
+
function createAttachmentFromInlineData(data, mimeType) {
|
|
22822
|
+
if (!(data instanceof Uint8Array || typeof Buffer !== "undefined" && Buffer.isBuffer(data) || typeof data === "string")) {
|
|
22823
|
+
return null;
|
|
22824
|
+
}
|
|
22825
|
+
const extension = mimeType ? mimeType.split("/")[1] : "bin";
|
|
22826
|
+
const filename = `file.${extension}`;
|
|
22827
|
+
const buffer = typeof data === "string" ? typeof Buffer !== "undefined" ? Buffer.from(data, "base64") : new Uint8Array(
|
|
22828
|
+
atob(data).split("").map((c) => c.charCodeAt(0))
|
|
22829
|
+
) : typeof Buffer !== "undefined" ? Buffer.from(data) : new Uint8Array(data);
|
|
22830
|
+
const arrayBuffer = buffer instanceof Uint8Array ? buffer.buffer.slice(
|
|
22831
|
+
buffer.byteOffset,
|
|
22832
|
+
buffer.byteOffset + buffer.byteLength
|
|
22833
|
+
) : buffer;
|
|
22834
|
+
return new Attachment({
|
|
22835
|
+
data: arrayBuffer,
|
|
22836
|
+
filename,
|
|
22837
|
+
contentType: mimeType || "application/octet-stream"
|
|
22838
|
+
});
|
|
22839
|
+
}
|
|
21864
22840
|
function serializeGenerateContentTools(params) {
|
|
21865
22841
|
const config3 = params.config ? tryToDict(params.config) : null;
|
|
21866
22842
|
const tools = config3?.tools;
|
|
@@ -21945,6 +22921,33 @@ function extractEmbedContentMetrics(response, startTime) {
|
|
|
21945
22921
|
}
|
|
21946
22922
|
return metrics;
|
|
21947
22923
|
}
|
|
22924
|
+
function extractInteractionMetrics(response, startTime) {
|
|
22925
|
+
const metrics = {};
|
|
22926
|
+
if (startTime !== void 0) {
|
|
22927
|
+
const end = getCurrentUnixTimestamp();
|
|
22928
|
+
metrics.start = startTime;
|
|
22929
|
+
metrics.end = end;
|
|
22930
|
+
metrics.duration = end - startTime;
|
|
22931
|
+
}
|
|
22932
|
+
if (response?.usage) {
|
|
22933
|
+
populateInteractionUsageMetrics(metrics, response.usage);
|
|
22934
|
+
}
|
|
22935
|
+
return metrics;
|
|
22936
|
+
}
|
|
22937
|
+
function extractInteractionResponseMetadata(response) {
|
|
22938
|
+
const responseDict = tryToDict(response);
|
|
22939
|
+
if (!responseDict) {
|
|
22940
|
+
return void 0;
|
|
22941
|
+
}
|
|
22942
|
+
const metadata = {};
|
|
22943
|
+
if (typeof responseDict.id === "string") {
|
|
22944
|
+
metadata.interaction_id = responseDict.id;
|
|
22945
|
+
}
|
|
22946
|
+
if (typeof responseDict.status === "string") {
|
|
22947
|
+
metadata.status = responseDict.status;
|
|
22948
|
+
}
|
|
22949
|
+
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
22950
|
+
}
|
|
21948
22951
|
function extractEmbedPromptTokenCount(response) {
|
|
21949
22952
|
if (!response) {
|
|
21950
22953
|
return void 0;
|
|
@@ -22007,6 +23010,23 @@ function populateUsageMetrics(metrics, usage) {
|
|
|
22007
23010
|
metrics.completion_reasoning_tokens = usage.thoughtsTokenCount;
|
|
22008
23011
|
}
|
|
22009
23012
|
}
|
|
23013
|
+
function populateInteractionUsageMetrics(metrics, usage) {
|
|
23014
|
+
if (typeof usage.total_input_tokens === "number") {
|
|
23015
|
+
metrics.prompt_tokens = usage.total_input_tokens;
|
|
23016
|
+
}
|
|
23017
|
+
if (typeof usage.total_output_tokens === "number") {
|
|
23018
|
+
metrics.completion_tokens = usage.total_output_tokens;
|
|
23019
|
+
}
|
|
23020
|
+
if (typeof usage.total_tokens === "number") {
|
|
23021
|
+
metrics.tokens = usage.total_tokens;
|
|
23022
|
+
}
|
|
23023
|
+
if (typeof usage.total_cached_tokens === "number") {
|
|
23024
|
+
metrics.prompt_cached_tokens = usage.total_cached_tokens;
|
|
23025
|
+
}
|
|
23026
|
+
if (typeof usage.total_thought_tokens === "number") {
|
|
23027
|
+
metrics.completion_reasoning_tokens = usage.total_thought_tokens;
|
|
23028
|
+
}
|
|
23029
|
+
}
|
|
22010
23030
|
function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
|
|
22011
23031
|
const end = getCurrentUnixTimestamp();
|
|
22012
23032
|
const metrics = {
|
|
@@ -22104,6 +23124,146 @@ function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
|
|
|
22104
23124
|
}
|
|
22105
23125
|
return { aggregated, metrics };
|
|
22106
23126
|
}
|
|
23127
|
+
function aggregateInteractionEvents(chunks, startTime) {
|
|
23128
|
+
const end = getCurrentUnixTimestamp();
|
|
23129
|
+
const metrics = {};
|
|
23130
|
+
if (startTime !== void 0) {
|
|
23131
|
+
metrics.start = startTime;
|
|
23132
|
+
metrics.end = end;
|
|
23133
|
+
metrics.duration = end - startTime;
|
|
23134
|
+
}
|
|
23135
|
+
let latestInteraction;
|
|
23136
|
+
let latestUsage;
|
|
23137
|
+
let status;
|
|
23138
|
+
let outputText = "";
|
|
23139
|
+
const steps = /* @__PURE__ */ new Map();
|
|
23140
|
+
for (const chunk of chunks) {
|
|
23141
|
+
const event = tryToDict(chunk);
|
|
23142
|
+
if (!event) {
|
|
23143
|
+
continue;
|
|
23144
|
+
}
|
|
23145
|
+
const usage = extractInteractionUsageFromEvent(event);
|
|
23146
|
+
if (usage) {
|
|
23147
|
+
latestUsage = usage;
|
|
23148
|
+
}
|
|
23149
|
+
const interaction = tryToDict(event.interaction);
|
|
23150
|
+
if (interaction) {
|
|
23151
|
+
latestInteraction = serializeInteractionValue(interaction);
|
|
23152
|
+
if (typeof interaction.status === "string") {
|
|
23153
|
+
status = interaction.status;
|
|
23154
|
+
}
|
|
23155
|
+
}
|
|
23156
|
+
if (typeof event.status === "string") {
|
|
23157
|
+
status = event.status;
|
|
23158
|
+
}
|
|
23159
|
+
const index = typeof event.index === "number" ? event.index : void 0;
|
|
23160
|
+
if (index === void 0) {
|
|
23161
|
+
continue;
|
|
23162
|
+
}
|
|
23163
|
+
if (event.event_type === "step.start") {
|
|
23164
|
+
const compact = compactInteractionStep(event.step);
|
|
23165
|
+
compact.index = index;
|
|
23166
|
+
steps.set(index, compact);
|
|
23167
|
+
continue;
|
|
23168
|
+
}
|
|
23169
|
+
if (event.event_type === "step.delta") {
|
|
23170
|
+
const step = steps.get(index) ?? { index };
|
|
23171
|
+
const textDelta = applyInteractionDelta(step, event.delta);
|
|
23172
|
+
if (textDelta) {
|
|
23173
|
+
outputText += textDelta;
|
|
23174
|
+
}
|
|
23175
|
+
steps.set(index, step);
|
|
23176
|
+
}
|
|
23177
|
+
}
|
|
23178
|
+
if (latestUsage) {
|
|
23179
|
+
populateInteractionUsageMetrics(metrics, latestUsage);
|
|
23180
|
+
}
|
|
23181
|
+
const output = latestInteraction ? { ...latestInteraction } : {};
|
|
23182
|
+
if (status) {
|
|
23183
|
+
output.status = status;
|
|
23184
|
+
}
|
|
23185
|
+
if (outputText) {
|
|
23186
|
+
output.output_text = outputText;
|
|
23187
|
+
}
|
|
23188
|
+
if (latestUsage) {
|
|
23189
|
+
output.usage = serializeInteractionValue(latestUsage);
|
|
23190
|
+
}
|
|
23191
|
+
const compactSteps = Array.from(steps.values()).sort(
|
|
23192
|
+
(left, right) => Number(left.index ?? 0) - Number(right.index ?? 0)
|
|
23193
|
+
);
|
|
23194
|
+
if (compactSteps.length > 0) {
|
|
23195
|
+
output.steps = compactSteps;
|
|
23196
|
+
}
|
|
23197
|
+
const metadata = {};
|
|
23198
|
+
if (typeof output.id === "string") {
|
|
23199
|
+
metadata.interaction_id = output.id;
|
|
23200
|
+
}
|
|
23201
|
+
if (typeof output.status === "string") {
|
|
23202
|
+
metadata.status = output.status;
|
|
23203
|
+
}
|
|
23204
|
+
return {
|
|
23205
|
+
output,
|
|
23206
|
+
metrics: cleanMetrics3(metrics),
|
|
23207
|
+
...Object.keys(metadata).length > 0 ? { metadata } : {}
|
|
23208
|
+
};
|
|
23209
|
+
}
|
|
23210
|
+
function extractInteractionUsageFromEvent(event) {
|
|
23211
|
+
const metadata = tryToDict(event.metadata);
|
|
23212
|
+
const metadataUsage = tryToDict(metadata?.usage);
|
|
23213
|
+
if (metadataUsage) {
|
|
23214
|
+
return metadataUsage;
|
|
23215
|
+
}
|
|
23216
|
+
const metadataTotalUsage = tryToDict(metadata?.total_usage);
|
|
23217
|
+
if (metadataTotalUsage) {
|
|
23218
|
+
return metadataTotalUsage;
|
|
23219
|
+
}
|
|
23220
|
+
const interaction = tryToDict(event.interaction);
|
|
23221
|
+
const interactionUsage = tryToDict(interaction?.usage);
|
|
23222
|
+
return interactionUsage ? interactionUsage : void 0;
|
|
23223
|
+
}
|
|
23224
|
+
function compactInteractionStep(step) {
|
|
23225
|
+
const stepDict = tryToDict(step);
|
|
23226
|
+
if (!stepDict) {
|
|
23227
|
+
return {};
|
|
23228
|
+
}
|
|
23229
|
+
const compact = {};
|
|
23230
|
+
for (const key of [
|
|
23231
|
+
"type",
|
|
23232
|
+
"content",
|
|
23233
|
+
"name",
|
|
23234
|
+
"server_name",
|
|
23235
|
+
"arguments",
|
|
23236
|
+
"result",
|
|
23237
|
+
"is_error"
|
|
23238
|
+
]) {
|
|
23239
|
+
if (stepDict[key] !== void 0) {
|
|
23240
|
+
compact[key] = serializeInteractionValue(stepDict[key]);
|
|
23241
|
+
}
|
|
23242
|
+
}
|
|
23243
|
+
return Object.keys(compact).length > 0 ? compact : serializeInteractionValue(stepDict);
|
|
23244
|
+
}
|
|
23245
|
+
function applyInteractionDelta(step, delta) {
|
|
23246
|
+
const deltaDict = tryToDict(delta);
|
|
23247
|
+
if (!deltaDict) {
|
|
23248
|
+
return void 0;
|
|
23249
|
+
}
|
|
23250
|
+
const deltaType = deltaDict.type;
|
|
23251
|
+
if (typeof deltaType === "string" && typeof step.type !== "string") {
|
|
23252
|
+
step.type = deltaType === "text" ? "model_output" : deltaType;
|
|
23253
|
+
}
|
|
23254
|
+
if (deltaType === "text" && typeof deltaDict.text === "string") {
|
|
23255
|
+
step.text = `${typeof step.text === "string" ? step.text : ""}${deltaDict.text}`;
|
|
23256
|
+
return deltaDict.text;
|
|
23257
|
+
}
|
|
23258
|
+
if (deltaType === "arguments_delta" && typeof deltaDict.arguments === "string") {
|
|
23259
|
+
step.arguments = `${typeof step.arguments === "string" ? step.arguments : ""}${deltaDict.arguments}`;
|
|
23260
|
+
return void 0;
|
|
23261
|
+
}
|
|
23262
|
+
const deltas = Array.isArray(step.deltas) ? step.deltas : [];
|
|
23263
|
+
deltas.push(serializeInteractionValue(deltaDict));
|
|
23264
|
+
step.deltas = deltas;
|
|
23265
|
+
return void 0;
|
|
23266
|
+
}
|
|
22107
23267
|
function cleanMetrics3(metrics) {
|
|
22108
23268
|
const cleaned = {};
|
|
22109
23269
|
for (const [key, value] of Object.entries(metrics)) {
|
|
@@ -27930,7 +29090,8 @@ var FlueObserveBridge = class {
|
|
|
27930
29090
|
metadata
|
|
27931
29091
|
}
|
|
27932
29092
|
});
|
|
27933
|
-
|
|
29093
|
+
const activeContext = enterCurrentFlueSpan(span);
|
|
29094
|
+
this.runsById.set(event.runId, { activeContext, metadata, span });
|
|
27934
29095
|
}
|
|
27935
29096
|
handleRunEnd(event) {
|
|
27936
29097
|
const state = this.runsById.get(event.runId);
|
|
@@ -27948,6 +29109,7 @@ var FlueObserveBridge = class {
|
|
|
27948
29109
|
});
|
|
27949
29110
|
safeEnd(state.span, eventTime(event.timestamp));
|
|
27950
29111
|
this.runsById.delete(event.runId);
|
|
29112
|
+
restoreCurrentFlueSpan(state.activeContext);
|
|
27951
29113
|
}
|
|
27952
29114
|
void flush().catch((error2) => {
|
|
27953
29115
|
logInstrumentationError3("Flue flush", error2);
|
|
@@ -28074,7 +29236,8 @@ var FlueObserveBridge = class {
|
|
|
28074
29236
|
metadata
|
|
28075
29237
|
}
|
|
28076
29238
|
});
|
|
28077
|
-
|
|
29239
|
+
const activeContext = enterCurrentFlueSpan(span);
|
|
29240
|
+
this.toolsByKey.set(toolKey(event), { activeContext, metadata, span });
|
|
28078
29241
|
}
|
|
28079
29242
|
handleToolCall(event) {
|
|
28080
29243
|
if (!event.toolCallId) {
|
|
@@ -28097,6 +29260,7 @@ var FlueObserveBridge = class {
|
|
|
28097
29260
|
});
|
|
28098
29261
|
safeEnd(state.span, eventTime(event.timestamp));
|
|
28099
29262
|
this.toolsByKey.delete(key);
|
|
29263
|
+
restoreCurrentFlueSpan(state.activeContext);
|
|
28100
29264
|
}
|
|
28101
29265
|
handleTaskStart(event) {
|
|
28102
29266
|
if (!event.taskId) {
|
|
@@ -28501,11 +29665,39 @@ function stateMatchesRun(state, runId) {
|
|
|
28501
29665
|
function startFlueSpan(parent, args) {
|
|
28502
29666
|
return parent ? withCurrent(parent, () => startSpan(args)) : startSpan(args);
|
|
28503
29667
|
}
|
|
28504
|
-
function
|
|
29668
|
+
function enterCurrentFlueSpan(span) {
|
|
29669
|
+
const contextManager = _internalGetGlobalState()?.contextManager;
|
|
29670
|
+
const store = contextManager ? Reflect.get(contextManager, BRAINTRUST_CURRENT_SPAN_STORE) : void 0;
|
|
29671
|
+
if (!contextManager || !isCurrentSpanStore(store)) {
|
|
29672
|
+
return void 0;
|
|
29673
|
+
}
|
|
29674
|
+
const previous = store.getStore();
|
|
28505
29675
|
try {
|
|
28506
|
-
|
|
29676
|
+
store.enterWith(contextManager.wrapSpanForStore(span));
|
|
29677
|
+
return { previous, store };
|
|
28507
29678
|
} catch (error2) {
|
|
28508
|
-
logInstrumentationError3("Flue
|
|
29679
|
+
logInstrumentationError3("Flue context propagation", error2);
|
|
29680
|
+
return void 0;
|
|
29681
|
+
}
|
|
29682
|
+
}
|
|
29683
|
+
function isCurrentSpanStore(value) {
|
|
29684
|
+
return isObjectLike(value) && typeof Reflect.get(value, "enterWith") === "function" && typeof Reflect.get(value, "getStore") === "function";
|
|
29685
|
+
}
|
|
29686
|
+
function restoreCurrentFlueSpan(activeContext) {
|
|
29687
|
+
if (!activeContext) {
|
|
29688
|
+
return;
|
|
29689
|
+
}
|
|
29690
|
+
try {
|
|
29691
|
+
activeContext.store.enterWith(activeContext.previous);
|
|
29692
|
+
} catch (error2) {
|
|
29693
|
+
logInstrumentationError3("Flue context restoration", error2);
|
|
29694
|
+
}
|
|
29695
|
+
}
|
|
29696
|
+
function safeLog3(span, event) {
|
|
29697
|
+
try {
|
|
29698
|
+
span.log(event);
|
|
29699
|
+
} catch (error2) {
|
|
29700
|
+
logInstrumentationError3("Flue span log", error2);
|
|
28509
29701
|
}
|
|
28510
29702
|
}
|
|
28511
29703
|
function safeEnd(span, endTime) {
|
|
@@ -28978,6 +30170,890 @@ function isBraintrustHandler(handler) {
|
|
|
28978
30170
|
return Reflect.get(handler, "name") === BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
|
|
28979
30171
|
}
|
|
28980
30172
|
|
|
30173
|
+
// src/instrumentation/plugins/pi-coding-agent-channels.ts
|
|
30174
|
+
var piCodingAgentChannels = defineChannels(
|
|
30175
|
+
"@earendil-works/pi-coding-agent",
|
|
30176
|
+
{
|
|
30177
|
+
prompt: channel({
|
|
30178
|
+
channelName: "AgentSession.prompt",
|
|
30179
|
+
kind: "async"
|
|
30180
|
+
})
|
|
30181
|
+
}
|
|
30182
|
+
);
|
|
30183
|
+
|
|
30184
|
+
// src/instrumentation/plugins/pi-coding-agent-plugin.ts
|
|
30185
|
+
var piStreamPatchStates = /* @__PURE__ */ new WeakMap();
|
|
30186
|
+
var piPromptContextStore;
|
|
30187
|
+
var PiCodingAgentPlugin = class extends BasePlugin {
|
|
30188
|
+
activePromptStates = /* @__PURE__ */ new Set();
|
|
30189
|
+
onEnable() {
|
|
30190
|
+
this.subscribeToPrompt();
|
|
30191
|
+
}
|
|
30192
|
+
onDisable() {
|
|
30193
|
+
for (const unsubscribe of this.unsubscribers) {
|
|
30194
|
+
unsubscribe();
|
|
30195
|
+
}
|
|
30196
|
+
this.unsubscribers = [];
|
|
30197
|
+
for (const state of [...this.activePromptStates]) {
|
|
30198
|
+
void finalizePiPromptRun(state).catch((error2) => {
|
|
30199
|
+
logInstrumentationError4("Pi Coding Agent disable cleanup", error2);
|
|
30200
|
+
});
|
|
30201
|
+
}
|
|
30202
|
+
}
|
|
30203
|
+
subscribeToPrompt() {
|
|
30204
|
+
const channel2 = piCodingAgentChannels.prompt.tracingChannel();
|
|
30205
|
+
const states = /* @__PURE__ */ new WeakMap();
|
|
30206
|
+
const unbindAutoInstrumentationSuppression = bindAutoInstrumentationSuppressionToStart(channel2);
|
|
30207
|
+
const handlers = {
|
|
30208
|
+
start: (event) => {
|
|
30209
|
+
const state = startPiPromptRun(event, (state2) => {
|
|
30210
|
+
this.activePromptStates.delete(state2);
|
|
30211
|
+
});
|
|
30212
|
+
if (state) {
|
|
30213
|
+
this.activePromptStates.add(state);
|
|
30214
|
+
states.set(event, state);
|
|
30215
|
+
}
|
|
30216
|
+
},
|
|
30217
|
+
asyncEnd: async (event) => {
|
|
30218
|
+
const state = states.get(event);
|
|
30219
|
+
if (!state) {
|
|
30220
|
+
return;
|
|
30221
|
+
}
|
|
30222
|
+
states.delete(event);
|
|
30223
|
+
state.promptCallEnded = true;
|
|
30224
|
+
if (!state.finalized && state.deferCompletionUntilTurnEnd && !state.turnEnded) {
|
|
30225
|
+
if (!state.sawStreamFn) {
|
|
30226
|
+
state.queued = true;
|
|
30227
|
+
if (!state.streamPatchState.queuedPromptStates.includes(state)) {
|
|
30228
|
+
state.streamPatchState.queuedPromptStates.push(state);
|
|
30229
|
+
}
|
|
30230
|
+
}
|
|
30231
|
+
return;
|
|
30232
|
+
}
|
|
30233
|
+
await finalizePiPromptRun(state);
|
|
30234
|
+
},
|
|
30235
|
+
error: async (event) => {
|
|
30236
|
+
const state = states.get(event);
|
|
30237
|
+
if (!state) {
|
|
30238
|
+
return;
|
|
30239
|
+
}
|
|
30240
|
+
states.delete(event);
|
|
30241
|
+
await finalizePiPromptRun(state, event.error);
|
|
30242
|
+
}
|
|
30243
|
+
};
|
|
30244
|
+
channel2.subscribe(handlers);
|
|
30245
|
+
this.unsubscribers.push(() => {
|
|
30246
|
+
unbindAutoInstrumentationSuppression?.();
|
|
30247
|
+
channel2.unsubscribe(handlers);
|
|
30248
|
+
});
|
|
30249
|
+
}
|
|
30250
|
+
};
|
|
30251
|
+
function startPiPromptRun(event, onFinalize) {
|
|
30252
|
+
const session = extractSession(event);
|
|
30253
|
+
const agent = session?.agent;
|
|
30254
|
+
if (!session || !isPiAgent(agent)) {
|
|
30255
|
+
return void 0;
|
|
30256
|
+
}
|
|
30257
|
+
const metadata = {
|
|
30258
|
+
...extractSessionMetadata(session),
|
|
30259
|
+
...extractPromptOptionsMetadata(event.arguments[1]),
|
|
30260
|
+
"pi_coding_agent.operation": "AgentSession.prompt",
|
|
30261
|
+
provider: session.model?.provider ?? agent.state?.model?.provider ?? "pi",
|
|
30262
|
+
...session.model?.id || agent.state?.model?.id ? { model: session.model?.id ?? agent.state?.model?.id } : {},
|
|
30263
|
+
...event.moduleVersion ? { "pi_coding_agent.version": event.moduleVersion } : {}
|
|
30264
|
+
};
|
|
30265
|
+
const span = startSpan({
|
|
30266
|
+
event: {
|
|
30267
|
+
input: extractPromptInput(event.arguments[0], event.arguments[1]),
|
|
30268
|
+
metadata
|
|
30269
|
+
},
|
|
30270
|
+
name: "AgentSession.prompt",
|
|
30271
|
+
spanAttributes: { type: "task" /* TASK */ }
|
|
30272
|
+
});
|
|
30273
|
+
const streamPatchState = installPiStreamPatch(agent);
|
|
30274
|
+
const options = event.arguments[1];
|
|
30275
|
+
const promptText = event.arguments[0];
|
|
30276
|
+
const state = {
|
|
30277
|
+
activeLlmSpans: /* @__PURE__ */ new Set(),
|
|
30278
|
+
activeToolSpans: /* @__PURE__ */ new Map(),
|
|
30279
|
+
agent,
|
|
30280
|
+
collectedLlmUsageMetrics: false,
|
|
30281
|
+
deferCompletionUntilTurnEnd: options?.streamingBehavior === "followUp" || options?.streamingBehavior === "steer",
|
|
30282
|
+
finalized: false,
|
|
30283
|
+
metadata,
|
|
30284
|
+
metrics: {},
|
|
30285
|
+
onFinalize,
|
|
30286
|
+
promptCallEnded: false,
|
|
30287
|
+
...typeof promptText === "string" ? { promptText } : {},
|
|
30288
|
+
queued: false,
|
|
30289
|
+
span,
|
|
30290
|
+
sawStreamFn: false,
|
|
30291
|
+
startTime: getCurrentUnixTimestamp(),
|
|
30292
|
+
streamPatchState,
|
|
30293
|
+
turnEnded: false
|
|
30294
|
+
};
|
|
30295
|
+
state.restorePromptContext = enterPiPromptContext(state);
|
|
30296
|
+
streamPatchState.activePromptStates.add(state);
|
|
30297
|
+
try {
|
|
30298
|
+
state.unsubscribeAgent = agent.subscribe(async (agentEvent) => {
|
|
30299
|
+
try {
|
|
30300
|
+
await runWithAutoInstrumentationSuppressed(
|
|
30301
|
+
() => handlePiAgentEvent(state, agentEvent)
|
|
30302
|
+
);
|
|
30303
|
+
} catch (error2) {
|
|
30304
|
+
logInstrumentationError4("Pi Coding Agent event", error2);
|
|
30305
|
+
}
|
|
30306
|
+
});
|
|
30307
|
+
} catch (error2) {
|
|
30308
|
+
logInstrumentationError4("Pi Coding Agent event subscription", error2);
|
|
30309
|
+
}
|
|
30310
|
+
return state;
|
|
30311
|
+
}
|
|
30312
|
+
function extractSession(event) {
|
|
30313
|
+
const candidate = event.session ?? event.self;
|
|
30314
|
+
return isObject(candidate) && typeof candidate.prompt === "function" ? candidate : void 0;
|
|
30315
|
+
}
|
|
30316
|
+
function isPiAgent(value) {
|
|
30317
|
+
return isObject(value) && typeof value.streamFn === "function" && typeof value.subscribe === "function";
|
|
30318
|
+
}
|
|
30319
|
+
function promptContextStore() {
|
|
30320
|
+
piPromptContextStore ??= isomorph_default.newAsyncLocalStorage();
|
|
30321
|
+
return piPromptContextStore;
|
|
30322
|
+
}
|
|
30323
|
+
function currentPromptContextFrames() {
|
|
30324
|
+
return promptContextStore().getStore()?.frames ?? [];
|
|
30325
|
+
}
|
|
30326
|
+
function currentPiPromptState() {
|
|
30327
|
+
const frames = currentPromptContextFrames();
|
|
30328
|
+
return frames[frames.length - 1]?.state;
|
|
30329
|
+
}
|
|
30330
|
+
function enterPiPromptContext(state) {
|
|
30331
|
+
const frame = {
|
|
30332
|
+
id: /* @__PURE__ */ Symbol("braintrust.pi-coding-agent.prompt"),
|
|
30333
|
+
state
|
|
30334
|
+
};
|
|
30335
|
+
promptContextStore().enterWith({
|
|
30336
|
+
frames: [...currentPromptContextFrames(), frame]
|
|
30337
|
+
});
|
|
30338
|
+
return () => {
|
|
30339
|
+
const frames = currentPromptContextFrames().filter(
|
|
30340
|
+
(candidate) => candidate.id !== frame.id
|
|
30341
|
+
);
|
|
30342
|
+
promptContextStore().enterWith(frames.length > 0 ? { frames } : void 0);
|
|
30343
|
+
};
|
|
30344
|
+
}
|
|
30345
|
+
function installPiStreamPatch(agent) {
|
|
30346
|
+
const existing = piStreamPatchStates.get(agent);
|
|
30347
|
+
if (existing) {
|
|
30348
|
+
if (agent.streamFn !== existing.wrappedStreamFn) {
|
|
30349
|
+
debugLogger.debug(
|
|
30350
|
+
"Pi Coding Agent streamFn changed while Braintrust instrumentation was active; preserving existing patch state."
|
|
30351
|
+
);
|
|
30352
|
+
}
|
|
30353
|
+
return existing;
|
|
30354
|
+
}
|
|
30355
|
+
const patchState = {
|
|
30356
|
+
activePromptStates: /* @__PURE__ */ new Set(),
|
|
30357
|
+
agent,
|
|
30358
|
+
originalStreamFn: agent.streamFn,
|
|
30359
|
+
queuedPromptStates: [],
|
|
30360
|
+
wrappedStreamFn: agent.streamFn
|
|
30361
|
+
};
|
|
30362
|
+
patchState.wrappedStreamFn = makeSharedInstrumentedStreamFn(patchState);
|
|
30363
|
+
agent.streamFn = patchState.wrappedStreamFn;
|
|
30364
|
+
piStreamPatchStates.set(agent, patchState);
|
|
30365
|
+
return patchState;
|
|
30366
|
+
}
|
|
30367
|
+
function resolveStreamPromptState(patchState, context2) {
|
|
30368
|
+
let lastUserText;
|
|
30369
|
+
if (Array.isArray(context2.messages)) {
|
|
30370
|
+
for (let i = context2.messages.length - 1; i >= 0; i--) {
|
|
30371
|
+
const message = context2.messages[i];
|
|
30372
|
+
if (isPiUserMessage(message)) {
|
|
30373
|
+
if (typeof message.content === "string") {
|
|
30374
|
+
lastUserText = message.content;
|
|
30375
|
+
} else {
|
|
30376
|
+
lastUserText = message.content.flatMap((part) => part.type === "text" ? [part.text] : []).join("");
|
|
30377
|
+
}
|
|
30378
|
+
break;
|
|
30379
|
+
}
|
|
30380
|
+
}
|
|
30381
|
+
}
|
|
30382
|
+
if (lastUserText !== void 0) {
|
|
30383
|
+
const queuedMatch = patchState.queuedPromptStates.find(
|
|
30384
|
+
(state) => state.promptText === lastUserText
|
|
30385
|
+
);
|
|
30386
|
+
if (queuedMatch) {
|
|
30387
|
+
return queuedMatch;
|
|
30388
|
+
}
|
|
30389
|
+
const matches = [...patchState.activePromptStates].filter(
|
|
30390
|
+
(state) => state.promptText === lastUserText
|
|
30391
|
+
);
|
|
30392
|
+
if (matches.length === 1) {
|
|
30393
|
+
return matches[0];
|
|
30394
|
+
}
|
|
30395
|
+
}
|
|
30396
|
+
const contextState = currentPiPromptState();
|
|
30397
|
+
if (contextState && patchState.activePromptStates.has(contextState) && (!contextState.queued || lastUserText !== void 0 && contextState.promptText === lastUserText)) {
|
|
30398
|
+
return contextState;
|
|
30399
|
+
}
|
|
30400
|
+
if (patchState.activePromptStates.size === 1) {
|
|
30401
|
+
return [...patchState.activePromptStates][0];
|
|
30402
|
+
}
|
|
30403
|
+
return void 0;
|
|
30404
|
+
}
|
|
30405
|
+
function makeSharedInstrumentedStreamFn(patchState) {
|
|
30406
|
+
return async function instrumentedPiStreamFn(model, context2, options) {
|
|
30407
|
+
const state = resolveStreamPromptState(patchState, context2);
|
|
30408
|
+
if (!state) {
|
|
30409
|
+
const invokeOriginal = () => Reflect.apply(patchState.originalStreamFn, this, [
|
|
30410
|
+
model,
|
|
30411
|
+
context2,
|
|
30412
|
+
options
|
|
30413
|
+
]);
|
|
30414
|
+
return patchState.activePromptStates.size > 0 ? runWithAutoInstrumentationSuppressed(invokeOriginal) : invokeOriginal();
|
|
30415
|
+
}
|
|
30416
|
+
state.sawStreamFn = true;
|
|
30417
|
+
removeQueuedPromptState(state);
|
|
30418
|
+
state.streamPatchState.eventPromptState = state;
|
|
30419
|
+
const llmState = await startPiLlmSpan(state, model, context2, options);
|
|
30420
|
+
try {
|
|
30421
|
+
const stream = await runWithAutoInstrumentationSuppressed(
|
|
30422
|
+
() => Reflect.apply(patchState.originalStreamFn, this, [
|
|
30423
|
+
model,
|
|
30424
|
+
context2,
|
|
30425
|
+
options
|
|
30426
|
+
])
|
|
30427
|
+
);
|
|
30428
|
+
return patchAssistantMessageStream(stream, state, llmState);
|
|
30429
|
+
} catch (error2) {
|
|
30430
|
+
finishPiLlmSpan(state, llmState, void 0, error2);
|
|
30431
|
+
throw error2;
|
|
30432
|
+
}
|
|
30433
|
+
};
|
|
30434
|
+
}
|
|
30435
|
+
async function startPiLlmSpan(state, model, context2, options) {
|
|
30436
|
+
const metadata = {
|
|
30437
|
+
...extractModelMetadata2(model),
|
|
30438
|
+
...extractStreamOptionsMetadata(options),
|
|
30439
|
+
...extractToolMetadata(context2.tools),
|
|
30440
|
+
"pi_coding_agent.operation": "agent.streamFn"
|
|
30441
|
+
};
|
|
30442
|
+
const span = startSpan({
|
|
30443
|
+
event: {
|
|
30444
|
+
input: processInputAttachments(normalizePiContextInput(context2)),
|
|
30445
|
+
metadata
|
|
30446
|
+
},
|
|
30447
|
+
name: getLlmSpanName(model),
|
|
30448
|
+
parent: await state.span.export(),
|
|
30449
|
+
spanAttributes: { type: "llm" /* LLM */ }
|
|
30450
|
+
});
|
|
30451
|
+
const llmState = {
|
|
30452
|
+
finalized: false,
|
|
30453
|
+
metadata,
|
|
30454
|
+
metrics: {},
|
|
30455
|
+
span,
|
|
30456
|
+
startTime: getCurrentUnixTimestamp()
|
|
30457
|
+
};
|
|
30458
|
+
state.activeLlmSpans.add(llmState);
|
|
30459
|
+
return llmState;
|
|
30460
|
+
}
|
|
30461
|
+
function patchAssistantMessageStream(stream, promptState, llmState) {
|
|
30462
|
+
if (!isObject(stream)) {
|
|
30463
|
+
return stream;
|
|
30464
|
+
}
|
|
30465
|
+
const streamRecord = stream;
|
|
30466
|
+
const originalResult = stream.result;
|
|
30467
|
+
if (typeof originalResult === "function") {
|
|
30468
|
+
streamRecord.result = function patchedPiResult() {
|
|
30469
|
+
return Promise.resolve(Reflect.apply(originalResult, this, [])).then(
|
|
30470
|
+
(message) => {
|
|
30471
|
+
finishPiLlmSpan(promptState, llmState, message);
|
|
30472
|
+
return message;
|
|
30473
|
+
},
|
|
30474
|
+
(error2) => {
|
|
30475
|
+
finishPiLlmSpan(promptState, llmState, void 0, error2);
|
|
30476
|
+
throw error2;
|
|
30477
|
+
}
|
|
30478
|
+
);
|
|
30479
|
+
};
|
|
30480
|
+
}
|
|
30481
|
+
const originalIterator = stream[Symbol.asyncIterator];
|
|
30482
|
+
if (typeof originalIterator === "function") {
|
|
30483
|
+
streamRecord[Symbol.asyncIterator] = function patchedPiIterator() {
|
|
30484
|
+
const iterator = Reflect.apply(
|
|
30485
|
+
originalIterator,
|
|
30486
|
+
this,
|
|
30487
|
+
[]
|
|
30488
|
+
);
|
|
30489
|
+
return {
|
|
30490
|
+
async next() {
|
|
30491
|
+
try {
|
|
30492
|
+
const result = await iterator.next();
|
|
30493
|
+
if (result.done) {
|
|
30494
|
+
finishPiLlmSpan(promptState, llmState);
|
|
30495
|
+
return result;
|
|
30496
|
+
}
|
|
30497
|
+
recordPiAssistantMessageEvent(promptState, llmState, result.value);
|
|
30498
|
+
return result;
|
|
30499
|
+
} catch (error2) {
|
|
30500
|
+
finishPiLlmSpan(promptState, llmState, void 0, error2);
|
|
30501
|
+
if (typeof iterator.return === "function") {
|
|
30502
|
+
try {
|
|
30503
|
+
await iterator.return();
|
|
30504
|
+
} catch (cleanupError) {
|
|
30505
|
+
logInstrumentationError4(
|
|
30506
|
+
"Pi Coding Agent stream cleanup",
|
|
30507
|
+
cleanupError
|
|
30508
|
+
);
|
|
30509
|
+
}
|
|
30510
|
+
}
|
|
30511
|
+
throw error2;
|
|
30512
|
+
}
|
|
30513
|
+
},
|
|
30514
|
+
async return(value) {
|
|
30515
|
+
try {
|
|
30516
|
+
if (typeof iterator.return === "function") {
|
|
30517
|
+
return await iterator.return(value);
|
|
30518
|
+
}
|
|
30519
|
+
return {
|
|
30520
|
+
done: true,
|
|
30521
|
+
value
|
|
30522
|
+
};
|
|
30523
|
+
} catch (error2) {
|
|
30524
|
+
finishPiLlmSpan(promptState, llmState, void 0, error2);
|
|
30525
|
+
throw error2;
|
|
30526
|
+
} finally {
|
|
30527
|
+
finishPiLlmSpan(promptState, llmState);
|
|
30528
|
+
}
|
|
30529
|
+
},
|
|
30530
|
+
async throw(error2) {
|
|
30531
|
+
try {
|
|
30532
|
+
if (typeof iterator.throw === "function") {
|
|
30533
|
+
return await iterator.throw(error2);
|
|
30534
|
+
}
|
|
30535
|
+
throw error2;
|
|
30536
|
+
} catch (thrownError) {
|
|
30537
|
+
finishPiLlmSpan(promptState, llmState, void 0, thrownError);
|
|
30538
|
+
throw thrownError;
|
|
30539
|
+
}
|
|
30540
|
+
},
|
|
30541
|
+
[Symbol.asyncIterator]() {
|
|
30542
|
+
return this;
|
|
30543
|
+
}
|
|
30544
|
+
};
|
|
30545
|
+
};
|
|
30546
|
+
}
|
|
30547
|
+
return stream;
|
|
30548
|
+
}
|
|
30549
|
+
function recordPiAssistantMessageEvent(promptState, llmState, event) {
|
|
30550
|
+
recordFirstTokenMetric(llmState, event);
|
|
30551
|
+
const message = "message" in event ? event.message : void 0;
|
|
30552
|
+
const errorMessage2 = "error" in event ? event.error : void 0;
|
|
30553
|
+
if (event.type === "done" && isPiAssistantMessage(message)) {
|
|
30554
|
+
finishPiLlmSpan(promptState, llmState, message);
|
|
30555
|
+
} else if (event.type === "error" && isPiAssistantMessage(errorMessage2)) {
|
|
30556
|
+
finishPiLlmSpan(promptState, llmState, errorMessage2);
|
|
30557
|
+
}
|
|
30558
|
+
}
|
|
30559
|
+
function recordFirstTokenMetric(state, event) {
|
|
30560
|
+
if (state.metrics.time_to_first_token !== void 0 || event.type === "start") {
|
|
30561
|
+
return;
|
|
30562
|
+
}
|
|
30563
|
+
state.metrics.time_to_first_token = getCurrentUnixTimestamp() - state.startTime;
|
|
30564
|
+
}
|
|
30565
|
+
async function handlePiAgentEvent(state, event) {
|
|
30566
|
+
if (state.finalized) {
|
|
30567
|
+
return;
|
|
30568
|
+
}
|
|
30569
|
+
const eventPromptState = state.streamPatchState.eventPromptState;
|
|
30570
|
+
if (eventPromptState && eventPromptState !== state) {
|
|
30571
|
+
return;
|
|
30572
|
+
}
|
|
30573
|
+
if (!eventPromptState && (state.queued || state.streamPatchState.activePromptStates.size > 1 && currentPiPromptState() !== state)) {
|
|
30574
|
+
return;
|
|
30575
|
+
}
|
|
30576
|
+
switch (event.type) {
|
|
30577
|
+
case "message_end":
|
|
30578
|
+
if (isPiAssistantMessage(event.message)) {
|
|
30579
|
+
state.output = extractAssistantOutput(event.message);
|
|
30580
|
+
}
|
|
30581
|
+
return;
|
|
30582
|
+
case "turn_end":
|
|
30583
|
+
state.turnEnded = true;
|
|
30584
|
+
if (isPiAssistantMessage(event.message)) {
|
|
30585
|
+
state.output = extractAssistantOutput(event.message);
|
|
30586
|
+
if (!state.collectedLlmUsageMetrics) {
|
|
30587
|
+
addMetrics(state.metrics, extractUsageMetrics2(event.message.usage));
|
|
30588
|
+
}
|
|
30589
|
+
}
|
|
30590
|
+
if (state.streamPatchState.eventPromptState === state) {
|
|
30591
|
+
state.streamPatchState.eventPromptState = void 0;
|
|
30592
|
+
}
|
|
30593
|
+
if (state.promptCallEnded && state.deferCompletionUntilTurnEnd) {
|
|
30594
|
+
await finalizePiPromptRun(state);
|
|
30595
|
+
}
|
|
30596
|
+
return;
|
|
30597
|
+
case "tool_execution_start":
|
|
30598
|
+
await startPiToolSpan(state, event);
|
|
30599
|
+
return;
|
|
30600
|
+
case "tool_execution_end":
|
|
30601
|
+
finishPiToolSpan(state, event);
|
|
30602
|
+
return;
|
|
30603
|
+
default:
|
|
30604
|
+
return;
|
|
30605
|
+
}
|
|
30606
|
+
}
|
|
30607
|
+
async function startPiToolSpan(state, event) {
|
|
30608
|
+
if (!event.toolCallId || state.activeToolSpans.has(event.toolCallId)) {
|
|
30609
|
+
return;
|
|
30610
|
+
}
|
|
30611
|
+
const restoreAutoInstrumentation = enterAutoInstrumentationAllowed();
|
|
30612
|
+
const metadata = {
|
|
30613
|
+
"gen_ai.tool.call.id": event.toolCallId,
|
|
30614
|
+
"gen_ai.tool.name": event.toolName,
|
|
30615
|
+
"pi_coding_agent.tool.name": event.toolName
|
|
30616
|
+
};
|
|
30617
|
+
try {
|
|
30618
|
+
const span = startSpan({
|
|
30619
|
+
event: {
|
|
30620
|
+
input: event.args,
|
|
30621
|
+
metadata
|
|
30622
|
+
},
|
|
30623
|
+
name: event.toolName || "tool",
|
|
30624
|
+
parent: await state.span.export(),
|
|
30625
|
+
spanAttributes: { type: "tool" /* TOOL */ }
|
|
30626
|
+
});
|
|
30627
|
+
state.activeToolSpans.set(event.toolCallId, {
|
|
30628
|
+
restoreAutoInstrumentation,
|
|
30629
|
+
span
|
|
30630
|
+
});
|
|
30631
|
+
} catch (error2) {
|
|
30632
|
+
restoreAutoInstrumentation();
|
|
30633
|
+
throw error2;
|
|
30634
|
+
}
|
|
30635
|
+
}
|
|
30636
|
+
function finishPiToolSpan(state, event) {
|
|
30637
|
+
const toolState = state.activeToolSpans.get(event.toolCallId);
|
|
30638
|
+
if (!toolState) {
|
|
30639
|
+
return;
|
|
30640
|
+
}
|
|
30641
|
+
state.activeToolSpans.delete(event.toolCallId);
|
|
30642
|
+
const metadata = {
|
|
30643
|
+
"gen_ai.tool.call.id": event.toolCallId,
|
|
30644
|
+
"gen_ai.tool.name": event.toolName,
|
|
30645
|
+
"pi_coding_agent.tool.name": event.toolName,
|
|
30646
|
+
"pi_coding_agent.tool.is_error": event.isError
|
|
30647
|
+
};
|
|
30648
|
+
try {
|
|
30649
|
+
safeLog4(toolState.span, {
|
|
30650
|
+
...event.isError ? { error: stringifyUnknown2(event.result) } : {},
|
|
30651
|
+
metadata,
|
|
30652
|
+
output: event.result
|
|
30653
|
+
});
|
|
30654
|
+
} finally {
|
|
30655
|
+
try {
|
|
30656
|
+
toolState.span.end();
|
|
30657
|
+
} finally {
|
|
30658
|
+
toolState.restoreAutoInstrumentation?.();
|
|
30659
|
+
}
|
|
30660
|
+
}
|
|
30661
|
+
}
|
|
30662
|
+
async function finalizePiPromptRun(state, error2) {
|
|
30663
|
+
if (state.finalized) {
|
|
30664
|
+
return;
|
|
30665
|
+
}
|
|
30666
|
+
state.finalized = true;
|
|
30667
|
+
state.onFinalize?.(state);
|
|
30668
|
+
restorePiStreamFn(state);
|
|
30669
|
+
try {
|
|
30670
|
+
state.unsubscribeAgent?.();
|
|
30671
|
+
} catch (unsubscribeError) {
|
|
30672
|
+
logInstrumentationError4("Pi Coding Agent unsubscribe", unsubscribeError);
|
|
30673
|
+
}
|
|
30674
|
+
await finishOpenLlmSpans(state, error2);
|
|
30675
|
+
finishOpenToolSpans(state, error2);
|
|
30676
|
+
const metadata = {
|
|
30677
|
+
...state.metadata,
|
|
30678
|
+
...extractModelMetadata2(state.agent.state?.model)
|
|
30679
|
+
};
|
|
30680
|
+
try {
|
|
30681
|
+
safeLog4(state.span, {
|
|
30682
|
+
...error2 ? { error: stringifyUnknown2(error2) } : {},
|
|
30683
|
+
metadata,
|
|
30684
|
+
metrics: {
|
|
30685
|
+
...cleanMetrics5(state.metrics),
|
|
30686
|
+
...buildDurationMetrics3(state.startTime)
|
|
30687
|
+
},
|
|
30688
|
+
output: state.output
|
|
30689
|
+
});
|
|
30690
|
+
} finally {
|
|
30691
|
+
state.span.end();
|
|
30692
|
+
}
|
|
30693
|
+
}
|
|
30694
|
+
function restorePiStreamFn(state) {
|
|
30695
|
+
const patchState = state.streamPatchState;
|
|
30696
|
+
patchState.activePromptStates.delete(state);
|
|
30697
|
+
removeQueuedPromptState(state);
|
|
30698
|
+
if (patchState.eventPromptState === state) {
|
|
30699
|
+
patchState.eventPromptState = void 0;
|
|
30700
|
+
}
|
|
30701
|
+
state.restorePromptContext?.();
|
|
30702
|
+
if (patchState.activePromptStates.size > 0) {
|
|
30703
|
+
return;
|
|
30704
|
+
}
|
|
30705
|
+
if (patchState.agent.streamFn === patchState.wrappedStreamFn) {
|
|
30706
|
+
patchState.agent.streamFn = patchState.originalStreamFn;
|
|
30707
|
+
}
|
|
30708
|
+
piStreamPatchStates.delete(patchState.agent);
|
|
30709
|
+
}
|
|
30710
|
+
function removeQueuedPromptState(state) {
|
|
30711
|
+
state.queued = false;
|
|
30712
|
+
const queuedPromptStates = state.streamPatchState.queuedPromptStates;
|
|
30713
|
+
const index = queuedPromptStates.indexOf(state);
|
|
30714
|
+
if (index >= 0) {
|
|
30715
|
+
queuedPromptStates.splice(index, 1);
|
|
30716
|
+
}
|
|
30717
|
+
}
|
|
30718
|
+
async function finishOpenLlmSpans(state, error2) {
|
|
30719
|
+
for (const llmState of [...state.activeLlmSpans]) {
|
|
30720
|
+
finishPiLlmSpan(state, llmState, void 0, error2);
|
|
30721
|
+
}
|
|
30722
|
+
}
|
|
30723
|
+
function finishPiLlmSpan(promptState, llmState, message, error2) {
|
|
30724
|
+
if (llmState.finalized) {
|
|
30725
|
+
return;
|
|
30726
|
+
}
|
|
30727
|
+
llmState.finalized = true;
|
|
30728
|
+
promptState.activeLlmSpans.delete(llmState);
|
|
30729
|
+
const messageError = message?.stopReason === "error" && message.errorMessage;
|
|
30730
|
+
const metrics = {
|
|
30731
|
+
...extractUsageMetrics2(message?.usage),
|
|
30732
|
+
...cleanMetrics5(llmState.metrics),
|
|
30733
|
+
...buildDurationMetrics3(llmState.startTime)
|
|
30734
|
+
};
|
|
30735
|
+
const usageMetrics = extractUsageMetrics2(message?.usage);
|
|
30736
|
+
if (Object.keys(usageMetrics).length > 0) {
|
|
30737
|
+
promptState.collectedLlmUsageMetrics = true;
|
|
30738
|
+
addMetrics(promptState.metrics, usageMetrics);
|
|
30739
|
+
}
|
|
30740
|
+
try {
|
|
30741
|
+
safeLog4(llmState.span, {
|
|
30742
|
+
...error2 || messageError ? { error: stringifyUnknown2(error2 ?? messageError) } : {},
|
|
30743
|
+
metadata: {
|
|
30744
|
+
...llmState.metadata,
|
|
30745
|
+
...message ? extractAssistantMetadata(message) : {}
|
|
30746
|
+
},
|
|
30747
|
+
metrics,
|
|
30748
|
+
...message ? { output: extractAssistantOutput(message) } : {}
|
|
30749
|
+
});
|
|
30750
|
+
} finally {
|
|
30751
|
+
llmState.span.end();
|
|
30752
|
+
}
|
|
30753
|
+
}
|
|
30754
|
+
function finishOpenToolSpans(state, error2) {
|
|
30755
|
+
for (const [, toolState] of state.activeToolSpans) {
|
|
30756
|
+
try {
|
|
30757
|
+
safeLog4(toolState.span, {
|
|
30758
|
+
error: error2 ? stringifyUnknown2(error2) : "Pi tool did not complete"
|
|
30759
|
+
});
|
|
30760
|
+
toolState.span.end();
|
|
30761
|
+
} finally {
|
|
30762
|
+
toolState.restoreAutoInstrumentation?.();
|
|
30763
|
+
}
|
|
30764
|
+
}
|
|
30765
|
+
state.activeToolSpans.clear();
|
|
30766
|
+
}
|
|
30767
|
+
function normalizePiContextInput(context2) {
|
|
30768
|
+
const messages = context2.messages.flatMap(
|
|
30769
|
+
(message) => normalizePiMessage(message)
|
|
30770
|
+
);
|
|
30771
|
+
if (context2.systemPrompt) {
|
|
30772
|
+
return [{ role: "system", content: context2.systemPrompt }, ...messages];
|
|
30773
|
+
}
|
|
30774
|
+
return messages;
|
|
30775
|
+
}
|
|
30776
|
+
function normalizePiMessage(message) {
|
|
30777
|
+
if (isPiUserMessage(message)) {
|
|
30778
|
+
return [
|
|
30779
|
+
{
|
|
30780
|
+
role: "user",
|
|
30781
|
+
content: normalizeUserContent(message.content)
|
|
30782
|
+
}
|
|
30783
|
+
];
|
|
30784
|
+
}
|
|
30785
|
+
if (isPiAssistantMessage(message)) {
|
|
30786
|
+
return [normalizeAssistantMessage(message)];
|
|
30787
|
+
}
|
|
30788
|
+
if (isPiToolResultMessage(message)) {
|
|
30789
|
+
return [normalizeToolResultMessage(message)];
|
|
30790
|
+
}
|
|
30791
|
+
return [];
|
|
30792
|
+
}
|
|
30793
|
+
function normalizeAssistantMessage(message) {
|
|
30794
|
+
const text = message.content.flatMap((part) => part.type === "text" ? [part.text] : []).join("");
|
|
30795
|
+
const thinking = message.content.flatMap(
|
|
30796
|
+
(part) => part.type === "thinking" && !part.redacted ? [part.thinking] : []
|
|
30797
|
+
).join("");
|
|
30798
|
+
const toolCalls = message.content.flatMap(
|
|
30799
|
+
(part) => part.type === "toolCall" ? [normalizeToolCall(part)] : []
|
|
30800
|
+
);
|
|
30801
|
+
return {
|
|
30802
|
+
role: "assistant",
|
|
30803
|
+
content: text || (toolCalls.length > 0 ? null : ""),
|
|
30804
|
+
...thinking ? { reasoning: thinking } : {},
|
|
30805
|
+
...toolCalls.length > 0 ? { tool_calls: toolCalls } : {}
|
|
30806
|
+
};
|
|
30807
|
+
}
|
|
30808
|
+
function normalizeToolResultMessage(message) {
|
|
30809
|
+
return {
|
|
30810
|
+
role: "tool",
|
|
30811
|
+
tool_call_id: message.toolCallId,
|
|
30812
|
+
content: normalizeUserContent(message.content)
|
|
30813
|
+
};
|
|
30814
|
+
}
|
|
30815
|
+
function normalizeUserContent(content) {
|
|
30816
|
+
if (typeof content === "string") {
|
|
30817
|
+
return content;
|
|
30818
|
+
}
|
|
30819
|
+
return content.map((part) => {
|
|
30820
|
+
if (part.type === "text") {
|
|
30821
|
+
return { type: "text", text: part.text };
|
|
30822
|
+
}
|
|
30823
|
+
if (part.type === "image") {
|
|
30824
|
+
return {
|
|
30825
|
+
type: "image_url",
|
|
30826
|
+
image_url: {
|
|
30827
|
+
url: `data:${part.mimeType};base64,${part.data}`
|
|
30828
|
+
}
|
|
30829
|
+
};
|
|
30830
|
+
}
|
|
30831
|
+
return part;
|
|
30832
|
+
});
|
|
30833
|
+
}
|
|
30834
|
+
function normalizeToolCall(toolCall) {
|
|
30835
|
+
return {
|
|
30836
|
+
id: toolCall.id,
|
|
30837
|
+
type: "function",
|
|
30838
|
+
function: {
|
|
30839
|
+
name: toolCall.name,
|
|
30840
|
+
arguments: stringifyArguments(toolCall.arguments)
|
|
30841
|
+
}
|
|
30842
|
+
};
|
|
30843
|
+
}
|
|
30844
|
+
function extractAssistantOutput(message) {
|
|
30845
|
+
return processInputAttachments([
|
|
30846
|
+
{
|
|
30847
|
+
finish_reason: normalizeStopReason(message.stopReason),
|
|
30848
|
+
index: 0,
|
|
30849
|
+
message: normalizeAssistantMessage(message)
|
|
30850
|
+
}
|
|
30851
|
+
]);
|
|
30852
|
+
}
|
|
30853
|
+
function isPiUserMessage(message) {
|
|
30854
|
+
return message.role === "user" && "content" in message;
|
|
30855
|
+
}
|
|
30856
|
+
function isPiAssistantMessage(message) {
|
|
30857
|
+
return isObject(message) && message.role === "assistant" && Array.isArray(message.content);
|
|
30858
|
+
}
|
|
30859
|
+
function isPiToolResultMessage(message) {
|
|
30860
|
+
return message.role === "toolResult" && Array.isArray(message.content);
|
|
30861
|
+
}
|
|
30862
|
+
function normalizeStopReason(reason) {
|
|
30863
|
+
switch (reason) {
|
|
30864
|
+
case "toolUse":
|
|
30865
|
+
return "tool_calls";
|
|
30866
|
+
case "length":
|
|
30867
|
+
case "stop":
|
|
30868
|
+
return reason;
|
|
30869
|
+
default:
|
|
30870
|
+
return reason ?? "stop";
|
|
30871
|
+
}
|
|
30872
|
+
}
|
|
30873
|
+
function extractPromptInput(text, options) {
|
|
30874
|
+
const images = options?.images;
|
|
30875
|
+
if (!images || images.length === 0) {
|
|
30876
|
+
return text;
|
|
30877
|
+
}
|
|
30878
|
+
return processInputAttachments([
|
|
30879
|
+
{
|
|
30880
|
+
role: "user",
|
|
30881
|
+
content: [
|
|
30882
|
+
{ type: "text", text: text ?? "" },
|
|
30883
|
+
...images.map((image) => ({
|
|
30884
|
+
type: "image_url",
|
|
30885
|
+
image_url: {
|
|
30886
|
+
url: `data:${image.mimeType};base64,${image.data}`
|
|
30887
|
+
}
|
|
30888
|
+
}))
|
|
30889
|
+
]
|
|
30890
|
+
}
|
|
30891
|
+
]);
|
|
30892
|
+
}
|
|
30893
|
+
function extractToolMetadata(tools) {
|
|
30894
|
+
if (!tools || tools.length === 0) {
|
|
30895
|
+
return {};
|
|
30896
|
+
}
|
|
30897
|
+
return {
|
|
30898
|
+
tools: tools.map((tool) => ({
|
|
30899
|
+
type: "function",
|
|
30900
|
+
function: {
|
|
30901
|
+
name: tool.name,
|
|
30902
|
+
...tool.description ? { description: tool.description } : {},
|
|
30903
|
+
...tool.parameters ? { parameters: tool.parameters } : {}
|
|
30904
|
+
}
|
|
30905
|
+
}))
|
|
30906
|
+
};
|
|
30907
|
+
}
|
|
30908
|
+
function extractModelMetadata2(model) {
|
|
30909
|
+
if (!model) {
|
|
30910
|
+
return {};
|
|
30911
|
+
}
|
|
30912
|
+
return {
|
|
30913
|
+
...model.provider ? { provider: model.provider } : {},
|
|
30914
|
+
...model.id ? { model: model.id, "pi_coding_agent.model": model.id } : {},
|
|
30915
|
+
...model.api ? { "pi_coding_agent.api": model.api } : {},
|
|
30916
|
+
...model.name ? { "pi_coding_agent.model_name": model.name } : {}
|
|
30917
|
+
};
|
|
30918
|
+
}
|
|
30919
|
+
function extractAssistantMetadata(message) {
|
|
30920
|
+
return {
|
|
30921
|
+
...message.provider ? { provider: message.provider } : {},
|
|
30922
|
+
...message.responseModel || message.model ? { model: message.responseModel ?? message.model } : {},
|
|
30923
|
+
...message.api ? { "pi_coding_agent.api": message.api } : {},
|
|
30924
|
+
...message.model ? { "pi_coding_agent.model": message.model } : {},
|
|
30925
|
+
...message.responseModel ? { "pi_coding_agent.response_model": message.responseModel } : {},
|
|
30926
|
+
...message.responseId ? { "pi_coding_agent.response_id": message.responseId } : {},
|
|
30927
|
+
...message.stopReason ? { "pi_coding_agent.stop_reason": message.stopReason } : {}
|
|
30928
|
+
};
|
|
30929
|
+
}
|
|
30930
|
+
function extractSessionMetadata(session) {
|
|
30931
|
+
return {
|
|
30932
|
+
...extractModelMetadata2(session.model),
|
|
30933
|
+
...session.sessionId ? { "pi_coding_agent.session_id": session.sessionId } : {},
|
|
30934
|
+
...session.sessionName ? { "pi_coding_agent.session_name": session.sessionName } : {},
|
|
30935
|
+
...session.thinkingLevel ? { "pi_coding_agent.thinking_level": session.thinkingLevel } : {},
|
|
30936
|
+
...typeof session.getActiveToolNames === "function" ? { "pi_coding_agent.active_tools": session.getActiveToolNames() } : {}
|
|
30937
|
+
};
|
|
30938
|
+
}
|
|
30939
|
+
function extractPromptOptionsMetadata(options) {
|
|
30940
|
+
if (!options) {
|
|
30941
|
+
return {};
|
|
30942
|
+
}
|
|
30943
|
+
return {
|
|
30944
|
+
...options.source ? { "pi_coding_agent.source": options.source } : {},
|
|
30945
|
+
...options.streamingBehavior ? { "pi_coding_agent.streaming_behavior": options.streamingBehavior } : {},
|
|
30946
|
+
...options.expandPromptTemplates !== void 0 ? {
|
|
30947
|
+
"pi_coding_agent.expand_prompt_templates": options.expandPromptTemplates
|
|
30948
|
+
} : {}
|
|
30949
|
+
};
|
|
30950
|
+
}
|
|
30951
|
+
function extractStreamOptionsMetadata(options) {
|
|
30952
|
+
if (!options) {
|
|
30953
|
+
return {};
|
|
30954
|
+
}
|
|
30955
|
+
return {
|
|
30956
|
+
...options.temperature !== void 0 ? { temperature: options.temperature } : {},
|
|
30957
|
+
...options.maxTokens !== void 0 ? { max_tokens: options.maxTokens } : {},
|
|
30958
|
+
...options.reasoning ? { "pi_coding_agent.reasoning": options.reasoning } : {},
|
|
30959
|
+
...options.transport ? { "pi_coding_agent.transport": options.transport } : {},
|
|
30960
|
+
...options.cacheRetention ? { "pi_coding_agent.cache_retention": options.cacheRetention } : {},
|
|
30961
|
+
...options.sessionId ? { "pi_coding_agent.session_id": options.sessionId } : {},
|
|
30962
|
+
...options.timeoutMs !== void 0 ? { "pi_coding_agent.timeout_ms": options.timeoutMs } : {},
|
|
30963
|
+
...options.maxRetries !== void 0 ? { "pi_coding_agent.max_retries": options.maxRetries } : {},
|
|
30964
|
+
...options.maxRetryDelayMs !== void 0 ? { "pi_coding_agent.max_retry_delay_ms": options.maxRetryDelayMs } : {},
|
|
30965
|
+
...options.metadata ? { "pi_coding_agent.metadata": options.metadata } : {}
|
|
30966
|
+
};
|
|
30967
|
+
}
|
|
30968
|
+
function getLlmSpanName(model) {
|
|
30969
|
+
switch (model.api) {
|
|
30970
|
+
case "anthropic-messages":
|
|
30971
|
+
return "anthropic.messages.create";
|
|
30972
|
+
case "openai-completions":
|
|
30973
|
+
return "Chat Completion";
|
|
30974
|
+
case "openai-responses":
|
|
30975
|
+
case "azure-openai-responses":
|
|
30976
|
+
case "openai-codex-responses":
|
|
30977
|
+
return "openai.responses.create";
|
|
30978
|
+
case "google-generative-ai":
|
|
30979
|
+
case "google-vertex":
|
|
30980
|
+
return "generate_content";
|
|
30981
|
+
case "mistral-conversations":
|
|
30982
|
+
return "mistral.chat.stream";
|
|
30983
|
+
case "bedrock-converse-stream":
|
|
30984
|
+
return "bedrock.converse_stream";
|
|
30985
|
+
default:
|
|
30986
|
+
return "pi_ai.streamSimple";
|
|
30987
|
+
}
|
|
30988
|
+
}
|
|
30989
|
+
function extractUsageMetrics2(usage) {
|
|
30990
|
+
if (!usage) {
|
|
30991
|
+
return {};
|
|
30992
|
+
}
|
|
30993
|
+
return cleanMetrics5({
|
|
30994
|
+
completion_tokens: usage.output,
|
|
30995
|
+
prompt_cache_creation_tokens: usage.cacheWrite,
|
|
30996
|
+
prompt_cached_tokens: usage.cacheRead,
|
|
30997
|
+
prompt_tokens: usage.input,
|
|
30998
|
+
tokens: usage.totalTokens ?? usage.tokens
|
|
30999
|
+
});
|
|
31000
|
+
}
|
|
31001
|
+
function addMetrics(target, source) {
|
|
31002
|
+
for (const [key, value] of Object.entries(source)) {
|
|
31003
|
+
target[key] = (target[key] ?? 0) + value;
|
|
31004
|
+
}
|
|
31005
|
+
}
|
|
31006
|
+
function buildDurationMetrics3(startTime) {
|
|
31007
|
+
const end = getCurrentUnixTimestamp();
|
|
31008
|
+
return {
|
|
31009
|
+
duration: end - startTime,
|
|
31010
|
+
end,
|
|
31011
|
+
start: startTime
|
|
31012
|
+
};
|
|
31013
|
+
}
|
|
31014
|
+
function cleanMetrics5(metrics) {
|
|
31015
|
+
const cleaned = {};
|
|
31016
|
+
for (const [key, value] of Object.entries(metrics)) {
|
|
31017
|
+
if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
|
|
31018
|
+
cleaned[key] = value;
|
|
31019
|
+
}
|
|
31020
|
+
}
|
|
31021
|
+
return cleaned;
|
|
31022
|
+
}
|
|
31023
|
+
function stringifyArguments(value) {
|
|
31024
|
+
if (typeof value === "string") {
|
|
31025
|
+
return value;
|
|
31026
|
+
}
|
|
31027
|
+
try {
|
|
31028
|
+
return JSON.stringify(value);
|
|
31029
|
+
} catch {
|
|
31030
|
+
return stringifyUnknown2(value);
|
|
31031
|
+
}
|
|
31032
|
+
}
|
|
31033
|
+
function stringifyUnknown2(value) {
|
|
31034
|
+
if (value instanceof Error) {
|
|
31035
|
+
return value.message;
|
|
31036
|
+
}
|
|
31037
|
+
if (typeof value === "string") {
|
|
31038
|
+
return value;
|
|
31039
|
+
}
|
|
31040
|
+
try {
|
|
31041
|
+
return JSON.stringify(value);
|
|
31042
|
+
} catch {
|
|
31043
|
+
return String(value);
|
|
31044
|
+
}
|
|
31045
|
+
}
|
|
31046
|
+
function safeLog4(span, event) {
|
|
31047
|
+
try {
|
|
31048
|
+
span.log(event);
|
|
31049
|
+
} catch (error2) {
|
|
31050
|
+
logInstrumentationError4("Pi Coding Agent span log", error2);
|
|
31051
|
+
}
|
|
31052
|
+
}
|
|
31053
|
+
function logInstrumentationError4(context2, error2) {
|
|
31054
|
+
debugLogger.debug(`${context2}:`, error2);
|
|
31055
|
+
}
|
|
31056
|
+
|
|
28981
31057
|
// src/instrumentation/braintrust-plugin.ts
|
|
28982
31058
|
function getIntegrationConfig(integrations, key) {
|
|
28983
31059
|
return integrations[key];
|
|
@@ -29003,6 +31079,7 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
29003
31079
|
gitHubCopilotPlugin = null;
|
|
29004
31080
|
fluePlugin = null;
|
|
29005
31081
|
langChainPlugin = null;
|
|
31082
|
+
piCodingAgentPlugin = null;
|
|
29006
31083
|
constructor(config3 = {}) {
|
|
29007
31084
|
super();
|
|
29008
31085
|
this.config = config3;
|
|
@@ -29077,6 +31154,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
29077
31154
|
this.gitHubCopilotPlugin = new GitHubCopilotPlugin();
|
|
29078
31155
|
this.gitHubCopilotPlugin.enable();
|
|
29079
31156
|
}
|
|
31157
|
+
if (integrations.piCodingAgent !== false) {
|
|
31158
|
+
this.piCodingAgentPlugin = new PiCodingAgentPlugin();
|
|
31159
|
+
this.piCodingAgentPlugin.enable();
|
|
31160
|
+
}
|
|
29080
31161
|
if (getIntegrationConfig(integrations, "flue") !== false) {
|
|
29081
31162
|
this.fluePlugin = new FluePlugin();
|
|
29082
31163
|
this.fluePlugin.enable();
|
|
@@ -29155,6 +31236,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
29155
31236
|
this.gitHubCopilotPlugin.disable();
|
|
29156
31237
|
this.gitHubCopilotPlugin = null;
|
|
29157
31238
|
}
|
|
31239
|
+
if (this.piCodingAgentPlugin) {
|
|
31240
|
+
this.piCodingAgentPlugin.disable();
|
|
31241
|
+
this.piCodingAgentPlugin = null;
|
|
31242
|
+
}
|
|
29158
31243
|
if (this.fluePlugin) {
|
|
29159
31244
|
this.fluePlugin.disable();
|
|
29160
31245
|
this.fluePlugin = null;
|
|
@@ -29174,6 +31259,11 @@ var envIntegrationAliases = {
|
|
|
29174
31259
|
openaicodexsdk: "openaiCodexSDK",
|
|
29175
31260
|
codex: "openaiCodexSDK",
|
|
29176
31261
|
"codex-sdk": "openaiCodexSDK",
|
|
31262
|
+
"pi-coding-agent": "piCodingAgent",
|
|
31263
|
+
"pi-coding-agent-sdk": "piCodingAgent",
|
|
31264
|
+
picodingagent: "piCodingAgent",
|
|
31265
|
+
picodingagentsdk: "piCodingAgent",
|
|
31266
|
+
"@earendil-works/pi-coding-agent": "piCodingAgent",
|
|
29177
31267
|
anthropic: "anthropic",
|
|
29178
31268
|
aisdk: "aisdk",
|
|
29179
31269
|
"ai-sdk": "aisdk",
|
|
@@ -29239,7 +31329,8 @@ function getDefaultInstrumentationIntegrations() {
|
|
|
29239
31329
|
genkit: true,
|
|
29240
31330
|
gitHubCopilot: true,
|
|
29241
31331
|
langchain: true,
|
|
29242
|
-
langgraph: true
|
|
31332
|
+
langgraph: true,
|
|
31333
|
+
piCodingAgent: true
|
|
29243
31334
|
};
|
|
29244
31335
|
}
|
|
29245
31336
|
function readDisabledInstrumentationEnvConfig(disabledList) {
|
|
@@ -29970,6 +32061,7 @@ var Project2 = class {
|
|
|
29970
32061
|
prompts;
|
|
29971
32062
|
parameters;
|
|
29972
32063
|
scorers;
|
|
32064
|
+
classifiers;
|
|
29973
32065
|
_publishableCodeFunctions = [];
|
|
29974
32066
|
_publishablePrompts = [];
|
|
29975
32067
|
_publishableParameters = [];
|
|
@@ -29981,6 +32073,7 @@ var Project2 = class {
|
|
|
29981
32073
|
this.prompts = new PromptBuilder(this);
|
|
29982
32074
|
this.parameters = new ParametersBuilder(this);
|
|
29983
32075
|
this.scorers = new ScorerBuilder(this);
|
|
32076
|
+
this.classifiers = new ClassifierBuilder(this);
|
|
29984
32077
|
}
|
|
29985
32078
|
addPrompt(prompt) {
|
|
29986
32079
|
this._publishablePrompts.push(prompt);
|
|
@@ -30115,6 +32208,28 @@ var ScorerBuilder = class {
|
|
|
30115
32208
|
}
|
|
30116
32209
|
}
|
|
30117
32210
|
};
|
|
32211
|
+
var ClassifierBuilder = class {
|
|
32212
|
+
constructor(project) {
|
|
32213
|
+
this.project = project;
|
|
32214
|
+
}
|
|
32215
|
+
taskCounter = 0;
|
|
32216
|
+
create(opts) {
|
|
32217
|
+
this.taskCounter++;
|
|
32218
|
+
let resolvedName = opts.name ?? opts.handler.name;
|
|
32219
|
+
if (!resolvedName || resolvedName.trim().length === 0) {
|
|
32220
|
+
resolvedName = `Classifier ${isomorph_default.basename(currentFilename)} ${this.taskCounter}`;
|
|
32221
|
+
}
|
|
32222
|
+
const slug = opts.slug ?? slugify(resolvedName, { lower: true, strict: true });
|
|
32223
|
+
const classifier = new CodeFunction(this.project, {
|
|
32224
|
+
...opts,
|
|
32225
|
+
name: resolvedName,
|
|
32226
|
+
slug,
|
|
32227
|
+
type: "classifier"
|
|
32228
|
+
});
|
|
32229
|
+
this.project.addCodeFunction(classifier);
|
|
32230
|
+
return classifier;
|
|
32231
|
+
}
|
|
32232
|
+
};
|
|
30118
32233
|
var CodeFunction = class {
|
|
30119
32234
|
constructor(project, opts) {
|
|
30120
32235
|
this.project = project;
|
|
@@ -31445,7 +33560,7 @@ var serializedParametersContainerSchema = import_v315.z.union([
|
|
|
31445
33560
|
staticParametersSchema
|
|
31446
33561
|
]);
|
|
31447
33562
|
var evaluatorDefinitionSchema = import_v315.z.object({
|
|
31448
|
-
parameters: serializedParametersContainerSchema.
|
|
33563
|
+
parameters: serializedParametersContainerSchema.nullish(),
|
|
31449
33564
|
scores: import_v315.z.array(import_v315.z.object({ name: import_v315.z.string() })).optional(),
|
|
31450
33565
|
classifiers: import_v315.z.array(import_v315.z.object({ name: import_v315.z.string() })).optional()
|
|
31451
33566
|
});
|