braintrust 3.16.0 → 3.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/bt +41 -0
- package/dev/dist/index.d.mts +13 -0
- package/dev/dist/index.d.ts +13 -0
- package/dev/dist/index.js +4300 -2199
- package/dev/dist/index.mjs +2211 -110
- package/dist/apply-auto-instrumentation.js +238 -186
- package/dist/apply-auto-instrumentation.mjs +68 -16
- package/dist/auto-instrumentations/bundler/esbuild.cjs +90 -15
- package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
- package/dist/auto-instrumentations/bundler/next.cjs +90 -15
- package/dist/auto-instrumentations/bundler/next.mjs +3 -3
- package/dist/auto-instrumentations/bundler/rollup.cjs +90 -15
- package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
- package/dist/auto-instrumentations/bundler/vite.cjs +90 -15
- package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
- package/dist/auto-instrumentations/bundler/webpack-loader.cjs +89 -14
- package/dist/auto-instrumentations/bundler/webpack.cjs +90 -15
- package/dist/auto-instrumentations/bundler/webpack.mjs +3 -3
- package/dist/auto-instrumentations/{chunk-VXJONZVX.mjs → chunk-GNUEZ2PE.mjs} +13 -3
- package/dist/auto-instrumentations/{chunk-CNQ7BUKN.mjs → chunk-MYCHHXOE.mjs} +1 -1
- package/dist/auto-instrumentations/{chunk-E5DUYJWK.mjs → chunk-ZYKZEMRT.mjs} +82 -15
- package/dist/auto-instrumentations/hook.mjs +102 -15
- package/dist/auto-instrumentations/index.cjs +84 -16
- package/dist/auto-instrumentations/index.d.mts +3 -1
- package/dist/auto-instrumentations/index.d.ts +3 -1
- package/dist/auto-instrumentations/index.mjs +5 -3
- package/dist/auto-instrumentations/loader/cjs-patch.cjs +1 -1
- package/dist/auto-instrumentations/loader/cjs-patch.mjs +1 -1
- package/dist/auto-instrumentations/loader/esm-hook.mjs +1 -1
- package/dist/browser.d.mts +177 -11
- package/dist/browser.d.ts +177 -11
- package/dist/browser.js +2296 -104
- package/dist/browser.mjs +2455 -263
- package/dist/{chunk-VMBQETG3.js → chunk-73IYIIOL.js} +28 -2
- package/dist/{chunk-O4ZIWXO3.mjs → chunk-BYFADLEZ.mjs} +27 -1
- package/dist/cli.js +2228 -113
- package/dist/edge-light.d.mts +1 -1
- package/dist/edge-light.d.ts +1 -1
- package/dist/edge-light.js +2296 -104
- package/dist/edge-light.mjs +2455 -263
- package/dist/index.d.mts +177 -11
- package/dist/index.d.ts +177 -11
- package/dist/index.js +3296 -1128
- package/dist/index.mjs +2272 -104
- package/dist/instrumentation/index.d.mts +3 -0
- package/dist/instrumentation/index.d.ts +3 -0
- package/dist/instrumentation/index.js +2171 -105
- package/dist/instrumentation/index.mjs +2171 -105
- package/dist/workerd.d.mts +1 -1
- package/dist/workerd.d.ts +1 -1
- package/dist/workerd.js +2296 -104
- package/dist/workerd.mjs +2455 -263
- package/package.json +19 -5
- package/scripts/bt-helper.js +139 -0
- package/scripts/install.js +153 -0
package/dist/workerd.mjs
CHANGED
|
@@ -4954,14 +4954,18 @@ function useTestBackgroundLogger() {
|
|
|
4954
4954
|
function clearTestBackgroundLogger() {
|
|
4955
4955
|
_internalGetGlobalState()?.setOverrideBgLogger(null);
|
|
4956
4956
|
}
|
|
4957
|
-
function initTestExperiment(experimentName, projectName) {
|
|
4957
|
+
function initTestExperiment(experimentName, projectName, experimentFullInfo = {}) {
|
|
4958
4958
|
setInitialTestState();
|
|
4959
4959
|
const state = _internalGetGlobalState();
|
|
4960
4960
|
const project = projectName ?? experimentName;
|
|
4961
4961
|
const lazyMetadata = new LazyValue(
|
|
4962
4962
|
async () => ({
|
|
4963
4963
|
project: { id: project, name: project, fullInfo: {} },
|
|
4964
|
-
experiment: {
|
|
4964
|
+
experiment: {
|
|
4965
|
+
id: experimentName,
|
|
4966
|
+
name: experimentName,
|
|
4967
|
+
fullInfo: experimentFullInfo
|
|
4968
|
+
}
|
|
4965
4969
|
})
|
|
4966
4970
|
);
|
|
4967
4971
|
return new Experiment2(state, lazyMetadata);
|
|
@@ -8326,6 +8330,10 @@ var Experiment2 = class extends ObjectFetcher {
|
|
|
8326
8330
|
return (await this.lazyMetadata.get()).project;
|
|
8327
8331
|
})();
|
|
8328
8332
|
}
|
|
8333
|
+
async _getBaseExperimentId() {
|
|
8334
|
+
const baseExperimentId = (await this.lazyMetadata.get()).experiment.fullInfo["base_exp_id"];
|
|
8335
|
+
return typeof baseExperimentId === "string" && baseExperimentId ? baseExperimentId : void 0;
|
|
8336
|
+
}
|
|
8329
8337
|
parentObjectType() {
|
|
8330
8338
|
return 1 /* EXPERIMENT */;
|
|
8331
8339
|
}
|
|
@@ -8466,6 +8474,14 @@ var Experiment2 = class extends ObjectFetcher {
|
|
|
8466
8474
|
comparisonExperimentId = baseExperiment.id;
|
|
8467
8475
|
comparisonExperimentName = baseExperiment.name;
|
|
8468
8476
|
}
|
|
8477
|
+
} else {
|
|
8478
|
+
try {
|
|
8479
|
+
const comparisonExperiment = await state.apiConn().get_json(`v1/experiment/${comparisonExperimentId}`);
|
|
8480
|
+
if (typeof comparisonExperiment["name"] === "string") {
|
|
8481
|
+
comparisonExperimentName = comparisonExperiment["name"];
|
|
8482
|
+
}
|
|
8483
|
+
} catch {
|
|
8484
|
+
}
|
|
8469
8485
|
}
|
|
8470
8486
|
try {
|
|
8471
8487
|
const results = await state.apiConn().get_json(
|
|
@@ -10630,6 +10646,64 @@ var BasePlugin = class {
|
|
|
10630
10646
|
}
|
|
10631
10647
|
};
|
|
10632
10648
|
|
|
10649
|
+
// src/instrumentation/auto-instrumentation-suppression.ts
|
|
10650
|
+
var autoInstrumentationSuppressionStore;
|
|
10651
|
+
function suppressionStore() {
|
|
10652
|
+
autoInstrumentationSuppressionStore ??= isomorph_default.newAsyncLocalStorage();
|
|
10653
|
+
return autoInstrumentationSuppressionStore;
|
|
10654
|
+
}
|
|
10655
|
+
function currentFrames() {
|
|
10656
|
+
return suppressionStore().getStore()?.frames ?? [];
|
|
10657
|
+
}
|
|
10658
|
+
function isAutoInstrumentationSuppressed() {
|
|
10659
|
+
const frames = currentFrames();
|
|
10660
|
+
return frames[frames.length - 1]?.mode === "suppress";
|
|
10661
|
+
}
|
|
10662
|
+
function runWithAutoInstrumentationSuppressed(callback) {
|
|
10663
|
+
const frame = {
|
|
10664
|
+
id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
|
|
10665
|
+
mode: "suppress"
|
|
10666
|
+
};
|
|
10667
|
+
return suppressionStore().run(
|
|
10668
|
+
{ frames: [...currentFrames(), frame] },
|
|
10669
|
+
callback
|
|
10670
|
+
);
|
|
10671
|
+
}
|
|
10672
|
+
function bindAutoInstrumentationSuppressionToStart(tracingChannel2) {
|
|
10673
|
+
const startChannel = tracingChannel2.start;
|
|
10674
|
+
if (!startChannel) {
|
|
10675
|
+
return void 0;
|
|
10676
|
+
}
|
|
10677
|
+
const store = suppressionStore();
|
|
10678
|
+
startChannel.bindStore(store, () => ({
|
|
10679
|
+
frames: [
|
|
10680
|
+
...currentFrames(),
|
|
10681
|
+
{
|
|
10682
|
+
id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
|
|
10683
|
+
mode: "suppress"
|
|
10684
|
+
}
|
|
10685
|
+
]
|
|
10686
|
+
}));
|
|
10687
|
+
return () => {
|
|
10688
|
+
startChannel.unbindStore(store);
|
|
10689
|
+
};
|
|
10690
|
+
}
|
|
10691
|
+
function enterAutoInstrumentationAllowed() {
|
|
10692
|
+
const frame = {
|
|
10693
|
+
id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-allow"),
|
|
10694
|
+
mode: "allow"
|
|
10695
|
+
};
|
|
10696
|
+
suppressionStore().enterWith({
|
|
10697
|
+
frames: [...currentFrames(), frame]
|
|
10698
|
+
});
|
|
10699
|
+
return () => {
|
|
10700
|
+
const frames = currentFrames().filter(
|
|
10701
|
+
(candidate) => candidate.id !== frame.id
|
|
10702
|
+
);
|
|
10703
|
+
suppressionStore().enterWith(frames.length > 0 ? { frames } : void 0);
|
|
10704
|
+
};
|
|
10705
|
+
}
|
|
10706
|
+
|
|
10633
10707
|
// src/instrumentation/core/channel-tracing.ts
|
|
10634
10708
|
function isSyncStreamLike(value) {
|
|
10635
10709
|
return !!value && typeof value === "object" && typeof value.on === "function";
|
|
@@ -10661,16 +10735,33 @@ function startSpanForEvent(config, event, channelName) {
|
|
|
10661
10735
|
metadata: mergeInputMetadata(metadata, spanInfoMetadata)
|
|
10662
10736
|
});
|
|
10663
10737
|
} catch (error) {
|
|
10664
|
-
|
|
10738
|
+
debugLogger.error(`Error extracting input for ${channelName}:`, error);
|
|
10665
10739
|
}
|
|
10666
10740
|
return { span, startTime };
|
|
10667
10741
|
}
|
|
10742
|
+
function shouldTraceEvent(config, event, channelName) {
|
|
10743
|
+
if (!config.shouldTrace) {
|
|
10744
|
+
return true;
|
|
10745
|
+
}
|
|
10746
|
+
try {
|
|
10747
|
+
return config.shouldTrace(event.arguments, event);
|
|
10748
|
+
} catch (error) {
|
|
10749
|
+
debugLogger.error(
|
|
10750
|
+
`Error checking trace predicate for ${channelName}:`,
|
|
10751
|
+
error
|
|
10752
|
+
);
|
|
10753
|
+
return true;
|
|
10754
|
+
}
|
|
10755
|
+
}
|
|
10668
10756
|
function ensureSpanStateForEvent(states, config, event, channelName) {
|
|
10669
10757
|
const key = event;
|
|
10670
10758
|
const existing = states.get(key);
|
|
10671
10759
|
if (existing) {
|
|
10672
10760
|
return existing;
|
|
10673
10761
|
}
|
|
10762
|
+
if (!shouldTraceEvent(config, event, channelName)) {
|
|
10763
|
+
return void 0;
|
|
10764
|
+
}
|
|
10674
10765
|
const created = startSpanForEvent(config, event, channelName);
|
|
10675
10766
|
states.set(key, created);
|
|
10676
10767
|
return created;
|
|
@@ -10686,13 +10777,16 @@ function bindCurrentSpanStoreToStart(tracingChannel2, states, config, channelNam
|
|
|
10686
10777
|
startChannel.bindStore(
|
|
10687
10778
|
currentSpanStore,
|
|
10688
10779
|
(event) => {
|
|
10689
|
-
|
|
10780
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
10781
|
+
return currentSpanStore.getStore();
|
|
10782
|
+
}
|
|
10783
|
+
const spanState = ensureSpanStateForEvent(
|
|
10690
10784
|
states,
|
|
10691
10785
|
config,
|
|
10692
10786
|
event,
|
|
10693
10787
|
channelName
|
|
10694
|
-
)
|
|
10695
|
-
return contextManager.wrapSpanForStore(span);
|
|
10788
|
+
);
|
|
10789
|
+
return spanState ? contextManager.wrapSpanForStore(spanState.span) : currentSpanStore.getStore();
|
|
10696
10790
|
}
|
|
10697
10791
|
);
|
|
10698
10792
|
return () => {
|
|
@@ -10727,7 +10821,10 @@ function runStreamingCompletionHook(args) {
|
|
|
10727
10821
|
startTime: args.startTime
|
|
10728
10822
|
});
|
|
10729
10823
|
} catch (error) {
|
|
10730
|
-
|
|
10824
|
+
debugLogger.error(
|
|
10825
|
+
`Error in onComplete hook for ${args.channelName}:`,
|
|
10826
|
+
error
|
|
10827
|
+
);
|
|
10731
10828
|
}
|
|
10732
10829
|
}
|
|
10733
10830
|
function traceAsyncChannel(channel2, config) {
|
|
@@ -10742,6 +10839,9 @@ function traceAsyncChannel(channel2, config) {
|
|
|
10742
10839
|
);
|
|
10743
10840
|
const handlers = {
|
|
10744
10841
|
start: (event) => {
|
|
10842
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
10843
|
+
return;
|
|
10844
|
+
}
|
|
10745
10845
|
ensureSpanStateForEvent(
|
|
10746
10846
|
states,
|
|
10747
10847
|
config,
|
|
@@ -10776,7 +10876,7 @@ function traceAsyncChannel(channel2, config) {
|
|
|
10776
10876
|
metrics
|
|
10777
10877
|
});
|
|
10778
10878
|
} catch (error) {
|
|
10779
|
-
|
|
10879
|
+
debugLogger.error(`Error extracting output for ${channelName}:`, error);
|
|
10780
10880
|
} finally {
|
|
10781
10881
|
span.end();
|
|
10782
10882
|
states.delete(event);
|
|
@@ -10804,6 +10904,9 @@ function traceStreamingChannel(channel2, config) {
|
|
|
10804
10904
|
);
|
|
10805
10905
|
const handlers = {
|
|
10806
10906
|
start: (event) => {
|
|
10907
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
10908
|
+
return;
|
|
10909
|
+
}
|
|
10807
10910
|
ensureSpanStateForEvent(
|
|
10808
10911
|
states,
|
|
10809
10912
|
config,
|
|
@@ -10875,7 +10978,7 @@ function traceStreamingChannel(channel2, config) {
|
|
|
10875
10978
|
metrics
|
|
10876
10979
|
});
|
|
10877
10980
|
} catch (error) {
|
|
10878
|
-
|
|
10981
|
+
debugLogger.error(
|
|
10879
10982
|
`Error extracting output for ${channelName}:`,
|
|
10880
10983
|
error
|
|
10881
10984
|
);
|
|
@@ -10935,7 +11038,7 @@ function traceStreamingChannel(channel2, config) {
|
|
|
10935
11038
|
metrics
|
|
10936
11039
|
});
|
|
10937
11040
|
} catch (error) {
|
|
10938
|
-
|
|
11041
|
+
debugLogger.error(`Error extracting output for ${channelName}:`, error);
|
|
10939
11042
|
} finally {
|
|
10940
11043
|
span.end();
|
|
10941
11044
|
states.delete(event);
|
|
@@ -10963,6 +11066,9 @@ function traceSyncStreamChannel(channel2, config) {
|
|
|
10963
11066
|
);
|
|
10964
11067
|
const handlers = {
|
|
10965
11068
|
start: (event) => {
|
|
11069
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
11070
|
+
return;
|
|
11071
|
+
}
|
|
10966
11072
|
ensureSpanStateForEvent(
|
|
10967
11073
|
states,
|
|
10968
11074
|
config,
|
|
@@ -11016,7 +11122,7 @@ function traceSyncStreamChannel(channel2, config) {
|
|
|
11016
11122
|
});
|
|
11017
11123
|
}
|
|
11018
11124
|
} catch (error) {
|
|
11019
|
-
|
|
11125
|
+
debugLogger.error(
|
|
11020
11126
|
`Error extracting chatCompletion for ${channelName}:`,
|
|
11021
11127
|
error
|
|
11022
11128
|
);
|
|
@@ -11040,7 +11146,10 @@ function traceSyncStreamChannel(channel2, config) {
|
|
|
11040
11146
|
span.log(extracted);
|
|
11041
11147
|
}
|
|
11042
11148
|
} catch (error) {
|
|
11043
|
-
|
|
11149
|
+
debugLogger.error(
|
|
11150
|
+
`Error extracting event for ${channelName}:`,
|
|
11151
|
+
error
|
|
11152
|
+
);
|
|
11044
11153
|
}
|
|
11045
11154
|
});
|
|
11046
11155
|
stream.on("end", () => {
|
|
@@ -12569,6 +12678,9 @@ var AnthropicPlugin = class extends BasePlugin {
|
|
|
12569
12678
|
const states = /* @__PURE__ */ new WeakMap();
|
|
12570
12679
|
const handlers = {
|
|
12571
12680
|
start: (event) => {
|
|
12681
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
12682
|
+
return;
|
|
12683
|
+
}
|
|
12572
12684
|
const params = event.arguments[0] ?? {};
|
|
12573
12685
|
const span = startSpan({
|
|
12574
12686
|
name: "anthropic.beta.messages.toolRunner",
|
|
@@ -13298,6 +13410,520 @@ function serializeAISDKToolsForLogging(tools) {
|
|
|
13298
13410
|
return serialized;
|
|
13299
13411
|
}
|
|
13300
13412
|
|
|
13413
|
+
// src/wrappers/ai-sdk/telemetry.ts
|
|
13414
|
+
function braintrustAISDKTelemetry() {
|
|
13415
|
+
const operations = /* @__PURE__ */ new Map();
|
|
13416
|
+
const modelSpans = /* @__PURE__ */ new Map();
|
|
13417
|
+
const objectSpans = /* @__PURE__ */ new Map();
|
|
13418
|
+
const embedSpans = /* @__PURE__ */ new Map();
|
|
13419
|
+
const rerankSpans = /* @__PURE__ */ new Map();
|
|
13420
|
+
const toolSpans = /* @__PURE__ */ new Map();
|
|
13421
|
+
const runSafely = (name, callback) => {
|
|
13422
|
+
try {
|
|
13423
|
+
callback();
|
|
13424
|
+
} catch (error) {
|
|
13425
|
+
console.error(`Error in Braintrust AI SDK telemetry ${name}:`, error);
|
|
13426
|
+
}
|
|
13427
|
+
};
|
|
13428
|
+
const startChildSpan = (callId, name, type, event) => {
|
|
13429
|
+
const parent = operations.get(callId)?.span;
|
|
13430
|
+
const spanArgs = {
|
|
13431
|
+
name,
|
|
13432
|
+
spanAttributes: { type },
|
|
13433
|
+
...event ? { event } : {}
|
|
13434
|
+
};
|
|
13435
|
+
const span = parent ? parent.startSpan(spanArgs) : startSpan(spanArgs);
|
|
13436
|
+
const state = operations.get(callId);
|
|
13437
|
+
if (state && type === "llm" /* LLM */) {
|
|
13438
|
+
state.hadModelChild = true;
|
|
13439
|
+
}
|
|
13440
|
+
return span;
|
|
13441
|
+
};
|
|
13442
|
+
return {
|
|
13443
|
+
onStart(event) {
|
|
13444
|
+
runSafely("onStart", () => {
|
|
13445
|
+
const operationName = operationNameFromId(event.operationId);
|
|
13446
|
+
const span = startSpan({
|
|
13447
|
+
name: operationName,
|
|
13448
|
+
spanAttributes: { type: "function" /* FUNCTION */ }
|
|
13449
|
+
});
|
|
13450
|
+
operations.set(event.callId, {
|
|
13451
|
+
hadModelChild: false,
|
|
13452
|
+
operationName,
|
|
13453
|
+
span,
|
|
13454
|
+
startTime: getCurrentUnixTimestamp()
|
|
13455
|
+
});
|
|
13456
|
+
const metadata = metadataFromEvent(event);
|
|
13457
|
+
const logPayload = { metadata };
|
|
13458
|
+
if (shouldRecordInputs(event)) {
|
|
13459
|
+
const { input, outputPromise } = processAISDKCallInput(
|
|
13460
|
+
operationInput(event, operationName)
|
|
13461
|
+
);
|
|
13462
|
+
logPayload.input = input;
|
|
13463
|
+
if (outputPromise && input && typeof input === "object") {
|
|
13464
|
+
outputPromise.then((resolvedData) => {
|
|
13465
|
+
span.log({
|
|
13466
|
+
input: {
|
|
13467
|
+
...input,
|
|
13468
|
+
...resolvedData
|
|
13469
|
+
}
|
|
13470
|
+
});
|
|
13471
|
+
}).catch(() => {
|
|
13472
|
+
});
|
|
13473
|
+
}
|
|
13474
|
+
}
|
|
13475
|
+
span.log(logPayload);
|
|
13476
|
+
});
|
|
13477
|
+
},
|
|
13478
|
+
onLanguageModelCallStart(event) {
|
|
13479
|
+
runSafely("onLanguageModelCallStart", () => {
|
|
13480
|
+
const state = operations.get(event.callId);
|
|
13481
|
+
const openSpans = modelSpans.get(event.callId);
|
|
13482
|
+
if (openSpans) {
|
|
13483
|
+
for (const span2 of openSpans) {
|
|
13484
|
+
span2.end();
|
|
13485
|
+
}
|
|
13486
|
+
modelSpans.delete(event.callId);
|
|
13487
|
+
}
|
|
13488
|
+
const span = startChildSpan(
|
|
13489
|
+
event.callId,
|
|
13490
|
+
state?.operationName === "streamText" ? "doStream" : "doGenerate",
|
|
13491
|
+
"llm" /* LLM */,
|
|
13492
|
+
{
|
|
13493
|
+
...shouldRecordInputs(event) ? {
|
|
13494
|
+
input: processAISDKCallInput(
|
|
13495
|
+
operationInput(
|
|
13496
|
+
event,
|
|
13497
|
+
state?.operationName ?? "generateText"
|
|
13498
|
+
)
|
|
13499
|
+
).input
|
|
13500
|
+
} : {},
|
|
13501
|
+
metadata: metadataFromEvent(event)
|
|
13502
|
+
}
|
|
13503
|
+
);
|
|
13504
|
+
const spans = modelSpans.get(event.callId) ?? [];
|
|
13505
|
+
spans.push(span);
|
|
13506
|
+
modelSpans.set(event.callId, spans);
|
|
13507
|
+
});
|
|
13508
|
+
},
|
|
13509
|
+
onLanguageModelCallEnd(event) {
|
|
13510
|
+
runSafely("onLanguageModelCallEnd", () => {
|
|
13511
|
+
const span = shiftModelSpan(modelSpans, event.callId);
|
|
13512
|
+
if (!span) {
|
|
13513
|
+
return;
|
|
13514
|
+
}
|
|
13515
|
+
const result = {
|
|
13516
|
+
...event,
|
|
13517
|
+
response: event.responseId ? { id: event.responseId } : void 0
|
|
13518
|
+
};
|
|
13519
|
+
span.log({
|
|
13520
|
+
...shouldRecordOutputs(event) ? {
|
|
13521
|
+
output: processAISDKOutput(result, DEFAULT_DENY_OUTPUT_PATHS)
|
|
13522
|
+
} : {},
|
|
13523
|
+
metrics: extractTokenMetrics(result)
|
|
13524
|
+
});
|
|
13525
|
+
span.end();
|
|
13526
|
+
});
|
|
13527
|
+
},
|
|
13528
|
+
onObjectStepStart(event) {
|
|
13529
|
+
runSafely("onObjectStepStart", () => {
|
|
13530
|
+
const state = operations.get(event.callId);
|
|
13531
|
+
const openSpan = objectSpans.get(event.callId);
|
|
13532
|
+
if (openSpan) {
|
|
13533
|
+
openSpan.end();
|
|
13534
|
+
objectSpans.delete(event.callId);
|
|
13535
|
+
}
|
|
13536
|
+
const span = startChildSpan(
|
|
13537
|
+
event.callId,
|
|
13538
|
+
state?.operationName === "streamObject" ? "doStream" : "doGenerate",
|
|
13539
|
+
"llm" /* LLM */,
|
|
13540
|
+
{
|
|
13541
|
+
...shouldRecordInputs(event) ? {
|
|
13542
|
+
input: {
|
|
13543
|
+
prompt: event.promptMessages
|
|
13544
|
+
}
|
|
13545
|
+
} : {},
|
|
13546
|
+
metadata: metadataFromEvent(event)
|
|
13547
|
+
}
|
|
13548
|
+
);
|
|
13549
|
+
objectSpans.set(event.callId, span);
|
|
13550
|
+
});
|
|
13551
|
+
},
|
|
13552
|
+
onObjectStepFinish(event) {
|
|
13553
|
+
runSafely("onObjectStepFinish", () => {
|
|
13554
|
+
const span = objectSpans.get(event.callId);
|
|
13555
|
+
if (!span) {
|
|
13556
|
+
return;
|
|
13557
|
+
}
|
|
13558
|
+
const result = {
|
|
13559
|
+
...event,
|
|
13560
|
+
text: event.objectText
|
|
13561
|
+
};
|
|
13562
|
+
span.log({
|
|
13563
|
+
...shouldRecordOutputs(event) ? {
|
|
13564
|
+
output: processAISDKOutput(result, DEFAULT_DENY_OUTPUT_PATHS)
|
|
13565
|
+
} : {},
|
|
13566
|
+
metrics: extractTokenMetrics(result)
|
|
13567
|
+
});
|
|
13568
|
+
span.end();
|
|
13569
|
+
objectSpans.delete(event.callId);
|
|
13570
|
+
});
|
|
13571
|
+
},
|
|
13572
|
+
onEmbedStart(event) {
|
|
13573
|
+
runSafely("onEmbedStart", () => {
|
|
13574
|
+
const state = operations.get(event.callId);
|
|
13575
|
+
for (const [embedCallId, embedState] of embedSpans) {
|
|
13576
|
+
if (embedState.callId === event.callId && (state?.operationName === "embed" || embedState.values === event.values)) {
|
|
13577
|
+
embedState.span.end();
|
|
13578
|
+
embedSpans.delete(embedCallId);
|
|
13579
|
+
}
|
|
13580
|
+
}
|
|
13581
|
+
const span = startChildSpan(
|
|
13582
|
+
event.callId,
|
|
13583
|
+
"doEmbed",
|
|
13584
|
+
"llm" /* LLM */,
|
|
13585
|
+
{
|
|
13586
|
+
...shouldRecordInputs(event) ? {
|
|
13587
|
+
input: {
|
|
13588
|
+
values: event.values
|
|
13589
|
+
}
|
|
13590
|
+
} : {},
|
|
13591
|
+
metadata: metadataFromEvent(event)
|
|
13592
|
+
}
|
|
13593
|
+
);
|
|
13594
|
+
embedSpans.set(event.embedCallId, {
|
|
13595
|
+
callId: event.callId,
|
|
13596
|
+
span,
|
|
13597
|
+
values: event.values
|
|
13598
|
+
});
|
|
13599
|
+
});
|
|
13600
|
+
},
|
|
13601
|
+
onEmbedFinish(event) {
|
|
13602
|
+
runSafely("onEmbedFinish", () => {
|
|
13603
|
+
const state = embedSpans.get(event.embedCallId);
|
|
13604
|
+
if (!state) {
|
|
13605
|
+
return;
|
|
13606
|
+
}
|
|
13607
|
+
const result = {
|
|
13608
|
+
...event,
|
|
13609
|
+
embeddings: event.embeddings
|
|
13610
|
+
};
|
|
13611
|
+
state.span.log({
|
|
13612
|
+
...shouldRecordOutputs(event) ? {
|
|
13613
|
+
output: processAISDKEmbeddingOutput(
|
|
13614
|
+
result,
|
|
13615
|
+
DEFAULT_DENY_OUTPUT_PATHS
|
|
13616
|
+
)
|
|
13617
|
+
} : {},
|
|
13618
|
+
metrics: extractTokenMetrics(result)
|
|
13619
|
+
});
|
|
13620
|
+
state.span.end();
|
|
13621
|
+
embedSpans.delete(event.embedCallId);
|
|
13622
|
+
});
|
|
13623
|
+
},
|
|
13624
|
+
onRerankStart(event) {
|
|
13625
|
+
runSafely("onRerankStart", () => {
|
|
13626
|
+
const openSpan = rerankSpans.get(event.callId);
|
|
13627
|
+
if (openSpan) {
|
|
13628
|
+
openSpan.end();
|
|
13629
|
+
rerankSpans.delete(event.callId);
|
|
13630
|
+
}
|
|
13631
|
+
const span = startChildSpan(
|
|
13632
|
+
event.callId,
|
|
13633
|
+
"doRerank",
|
|
13634
|
+
"llm" /* LLM */,
|
|
13635
|
+
{
|
|
13636
|
+
...shouldRecordInputs(event) ? {
|
|
13637
|
+
input: {
|
|
13638
|
+
documents: event.documents,
|
|
13639
|
+
query: event.query,
|
|
13640
|
+
topN: event.topN
|
|
13641
|
+
}
|
|
13642
|
+
} : {},
|
|
13643
|
+
metadata: metadataFromEvent(event)
|
|
13644
|
+
}
|
|
13645
|
+
);
|
|
13646
|
+
rerankSpans.set(event.callId, span);
|
|
13647
|
+
});
|
|
13648
|
+
},
|
|
13649
|
+
onRerankFinish(event) {
|
|
13650
|
+
runSafely("onRerankFinish", () => {
|
|
13651
|
+
const span = rerankSpans.get(event.callId);
|
|
13652
|
+
if (!span) {
|
|
13653
|
+
return;
|
|
13654
|
+
}
|
|
13655
|
+
const result = {
|
|
13656
|
+
ranking: event.ranking?.map((entry) => ({
|
|
13657
|
+
originalIndex: entry.index,
|
|
13658
|
+
score: entry.relevanceScore
|
|
13659
|
+
}))
|
|
13660
|
+
};
|
|
13661
|
+
span.log({
|
|
13662
|
+
...shouldRecordOutputs(event) ? {
|
|
13663
|
+
output: processAISDKRerankOutput(
|
|
13664
|
+
result,
|
|
13665
|
+
DEFAULT_DENY_OUTPUT_PATHS
|
|
13666
|
+
)
|
|
13667
|
+
} : {}
|
|
13668
|
+
});
|
|
13669
|
+
span.end();
|
|
13670
|
+
rerankSpans.delete(event.callId);
|
|
13671
|
+
});
|
|
13672
|
+
},
|
|
13673
|
+
onToolExecutionStart(event) {
|
|
13674
|
+
runSafely("onToolExecutionStart", () => {
|
|
13675
|
+
const toolCallId = event.toolCall.toolCallId;
|
|
13676
|
+
if (!toolCallId) {
|
|
13677
|
+
return;
|
|
13678
|
+
}
|
|
13679
|
+
const span = startChildSpan(
|
|
13680
|
+
event.callId,
|
|
13681
|
+
event.toolCall.toolName || "tool",
|
|
13682
|
+
"tool" /* TOOL */,
|
|
13683
|
+
{
|
|
13684
|
+
...shouldRecordInputs(event) ? {
|
|
13685
|
+
input: event.toolCall.input
|
|
13686
|
+
} : {},
|
|
13687
|
+
metadata: {
|
|
13688
|
+
...createAISDKIntegrationMetadata(),
|
|
13689
|
+
toolCallId,
|
|
13690
|
+
...typeof event.toolCall.toolName === "string" ? { toolName: event.toolCall.toolName } : {}
|
|
13691
|
+
}
|
|
13692
|
+
}
|
|
13693
|
+
);
|
|
13694
|
+
toolSpans.set(toolCallId, { callId: event.callId, span });
|
|
13695
|
+
});
|
|
13696
|
+
},
|
|
13697
|
+
onToolExecutionEnd(event) {
|
|
13698
|
+
runSafely("onToolExecutionEnd", () => {
|
|
13699
|
+
const toolCallId = event.toolCall.toolCallId;
|
|
13700
|
+
const state = toolCallId ? toolSpans.get(toolCallId) : void 0;
|
|
13701
|
+
if (!toolCallId || !state) {
|
|
13702
|
+
return;
|
|
13703
|
+
}
|
|
13704
|
+
const toolOutput = event.toolOutput;
|
|
13705
|
+
if (toolOutput?.type === "tool-error") {
|
|
13706
|
+
state.span.log({
|
|
13707
|
+
error: toolOutput.error instanceof Error ? toolOutput.error.message : String(toolOutput?.error),
|
|
13708
|
+
metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } : {}
|
|
13709
|
+
});
|
|
13710
|
+
} else {
|
|
13711
|
+
state.span.log({
|
|
13712
|
+
...shouldRecordOutputs(event) ? { output: toolOutput?.output } : {},
|
|
13713
|
+
metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } : {}
|
|
13714
|
+
});
|
|
13715
|
+
}
|
|
13716
|
+
state.span.end();
|
|
13717
|
+
toolSpans.delete(toolCallId);
|
|
13718
|
+
});
|
|
13719
|
+
},
|
|
13720
|
+
onChunk(event) {
|
|
13721
|
+
runSafely("onChunk", () => {
|
|
13722
|
+
const callId = event.chunk?.callId;
|
|
13723
|
+
if (!callId) {
|
|
13724
|
+
return;
|
|
13725
|
+
}
|
|
13726
|
+
const state = operations.get(callId);
|
|
13727
|
+
if (!state || state.firstChunkTime !== void 0) {
|
|
13728
|
+
return;
|
|
13729
|
+
}
|
|
13730
|
+
state.firstChunkTime = getCurrentUnixTimestamp();
|
|
13731
|
+
});
|
|
13732
|
+
},
|
|
13733
|
+
onFinish(event) {
|
|
13734
|
+
runSafely("onFinish", () => {
|
|
13735
|
+
const state = operations.get(event.callId);
|
|
13736
|
+
if (!state) {
|
|
13737
|
+
return;
|
|
13738
|
+
}
|
|
13739
|
+
const result = finishResult(event, state.operationName);
|
|
13740
|
+
const metrics = state.hadModelChild ? {} : extractTokenMetrics(result);
|
|
13741
|
+
if (state.firstChunkTime !== void 0) {
|
|
13742
|
+
metrics.time_to_first_token = state.firstChunkTime - state.startTime;
|
|
13743
|
+
}
|
|
13744
|
+
state.span.log({
|
|
13745
|
+
...shouldRecordOutputs(event) ? {
|
|
13746
|
+
output: finishOutput(result, state.operationName)
|
|
13747
|
+
} : {},
|
|
13748
|
+
metrics
|
|
13749
|
+
});
|
|
13750
|
+
state.span.end();
|
|
13751
|
+
operations.delete(event.callId);
|
|
13752
|
+
});
|
|
13753
|
+
},
|
|
13754
|
+
onError(event) {
|
|
13755
|
+
runSafely("onError", () => {
|
|
13756
|
+
const errorEvent = isObject(event) ? event : {};
|
|
13757
|
+
const callId = typeof errorEvent.callId === "string" ? errorEvent.callId : void 0;
|
|
13758
|
+
if (!callId) {
|
|
13759
|
+
return;
|
|
13760
|
+
}
|
|
13761
|
+
const state = operations.get(callId);
|
|
13762
|
+
if (!state) {
|
|
13763
|
+
return;
|
|
13764
|
+
}
|
|
13765
|
+
const error = errorEvent.error ?? event;
|
|
13766
|
+
const openModelSpans = modelSpans.get(callId);
|
|
13767
|
+
if (openModelSpans) {
|
|
13768
|
+
for (const span of openModelSpans) {
|
|
13769
|
+
logError(span, error);
|
|
13770
|
+
span.end();
|
|
13771
|
+
}
|
|
13772
|
+
modelSpans.delete(callId);
|
|
13773
|
+
}
|
|
13774
|
+
const openObjectSpan = objectSpans.get(callId);
|
|
13775
|
+
if (openObjectSpan) {
|
|
13776
|
+
logError(openObjectSpan, error);
|
|
13777
|
+
openObjectSpan.end();
|
|
13778
|
+
objectSpans.delete(callId);
|
|
13779
|
+
}
|
|
13780
|
+
for (const [embedCallId, embedState] of embedSpans) {
|
|
13781
|
+
if (embedState.callId === callId) {
|
|
13782
|
+
logError(embedState.span, error);
|
|
13783
|
+
embedState.span.end();
|
|
13784
|
+
embedSpans.delete(embedCallId);
|
|
13785
|
+
}
|
|
13786
|
+
}
|
|
13787
|
+
const openRerankSpan = rerankSpans.get(callId);
|
|
13788
|
+
if (openRerankSpan) {
|
|
13789
|
+
logError(openRerankSpan, error);
|
|
13790
|
+
openRerankSpan.end();
|
|
13791
|
+
rerankSpans.delete(callId);
|
|
13792
|
+
}
|
|
13793
|
+
for (const [toolCallId, toolState] of toolSpans) {
|
|
13794
|
+
if (toolState.callId === callId) {
|
|
13795
|
+
logError(toolState.span, error);
|
|
13796
|
+
toolState.span.end();
|
|
13797
|
+
toolSpans.delete(toolCallId);
|
|
13798
|
+
}
|
|
13799
|
+
}
|
|
13800
|
+
logError(state.span, error);
|
|
13801
|
+
state.span.end();
|
|
13802
|
+
operations.delete(callId);
|
|
13803
|
+
});
|
|
13804
|
+
},
|
|
13805
|
+
executeTool({ toolCallId, execute }) {
|
|
13806
|
+
const state = toolSpans.get(toolCallId);
|
|
13807
|
+
return state ? withCurrent(state.span, () => execute()) : execute();
|
|
13808
|
+
}
|
|
13809
|
+
};
|
|
13810
|
+
}
|
|
13811
|
+
function shouldRecordInputs(event) {
|
|
13812
|
+
return event.recordInputs !== false;
|
|
13813
|
+
}
|
|
13814
|
+
function shouldRecordOutputs(event) {
|
|
13815
|
+
return event.recordOutputs !== false;
|
|
13816
|
+
}
|
|
13817
|
+
function operationNameFromId(operationId) {
|
|
13818
|
+
return operationId?.startsWith("ai.") ? operationId.slice("ai.".length) : operationId || "ai-sdk";
|
|
13819
|
+
}
|
|
13820
|
+
function modelFromEvent(event) {
|
|
13821
|
+
return event.modelId ? {
|
|
13822
|
+
modelId: event.modelId,
|
|
13823
|
+
...event.provider ? { provider: event.provider } : {}
|
|
13824
|
+
} : void 0;
|
|
13825
|
+
}
|
|
13826
|
+
function metadataFromEvent(event) {
|
|
13827
|
+
const metadata = createAISDKIntegrationMetadata();
|
|
13828
|
+
const { model, provider } = serializeModelWithProvider(modelFromEvent(event));
|
|
13829
|
+
if (model) {
|
|
13830
|
+
metadata.model = model;
|
|
13831
|
+
}
|
|
13832
|
+
if (provider) {
|
|
13833
|
+
metadata.provider = provider;
|
|
13834
|
+
}
|
|
13835
|
+
if (typeof event.functionId === "string") {
|
|
13836
|
+
metadata.functionId = event.functionId;
|
|
13837
|
+
}
|
|
13838
|
+
return metadata;
|
|
13839
|
+
}
|
|
13840
|
+
function operationInput(event, operationName) {
|
|
13841
|
+
if (operationName === "embed") {
|
|
13842
|
+
return {
|
|
13843
|
+
model: modelFromEvent(event),
|
|
13844
|
+
value: event.value
|
|
13845
|
+
};
|
|
13846
|
+
}
|
|
13847
|
+
if (operationName === "embedMany") {
|
|
13848
|
+
return {
|
|
13849
|
+
model: modelFromEvent(event),
|
|
13850
|
+
values: Array.isArray(event.value) ? event.value ?? [] : void 0
|
|
13851
|
+
};
|
|
13852
|
+
}
|
|
13853
|
+
if (operationName === "rerank") {
|
|
13854
|
+
return {
|
|
13855
|
+
model: modelFromEvent(event),
|
|
13856
|
+
documents: event.documents,
|
|
13857
|
+
query: event.query,
|
|
13858
|
+
topN: event.topN
|
|
13859
|
+
};
|
|
13860
|
+
}
|
|
13861
|
+
return {
|
|
13862
|
+
model: modelFromEvent(event),
|
|
13863
|
+
system: event.system,
|
|
13864
|
+
prompt: event.prompt,
|
|
13865
|
+
messages: event.messages,
|
|
13866
|
+
tools: event.tools,
|
|
13867
|
+
toolChoice: event.toolChoice,
|
|
13868
|
+
activeTools: event.activeTools,
|
|
13869
|
+
output: event.output,
|
|
13870
|
+
schema: event.schema,
|
|
13871
|
+
schemaName: event.schemaName,
|
|
13872
|
+
schemaDescription: event.schemaDescription,
|
|
13873
|
+
maxOutputTokens: event.maxOutputTokens,
|
|
13874
|
+
temperature: event.temperature,
|
|
13875
|
+
topP: event.topP,
|
|
13876
|
+
topK: event.topK,
|
|
13877
|
+
presencePenalty: event.presencePenalty,
|
|
13878
|
+
frequencyPenalty: event.frequencyPenalty,
|
|
13879
|
+
seed: event.seed,
|
|
13880
|
+
maxRetries: event.maxRetries,
|
|
13881
|
+
headers: event.headers,
|
|
13882
|
+
providerOptions: event.providerOptions
|
|
13883
|
+
};
|
|
13884
|
+
}
|
|
13885
|
+
function shiftModelSpan(modelSpans, callId) {
|
|
13886
|
+
const spans = modelSpans.get(callId);
|
|
13887
|
+
const span = spans?.shift();
|
|
13888
|
+
if (spans && spans.length === 0) {
|
|
13889
|
+
modelSpans.delete(callId);
|
|
13890
|
+
}
|
|
13891
|
+
return span;
|
|
13892
|
+
}
|
|
13893
|
+
function finishResult(event, operationName) {
|
|
13894
|
+
if (operationName === "embed") {
|
|
13895
|
+
return {
|
|
13896
|
+
...event,
|
|
13897
|
+
embedding: event.embedding
|
|
13898
|
+
};
|
|
13899
|
+
}
|
|
13900
|
+
if (operationName === "embedMany") {
|
|
13901
|
+
return {
|
|
13902
|
+
...event,
|
|
13903
|
+
embeddings: event.embedding
|
|
13904
|
+
};
|
|
13905
|
+
}
|
|
13906
|
+
if (operationName === "rerank") {
|
|
13907
|
+
return event;
|
|
13908
|
+
}
|
|
13909
|
+
return event;
|
|
13910
|
+
}
|
|
13911
|
+
function finishOutput(result, operationName) {
|
|
13912
|
+
if (operationName === "embed" || operationName === "embedMany") {
|
|
13913
|
+
return processAISDKEmbeddingOutput(
|
|
13914
|
+
result,
|
|
13915
|
+
DEFAULT_DENY_OUTPUT_PATHS
|
|
13916
|
+
);
|
|
13917
|
+
}
|
|
13918
|
+
if (operationName === "rerank") {
|
|
13919
|
+
return processAISDKRerankOutput(
|
|
13920
|
+
result,
|
|
13921
|
+
DEFAULT_DENY_OUTPUT_PATHS
|
|
13922
|
+
);
|
|
13923
|
+
}
|
|
13924
|
+
return processAISDKOutput(result, DEFAULT_DENY_OUTPUT_PATHS);
|
|
13925
|
+
}
|
|
13926
|
+
|
|
13301
13927
|
// src/instrumentation/plugins/ai-sdk-channels.ts
|
|
13302
13928
|
var aiSDKChannels = defineChannels("ai", {
|
|
13303
13929
|
generateText: channel({
|
|
@@ -13357,6 +13983,10 @@ var aiSDKChannels = defineChannels("ai", {
|
|
|
13357
13983
|
toolLoopAgentStream: channel({
|
|
13358
13984
|
channelName: "ToolLoopAgent.stream",
|
|
13359
13985
|
kind: "async"
|
|
13986
|
+
}),
|
|
13987
|
+
v7CreateTelemetryDispatcher: channel({
|
|
13988
|
+
channelName: "createTelemetryDispatcher",
|
|
13989
|
+
kind: "sync-stream"
|
|
13360
13990
|
})
|
|
13361
13991
|
});
|
|
13362
13992
|
|
|
@@ -13377,9 +14007,30 @@ var DEFAULT_DENY_OUTPUT_PATHS = [
|
|
|
13377
14007
|
];
|
|
13378
14008
|
var AUTO_PATCHED_MODEL = /* @__PURE__ */ Symbol.for("braintrust.ai-sdk.auto-patched-model");
|
|
13379
14009
|
var AUTO_PATCHED_TOOL = /* @__PURE__ */ Symbol.for("braintrust.ai-sdk.auto-patched-tool");
|
|
14010
|
+
var AUTO_PATCHED_V7_TELEMETRY_DISPATCHER = /* @__PURE__ */ Symbol.for(
|
|
14011
|
+
"braintrust.ai-sdk.v7.auto-patched-telemetry-dispatcher"
|
|
14012
|
+
);
|
|
13380
14013
|
var RUNTIME_DENY_OUTPUT_PATHS = /* @__PURE__ */ Symbol.for(
|
|
13381
14014
|
"braintrust.ai-sdk.deny-output-paths"
|
|
13382
14015
|
);
|
|
14016
|
+
var AI_SDK_V7_TELEMETRY_CALLBACKS = [
|
|
14017
|
+
"onStart",
|
|
14018
|
+
"onStepStart",
|
|
14019
|
+
"onLanguageModelCallStart",
|
|
14020
|
+
"onLanguageModelCallEnd",
|
|
14021
|
+
"onToolExecutionStart",
|
|
14022
|
+
"onToolExecutionEnd",
|
|
14023
|
+
"onChunk",
|
|
14024
|
+
"onStepFinish",
|
|
14025
|
+
"onObjectStepStart",
|
|
14026
|
+
"onObjectStepFinish",
|
|
14027
|
+
"onEmbedStart",
|
|
14028
|
+
"onEmbedFinish",
|
|
14029
|
+
"onRerankStart",
|
|
14030
|
+
"onRerankFinish",
|
|
14031
|
+
"onFinish",
|
|
14032
|
+
"onError"
|
|
14033
|
+
];
|
|
13383
14034
|
var AISDKPlugin = class extends BasePlugin {
|
|
13384
14035
|
config;
|
|
13385
14036
|
constructor(config = {}) {
|
|
@@ -13394,6 +14045,7 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
13394
14045
|
}
|
|
13395
14046
|
subscribeToAISDK() {
|
|
13396
14047
|
const denyOutputPaths = this.config.denyOutputPaths || DEFAULT_DENY_OUTPUT_PATHS;
|
|
14048
|
+
this.unsubscribers.push(subscribeToAISDKV7TelemetryDispatcher());
|
|
13397
14049
|
this.unsubscribers.push(
|
|
13398
14050
|
traceStreamingChannel(aiSDKChannels.generateText, {
|
|
13399
14051
|
name: "generateText",
|
|
@@ -13618,18 +14270,69 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
13618
14270
|
);
|
|
13619
14271
|
}
|
|
13620
14272
|
};
|
|
13621
|
-
function
|
|
13622
|
-
|
|
13623
|
-
|
|
13624
|
-
|
|
13625
|
-
|
|
13626
|
-
|
|
13627
|
-
|
|
13628
|
-
|
|
13629
|
-
|
|
13630
|
-
|
|
13631
|
-
|
|
13632
|
-
}
|
|
14273
|
+
function subscribeToAISDKV7TelemetryDispatcher() {
|
|
14274
|
+
const channel2 = aiSDKChannels.v7CreateTelemetryDispatcher.tracingChannel();
|
|
14275
|
+
const telemetry = braintrustAISDKTelemetry();
|
|
14276
|
+
const handlers = {
|
|
14277
|
+
end: (event) => {
|
|
14278
|
+
const telemetryOptions = event.arguments?.[0]?.telemetry;
|
|
14279
|
+
if (telemetryOptions?.isEnabled === false) {
|
|
14280
|
+
return;
|
|
14281
|
+
}
|
|
14282
|
+
patchAISDKV7TelemetryDispatcher(event.result, telemetry);
|
|
14283
|
+
}
|
|
14284
|
+
};
|
|
14285
|
+
channel2.subscribe(handlers);
|
|
14286
|
+
return () => {
|
|
14287
|
+
channel2.unsubscribe(handlers);
|
|
14288
|
+
};
|
|
14289
|
+
}
|
|
14290
|
+
function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry) {
|
|
14291
|
+
if (!isObject(dispatcher)) {
|
|
14292
|
+
return;
|
|
14293
|
+
}
|
|
14294
|
+
const dispatcherRecord = dispatcher;
|
|
14295
|
+
if (dispatcherRecord[AUTO_PATCHED_V7_TELEMETRY_DISPATCHER]) {
|
|
14296
|
+
return;
|
|
14297
|
+
}
|
|
14298
|
+
dispatcherRecord[AUTO_PATCHED_V7_TELEMETRY_DISPATCHER] = true;
|
|
14299
|
+
for (const key of AI_SDK_V7_TELEMETRY_CALLBACKS) {
|
|
14300
|
+
const braintrustCallback = telemetry[key];
|
|
14301
|
+
if (typeof braintrustCallback !== "function") {
|
|
14302
|
+
continue;
|
|
14303
|
+
}
|
|
14304
|
+
const existingCallback = dispatcherRecord[key];
|
|
14305
|
+
dispatcherRecord[key] = (event) => {
|
|
14306
|
+
const existingResult = typeof existingCallback === "function" ? existingCallback.call(dispatcher, event) : void 0;
|
|
14307
|
+
const braintrustResult = braintrustCallback.call(telemetry, event);
|
|
14308
|
+
const pending = [existingResult, braintrustResult].filter(isPromiseLike);
|
|
14309
|
+
if (pending.length > 0) {
|
|
14310
|
+
return Promise.allSettled(pending).then(() => void 0);
|
|
14311
|
+
}
|
|
14312
|
+
};
|
|
14313
|
+
}
|
|
14314
|
+
const braintrustExecuteTool = telemetry.executeTool;
|
|
14315
|
+
if (typeof braintrustExecuteTool !== "function") {
|
|
14316
|
+
return;
|
|
14317
|
+
}
|
|
14318
|
+
const existingExecuteTool = dispatcherRecord.executeTool;
|
|
14319
|
+
dispatcherRecord.executeTool = (args) => braintrustExecuteTool.call(telemetry, {
|
|
14320
|
+
...args,
|
|
14321
|
+
execute: () => typeof existingExecuteTool === "function" ? existingExecuteTool.call(dispatcher, args) : args.execute()
|
|
14322
|
+
});
|
|
14323
|
+
}
|
|
14324
|
+
function resolveDenyOutputPaths(event, defaultDenyOutputPaths) {
|
|
14325
|
+
if (Array.isArray(event?.denyOutputPaths)) {
|
|
14326
|
+
return event.denyOutputPaths;
|
|
14327
|
+
}
|
|
14328
|
+
const firstArgument2 = event?.arguments && event.arguments.length > 0 ? event.arguments[0] : void 0;
|
|
14329
|
+
if (!firstArgument2 || typeof firstArgument2 !== "object") {
|
|
14330
|
+
return defaultDenyOutputPaths;
|
|
14331
|
+
}
|
|
14332
|
+
const runtimeDenyOutputPaths = firstArgument2[RUNTIME_DENY_OUTPUT_PATHS];
|
|
14333
|
+
if (Array.isArray(runtimeDenyOutputPaths) && runtimeDenyOutputPaths.every((path) => typeof path === "string")) {
|
|
14334
|
+
return runtimeDenyOutputPaths;
|
|
14335
|
+
}
|
|
13633
14336
|
return defaultDenyOutputPaths;
|
|
13634
14337
|
}
|
|
13635
14338
|
var isZodSchema2 = (value) => {
|
|
@@ -14069,11 +14772,11 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
|
|
|
14069
14772
|
metadata: baseMetadata
|
|
14070
14773
|
}
|
|
14071
14774
|
});
|
|
14775
|
+
const streamStartTime = getCurrentUnixTimestamp();
|
|
14072
14776
|
const result = await withCurrent(
|
|
14073
14777
|
span,
|
|
14074
14778
|
() => Reflect.apply(originalDoStream, resolvedModel, [options])
|
|
14075
14779
|
);
|
|
14076
|
-
const streamStartTime = getCurrentUnixTimestamp();
|
|
14077
14780
|
let firstChunkTime;
|
|
14078
14781
|
const output = {};
|
|
14079
14782
|
let text = "";
|
|
@@ -14082,7 +14785,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
|
|
|
14082
14785
|
let object = void 0;
|
|
14083
14786
|
const transformStream = new TransformStream({
|
|
14084
14787
|
transform(chunk, controller) {
|
|
14085
|
-
if (firstChunkTime === void 0) {
|
|
14788
|
+
if (firstChunkTime === void 0 && isAISDKContentStreamChunk(chunk)) {
|
|
14086
14789
|
firstChunkTime = getCurrentUnixTimestamp();
|
|
14087
14790
|
}
|
|
14088
14791
|
switch (chunk.type) {
|
|
@@ -14274,6 +14977,78 @@ function finalizeAISDKChildTracing(event) {
|
|
|
14274
14977
|
delete event.__braintrust_ai_sdk_cleanup;
|
|
14275
14978
|
}
|
|
14276
14979
|
}
|
|
14980
|
+
function extractAISDKStreamPart(chunk) {
|
|
14981
|
+
if (!isObject(chunk) || !isObject(chunk.part)) {
|
|
14982
|
+
return chunk;
|
|
14983
|
+
}
|
|
14984
|
+
return chunk.part;
|
|
14985
|
+
}
|
|
14986
|
+
function stringContent(value) {
|
|
14987
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
14988
|
+
}
|
|
14989
|
+
function rawValueHasAISDKContent(value) {
|
|
14990
|
+
if (value === void 0 || value === null) {
|
|
14991
|
+
return false;
|
|
14992
|
+
}
|
|
14993
|
+
if (typeof value === "string") {
|
|
14994
|
+
return value.length > 0;
|
|
14995
|
+
}
|
|
14996
|
+
if (!isObject(value)) {
|
|
14997
|
+
return true;
|
|
14998
|
+
}
|
|
14999
|
+
const delta = value.delta;
|
|
15000
|
+
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) => {
|
|
15001
|
+
if (!isObject(choice) || !isObject(choice.delta)) {
|
|
15002
|
+
return false;
|
|
15003
|
+
}
|
|
15004
|
+
const choiceDelta = choice.delta;
|
|
15005
|
+
if (stringContent(choiceDelta.content) || stringContent(choiceDelta.text)) {
|
|
15006
|
+
return true;
|
|
15007
|
+
}
|
|
15008
|
+
if (isObject(choiceDelta.function_call) && stringContent(choiceDelta.function_call.arguments)) {
|
|
15009
|
+
return true;
|
|
15010
|
+
}
|
|
15011
|
+
return Array.isArray(choiceDelta.tool_calls) && choiceDelta.tool_calls.some(
|
|
15012
|
+
(toolCall) => isObject(toolCall) && isObject(toolCall.function) && stringContent(toolCall.function.arguments)
|
|
15013
|
+
);
|
|
15014
|
+
})) {
|
|
15015
|
+
return true;
|
|
15016
|
+
}
|
|
15017
|
+
return false;
|
|
15018
|
+
}
|
|
15019
|
+
function isAISDKContentStreamChunk(chunk) {
|
|
15020
|
+
const part = extractAISDKStreamPart(chunk);
|
|
15021
|
+
if (typeof part === "string") {
|
|
15022
|
+
return part.length > 0;
|
|
15023
|
+
}
|
|
15024
|
+
if (!isObject(part) || typeof part.type !== "string") {
|
|
15025
|
+
return false;
|
|
15026
|
+
}
|
|
15027
|
+
switch (part.type) {
|
|
15028
|
+
case "text-delta":
|
|
15029
|
+
return stringContent(part.textDelta) !== void 0 || stringContent(part.delta) !== void 0 || stringContent(part.text) !== void 0 || stringContent(part.content) !== void 0;
|
|
15030
|
+
case "reasoning-delta":
|
|
15031
|
+
return stringContent(part.delta) !== void 0 || stringContent(part.text) !== void 0 || stringContent(part.content) !== void 0;
|
|
15032
|
+
case "tool-call":
|
|
15033
|
+
case "object":
|
|
15034
|
+
case "file":
|
|
15035
|
+
return true;
|
|
15036
|
+
case "tool-input-delta":
|
|
15037
|
+
case "tool-call-delta":
|
|
15038
|
+
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;
|
|
15039
|
+
case "raw":
|
|
15040
|
+
return rawValueHasAISDKContent(part.rawValue);
|
|
15041
|
+
default:
|
|
15042
|
+
return false;
|
|
15043
|
+
}
|
|
15044
|
+
}
|
|
15045
|
+
function isAISDKContentAsyncIterableChunk(chunk) {
|
|
15046
|
+
if (isAISDKContentStreamChunk(chunk)) {
|
|
15047
|
+
return true;
|
|
15048
|
+
}
|
|
15049
|
+
const part = extractAISDKStreamPart(chunk);
|
|
15050
|
+
return isObject(part) && typeof part.type !== "string";
|
|
15051
|
+
}
|
|
14277
15052
|
function patchAISDKStreamingResult(args) {
|
|
14278
15053
|
const { defaultDenyOutputPaths, endEvent, result, span, startTime } = args;
|
|
14279
15054
|
if (!result || typeof result !== "object") {
|
|
@@ -14286,7 +15061,7 @@ function patchAISDKStreamingResult(args) {
|
|
|
14286
15061
|
const wrappedBaseStream = resultRecord.baseStream.pipeThrough(
|
|
14287
15062
|
new TransformStream({
|
|
14288
15063
|
transform(chunk, controller) {
|
|
14289
|
-
if (firstChunkTime2 === void 0) {
|
|
15064
|
+
if (firstChunkTime2 === void 0 && isAISDKContentStreamChunk(chunk)) {
|
|
14290
15065
|
firstChunkTime2 = getCurrentUnixTimestamp();
|
|
14291
15066
|
}
|
|
14292
15067
|
controller.enqueue(chunk);
|
|
@@ -14330,8 +15105,8 @@ function patchAISDKStreamingResult(args) {
|
|
|
14330
15105
|
}
|
|
14331
15106
|
let firstChunkTime;
|
|
14332
15107
|
const wrappedStream = createPatchedAsyncIterable(streamField.stream, {
|
|
14333
|
-
onChunk: () => {
|
|
14334
|
-
if (firstChunkTime === void 0) {
|
|
15108
|
+
onChunk: (chunk) => {
|
|
15109
|
+
if (firstChunkTime === void 0 && isAISDKContentAsyncIterableChunk(chunk)) {
|
|
14335
15110
|
firstChunkTime = getCurrentUnixTimestamp();
|
|
14336
15111
|
}
|
|
14337
15112
|
},
|
|
@@ -15303,15 +16078,17 @@ function collectLocalMcpServerToolHookNames(serverName, serverConfig) {
|
|
|
15303
16078
|
|
|
15304
16079
|
// src/instrumentation/plugins/claude-agent-sdk-plugin.ts
|
|
15305
16080
|
var ROOT_LLM_PARENT_KEY = "__root__";
|
|
16081
|
+
var SUB_AGENT_PROMPT_SOURCE_PRIORITY = {
|
|
16082
|
+
delegation: 0,
|
|
16083
|
+
lifecycle: 1,
|
|
16084
|
+
sidechain: 2
|
|
16085
|
+
};
|
|
15306
16086
|
function llmParentKey(parentToolUseId) {
|
|
15307
16087
|
return parentToolUseId ?? ROOT_LLM_PARENT_KEY;
|
|
15308
16088
|
}
|
|
15309
16089
|
function isSubAgentDelegationToolName(toolName) {
|
|
15310
16090
|
return toolName === "Agent" || toolName === "Task";
|
|
15311
16091
|
}
|
|
15312
|
-
function shouldParentToolAsTaskSibling(toolName) {
|
|
15313
|
-
return toolName === "Agent" || toolName === "Task" || toolName === "Bash";
|
|
15314
|
-
}
|
|
15315
16092
|
function filterSerializableOptions(options) {
|
|
15316
16093
|
const allowedKeys = [
|
|
15317
16094
|
"model",
|
|
@@ -15448,26 +16225,39 @@ function extractUsageFromMessage(message) {
|
|
|
15448
16225
|
}
|
|
15449
16226
|
return metrics;
|
|
15450
16227
|
}
|
|
15451
|
-
function buildLLMInput(
|
|
15452
|
-
const promptMessages = [];
|
|
15453
|
-
if (typeof prompt === "string") {
|
|
15454
|
-
promptMessages.push({ content: prompt, role: "user" });
|
|
15455
|
-
} else if (capturedPromptMessages && capturedPromptMessages.length > 0) {
|
|
15456
|
-
for (const msg of capturedPromptMessages) {
|
|
15457
|
-
const role = msg.message?.role;
|
|
15458
|
-
const content = msg.message?.content;
|
|
15459
|
-
if (role && content !== void 0) {
|
|
15460
|
-
promptMessages.push({ content, role });
|
|
15461
|
-
}
|
|
15462
|
-
}
|
|
15463
|
-
}
|
|
16228
|
+
function buildLLMInput(promptMessages, conversationHistory) {
|
|
15464
16229
|
const inputParts = [...promptMessages, ...conversationHistory];
|
|
15465
16230
|
return inputParts.length > 0 ? inputParts : void 0;
|
|
15466
16231
|
}
|
|
16232
|
+
function conversationMessageFromSDKMessage(message) {
|
|
16233
|
+
const role = message.message?.role;
|
|
16234
|
+
const content = message.message?.content;
|
|
16235
|
+
if (role && content !== void 0) {
|
|
16236
|
+
return { content, role };
|
|
16237
|
+
}
|
|
16238
|
+
return void 0;
|
|
16239
|
+
}
|
|
16240
|
+
function messageContentHasBlockType(message, blockType) {
|
|
16241
|
+
const content = message.message?.content;
|
|
16242
|
+
return Array.isArray(content) && content.some(
|
|
16243
|
+
(block) => typeof block === "object" && block !== null && "type" in block && block.type === blockType
|
|
16244
|
+
);
|
|
16245
|
+
}
|
|
16246
|
+
function buildRootPromptMessages(prompt, capturedPromptMessages) {
|
|
16247
|
+
if (typeof prompt === "string") {
|
|
16248
|
+
return [{ content: prompt, role: "user" }];
|
|
16249
|
+
}
|
|
16250
|
+
if (!capturedPromptMessages || capturedPromptMessages.length === 0) {
|
|
16251
|
+
return [];
|
|
16252
|
+
}
|
|
16253
|
+
return capturedPromptMessages.map(conversationMessageFromSDKMessage).filter(
|
|
16254
|
+
(message) => message !== void 0
|
|
16255
|
+
);
|
|
16256
|
+
}
|
|
15467
16257
|
function formatCapturedMessages(messages) {
|
|
15468
16258
|
return messages.length > 0 ? messages : [];
|
|
15469
16259
|
}
|
|
15470
|
-
async function createLLMSpanForMessages(messages,
|
|
16260
|
+
async function createLLMSpanForMessages(messages, promptMessages, conversationHistory, options, startTime, parentSpan, existingSpan) {
|
|
15471
16261
|
if (messages.length === 0) {
|
|
15472
16262
|
return void 0;
|
|
15473
16263
|
}
|
|
@@ -15477,11 +16267,7 @@ async function createLLMSpanForMessages(messages, prompt, conversationHistory, o
|
|
|
15477
16267
|
}
|
|
15478
16268
|
const model = lastMessage.message.model || options.model;
|
|
15479
16269
|
const usage = extractUsageFromMessage(lastMessage);
|
|
15480
|
-
const input = buildLLMInput(
|
|
15481
|
-
prompt,
|
|
15482
|
-
conversationHistory,
|
|
15483
|
-
capturedPromptMessages
|
|
15484
|
-
);
|
|
16270
|
+
const input = buildLLMInput(promptMessages, conversationHistory);
|
|
15485
16271
|
const outputs = messages.map(
|
|
15486
16272
|
(m) => m.message?.content && m.message?.role ? { content: m.message.content, role: m.message.role } : void 0
|
|
15487
16273
|
).filter(
|
|
@@ -15612,8 +16398,7 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
|
|
|
15612
16398
|
},
|
|
15613
16399
|
name: parsed.displayName,
|
|
15614
16400
|
parent: await resolveParentSpan(toolUseID, {
|
|
15615
|
-
agentId: input.agent_id
|
|
15616
|
-
preferTaskSiblingParent: shouldParentToolAsTaskSibling(parsed.toolName)
|
|
16401
|
+
agentId: input.agent_id
|
|
15617
16402
|
}),
|
|
15618
16403
|
spanAttributes: { type: "tool" /* TOOL */ }
|
|
15619
16404
|
});
|
|
@@ -15859,12 +16644,37 @@ function injectTracingHooks(options, resolveParentSpan, activeToolSpans, localTo
|
|
|
15859
16644
|
}
|
|
15860
16645
|
};
|
|
15861
16646
|
}
|
|
16647
|
+
function setSubAgentPromptMessages(state, parentToolUseId, promptMessages, source) {
|
|
16648
|
+
if (promptMessages.length === 0) {
|
|
16649
|
+
return;
|
|
16650
|
+
}
|
|
16651
|
+
const parentKey = llmParentKey(parentToolUseId);
|
|
16652
|
+
const sourcePriority = SUB_AGENT_PROMPT_SOURCE_PRIORITY[source];
|
|
16653
|
+
const currentPriority = state.promptSourcePriorityByParentKey.get(parentKey) ?? -1;
|
|
16654
|
+
if (sourcePriority > currentPriority) {
|
|
16655
|
+
state.promptMessagesByParentKey.set(parentKey, promptMessages);
|
|
16656
|
+
state.promptSourcePriorityByParentKey.set(parentKey, sourcePriority);
|
|
16657
|
+
}
|
|
16658
|
+
}
|
|
16659
|
+
function getConversationHistory(state, parentKey) {
|
|
16660
|
+
let conversationHistory = state.conversationHistoryByParentKey.get(parentKey);
|
|
16661
|
+
if (!conversationHistory) {
|
|
16662
|
+
conversationHistory = [];
|
|
16663
|
+
state.conversationHistoryByParentKey.set(parentKey, conversationHistory);
|
|
16664
|
+
}
|
|
16665
|
+
return conversationHistory;
|
|
16666
|
+
}
|
|
15862
16667
|
async function finalizeCurrentMessageGroup(state) {
|
|
15863
16668
|
if (state.currentMessages.length === 0) {
|
|
15864
16669
|
return;
|
|
15865
16670
|
}
|
|
15866
16671
|
const parentToolUseId = state.currentMessages[0]?.parent_tool_use_id ?? null;
|
|
15867
16672
|
const parentKey = llmParentKey(parentToolUseId);
|
|
16673
|
+
const conversationHistory = getConversationHistory(state, parentKey);
|
|
16674
|
+
const promptMessages = parentToolUseId ? state.promptMessagesByParentKey.get(parentKey) ?? [] : buildRootPromptMessages(
|
|
16675
|
+
state.originalPrompt,
|
|
16676
|
+
state.capturedPromptMessages
|
|
16677
|
+
);
|
|
15868
16678
|
let parentSpan = await state.span.export();
|
|
15869
16679
|
if (parentToolUseId) {
|
|
15870
16680
|
const subAgentSpan = state.subAgentSpans.get(parentToolUseId);
|
|
@@ -15875,11 +16685,10 @@ async function finalizeCurrentMessageGroup(state) {
|
|
|
15875
16685
|
const existingLlmSpan = state.activeLlmSpansByParentToolUse.get(parentKey);
|
|
15876
16686
|
const llmSpanResult = await createLLMSpanForMessages(
|
|
15877
16687
|
state.currentMessages,
|
|
15878
|
-
|
|
15879
|
-
|
|
16688
|
+
promptMessages,
|
|
16689
|
+
conversationHistory,
|
|
15880
16690
|
state.options,
|
|
15881
16691
|
state.currentMessageStartTime,
|
|
15882
|
-
state.capturedPromptMessages,
|
|
15883
16692
|
parentSpan,
|
|
15884
16693
|
existingLlmSpan
|
|
15885
16694
|
);
|
|
@@ -15893,6 +16702,7 @@ async function finalizeCurrentMessageGroup(state) {
|
|
|
15893
16702
|
state.latestRootLlmParentRef.value = llmSpanResult.spanExport;
|
|
15894
16703
|
}
|
|
15895
16704
|
if (llmSpanResult.finalMessage) {
|
|
16705
|
+
conversationHistory.push(llmSpanResult.finalMessage);
|
|
15896
16706
|
state.finalResults.push(llmSpanResult.finalMessage);
|
|
15897
16707
|
}
|
|
15898
16708
|
}
|
|
@@ -15920,6 +16730,15 @@ function maybeTrackToolUseContext(state, message) {
|
|
|
15920
16730
|
description: getStringProperty(block.input, "description"),
|
|
15921
16731
|
toolUseId: block.id
|
|
15922
16732
|
});
|
|
16733
|
+
const prompt = getStringProperty(block.input, "prompt");
|
|
16734
|
+
if (prompt) {
|
|
16735
|
+
setSubAgentPromptMessages(
|
|
16736
|
+
state,
|
|
16737
|
+
block.id,
|
|
16738
|
+
[{ content: prompt, role: "user" }],
|
|
16739
|
+
"delegation"
|
|
16740
|
+
);
|
|
16741
|
+
}
|
|
15923
16742
|
}
|
|
15924
16743
|
}
|
|
15925
16744
|
}
|
|
@@ -16038,6 +16857,14 @@ async function maybeHandleTaskLifecycleMessage(state, message) {
|
|
|
16038
16857
|
};
|
|
16039
16858
|
if (message.subtype === "task_started") {
|
|
16040
16859
|
const prompt = getStringProperty(message, "prompt");
|
|
16860
|
+
if (prompt) {
|
|
16861
|
+
setSubAgentPromptMessages(
|
|
16862
|
+
state,
|
|
16863
|
+
toolUseId,
|
|
16864
|
+
[{ content: prompt, role: "user" }],
|
|
16865
|
+
"lifecycle"
|
|
16866
|
+
);
|
|
16867
|
+
}
|
|
16041
16868
|
subAgentSpan.log({
|
|
16042
16869
|
input: prompt,
|
|
16043
16870
|
metadata
|
|
@@ -16088,6 +16915,28 @@ async function handleStreamMessage(state, message) {
|
|
|
16088
16915
|
return;
|
|
16089
16916
|
}
|
|
16090
16917
|
await maybeStartSubAgentSpan(state, message);
|
|
16918
|
+
const messageParentToolUseId = message.parent_tool_use_id;
|
|
16919
|
+
if (messageParentToolUseId && message.type === "user") {
|
|
16920
|
+
const conversationMessage = conversationMessageFromSDKMessage(message);
|
|
16921
|
+
if (conversationMessage?.role === "user") {
|
|
16922
|
+
await finalizeCurrentMessageGroup(state);
|
|
16923
|
+
const parentKey = llmParentKey(messageParentToolUseId);
|
|
16924
|
+
const conversationHistory = getConversationHistory(state, parentKey);
|
|
16925
|
+
const currentPromptSourcePriority = state.promptSourcePriorityByParentKey.get(parentKey) ?? -1;
|
|
16926
|
+
const canUseAsInitialSidechainPrompt = conversationHistory.length === 0 && currentPromptSourcePriority < SUB_AGENT_PROMPT_SOURCE_PRIORITY.sidechain && !messageContentHasBlockType(message, "tool_result");
|
|
16927
|
+
if (!canUseAsInitialSidechainPrompt) {
|
|
16928
|
+
conversationHistory.push(conversationMessage);
|
|
16929
|
+
return;
|
|
16930
|
+
}
|
|
16931
|
+
setSubAgentPromptMessages(
|
|
16932
|
+
state,
|
|
16933
|
+
messageParentToolUseId,
|
|
16934
|
+
[conversationMessage],
|
|
16935
|
+
"sidechain"
|
|
16936
|
+
);
|
|
16937
|
+
return;
|
|
16938
|
+
}
|
|
16939
|
+
}
|
|
16091
16940
|
const messageId = message.message?.id;
|
|
16092
16941
|
if (messageId && messageId !== state.currentMessageId) {
|
|
16093
16942
|
await finalizeCurrentMessageGroup(state);
|
|
@@ -16239,6 +17088,7 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
16239
17088
|
}
|
|
16240
17089
|
const activeToolSpans = /* @__PURE__ */ new Map();
|
|
16241
17090
|
const activeLlmSpansByParentToolUse = /* @__PURE__ */ new Map();
|
|
17091
|
+
const conversationHistoryByParentKey = /* @__PURE__ */ new Map();
|
|
16242
17092
|
const subAgentSpans = /* @__PURE__ */ new Map();
|
|
16243
17093
|
const endedSubAgentSpans = /* @__PURE__ */ new Set();
|
|
16244
17094
|
const toolUseToParent = /* @__PURE__ */ new Map();
|
|
@@ -16248,6 +17098,8 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
16248
17098
|
};
|
|
16249
17099
|
const subAgentDetailsByToolUseId = /* @__PURE__ */ new Map();
|
|
16250
17100
|
const taskIdToToolUseId = /* @__PURE__ */ new Map();
|
|
17101
|
+
const promptMessagesByParentKey = /* @__PURE__ */ new Map();
|
|
17102
|
+
const promptSourcePriorityByParentKey = /* @__PURE__ */ new Map();
|
|
16251
17103
|
const localToolContext = createClaudeLocalToolContext();
|
|
16252
17104
|
const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
|
|
16253
17105
|
const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
|
|
@@ -16256,38 +17108,19 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
16256
17108
|
const parentToolUseId = trackedParentToolUseId ?? (context?.agentId ? taskIdToToolUseId.get(context.agentId) ?? null : null);
|
|
16257
17109
|
const parentKey = llmParentKey(parentToolUseId);
|
|
16258
17110
|
const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
|
|
16259
|
-
|
|
16260
|
-
|
|
16261
|
-
|
|
16262
|
-
|
|
16263
|
-
|
|
16264
|
-
|
|
16265
|
-
|
|
16266
|
-
|
|
16267
|
-
|
|
16268
|
-
|
|
16269
|
-
|
|
16270
|
-
}
|
|
16271
|
-
if (parentToolUseId) {
|
|
16272
|
-
const subAgentSpan = await ensureSubAgentSpan(
|
|
16273
|
-
subAgentDetailsByToolUseId,
|
|
16274
|
-
span,
|
|
16275
|
-
activeToolSpans,
|
|
16276
|
-
subAgentSpans,
|
|
16277
|
-
parentToolUseId
|
|
16278
|
-
);
|
|
16279
|
-
return subAgentSpan.export();
|
|
16280
|
-
}
|
|
16281
|
-
return span.export();
|
|
16282
|
-
}
|
|
16283
|
-
if (activeLlmSpan) {
|
|
16284
|
-
return activeLlmSpan.export();
|
|
17111
|
+
const latestLlmParent = parentToolUseId ? latestLlmParentBySubAgentToolUse.get(parentToolUseId) : latestRootLlmParentRef.value;
|
|
17112
|
+
if (!activeLlmSpan && !latestLlmParent) {
|
|
17113
|
+
await ensureActiveLlmSpanForParentToolUse(
|
|
17114
|
+
span,
|
|
17115
|
+
activeLlmSpansByParentToolUse,
|
|
17116
|
+
subAgentDetailsByToolUseId,
|
|
17117
|
+
activeToolSpans,
|
|
17118
|
+
subAgentSpans,
|
|
17119
|
+
parentToolUseId,
|
|
17120
|
+
getCurrentUnixTimestamp()
|
|
17121
|
+
);
|
|
16285
17122
|
}
|
|
16286
17123
|
if (parentToolUseId) {
|
|
16287
|
-
const parentLlm = latestLlmParentBySubAgentToolUse.get(parentToolUseId);
|
|
16288
|
-
if (parentLlm) {
|
|
16289
|
-
return parentLlm;
|
|
16290
|
-
}
|
|
16291
17124
|
const subAgentSpan = await ensureSubAgentSpan(
|
|
16292
17125
|
subAgentDetailsByToolUseId,
|
|
16293
17126
|
span,
|
|
@@ -16297,9 +17130,6 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
16297
17130
|
);
|
|
16298
17131
|
return subAgentSpan.export();
|
|
16299
17132
|
}
|
|
16300
|
-
if (latestRootLlmParentRef.value) {
|
|
16301
|
-
return latestRootLlmParentRef.value;
|
|
16302
|
-
}
|
|
16303
17133
|
return span.export();
|
|
16304
17134
|
};
|
|
16305
17135
|
localToolContext.resolveLocalToolParent = resolveToolUseParentSpan;
|
|
@@ -16320,6 +17150,7 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
16320
17150
|
accumulatedOutputTokens: 0,
|
|
16321
17151
|
activeLlmSpansByParentToolUse,
|
|
16322
17152
|
activeToolSpans,
|
|
17153
|
+
conversationHistoryByParentKey,
|
|
16323
17154
|
capturedPromptMessages,
|
|
16324
17155
|
currentMessageId: void 0,
|
|
16325
17156
|
currentMessageStartTime: startTime,
|
|
@@ -16330,7 +17161,9 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
16330
17161
|
originalPrompt,
|
|
16331
17162
|
processing: Promise.resolve(),
|
|
16332
17163
|
promptDone,
|
|
17164
|
+
promptMessagesByParentKey,
|
|
16333
17165
|
promptStarted: () => promptStarted,
|
|
17166
|
+
promptSourcePriorityByParentKey,
|
|
16334
17167
|
span,
|
|
16335
17168
|
subAgentDetailsByToolUseId,
|
|
16336
17169
|
subAgentSpans,
|
|
@@ -17759,6 +18592,10 @@ var googleGenAIChannels = defineChannels("@google/genai", {
|
|
|
17759
18592
|
embedContent: channel({
|
|
17760
18593
|
channelName: "models.embedContent",
|
|
17761
18594
|
kind: "async"
|
|
18595
|
+
}),
|
|
18596
|
+
interactionsCreate: channel({
|
|
18597
|
+
channelName: "interactions.create",
|
|
18598
|
+
kind: "async"
|
|
17762
18599
|
})
|
|
17763
18600
|
});
|
|
17764
18601
|
|
|
@@ -17786,6 +18623,7 @@ var GoogleGenAIPlugin = class extends BasePlugin {
|
|
|
17786
18623
|
this.subscribeToGenerateContentChannel();
|
|
17787
18624
|
this.subscribeToGenerateContentStreamChannel();
|
|
17788
18625
|
this.subscribeToEmbedContentChannel();
|
|
18626
|
+
this.subscribeToInteractionsCreateChannel();
|
|
17789
18627
|
}
|
|
17790
18628
|
subscribeToGenerateContentChannel() {
|
|
17791
18629
|
const tracingChannel2 = googleGenAIChannels.generateContent.tracingChannel();
|
|
@@ -17958,7 +18796,30 @@ var GoogleGenAIPlugin = class extends BasePlugin {
|
|
|
17958
18796
|
tracingChannel2.unsubscribe(handlers);
|
|
17959
18797
|
});
|
|
17960
18798
|
}
|
|
18799
|
+
subscribeToInteractionsCreateChannel() {
|
|
18800
|
+
this.unsubscribers.push(
|
|
18801
|
+
traceStreamingChannel(
|
|
18802
|
+
googleGenAIChannels.interactionsCreate,
|
|
18803
|
+
{
|
|
18804
|
+
name: "create_interaction",
|
|
18805
|
+
shouldTrace: ([params]) => !isBackgroundInteractionCreate(params),
|
|
18806
|
+
type: "llm" /* LLM */,
|
|
18807
|
+
extractInput: ([params]) => ({
|
|
18808
|
+
input: serializeInteractionInput(params),
|
|
18809
|
+
metadata: extractInteractionMetadata(params)
|
|
18810
|
+
}),
|
|
18811
|
+
extractOutput: (result) => serializeInteractionValue(result),
|
|
18812
|
+
extractMetadata: (result) => extractInteractionResponseMetadata(result),
|
|
18813
|
+
extractMetrics: (result, startTime) => cleanMetrics3(extractInteractionMetrics(result, startTime)),
|
|
18814
|
+
aggregateChunks: (chunks, _result, _event, startTime) => aggregateInteractionEvents(chunks, startTime)
|
|
18815
|
+
}
|
|
18816
|
+
)
|
|
18817
|
+
);
|
|
18818
|
+
}
|
|
17961
18819
|
};
|
|
18820
|
+
function isBackgroundInteractionCreate(params) {
|
|
18821
|
+
return tryToDict(params)?.background === true;
|
|
18822
|
+
}
|
|
17962
18823
|
function ensureSpanState(states, event, create) {
|
|
17963
18824
|
const existing = states.get(event);
|
|
17964
18825
|
if (existing) {
|
|
@@ -18166,6 +19027,60 @@ function serializeEmbedContentInput(params) {
|
|
|
18166
19027
|
}
|
|
18167
19028
|
return input;
|
|
18168
19029
|
}
|
|
19030
|
+
function serializeInteractionInput(params) {
|
|
19031
|
+
const input = {
|
|
19032
|
+
input: serializeInteractionValue(params.input)
|
|
19033
|
+
};
|
|
19034
|
+
for (const key of [
|
|
19035
|
+
"model",
|
|
19036
|
+
"agent",
|
|
19037
|
+
"agent_config",
|
|
19038
|
+
"api_version",
|
|
19039
|
+
"background",
|
|
19040
|
+
"environment",
|
|
19041
|
+
"generation_config",
|
|
19042
|
+
"previous_interaction_id",
|
|
19043
|
+
"response_format",
|
|
19044
|
+
"response_mime_type",
|
|
19045
|
+
"response_modalities",
|
|
19046
|
+
"service_tier",
|
|
19047
|
+
"store",
|
|
19048
|
+
"stream",
|
|
19049
|
+
"system_instruction",
|
|
19050
|
+
"webhook_config"
|
|
19051
|
+
]) {
|
|
19052
|
+
const value = params[key];
|
|
19053
|
+
if (value !== void 0) {
|
|
19054
|
+
input[key] = serializeInteractionValue(value);
|
|
19055
|
+
}
|
|
19056
|
+
}
|
|
19057
|
+
return input;
|
|
19058
|
+
}
|
|
19059
|
+
function extractInteractionMetadata(params) {
|
|
19060
|
+
const metadata = {};
|
|
19061
|
+
for (const key of [
|
|
19062
|
+
"model",
|
|
19063
|
+
"agent",
|
|
19064
|
+
"agent_config",
|
|
19065
|
+
"generation_config",
|
|
19066
|
+
"system_instruction",
|
|
19067
|
+
"response_format",
|
|
19068
|
+
"response_mime_type",
|
|
19069
|
+
"response_modalities",
|
|
19070
|
+
"service_tier"
|
|
19071
|
+
]) {
|
|
19072
|
+
const value = params[key];
|
|
19073
|
+
if (value !== void 0) {
|
|
19074
|
+
metadata[key] = serializeInteractionValue(value);
|
|
19075
|
+
}
|
|
19076
|
+
}
|
|
19077
|
+
if (Array.isArray(params.tools)) {
|
|
19078
|
+
metadata.tools = params.tools.map(
|
|
19079
|
+
(tool) => serializeInteractionValue(tool)
|
|
19080
|
+
);
|
|
19081
|
+
}
|
|
19082
|
+
return metadata;
|
|
19083
|
+
}
|
|
18169
19084
|
function serializeContentCollection(contents) {
|
|
18170
19085
|
if (contents === null || contents === void 0) {
|
|
18171
19086
|
return null;
|
|
@@ -18196,21 +19111,8 @@ function serializePart(part) {
|
|
|
18196
19111
|
}
|
|
18197
19112
|
if (part.inlineData && part.inlineData.data) {
|
|
18198
19113
|
const { data, mimeType } = part.inlineData;
|
|
18199
|
-
|
|
18200
|
-
|
|
18201
|
-
const filename = `file.${extension}`;
|
|
18202
|
-
const buffer = typeof data === "string" ? typeof Buffer !== "undefined" ? Buffer.from(data, "base64") : new Uint8Array(
|
|
18203
|
-
atob(data).split("").map((c) => c.charCodeAt(0))
|
|
18204
|
-
) : typeof Buffer !== "undefined" ? Buffer.from(data) : new Uint8Array(data);
|
|
18205
|
-
const arrayBuffer = buffer instanceof Uint8Array ? buffer.buffer.slice(
|
|
18206
|
-
buffer.byteOffset,
|
|
18207
|
-
buffer.byteOffset + buffer.byteLength
|
|
18208
|
-
) : buffer;
|
|
18209
|
-
const attachment = new Attachment({
|
|
18210
|
-
data: arrayBuffer,
|
|
18211
|
-
filename,
|
|
18212
|
-
contentType: mimeType || "application/octet-stream"
|
|
18213
|
-
});
|
|
19114
|
+
const attachment = createAttachmentFromInlineData(data, mimeType);
|
|
19115
|
+
if (attachment) {
|
|
18214
19116
|
return {
|
|
18215
19117
|
image_url: { url: attachment }
|
|
18216
19118
|
};
|
|
@@ -18218,6 +19120,59 @@ function serializePart(part) {
|
|
|
18218
19120
|
}
|
|
18219
19121
|
return part;
|
|
18220
19122
|
}
|
|
19123
|
+
function serializeInteractionValue(value, seen = /* @__PURE__ */ new WeakSet()) {
|
|
19124
|
+
if (value === null || value === void 0 || typeof value !== "object") {
|
|
19125
|
+
return value;
|
|
19126
|
+
}
|
|
19127
|
+
if (Array.isArray(value)) {
|
|
19128
|
+
return value.map((item) => serializeInteractionValue(item, seen));
|
|
19129
|
+
}
|
|
19130
|
+
const dict = tryToDict(value);
|
|
19131
|
+
if (dict === null || dict === void 0 || typeof dict !== "object") {
|
|
19132
|
+
return dict;
|
|
19133
|
+
}
|
|
19134
|
+
if (Array.isArray(dict)) {
|
|
19135
|
+
return dict.map((item) => serializeInteractionValue(item, seen));
|
|
19136
|
+
}
|
|
19137
|
+
if (seen.has(dict)) {
|
|
19138
|
+
return "[Circular]";
|
|
19139
|
+
}
|
|
19140
|
+
seen.add(dict);
|
|
19141
|
+
try {
|
|
19142
|
+
const serialized = {};
|
|
19143
|
+
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;
|
|
19144
|
+
const attachment = mimeType && "data" in dict && dict.data !== void 0 ? createAttachmentFromInlineData(dict.data, mimeType) : null;
|
|
19145
|
+
for (const [key, entry] of Object.entries(dict)) {
|
|
19146
|
+
if (key === "data" && attachment) {
|
|
19147
|
+
serialized[key] = attachment;
|
|
19148
|
+
} else {
|
|
19149
|
+
serialized[key] = serializeInteractionValue(entry, seen);
|
|
19150
|
+
}
|
|
19151
|
+
}
|
|
19152
|
+
return serialized;
|
|
19153
|
+
} finally {
|
|
19154
|
+
seen.delete(dict);
|
|
19155
|
+
}
|
|
19156
|
+
}
|
|
19157
|
+
function createAttachmentFromInlineData(data, mimeType) {
|
|
19158
|
+
if (!(data instanceof Uint8Array || typeof Buffer !== "undefined" && Buffer.isBuffer(data) || typeof data === "string")) {
|
|
19159
|
+
return null;
|
|
19160
|
+
}
|
|
19161
|
+
const extension = mimeType ? mimeType.split("/")[1] : "bin";
|
|
19162
|
+
const filename = `file.${extension}`;
|
|
19163
|
+
const buffer = typeof data === "string" ? typeof Buffer !== "undefined" ? Buffer.from(data, "base64") : new Uint8Array(
|
|
19164
|
+
atob(data).split("").map((c) => c.charCodeAt(0))
|
|
19165
|
+
) : typeof Buffer !== "undefined" ? Buffer.from(data) : new Uint8Array(data);
|
|
19166
|
+
const arrayBuffer = buffer instanceof Uint8Array ? buffer.buffer.slice(
|
|
19167
|
+
buffer.byteOffset,
|
|
19168
|
+
buffer.byteOffset + buffer.byteLength
|
|
19169
|
+
) : buffer;
|
|
19170
|
+
return new Attachment({
|
|
19171
|
+
data: arrayBuffer,
|
|
19172
|
+
filename,
|
|
19173
|
+
contentType: mimeType || "application/octet-stream"
|
|
19174
|
+
});
|
|
19175
|
+
}
|
|
18221
19176
|
function serializeGenerateContentTools(params) {
|
|
18222
19177
|
const config = params.config ? tryToDict(params.config) : null;
|
|
18223
19178
|
const tools = config?.tools;
|
|
@@ -18302,6 +19257,33 @@ function extractEmbedContentMetrics(response, startTime) {
|
|
|
18302
19257
|
}
|
|
18303
19258
|
return metrics;
|
|
18304
19259
|
}
|
|
19260
|
+
function extractInteractionMetrics(response, startTime) {
|
|
19261
|
+
const metrics = {};
|
|
19262
|
+
if (startTime !== void 0) {
|
|
19263
|
+
const end = getCurrentUnixTimestamp();
|
|
19264
|
+
metrics.start = startTime;
|
|
19265
|
+
metrics.end = end;
|
|
19266
|
+
metrics.duration = end - startTime;
|
|
19267
|
+
}
|
|
19268
|
+
if (response?.usage) {
|
|
19269
|
+
populateInteractionUsageMetrics(metrics, response.usage);
|
|
19270
|
+
}
|
|
19271
|
+
return metrics;
|
|
19272
|
+
}
|
|
19273
|
+
function extractInteractionResponseMetadata(response) {
|
|
19274
|
+
const responseDict = tryToDict(response);
|
|
19275
|
+
if (!responseDict) {
|
|
19276
|
+
return void 0;
|
|
19277
|
+
}
|
|
19278
|
+
const metadata = {};
|
|
19279
|
+
if (typeof responseDict.id === "string") {
|
|
19280
|
+
metadata.interaction_id = responseDict.id;
|
|
19281
|
+
}
|
|
19282
|
+
if (typeof responseDict.status === "string") {
|
|
19283
|
+
metadata.status = responseDict.status;
|
|
19284
|
+
}
|
|
19285
|
+
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
19286
|
+
}
|
|
18305
19287
|
function extractEmbedPromptTokenCount(response) {
|
|
18306
19288
|
if (!response) {
|
|
18307
19289
|
return void 0;
|
|
@@ -18364,6 +19346,23 @@ function populateUsageMetrics(metrics, usage) {
|
|
|
18364
19346
|
metrics.completion_reasoning_tokens = usage.thoughtsTokenCount;
|
|
18365
19347
|
}
|
|
18366
19348
|
}
|
|
19349
|
+
function populateInteractionUsageMetrics(metrics, usage) {
|
|
19350
|
+
if (typeof usage.total_input_tokens === "number") {
|
|
19351
|
+
metrics.prompt_tokens = usage.total_input_tokens;
|
|
19352
|
+
}
|
|
19353
|
+
if (typeof usage.total_output_tokens === "number") {
|
|
19354
|
+
metrics.completion_tokens = usage.total_output_tokens;
|
|
19355
|
+
}
|
|
19356
|
+
if (typeof usage.total_tokens === "number") {
|
|
19357
|
+
metrics.tokens = usage.total_tokens;
|
|
19358
|
+
}
|
|
19359
|
+
if (typeof usage.total_cached_tokens === "number") {
|
|
19360
|
+
metrics.prompt_cached_tokens = usage.total_cached_tokens;
|
|
19361
|
+
}
|
|
19362
|
+
if (typeof usage.total_thought_tokens === "number") {
|
|
19363
|
+
metrics.completion_reasoning_tokens = usage.total_thought_tokens;
|
|
19364
|
+
}
|
|
19365
|
+
}
|
|
18367
19366
|
function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
|
|
18368
19367
|
const end = getCurrentUnixTimestamp();
|
|
18369
19368
|
const metrics = {
|
|
@@ -18461,41 +19460,181 @@ function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
|
|
|
18461
19460
|
}
|
|
18462
19461
|
return { aggregated, metrics };
|
|
18463
19462
|
}
|
|
18464
|
-
function
|
|
18465
|
-
const
|
|
18466
|
-
|
|
18467
|
-
|
|
18468
|
-
|
|
18469
|
-
|
|
18470
|
-
|
|
18471
|
-
return cleaned;
|
|
18472
|
-
}
|
|
18473
|
-
function extractResponseMetadata(response) {
|
|
18474
|
-
const responseDict = tryToDict(response);
|
|
18475
|
-
if (!responseDict) {
|
|
18476
|
-
return void 0;
|
|
19463
|
+
function aggregateInteractionEvents(chunks, startTime) {
|
|
19464
|
+
const end = getCurrentUnixTimestamp();
|
|
19465
|
+
const metrics = {};
|
|
19466
|
+
if (startTime !== void 0) {
|
|
19467
|
+
metrics.start = startTime;
|
|
19468
|
+
metrics.end = end;
|
|
19469
|
+
metrics.duration = end - startTime;
|
|
18477
19470
|
}
|
|
18478
|
-
|
|
18479
|
-
|
|
18480
|
-
|
|
18481
|
-
|
|
18482
|
-
|
|
18483
|
-
|
|
18484
|
-
|
|
18485
|
-
|
|
19471
|
+
let latestInteraction;
|
|
19472
|
+
let latestUsage;
|
|
19473
|
+
let status;
|
|
19474
|
+
let outputText = "";
|
|
19475
|
+
const steps = /* @__PURE__ */ new Map();
|
|
19476
|
+
for (const chunk of chunks) {
|
|
19477
|
+
const event = tryToDict(chunk);
|
|
19478
|
+
if (!event) {
|
|
19479
|
+
continue;
|
|
19480
|
+
}
|
|
19481
|
+
const usage = extractInteractionUsageFromEvent(event);
|
|
19482
|
+
if (usage) {
|
|
19483
|
+
latestUsage = usage;
|
|
19484
|
+
}
|
|
19485
|
+
const interaction = tryToDict(event.interaction);
|
|
19486
|
+
if (interaction) {
|
|
19487
|
+
latestInteraction = serializeInteractionValue(interaction);
|
|
19488
|
+
if (typeof interaction.status === "string") {
|
|
19489
|
+
status = interaction.status;
|
|
18486
19490
|
}
|
|
18487
19491
|
}
|
|
19492
|
+
if (typeof event.status === "string") {
|
|
19493
|
+
status = event.status;
|
|
19494
|
+
}
|
|
19495
|
+
const index = typeof event.index === "number" ? event.index : void 0;
|
|
19496
|
+
if (index === void 0) {
|
|
19497
|
+
continue;
|
|
19498
|
+
}
|
|
19499
|
+
if (event.event_type === "step.start") {
|
|
19500
|
+
const compact = compactInteractionStep(event.step);
|
|
19501
|
+
compact.index = index;
|
|
19502
|
+
steps.set(index, compact);
|
|
19503
|
+
continue;
|
|
19504
|
+
}
|
|
19505
|
+
if (event.event_type === "step.delta") {
|
|
19506
|
+
const step = steps.get(index) ?? { index };
|
|
19507
|
+
const textDelta = applyInteractionDelta(step, event.delta);
|
|
19508
|
+
if (textDelta) {
|
|
19509
|
+
outputText += textDelta;
|
|
19510
|
+
}
|
|
19511
|
+
steps.set(index, step);
|
|
19512
|
+
}
|
|
18488
19513
|
}
|
|
18489
|
-
if (
|
|
18490
|
-
|
|
18491
|
-
} else if (candidateGroundingMetadata.length === 1) {
|
|
18492
|
-
[metadata.groundingMetadata] = candidateGroundingMetadata;
|
|
18493
|
-
} else if (candidateGroundingMetadata.length > 1) {
|
|
18494
|
-
metadata.groundingMetadata = candidateGroundingMetadata;
|
|
19514
|
+
if (latestUsage) {
|
|
19515
|
+
populateInteractionUsageMetrics(metrics, latestUsage);
|
|
18495
19516
|
}
|
|
18496
|
-
|
|
18497
|
-
|
|
18498
|
-
|
|
19517
|
+
const output = latestInteraction ? { ...latestInteraction } : {};
|
|
19518
|
+
if (status) {
|
|
19519
|
+
output.status = status;
|
|
19520
|
+
}
|
|
19521
|
+
if (outputText) {
|
|
19522
|
+
output.output_text = outputText;
|
|
19523
|
+
}
|
|
19524
|
+
if (latestUsage) {
|
|
19525
|
+
output.usage = serializeInteractionValue(latestUsage);
|
|
19526
|
+
}
|
|
19527
|
+
const compactSteps = Array.from(steps.values()).sort(
|
|
19528
|
+
(left, right) => Number(left.index ?? 0) - Number(right.index ?? 0)
|
|
19529
|
+
);
|
|
19530
|
+
if (compactSteps.length > 0) {
|
|
19531
|
+
output.steps = compactSteps;
|
|
19532
|
+
}
|
|
19533
|
+
const metadata = {};
|
|
19534
|
+
if (typeof output.id === "string") {
|
|
19535
|
+
metadata.interaction_id = output.id;
|
|
19536
|
+
}
|
|
19537
|
+
if (typeof output.status === "string") {
|
|
19538
|
+
metadata.status = output.status;
|
|
19539
|
+
}
|
|
19540
|
+
return {
|
|
19541
|
+
output,
|
|
19542
|
+
metrics: cleanMetrics3(metrics),
|
|
19543
|
+
...Object.keys(metadata).length > 0 ? { metadata } : {}
|
|
19544
|
+
};
|
|
19545
|
+
}
|
|
19546
|
+
function extractInteractionUsageFromEvent(event) {
|
|
19547
|
+
const metadata = tryToDict(event.metadata);
|
|
19548
|
+
const metadataUsage = tryToDict(metadata?.usage);
|
|
19549
|
+
if (metadataUsage) {
|
|
19550
|
+
return metadataUsage;
|
|
19551
|
+
}
|
|
19552
|
+
const metadataTotalUsage = tryToDict(metadata?.total_usage);
|
|
19553
|
+
if (metadataTotalUsage) {
|
|
19554
|
+
return metadataTotalUsage;
|
|
19555
|
+
}
|
|
19556
|
+
const interaction = tryToDict(event.interaction);
|
|
19557
|
+
const interactionUsage = tryToDict(interaction?.usage);
|
|
19558
|
+
return interactionUsage ? interactionUsage : void 0;
|
|
19559
|
+
}
|
|
19560
|
+
function compactInteractionStep(step) {
|
|
19561
|
+
const stepDict = tryToDict(step);
|
|
19562
|
+
if (!stepDict) {
|
|
19563
|
+
return {};
|
|
19564
|
+
}
|
|
19565
|
+
const compact = {};
|
|
19566
|
+
for (const key of [
|
|
19567
|
+
"type",
|
|
19568
|
+
"content",
|
|
19569
|
+
"name",
|
|
19570
|
+
"server_name",
|
|
19571
|
+
"arguments",
|
|
19572
|
+
"result",
|
|
19573
|
+
"is_error"
|
|
19574
|
+
]) {
|
|
19575
|
+
if (stepDict[key] !== void 0) {
|
|
19576
|
+
compact[key] = serializeInteractionValue(stepDict[key]);
|
|
19577
|
+
}
|
|
19578
|
+
}
|
|
19579
|
+
return Object.keys(compact).length > 0 ? compact : serializeInteractionValue(stepDict);
|
|
19580
|
+
}
|
|
19581
|
+
function applyInteractionDelta(step, delta) {
|
|
19582
|
+
const deltaDict = tryToDict(delta);
|
|
19583
|
+
if (!deltaDict) {
|
|
19584
|
+
return void 0;
|
|
19585
|
+
}
|
|
19586
|
+
const deltaType = deltaDict.type;
|
|
19587
|
+
if (typeof deltaType === "string" && typeof step.type !== "string") {
|
|
19588
|
+
step.type = deltaType === "text" ? "model_output" : deltaType;
|
|
19589
|
+
}
|
|
19590
|
+
if (deltaType === "text" && typeof deltaDict.text === "string") {
|
|
19591
|
+
step.text = `${typeof step.text === "string" ? step.text : ""}${deltaDict.text}`;
|
|
19592
|
+
return deltaDict.text;
|
|
19593
|
+
}
|
|
19594
|
+
if (deltaType === "arguments_delta" && typeof deltaDict.arguments === "string") {
|
|
19595
|
+
step.arguments = `${typeof step.arguments === "string" ? step.arguments : ""}${deltaDict.arguments}`;
|
|
19596
|
+
return void 0;
|
|
19597
|
+
}
|
|
19598
|
+
const deltas = Array.isArray(step.deltas) ? step.deltas : [];
|
|
19599
|
+
deltas.push(serializeInteractionValue(deltaDict));
|
|
19600
|
+
step.deltas = deltas;
|
|
19601
|
+
return void 0;
|
|
19602
|
+
}
|
|
19603
|
+
function cleanMetrics3(metrics) {
|
|
19604
|
+
const cleaned = {};
|
|
19605
|
+
for (const [key, value] of Object.entries(metrics)) {
|
|
19606
|
+
if (value !== null && value !== void 0) {
|
|
19607
|
+
cleaned[key] = value;
|
|
19608
|
+
}
|
|
19609
|
+
}
|
|
19610
|
+
return cleaned;
|
|
19611
|
+
}
|
|
19612
|
+
function extractResponseMetadata(response) {
|
|
19613
|
+
const responseDict = tryToDict(response);
|
|
19614
|
+
if (!responseDict) {
|
|
19615
|
+
return void 0;
|
|
19616
|
+
}
|
|
19617
|
+
const metadata = {};
|
|
19618
|
+
const responseGroundingMetadata = responseDict.groundingMetadata;
|
|
19619
|
+
const candidateGroundingMetadata = [];
|
|
19620
|
+
if (Array.isArray(responseDict.candidates)) {
|
|
19621
|
+
for (const candidate of responseDict.candidates) {
|
|
19622
|
+
const candidateDict = tryToDict(candidate);
|
|
19623
|
+
if (candidateDict?.groundingMetadata !== void 0) {
|
|
19624
|
+
candidateGroundingMetadata.push(candidateDict.groundingMetadata);
|
|
19625
|
+
}
|
|
19626
|
+
}
|
|
19627
|
+
}
|
|
19628
|
+
if (responseGroundingMetadata !== void 0) {
|
|
19629
|
+
metadata.groundingMetadata = responseGroundingMetadata;
|
|
19630
|
+
} else if (candidateGroundingMetadata.length === 1) {
|
|
19631
|
+
[metadata.groundingMetadata] = candidateGroundingMetadata;
|
|
19632
|
+
} else if (candidateGroundingMetadata.length > 1) {
|
|
19633
|
+
metadata.groundingMetadata = candidateGroundingMetadata;
|
|
19634
|
+
}
|
|
19635
|
+
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
19636
|
+
}
|
|
19637
|
+
function tryToDict(obj) {
|
|
18499
19638
|
if (obj === null || obj === void 0) {
|
|
18500
19639
|
return null;
|
|
18501
19640
|
}
|
|
@@ -24287,7 +25426,8 @@ var FlueObserveBridge = class {
|
|
|
24287
25426
|
metadata
|
|
24288
25427
|
}
|
|
24289
25428
|
});
|
|
24290
|
-
|
|
25429
|
+
const activeContext = enterCurrentFlueSpan(span);
|
|
25430
|
+
this.runsById.set(event.runId, { activeContext, metadata, span });
|
|
24291
25431
|
}
|
|
24292
25432
|
handleRunEnd(event) {
|
|
24293
25433
|
const state = this.runsById.get(event.runId);
|
|
@@ -24305,6 +25445,7 @@ var FlueObserveBridge = class {
|
|
|
24305
25445
|
});
|
|
24306
25446
|
safeEnd(state.span, eventTime(event.timestamp));
|
|
24307
25447
|
this.runsById.delete(event.runId);
|
|
25448
|
+
restoreCurrentFlueSpan(state.activeContext);
|
|
24308
25449
|
}
|
|
24309
25450
|
void flush().catch((error) => {
|
|
24310
25451
|
logInstrumentationError3("Flue flush", error);
|
|
@@ -24431,7 +25572,8 @@ var FlueObserveBridge = class {
|
|
|
24431
25572
|
metadata
|
|
24432
25573
|
}
|
|
24433
25574
|
});
|
|
24434
|
-
|
|
25575
|
+
const activeContext = enterCurrentFlueSpan(span);
|
|
25576
|
+
this.toolsByKey.set(toolKey(event), { activeContext, metadata, span });
|
|
24435
25577
|
}
|
|
24436
25578
|
handleToolCall(event) {
|
|
24437
25579
|
if (!event.toolCallId) {
|
|
@@ -24454,6 +25596,7 @@ var FlueObserveBridge = class {
|
|
|
24454
25596
|
});
|
|
24455
25597
|
safeEnd(state.span, eventTime(event.timestamp));
|
|
24456
25598
|
this.toolsByKey.delete(key);
|
|
25599
|
+
restoreCurrentFlueSpan(state.activeContext);
|
|
24457
25600
|
}
|
|
24458
25601
|
handleTaskStart(event) {
|
|
24459
25602
|
if (!event.taskId) {
|
|
@@ -24858,6 +26001,34 @@ function stateMatchesRun(state, runId) {
|
|
|
24858
26001
|
function startFlueSpan(parent, args) {
|
|
24859
26002
|
return parent ? withCurrent(parent, () => startSpan(args)) : startSpan(args);
|
|
24860
26003
|
}
|
|
26004
|
+
function enterCurrentFlueSpan(span) {
|
|
26005
|
+
const contextManager = _internalGetGlobalState()?.contextManager;
|
|
26006
|
+
const store = contextManager ? Reflect.get(contextManager, BRAINTRUST_CURRENT_SPAN_STORE) : void 0;
|
|
26007
|
+
if (!contextManager || !isCurrentSpanStore(store)) {
|
|
26008
|
+
return void 0;
|
|
26009
|
+
}
|
|
26010
|
+
const previous = store.getStore();
|
|
26011
|
+
try {
|
|
26012
|
+
store.enterWith(contextManager.wrapSpanForStore(span));
|
|
26013
|
+
return { previous, store };
|
|
26014
|
+
} catch (error) {
|
|
26015
|
+
logInstrumentationError3("Flue context propagation", error);
|
|
26016
|
+
return void 0;
|
|
26017
|
+
}
|
|
26018
|
+
}
|
|
26019
|
+
function isCurrentSpanStore(value) {
|
|
26020
|
+
return isObjectLike(value) && typeof Reflect.get(value, "enterWith") === "function" && typeof Reflect.get(value, "getStore") === "function";
|
|
26021
|
+
}
|
|
26022
|
+
function restoreCurrentFlueSpan(activeContext) {
|
|
26023
|
+
if (!activeContext) {
|
|
26024
|
+
return;
|
|
26025
|
+
}
|
|
26026
|
+
try {
|
|
26027
|
+
activeContext.store.enterWith(activeContext.previous);
|
|
26028
|
+
} catch (error) {
|
|
26029
|
+
logInstrumentationError3("Flue context restoration", error);
|
|
26030
|
+
}
|
|
26031
|
+
}
|
|
24861
26032
|
function safeLog3(span, event) {
|
|
24862
26033
|
try {
|
|
24863
26034
|
span.log(event);
|
|
@@ -25196,143 +26367,1027 @@ function getModelNameFromResponse(response) {
|
|
|
25196
26367
|
return modelName3;
|
|
25197
26368
|
}
|
|
25198
26369
|
}
|
|
25199
|
-
const llmOutput = response.llmOutput || {};
|
|
25200
|
-
const modelName2 = llmOutput.model_name ?? llmOutput.model;
|
|
25201
|
-
return typeof modelName2 === "string" ? modelName2 : void 0;
|
|
26370
|
+
const llmOutput = response.llmOutput || {};
|
|
26371
|
+
const modelName2 = llmOutput.model_name ?? llmOutput.model;
|
|
26372
|
+
return typeof modelName2 === "string" ? modelName2 : void 0;
|
|
26373
|
+
}
|
|
26374
|
+
function getMetricsFromResponse(response) {
|
|
26375
|
+
for (const generation of walkGenerations(response)) {
|
|
26376
|
+
const message = generation.message;
|
|
26377
|
+
if (!isRecord(message)) {
|
|
26378
|
+
continue;
|
|
26379
|
+
}
|
|
26380
|
+
const usageMetadata = message.usage_metadata;
|
|
26381
|
+
if (!isRecord(usageMetadata)) {
|
|
26382
|
+
continue;
|
|
26383
|
+
}
|
|
26384
|
+
const inputTokenDetails = usageMetadata.input_token_details;
|
|
26385
|
+
return cleanObject({
|
|
26386
|
+
total_tokens: usageMetadata.total_tokens,
|
|
26387
|
+
prompt_tokens: usageMetadata.input_tokens,
|
|
26388
|
+
completion_tokens: usageMetadata.output_tokens,
|
|
26389
|
+
prompt_cache_creation_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_creation : void 0,
|
|
26390
|
+
prompt_cached_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_read : void 0
|
|
26391
|
+
});
|
|
26392
|
+
}
|
|
26393
|
+
const llmOutput = response.llmOutput || {};
|
|
26394
|
+
const tokenUsage = isRecord(llmOutput.tokenUsage) ? llmOutput.tokenUsage : isRecord(llmOutput.estimatedTokens) ? llmOutput.estimatedTokens : {};
|
|
26395
|
+
return cleanObject({
|
|
26396
|
+
total_tokens: tokenUsage.totalTokens,
|
|
26397
|
+
prompt_tokens: tokenUsage.promptTokens,
|
|
26398
|
+
completion_tokens: tokenUsage.completionTokens
|
|
26399
|
+
});
|
|
26400
|
+
}
|
|
26401
|
+
function safeJsonParse(input) {
|
|
26402
|
+
try {
|
|
26403
|
+
return JSON.parse(input);
|
|
26404
|
+
} catch {
|
|
26405
|
+
return input;
|
|
26406
|
+
}
|
|
26407
|
+
}
|
|
26408
|
+
function isRecord(value) {
|
|
26409
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
26410
|
+
}
|
|
26411
|
+
|
|
26412
|
+
// src/instrumentation/plugins/langchain-channels.ts
|
|
26413
|
+
var langChainChannels = defineChannels("@langchain/core", {
|
|
26414
|
+
configure: channel({
|
|
26415
|
+
channelName: "CallbackManager.configure",
|
|
26416
|
+
kind: "sync-stream"
|
|
26417
|
+
}),
|
|
26418
|
+
configureSync: channel({
|
|
26419
|
+
channelName: "CallbackManager._configureSync",
|
|
26420
|
+
kind: "sync-stream"
|
|
26421
|
+
})
|
|
26422
|
+
});
|
|
26423
|
+
|
|
26424
|
+
// src/instrumentation/plugins/langchain-plugin.ts
|
|
26425
|
+
var LangChainPlugin = class extends BasePlugin {
|
|
26426
|
+
injectedManagers = /* @__PURE__ */ new WeakSet();
|
|
26427
|
+
onEnable() {
|
|
26428
|
+
this.subscribeToConfigure(langChainChannels.configure);
|
|
26429
|
+
this.subscribeToConfigure(langChainChannels.configureSync);
|
|
26430
|
+
}
|
|
26431
|
+
onDisable() {
|
|
26432
|
+
for (const unsubscribe of this.unsubscribers) {
|
|
26433
|
+
unsubscribe();
|
|
26434
|
+
}
|
|
26435
|
+
this.unsubscribers = [];
|
|
26436
|
+
this.injectedManagers = /* @__PURE__ */ new WeakSet();
|
|
26437
|
+
}
|
|
26438
|
+
subscribeToConfigure(channel2) {
|
|
26439
|
+
const tracingChannel2 = channel2.tracingChannel();
|
|
26440
|
+
const handlers = {
|
|
26441
|
+
start: (event) => {
|
|
26442
|
+
injectHandlerIntoArguments(event.arguments);
|
|
26443
|
+
},
|
|
26444
|
+
end: (event) => {
|
|
26445
|
+
this.injectHandler(event.result);
|
|
26446
|
+
}
|
|
26447
|
+
};
|
|
26448
|
+
tracingChannel2.subscribe(handlers);
|
|
26449
|
+
this.unsubscribers.push(() => {
|
|
26450
|
+
tracingChannel2.unsubscribe(handlers);
|
|
26451
|
+
});
|
|
26452
|
+
}
|
|
26453
|
+
injectHandler(result) {
|
|
26454
|
+
if (!isCallbackManager(result)) {
|
|
26455
|
+
return;
|
|
26456
|
+
}
|
|
26457
|
+
if (this.injectedManagers.has(result) || hasBraintrustHandler(result)) {
|
|
26458
|
+
return;
|
|
26459
|
+
}
|
|
26460
|
+
try {
|
|
26461
|
+
result.addHandler(new BraintrustLangChainCallbackHandler(), true);
|
|
26462
|
+
this.injectedManagers.add(result);
|
|
26463
|
+
} catch {
|
|
26464
|
+
}
|
|
26465
|
+
}
|
|
26466
|
+
};
|
|
26467
|
+
function isCallbackManager(value) {
|
|
26468
|
+
if (typeof value !== "object" || value === null) {
|
|
26469
|
+
return false;
|
|
26470
|
+
}
|
|
26471
|
+
const maybeManager = value;
|
|
26472
|
+
return typeof maybeManager.addHandler === "function";
|
|
26473
|
+
}
|
|
26474
|
+
function hasBraintrustHandler(manager) {
|
|
26475
|
+
return manager.handlers?.some((handler) => {
|
|
26476
|
+
if (typeof handler !== "object" || handler === null) {
|
|
26477
|
+
return false;
|
|
26478
|
+
}
|
|
26479
|
+
const name = Reflect.get(handler, "name");
|
|
26480
|
+
return name === BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
|
|
26481
|
+
}) ?? false;
|
|
26482
|
+
}
|
|
26483
|
+
function injectHandlerIntoArguments(args) {
|
|
26484
|
+
if (!isWritableArgumentsObject(args)) {
|
|
26485
|
+
return;
|
|
26486
|
+
}
|
|
26487
|
+
const inheritedHandlers = Reflect.get(args, "0");
|
|
26488
|
+
const handler = new BraintrustLangChainCallbackHandler();
|
|
26489
|
+
if (inheritedHandlers === void 0 || inheritedHandlers === null) {
|
|
26490
|
+
Reflect.set(args, "0", [handler]);
|
|
26491
|
+
return;
|
|
26492
|
+
}
|
|
26493
|
+
if (Array.isArray(inheritedHandlers)) {
|
|
26494
|
+
if (!inheritedHandlers.some(isBraintrustHandler)) {
|
|
26495
|
+
inheritedHandlers.push(handler);
|
|
26496
|
+
}
|
|
26497
|
+
}
|
|
26498
|
+
}
|
|
26499
|
+
function isWritableArgumentsObject(args) {
|
|
26500
|
+
return typeof args === "object" && args !== null;
|
|
26501
|
+
}
|
|
26502
|
+
function isBraintrustHandler(handler) {
|
|
26503
|
+
if (typeof handler !== "object" || handler === null) {
|
|
26504
|
+
return false;
|
|
26505
|
+
}
|
|
26506
|
+
return Reflect.get(handler, "name") === BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
|
|
26507
|
+
}
|
|
26508
|
+
|
|
26509
|
+
// src/instrumentation/plugins/pi-coding-agent-channels.ts
|
|
26510
|
+
var piCodingAgentChannels = defineChannels(
|
|
26511
|
+
"@earendil-works/pi-coding-agent",
|
|
26512
|
+
{
|
|
26513
|
+
prompt: channel({
|
|
26514
|
+
channelName: "AgentSession.prompt",
|
|
26515
|
+
kind: "async"
|
|
26516
|
+
})
|
|
26517
|
+
}
|
|
26518
|
+
);
|
|
26519
|
+
|
|
26520
|
+
// src/instrumentation/plugins/pi-coding-agent-plugin.ts
|
|
26521
|
+
var piStreamPatchStates = /* @__PURE__ */ new WeakMap();
|
|
26522
|
+
var piPromptContextStore;
|
|
26523
|
+
var PiCodingAgentPlugin = class extends BasePlugin {
|
|
26524
|
+
activePromptStates = /* @__PURE__ */ new Set();
|
|
26525
|
+
onEnable() {
|
|
26526
|
+
this.subscribeToPrompt();
|
|
26527
|
+
}
|
|
26528
|
+
onDisable() {
|
|
26529
|
+
for (const unsubscribe of this.unsubscribers) {
|
|
26530
|
+
unsubscribe();
|
|
26531
|
+
}
|
|
26532
|
+
this.unsubscribers = [];
|
|
26533
|
+
for (const state of [...this.activePromptStates]) {
|
|
26534
|
+
void finalizePiPromptRun(state).catch((error) => {
|
|
26535
|
+
logInstrumentationError4("Pi Coding Agent disable cleanup", error);
|
|
26536
|
+
});
|
|
26537
|
+
}
|
|
26538
|
+
}
|
|
26539
|
+
subscribeToPrompt() {
|
|
26540
|
+
const channel2 = piCodingAgentChannels.prompt.tracingChannel();
|
|
26541
|
+
const states = /* @__PURE__ */ new WeakMap();
|
|
26542
|
+
const unbindAutoInstrumentationSuppression = bindAutoInstrumentationSuppressionToStart(channel2);
|
|
26543
|
+
const handlers = {
|
|
26544
|
+
start: (event) => {
|
|
26545
|
+
const state = startPiPromptRun(event, (state2) => {
|
|
26546
|
+
this.activePromptStates.delete(state2);
|
|
26547
|
+
});
|
|
26548
|
+
if (state) {
|
|
26549
|
+
this.activePromptStates.add(state);
|
|
26550
|
+
states.set(event, state);
|
|
26551
|
+
}
|
|
26552
|
+
},
|
|
26553
|
+
asyncEnd: async (event) => {
|
|
26554
|
+
const state = states.get(event);
|
|
26555
|
+
if (!state) {
|
|
26556
|
+
return;
|
|
26557
|
+
}
|
|
26558
|
+
states.delete(event);
|
|
26559
|
+
state.promptCallEnded = true;
|
|
26560
|
+
if (!state.finalized && state.deferCompletionUntilTurnEnd && !state.turnEnded) {
|
|
26561
|
+
if (!state.sawStreamFn) {
|
|
26562
|
+
state.queued = true;
|
|
26563
|
+
if (!state.streamPatchState.queuedPromptStates.includes(state)) {
|
|
26564
|
+
state.streamPatchState.queuedPromptStates.push(state);
|
|
26565
|
+
}
|
|
26566
|
+
}
|
|
26567
|
+
return;
|
|
26568
|
+
}
|
|
26569
|
+
await finalizePiPromptRun(state);
|
|
26570
|
+
},
|
|
26571
|
+
error: async (event) => {
|
|
26572
|
+
const state = states.get(event);
|
|
26573
|
+
if (!state) {
|
|
26574
|
+
return;
|
|
26575
|
+
}
|
|
26576
|
+
states.delete(event);
|
|
26577
|
+
await finalizePiPromptRun(state, event.error);
|
|
26578
|
+
}
|
|
26579
|
+
};
|
|
26580
|
+
channel2.subscribe(handlers);
|
|
26581
|
+
this.unsubscribers.push(() => {
|
|
26582
|
+
unbindAutoInstrumentationSuppression?.();
|
|
26583
|
+
channel2.unsubscribe(handlers);
|
|
26584
|
+
});
|
|
26585
|
+
}
|
|
26586
|
+
};
|
|
26587
|
+
function startPiPromptRun(event, onFinalize) {
|
|
26588
|
+
const session = extractSession(event);
|
|
26589
|
+
const agent = session?.agent;
|
|
26590
|
+
if (!session || !isPiAgent(agent)) {
|
|
26591
|
+
return void 0;
|
|
26592
|
+
}
|
|
26593
|
+
const metadata = {
|
|
26594
|
+
...extractSessionMetadata(session),
|
|
26595
|
+
...extractPromptOptionsMetadata(event.arguments[1]),
|
|
26596
|
+
"pi_coding_agent.operation": "AgentSession.prompt",
|
|
26597
|
+
provider: session.model?.provider ?? agent.state?.model?.provider ?? "pi",
|
|
26598
|
+
...session.model?.id || agent.state?.model?.id ? { model: session.model?.id ?? agent.state?.model?.id } : {},
|
|
26599
|
+
...event.moduleVersion ? { "pi_coding_agent.version": event.moduleVersion } : {}
|
|
26600
|
+
};
|
|
26601
|
+
const span = startSpan({
|
|
26602
|
+
event: {
|
|
26603
|
+
input: extractPromptInput(event.arguments[0], event.arguments[1]),
|
|
26604
|
+
metadata
|
|
26605
|
+
},
|
|
26606
|
+
name: "AgentSession.prompt",
|
|
26607
|
+
spanAttributes: { type: "task" /* TASK */ }
|
|
26608
|
+
});
|
|
26609
|
+
const streamPatchState = installPiStreamPatch(agent);
|
|
26610
|
+
const options = event.arguments[1];
|
|
26611
|
+
const promptText = event.arguments[0];
|
|
26612
|
+
const state = {
|
|
26613
|
+
activeLlmSpans: /* @__PURE__ */ new Set(),
|
|
26614
|
+
activeToolSpans: /* @__PURE__ */ new Map(),
|
|
26615
|
+
agent,
|
|
26616
|
+
collectedLlmUsageMetrics: false,
|
|
26617
|
+
deferCompletionUntilTurnEnd: options?.streamingBehavior === "followUp" || options?.streamingBehavior === "steer",
|
|
26618
|
+
finalized: false,
|
|
26619
|
+
metadata,
|
|
26620
|
+
metrics: {},
|
|
26621
|
+
onFinalize,
|
|
26622
|
+
promptCallEnded: false,
|
|
26623
|
+
...typeof promptText === "string" ? { promptText } : {},
|
|
26624
|
+
queued: false,
|
|
26625
|
+
span,
|
|
26626
|
+
sawStreamFn: false,
|
|
26627
|
+
startTime: getCurrentUnixTimestamp(),
|
|
26628
|
+
streamPatchState,
|
|
26629
|
+
turnEnded: false
|
|
26630
|
+
};
|
|
26631
|
+
state.restorePromptContext = enterPiPromptContext(state);
|
|
26632
|
+
streamPatchState.activePromptStates.add(state);
|
|
26633
|
+
try {
|
|
26634
|
+
state.unsubscribeAgent = agent.subscribe(async (agentEvent) => {
|
|
26635
|
+
try {
|
|
26636
|
+
await runWithAutoInstrumentationSuppressed(
|
|
26637
|
+
() => handlePiAgentEvent(state, agentEvent)
|
|
26638
|
+
);
|
|
26639
|
+
} catch (error) {
|
|
26640
|
+
logInstrumentationError4("Pi Coding Agent event", error);
|
|
26641
|
+
}
|
|
26642
|
+
});
|
|
26643
|
+
} catch (error) {
|
|
26644
|
+
logInstrumentationError4("Pi Coding Agent event subscription", error);
|
|
26645
|
+
}
|
|
26646
|
+
return state;
|
|
26647
|
+
}
|
|
26648
|
+
function extractSession(event) {
|
|
26649
|
+
const candidate = event.session ?? event.self;
|
|
26650
|
+
return isObject(candidate) && typeof candidate.prompt === "function" ? candidate : void 0;
|
|
26651
|
+
}
|
|
26652
|
+
function isPiAgent(value) {
|
|
26653
|
+
return isObject(value) && typeof value.streamFn === "function" && typeof value.subscribe === "function";
|
|
26654
|
+
}
|
|
26655
|
+
function promptContextStore() {
|
|
26656
|
+
piPromptContextStore ??= isomorph_default.newAsyncLocalStorage();
|
|
26657
|
+
return piPromptContextStore;
|
|
26658
|
+
}
|
|
26659
|
+
function currentPromptContextFrames() {
|
|
26660
|
+
return promptContextStore().getStore()?.frames ?? [];
|
|
26661
|
+
}
|
|
26662
|
+
function currentPiPromptState() {
|
|
26663
|
+
const frames = currentPromptContextFrames();
|
|
26664
|
+
return frames[frames.length - 1]?.state;
|
|
26665
|
+
}
|
|
26666
|
+
function enterPiPromptContext(state) {
|
|
26667
|
+
const frame = {
|
|
26668
|
+
id: /* @__PURE__ */ Symbol("braintrust.pi-coding-agent.prompt"),
|
|
26669
|
+
state
|
|
26670
|
+
};
|
|
26671
|
+
promptContextStore().enterWith({
|
|
26672
|
+
frames: [...currentPromptContextFrames(), frame]
|
|
26673
|
+
});
|
|
26674
|
+
return () => {
|
|
26675
|
+
const frames = currentPromptContextFrames().filter(
|
|
26676
|
+
(candidate) => candidate.id !== frame.id
|
|
26677
|
+
);
|
|
26678
|
+
promptContextStore().enterWith(frames.length > 0 ? { frames } : void 0);
|
|
26679
|
+
};
|
|
26680
|
+
}
|
|
26681
|
+
function installPiStreamPatch(agent) {
|
|
26682
|
+
const existing = piStreamPatchStates.get(agent);
|
|
26683
|
+
if (existing) {
|
|
26684
|
+
if (agent.streamFn !== existing.wrappedStreamFn) {
|
|
26685
|
+
debugLogger.debug(
|
|
26686
|
+
"Pi Coding Agent streamFn changed while Braintrust instrumentation was active; preserving existing patch state."
|
|
26687
|
+
);
|
|
26688
|
+
}
|
|
26689
|
+
return existing;
|
|
26690
|
+
}
|
|
26691
|
+
const patchState = {
|
|
26692
|
+
activePromptStates: /* @__PURE__ */ new Set(),
|
|
26693
|
+
agent,
|
|
26694
|
+
originalStreamFn: agent.streamFn,
|
|
26695
|
+
queuedPromptStates: [],
|
|
26696
|
+
wrappedStreamFn: agent.streamFn
|
|
26697
|
+
};
|
|
26698
|
+
patchState.wrappedStreamFn = makeSharedInstrumentedStreamFn(patchState);
|
|
26699
|
+
agent.streamFn = patchState.wrappedStreamFn;
|
|
26700
|
+
piStreamPatchStates.set(agent, patchState);
|
|
26701
|
+
return patchState;
|
|
26702
|
+
}
|
|
26703
|
+
function resolveStreamPromptState(patchState, context) {
|
|
26704
|
+
let lastUserText;
|
|
26705
|
+
if (Array.isArray(context.messages)) {
|
|
26706
|
+
for (let i = context.messages.length - 1; i >= 0; i--) {
|
|
26707
|
+
const message = context.messages[i];
|
|
26708
|
+
if (isPiUserMessage(message)) {
|
|
26709
|
+
if (typeof message.content === "string") {
|
|
26710
|
+
lastUserText = message.content;
|
|
26711
|
+
} else {
|
|
26712
|
+
lastUserText = message.content.flatMap((part) => part.type === "text" ? [part.text] : []).join("");
|
|
26713
|
+
}
|
|
26714
|
+
break;
|
|
26715
|
+
}
|
|
26716
|
+
}
|
|
26717
|
+
}
|
|
26718
|
+
if (lastUserText !== void 0) {
|
|
26719
|
+
const queuedMatch = patchState.queuedPromptStates.find(
|
|
26720
|
+
(state) => state.promptText === lastUserText
|
|
26721
|
+
);
|
|
26722
|
+
if (queuedMatch) {
|
|
26723
|
+
return queuedMatch;
|
|
26724
|
+
}
|
|
26725
|
+
const matches = [...patchState.activePromptStates].filter(
|
|
26726
|
+
(state) => state.promptText === lastUserText
|
|
26727
|
+
);
|
|
26728
|
+
if (matches.length === 1) {
|
|
26729
|
+
return matches[0];
|
|
26730
|
+
}
|
|
26731
|
+
}
|
|
26732
|
+
const contextState = currentPiPromptState();
|
|
26733
|
+
if (contextState && patchState.activePromptStates.has(contextState) && (!contextState.queued || lastUserText !== void 0 && contextState.promptText === lastUserText)) {
|
|
26734
|
+
return contextState;
|
|
26735
|
+
}
|
|
26736
|
+
if (patchState.activePromptStates.size === 1) {
|
|
26737
|
+
return [...patchState.activePromptStates][0];
|
|
26738
|
+
}
|
|
26739
|
+
return void 0;
|
|
26740
|
+
}
|
|
26741
|
+
function makeSharedInstrumentedStreamFn(patchState) {
|
|
26742
|
+
return async function instrumentedPiStreamFn(model, context, options) {
|
|
26743
|
+
const state = resolveStreamPromptState(patchState, context);
|
|
26744
|
+
if (!state) {
|
|
26745
|
+
const invokeOriginal = () => Reflect.apply(patchState.originalStreamFn, this, [
|
|
26746
|
+
model,
|
|
26747
|
+
context,
|
|
26748
|
+
options
|
|
26749
|
+
]);
|
|
26750
|
+
return patchState.activePromptStates.size > 0 ? runWithAutoInstrumentationSuppressed(invokeOriginal) : invokeOriginal();
|
|
26751
|
+
}
|
|
26752
|
+
state.sawStreamFn = true;
|
|
26753
|
+
removeQueuedPromptState(state);
|
|
26754
|
+
state.streamPatchState.eventPromptState = state;
|
|
26755
|
+
const llmState = await startPiLlmSpan(state, model, context, options);
|
|
26756
|
+
try {
|
|
26757
|
+
const stream = await runWithAutoInstrumentationSuppressed(
|
|
26758
|
+
() => Reflect.apply(patchState.originalStreamFn, this, [
|
|
26759
|
+
model,
|
|
26760
|
+
context,
|
|
26761
|
+
options
|
|
26762
|
+
])
|
|
26763
|
+
);
|
|
26764
|
+
return patchAssistantMessageStream(stream, state, llmState);
|
|
26765
|
+
} catch (error) {
|
|
26766
|
+
finishPiLlmSpan(state, llmState, void 0, error);
|
|
26767
|
+
throw error;
|
|
26768
|
+
}
|
|
26769
|
+
};
|
|
26770
|
+
}
|
|
26771
|
+
async function startPiLlmSpan(state, model, context, options) {
|
|
26772
|
+
const metadata = {
|
|
26773
|
+
...extractModelMetadata2(model),
|
|
26774
|
+
...extractStreamOptionsMetadata(options),
|
|
26775
|
+
...extractToolMetadata(context.tools),
|
|
26776
|
+
"pi_coding_agent.operation": "agent.streamFn"
|
|
26777
|
+
};
|
|
26778
|
+
const span = startSpan({
|
|
26779
|
+
event: {
|
|
26780
|
+
input: processInputAttachments(normalizePiContextInput(context)),
|
|
26781
|
+
metadata
|
|
26782
|
+
},
|
|
26783
|
+
name: getLlmSpanName(model),
|
|
26784
|
+
parent: await state.span.export(),
|
|
26785
|
+
spanAttributes: { type: "llm" /* LLM */ }
|
|
26786
|
+
});
|
|
26787
|
+
const llmState = {
|
|
26788
|
+
finalized: false,
|
|
26789
|
+
metadata,
|
|
26790
|
+
metrics: {},
|
|
26791
|
+
span,
|
|
26792
|
+
startTime: getCurrentUnixTimestamp()
|
|
26793
|
+
};
|
|
26794
|
+
state.activeLlmSpans.add(llmState);
|
|
26795
|
+
return llmState;
|
|
26796
|
+
}
|
|
26797
|
+
function patchAssistantMessageStream(stream, promptState, llmState) {
|
|
26798
|
+
if (!isObject(stream)) {
|
|
26799
|
+
return stream;
|
|
26800
|
+
}
|
|
26801
|
+
const streamRecord = stream;
|
|
26802
|
+
const originalResult = stream.result;
|
|
26803
|
+
if (typeof originalResult === "function") {
|
|
26804
|
+
streamRecord.result = function patchedPiResult() {
|
|
26805
|
+
return Promise.resolve(Reflect.apply(originalResult, this, [])).then(
|
|
26806
|
+
(message) => {
|
|
26807
|
+
finishPiLlmSpan(promptState, llmState, message);
|
|
26808
|
+
return message;
|
|
26809
|
+
},
|
|
26810
|
+
(error) => {
|
|
26811
|
+
finishPiLlmSpan(promptState, llmState, void 0, error);
|
|
26812
|
+
throw error;
|
|
26813
|
+
}
|
|
26814
|
+
);
|
|
26815
|
+
};
|
|
26816
|
+
}
|
|
26817
|
+
const originalIterator = stream[Symbol.asyncIterator];
|
|
26818
|
+
if (typeof originalIterator === "function") {
|
|
26819
|
+
streamRecord[Symbol.asyncIterator] = function patchedPiIterator() {
|
|
26820
|
+
const iterator = Reflect.apply(
|
|
26821
|
+
originalIterator,
|
|
26822
|
+
this,
|
|
26823
|
+
[]
|
|
26824
|
+
);
|
|
26825
|
+
return {
|
|
26826
|
+
async next() {
|
|
26827
|
+
try {
|
|
26828
|
+
const result = await iterator.next();
|
|
26829
|
+
if (result.done) {
|
|
26830
|
+
finishPiLlmSpan(promptState, llmState);
|
|
26831
|
+
return result;
|
|
26832
|
+
}
|
|
26833
|
+
recordPiAssistantMessageEvent(promptState, llmState, result.value);
|
|
26834
|
+
return result;
|
|
26835
|
+
} catch (error) {
|
|
26836
|
+
finishPiLlmSpan(promptState, llmState, void 0, error);
|
|
26837
|
+
if (typeof iterator.return === "function") {
|
|
26838
|
+
try {
|
|
26839
|
+
await iterator.return();
|
|
26840
|
+
} catch (cleanupError) {
|
|
26841
|
+
logInstrumentationError4(
|
|
26842
|
+
"Pi Coding Agent stream cleanup",
|
|
26843
|
+
cleanupError
|
|
26844
|
+
);
|
|
26845
|
+
}
|
|
26846
|
+
}
|
|
26847
|
+
throw error;
|
|
26848
|
+
}
|
|
26849
|
+
},
|
|
26850
|
+
async return(value) {
|
|
26851
|
+
try {
|
|
26852
|
+
if (typeof iterator.return === "function") {
|
|
26853
|
+
return await iterator.return(value);
|
|
26854
|
+
}
|
|
26855
|
+
return {
|
|
26856
|
+
done: true,
|
|
26857
|
+
value
|
|
26858
|
+
};
|
|
26859
|
+
} catch (error) {
|
|
26860
|
+
finishPiLlmSpan(promptState, llmState, void 0, error);
|
|
26861
|
+
throw error;
|
|
26862
|
+
} finally {
|
|
26863
|
+
finishPiLlmSpan(promptState, llmState);
|
|
26864
|
+
}
|
|
26865
|
+
},
|
|
26866
|
+
async throw(error) {
|
|
26867
|
+
try {
|
|
26868
|
+
if (typeof iterator.throw === "function") {
|
|
26869
|
+
return await iterator.throw(error);
|
|
26870
|
+
}
|
|
26871
|
+
throw error;
|
|
26872
|
+
} catch (thrownError) {
|
|
26873
|
+
finishPiLlmSpan(promptState, llmState, void 0, thrownError);
|
|
26874
|
+
throw thrownError;
|
|
26875
|
+
}
|
|
26876
|
+
},
|
|
26877
|
+
[Symbol.asyncIterator]() {
|
|
26878
|
+
return this;
|
|
26879
|
+
}
|
|
26880
|
+
};
|
|
26881
|
+
};
|
|
26882
|
+
}
|
|
26883
|
+
return stream;
|
|
26884
|
+
}
|
|
26885
|
+
function recordPiAssistantMessageEvent(promptState, llmState, event) {
|
|
26886
|
+
recordFirstTokenMetric(llmState, event);
|
|
26887
|
+
const message = "message" in event ? event.message : void 0;
|
|
26888
|
+
const errorMessage2 = "error" in event ? event.error : void 0;
|
|
26889
|
+
if (event.type === "done" && isPiAssistantMessage(message)) {
|
|
26890
|
+
finishPiLlmSpan(promptState, llmState, message);
|
|
26891
|
+
} else if (event.type === "error" && isPiAssistantMessage(errorMessage2)) {
|
|
26892
|
+
finishPiLlmSpan(promptState, llmState, errorMessage2);
|
|
26893
|
+
}
|
|
26894
|
+
}
|
|
26895
|
+
function recordFirstTokenMetric(state, event) {
|
|
26896
|
+
if (state.metrics.time_to_first_token !== void 0 || event.type === "start") {
|
|
26897
|
+
return;
|
|
26898
|
+
}
|
|
26899
|
+
state.metrics.time_to_first_token = getCurrentUnixTimestamp() - state.startTime;
|
|
26900
|
+
}
|
|
26901
|
+
async function handlePiAgentEvent(state, event) {
|
|
26902
|
+
if (state.finalized) {
|
|
26903
|
+
return;
|
|
26904
|
+
}
|
|
26905
|
+
const eventPromptState = state.streamPatchState.eventPromptState;
|
|
26906
|
+
if (eventPromptState && eventPromptState !== state) {
|
|
26907
|
+
return;
|
|
26908
|
+
}
|
|
26909
|
+
if (!eventPromptState && (state.queued || state.streamPatchState.activePromptStates.size > 1 && currentPiPromptState() !== state)) {
|
|
26910
|
+
return;
|
|
26911
|
+
}
|
|
26912
|
+
switch (event.type) {
|
|
26913
|
+
case "message_end":
|
|
26914
|
+
if (isPiAssistantMessage(event.message)) {
|
|
26915
|
+
state.output = extractAssistantOutput(event.message);
|
|
26916
|
+
}
|
|
26917
|
+
return;
|
|
26918
|
+
case "turn_end":
|
|
26919
|
+
state.turnEnded = true;
|
|
26920
|
+
if (isPiAssistantMessage(event.message)) {
|
|
26921
|
+
state.output = extractAssistantOutput(event.message);
|
|
26922
|
+
if (!state.collectedLlmUsageMetrics) {
|
|
26923
|
+
addMetrics(state.metrics, extractUsageMetrics2(event.message.usage));
|
|
26924
|
+
}
|
|
26925
|
+
}
|
|
26926
|
+
if (state.streamPatchState.eventPromptState === state) {
|
|
26927
|
+
state.streamPatchState.eventPromptState = void 0;
|
|
26928
|
+
}
|
|
26929
|
+
if (state.promptCallEnded && state.deferCompletionUntilTurnEnd) {
|
|
26930
|
+
await finalizePiPromptRun(state);
|
|
26931
|
+
}
|
|
26932
|
+
return;
|
|
26933
|
+
case "tool_execution_start":
|
|
26934
|
+
await startPiToolSpan(state, event);
|
|
26935
|
+
return;
|
|
26936
|
+
case "tool_execution_end":
|
|
26937
|
+
finishPiToolSpan(state, event);
|
|
26938
|
+
return;
|
|
26939
|
+
default:
|
|
26940
|
+
return;
|
|
26941
|
+
}
|
|
26942
|
+
}
|
|
26943
|
+
async function startPiToolSpan(state, event) {
|
|
26944
|
+
if (!event.toolCallId || state.activeToolSpans.has(event.toolCallId)) {
|
|
26945
|
+
return;
|
|
26946
|
+
}
|
|
26947
|
+
const restoreAutoInstrumentation = enterAutoInstrumentationAllowed();
|
|
26948
|
+
const metadata = {
|
|
26949
|
+
"gen_ai.tool.call.id": event.toolCallId,
|
|
26950
|
+
"gen_ai.tool.name": event.toolName,
|
|
26951
|
+
"pi_coding_agent.tool.name": event.toolName
|
|
26952
|
+
};
|
|
26953
|
+
try {
|
|
26954
|
+
const span = startSpan({
|
|
26955
|
+
event: {
|
|
26956
|
+
input: event.args,
|
|
26957
|
+
metadata
|
|
26958
|
+
},
|
|
26959
|
+
name: event.toolName || "tool",
|
|
26960
|
+
parent: await state.span.export(),
|
|
26961
|
+
spanAttributes: { type: "tool" /* TOOL */ }
|
|
26962
|
+
});
|
|
26963
|
+
state.activeToolSpans.set(event.toolCallId, {
|
|
26964
|
+
restoreAutoInstrumentation,
|
|
26965
|
+
span
|
|
26966
|
+
});
|
|
26967
|
+
} catch (error) {
|
|
26968
|
+
restoreAutoInstrumentation();
|
|
26969
|
+
throw error;
|
|
26970
|
+
}
|
|
26971
|
+
}
|
|
26972
|
+
function finishPiToolSpan(state, event) {
|
|
26973
|
+
const toolState = state.activeToolSpans.get(event.toolCallId);
|
|
26974
|
+
if (!toolState) {
|
|
26975
|
+
return;
|
|
26976
|
+
}
|
|
26977
|
+
state.activeToolSpans.delete(event.toolCallId);
|
|
26978
|
+
const metadata = {
|
|
26979
|
+
"gen_ai.tool.call.id": event.toolCallId,
|
|
26980
|
+
"gen_ai.tool.name": event.toolName,
|
|
26981
|
+
"pi_coding_agent.tool.name": event.toolName,
|
|
26982
|
+
"pi_coding_agent.tool.is_error": event.isError
|
|
26983
|
+
};
|
|
26984
|
+
try {
|
|
26985
|
+
safeLog4(toolState.span, {
|
|
26986
|
+
...event.isError ? { error: stringifyUnknown2(event.result) } : {},
|
|
26987
|
+
metadata,
|
|
26988
|
+
output: event.result
|
|
26989
|
+
});
|
|
26990
|
+
} finally {
|
|
26991
|
+
try {
|
|
26992
|
+
toolState.span.end();
|
|
26993
|
+
} finally {
|
|
26994
|
+
toolState.restoreAutoInstrumentation?.();
|
|
26995
|
+
}
|
|
26996
|
+
}
|
|
26997
|
+
}
|
|
26998
|
+
async function finalizePiPromptRun(state, error) {
|
|
26999
|
+
if (state.finalized) {
|
|
27000
|
+
return;
|
|
27001
|
+
}
|
|
27002
|
+
state.finalized = true;
|
|
27003
|
+
state.onFinalize?.(state);
|
|
27004
|
+
restorePiStreamFn(state);
|
|
27005
|
+
try {
|
|
27006
|
+
state.unsubscribeAgent?.();
|
|
27007
|
+
} catch (unsubscribeError) {
|
|
27008
|
+
logInstrumentationError4("Pi Coding Agent unsubscribe", unsubscribeError);
|
|
27009
|
+
}
|
|
27010
|
+
await finishOpenLlmSpans(state, error);
|
|
27011
|
+
finishOpenToolSpans(state, error);
|
|
27012
|
+
const metadata = {
|
|
27013
|
+
...state.metadata,
|
|
27014
|
+
...extractModelMetadata2(state.agent.state?.model)
|
|
27015
|
+
};
|
|
27016
|
+
try {
|
|
27017
|
+
safeLog4(state.span, {
|
|
27018
|
+
...error ? { error: stringifyUnknown2(error) } : {},
|
|
27019
|
+
metadata,
|
|
27020
|
+
metrics: {
|
|
27021
|
+
...cleanMetrics5(state.metrics),
|
|
27022
|
+
...buildDurationMetrics3(state.startTime)
|
|
27023
|
+
},
|
|
27024
|
+
output: state.output
|
|
27025
|
+
});
|
|
27026
|
+
} finally {
|
|
27027
|
+
state.span.end();
|
|
27028
|
+
}
|
|
27029
|
+
}
|
|
27030
|
+
function restorePiStreamFn(state) {
|
|
27031
|
+
const patchState = state.streamPatchState;
|
|
27032
|
+
patchState.activePromptStates.delete(state);
|
|
27033
|
+
removeQueuedPromptState(state);
|
|
27034
|
+
if (patchState.eventPromptState === state) {
|
|
27035
|
+
patchState.eventPromptState = void 0;
|
|
27036
|
+
}
|
|
27037
|
+
state.restorePromptContext?.();
|
|
27038
|
+
if (patchState.activePromptStates.size > 0) {
|
|
27039
|
+
return;
|
|
27040
|
+
}
|
|
27041
|
+
if (patchState.agent.streamFn === patchState.wrappedStreamFn) {
|
|
27042
|
+
patchState.agent.streamFn = patchState.originalStreamFn;
|
|
27043
|
+
}
|
|
27044
|
+
piStreamPatchStates.delete(patchState.agent);
|
|
27045
|
+
}
|
|
27046
|
+
function removeQueuedPromptState(state) {
|
|
27047
|
+
state.queued = false;
|
|
27048
|
+
const queuedPromptStates = state.streamPatchState.queuedPromptStates;
|
|
27049
|
+
const index = queuedPromptStates.indexOf(state);
|
|
27050
|
+
if (index >= 0) {
|
|
27051
|
+
queuedPromptStates.splice(index, 1);
|
|
27052
|
+
}
|
|
27053
|
+
}
|
|
27054
|
+
async function finishOpenLlmSpans(state, error) {
|
|
27055
|
+
for (const llmState of [...state.activeLlmSpans]) {
|
|
27056
|
+
finishPiLlmSpan(state, llmState, void 0, error);
|
|
27057
|
+
}
|
|
27058
|
+
}
|
|
27059
|
+
function finishPiLlmSpan(promptState, llmState, message, error) {
|
|
27060
|
+
if (llmState.finalized) {
|
|
27061
|
+
return;
|
|
27062
|
+
}
|
|
27063
|
+
llmState.finalized = true;
|
|
27064
|
+
promptState.activeLlmSpans.delete(llmState);
|
|
27065
|
+
const messageError = message?.stopReason === "error" && message.errorMessage;
|
|
27066
|
+
const metrics = {
|
|
27067
|
+
...extractUsageMetrics2(message?.usage),
|
|
27068
|
+
...cleanMetrics5(llmState.metrics),
|
|
27069
|
+
...buildDurationMetrics3(llmState.startTime)
|
|
27070
|
+
};
|
|
27071
|
+
const usageMetrics = extractUsageMetrics2(message?.usage);
|
|
27072
|
+
if (Object.keys(usageMetrics).length > 0) {
|
|
27073
|
+
promptState.collectedLlmUsageMetrics = true;
|
|
27074
|
+
addMetrics(promptState.metrics, usageMetrics);
|
|
27075
|
+
}
|
|
27076
|
+
try {
|
|
27077
|
+
safeLog4(llmState.span, {
|
|
27078
|
+
...error || messageError ? { error: stringifyUnknown2(error ?? messageError) } : {},
|
|
27079
|
+
metadata: {
|
|
27080
|
+
...llmState.metadata,
|
|
27081
|
+
...message ? extractAssistantMetadata(message) : {}
|
|
27082
|
+
},
|
|
27083
|
+
metrics,
|
|
27084
|
+
...message ? { output: extractAssistantOutput(message) } : {}
|
|
27085
|
+
});
|
|
27086
|
+
} finally {
|
|
27087
|
+
llmState.span.end();
|
|
27088
|
+
}
|
|
27089
|
+
}
|
|
27090
|
+
function finishOpenToolSpans(state, error) {
|
|
27091
|
+
for (const [, toolState] of state.activeToolSpans) {
|
|
27092
|
+
try {
|
|
27093
|
+
safeLog4(toolState.span, {
|
|
27094
|
+
error: error ? stringifyUnknown2(error) : "Pi tool did not complete"
|
|
27095
|
+
});
|
|
27096
|
+
toolState.span.end();
|
|
27097
|
+
} finally {
|
|
27098
|
+
toolState.restoreAutoInstrumentation?.();
|
|
27099
|
+
}
|
|
27100
|
+
}
|
|
27101
|
+
state.activeToolSpans.clear();
|
|
27102
|
+
}
|
|
27103
|
+
function normalizePiContextInput(context) {
|
|
27104
|
+
const messages = context.messages.flatMap(
|
|
27105
|
+
(message) => normalizePiMessage(message)
|
|
27106
|
+
);
|
|
27107
|
+
if (context.systemPrompt) {
|
|
27108
|
+
return [{ role: "system", content: context.systemPrompt }, ...messages];
|
|
27109
|
+
}
|
|
27110
|
+
return messages;
|
|
27111
|
+
}
|
|
27112
|
+
function normalizePiMessage(message) {
|
|
27113
|
+
if (isPiUserMessage(message)) {
|
|
27114
|
+
return [
|
|
27115
|
+
{
|
|
27116
|
+
role: "user",
|
|
27117
|
+
content: normalizeUserContent(message.content)
|
|
27118
|
+
}
|
|
27119
|
+
];
|
|
27120
|
+
}
|
|
27121
|
+
if (isPiAssistantMessage(message)) {
|
|
27122
|
+
return [normalizeAssistantMessage(message)];
|
|
27123
|
+
}
|
|
27124
|
+
if (isPiToolResultMessage(message)) {
|
|
27125
|
+
return [normalizeToolResultMessage(message)];
|
|
27126
|
+
}
|
|
27127
|
+
return [];
|
|
27128
|
+
}
|
|
27129
|
+
function normalizeAssistantMessage(message) {
|
|
27130
|
+
const text = message.content.flatMap((part) => part.type === "text" ? [part.text] : []).join("");
|
|
27131
|
+
const thinking = message.content.flatMap(
|
|
27132
|
+
(part) => part.type === "thinking" && !part.redacted ? [part.thinking] : []
|
|
27133
|
+
).join("");
|
|
27134
|
+
const toolCalls = message.content.flatMap(
|
|
27135
|
+
(part) => part.type === "toolCall" ? [normalizeToolCall(part)] : []
|
|
27136
|
+
);
|
|
27137
|
+
return {
|
|
27138
|
+
role: "assistant",
|
|
27139
|
+
content: text || (toolCalls.length > 0 ? null : ""),
|
|
27140
|
+
...thinking ? { reasoning: thinking } : {},
|
|
27141
|
+
...toolCalls.length > 0 ? { tool_calls: toolCalls } : {}
|
|
27142
|
+
};
|
|
27143
|
+
}
|
|
27144
|
+
function normalizeToolResultMessage(message) {
|
|
27145
|
+
return {
|
|
27146
|
+
role: "tool",
|
|
27147
|
+
tool_call_id: message.toolCallId,
|
|
27148
|
+
content: normalizeUserContent(message.content)
|
|
27149
|
+
};
|
|
27150
|
+
}
|
|
27151
|
+
function normalizeUserContent(content) {
|
|
27152
|
+
if (typeof content === "string") {
|
|
27153
|
+
return content;
|
|
27154
|
+
}
|
|
27155
|
+
return content.map((part) => {
|
|
27156
|
+
if (part.type === "text") {
|
|
27157
|
+
return { type: "text", text: part.text };
|
|
27158
|
+
}
|
|
27159
|
+
if (part.type === "image") {
|
|
27160
|
+
return {
|
|
27161
|
+
type: "image_url",
|
|
27162
|
+
image_url: {
|
|
27163
|
+
url: `data:${part.mimeType};base64,${part.data}`
|
|
27164
|
+
}
|
|
27165
|
+
};
|
|
27166
|
+
}
|
|
27167
|
+
return part;
|
|
27168
|
+
});
|
|
27169
|
+
}
|
|
27170
|
+
function normalizeToolCall(toolCall) {
|
|
27171
|
+
return {
|
|
27172
|
+
id: toolCall.id,
|
|
27173
|
+
type: "function",
|
|
27174
|
+
function: {
|
|
27175
|
+
name: toolCall.name,
|
|
27176
|
+
arguments: stringifyArguments(toolCall.arguments)
|
|
27177
|
+
}
|
|
27178
|
+
};
|
|
27179
|
+
}
|
|
27180
|
+
function extractAssistantOutput(message) {
|
|
27181
|
+
return processInputAttachments([
|
|
27182
|
+
{
|
|
27183
|
+
finish_reason: normalizeStopReason(message.stopReason),
|
|
27184
|
+
index: 0,
|
|
27185
|
+
message: normalizeAssistantMessage(message)
|
|
27186
|
+
}
|
|
27187
|
+
]);
|
|
27188
|
+
}
|
|
27189
|
+
function isPiUserMessage(message) {
|
|
27190
|
+
return message.role === "user" && "content" in message;
|
|
27191
|
+
}
|
|
27192
|
+
function isPiAssistantMessage(message) {
|
|
27193
|
+
return isObject(message) && message.role === "assistant" && Array.isArray(message.content);
|
|
27194
|
+
}
|
|
27195
|
+
function isPiToolResultMessage(message) {
|
|
27196
|
+
return message.role === "toolResult" && Array.isArray(message.content);
|
|
27197
|
+
}
|
|
27198
|
+
function normalizeStopReason(reason) {
|
|
27199
|
+
switch (reason) {
|
|
27200
|
+
case "toolUse":
|
|
27201
|
+
return "tool_calls";
|
|
27202
|
+
case "length":
|
|
27203
|
+
case "stop":
|
|
27204
|
+
return reason;
|
|
27205
|
+
default:
|
|
27206
|
+
return reason ?? "stop";
|
|
27207
|
+
}
|
|
25202
27208
|
}
|
|
25203
|
-
function
|
|
25204
|
-
|
|
25205
|
-
|
|
25206
|
-
|
|
25207
|
-
|
|
25208
|
-
|
|
25209
|
-
|
|
25210
|
-
|
|
25211
|
-
|
|
27209
|
+
function extractPromptInput(text, options) {
|
|
27210
|
+
const images = options?.images;
|
|
27211
|
+
if (!images || images.length === 0) {
|
|
27212
|
+
return text;
|
|
27213
|
+
}
|
|
27214
|
+
return processInputAttachments([
|
|
27215
|
+
{
|
|
27216
|
+
role: "user",
|
|
27217
|
+
content: [
|
|
27218
|
+
{ type: "text", text: text ?? "" },
|
|
27219
|
+
...images.map((image) => ({
|
|
27220
|
+
type: "image_url",
|
|
27221
|
+
image_url: {
|
|
27222
|
+
url: `data:${image.mimeType};base64,${image.data}`
|
|
27223
|
+
}
|
|
27224
|
+
}))
|
|
27225
|
+
]
|
|
25212
27226
|
}
|
|
25213
|
-
|
|
25214
|
-
|
|
25215
|
-
|
|
25216
|
-
|
|
25217
|
-
|
|
25218
|
-
prompt_cache_creation_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_creation : void 0,
|
|
25219
|
-
prompt_cached_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_read : void 0
|
|
25220
|
-
});
|
|
27227
|
+
]);
|
|
27228
|
+
}
|
|
27229
|
+
function extractToolMetadata(tools) {
|
|
27230
|
+
if (!tools || tools.length === 0) {
|
|
27231
|
+
return {};
|
|
25221
27232
|
}
|
|
25222
|
-
|
|
25223
|
-
|
|
25224
|
-
|
|
25225
|
-
|
|
25226
|
-
|
|
25227
|
-
|
|
25228
|
-
|
|
27233
|
+
return {
|
|
27234
|
+
tools: tools.map((tool) => ({
|
|
27235
|
+
type: "function",
|
|
27236
|
+
function: {
|
|
27237
|
+
name: tool.name,
|
|
27238
|
+
...tool.description ? { description: tool.description } : {},
|
|
27239
|
+
...tool.parameters ? { parameters: tool.parameters } : {}
|
|
27240
|
+
}
|
|
27241
|
+
}))
|
|
27242
|
+
};
|
|
25229
27243
|
}
|
|
25230
|
-
function
|
|
25231
|
-
|
|
25232
|
-
return
|
|
25233
|
-
} catch {
|
|
25234
|
-
return input;
|
|
27244
|
+
function extractModelMetadata2(model) {
|
|
27245
|
+
if (!model) {
|
|
27246
|
+
return {};
|
|
25235
27247
|
}
|
|
27248
|
+
return {
|
|
27249
|
+
...model.provider ? { provider: model.provider } : {},
|
|
27250
|
+
...model.id ? { model: model.id, "pi_coding_agent.model": model.id } : {},
|
|
27251
|
+
...model.api ? { "pi_coding_agent.api": model.api } : {},
|
|
27252
|
+
...model.name ? { "pi_coding_agent.model_name": model.name } : {}
|
|
27253
|
+
};
|
|
25236
27254
|
}
|
|
25237
|
-
function
|
|
25238
|
-
return
|
|
27255
|
+
function extractAssistantMetadata(message) {
|
|
27256
|
+
return {
|
|
27257
|
+
...message.provider ? { provider: message.provider } : {},
|
|
27258
|
+
...message.responseModel || message.model ? { model: message.responseModel ?? message.model } : {},
|
|
27259
|
+
...message.api ? { "pi_coding_agent.api": message.api } : {},
|
|
27260
|
+
...message.model ? { "pi_coding_agent.model": message.model } : {},
|
|
27261
|
+
...message.responseModel ? { "pi_coding_agent.response_model": message.responseModel } : {},
|
|
27262
|
+
...message.responseId ? { "pi_coding_agent.response_id": message.responseId } : {},
|
|
27263
|
+
...message.stopReason ? { "pi_coding_agent.stop_reason": message.stopReason } : {}
|
|
27264
|
+
};
|
|
25239
27265
|
}
|
|
25240
|
-
|
|
25241
|
-
|
|
25242
|
-
|
|
25243
|
-
|
|
25244
|
-
|
|
25245
|
-
|
|
25246
|
-
|
|
25247
|
-
|
|
25248
|
-
|
|
25249
|
-
|
|
25250
|
-
|
|
25251
|
-
}
|
|
25252
|
-
|
|
25253
|
-
// src/instrumentation/plugins/langchain-plugin.ts
|
|
25254
|
-
var LangChainPlugin = class extends BasePlugin {
|
|
25255
|
-
injectedManagers = /* @__PURE__ */ new WeakSet();
|
|
25256
|
-
onEnable() {
|
|
25257
|
-
this.subscribeToConfigure(langChainChannels.configure);
|
|
25258
|
-
this.subscribeToConfigure(langChainChannels.configureSync);
|
|
27266
|
+
function extractSessionMetadata(session) {
|
|
27267
|
+
return {
|
|
27268
|
+
...extractModelMetadata2(session.model),
|
|
27269
|
+
...session.sessionId ? { "pi_coding_agent.session_id": session.sessionId } : {},
|
|
27270
|
+
...session.sessionName ? { "pi_coding_agent.session_name": session.sessionName } : {},
|
|
27271
|
+
...session.thinkingLevel ? { "pi_coding_agent.thinking_level": session.thinkingLevel } : {},
|
|
27272
|
+
...typeof session.getActiveToolNames === "function" ? { "pi_coding_agent.active_tools": session.getActiveToolNames() } : {}
|
|
27273
|
+
};
|
|
27274
|
+
}
|
|
27275
|
+
function extractPromptOptionsMetadata(options) {
|
|
27276
|
+
if (!options) {
|
|
27277
|
+
return {};
|
|
25259
27278
|
}
|
|
25260
|
-
|
|
25261
|
-
|
|
25262
|
-
|
|
25263
|
-
|
|
25264
|
-
|
|
25265
|
-
|
|
27279
|
+
return {
|
|
27280
|
+
...options.source ? { "pi_coding_agent.source": options.source } : {},
|
|
27281
|
+
...options.streamingBehavior ? { "pi_coding_agent.streaming_behavior": options.streamingBehavior } : {},
|
|
27282
|
+
...options.expandPromptTemplates !== void 0 ? {
|
|
27283
|
+
"pi_coding_agent.expand_prompt_templates": options.expandPromptTemplates
|
|
27284
|
+
} : {}
|
|
27285
|
+
};
|
|
27286
|
+
}
|
|
27287
|
+
function extractStreamOptionsMetadata(options) {
|
|
27288
|
+
if (!options) {
|
|
27289
|
+
return {};
|
|
25266
27290
|
}
|
|
25267
|
-
|
|
25268
|
-
|
|
25269
|
-
|
|
25270
|
-
|
|
25271
|
-
|
|
25272
|
-
|
|
25273
|
-
|
|
25274
|
-
|
|
25275
|
-
|
|
25276
|
-
}
|
|
25277
|
-
|
|
25278
|
-
|
|
25279
|
-
|
|
25280
|
-
|
|
27291
|
+
return {
|
|
27292
|
+
...options.temperature !== void 0 ? { temperature: options.temperature } : {},
|
|
27293
|
+
...options.maxTokens !== void 0 ? { max_tokens: options.maxTokens } : {},
|
|
27294
|
+
...options.reasoning ? { "pi_coding_agent.reasoning": options.reasoning } : {},
|
|
27295
|
+
...options.transport ? { "pi_coding_agent.transport": options.transport } : {},
|
|
27296
|
+
...options.cacheRetention ? { "pi_coding_agent.cache_retention": options.cacheRetention } : {},
|
|
27297
|
+
...options.sessionId ? { "pi_coding_agent.session_id": options.sessionId } : {},
|
|
27298
|
+
...options.timeoutMs !== void 0 ? { "pi_coding_agent.timeout_ms": options.timeoutMs } : {},
|
|
27299
|
+
...options.maxRetries !== void 0 ? { "pi_coding_agent.max_retries": options.maxRetries } : {},
|
|
27300
|
+
...options.maxRetryDelayMs !== void 0 ? { "pi_coding_agent.max_retry_delay_ms": options.maxRetryDelayMs } : {},
|
|
27301
|
+
...options.metadata ? { "pi_coding_agent.metadata": options.metadata } : {}
|
|
27302
|
+
};
|
|
27303
|
+
}
|
|
27304
|
+
function getLlmSpanName(model) {
|
|
27305
|
+
switch (model.api) {
|
|
27306
|
+
case "anthropic-messages":
|
|
27307
|
+
return "anthropic.messages.create";
|
|
27308
|
+
case "openai-completions":
|
|
27309
|
+
return "Chat Completion";
|
|
27310
|
+
case "openai-responses":
|
|
27311
|
+
case "azure-openai-responses":
|
|
27312
|
+
case "openai-codex-responses":
|
|
27313
|
+
return "openai.responses.create";
|
|
27314
|
+
case "google-generative-ai":
|
|
27315
|
+
case "google-vertex":
|
|
27316
|
+
return "generate_content";
|
|
27317
|
+
case "mistral-conversations":
|
|
27318
|
+
return "mistral.chat.stream";
|
|
27319
|
+
case "bedrock-converse-stream":
|
|
27320
|
+
return "bedrock.converse_stream";
|
|
27321
|
+
default:
|
|
27322
|
+
return "pi_ai.streamSimple";
|
|
25281
27323
|
}
|
|
25282
|
-
|
|
25283
|
-
|
|
25284
|
-
|
|
25285
|
-
}
|
|
25286
|
-
if (this.injectedManagers.has(result) || hasBraintrustHandler(result)) {
|
|
25287
|
-
return;
|
|
25288
|
-
}
|
|
25289
|
-
try {
|
|
25290
|
-
result.addHandler(new BraintrustLangChainCallbackHandler(), true);
|
|
25291
|
-
this.injectedManagers.add(result);
|
|
25292
|
-
} catch {
|
|
25293
|
-
}
|
|
27324
|
+
}
|
|
27325
|
+
function extractUsageMetrics2(usage) {
|
|
27326
|
+
if (!usage) {
|
|
27327
|
+
return {};
|
|
25294
27328
|
}
|
|
25295
|
-
|
|
25296
|
-
|
|
25297
|
-
|
|
25298
|
-
|
|
27329
|
+
return cleanMetrics5({
|
|
27330
|
+
completion_tokens: usage.output,
|
|
27331
|
+
prompt_cache_creation_tokens: usage.cacheWrite,
|
|
27332
|
+
prompt_cached_tokens: usage.cacheRead,
|
|
27333
|
+
prompt_tokens: usage.input,
|
|
27334
|
+
tokens: usage.totalTokens ?? usage.tokens
|
|
27335
|
+
});
|
|
27336
|
+
}
|
|
27337
|
+
function addMetrics(target, source) {
|
|
27338
|
+
for (const [key, value] of Object.entries(source)) {
|
|
27339
|
+
target[key] = (target[key] ?? 0) + value;
|
|
25299
27340
|
}
|
|
25300
|
-
const maybeManager = value;
|
|
25301
|
-
return typeof maybeManager.addHandler === "function";
|
|
25302
27341
|
}
|
|
25303
|
-
function
|
|
25304
|
-
|
|
25305
|
-
|
|
25306
|
-
|
|
25307
|
-
|
|
25308
|
-
|
|
25309
|
-
|
|
25310
|
-
}) ?? false;
|
|
27342
|
+
function buildDurationMetrics3(startTime) {
|
|
27343
|
+
const end = getCurrentUnixTimestamp();
|
|
27344
|
+
return {
|
|
27345
|
+
duration: end - startTime,
|
|
27346
|
+
end,
|
|
27347
|
+
start: startTime
|
|
27348
|
+
};
|
|
25311
27349
|
}
|
|
25312
|
-
function
|
|
25313
|
-
|
|
25314
|
-
|
|
27350
|
+
function cleanMetrics5(metrics) {
|
|
27351
|
+
const cleaned = {};
|
|
27352
|
+
for (const [key, value] of Object.entries(metrics)) {
|
|
27353
|
+
if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
|
|
27354
|
+
cleaned[key] = value;
|
|
27355
|
+
}
|
|
25315
27356
|
}
|
|
25316
|
-
|
|
25317
|
-
|
|
25318
|
-
|
|
25319
|
-
|
|
25320
|
-
return;
|
|
27357
|
+
return cleaned;
|
|
27358
|
+
}
|
|
27359
|
+
function stringifyArguments(value) {
|
|
27360
|
+
if (typeof value === "string") {
|
|
27361
|
+
return value;
|
|
25321
27362
|
}
|
|
25322
|
-
|
|
25323
|
-
|
|
25324
|
-
|
|
25325
|
-
|
|
27363
|
+
try {
|
|
27364
|
+
return JSON.stringify(value);
|
|
27365
|
+
} catch {
|
|
27366
|
+
return stringifyUnknown2(value);
|
|
25326
27367
|
}
|
|
25327
27368
|
}
|
|
25328
|
-
function
|
|
25329
|
-
|
|
27369
|
+
function stringifyUnknown2(value) {
|
|
27370
|
+
if (value instanceof Error) {
|
|
27371
|
+
return value.message;
|
|
27372
|
+
}
|
|
27373
|
+
if (typeof value === "string") {
|
|
27374
|
+
return value;
|
|
27375
|
+
}
|
|
27376
|
+
try {
|
|
27377
|
+
return JSON.stringify(value);
|
|
27378
|
+
} catch {
|
|
27379
|
+
return String(value);
|
|
27380
|
+
}
|
|
25330
27381
|
}
|
|
25331
|
-
function
|
|
25332
|
-
|
|
25333
|
-
|
|
27382
|
+
function safeLog4(span, event) {
|
|
27383
|
+
try {
|
|
27384
|
+
span.log(event);
|
|
27385
|
+
} catch (error) {
|
|
27386
|
+
logInstrumentationError4("Pi Coding Agent span log", error);
|
|
25334
27387
|
}
|
|
25335
|
-
|
|
27388
|
+
}
|
|
27389
|
+
function logInstrumentationError4(context, error) {
|
|
27390
|
+
debugLogger.debug(`${context}:`, error);
|
|
25336
27391
|
}
|
|
25337
27392
|
|
|
25338
27393
|
// src/instrumentation/braintrust-plugin.ts
|
|
@@ -25360,6 +27415,7 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
25360
27415
|
gitHubCopilotPlugin = null;
|
|
25361
27416
|
fluePlugin = null;
|
|
25362
27417
|
langChainPlugin = null;
|
|
27418
|
+
piCodingAgentPlugin = null;
|
|
25363
27419
|
constructor(config = {}) {
|
|
25364
27420
|
super();
|
|
25365
27421
|
this.config = config;
|
|
@@ -25434,6 +27490,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
25434
27490
|
this.gitHubCopilotPlugin = new GitHubCopilotPlugin();
|
|
25435
27491
|
this.gitHubCopilotPlugin.enable();
|
|
25436
27492
|
}
|
|
27493
|
+
if (integrations.piCodingAgent !== false) {
|
|
27494
|
+
this.piCodingAgentPlugin = new PiCodingAgentPlugin();
|
|
27495
|
+
this.piCodingAgentPlugin.enable();
|
|
27496
|
+
}
|
|
25437
27497
|
if (getIntegrationConfig(integrations, "flue") !== false) {
|
|
25438
27498
|
this.fluePlugin = new FluePlugin();
|
|
25439
27499
|
this.fluePlugin.enable();
|
|
@@ -25512,6 +27572,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
25512
27572
|
this.gitHubCopilotPlugin.disable();
|
|
25513
27573
|
this.gitHubCopilotPlugin = null;
|
|
25514
27574
|
}
|
|
27575
|
+
if (this.piCodingAgentPlugin) {
|
|
27576
|
+
this.piCodingAgentPlugin.disable();
|
|
27577
|
+
this.piCodingAgentPlugin = null;
|
|
27578
|
+
}
|
|
25515
27579
|
if (this.fluePlugin) {
|
|
25516
27580
|
this.fluePlugin.disable();
|
|
25517
27581
|
this.fluePlugin = null;
|
|
@@ -25531,6 +27595,11 @@ var envIntegrationAliases = {
|
|
|
25531
27595
|
openaicodexsdk: "openaiCodexSDK",
|
|
25532
27596
|
codex: "openaiCodexSDK",
|
|
25533
27597
|
"codex-sdk": "openaiCodexSDK",
|
|
27598
|
+
"pi-coding-agent": "piCodingAgent",
|
|
27599
|
+
"pi-coding-agent-sdk": "piCodingAgent",
|
|
27600
|
+
picodingagent: "piCodingAgent",
|
|
27601
|
+
picodingagentsdk: "piCodingAgent",
|
|
27602
|
+
"@earendil-works/pi-coding-agent": "piCodingAgent",
|
|
25534
27603
|
anthropic: "anthropic",
|
|
25535
27604
|
aisdk: "aisdk",
|
|
25536
27605
|
"ai-sdk": "aisdk",
|
|
@@ -25596,7 +27665,8 @@ function getDefaultInstrumentationIntegrations() {
|
|
|
25596
27665
|
genkit: true,
|
|
25597
27666
|
gitHubCopilot: true,
|
|
25598
27667
|
langchain: true,
|
|
25599
|
-
langgraph: true
|
|
27668
|
+
langgraph: true,
|
|
27669
|
+
piCodingAgent: true
|
|
25600
27670
|
};
|
|
25601
27671
|
}
|
|
25602
27672
|
function readDisabledInstrumentationEnvConfig(disabledList) {
|
|
@@ -25807,6 +27877,7 @@ __export(exports_exports, {
|
|
|
25807
27877
|
_internalIso: () => isomorph_default,
|
|
25808
27878
|
_internalSetInitialState: () => _internalSetInitialState,
|
|
25809
27879
|
addAzureBlobHeaders: () => addAzureBlobHeaders,
|
|
27880
|
+
braintrustAISDKTelemetry: () => braintrustAISDKTelemetry,
|
|
25810
27881
|
braintrustFlueObserver: () => braintrustFlueObserver,
|
|
25811
27882
|
braintrustStreamChunkSchema: () => braintrustStreamChunkSchema,
|
|
25812
27883
|
buildLocalSummary: () => buildLocalSummary,
|
|
@@ -25899,6 +27970,7 @@ __export(exports_exports, {
|
|
|
25899
27970
|
wrapOpenAIv4: () => wrapOpenAIv4,
|
|
25900
27971
|
wrapOpenRouter: () => wrapOpenRouter,
|
|
25901
27972
|
wrapOpenRouterAgent: () => wrapOpenRouterAgent,
|
|
27973
|
+
wrapPiCodingAgentSDK: () => wrapPiCodingAgentSDK,
|
|
25902
27974
|
wrapTraced: () => wrapTraced,
|
|
25903
27975
|
wrapVitest: () => wrapVitest
|
|
25904
27976
|
});
|
|
@@ -27959,6 +30031,54 @@ function wrapCursorAgent(agent) {
|
|
|
27959
30031
|
return proxy;
|
|
27960
30032
|
}
|
|
27961
30033
|
|
|
30034
|
+
// src/wrappers/pi-coding-agent.ts
|
|
30035
|
+
var WRAPPED_PROMPT = /* @__PURE__ */ Symbol.for("braintrust.pi-coding-agent.wrapped-prompt");
|
|
30036
|
+
function wrapPiCodingAgentSDK(sdk) {
|
|
30037
|
+
if (!sdk || typeof sdk !== "object") {
|
|
30038
|
+
return sdk;
|
|
30039
|
+
}
|
|
30040
|
+
const maybeSDK = sdk;
|
|
30041
|
+
if (!maybeSDK.AgentSession || typeof maybeSDK.AgentSession !== "function") {
|
|
30042
|
+
console.warn("Unsupported Pi Coding Agent SDK. Not wrapping.");
|
|
30043
|
+
return sdk;
|
|
30044
|
+
}
|
|
30045
|
+
patchAgentSessionClass(
|
|
30046
|
+
maybeSDK.AgentSession
|
|
30047
|
+
);
|
|
30048
|
+
return sdk;
|
|
30049
|
+
}
|
|
30050
|
+
function patchAgentSessionClass(AgentSession) {
|
|
30051
|
+
const prototype = AgentSession.prototype;
|
|
30052
|
+
if (!prototype || prototype[WRAPPED_PROMPT]) {
|
|
30053
|
+
return;
|
|
30054
|
+
}
|
|
30055
|
+
const descriptor = Object.getOwnPropertyDescriptor(prototype, "prompt");
|
|
30056
|
+
if (!descriptor || typeof descriptor.value !== "function") {
|
|
30057
|
+
console.warn("Unsupported Pi Coding Agent SDK. Not wrapping.");
|
|
30058
|
+
return;
|
|
30059
|
+
}
|
|
30060
|
+
const originalPrompt = descriptor.value;
|
|
30061
|
+
Object.defineProperty(prototype, "prompt", {
|
|
30062
|
+
...descriptor,
|
|
30063
|
+
value: function wrappedPiCodingAgentPrompt(text, options) {
|
|
30064
|
+
const args = [text, options];
|
|
30065
|
+
return piCodingAgentChannels.prompt.tracePromise(
|
|
30066
|
+
() => Reflect.apply(originalPrompt, this, args),
|
|
30067
|
+
{
|
|
30068
|
+
arguments: args,
|
|
30069
|
+
self: this,
|
|
30070
|
+
session: this
|
|
30071
|
+
}
|
|
30072
|
+
);
|
|
30073
|
+
}
|
|
30074
|
+
});
|
|
30075
|
+
Object.defineProperty(prototype, WRAPPED_PROMPT, {
|
|
30076
|
+
configurable: false,
|
|
30077
|
+
enumerable: false,
|
|
30078
|
+
value: true
|
|
30079
|
+
});
|
|
30080
|
+
}
|
|
30081
|
+
|
|
27962
30082
|
// src/wrappers/google-genai.ts
|
|
27963
30083
|
function wrapGoogleGenAI(googleGenAI) {
|
|
27964
30084
|
if (!googleGenAI || typeof googleGenAI !== "object") {
|
|
@@ -27995,12 +30115,25 @@ function wrapGoogleGenAIClass(OriginalGoogleGenAI) {
|
|
|
27995
30115
|
}
|
|
27996
30116
|
function wrapGoogleGenAIInstance(instance) {
|
|
27997
30117
|
const wrappedModels = wrapModels(instance.models);
|
|
30118
|
+
let originalInteractions;
|
|
30119
|
+
let wrappedInteractions;
|
|
27998
30120
|
patchGoogleGenAIChats(instance, wrappedModels);
|
|
27999
30121
|
return new Proxy(instance, {
|
|
28000
30122
|
get(target, prop, receiver) {
|
|
28001
30123
|
if (prop === "models") {
|
|
28002
30124
|
return wrappedModels;
|
|
28003
30125
|
}
|
|
30126
|
+
if (prop === "interactions") {
|
|
30127
|
+
const interactions = Reflect.get(target, prop, receiver);
|
|
30128
|
+
if (!isObject(interactions) || typeof interactions.create !== "function") {
|
|
30129
|
+
return interactions;
|
|
30130
|
+
}
|
|
30131
|
+
if (interactions !== originalInteractions) {
|
|
30132
|
+
originalInteractions = interactions;
|
|
30133
|
+
wrappedInteractions = wrapInteractions(interactions);
|
|
30134
|
+
}
|
|
30135
|
+
return wrappedInteractions;
|
|
30136
|
+
}
|
|
28004
30137
|
return Reflect.get(target, prop, receiver);
|
|
28005
30138
|
}
|
|
28006
30139
|
});
|
|
@@ -28027,6 +30160,16 @@ function wrapModels(models) {
|
|
|
28027
30160
|
}
|
|
28028
30161
|
});
|
|
28029
30162
|
}
|
|
30163
|
+
function wrapInteractions(interactions) {
|
|
30164
|
+
return new Proxy(interactions, {
|
|
30165
|
+
get(target, prop, receiver) {
|
|
30166
|
+
if (prop === "create") {
|
|
30167
|
+
return wrapInteractionCreate(target.create.bind(target));
|
|
30168
|
+
}
|
|
30169
|
+
return Reflect.get(target, prop, receiver);
|
|
30170
|
+
}
|
|
30171
|
+
});
|
|
30172
|
+
}
|
|
28030
30173
|
function wrapGenerateContent(original) {
|
|
28031
30174
|
return function(params) {
|
|
28032
30175
|
return googleGenAIChannels.generateContent.tracePromise(
|
|
@@ -28051,6 +30194,18 @@ function wrapEmbedContent(original) {
|
|
|
28051
30194
|
);
|
|
28052
30195
|
};
|
|
28053
30196
|
}
|
|
30197
|
+
function wrapInteractionCreate(original) {
|
|
30198
|
+
return function(params, options) {
|
|
30199
|
+
if (params.background === true) {
|
|
30200
|
+
return options === void 0 ? original(params) : original(params, options);
|
|
30201
|
+
}
|
|
30202
|
+
const traceContext = options === void 0 ? { arguments: [params] } : { arguments: [params, options] };
|
|
30203
|
+
return googleGenAIChannels.interactionsCreate.tracePromise(
|
|
30204
|
+
() => options === void 0 ? original(params) : original(params, options),
|
|
30205
|
+
traceContext
|
|
30206
|
+
);
|
|
30207
|
+
};
|
|
30208
|
+
}
|
|
28054
30209
|
|
|
28055
30210
|
// src/wrappers/google-adk.ts
|
|
28056
30211
|
function wrapGoogleADK(adkModule) {
|
|
@@ -31568,6 +33723,13 @@ var EvalResultWithSummary = class {
|
|
|
31568
33723
|
};
|
|
31569
33724
|
}
|
|
31570
33725
|
};
|
|
33726
|
+
async function getPersistedBaseExperimentId(experiment) {
|
|
33727
|
+
try {
|
|
33728
|
+
return await experiment._getBaseExperimentId();
|
|
33729
|
+
} catch {
|
|
33730
|
+
return void 0;
|
|
33731
|
+
}
|
|
33732
|
+
}
|
|
31571
33733
|
function makeEvalName(projectName, experimentName) {
|
|
31572
33734
|
let out = projectName;
|
|
31573
33735
|
if (experimentName) {
|
|
@@ -31950,6 +34112,14 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
|
|
|
31950
34112
|
return;
|
|
31951
34113
|
}
|
|
31952
34114
|
const eventDataset = experiment ? experiment.dataset : Dataset2.isDataset(evaluator.data) ? evaluator.data : void 0;
|
|
34115
|
+
const inlineOrigin = datum.origin === void 0 ? void 0 : ObjectReference.parse(datum.origin);
|
|
34116
|
+
const origin = inlineOrigin ?? (eventDataset && datum.id && datum._xact_id ? {
|
|
34117
|
+
object_type: "dataset",
|
|
34118
|
+
object_id: await eventDataset.id,
|
|
34119
|
+
id: datum.id,
|
|
34120
|
+
created: datum.created,
|
|
34121
|
+
_xact_id: datum._xact_id
|
|
34122
|
+
} : void 0);
|
|
31953
34123
|
const baseEvent = {
|
|
31954
34124
|
name: "eval",
|
|
31955
34125
|
spanAttributes: {
|
|
@@ -31959,13 +34129,7 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
|
|
|
31959
34129
|
input: datum.input,
|
|
31960
34130
|
expected: "expected" in datum ? datum.expected : void 0,
|
|
31961
34131
|
tags: datum.tags,
|
|
31962
|
-
origin
|
|
31963
|
-
object_type: "dataset",
|
|
31964
|
-
object_id: await eventDataset.id,
|
|
31965
|
-
id: datum.id,
|
|
31966
|
-
created: datum.created,
|
|
31967
|
-
_xact_id: datum._xact_id
|
|
31968
|
-
} : void 0,
|
|
34132
|
+
origin,
|
|
31969
34133
|
...datum.upsert_id ? { id: datum.upsert_id } : {}
|
|
31970
34134
|
}
|
|
31971
34135
|
};
|
|
@@ -32322,8 +34486,10 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
|
|
|
32322
34486
|
collectedResults.length = 0;
|
|
32323
34487
|
}
|
|
32324
34488
|
}
|
|
34489
|
+
const comparisonExperimentId = experiment ? evaluator.baseExperimentId ?? await getPersistedBaseExperimentId(experiment) : void 0;
|
|
32325
34490
|
const summary = experiment ? await experiment.summarize({
|
|
32326
|
-
summarizeScores: evaluator.summarizeScores
|
|
34491
|
+
summarizeScores: evaluator.summarizeScores,
|
|
34492
|
+
...comparisonExperimentId !== void 0 ? { comparisonExperimentId } : {}
|
|
32327
34493
|
}) : buildLocalSummary(
|
|
32328
34494
|
evaluator,
|
|
32329
34495
|
collectResults ? collectedResults : [],
|
|
@@ -32552,6 +34718,7 @@ var Project2 = class {
|
|
|
32552
34718
|
prompts;
|
|
32553
34719
|
parameters;
|
|
32554
34720
|
scorers;
|
|
34721
|
+
classifiers;
|
|
32555
34722
|
_publishableCodeFunctions = [];
|
|
32556
34723
|
_publishablePrompts = [];
|
|
32557
34724
|
_publishableParameters = [];
|
|
@@ -32563,6 +34730,7 @@ var Project2 = class {
|
|
|
32563
34730
|
this.prompts = new PromptBuilder(this);
|
|
32564
34731
|
this.parameters = new ParametersBuilder(this);
|
|
32565
34732
|
this.scorers = new ScorerBuilder(this);
|
|
34733
|
+
this.classifiers = new ClassifierBuilder(this);
|
|
32566
34734
|
}
|
|
32567
34735
|
addPrompt(prompt) {
|
|
32568
34736
|
this._publishablePrompts.push(prompt);
|
|
@@ -32697,6 +34865,28 @@ var ScorerBuilder = class {
|
|
|
32697
34865
|
}
|
|
32698
34866
|
}
|
|
32699
34867
|
};
|
|
34868
|
+
var ClassifierBuilder = class {
|
|
34869
|
+
constructor(project) {
|
|
34870
|
+
this.project = project;
|
|
34871
|
+
}
|
|
34872
|
+
taskCounter = 0;
|
|
34873
|
+
create(opts) {
|
|
34874
|
+
this.taskCounter++;
|
|
34875
|
+
let resolvedName = opts.name ?? opts.handler.name;
|
|
34876
|
+
if (!resolvedName || resolvedName.trim().length === 0) {
|
|
34877
|
+
resolvedName = `Classifier ${isomorph_default.basename(currentFilename)} ${this.taskCounter}`;
|
|
34878
|
+
}
|
|
34879
|
+
const slug = opts.slug ?? slugify(resolvedName, { lower: true, strict: true });
|
|
34880
|
+
const classifier = new CodeFunction(this.project, {
|
|
34881
|
+
...opts,
|
|
34882
|
+
name: resolvedName,
|
|
34883
|
+
slug,
|
|
34884
|
+
type: "classifier"
|
|
34885
|
+
});
|
|
34886
|
+
this.project.addCodeFunction(classifier);
|
|
34887
|
+
return classifier;
|
|
34888
|
+
}
|
|
34889
|
+
};
|
|
32700
34890
|
var CodeFunction = class {
|
|
32701
34891
|
constructor(project, opts) {
|
|
32702
34892
|
this.project = project;
|
|
@@ -33046,7 +35236,7 @@ var serializedParametersContainerSchema = z13.union([
|
|
|
33046
35236
|
staticParametersSchema
|
|
33047
35237
|
]);
|
|
33048
35238
|
var evaluatorDefinitionSchema = z13.object({
|
|
33049
|
-
parameters: serializedParametersContainerSchema.
|
|
35239
|
+
parameters: serializedParametersContainerSchema.nullish(),
|
|
33050
35240
|
scores: z13.array(z13.object({ name: z13.string() })).optional(),
|
|
33051
35241
|
classifiers: z13.array(z13.object({ name: z13.string() })).optional()
|
|
33052
35242
|
});
|
|
@@ -33114,6 +35304,7 @@ export {
|
|
|
33114
35304
|
isomorph_default as _internalIso,
|
|
33115
35305
|
_internalSetInitialState,
|
|
33116
35306
|
addAzureBlobHeaders,
|
|
35307
|
+
braintrustAISDKTelemetry,
|
|
33117
35308
|
braintrustFlueObserver,
|
|
33118
35309
|
braintrustStreamChunkSchema,
|
|
33119
35310
|
buildLocalSummary,
|
|
@@ -33207,6 +35398,7 @@ export {
|
|
|
33207
35398
|
wrapOpenAIv4,
|
|
33208
35399
|
wrapOpenRouter,
|
|
33209
35400
|
wrapOpenRouterAgent,
|
|
35401
|
+
wrapPiCodingAgentSDK,
|
|
33210
35402
|
wrapTraced,
|
|
33211
35403
|
wrapVitest
|
|
33212
35404
|
};
|