braintrust 3.17.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/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 +2219 -118
- 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 +10 -10
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",
|
|
@@ -1419,14 +1419,14 @@ var require_package = __commonJS({
|
|
|
1419
1419
|
"eslint-plugin-node-import": "^1.0.5",
|
|
1420
1420
|
openai: "6.25.0",
|
|
1421
1421
|
rollup: "^4.60.3",
|
|
1422
|
-
tar: "^7.5.
|
|
1422
|
+
tar: "^7.5.16",
|
|
1423
1423
|
tinybench: "^4.0.1",
|
|
1424
1424
|
tsup: "^8.5.1",
|
|
1425
1425
|
tsx: "^4.21.0",
|
|
1426
1426
|
typedoc: "^0.25.13",
|
|
1427
1427
|
"typedoc-plugin-markdown": "^3.17.1",
|
|
1428
1428
|
typescript: "5.4.4",
|
|
1429
|
-
vite: "^6.4.
|
|
1429
|
+
vite: "^6.4.3",
|
|
1430
1430
|
"vite-tsconfig-paths": "^4.3.2",
|
|
1431
1431
|
vitest: "4.1.5",
|
|
1432
1432
|
webpack: "^5.106.2",
|
|
@@ -1462,13 +1462,13 @@ var require_package = __commonJS({
|
|
|
1462
1462
|
zod: "^3.25.34 || ^4.0"
|
|
1463
1463
|
},
|
|
1464
1464
|
optionalDependencies: {
|
|
1465
|
-
"@braintrust/bt-darwin-arm64": "0.
|
|
1466
|
-
"@braintrust/bt-darwin-x64": "0.
|
|
1467
|
-
"@braintrust/bt-linux-arm64": "0.
|
|
1468
|
-
"@braintrust/bt-linux-x64": "0.
|
|
1469
|
-
"@braintrust/bt-linux-x64-musl": "0.
|
|
1470
|
-
"@braintrust/bt-win32-arm64": "0.
|
|
1471
|
-
"@braintrust/bt-win32-x64": "0.
|
|
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
1472
|
},
|
|
1473
1473
|
publishConfig: {
|
|
1474
1474
|
access: "public",
|
|
@@ -9133,6 +9133,10 @@ var Experiment2 = class extends ObjectFetcher {
|
|
|
9133
9133
|
return (await this.lazyMetadata.get()).project;
|
|
9134
9134
|
})();
|
|
9135
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
|
+
}
|
|
9136
9140
|
parentObjectType() {
|
|
9137
9141
|
return 1 /* EXPERIMENT */;
|
|
9138
9142
|
}
|
|
@@ -9273,6 +9277,14 @@ var Experiment2 = class extends ObjectFetcher {
|
|
|
9273
9277
|
comparisonExperimentId = baseExperiment.id;
|
|
9274
9278
|
comparisonExperimentName = baseExperiment.name;
|
|
9275
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
|
+
}
|
|
9276
9288
|
}
|
|
9277
9289
|
try {
|
|
9278
9290
|
const results = await state.apiConn().get_json(
|
|
@@ -12257,6 +12269,13 @@ var EvalResultWithSummary = class {
|
|
|
12257
12269
|
};
|
|
12258
12270
|
}
|
|
12259
12271
|
};
|
|
12272
|
+
async function getPersistedBaseExperimentId(experiment) {
|
|
12273
|
+
try {
|
|
12274
|
+
return await experiment._getBaseExperimentId();
|
|
12275
|
+
} catch {
|
|
12276
|
+
return void 0;
|
|
12277
|
+
}
|
|
12278
|
+
}
|
|
12260
12279
|
function makeEvalName(projectName, experimentName) {
|
|
12261
12280
|
let out = projectName;
|
|
12262
12281
|
if (experimentName) {
|
|
@@ -12646,6 +12665,14 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
|
|
|
12646
12665
|
return;
|
|
12647
12666
|
}
|
|
12648
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);
|
|
12649
12676
|
const baseEvent = {
|
|
12650
12677
|
name: "eval",
|
|
12651
12678
|
spanAttributes: {
|
|
@@ -12655,13 +12682,7 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
|
|
|
12655
12682
|
input: datum.input,
|
|
12656
12683
|
expected: "expected" in datum ? datum.expected : void 0,
|
|
12657
12684
|
tags: datum.tags,
|
|
12658
|
-
origin
|
|
12659
|
-
object_type: "dataset",
|
|
12660
|
-
object_id: await eventDataset.id,
|
|
12661
|
-
id: datum.id,
|
|
12662
|
-
created: datum.created,
|
|
12663
|
-
_xact_id: datum._xact_id
|
|
12664
|
-
} : void 0,
|
|
12685
|
+
origin,
|
|
12665
12686
|
...datum.upsert_id ? { id: datum.upsert_id } : {}
|
|
12666
12687
|
}
|
|
12667
12688
|
};
|
|
@@ -13018,8 +13039,10 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
|
|
|
13018
13039
|
collectedResults.length = 0;
|
|
13019
13040
|
}
|
|
13020
13041
|
}
|
|
13042
|
+
const comparisonExperimentId = experiment ? evaluator.baseExperimentId ?? await getPersistedBaseExperimentId(experiment) : void 0;
|
|
13021
13043
|
const summary = experiment ? await experiment.summarize({
|
|
13022
|
-
summarizeScores: evaluator.summarizeScores
|
|
13044
|
+
summarizeScores: evaluator.summarizeScores,
|
|
13045
|
+
...comparisonExperimentId !== void 0 ? { comparisonExperimentId } : {}
|
|
13023
13046
|
}) : buildLocalSummary(
|
|
13024
13047
|
evaluator,
|
|
13025
13048
|
collectResults ? collectedResults : [],
|
|
@@ -14287,6 +14310,64 @@ var BasePlugin = class {
|
|
|
14287
14310
|
}
|
|
14288
14311
|
};
|
|
14289
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
|
+
|
|
14290
14371
|
// src/instrumentation/core/channel-tracing.ts
|
|
14291
14372
|
function isSyncStreamLike(value) {
|
|
14292
14373
|
return !!value && typeof value === "object" && typeof value.on === "function";
|
|
@@ -14318,16 +14399,33 @@ function startSpanForEvent(config3, event, channelName) {
|
|
|
14318
14399
|
metadata: mergeInputMetadata(metadata, spanInfoMetadata)
|
|
14319
14400
|
});
|
|
14320
14401
|
} catch (error2) {
|
|
14321
|
-
|
|
14402
|
+
debugLogger.error(`Error extracting input for ${channelName}:`, error2);
|
|
14322
14403
|
}
|
|
14323
14404
|
return { span, startTime };
|
|
14324
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
|
+
}
|
|
14325
14420
|
function ensureSpanStateForEvent(states, config3, event, channelName) {
|
|
14326
14421
|
const key = event;
|
|
14327
14422
|
const existing = states.get(key);
|
|
14328
14423
|
if (existing) {
|
|
14329
14424
|
return existing;
|
|
14330
14425
|
}
|
|
14426
|
+
if (!shouldTraceEvent(config3, event, channelName)) {
|
|
14427
|
+
return void 0;
|
|
14428
|
+
}
|
|
14331
14429
|
const created = startSpanForEvent(config3, event, channelName);
|
|
14332
14430
|
states.set(key, created);
|
|
14333
14431
|
return created;
|
|
@@ -14343,13 +14441,16 @@ function bindCurrentSpanStoreToStart(tracingChannel2, states, config3, channelNa
|
|
|
14343
14441
|
startChannel.bindStore(
|
|
14344
14442
|
currentSpanStore,
|
|
14345
14443
|
(event) => {
|
|
14346
|
-
|
|
14444
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
14445
|
+
return currentSpanStore.getStore();
|
|
14446
|
+
}
|
|
14447
|
+
const spanState = ensureSpanStateForEvent(
|
|
14347
14448
|
states,
|
|
14348
14449
|
config3,
|
|
14349
14450
|
event,
|
|
14350
14451
|
channelName
|
|
14351
|
-
)
|
|
14352
|
-
return contextManager.wrapSpanForStore(span);
|
|
14452
|
+
);
|
|
14453
|
+
return spanState ? contextManager.wrapSpanForStore(spanState.span) : currentSpanStore.getStore();
|
|
14353
14454
|
}
|
|
14354
14455
|
);
|
|
14355
14456
|
return () => {
|
|
@@ -14384,7 +14485,10 @@ function runStreamingCompletionHook(args) {
|
|
|
14384
14485
|
startTime: args.startTime
|
|
14385
14486
|
});
|
|
14386
14487
|
} catch (error2) {
|
|
14387
|
-
|
|
14488
|
+
debugLogger.error(
|
|
14489
|
+
`Error in onComplete hook for ${args.channelName}:`,
|
|
14490
|
+
error2
|
|
14491
|
+
);
|
|
14388
14492
|
}
|
|
14389
14493
|
}
|
|
14390
14494
|
function traceAsyncChannel(channel2, config3) {
|
|
@@ -14399,6 +14503,9 @@ function traceAsyncChannel(channel2, config3) {
|
|
|
14399
14503
|
);
|
|
14400
14504
|
const handlers = {
|
|
14401
14505
|
start: (event) => {
|
|
14506
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
14507
|
+
return;
|
|
14508
|
+
}
|
|
14402
14509
|
ensureSpanStateForEvent(
|
|
14403
14510
|
states,
|
|
14404
14511
|
config3,
|
|
@@ -14433,7 +14540,7 @@ function traceAsyncChannel(channel2, config3) {
|
|
|
14433
14540
|
metrics
|
|
14434
14541
|
});
|
|
14435
14542
|
} catch (error2) {
|
|
14436
|
-
|
|
14543
|
+
debugLogger.error(`Error extracting output for ${channelName}:`, error2);
|
|
14437
14544
|
} finally {
|
|
14438
14545
|
span.end();
|
|
14439
14546
|
states.delete(event);
|
|
@@ -14461,6 +14568,9 @@ function traceStreamingChannel(channel2, config3) {
|
|
|
14461
14568
|
);
|
|
14462
14569
|
const handlers = {
|
|
14463
14570
|
start: (event) => {
|
|
14571
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
14572
|
+
return;
|
|
14573
|
+
}
|
|
14464
14574
|
ensureSpanStateForEvent(
|
|
14465
14575
|
states,
|
|
14466
14576
|
config3,
|
|
@@ -14532,7 +14642,7 @@ function traceStreamingChannel(channel2, config3) {
|
|
|
14532
14642
|
metrics
|
|
14533
14643
|
});
|
|
14534
14644
|
} catch (error2) {
|
|
14535
|
-
|
|
14645
|
+
debugLogger.error(
|
|
14536
14646
|
`Error extracting output for ${channelName}:`,
|
|
14537
14647
|
error2
|
|
14538
14648
|
);
|
|
@@ -14592,7 +14702,7 @@ function traceStreamingChannel(channel2, config3) {
|
|
|
14592
14702
|
metrics
|
|
14593
14703
|
});
|
|
14594
14704
|
} catch (error2) {
|
|
14595
|
-
|
|
14705
|
+
debugLogger.error(`Error extracting output for ${channelName}:`, error2);
|
|
14596
14706
|
} finally {
|
|
14597
14707
|
span.end();
|
|
14598
14708
|
states.delete(event);
|
|
@@ -14620,6 +14730,9 @@ function traceSyncStreamChannel(channel2, config3) {
|
|
|
14620
14730
|
);
|
|
14621
14731
|
const handlers = {
|
|
14622
14732
|
start: (event) => {
|
|
14733
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
14734
|
+
return;
|
|
14735
|
+
}
|
|
14623
14736
|
ensureSpanStateForEvent(
|
|
14624
14737
|
states,
|
|
14625
14738
|
config3,
|
|
@@ -14673,7 +14786,7 @@ function traceSyncStreamChannel(channel2, config3) {
|
|
|
14673
14786
|
});
|
|
14674
14787
|
}
|
|
14675
14788
|
} catch (error2) {
|
|
14676
|
-
|
|
14789
|
+
debugLogger.error(
|
|
14677
14790
|
`Error extracting chatCompletion for ${channelName}:`,
|
|
14678
14791
|
error2
|
|
14679
14792
|
);
|
|
@@ -14697,7 +14810,10 @@ function traceSyncStreamChannel(channel2, config3) {
|
|
|
14697
14810
|
span.log(extracted);
|
|
14698
14811
|
}
|
|
14699
14812
|
} catch (error2) {
|
|
14700
|
-
|
|
14813
|
+
debugLogger.error(
|
|
14814
|
+
`Error extracting event for ${channelName}:`,
|
|
14815
|
+
error2
|
|
14816
|
+
);
|
|
14701
14817
|
}
|
|
14702
14818
|
});
|
|
14703
14819
|
stream.on("end", () => {
|
|
@@ -16226,6 +16342,9 @@ var AnthropicPlugin = class extends BasePlugin {
|
|
|
16226
16342
|
const states = /* @__PURE__ */ new WeakMap();
|
|
16227
16343
|
const handlers = {
|
|
16228
16344
|
start: (event) => {
|
|
16345
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
16346
|
+
return;
|
|
16347
|
+
}
|
|
16229
16348
|
const params = event.arguments[0] ?? {};
|
|
16230
16349
|
const span = startSpan({
|
|
16231
16350
|
name: "anthropic.beta.messages.toolRunner",
|
|
@@ -16955,6 +17074,520 @@ function serializeAISDKToolsForLogging(tools) {
|
|
|
16955
17074
|
return serialized;
|
|
16956
17075
|
}
|
|
16957
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
|
+
|
|
16958
17591
|
// src/instrumentation/plugins/ai-sdk-channels.ts
|
|
16959
17592
|
var aiSDKChannels = defineChannels("ai", {
|
|
16960
17593
|
generateText: channel({
|
|
@@ -17014,6 +17647,10 @@ var aiSDKChannels = defineChannels("ai", {
|
|
|
17014
17647
|
toolLoopAgentStream: channel({
|
|
17015
17648
|
channelName: "ToolLoopAgent.stream",
|
|
17016
17649
|
kind: "async"
|
|
17650
|
+
}),
|
|
17651
|
+
v7CreateTelemetryDispatcher: channel({
|
|
17652
|
+
channelName: "createTelemetryDispatcher",
|
|
17653
|
+
kind: "sync-stream"
|
|
17017
17654
|
})
|
|
17018
17655
|
});
|
|
17019
17656
|
|
|
@@ -17034,9 +17671,30 @@ var DEFAULT_DENY_OUTPUT_PATHS = [
|
|
|
17034
17671
|
];
|
|
17035
17672
|
var AUTO_PATCHED_MODEL = /* @__PURE__ */ Symbol.for("braintrust.ai-sdk.auto-patched-model");
|
|
17036
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
|
+
);
|
|
17037
17677
|
var RUNTIME_DENY_OUTPUT_PATHS = /* @__PURE__ */ Symbol.for(
|
|
17038
17678
|
"braintrust.ai-sdk.deny-output-paths"
|
|
17039
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
|
+
];
|
|
17040
17698
|
var AISDKPlugin = class extends BasePlugin {
|
|
17041
17699
|
config;
|
|
17042
17700
|
constructor(config3 = {}) {
|
|
@@ -17051,6 +17709,7 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
17051
17709
|
}
|
|
17052
17710
|
subscribeToAISDK() {
|
|
17053
17711
|
const denyOutputPaths = this.config.denyOutputPaths || DEFAULT_DENY_OUTPUT_PATHS;
|
|
17712
|
+
this.unsubscribers.push(subscribeToAISDKV7TelemetryDispatcher());
|
|
17054
17713
|
this.unsubscribers.push(
|
|
17055
17714
|
traceStreamingChannel(aiSDKChannels.generateText, {
|
|
17056
17715
|
name: "generateText",
|
|
@@ -17275,10 +17934,61 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
17275
17934
|
);
|
|
17276
17935
|
}
|
|
17277
17936
|
};
|
|
17278
|
-
function
|
|
17279
|
-
|
|
17280
|
-
|
|
17281
|
-
|
|
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;
|
|
17991
|
+
}
|
|
17282
17992
|
const firstArgument2 = event?.arguments && event.arguments.length > 0 ? event.arguments[0] : void 0;
|
|
17283
17993
|
if (!firstArgument2 || typeof firstArgument2 !== "object") {
|
|
17284
17994
|
return defaultDenyOutputPaths;
|
|
@@ -17726,11 +18436,11 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
|
|
|
17726
18436
|
metadata: baseMetadata
|
|
17727
18437
|
}
|
|
17728
18438
|
});
|
|
18439
|
+
const streamStartTime = getCurrentUnixTimestamp();
|
|
17729
18440
|
const result = await withCurrent(
|
|
17730
18441
|
span,
|
|
17731
18442
|
() => Reflect.apply(originalDoStream, resolvedModel, [options])
|
|
17732
18443
|
);
|
|
17733
|
-
const streamStartTime = getCurrentUnixTimestamp();
|
|
17734
18444
|
let firstChunkTime;
|
|
17735
18445
|
const output = {};
|
|
17736
18446
|
let text = "";
|
|
@@ -17739,7 +18449,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
|
|
|
17739
18449
|
let object = void 0;
|
|
17740
18450
|
const transformStream = new TransformStream({
|
|
17741
18451
|
transform(chunk, controller) {
|
|
17742
|
-
if (firstChunkTime === void 0) {
|
|
18452
|
+
if (firstChunkTime === void 0 && isAISDKContentStreamChunk(chunk)) {
|
|
17743
18453
|
firstChunkTime = getCurrentUnixTimestamp();
|
|
17744
18454
|
}
|
|
17745
18455
|
switch (chunk.type) {
|
|
@@ -17931,6 +18641,78 @@ function finalizeAISDKChildTracing(event) {
|
|
|
17931
18641
|
delete event.__braintrust_ai_sdk_cleanup;
|
|
17932
18642
|
}
|
|
17933
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
|
+
}
|
|
17934
18716
|
function patchAISDKStreamingResult(args) {
|
|
17935
18717
|
const { defaultDenyOutputPaths, endEvent, result, span, startTime } = args;
|
|
17936
18718
|
if (!result || typeof result !== "object") {
|
|
@@ -17943,7 +18725,7 @@ function patchAISDKStreamingResult(args) {
|
|
|
17943
18725
|
const wrappedBaseStream = resultRecord.baseStream.pipeThrough(
|
|
17944
18726
|
new TransformStream({
|
|
17945
18727
|
transform(chunk, controller) {
|
|
17946
|
-
if (firstChunkTime2 === void 0) {
|
|
18728
|
+
if (firstChunkTime2 === void 0 && isAISDKContentStreamChunk(chunk)) {
|
|
17947
18729
|
firstChunkTime2 = getCurrentUnixTimestamp();
|
|
17948
18730
|
}
|
|
17949
18731
|
controller.enqueue(chunk);
|
|
@@ -17987,8 +18769,8 @@ function patchAISDKStreamingResult(args) {
|
|
|
17987
18769
|
}
|
|
17988
18770
|
let firstChunkTime;
|
|
17989
18771
|
const wrappedStream = createPatchedAsyncIterable(streamField.stream, {
|
|
17990
|
-
onChunk: () => {
|
|
17991
|
-
if (firstChunkTime === void 0) {
|
|
18772
|
+
onChunk: (chunk) => {
|
|
18773
|
+
if (firstChunkTime === void 0 && isAISDKContentAsyncIterableChunk(chunk)) {
|
|
17992
18774
|
firstChunkTime = getCurrentUnixTimestamp();
|
|
17993
18775
|
}
|
|
17994
18776
|
},
|
|
@@ -18960,15 +19742,17 @@ function collectLocalMcpServerToolHookNames(serverName, serverConfig) {
|
|
|
18960
19742
|
|
|
18961
19743
|
// src/instrumentation/plugins/claude-agent-sdk-plugin.ts
|
|
18962
19744
|
var ROOT_LLM_PARENT_KEY = "__root__";
|
|
19745
|
+
var SUB_AGENT_PROMPT_SOURCE_PRIORITY = {
|
|
19746
|
+
delegation: 0,
|
|
19747
|
+
lifecycle: 1,
|
|
19748
|
+
sidechain: 2
|
|
19749
|
+
};
|
|
18963
19750
|
function llmParentKey(parentToolUseId) {
|
|
18964
19751
|
return parentToolUseId ?? ROOT_LLM_PARENT_KEY;
|
|
18965
19752
|
}
|
|
18966
19753
|
function isSubAgentDelegationToolName(toolName) {
|
|
18967
19754
|
return toolName === "Agent" || toolName === "Task";
|
|
18968
19755
|
}
|
|
18969
|
-
function shouldParentToolAsTaskSibling(toolName) {
|
|
18970
|
-
return toolName === "Agent" || toolName === "Task" || toolName === "Bash";
|
|
18971
|
-
}
|
|
18972
19756
|
function filterSerializableOptions(options) {
|
|
18973
19757
|
const allowedKeys = [
|
|
18974
19758
|
"model",
|
|
@@ -19105,26 +19889,39 @@ function extractUsageFromMessage(message) {
|
|
|
19105
19889
|
}
|
|
19106
19890
|
return metrics;
|
|
19107
19891
|
}
|
|
19108
|
-
function buildLLMInput(
|
|
19109
|
-
const promptMessages = [];
|
|
19110
|
-
if (typeof prompt === "string") {
|
|
19111
|
-
promptMessages.push({ content: prompt, role: "user" });
|
|
19112
|
-
} else if (capturedPromptMessages && capturedPromptMessages.length > 0) {
|
|
19113
|
-
for (const msg of capturedPromptMessages) {
|
|
19114
|
-
const role = msg.message?.role;
|
|
19115
|
-
const content = msg.message?.content;
|
|
19116
|
-
if (role && content !== void 0) {
|
|
19117
|
-
promptMessages.push({ content, role });
|
|
19118
|
-
}
|
|
19119
|
-
}
|
|
19120
|
-
}
|
|
19892
|
+
function buildLLMInput(promptMessages, conversationHistory) {
|
|
19121
19893
|
const inputParts = [...promptMessages, ...conversationHistory];
|
|
19122
19894
|
return inputParts.length > 0 ? inputParts : void 0;
|
|
19123
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
|
+
}
|
|
19124
19921
|
function formatCapturedMessages(messages) {
|
|
19125
19922
|
return messages.length > 0 ? messages : [];
|
|
19126
19923
|
}
|
|
19127
|
-
async function createLLMSpanForMessages(messages,
|
|
19924
|
+
async function createLLMSpanForMessages(messages, promptMessages, conversationHistory, options, startTime, parentSpan, existingSpan) {
|
|
19128
19925
|
if (messages.length === 0) {
|
|
19129
19926
|
return void 0;
|
|
19130
19927
|
}
|
|
@@ -19134,11 +19931,7 @@ async function createLLMSpanForMessages(messages, prompt, conversationHistory, o
|
|
|
19134
19931
|
}
|
|
19135
19932
|
const model = lastMessage.message.model || options.model;
|
|
19136
19933
|
const usage = extractUsageFromMessage(lastMessage);
|
|
19137
|
-
const input = buildLLMInput(
|
|
19138
|
-
prompt,
|
|
19139
|
-
conversationHistory,
|
|
19140
|
-
capturedPromptMessages
|
|
19141
|
-
);
|
|
19934
|
+
const input = buildLLMInput(promptMessages, conversationHistory);
|
|
19142
19935
|
const outputs = messages.map(
|
|
19143
19936
|
(m) => m.message?.content && m.message?.role ? { content: m.message.content, role: m.message.role } : void 0
|
|
19144
19937
|
).filter(
|
|
@@ -19269,8 +20062,7 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
|
|
|
19269
20062
|
},
|
|
19270
20063
|
name: parsed.displayName,
|
|
19271
20064
|
parent: await resolveParentSpan(toolUseID, {
|
|
19272
|
-
agentId: input.agent_id
|
|
19273
|
-
preferTaskSiblingParent: shouldParentToolAsTaskSibling(parsed.toolName)
|
|
20065
|
+
agentId: input.agent_id
|
|
19274
20066
|
}),
|
|
19275
20067
|
spanAttributes: { type: "tool" /* TOOL */ }
|
|
19276
20068
|
});
|
|
@@ -19516,12 +20308,37 @@ function injectTracingHooks(options, resolveParentSpan, activeToolSpans, localTo
|
|
|
19516
20308
|
}
|
|
19517
20309
|
};
|
|
19518
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
|
+
}
|
|
19519
20331
|
async function finalizeCurrentMessageGroup(state) {
|
|
19520
20332
|
if (state.currentMessages.length === 0) {
|
|
19521
20333
|
return;
|
|
19522
20334
|
}
|
|
19523
20335
|
const parentToolUseId = state.currentMessages[0]?.parent_tool_use_id ?? null;
|
|
19524
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
|
+
);
|
|
19525
20342
|
let parentSpan = await state.span.export();
|
|
19526
20343
|
if (parentToolUseId) {
|
|
19527
20344
|
const subAgentSpan = state.subAgentSpans.get(parentToolUseId);
|
|
@@ -19532,11 +20349,10 @@ async function finalizeCurrentMessageGroup(state) {
|
|
|
19532
20349
|
const existingLlmSpan = state.activeLlmSpansByParentToolUse.get(parentKey);
|
|
19533
20350
|
const llmSpanResult = await createLLMSpanForMessages(
|
|
19534
20351
|
state.currentMessages,
|
|
19535
|
-
|
|
19536
|
-
|
|
20352
|
+
promptMessages,
|
|
20353
|
+
conversationHistory,
|
|
19537
20354
|
state.options,
|
|
19538
20355
|
state.currentMessageStartTime,
|
|
19539
|
-
state.capturedPromptMessages,
|
|
19540
20356
|
parentSpan,
|
|
19541
20357
|
existingLlmSpan
|
|
19542
20358
|
);
|
|
@@ -19550,6 +20366,7 @@ async function finalizeCurrentMessageGroup(state) {
|
|
|
19550
20366
|
state.latestRootLlmParentRef.value = llmSpanResult.spanExport;
|
|
19551
20367
|
}
|
|
19552
20368
|
if (llmSpanResult.finalMessage) {
|
|
20369
|
+
conversationHistory.push(llmSpanResult.finalMessage);
|
|
19553
20370
|
state.finalResults.push(llmSpanResult.finalMessage);
|
|
19554
20371
|
}
|
|
19555
20372
|
}
|
|
@@ -19577,6 +20394,15 @@ function maybeTrackToolUseContext(state, message) {
|
|
|
19577
20394
|
description: getStringProperty(block.input, "description"),
|
|
19578
20395
|
toolUseId: block.id
|
|
19579
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
|
+
}
|
|
19580
20406
|
}
|
|
19581
20407
|
}
|
|
19582
20408
|
}
|
|
@@ -19695,6 +20521,14 @@ async function maybeHandleTaskLifecycleMessage(state, message) {
|
|
|
19695
20521
|
};
|
|
19696
20522
|
if (message.subtype === "task_started") {
|
|
19697
20523
|
const prompt = getStringProperty(message, "prompt");
|
|
20524
|
+
if (prompt) {
|
|
20525
|
+
setSubAgentPromptMessages(
|
|
20526
|
+
state,
|
|
20527
|
+
toolUseId,
|
|
20528
|
+
[{ content: prompt, role: "user" }],
|
|
20529
|
+
"lifecycle"
|
|
20530
|
+
);
|
|
20531
|
+
}
|
|
19698
20532
|
subAgentSpan.log({
|
|
19699
20533
|
input: prompt,
|
|
19700
20534
|
metadata
|
|
@@ -19745,6 +20579,28 @@ async function handleStreamMessage(state, message) {
|
|
|
19745
20579
|
return;
|
|
19746
20580
|
}
|
|
19747
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
|
+
}
|
|
19748
20604
|
const messageId = message.message?.id;
|
|
19749
20605
|
if (messageId && messageId !== state.currentMessageId) {
|
|
19750
20606
|
await finalizeCurrentMessageGroup(state);
|
|
@@ -19896,6 +20752,7 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
19896
20752
|
}
|
|
19897
20753
|
const activeToolSpans = /* @__PURE__ */ new Map();
|
|
19898
20754
|
const activeLlmSpansByParentToolUse = /* @__PURE__ */ new Map();
|
|
20755
|
+
const conversationHistoryByParentKey = /* @__PURE__ */ new Map();
|
|
19899
20756
|
const subAgentSpans = /* @__PURE__ */ new Map();
|
|
19900
20757
|
const endedSubAgentSpans = /* @__PURE__ */ new Set();
|
|
19901
20758
|
const toolUseToParent = /* @__PURE__ */ new Map();
|
|
@@ -19905,6 +20762,8 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
19905
20762
|
};
|
|
19906
20763
|
const subAgentDetailsByToolUseId = /* @__PURE__ */ new Map();
|
|
19907
20764
|
const taskIdToToolUseId = /* @__PURE__ */ new Map();
|
|
20765
|
+
const promptMessagesByParentKey = /* @__PURE__ */ new Map();
|
|
20766
|
+
const promptSourcePriorityByParentKey = /* @__PURE__ */ new Map();
|
|
19908
20767
|
const localToolContext = createClaudeLocalToolContext();
|
|
19909
20768
|
const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
|
|
19910
20769
|
const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
|
|
@@ -19913,38 +20772,19 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
19913
20772
|
const parentToolUseId = trackedParentToolUseId ?? (context2?.agentId ? taskIdToToolUseId.get(context2.agentId) ?? null : null);
|
|
19914
20773
|
const parentKey = llmParentKey(parentToolUseId);
|
|
19915
20774
|
const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
|
|
19916
|
-
|
|
19917
|
-
|
|
19918
|
-
|
|
19919
|
-
|
|
19920
|
-
|
|
19921
|
-
|
|
19922
|
-
|
|
19923
|
-
|
|
19924
|
-
|
|
19925
|
-
|
|
19926
|
-
|
|
19927
|
-
}
|
|
19928
|
-
if (parentToolUseId) {
|
|
19929
|
-
const subAgentSpan = await ensureSubAgentSpan(
|
|
19930
|
-
subAgentDetailsByToolUseId,
|
|
19931
|
-
span,
|
|
19932
|
-
activeToolSpans,
|
|
19933
|
-
subAgentSpans,
|
|
19934
|
-
parentToolUseId
|
|
19935
|
-
);
|
|
19936
|
-
return subAgentSpan.export();
|
|
19937
|
-
}
|
|
19938
|
-
return span.export();
|
|
19939
|
-
}
|
|
19940
|
-
if (activeLlmSpan) {
|
|
19941
|
-
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
|
+
);
|
|
19942
20786
|
}
|
|
19943
20787
|
if (parentToolUseId) {
|
|
19944
|
-
const parentLlm = latestLlmParentBySubAgentToolUse.get(parentToolUseId);
|
|
19945
|
-
if (parentLlm) {
|
|
19946
|
-
return parentLlm;
|
|
19947
|
-
}
|
|
19948
20788
|
const subAgentSpan = await ensureSubAgentSpan(
|
|
19949
20789
|
subAgentDetailsByToolUseId,
|
|
19950
20790
|
span,
|
|
@@ -19954,9 +20794,6 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
19954
20794
|
);
|
|
19955
20795
|
return subAgentSpan.export();
|
|
19956
20796
|
}
|
|
19957
|
-
if (latestRootLlmParentRef.value) {
|
|
19958
|
-
return latestRootLlmParentRef.value;
|
|
19959
|
-
}
|
|
19960
20797
|
return span.export();
|
|
19961
20798
|
};
|
|
19962
20799
|
localToolContext.resolveLocalToolParent = resolveToolUseParentSpan;
|
|
@@ -19977,6 +20814,7 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
19977
20814
|
accumulatedOutputTokens: 0,
|
|
19978
20815
|
activeLlmSpansByParentToolUse,
|
|
19979
20816
|
activeToolSpans,
|
|
20817
|
+
conversationHistoryByParentKey,
|
|
19980
20818
|
capturedPromptMessages,
|
|
19981
20819
|
currentMessageId: void 0,
|
|
19982
20820
|
currentMessageStartTime: startTime,
|
|
@@ -19987,7 +20825,9 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
19987
20825
|
originalPrompt,
|
|
19988
20826
|
processing: Promise.resolve(),
|
|
19989
20827
|
promptDone,
|
|
20828
|
+
promptMessagesByParentKey,
|
|
19990
20829
|
promptStarted: () => promptStarted,
|
|
20830
|
+
promptSourcePriorityByParentKey,
|
|
19991
20831
|
span,
|
|
19992
20832
|
subAgentDetailsByToolUseId,
|
|
19993
20833
|
subAgentSpans,
|
|
@@ -21416,6 +22256,10 @@ var googleGenAIChannels = defineChannels("@google/genai", {
|
|
|
21416
22256
|
embedContent: channel({
|
|
21417
22257
|
channelName: "models.embedContent",
|
|
21418
22258
|
kind: "async"
|
|
22259
|
+
}),
|
|
22260
|
+
interactionsCreate: channel({
|
|
22261
|
+
channelName: "interactions.create",
|
|
22262
|
+
kind: "async"
|
|
21419
22263
|
})
|
|
21420
22264
|
});
|
|
21421
22265
|
|
|
@@ -21443,6 +22287,7 @@ var GoogleGenAIPlugin = class extends BasePlugin {
|
|
|
21443
22287
|
this.subscribeToGenerateContentChannel();
|
|
21444
22288
|
this.subscribeToGenerateContentStreamChannel();
|
|
21445
22289
|
this.subscribeToEmbedContentChannel();
|
|
22290
|
+
this.subscribeToInteractionsCreateChannel();
|
|
21446
22291
|
}
|
|
21447
22292
|
subscribeToGenerateContentChannel() {
|
|
21448
22293
|
const tracingChannel2 = googleGenAIChannels.generateContent.tracingChannel();
|
|
@@ -21615,7 +22460,30 @@ var GoogleGenAIPlugin = class extends BasePlugin {
|
|
|
21615
22460
|
tracingChannel2.unsubscribe(handlers);
|
|
21616
22461
|
});
|
|
21617
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
|
+
}
|
|
21618
22483
|
};
|
|
22484
|
+
function isBackgroundInteractionCreate(params) {
|
|
22485
|
+
return tryToDict(params)?.background === true;
|
|
22486
|
+
}
|
|
21619
22487
|
function ensureSpanState(states, event, create) {
|
|
21620
22488
|
const existing = states.get(event);
|
|
21621
22489
|
if (existing) {
|
|
@@ -21823,6 +22691,60 @@ function serializeEmbedContentInput(params) {
|
|
|
21823
22691
|
}
|
|
21824
22692
|
return input;
|
|
21825
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
|
+
}
|
|
21826
22748
|
function serializeContentCollection(contents) {
|
|
21827
22749
|
if (contents === null || contents === void 0) {
|
|
21828
22750
|
return null;
|
|
@@ -21853,21 +22775,8 @@ function serializePart(part) {
|
|
|
21853
22775
|
}
|
|
21854
22776
|
if (part.inlineData && part.inlineData.data) {
|
|
21855
22777
|
const { data, mimeType } = part.inlineData;
|
|
21856
|
-
|
|
21857
|
-
|
|
21858
|
-
const filename = `file.${extension}`;
|
|
21859
|
-
const buffer = typeof data === "string" ? typeof Buffer !== "undefined" ? Buffer.from(data, "base64") : new Uint8Array(
|
|
21860
|
-
atob(data).split("").map((c) => c.charCodeAt(0))
|
|
21861
|
-
) : typeof Buffer !== "undefined" ? Buffer.from(data) : new Uint8Array(data);
|
|
21862
|
-
const arrayBuffer = buffer instanceof Uint8Array ? buffer.buffer.slice(
|
|
21863
|
-
buffer.byteOffset,
|
|
21864
|
-
buffer.byteOffset + buffer.byteLength
|
|
21865
|
-
) : buffer;
|
|
21866
|
-
const attachment = new Attachment({
|
|
21867
|
-
data: arrayBuffer,
|
|
21868
|
-
filename,
|
|
21869
|
-
contentType: mimeType || "application/octet-stream"
|
|
21870
|
-
});
|
|
22778
|
+
const attachment = createAttachmentFromInlineData(data, mimeType);
|
|
22779
|
+
if (attachment) {
|
|
21871
22780
|
return {
|
|
21872
22781
|
image_url: { url: attachment }
|
|
21873
22782
|
};
|
|
@@ -21875,6 +22784,59 @@ function serializePart(part) {
|
|
|
21875
22784
|
}
|
|
21876
22785
|
return part;
|
|
21877
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
|
+
}
|
|
21878
22840
|
function serializeGenerateContentTools(params) {
|
|
21879
22841
|
const config3 = params.config ? tryToDict(params.config) : null;
|
|
21880
22842
|
const tools = config3?.tools;
|
|
@@ -21959,6 +22921,33 @@ function extractEmbedContentMetrics(response, startTime) {
|
|
|
21959
22921
|
}
|
|
21960
22922
|
return metrics;
|
|
21961
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
|
+
}
|
|
21962
22951
|
function extractEmbedPromptTokenCount(response) {
|
|
21963
22952
|
if (!response) {
|
|
21964
22953
|
return void 0;
|
|
@@ -22021,6 +23010,23 @@ function populateUsageMetrics(metrics, usage) {
|
|
|
22021
23010
|
metrics.completion_reasoning_tokens = usage.thoughtsTokenCount;
|
|
22022
23011
|
}
|
|
22023
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
|
+
}
|
|
22024
23030
|
function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
|
|
22025
23031
|
const end = getCurrentUnixTimestamp();
|
|
22026
23032
|
const metrics = {
|
|
@@ -22118,6 +23124,146 @@ function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
|
|
|
22118
23124
|
}
|
|
22119
23125
|
return { aggregated, metrics };
|
|
22120
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
|
+
}
|
|
22121
23267
|
function cleanMetrics3(metrics) {
|
|
22122
23268
|
const cleaned = {};
|
|
22123
23269
|
for (const [key, value] of Object.entries(metrics)) {
|
|
@@ -27944,7 +29090,8 @@ var FlueObserveBridge = class {
|
|
|
27944
29090
|
metadata
|
|
27945
29091
|
}
|
|
27946
29092
|
});
|
|
27947
|
-
|
|
29093
|
+
const activeContext = enterCurrentFlueSpan(span);
|
|
29094
|
+
this.runsById.set(event.runId, { activeContext, metadata, span });
|
|
27948
29095
|
}
|
|
27949
29096
|
handleRunEnd(event) {
|
|
27950
29097
|
const state = this.runsById.get(event.runId);
|
|
@@ -27962,6 +29109,7 @@ var FlueObserveBridge = class {
|
|
|
27962
29109
|
});
|
|
27963
29110
|
safeEnd(state.span, eventTime(event.timestamp));
|
|
27964
29111
|
this.runsById.delete(event.runId);
|
|
29112
|
+
restoreCurrentFlueSpan(state.activeContext);
|
|
27965
29113
|
}
|
|
27966
29114
|
void flush().catch((error2) => {
|
|
27967
29115
|
logInstrumentationError3("Flue flush", error2);
|
|
@@ -28088,7 +29236,8 @@ var FlueObserveBridge = class {
|
|
|
28088
29236
|
metadata
|
|
28089
29237
|
}
|
|
28090
29238
|
});
|
|
28091
|
-
|
|
29239
|
+
const activeContext = enterCurrentFlueSpan(span);
|
|
29240
|
+
this.toolsByKey.set(toolKey(event), { activeContext, metadata, span });
|
|
28092
29241
|
}
|
|
28093
29242
|
handleToolCall(event) {
|
|
28094
29243
|
if (!event.toolCallId) {
|
|
@@ -28111,6 +29260,7 @@ var FlueObserveBridge = class {
|
|
|
28111
29260
|
});
|
|
28112
29261
|
safeEnd(state.span, eventTime(event.timestamp));
|
|
28113
29262
|
this.toolsByKey.delete(key);
|
|
29263
|
+
restoreCurrentFlueSpan(state.activeContext);
|
|
28114
29264
|
}
|
|
28115
29265
|
handleTaskStart(event) {
|
|
28116
29266
|
if (!event.taskId) {
|
|
@@ -28515,9 +29665,37 @@ function stateMatchesRun(state, runId) {
|
|
|
28515
29665
|
function startFlueSpan(parent, args) {
|
|
28516
29666
|
return parent ? withCurrent(parent, () => startSpan(args)) : startSpan(args);
|
|
28517
29667
|
}
|
|
28518
|
-
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();
|
|
28519
29675
|
try {
|
|
28520
|
-
|
|
29676
|
+
store.enterWith(contextManager.wrapSpanForStore(span));
|
|
29677
|
+
return { previous, store };
|
|
29678
|
+
} catch (error2) {
|
|
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);
|
|
28521
29699
|
} catch (error2) {
|
|
28522
29700
|
logInstrumentationError3("Flue span log", error2);
|
|
28523
29701
|
}
|
|
@@ -28992,6 +30170,890 @@ function isBraintrustHandler(handler) {
|
|
|
28992
30170
|
return Reflect.get(handler, "name") === BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
|
|
28993
30171
|
}
|
|
28994
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
|
+
|
|
28995
31057
|
// src/instrumentation/braintrust-plugin.ts
|
|
28996
31058
|
function getIntegrationConfig(integrations, key) {
|
|
28997
31059
|
return integrations[key];
|
|
@@ -29017,6 +31079,7 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
29017
31079
|
gitHubCopilotPlugin = null;
|
|
29018
31080
|
fluePlugin = null;
|
|
29019
31081
|
langChainPlugin = null;
|
|
31082
|
+
piCodingAgentPlugin = null;
|
|
29020
31083
|
constructor(config3 = {}) {
|
|
29021
31084
|
super();
|
|
29022
31085
|
this.config = config3;
|
|
@@ -29091,6 +31154,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
29091
31154
|
this.gitHubCopilotPlugin = new GitHubCopilotPlugin();
|
|
29092
31155
|
this.gitHubCopilotPlugin.enable();
|
|
29093
31156
|
}
|
|
31157
|
+
if (integrations.piCodingAgent !== false) {
|
|
31158
|
+
this.piCodingAgentPlugin = new PiCodingAgentPlugin();
|
|
31159
|
+
this.piCodingAgentPlugin.enable();
|
|
31160
|
+
}
|
|
29094
31161
|
if (getIntegrationConfig(integrations, "flue") !== false) {
|
|
29095
31162
|
this.fluePlugin = new FluePlugin();
|
|
29096
31163
|
this.fluePlugin.enable();
|
|
@@ -29169,6 +31236,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
29169
31236
|
this.gitHubCopilotPlugin.disable();
|
|
29170
31237
|
this.gitHubCopilotPlugin = null;
|
|
29171
31238
|
}
|
|
31239
|
+
if (this.piCodingAgentPlugin) {
|
|
31240
|
+
this.piCodingAgentPlugin.disable();
|
|
31241
|
+
this.piCodingAgentPlugin = null;
|
|
31242
|
+
}
|
|
29172
31243
|
if (this.fluePlugin) {
|
|
29173
31244
|
this.fluePlugin.disable();
|
|
29174
31245
|
this.fluePlugin = null;
|
|
@@ -29188,6 +31259,11 @@ var envIntegrationAliases = {
|
|
|
29188
31259
|
openaicodexsdk: "openaiCodexSDK",
|
|
29189
31260
|
codex: "openaiCodexSDK",
|
|
29190
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",
|
|
29191
31267
|
anthropic: "anthropic",
|
|
29192
31268
|
aisdk: "aisdk",
|
|
29193
31269
|
"ai-sdk": "aisdk",
|
|
@@ -29253,7 +31329,8 @@ function getDefaultInstrumentationIntegrations() {
|
|
|
29253
31329
|
genkit: true,
|
|
29254
31330
|
gitHubCopilot: true,
|
|
29255
31331
|
langchain: true,
|
|
29256
|
-
langgraph: true
|
|
31332
|
+
langgraph: true,
|
|
31333
|
+
piCodingAgent: true
|
|
29257
31334
|
};
|
|
29258
31335
|
}
|
|
29259
31336
|
function readDisabledInstrumentationEnvConfig(disabledList) {
|
|
@@ -29984,6 +32061,7 @@ var Project2 = class {
|
|
|
29984
32061
|
prompts;
|
|
29985
32062
|
parameters;
|
|
29986
32063
|
scorers;
|
|
32064
|
+
classifiers;
|
|
29987
32065
|
_publishableCodeFunctions = [];
|
|
29988
32066
|
_publishablePrompts = [];
|
|
29989
32067
|
_publishableParameters = [];
|
|
@@ -29995,6 +32073,7 @@ var Project2 = class {
|
|
|
29995
32073
|
this.prompts = new PromptBuilder(this);
|
|
29996
32074
|
this.parameters = new ParametersBuilder(this);
|
|
29997
32075
|
this.scorers = new ScorerBuilder(this);
|
|
32076
|
+
this.classifiers = new ClassifierBuilder(this);
|
|
29998
32077
|
}
|
|
29999
32078
|
addPrompt(prompt) {
|
|
30000
32079
|
this._publishablePrompts.push(prompt);
|
|
@@ -30129,6 +32208,28 @@ var ScorerBuilder = class {
|
|
|
30129
32208
|
}
|
|
30130
32209
|
}
|
|
30131
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
|
+
};
|
|
30132
32233
|
var CodeFunction = class {
|
|
30133
32234
|
constructor(project, opts) {
|
|
30134
32235
|
this.project = project;
|
|
@@ -31459,7 +33560,7 @@ var serializedParametersContainerSchema = import_v315.z.union([
|
|
|
31459
33560
|
staticParametersSchema
|
|
31460
33561
|
]);
|
|
31461
33562
|
var evaluatorDefinitionSchema = import_v315.z.object({
|
|
31462
|
-
parameters: serializedParametersContainerSchema.
|
|
33563
|
+
parameters: serializedParametersContainerSchema.nullish(),
|
|
31463
33564
|
scores: import_v315.z.array(import_v315.z.object({ name: import_v315.z.string() })).optional(),
|
|
31464
33565
|
classifiers: import_v315.z.array(import_v315.z.object({ name: import_v315.z.string() })).optional()
|
|
31465
33566
|
});
|