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/index.mjs
CHANGED
|
@@ -25,8 +25,9 @@ import {
|
|
|
25
25
|
openRouterAgentChannels,
|
|
26
26
|
openRouterChannels,
|
|
27
27
|
patchTracingChannel,
|
|
28
|
+
piCodingAgentChannels,
|
|
28
29
|
readDisabledInstrumentationEnvConfig
|
|
29
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-BYFADLEZ.mjs";
|
|
30
31
|
|
|
31
32
|
// src/node/config.ts
|
|
32
33
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
@@ -5106,14 +5107,18 @@ function useTestBackgroundLogger() {
|
|
|
5106
5107
|
function clearTestBackgroundLogger() {
|
|
5107
5108
|
_internalGetGlobalState()?.setOverrideBgLogger(null);
|
|
5108
5109
|
}
|
|
5109
|
-
function initTestExperiment(experimentName, projectName) {
|
|
5110
|
+
function initTestExperiment(experimentName, projectName, experimentFullInfo = {}) {
|
|
5110
5111
|
setInitialTestState();
|
|
5111
5112
|
const state = _internalGetGlobalState();
|
|
5112
5113
|
const project = projectName ?? experimentName;
|
|
5113
5114
|
const lazyMetadata = new LazyValue(
|
|
5114
5115
|
async () => ({
|
|
5115
5116
|
project: { id: project, name: project, fullInfo: {} },
|
|
5116
|
-
experiment: {
|
|
5117
|
+
experiment: {
|
|
5118
|
+
id: experimentName,
|
|
5119
|
+
name: experimentName,
|
|
5120
|
+
fullInfo: experimentFullInfo
|
|
5121
|
+
}
|
|
5117
5122
|
})
|
|
5118
5123
|
);
|
|
5119
5124
|
return new Experiment2(state, lazyMetadata);
|
|
@@ -8478,6 +8483,10 @@ var Experiment2 = class extends ObjectFetcher {
|
|
|
8478
8483
|
return (await this.lazyMetadata.get()).project;
|
|
8479
8484
|
})();
|
|
8480
8485
|
}
|
|
8486
|
+
async _getBaseExperimentId() {
|
|
8487
|
+
const baseExperimentId = (await this.lazyMetadata.get()).experiment.fullInfo["base_exp_id"];
|
|
8488
|
+
return typeof baseExperimentId === "string" && baseExperimentId ? baseExperimentId : void 0;
|
|
8489
|
+
}
|
|
8481
8490
|
parentObjectType() {
|
|
8482
8491
|
return 1 /* EXPERIMENT */;
|
|
8483
8492
|
}
|
|
@@ -8618,6 +8627,14 @@ var Experiment2 = class extends ObjectFetcher {
|
|
|
8618
8627
|
comparisonExperimentId = baseExperiment.id;
|
|
8619
8628
|
comparisonExperimentName = baseExperiment.name;
|
|
8620
8629
|
}
|
|
8630
|
+
} else {
|
|
8631
|
+
try {
|
|
8632
|
+
const comparisonExperiment = await state.apiConn().get_json(`v1/experiment/${comparisonExperimentId}`);
|
|
8633
|
+
if (typeof comparisonExperiment["name"] === "string") {
|
|
8634
|
+
comparisonExperimentName = comparisonExperiment["name"];
|
|
8635
|
+
}
|
|
8636
|
+
} catch {
|
|
8637
|
+
}
|
|
8621
8638
|
}
|
|
8622
8639
|
try {
|
|
8623
8640
|
const results = await state.apiConn().get_json(
|
|
@@ -10659,6 +10676,64 @@ var BasePlugin = class {
|
|
|
10659
10676
|
}
|
|
10660
10677
|
};
|
|
10661
10678
|
|
|
10679
|
+
// src/instrumentation/auto-instrumentation-suppression.ts
|
|
10680
|
+
var autoInstrumentationSuppressionStore;
|
|
10681
|
+
function suppressionStore() {
|
|
10682
|
+
autoInstrumentationSuppressionStore ??= isomorph_default.newAsyncLocalStorage();
|
|
10683
|
+
return autoInstrumentationSuppressionStore;
|
|
10684
|
+
}
|
|
10685
|
+
function currentFrames() {
|
|
10686
|
+
return suppressionStore().getStore()?.frames ?? [];
|
|
10687
|
+
}
|
|
10688
|
+
function isAutoInstrumentationSuppressed() {
|
|
10689
|
+
const frames = currentFrames();
|
|
10690
|
+
return frames[frames.length - 1]?.mode === "suppress";
|
|
10691
|
+
}
|
|
10692
|
+
function runWithAutoInstrumentationSuppressed(callback) {
|
|
10693
|
+
const frame = {
|
|
10694
|
+
id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
|
|
10695
|
+
mode: "suppress"
|
|
10696
|
+
};
|
|
10697
|
+
return suppressionStore().run(
|
|
10698
|
+
{ frames: [...currentFrames(), frame] },
|
|
10699
|
+
callback
|
|
10700
|
+
);
|
|
10701
|
+
}
|
|
10702
|
+
function bindAutoInstrumentationSuppressionToStart(tracingChannel2) {
|
|
10703
|
+
const startChannel = tracingChannel2.start;
|
|
10704
|
+
if (!startChannel) {
|
|
10705
|
+
return void 0;
|
|
10706
|
+
}
|
|
10707
|
+
const store = suppressionStore();
|
|
10708
|
+
startChannel.bindStore(store, () => ({
|
|
10709
|
+
frames: [
|
|
10710
|
+
...currentFrames(),
|
|
10711
|
+
{
|
|
10712
|
+
id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
|
|
10713
|
+
mode: "suppress"
|
|
10714
|
+
}
|
|
10715
|
+
]
|
|
10716
|
+
}));
|
|
10717
|
+
return () => {
|
|
10718
|
+
startChannel.unbindStore(store);
|
|
10719
|
+
};
|
|
10720
|
+
}
|
|
10721
|
+
function enterAutoInstrumentationAllowed() {
|
|
10722
|
+
const frame = {
|
|
10723
|
+
id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-allow"),
|
|
10724
|
+
mode: "allow"
|
|
10725
|
+
};
|
|
10726
|
+
suppressionStore().enterWith({
|
|
10727
|
+
frames: [...currentFrames(), frame]
|
|
10728
|
+
});
|
|
10729
|
+
return () => {
|
|
10730
|
+
const frames = currentFrames().filter(
|
|
10731
|
+
(candidate) => candidate.id !== frame.id
|
|
10732
|
+
);
|
|
10733
|
+
suppressionStore().enterWith(frames.length > 0 ? { frames } : void 0);
|
|
10734
|
+
};
|
|
10735
|
+
}
|
|
10736
|
+
|
|
10662
10737
|
// src/instrumentation/core/channel-tracing.ts
|
|
10663
10738
|
function isSyncStreamLike(value) {
|
|
10664
10739
|
return !!value && typeof value === "object" && typeof value.on === "function";
|
|
@@ -10690,16 +10765,33 @@ function startSpanForEvent(config, event, channelName) {
|
|
|
10690
10765
|
metadata: mergeInputMetadata(metadata, spanInfoMetadata)
|
|
10691
10766
|
});
|
|
10692
10767
|
} catch (error) {
|
|
10693
|
-
|
|
10768
|
+
debugLogger.error(`Error extracting input for ${channelName}:`, error);
|
|
10694
10769
|
}
|
|
10695
10770
|
return { span, startTime };
|
|
10696
10771
|
}
|
|
10772
|
+
function shouldTraceEvent(config, event, channelName) {
|
|
10773
|
+
if (!config.shouldTrace) {
|
|
10774
|
+
return true;
|
|
10775
|
+
}
|
|
10776
|
+
try {
|
|
10777
|
+
return config.shouldTrace(event.arguments, event);
|
|
10778
|
+
} catch (error) {
|
|
10779
|
+
debugLogger.error(
|
|
10780
|
+
`Error checking trace predicate for ${channelName}:`,
|
|
10781
|
+
error
|
|
10782
|
+
);
|
|
10783
|
+
return true;
|
|
10784
|
+
}
|
|
10785
|
+
}
|
|
10697
10786
|
function ensureSpanStateForEvent(states, config, event, channelName) {
|
|
10698
10787
|
const key = event;
|
|
10699
10788
|
const existing = states.get(key);
|
|
10700
10789
|
if (existing) {
|
|
10701
10790
|
return existing;
|
|
10702
10791
|
}
|
|
10792
|
+
if (!shouldTraceEvent(config, event, channelName)) {
|
|
10793
|
+
return void 0;
|
|
10794
|
+
}
|
|
10703
10795
|
const created = startSpanForEvent(config, event, channelName);
|
|
10704
10796
|
states.set(key, created);
|
|
10705
10797
|
return created;
|
|
@@ -10715,13 +10807,16 @@ function bindCurrentSpanStoreToStart(tracingChannel2, states, config, channelNam
|
|
|
10715
10807
|
startChannel.bindStore(
|
|
10716
10808
|
currentSpanStore,
|
|
10717
10809
|
(event) => {
|
|
10718
|
-
|
|
10810
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
10811
|
+
return currentSpanStore.getStore();
|
|
10812
|
+
}
|
|
10813
|
+
const spanState = ensureSpanStateForEvent(
|
|
10719
10814
|
states,
|
|
10720
10815
|
config,
|
|
10721
10816
|
event,
|
|
10722
10817
|
channelName
|
|
10723
|
-
)
|
|
10724
|
-
return contextManager.wrapSpanForStore(span);
|
|
10818
|
+
);
|
|
10819
|
+
return spanState ? contextManager.wrapSpanForStore(spanState.span) : currentSpanStore.getStore();
|
|
10725
10820
|
}
|
|
10726
10821
|
);
|
|
10727
10822
|
return () => {
|
|
@@ -10756,7 +10851,10 @@ function runStreamingCompletionHook(args) {
|
|
|
10756
10851
|
startTime: args.startTime
|
|
10757
10852
|
});
|
|
10758
10853
|
} catch (error) {
|
|
10759
|
-
|
|
10854
|
+
debugLogger.error(
|
|
10855
|
+
`Error in onComplete hook for ${args.channelName}:`,
|
|
10856
|
+
error
|
|
10857
|
+
);
|
|
10760
10858
|
}
|
|
10761
10859
|
}
|
|
10762
10860
|
function traceAsyncChannel(channel, config) {
|
|
@@ -10771,6 +10869,9 @@ function traceAsyncChannel(channel, config) {
|
|
|
10771
10869
|
);
|
|
10772
10870
|
const handlers = {
|
|
10773
10871
|
start: (event) => {
|
|
10872
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
10873
|
+
return;
|
|
10874
|
+
}
|
|
10774
10875
|
ensureSpanStateForEvent(
|
|
10775
10876
|
states,
|
|
10776
10877
|
config,
|
|
@@ -10805,7 +10906,7 @@ function traceAsyncChannel(channel, config) {
|
|
|
10805
10906
|
metrics
|
|
10806
10907
|
});
|
|
10807
10908
|
} catch (error) {
|
|
10808
|
-
|
|
10909
|
+
debugLogger.error(`Error extracting output for ${channelName}:`, error);
|
|
10809
10910
|
} finally {
|
|
10810
10911
|
span.end();
|
|
10811
10912
|
states.delete(event);
|
|
@@ -10833,6 +10934,9 @@ function traceStreamingChannel(channel, config) {
|
|
|
10833
10934
|
);
|
|
10834
10935
|
const handlers = {
|
|
10835
10936
|
start: (event) => {
|
|
10937
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
10938
|
+
return;
|
|
10939
|
+
}
|
|
10836
10940
|
ensureSpanStateForEvent(
|
|
10837
10941
|
states,
|
|
10838
10942
|
config,
|
|
@@ -10904,7 +11008,7 @@ function traceStreamingChannel(channel, config) {
|
|
|
10904
11008
|
metrics
|
|
10905
11009
|
});
|
|
10906
11010
|
} catch (error) {
|
|
10907
|
-
|
|
11011
|
+
debugLogger.error(
|
|
10908
11012
|
`Error extracting output for ${channelName}:`,
|
|
10909
11013
|
error
|
|
10910
11014
|
);
|
|
@@ -10964,7 +11068,7 @@ function traceStreamingChannel(channel, config) {
|
|
|
10964
11068
|
metrics
|
|
10965
11069
|
});
|
|
10966
11070
|
} catch (error) {
|
|
10967
|
-
|
|
11071
|
+
debugLogger.error(`Error extracting output for ${channelName}:`, error);
|
|
10968
11072
|
} finally {
|
|
10969
11073
|
span.end();
|
|
10970
11074
|
states.delete(event);
|
|
@@ -10992,6 +11096,9 @@ function traceSyncStreamChannel(channel, config) {
|
|
|
10992
11096
|
);
|
|
10993
11097
|
const handlers = {
|
|
10994
11098
|
start: (event) => {
|
|
11099
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
11100
|
+
return;
|
|
11101
|
+
}
|
|
10995
11102
|
ensureSpanStateForEvent(
|
|
10996
11103
|
states,
|
|
10997
11104
|
config,
|
|
@@ -11045,7 +11152,7 @@ function traceSyncStreamChannel(channel, config) {
|
|
|
11045
11152
|
});
|
|
11046
11153
|
}
|
|
11047
11154
|
} catch (error) {
|
|
11048
|
-
|
|
11155
|
+
debugLogger.error(
|
|
11049
11156
|
`Error extracting chatCompletion for ${channelName}:`,
|
|
11050
11157
|
error
|
|
11051
11158
|
);
|
|
@@ -11069,7 +11176,10 @@ function traceSyncStreamChannel(channel, config) {
|
|
|
11069
11176
|
span.log(extracted);
|
|
11070
11177
|
}
|
|
11071
11178
|
} catch (error) {
|
|
11072
|
-
|
|
11179
|
+
debugLogger.error(
|
|
11180
|
+
`Error extracting event for ${channelName}:`,
|
|
11181
|
+
error
|
|
11182
|
+
);
|
|
11073
11183
|
}
|
|
11074
11184
|
});
|
|
11075
11185
|
stream.on("end", () => {
|
|
@@ -12484,6 +12594,9 @@ var AnthropicPlugin = class extends BasePlugin {
|
|
|
12484
12594
|
const states = /* @__PURE__ */ new WeakMap();
|
|
12485
12595
|
const handlers = {
|
|
12486
12596
|
start: (event) => {
|
|
12597
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
12598
|
+
return;
|
|
12599
|
+
}
|
|
12487
12600
|
const params = event.arguments[0] ?? {};
|
|
12488
12601
|
const span = startSpan({
|
|
12489
12602
|
name: "anthropic.beta.messages.toolRunner",
|
|
@@ -13213,6 +13326,520 @@ function serializeAISDKToolsForLogging(tools) {
|
|
|
13213
13326
|
return serialized;
|
|
13214
13327
|
}
|
|
13215
13328
|
|
|
13329
|
+
// src/wrappers/ai-sdk/telemetry.ts
|
|
13330
|
+
function braintrustAISDKTelemetry() {
|
|
13331
|
+
const operations = /* @__PURE__ */ new Map();
|
|
13332
|
+
const modelSpans = /* @__PURE__ */ new Map();
|
|
13333
|
+
const objectSpans = /* @__PURE__ */ new Map();
|
|
13334
|
+
const embedSpans = /* @__PURE__ */ new Map();
|
|
13335
|
+
const rerankSpans = /* @__PURE__ */ new Map();
|
|
13336
|
+
const toolSpans = /* @__PURE__ */ new Map();
|
|
13337
|
+
const runSafely = (name, callback) => {
|
|
13338
|
+
try {
|
|
13339
|
+
callback();
|
|
13340
|
+
} catch (error) {
|
|
13341
|
+
console.error(`Error in Braintrust AI SDK telemetry ${name}:`, error);
|
|
13342
|
+
}
|
|
13343
|
+
};
|
|
13344
|
+
const startChildSpan = (callId, name, type, event) => {
|
|
13345
|
+
const parent = operations.get(callId)?.span;
|
|
13346
|
+
const spanArgs = {
|
|
13347
|
+
name,
|
|
13348
|
+
spanAttributes: { type },
|
|
13349
|
+
...event ? { event } : {}
|
|
13350
|
+
};
|
|
13351
|
+
const span = parent ? parent.startSpan(spanArgs) : startSpan(spanArgs);
|
|
13352
|
+
const state = operations.get(callId);
|
|
13353
|
+
if (state && type === "llm" /* LLM */) {
|
|
13354
|
+
state.hadModelChild = true;
|
|
13355
|
+
}
|
|
13356
|
+
return span;
|
|
13357
|
+
};
|
|
13358
|
+
return {
|
|
13359
|
+
onStart(event) {
|
|
13360
|
+
runSafely("onStart", () => {
|
|
13361
|
+
const operationName = operationNameFromId(event.operationId);
|
|
13362
|
+
const span = startSpan({
|
|
13363
|
+
name: operationName,
|
|
13364
|
+
spanAttributes: { type: "function" /* FUNCTION */ }
|
|
13365
|
+
});
|
|
13366
|
+
operations.set(event.callId, {
|
|
13367
|
+
hadModelChild: false,
|
|
13368
|
+
operationName,
|
|
13369
|
+
span,
|
|
13370
|
+
startTime: getCurrentUnixTimestamp()
|
|
13371
|
+
});
|
|
13372
|
+
const metadata = metadataFromEvent(event);
|
|
13373
|
+
const logPayload = { metadata };
|
|
13374
|
+
if (shouldRecordInputs(event)) {
|
|
13375
|
+
const { input, outputPromise } = processAISDKCallInput(
|
|
13376
|
+
operationInput(event, operationName)
|
|
13377
|
+
);
|
|
13378
|
+
logPayload.input = input;
|
|
13379
|
+
if (outputPromise && input && typeof input === "object") {
|
|
13380
|
+
outputPromise.then((resolvedData) => {
|
|
13381
|
+
span.log({
|
|
13382
|
+
input: {
|
|
13383
|
+
...input,
|
|
13384
|
+
...resolvedData
|
|
13385
|
+
}
|
|
13386
|
+
});
|
|
13387
|
+
}).catch(() => {
|
|
13388
|
+
});
|
|
13389
|
+
}
|
|
13390
|
+
}
|
|
13391
|
+
span.log(logPayload);
|
|
13392
|
+
});
|
|
13393
|
+
},
|
|
13394
|
+
onLanguageModelCallStart(event) {
|
|
13395
|
+
runSafely("onLanguageModelCallStart", () => {
|
|
13396
|
+
const state = operations.get(event.callId);
|
|
13397
|
+
const openSpans = modelSpans.get(event.callId);
|
|
13398
|
+
if (openSpans) {
|
|
13399
|
+
for (const span2 of openSpans) {
|
|
13400
|
+
span2.end();
|
|
13401
|
+
}
|
|
13402
|
+
modelSpans.delete(event.callId);
|
|
13403
|
+
}
|
|
13404
|
+
const span = startChildSpan(
|
|
13405
|
+
event.callId,
|
|
13406
|
+
state?.operationName === "streamText" ? "doStream" : "doGenerate",
|
|
13407
|
+
"llm" /* LLM */,
|
|
13408
|
+
{
|
|
13409
|
+
...shouldRecordInputs(event) ? {
|
|
13410
|
+
input: processAISDKCallInput(
|
|
13411
|
+
operationInput(
|
|
13412
|
+
event,
|
|
13413
|
+
state?.operationName ?? "generateText"
|
|
13414
|
+
)
|
|
13415
|
+
).input
|
|
13416
|
+
} : {},
|
|
13417
|
+
metadata: metadataFromEvent(event)
|
|
13418
|
+
}
|
|
13419
|
+
);
|
|
13420
|
+
const spans = modelSpans.get(event.callId) ?? [];
|
|
13421
|
+
spans.push(span);
|
|
13422
|
+
modelSpans.set(event.callId, spans);
|
|
13423
|
+
});
|
|
13424
|
+
},
|
|
13425
|
+
onLanguageModelCallEnd(event) {
|
|
13426
|
+
runSafely("onLanguageModelCallEnd", () => {
|
|
13427
|
+
const span = shiftModelSpan(modelSpans, event.callId);
|
|
13428
|
+
if (!span) {
|
|
13429
|
+
return;
|
|
13430
|
+
}
|
|
13431
|
+
const result = {
|
|
13432
|
+
...event,
|
|
13433
|
+
response: event.responseId ? { id: event.responseId } : void 0
|
|
13434
|
+
};
|
|
13435
|
+
span.log({
|
|
13436
|
+
...shouldRecordOutputs(event) ? {
|
|
13437
|
+
output: processAISDKOutput(result, DEFAULT_DENY_OUTPUT_PATHS)
|
|
13438
|
+
} : {},
|
|
13439
|
+
metrics: extractTokenMetrics(result)
|
|
13440
|
+
});
|
|
13441
|
+
span.end();
|
|
13442
|
+
});
|
|
13443
|
+
},
|
|
13444
|
+
onObjectStepStart(event) {
|
|
13445
|
+
runSafely("onObjectStepStart", () => {
|
|
13446
|
+
const state = operations.get(event.callId);
|
|
13447
|
+
const openSpan = objectSpans.get(event.callId);
|
|
13448
|
+
if (openSpan) {
|
|
13449
|
+
openSpan.end();
|
|
13450
|
+
objectSpans.delete(event.callId);
|
|
13451
|
+
}
|
|
13452
|
+
const span = startChildSpan(
|
|
13453
|
+
event.callId,
|
|
13454
|
+
state?.operationName === "streamObject" ? "doStream" : "doGenerate",
|
|
13455
|
+
"llm" /* LLM */,
|
|
13456
|
+
{
|
|
13457
|
+
...shouldRecordInputs(event) ? {
|
|
13458
|
+
input: {
|
|
13459
|
+
prompt: event.promptMessages
|
|
13460
|
+
}
|
|
13461
|
+
} : {},
|
|
13462
|
+
metadata: metadataFromEvent(event)
|
|
13463
|
+
}
|
|
13464
|
+
);
|
|
13465
|
+
objectSpans.set(event.callId, span);
|
|
13466
|
+
});
|
|
13467
|
+
},
|
|
13468
|
+
onObjectStepFinish(event) {
|
|
13469
|
+
runSafely("onObjectStepFinish", () => {
|
|
13470
|
+
const span = objectSpans.get(event.callId);
|
|
13471
|
+
if (!span) {
|
|
13472
|
+
return;
|
|
13473
|
+
}
|
|
13474
|
+
const result = {
|
|
13475
|
+
...event,
|
|
13476
|
+
text: event.objectText
|
|
13477
|
+
};
|
|
13478
|
+
span.log({
|
|
13479
|
+
...shouldRecordOutputs(event) ? {
|
|
13480
|
+
output: processAISDKOutput(result, DEFAULT_DENY_OUTPUT_PATHS)
|
|
13481
|
+
} : {},
|
|
13482
|
+
metrics: extractTokenMetrics(result)
|
|
13483
|
+
});
|
|
13484
|
+
span.end();
|
|
13485
|
+
objectSpans.delete(event.callId);
|
|
13486
|
+
});
|
|
13487
|
+
},
|
|
13488
|
+
onEmbedStart(event) {
|
|
13489
|
+
runSafely("onEmbedStart", () => {
|
|
13490
|
+
const state = operations.get(event.callId);
|
|
13491
|
+
for (const [embedCallId, embedState] of embedSpans) {
|
|
13492
|
+
if (embedState.callId === event.callId && (state?.operationName === "embed" || embedState.values === event.values)) {
|
|
13493
|
+
embedState.span.end();
|
|
13494
|
+
embedSpans.delete(embedCallId);
|
|
13495
|
+
}
|
|
13496
|
+
}
|
|
13497
|
+
const span = startChildSpan(
|
|
13498
|
+
event.callId,
|
|
13499
|
+
"doEmbed",
|
|
13500
|
+
"llm" /* LLM */,
|
|
13501
|
+
{
|
|
13502
|
+
...shouldRecordInputs(event) ? {
|
|
13503
|
+
input: {
|
|
13504
|
+
values: event.values
|
|
13505
|
+
}
|
|
13506
|
+
} : {},
|
|
13507
|
+
metadata: metadataFromEvent(event)
|
|
13508
|
+
}
|
|
13509
|
+
);
|
|
13510
|
+
embedSpans.set(event.embedCallId, {
|
|
13511
|
+
callId: event.callId,
|
|
13512
|
+
span,
|
|
13513
|
+
values: event.values
|
|
13514
|
+
});
|
|
13515
|
+
});
|
|
13516
|
+
},
|
|
13517
|
+
onEmbedFinish(event) {
|
|
13518
|
+
runSafely("onEmbedFinish", () => {
|
|
13519
|
+
const state = embedSpans.get(event.embedCallId);
|
|
13520
|
+
if (!state) {
|
|
13521
|
+
return;
|
|
13522
|
+
}
|
|
13523
|
+
const result = {
|
|
13524
|
+
...event,
|
|
13525
|
+
embeddings: event.embeddings
|
|
13526
|
+
};
|
|
13527
|
+
state.span.log({
|
|
13528
|
+
...shouldRecordOutputs(event) ? {
|
|
13529
|
+
output: processAISDKEmbeddingOutput(
|
|
13530
|
+
result,
|
|
13531
|
+
DEFAULT_DENY_OUTPUT_PATHS
|
|
13532
|
+
)
|
|
13533
|
+
} : {},
|
|
13534
|
+
metrics: extractTokenMetrics(result)
|
|
13535
|
+
});
|
|
13536
|
+
state.span.end();
|
|
13537
|
+
embedSpans.delete(event.embedCallId);
|
|
13538
|
+
});
|
|
13539
|
+
},
|
|
13540
|
+
onRerankStart(event) {
|
|
13541
|
+
runSafely("onRerankStart", () => {
|
|
13542
|
+
const openSpan = rerankSpans.get(event.callId);
|
|
13543
|
+
if (openSpan) {
|
|
13544
|
+
openSpan.end();
|
|
13545
|
+
rerankSpans.delete(event.callId);
|
|
13546
|
+
}
|
|
13547
|
+
const span = startChildSpan(
|
|
13548
|
+
event.callId,
|
|
13549
|
+
"doRerank",
|
|
13550
|
+
"llm" /* LLM */,
|
|
13551
|
+
{
|
|
13552
|
+
...shouldRecordInputs(event) ? {
|
|
13553
|
+
input: {
|
|
13554
|
+
documents: event.documents,
|
|
13555
|
+
query: event.query,
|
|
13556
|
+
topN: event.topN
|
|
13557
|
+
}
|
|
13558
|
+
} : {},
|
|
13559
|
+
metadata: metadataFromEvent(event)
|
|
13560
|
+
}
|
|
13561
|
+
);
|
|
13562
|
+
rerankSpans.set(event.callId, span);
|
|
13563
|
+
});
|
|
13564
|
+
},
|
|
13565
|
+
onRerankFinish(event) {
|
|
13566
|
+
runSafely("onRerankFinish", () => {
|
|
13567
|
+
const span = rerankSpans.get(event.callId);
|
|
13568
|
+
if (!span) {
|
|
13569
|
+
return;
|
|
13570
|
+
}
|
|
13571
|
+
const result = {
|
|
13572
|
+
ranking: event.ranking?.map((entry) => ({
|
|
13573
|
+
originalIndex: entry.index,
|
|
13574
|
+
score: entry.relevanceScore
|
|
13575
|
+
}))
|
|
13576
|
+
};
|
|
13577
|
+
span.log({
|
|
13578
|
+
...shouldRecordOutputs(event) ? {
|
|
13579
|
+
output: processAISDKRerankOutput(
|
|
13580
|
+
result,
|
|
13581
|
+
DEFAULT_DENY_OUTPUT_PATHS
|
|
13582
|
+
)
|
|
13583
|
+
} : {}
|
|
13584
|
+
});
|
|
13585
|
+
span.end();
|
|
13586
|
+
rerankSpans.delete(event.callId);
|
|
13587
|
+
});
|
|
13588
|
+
},
|
|
13589
|
+
onToolExecutionStart(event) {
|
|
13590
|
+
runSafely("onToolExecutionStart", () => {
|
|
13591
|
+
const toolCallId = event.toolCall.toolCallId;
|
|
13592
|
+
if (!toolCallId) {
|
|
13593
|
+
return;
|
|
13594
|
+
}
|
|
13595
|
+
const span = startChildSpan(
|
|
13596
|
+
event.callId,
|
|
13597
|
+
event.toolCall.toolName || "tool",
|
|
13598
|
+
"tool" /* TOOL */,
|
|
13599
|
+
{
|
|
13600
|
+
...shouldRecordInputs(event) ? {
|
|
13601
|
+
input: event.toolCall.input
|
|
13602
|
+
} : {},
|
|
13603
|
+
metadata: {
|
|
13604
|
+
...createAISDKIntegrationMetadata(),
|
|
13605
|
+
toolCallId,
|
|
13606
|
+
...typeof event.toolCall.toolName === "string" ? { toolName: event.toolCall.toolName } : {}
|
|
13607
|
+
}
|
|
13608
|
+
}
|
|
13609
|
+
);
|
|
13610
|
+
toolSpans.set(toolCallId, { callId: event.callId, span });
|
|
13611
|
+
});
|
|
13612
|
+
},
|
|
13613
|
+
onToolExecutionEnd(event) {
|
|
13614
|
+
runSafely("onToolExecutionEnd", () => {
|
|
13615
|
+
const toolCallId = event.toolCall.toolCallId;
|
|
13616
|
+
const state = toolCallId ? toolSpans.get(toolCallId) : void 0;
|
|
13617
|
+
if (!toolCallId || !state) {
|
|
13618
|
+
return;
|
|
13619
|
+
}
|
|
13620
|
+
const toolOutput = event.toolOutput;
|
|
13621
|
+
if (toolOutput?.type === "tool-error") {
|
|
13622
|
+
state.span.log({
|
|
13623
|
+
error: toolOutput.error instanceof Error ? toolOutput.error.message : String(toolOutput?.error),
|
|
13624
|
+
metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } : {}
|
|
13625
|
+
});
|
|
13626
|
+
} else {
|
|
13627
|
+
state.span.log({
|
|
13628
|
+
...shouldRecordOutputs(event) ? { output: toolOutput?.output } : {},
|
|
13629
|
+
metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } : {}
|
|
13630
|
+
});
|
|
13631
|
+
}
|
|
13632
|
+
state.span.end();
|
|
13633
|
+
toolSpans.delete(toolCallId);
|
|
13634
|
+
});
|
|
13635
|
+
},
|
|
13636
|
+
onChunk(event) {
|
|
13637
|
+
runSafely("onChunk", () => {
|
|
13638
|
+
const callId = event.chunk?.callId;
|
|
13639
|
+
if (!callId) {
|
|
13640
|
+
return;
|
|
13641
|
+
}
|
|
13642
|
+
const state = operations.get(callId);
|
|
13643
|
+
if (!state || state.firstChunkTime !== void 0) {
|
|
13644
|
+
return;
|
|
13645
|
+
}
|
|
13646
|
+
state.firstChunkTime = getCurrentUnixTimestamp();
|
|
13647
|
+
});
|
|
13648
|
+
},
|
|
13649
|
+
onFinish(event) {
|
|
13650
|
+
runSafely("onFinish", () => {
|
|
13651
|
+
const state = operations.get(event.callId);
|
|
13652
|
+
if (!state) {
|
|
13653
|
+
return;
|
|
13654
|
+
}
|
|
13655
|
+
const result = finishResult(event, state.operationName);
|
|
13656
|
+
const metrics = state.hadModelChild ? {} : extractTokenMetrics(result);
|
|
13657
|
+
if (state.firstChunkTime !== void 0) {
|
|
13658
|
+
metrics.time_to_first_token = state.firstChunkTime - state.startTime;
|
|
13659
|
+
}
|
|
13660
|
+
state.span.log({
|
|
13661
|
+
...shouldRecordOutputs(event) ? {
|
|
13662
|
+
output: finishOutput(result, state.operationName)
|
|
13663
|
+
} : {},
|
|
13664
|
+
metrics
|
|
13665
|
+
});
|
|
13666
|
+
state.span.end();
|
|
13667
|
+
operations.delete(event.callId);
|
|
13668
|
+
});
|
|
13669
|
+
},
|
|
13670
|
+
onError(event) {
|
|
13671
|
+
runSafely("onError", () => {
|
|
13672
|
+
const errorEvent = isObject(event) ? event : {};
|
|
13673
|
+
const callId = typeof errorEvent.callId === "string" ? errorEvent.callId : void 0;
|
|
13674
|
+
if (!callId) {
|
|
13675
|
+
return;
|
|
13676
|
+
}
|
|
13677
|
+
const state = operations.get(callId);
|
|
13678
|
+
if (!state) {
|
|
13679
|
+
return;
|
|
13680
|
+
}
|
|
13681
|
+
const error = errorEvent.error ?? event;
|
|
13682
|
+
const openModelSpans = modelSpans.get(callId);
|
|
13683
|
+
if (openModelSpans) {
|
|
13684
|
+
for (const span of openModelSpans) {
|
|
13685
|
+
logError(span, error);
|
|
13686
|
+
span.end();
|
|
13687
|
+
}
|
|
13688
|
+
modelSpans.delete(callId);
|
|
13689
|
+
}
|
|
13690
|
+
const openObjectSpan = objectSpans.get(callId);
|
|
13691
|
+
if (openObjectSpan) {
|
|
13692
|
+
logError(openObjectSpan, error);
|
|
13693
|
+
openObjectSpan.end();
|
|
13694
|
+
objectSpans.delete(callId);
|
|
13695
|
+
}
|
|
13696
|
+
for (const [embedCallId, embedState] of embedSpans) {
|
|
13697
|
+
if (embedState.callId === callId) {
|
|
13698
|
+
logError(embedState.span, error);
|
|
13699
|
+
embedState.span.end();
|
|
13700
|
+
embedSpans.delete(embedCallId);
|
|
13701
|
+
}
|
|
13702
|
+
}
|
|
13703
|
+
const openRerankSpan = rerankSpans.get(callId);
|
|
13704
|
+
if (openRerankSpan) {
|
|
13705
|
+
logError(openRerankSpan, error);
|
|
13706
|
+
openRerankSpan.end();
|
|
13707
|
+
rerankSpans.delete(callId);
|
|
13708
|
+
}
|
|
13709
|
+
for (const [toolCallId, toolState] of toolSpans) {
|
|
13710
|
+
if (toolState.callId === callId) {
|
|
13711
|
+
logError(toolState.span, error);
|
|
13712
|
+
toolState.span.end();
|
|
13713
|
+
toolSpans.delete(toolCallId);
|
|
13714
|
+
}
|
|
13715
|
+
}
|
|
13716
|
+
logError(state.span, error);
|
|
13717
|
+
state.span.end();
|
|
13718
|
+
operations.delete(callId);
|
|
13719
|
+
});
|
|
13720
|
+
},
|
|
13721
|
+
executeTool({ toolCallId, execute }) {
|
|
13722
|
+
const state = toolSpans.get(toolCallId);
|
|
13723
|
+
return state ? withCurrent(state.span, () => execute()) : execute();
|
|
13724
|
+
}
|
|
13725
|
+
};
|
|
13726
|
+
}
|
|
13727
|
+
function shouldRecordInputs(event) {
|
|
13728
|
+
return event.recordInputs !== false;
|
|
13729
|
+
}
|
|
13730
|
+
function shouldRecordOutputs(event) {
|
|
13731
|
+
return event.recordOutputs !== false;
|
|
13732
|
+
}
|
|
13733
|
+
function operationNameFromId(operationId) {
|
|
13734
|
+
return operationId?.startsWith("ai.") ? operationId.slice("ai.".length) : operationId || "ai-sdk";
|
|
13735
|
+
}
|
|
13736
|
+
function modelFromEvent(event) {
|
|
13737
|
+
return event.modelId ? {
|
|
13738
|
+
modelId: event.modelId,
|
|
13739
|
+
...event.provider ? { provider: event.provider } : {}
|
|
13740
|
+
} : void 0;
|
|
13741
|
+
}
|
|
13742
|
+
function metadataFromEvent(event) {
|
|
13743
|
+
const metadata = createAISDKIntegrationMetadata();
|
|
13744
|
+
const { model, provider } = serializeModelWithProvider(modelFromEvent(event));
|
|
13745
|
+
if (model) {
|
|
13746
|
+
metadata.model = model;
|
|
13747
|
+
}
|
|
13748
|
+
if (provider) {
|
|
13749
|
+
metadata.provider = provider;
|
|
13750
|
+
}
|
|
13751
|
+
if (typeof event.functionId === "string") {
|
|
13752
|
+
metadata.functionId = event.functionId;
|
|
13753
|
+
}
|
|
13754
|
+
return metadata;
|
|
13755
|
+
}
|
|
13756
|
+
function operationInput(event, operationName) {
|
|
13757
|
+
if (operationName === "embed") {
|
|
13758
|
+
return {
|
|
13759
|
+
model: modelFromEvent(event),
|
|
13760
|
+
value: event.value
|
|
13761
|
+
};
|
|
13762
|
+
}
|
|
13763
|
+
if (operationName === "embedMany") {
|
|
13764
|
+
return {
|
|
13765
|
+
model: modelFromEvent(event),
|
|
13766
|
+
values: Array.isArray(event.value) ? event.value ?? [] : void 0
|
|
13767
|
+
};
|
|
13768
|
+
}
|
|
13769
|
+
if (operationName === "rerank") {
|
|
13770
|
+
return {
|
|
13771
|
+
model: modelFromEvent(event),
|
|
13772
|
+
documents: event.documents,
|
|
13773
|
+
query: event.query,
|
|
13774
|
+
topN: event.topN
|
|
13775
|
+
};
|
|
13776
|
+
}
|
|
13777
|
+
return {
|
|
13778
|
+
model: modelFromEvent(event),
|
|
13779
|
+
system: event.system,
|
|
13780
|
+
prompt: event.prompt,
|
|
13781
|
+
messages: event.messages,
|
|
13782
|
+
tools: event.tools,
|
|
13783
|
+
toolChoice: event.toolChoice,
|
|
13784
|
+
activeTools: event.activeTools,
|
|
13785
|
+
output: event.output,
|
|
13786
|
+
schema: event.schema,
|
|
13787
|
+
schemaName: event.schemaName,
|
|
13788
|
+
schemaDescription: event.schemaDescription,
|
|
13789
|
+
maxOutputTokens: event.maxOutputTokens,
|
|
13790
|
+
temperature: event.temperature,
|
|
13791
|
+
topP: event.topP,
|
|
13792
|
+
topK: event.topK,
|
|
13793
|
+
presencePenalty: event.presencePenalty,
|
|
13794
|
+
frequencyPenalty: event.frequencyPenalty,
|
|
13795
|
+
seed: event.seed,
|
|
13796
|
+
maxRetries: event.maxRetries,
|
|
13797
|
+
headers: event.headers,
|
|
13798
|
+
providerOptions: event.providerOptions
|
|
13799
|
+
};
|
|
13800
|
+
}
|
|
13801
|
+
function shiftModelSpan(modelSpans, callId) {
|
|
13802
|
+
const spans = modelSpans.get(callId);
|
|
13803
|
+
const span = spans?.shift();
|
|
13804
|
+
if (spans && spans.length === 0) {
|
|
13805
|
+
modelSpans.delete(callId);
|
|
13806
|
+
}
|
|
13807
|
+
return span;
|
|
13808
|
+
}
|
|
13809
|
+
function finishResult(event, operationName) {
|
|
13810
|
+
if (operationName === "embed") {
|
|
13811
|
+
return {
|
|
13812
|
+
...event,
|
|
13813
|
+
embedding: event.embedding
|
|
13814
|
+
};
|
|
13815
|
+
}
|
|
13816
|
+
if (operationName === "embedMany") {
|
|
13817
|
+
return {
|
|
13818
|
+
...event,
|
|
13819
|
+
embeddings: event.embedding
|
|
13820
|
+
};
|
|
13821
|
+
}
|
|
13822
|
+
if (operationName === "rerank") {
|
|
13823
|
+
return event;
|
|
13824
|
+
}
|
|
13825
|
+
return event;
|
|
13826
|
+
}
|
|
13827
|
+
function finishOutput(result, operationName) {
|
|
13828
|
+
if (operationName === "embed" || operationName === "embedMany") {
|
|
13829
|
+
return processAISDKEmbeddingOutput(
|
|
13830
|
+
result,
|
|
13831
|
+
DEFAULT_DENY_OUTPUT_PATHS
|
|
13832
|
+
);
|
|
13833
|
+
}
|
|
13834
|
+
if (operationName === "rerank") {
|
|
13835
|
+
return processAISDKRerankOutput(
|
|
13836
|
+
result,
|
|
13837
|
+
DEFAULT_DENY_OUTPUT_PATHS
|
|
13838
|
+
);
|
|
13839
|
+
}
|
|
13840
|
+
return processAISDKOutput(result, DEFAULT_DENY_OUTPUT_PATHS);
|
|
13841
|
+
}
|
|
13842
|
+
|
|
13216
13843
|
// src/instrumentation/plugins/ai-sdk-plugin.ts
|
|
13217
13844
|
var DEFAULT_DENY_OUTPUT_PATHS = [
|
|
13218
13845
|
// v3
|
|
@@ -13230,9 +13857,30 @@ var DEFAULT_DENY_OUTPUT_PATHS = [
|
|
|
13230
13857
|
];
|
|
13231
13858
|
var AUTO_PATCHED_MODEL = /* @__PURE__ */ Symbol.for("braintrust.ai-sdk.auto-patched-model");
|
|
13232
13859
|
var AUTO_PATCHED_TOOL = /* @__PURE__ */ Symbol.for("braintrust.ai-sdk.auto-patched-tool");
|
|
13860
|
+
var AUTO_PATCHED_V7_TELEMETRY_DISPATCHER = /* @__PURE__ */ Symbol.for(
|
|
13861
|
+
"braintrust.ai-sdk.v7.auto-patched-telemetry-dispatcher"
|
|
13862
|
+
);
|
|
13233
13863
|
var RUNTIME_DENY_OUTPUT_PATHS = /* @__PURE__ */ Symbol.for(
|
|
13234
13864
|
"braintrust.ai-sdk.deny-output-paths"
|
|
13235
13865
|
);
|
|
13866
|
+
var AI_SDK_V7_TELEMETRY_CALLBACKS = [
|
|
13867
|
+
"onStart",
|
|
13868
|
+
"onStepStart",
|
|
13869
|
+
"onLanguageModelCallStart",
|
|
13870
|
+
"onLanguageModelCallEnd",
|
|
13871
|
+
"onToolExecutionStart",
|
|
13872
|
+
"onToolExecutionEnd",
|
|
13873
|
+
"onChunk",
|
|
13874
|
+
"onStepFinish",
|
|
13875
|
+
"onObjectStepStart",
|
|
13876
|
+
"onObjectStepFinish",
|
|
13877
|
+
"onEmbedStart",
|
|
13878
|
+
"onEmbedFinish",
|
|
13879
|
+
"onRerankStart",
|
|
13880
|
+
"onRerankFinish",
|
|
13881
|
+
"onFinish",
|
|
13882
|
+
"onError"
|
|
13883
|
+
];
|
|
13236
13884
|
var AISDKPlugin = class extends BasePlugin {
|
|
13237
13885
|
config;
|
|
13238
13886
|
constructor(config = {}) {
|
|
@@ -13247,6 +13895,7 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
13247
13895
|
}
|
|
13248
13896
|
subscribeToAISDK() {
|
|
13249
13897
|
const denyOutputPaths = this.config.denyOutputPaths || DEFAULT_DENY_OUTPUT_PATHS;
|
|
13898
|
+
this.unsubscribers.push(subscribeToAISDKV7TelemetryDispatcher());
|
|
13250
13899
|
this.unsubscribers.push(
|
|
13251
13900
|
traceStreamingChannel(aiSDKChannels.generateText, {
|
|
13252
13901
|
name: "generateText",
|
|
@@ -13471,6 +14120,57 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
13471
14120
|
);
|
|
13472
14121
|
}
|
|
13473
14122
|
};
|
|
14123
|
+
function subscribeToAISDKV7TelemetryDispatcher() {
|
|
14124
|
+
const channel = aiSDKChannels.v7CreateTelemetryDispatcher.tracingChannel();
|
|
14125
|
+
const telemetry = braintrustAISDKTelemetry();
|
|
14126
|
+
const handlers = {
|
|
14127
|
+
end: (event) => {
|
|
14128
|
+
const telemetryOptions = event.arguments?.[0]?.telemetry;
|
|
14129
|
+
if (telemetryOptions?.isEnabled === false) {
|
|
14130
|
+
return;
|
|
14131
|
+
}
|
|
14132
|
+
patchAISDKV7TelemetryDispatcher(event.result, telemetry);
|
|
14133
|
+
}
|
|
14134
|
+
};
|
|
14135
|
+
channel.subscribe(handlers);
|
|
14136
|
+
return () => {
|
|
14137
|
+
channel.unsubscribe(handlers);
|
|
14138
|
+
};
|
|
14139
|
+
}
|
|
14140
|
+
function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry) {
|
|
14141
|
+
if (!isObject(dispatcher)) {
|
|
14142
|
+
return;
|
|
14143
|
+
}
|
|
14144
|
+
const dispatcherRecord = dispatcher;
|
|
14145
|
+
if (dispatcherRecord[AUTO_PATCHED_V7_TELEMETRY_DISPATCHER]) {
|
|
14146
|
+
return;
|
|
14147
|
+
}
|
|
14148
|
+
dispatcherRecord[AUTO_PATCHED_V7_TELEMETRY_DISPATCHER] = true;
|
|
14149
|
+
for (const key of AI_SDK_V7_TELEMETRY_CALLBACKS) {
|
|
14150
|
+
const braintrustCallback = telemetry[key];
|
|
14151
|
+
if (typeof braintrustCallback !== "function") {
|
|
14152
|
+
continue;
|
|
14153
|
+
}
|
|
14154
|
+
const existingCallback = dispatcherRecord[key];
|
|
14155
|
+
dispatcherRecord[key] = (event) => {
|
|
14156
|
+
const existingResult = typeof existingCallback === "function" ? existingCallback.call(dispatcher, event) : void 0;
|
|
14157
|
+
const braintrustResult = braintrustCallback.call(telemetry, event);
|
|
14158
|
+
const pending = [existingResult, braintrustResult].filter(isPromiseLike);
|
|
14159
|
+
if (pending.length > 0) {
|
|
14160
|
+
return Promise.allSettled(pending).then(() => void 0);
|
|
14161
|
+
}
|
|
14162
|
+
};
|
|
14163
|
+
}
|
|
14164
|
+
const braintrustExecuteTool = telemetry.executeTool;
|
|
14165
|
+
if (typeof braintrustExecuteTool !== "function") {
|
|
14166
|
+
return;
|
|
14167
|
+
}
|
|
14168
|
+
const existingExecuteTool = dispatcherRecord.executeTool;
|
|
14169
|
+
dispatcherRecord.executeTool = (args) => braintrustExecuteTool.call(telemetry, {
|
|
14170
|
+
...args,
|
|
14171
|
+
execute: () => typeof existingExecuteTool === "function" ? existingExecuteTool.call(dispatcher, args) : args.execute()
|
|
14172
|
+
});
|
|
14173
|
+
}
|
|
13474
14174
|
function resolveDenyOutputPaths(event, defaultDenyOutputPaths) {
|
|
13475
14175
|
if (Array.isArray(event?.denyOutputPaths)) {
|
|
13476
14176
|
return event.denyOutputPaths;
|
|
@@ -13922,11 +14622,11 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
|
|
|
13922
14622
|
metadata: baseMetadata
|
|
13923
14623
|
}
|
|
13924
14624
|
});
|
|
14625
|
+
const streamStartTime = getCurrentUnixTimestamp();
|
|
13925
14626
|
const result = await withCurrent(
|
|
13926
14627
|
span,
|
|
13927
14628
|
() => Reflect.apply(originalDoStream, resolvedModel, [options])
|
|
13928
14629
|
);
|
|
13929
|
-
const streamStartTime = getCurrentUnixTimestamp();
|
|
13930
14630
|
let firstChunkTime;
|
|
13931
14631
|
const output = {};
|
|
13932
14632
|
let text = "";
|
|
@@ -13935,7 +14635,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
|
|
|
13935
14635
|
let object = void 0;
|
|
13936
14636
|
const transformStream = new TransformStream({
|
|
13937
14637
|
transform(chunk, controller) {
|
|
13938
|
-
if (firstChunkTime === void 0) {
|
|
14638
|
+
if (firstChunkTime === void 0 && isAISDKContentStreamChunk(chunk)) {
|
|
13939
14639
|
firstChunkTime = getCurrentUnixTimestamp();
|
|
13940
14640
|
}
|
|
13941
14641
|
switch (chunk.type) {
|
|
@@ -14127,6 +14827,78 @@ function finalizeAISDKChildTracing(event) {
|
|
|
14127
14827
|
delete event.__braintrust_ai_sdk_cleanup;
|
|
14128
14828
|
}
|
|
14129
14829
|
}
|
|
14830
|
+
function extractAISDKStreamPart(chunk) {
|
|
14831
|
+
if (!isObject(chunk) || !isObject(chunk.part)) {
|
|
14832
|
+
return chunk;
|
|
14833
|
+
}
|
|
14834
|
+
return chunk.part;
|
|
14835
|
+
}
|
|
14836
|
+
function stringContent(value) {
|
|
14837
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
14838
|
+
}
|
|
14839
|
+
function rawValueHasAISDKContent(value) {
|
|
14840
|
+
if (value === void 0 || value === null) {
|
|
14841
|
+
return false;
|
|
14842
|
+
}
|
|
14843
|
+
if (typeof value === "string") {
|
|
14844
|
+
return value.length > 0;
|
|
14845
|
+
}
|
|
14846
|
+
if (!isObject(value)) {
|
|
14847
|
+
return true;
|
|
14848
|
+
}
|
|
14849
|
+
const delta = value.delta;
|
|
14850
|
+
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) => {
|
|
14851
|
+
if (!isObject(choice) || !isObject(choice.delta)) {
|
|
14852
|
+
return false;
|
|
14853
|
+
}
|
|
14854
|
+
const choiceDelta = choice.delta;
|
|
14855
|
+
if (stringContent(choiceDelta.content) || stringContent(choiceDelta.text)) {
|
|
14856
|
+
return true;
|
|
14857
|
+
}
|
|
14858
|
+
if (isObject(choiceDelta.function_call) && stringContent(choiceDelta.function_call.arguments)) {
|
|
14859
|
+
return true;
|
|
14860
|
+
}
|
|
14861
|
+
return Array.isArray(choiceDelta.tool_calls) && choiceDelta.tool_calls.some(
|
|
14862
|
+
(toolCall) => isObject(toolCall) && isObject(toolCall.function) && stringContent(toolCall.function.arguments)
|
|
14863
|
+
);
|
|
14864
|
+
})) {
|
|
14865
|
+
return true;
|
|
14866
|
+
}
|
|
14867
|
+
return false;
|
|
14868
|
+
}
|
|
14869
|
+
function isAISDKContentStreamChunk(chunk) {
|
|
14870
|
+
const part = extractAISDKStreamPart(chunk);
|
|
14871
|
+
if (typeof part === "string") {
|
|
14872
|
+
return part.length > 0;
|
|
14873
|
+
}
|
|
14874
|
+
if (!isObject(part) || typeof part.type !== "string") {
|
|
14875
|
+
return false;
|
|
14876
|
+
}
|
|
14877
|
+
switch (part.type) {
|
|
14878
|
+
case "text-delta":
|
|
14879
|
+
return stringContent(part.textDelta) !== void 0 || stringContent(part.delta) !== void 0 || stringContent(part.text) !== void 0 || stringContent(part.content) !== void 0;
|
|
14880
|
+
case "reasoning-delta":
|
|
14881
|
+
return stringContent(part.delta) !== void 0 || stringContent(part.text) !== void 0 || stringContent(part.content) !== void 0;
|
|
14882
|
+
case "tool-call":
|
|
14883
|
+
case "object":
|
|
14884
|
+
case "file":
|
|
14885
|
+
return true;
|
|
14886
|
+
case "tool-input-delta":
|
|
14887
|
+
case "tool-call-delta":
|
|
14888
|
+
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;
|
|
14889
|
+
case "raw":
|
|
14890
|
+
return rawValueHasAISDKContent(part.rawValue);
|
|
14891
|
+
default:
|
|
14892
|
+
return false;
|
|
14893
|
+
}
|
|
14894
|
+
}
|
|
14895
|
+
function isAISDKContentAsyncIterableChunk(chunk) {
|
|
14896
|
+
if (isAISDKContentStreamChunk(chunk)) {
|
|
14897
|
+
return true;
|
|
14898
|
+
}
|
|
14899
|
+
const part = extractAISDKStreamPart(chunk);
|
|
14900
|
+
return isObject(part) && typeof part.type !== "string";
|
|
14901
|
+
}
|
|
14130
14902
|
function patchAISDKStreamingResult(args) {
|
|
14131
14903
|
const { defaultDenyOutputPaths, endEvent, result, span, startTime } = args;
|
|
14132
14904
|
if (!result || typeof result !== "object") {
|
|
@@ -14139,7 +14911,7 @@ function patchAISDKStreamingResult(args) {
|
|
|
14139
14911
|
const wrappedBaseStream = resultRecord.baseStream.pipeThrough(
|
|
14140
14912
|
new TransformStream({
|
|
14141
14913
|
transform(chunk, controller) {
|
|
14142
|
-
if (firstChunkTime2 === void 0) {
|
|
14914
|
+
if (firstChunkTime2 === void 0 && isAISDKContentStreamChunk(chunk)) {
|
|
14143
14915
|
firstChunkTime2 = getCurrentUnixTimestamp();
|
|
14144
14916
|
}
|
|
14145
14917
|
controller.enqueue(chunk);
|
|
@@ -14183,8 +14955,8 @@ function patchAISDKStreamingResult(args) {
|
|
|
14183
14955
|
}
|
|
14184
14956
|
let firstChunkTime;
|
|
14185
14957
|
const wrappedStream = createPatchedAsyncIterable(streamField.stream, {
|
|
14186
|
-
onChunk: () => {
|
|
14187
|
-
if (firstChunkTime === void 0) {
|
|
14958
|
+
onChunk: (chunk) => {
|
|
14959
|
+
if (firstChunkTime === void 0 && isAISDKContentAsyncIterableChunk(chunk)) {
|
|
14188
14960
|
firstChunkTime = getCurrentUnixTimestamp();
|
|
14189
14961
|
}
|
|
14190
14962
|
},
|
|
@@ -15145,15 +15917,17 @@ function collectLocalMcpServerToolHookNames(serverName, serverConfig) {
|
|
|
15145
15917
|
|
|
15146
15918
|
// src/instrumentation/plugins/claude-agent-sdk-plugin.ts
|
|
15147
15919
|
var ROOT_LLM_PARENT_KEY = "__root__";
|
|
15920
|
+
var SUB_AGENT_PROMPT_SOURCE_PRIORITY = {
|
|
15921
|
+
delegation: 0,
|
|
15922
|
+
lifecycle: 1,
|
|
15923
|
+
sidechain: 2
|
|
15924
|
+
};
|
|
15148
15925
|
function llmParentKey(parentToolUseId) {
|
|
15149
15926
|
return parentToolUseId ?? ROOT_LLM_PARENT_KEY;
|
|
15150
15927
|
}
|
|
15151
15928
|
function isSubAgentDelegationToolName(toolName) {
|
|
15152
15929
|
return toolName === "Agent" || toolName === "Task";
|
|
15153
15930
|
}
|
|
15154
|
-
function shouldParentToolAsTaskSibling(toolName) {
|
|
15155
|
-
return toolName === "Agent" || toolName === "Task" || toolName === "Bash";
|
|
15156
|
-
}
|
|
15157
15931
|
function filterSerializableOptions(options) {
|
|
15158
15932
|
const allowedKeys = [
|
|
15159
15933
|
"model",
|
|
@@ -15290,26 +16064,39 @@ function extractUsageFromMessage(message) {
|
|
|
15290
16064
|
}
|
|
15291
16065
|
return metrics;
|
|
15292
16066
|
}
|
|
15293
|
-
function buildLLMInput(
|
|
15294
|
-
const promptMessages = [];
|
|
15295
|
-
if (typeof prompt === "string") {
|
|
15296
|
-
promptMessages.push({ content: prompt, role: "user" });
|
|
15297
|
-
} else if (capturedPromptMessages && capturedPromptMessages.length > 0) {
|
|
15298
|
-
for (const msg of capturedPromptMessages) {
|
|
15299
|
-
const role = msg.message?.role;
|
|
15300
|
-
const content = msg.message?.content;
|
|
15301
|
-
if (role && content !== void 0) {
|
|
15302
|
-
promptMessages.push({ content, role });
|
|
15303
|
-
}
|
|
15304
|
-
}
|
|
15305
|
-
}
|
|
16067
|
+
function buildLLMInput(promptMessages, conversationHistory) {
|
|
15306
16068
|
const inputParts = [...promptMessages, ...conversationHistory];
|
|
15307
16069
|
return inputParts.length > 0 ? inputParts : void 0;
|
|
15308
16070
|
}
|
|
16071
|
+
function conversationMessageFromSDKMessage(message) {
|
|
16072
|
+
const role = message.message?.role;
|
|
16073
|
+
const content = message.message?.content;
|
|
16074
|
+
if (role && content !== void 0) {
|
|
16075
|
+
return { content, role };
|
|
16076
|
+
}
|
|
16077
|
+
return void 0;
|
|
16078
|
+
}
|
|
16079
|
+
function messageContentHasBlockType(message, blockType) {
|
|
16080
|
+
const content = message.message?.content;
|
|
16081
|
+
return Array.isArray(content) && content.some(
|
|
16082
|
+
(block) => typeof block === "object" && block !== null && "type" in block && block.type === blockType
|
|
16083
|
+
);
|
|
16084
|
+
}
|
|
16085
|
+
function buildRootPromptMessages(prompt, capturedPromptMessages) {
|
|
16086
|
+
if (typeof prompt === "string") {
|
|
16087
|
+
return [{ content: prompt, role: "user" }];
|
|
16088
|
+
}
|
|
16089
|
+
if (!capturedPromptMessages || capturedPromptMessages.length === 0) {
|
|
16090
|
+
return [];
|
|
16091
|
+
}
|
|
16092
|
+
return capturedPromptMessages.map(conversationMessageFromSDKMessage).filter(
|
|
16093
|
+
(message) => message !== void 0
|
|
16094
|
+
);
|
|
16095
|
+
}
|
|
15309
16096
|
function formatCapturedMessages(messages) {
|
|
15310
16097
|
return messages.length > 0 ? messages : [];
|
|
15311
16098
|
}
|
|
15312
|
-
async function createLLMSpanForMessages(messages,
|
|
16099
|
+
async function createLLMSpanForMessages(messages, promptMessages, conversationHistory, options, startTime, parentSpan, existingSpan) {
|
|
15313
16100
|
if (messages.length === 0) {
|
|
15314
16101
|
return void 0;
|
|
15315
16102
|
}
|
|
@@ -15319,11 +16106,7 @@ async function createLLMSpanForMessages(messages, prompt, conversationHistory, o
|
|
|
15319
16106
|
}
|
|
15320
16107
|
const model = lastMessage.message.model || options.model;
|
|
15321
16108
|
const usage = extractUsageFromMessage(lastMessage);
|
|
15322
|
-
const input = buildLLMInput(
|
|
15323
|
-
prompt,
|
|
15324
|
-
conversationHistory,
|
|
15325
|
-
capturedPromptMessages
|
|
15326
|
-
);
|
|
16109
|
+
const input = buildLLMInput(promptMessages, conversationHistory);
|
|
15327
16110
|
const outputs = messages.map(
|
|
15328
16111
|
(m) => m.message?.content && m.message?.role ? { content: m.message.content, role: m.message.role } : void 0
|
|
15329
16112
|
).filter(
|
|
@@ -15454,8 +16237,7 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
|
|
|
15454
16237
|
},
|
|
15455
16238
|
name: parsed.displayName,
|
|
15456
16239
|
parent: await resolveParentSpan(toolUseID, {
|
|
15457
|
-
agentId: input.agent_id
|
|
15458
|
-
preferTaskSiblingParent: shouldParentToolAsTaskSibling(parsed.toolName)
|
|
16240
|
+
agentId: input.agent_id
|
|
15459
16241
|
}),
|
|
15460
16242
|
spanAttributes: { type: "tool" /* TOOL */ }
|
|
15461
16243
|
});
|
|
@@ -15701,12 +16483,37 @@ function injectTracingHooks(options, resolveParentSpan, activeToolSpans, localTo
|
|
|
15701
16483
|
}
|
|
15702
16484
|
};
|
|
15703
16485
|
}
|
|
16486
|
+
function setSubAgentPromptMessages(state, parentToolUseId, promptMessages, source) {
|
|
16487
|
+
if (promptMessages.length === 0) {
|
|
16488
|
+
return;
|
|
16489
|
+
}
|
|
16490
|
+
const parentKey = llmParentKey(parentToolUseId);
|
|
16491
|
+
const sourcePriority = SUB_AGENT_PROMPT_SOURCE_PRIORITY[source];
|
|
16492
|
+
const currentPriority = state.promptSourcePriorityByParentKey.get(parentKey) ?? -1;
|
|
16493
|
+
if (sourcePriority > currentPriority) {
|
|
16494
|
+
state.promptMessagesByParentKey.set(parentKey, promptMessages);
|
|
16495
|
+
state.promptSourcePriorityByParentKey.set(parentKey, sourcePriority);
|
|
16496
|
+
}
|
|
16497
|
+
}
|
|
16498
|
+
function getConversationHistory(state, parentKey) {
|
|
16499
|
+
let conversationHistory = state.conversationHistoryByParentKey.get(parentKey);
|
|
16500
|
+
if (!conversationHistory) {
|
|
16501
|
+
conversationHistory = [];
|
|
16502
|
+
state.conversationHistoryByParentKey.set(parentKey, conversationHistory);
|
|
16503
|
+
}
|
|
16504
|
+
return conversationHistory;
|
|
16505
|
+
}
|
|
15704
16506
|
async function finalizeCurrentMessageGroup(state) {
|
|
15705
16507
|
if (state.currentMessages.length === 0) {
|
|
15706
16508
|
return;
|
|
15707
16509
|
}
|
|
15708
16510
|
const parentToolUseId = state.currentMessages[0]?.parent_tool_use_id ?? null;
|
|
15709
16511
|
const parentKey = llmParentKey(parentToolUseId);
|
|
16512
|
+
const conversationHistory = getConversationHistory(state, parentKey);
|
|
16513
|
+
const promptMessages = parentToolUseId ? state.promptMessagesByParentKey.get(parentKey) ?? [] : buildRootPromptMessages(
|
|
16514
|
+
state.originalPrompt,
|
|
16515
|
+
state.capturedPromptMessages
|
|
16516
|
+
);
|
|
15710
16517
|
let parentSpan = await state.span.export();
|
|
15711
16518
|
if (parentToolUseId) {
|
|
15712
16519
|
const subAgentSpan = state.subAgentSpans.get(parentToolUseId);
|
|
@@ -15717,11 +16524,10 @@ async function finalizeCurrentMessageGroup(state) {
|
|
|
15717
16524
|
const existingLlmSpan = state.activeLlmSpansByParentToolUse.get(parentKey);
|
|
15718
16525
|
const llmSpanResult = await createLLMSpanForMessages(
|
|
15719
16526
|
state.currentMessages,
|
|
15720
|
-
|
|
15721
|
-
|
|
16527
|
+
promptMessages,
|
|
16528
|
+
conversationHistory,
|
|
15722
16529
|
state.options,
|
|
15723
16530
|
state.currentMessageStartTime,
|
|
15724
|
-
state.capturedPromptMessages,
|
|
15725
16531
|
parentSpan,
|
|
15726
16532
|
existingLlmSpan
|
|
15727
16533
|
);
|
|
@@ -15735,6 +16541,7 @@ async function finalizeCurrentMessageGroup(state) {
|
|
|
15735
16541
|
state.latestRootLlmParentRef.value = llmSpanResult.spanExport;
|
|
15736
16542
|
}
|
|
15737
16543
|
if (llmSpanResult.finalMessage) {
|
|
16544
|
+
conversationHistory.push(llmSpanResult.finalMessage);
|
|
15738
16545
|
state.finalResults.push(llmSpanResult.finalMessage);
|
|
15739
16546
|
}
|
|
15740
16547
|
}
|
|
@@ -15762,6 +16569,15 @@ function maybeTrackToolUseContext(state, message) {
|
|
|
15762
16569
|
description: getStringProperty(block.input, "description"),
|
|
15763
16570
|
toolUseId: block.id
|
|
15764
16571
|
});
|
|
16572
|
+
const prompt = getStringProperty(block.input, "prompt");
|
|
16573
|
+
if (prompt) {
|
|
16574
|
+
setSubAgentPromptMessages(
|
|
16575
|
+
state,
|
|
16576
|
+
block.id,
|
|
16577
|
+
[{ content: prompt, role: "user" }],
|
|
16578
|
+
"delegation"
|
|
16579
|
+
);
|
|
16580
|
+
}
|
|
15765
16581
|
}
|
|
15766
16582
|
}
|
|
15767
16583
|
}
|
|
@@ -15880,6 +16696,14 @@ async function maybeHandleTaskLifecycleMessage(state, message) {
|
|
|
15880
16696
|
};
|
|
15881
16697
|
if (message.subtype === "task_started") {
|
|
15882
16698
|
const prompt = getStringProperty(message, "prompt");
|
|
16699
|
+
if (prompt) {
|
|
16700
|
+
setSubAgentPromptMessages(
|
|
16701
|
+
state,
|
|
16702
|
+
toolUseId,
|
|
16703
|
+
[{ content: prompt, role: "user" }],
|
|
16704
|
+
"lifecycle"
|
|
16705
|
+
);
|
|
16706
|
+
}
|
|
15883
16707
|
subAgentSpan.log({
|
|
15884
16708
|
input: prompt,
|
|
15885
16709
|
metadata
|
|
@@ -15930,6 +16754,28 @@ async function handleStreamMessage(state, message) {
|
|
|
15930
16754
|
return;
|
|
15931
16755
|
}
|
|
15932
16756
|
await maybeStartSubAgentSpan(state, message);
|
|
16757
|
+
const messageParentToolUseId = message.parent_tool_use_id;
|
|
16758
|
+
if (messageParentToolUseId && message.type === "user") {
|
|
16759
|
+
const conversationMessage = conversationMessageFromSDKMessage(message);
|
|
16760
|
+
if (conversationMessage?.role === "user") {
|
|
16761
|
+
await finalizeCurrentMessageGroup(state);
|
|
16762
|
+
const parentKey = llmParentKey(messageParentToolUseId);
|
|
16763
|
+
const conversationHistory = getConversationHistory(state, parentKey);
|
|
16764
|
+
const currentPromptSourcePriority = state.promptSourcePriorityByParentKey.get(parentKey) ?? -1;
|
|
16765
|
+
const canUseAsInitialSidechainPrompt = conversationHistory.length === 0 && currentPromptSourcePriority < SUB_AGENT_PROMPT_SOURCE_PRIORITY.sidechain && !messageContentHasBlockType(message, "tool_result");
|
|
16766
|
+
if (!canUseAsInitialSidechainPrompt) {
|
|
16767
|
+
conversationHistory.push(conversationMessage);
|
|
16768
|
+
return;
|
|
16769
|
+
}
|
|
16770
|
+
setSubAgentPromptMessages(
|
|
16771
|
+
state,
|
|
16772
|
+
messageParentToolUseId,
|
|
16773
|
+
[conversationMessage],
|
|
16774
|
+
"sidechain"
|
|
16775
|
+
);
|
|
16776
|
+
return;
|
|
16777
|
+
}
|
|
16778
|
+
}
|
|
15933
16779
|
const messageId = message.message?.id;
|
|
15934
16780
|
if (messageId && messageId !== state.currentMessageId) {
|
|
15935
16781
|
await finalizeCurrentMessageGroup(state);
|
|
@@ -16081,6 +16927,7 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
16081
16927
|
}
|
|
16082
16928
|
const activeToolSpans = /* @__PURE__ */ new Map();
|
|
16083
16929
|
const activeLlmSpansByParentToolUse = /* @__PURE__ */ new Map();
|
|
16930
|
+
const conversationHistoryByParentKey = /* @__PURE__ */ new Map();
|
|
16084
16931
|
const subAgentSpans = /* @__PURE__ */ new Map();
|
|
16085
16932
|
const endedSubAgentSpans = /* @__PURE__ */ new Set();
|
|
16086
16933
|
const toolUseToParent = /* @__PURE__ */ new Map();
|
|
@@ -16090,6 +16937,8 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
16090
16937
|
};
|
|
16091
16938
|
const subAgentDetailsByToolUseId = /* @__PURE__ */ new Map();
|
|
16092
16939
|
const taskIdToToolUseId = /* @__PURE__ */ new Map();
|
|
16940
|
+
const promptMessagesByParentKey = /* @__PURE__ */ new Map();
|
|
16941
|
+
const promptSourcePriorityByParentKey = /* @__PURE__ */ new Map();
|
|
16093
16942
|
const localToolContext = createClaudeLocalToolContext();
|
|
16094
16943
|
const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
|
|
16095
16944
|
const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
|
|
@@ -16098,38 +16947,19 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
16098
16947
|
const parentToolUseId = trackedParentToolUseId ?? (context?.agentId ? taskIdToToolUseId.get(context.agentId) ?? null : null);
|
|
16099
16948
|
const parentKey = llmParentKey(parentToolUseId);
|
|
16100
16949
|
const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
|
|
16101
|
-
|
|
16102
|
-
|
|
16103
|
-
|
|
16104
|
-
|
|
16105
|
-
|
|
16106
|
-
|
|
16107
|
-
|
|
16108
|
-
|
|
16109
|
-
|
|
16110
|
-
|
|
16111
|
-
|
|
16112
|
-
}
|
|
16113
|
-
if (parentToolUseId) {
|
|
16114
|
-
const subAgentSpan = await ensureSubAgentSpan(
|
|
16115
|
-
subAgentDetailsByToolUseId,
|
|
16116
|
-
span,
|
|
16117
|
-
activeToolSpans,
|
|
16118
|
-
subAgentSpans,
|
|
16119
|
-
parentToolUseId
|
|
16120
|
-
);
|
|
16121
|
-
return subAgentSpan.export();
|
|
16122
|
-
}
|
|
16123
|
-
return span.export();
|
|
16124
|
-
}
|
|
16125
|
-
if (activeLlmSpan) {
|
|
16126
|
-
return activeLlmSpan.export();
|
|
16950
|
+
const latestLlmParent = parentToolUseId ? latestLlmParentBySubAgentToolUse.get(parentToolUseId) : latestRootLlmParentRef.value;
|
|
16951
|
+
if (!activeLlmSpan && !latestLlmParent) {
|
|
16952
|
+
await ensureActiveLlmSpanForParentToolUse(
|
|
16953
|
+
span,
|
|
16954
|
+
activeLlmSpansByParentToolUse,
|
|
16955
|
+
subAgentDetailsByToolUseId,
|
|
16956
|
+
activeToolSpans,
|
|
16957
|
+
subAgentSpans,
|
|
16958
|
+
parentToolUseId,
|
|
16959
|
+
getCurrentUnixTimestamp()
|
|
16960
|
+
);
|
|
16127
16961
|
}
|
|
16128
16962
|
if (parentToolUseId) {
|
|
16129
|
-
const parentLlm = latestLlmParentBySubAgentToolUse.get(parentToolUseId);
|
|
16130
|
-
if (parentLlm) {
|
|
16131
|
-
return parentLlm;
|
|
16132
|
-
}
|
|
16133
16963
|
const subAgentSpan = await ensureSubAgentSpan(
|
|
16134
16964
|
subAgentDetailsByToolUseId,
|
|
16135
16965
|
span,
|
|
@@ -16139,9 +16969,6 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
16139
16969
|
);
|
|
16140
16970
|
return subAgentSpan.export();
|
|
16141
16971
|
}
|
|
16142
|
-
if (latestRootLlmParentRef.value) {
|
|
16143
|
-
return latestRootLlmParentRef.value;
|
|
16144
|
-
}
|
|
16145
16972
|
return span.export();
|
|
16146
16973
|
};
|
|
16147
16974
|
localToolContext.resolveLocalToolParent = resolveToolUseParentSpan;
|
|
@@ -16162,6 +16989,7 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
16162
16989
|
accumulatedOutputTokens: 0,
|
|
16163
16990
|
activeLlmSpansByParentToolUse,
|
|
16164
16991
|
activeToolSpans,
|
|
16992
|
+
conversationHistoryByParentKey,
|
|
16165
16993
|
capturedPromptMessages,
|
|
16166
16994
|
currentMessageId: void 0,
|
|
16167
16995
|
currentMessageStartTime: startTime,
|
|
@@ -16172,7 +17000,9 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
16172
17000
|
originalPrompt,
|
|
16173
17001
|
processing: Promise.resolve(),
|
|
16174
17002
|
promptDone,
|
|
17003
|
+
promptMessagesByParentKey,
|
|
16175
17004
|
promptStarted: () => promptStarted,
|
|
17005
|
+
promptSourcePriorityByParentKey,
|
|
16176
17006
|
span,
|
|
16177
17007
|
subAgentDetailsByToolUseId,
|
|
16178
17008
|
subAgentSpans,
|
|
@@ -17572,6 +18402,7 @@ var GoogleGenAIPlugin = class extends BasePlugin {
|
|
|
17572
18402
|
this.subscribeToGenerateContentChannel();
|
|
17573
18403
|
this.subscribeToGenerateContentStreamChannel();
|
|
17574
18404
|
this.subscribeToEmbedContentChannel();
|
|
18405
|
+
this.subscribeToInteractionsCreateChannel();
|
|
17575
18406
|
}
|
|
17576
18407
|
subscribeToGenerateContentChannel() {
|
|
17577
18408
|
const tracingChannel2 = googleGenAIChannels.generateContent.tracingChannel();
|
|
@@ -17744,7 +18575,30 @@ var GoogleGenAIPlugin = class extends BasePlugin {
|
|
|
17744
18575
|
tracingChannel2.unsubscribe(handlers);
|
|
17745
18576
|
});
|
|
17746
18577
|
}
|
|
18578
|
+
subscribeToInteractionsCreateChannel() {
|
|
18579
|
+
this.unsubscribers.push(
|
|
18580
|
+
traceStreamingChannel(
|
|
18581
|
+
googleGenAIChannels.interactionsCreate,
|
|
18582
|
+
{
|
|
18583
|
+
name: "create_interaction",
|
|
18584
|
+
shouldTrace: ([params]) => !isBackgroundInteractionCreate(params),
|
|
18585
|
+
type: "llm" /* LLM */,
|
|
18586
|
+
extractInput: ([params]) => ({
|
|
18587
|
+
input: serializeInteractionInput(params),
|
|
18588
|
+
metadata: extractInteractionMetadata(params)
|
|
18589
|
+
}),
|
|
18590
|
+
extractOutput: (result) => serializeInteractionValue(result),
|
|
18591
|
+
extractMetadata: (result) => extractInteractionResponseMetadata(result),
|
|
18592
|
+
extractMetrics: (result, startTime) => cleanMetrics3(extractInteractionMetrics(result, startTime)),
|
|
18593
|
+
aggregateChunks: (chunks, _result, _event, startTime) => aggregateInteractionEvents(chunks, startTime)
|
|
18594
|
+
}
|
|
18595
|
+
)
|
|
18596
|
+
);
|
|
18597
|
+
}
|
|
17747
18598
|
};
|
|
18599
|
+
function isBackgroundInteractionCreate(params) {
|
|
18600
|
+
return tryToDict(params)?.background === true;
|
|
18601
|
+
}
|
|
17748
18602
|
function ensureSpanState(states, event, create) {
|
|
17749
18603
|
const existing = states.get(event);
|
|
17750
18604
|
if (existing) {
|
|
@@ -17952,6 +18806,60 @@ function serializeEmbedContentInput(params) {
|
|
|
17952
18806
|
}
|
|
17953
18807
|
return input;
|
|
17954
18808
|
}
|
|
18809
|
+
function serializeInteractionInput(params) {
|
|
18810
|
+
const input = {
|
|
18811
|
+
input: serializeInteractionValue(params.input)
|
|
18812
|
+
};
|
|
18813
|
+
for (const key of [
|
|
18814
|
+
"model",
|
|
18815
|
+
"agent",
|
|
18816
|
+
"agent_config",
|
|
18817
|
+
"api_version",
|
|
18818
|
+
"background",
|
|
18819
|
+
"environment",
|
|
18820
|
+
"generation_config",
|
|
18821
|
+
"previous_interaction_id",
|
|
18822
|
+
"response_format",
|
|
18823
|
+
"response_mime_type",
|
|
18824
|
+
"response_modalities",
|
|
18825
|
+
"service_tier",
|
|
18826
|
+
"store",
|
|
18827
|
+
"stream",
|
|
18828
|
+
"system_instruction",
|
|
18829
|
+
"webhook_config"
|
|
18830
|
+
]) {
|
|
18831
|
+
const value = params[key];
|
|
18832
|
+
if (value !== void 0) {
|
|
18833
|
+
input[key] = serializeInteractionValue(value);
|
|
18834
|
+
}
|
|
18835
|
+
}
|
|
18836
|
+
return input;
|
|
18837
|
+
}
|
|
18838
|
+
function extractInteractionMetadata(params) {
|
|
18839
|
+
const metadata = {};
|
|
18840
|
+
for (const key of [
|
|
18841
|
+
"model",
|
|
18842
|
+
"agent",
|
|
18843
|
+
"agent_config",
|
|
18844
|
+
"generation_config",
|
|
18845
|
+
"system_instruction",
|
|
18846
|
+
"response_format",
|
|
18847
|
+
"response_mime_type",
|
|
18848
|
+
"response_modalities",
|
|
18849
|
+
"service_tier"
|
|
18850
|
+
]) {
|
|
18851
|
+
const value = params[key];
|
|
18852
|
+
if (value !== void 0) {
|
|
18853
|
+
metadata[key] = serializeInteractionValue(value);
|
|
18854
|
+
}
|
|
18855
|
+
}
|
|
18856
|
+
if (Array.isArray(params.tools)) {
|
|
18857
|
+
metadata.tools = params.tools.map(
|
|
18858
|
+
(tool) => serializeInteractionValue(tool)
|
|
18859
|
+
);
|
|
18860
|
+
}
|
|
18861
|
+
return metadata;
|
|
18862
|
+
}
|
|
17955
18863
|
function serializeContentCollection(contents) {
|
|
17956
18864
|
if (contents === null || contents === void 0) {
|
|
17957
18865
|
return null;
|
|
@@ -17982,21 +18890,8 @@ function serializePart(part) {
|
|
|
17982
18890
|
}
|
|
17983
18891
|
if (part.inlineData && part.inlineData.data) {
|
|
17984
18892
|
const { data, mimeType } = part.inlineData;
|
|
17985
|
-
|
|
17986
|
-
|
|
17987
|
-
const filename = `file.${extension}`;
|
|
17988
|
-
const buffer = typeof data === "string" ? typeof Buffer !== "undefined" ? Buffer.from(data, "base64") : new Uint8Array(
|
|
17989
|
-
atob(data).split("").map((c) => c.charCodeAt(0))
|
|
17990
|
-
) : typeof Buffer !== "undefined" ? Buffer.from(data) : new Uint8Array(data);
|
|
17991
|
-
const arrayBuffer = buffer instanceof Uint8Array ? buffer.buffer.slice(
|
|
17992
|
-
buffer.byteOffset,
|
|
17993
|
-
buffer.byteOffset + buffer.byteLength
|
|
17994
|
-
) : buffer;
|
|
17995
|
-
const attachment = new Attachment({
|
|
17996
|
-
data: arrayBuffer,
|
|
17997
|
-
filename,
|
|
17998
|
-
contentType: mimeType || "application/octet-stream"
|
|
17999
|
-
});
|
|
18893
|
+
const attachment = createAttachmentFromInlineData(data, mimeType);
|
|
18894
|
+
if (attachment) {
|
|
18000
18895
|
return {
|
|
18001
18896
|
image_url: { url: attachment }
|
|
18002
18897
|
};
|
|
@@ -18004,6 +18899,59 @@ function serializePart(part) {
|
|
|
18004
18899
|
}
|
|
18005
18900
|
return part;
|
|
18006
18901
|
}
|
|
18902
|
+
function serializeInteractionValue(value, seen = /* @__PURE__ */ new WeakSet()) {
|
|
18903
|
+
if (value === null || value === void 0 || typeof value !== "object") {
|
|
18904
|
+
return value;
|
|
18905
|
+
}
|
|
18906
|
+
if (Array.isArray(value)) {
|
|
18907
|
+
return value.map((item) => serializeInteractionValue(item, seen));
|
|
18908
|
+
}
|
|
18909
|
+
const dict = tryToDict(value);
|
|
18910
|
+
if (dict === null || dict === void 0 || typeof dict !== "object") {
|
|
18911
|
+
return dict;
|
|
18912
|
+
}
|
|
18913
|
+
if (Array.isArray(dict)) {
|
|
18914
|
+
return dict.map((item) => serializeInteractionValue(item, seen));
|
|
18915
|
+
}
|
|
18916
|
+
if (seen.has(dict)) {
|
|
18917
|
+
return "[Circular]";
|
|
18918
|
+
}
|
|
18919
|
+
seen.add(dict);
|
|
18920
|
+
try {
|
|
18921
|
+
const serialized = {};
|
|
18922
|
+
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;
|
|
18923
|
+
const attachment = mimeType && "data" in dict && dict.data !== void 0 ? createAttachmentFromInlineData(dict.data, mimeType) : null;
|
|
18924
|
+
for (const [key, entry] of Object.entries(dict)) {
|
|
18925
|
+
if (key === "data" && attachment) {
|
|
18926
|
+
serialized[key] = attachment;
|
|
18927
|
+
} else {
|
|
18928
|
+
serialized[key] = serializeInteractionValue(entry, seen);
|
|
18929
|
+
}
|
|
18930
|
+
}
|
|
18931
|
+
return serialized;
|
|
18932
|
+
} finally {
|
|
18933
|
+
seen.delete(dict);
|
|
18934
|
+
}
|
|
18935
|
+
}
|
|
18936
|
+
function createAttachmentFromInlineData(data, mimeType) {
|
|
18937
|
+
if (!(data instanceof Uint8Array || typeof Buffer !== "undefined" && Buffer.isBuffer(data) || typeof data === "string")) {
|
|
18938
|
+
return null;
|
|
18939
|
+
}
|
|
18940
|
+
const extension = mimeType ? mimeType.split("/")[1] : "bin";
|
|
18941
|
+
const filename = `file.${extension}`;
|
|
18942
|
+
const buffer = typeof data === "string" ? typeof Buffer !== "undefined" ? Buffer.from(data, "base64") : new Uint8Array(
|
|
18943
|
+
atob(data).split("").map((c) => c.charCodeAt(0))
|
|
18944
|
+
) : typeof Buffer !== "undefined" ? Buffer.from(data) : new Uint8Array(data);
|
|
18945
|
+
const arrayBuffer = buffer instanceof Uint8Array ? buffer.buffer.slice(
|
|
18946
|
+
buffer.byteOffset,
|
|
18947
|
+
buffer.byteOffset + buffer.byteLength
|
|
18948
|
+
) : buffer;
|
|
18949
|
+
return new Attachment({
|
|
18950
|
+
data: arrayBuffer,
|
|
18951
|
+
filename,
|
|
18952
|
+
contentType: mimeType || "application/octet-stream"
|
|
18953
|
+
});
|
|
18954
|
+
}
|
|
18007
18955
|
function serializeGenerateContentTools(params) {
|
|
18008
18956
|
const config = params.config ? tryToDict(params.config) : null;
|
|
18009
18957
|
const tools = config?.tools;
|
|
@@ -18088,6 +19036,33 @@ function extractEmbedContentMetrics(response, startTime) {
|
|
|
18088
19036
|
}
|
|
18089
19037
|
return metrics;
|
|
18090
19038
|
}
|
|
19039
|
+
function extractInteractionMetrics(response, startTime) {
|
|
19040
|
+
const metrics = {};
|
|
19041
|
+
if (startTime !== void 0) {
|
|
19042
|
+
const end = getCurrentUnixTimestamp();
|
|
19043
|
+
metrics.start = startTime;
|
|
19044
|
+
metrics.end = end;
|
|
19045
|
+
metrics.duration = end - startTime;
|
|
19046
|
+
}
|
|
19047
|
+
if (response?.usage) {
|
|
19048
|
+
populateInteractionUsageMetrics(metrics, response.usage);
|
|
19049
|
+
}
|
|
19050
|
+
return metrics;
|
|
19051
|
+
}
|
|
19052
|
+
function extractInteractionResponseMetadata(response) {
|
|
19053
|
+
const responseDict = tryToDict(response);
|
|
19054
|
+
if (!responseDict) {
|
|
19055
|
+
return void 0;
|
|
19056
|
+
}
|
|
19057
|
+
const metadata = {};
|
|
19058
|
+
if (typeof responseDict.id === "string") {
|
|
19059
|
+
metadata.interaction_id = responseDict.id;
|
|
19060
|
+
}
|
|
19061
|
+
if (typeof responseDict.status === "string") {
|
|
19062
|
+
metadata.status = responseDict.status;
|
|
19063
|
+
}
|
|
19064
|
+
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
19065
|
+
}
|
|
18091
19066
|
function extractEmbedPromptTokenCount(response) {
|
|
18092
19067
|
if (!response) {
|
|
18093
19068
|
return void 0;
|
|
@@ -18150,6 +19125,23 @@ function populateUsageMetrics(metrics, usage) {
|
|
|
18150
19125
|
metrics.completion_reasoning_tokens = usage.thoughtsTokenCount;
|
|
18151
19126
|
}
|
|
18152
19127
|
}
|
|
19128
|
+
function populateInteractionUsageMetrics(metrics, usage) {
|
|
19129
|
+
if (typeof usage.total_input_tokens === "number") {
|
|
19130
|
+
metrics.prompt_tokens = usage.total_input_tokens;
|
|
19131
|
+
}
|
|
19132
|
+
if (typeof usage.total_output_tokens === "number") {
|
|
19133
|
+
metrics.completion_tokens = usage.total_output_tokens;
|
|
19134
|
+
}
|
|
19135
|
+
if (typeof usage.total_tokens === "number") {
|
|
19136
|
+
metrics.tokens = usage.total_tokens;
|
|
19137
|
+
}
|
|
19138
|
+
if (typeof usage.total_cached_tokens === "number") {
|
|
19139
|
+
metrics.prompt_cached_tokens = usage.total_cached_tokens;
|
|
19140
|
+
}
|
|
19141
|
+
if (typeof usage.total_thought_tokens === "number") {
|
|
19142
|
+
metrics.completion_reasoning_tokens = usage.total_thought_tokens;
|
|
19143
|
+
}
|
|
19144
|
+
}
|
|
18153
19145
|
function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
|
|
18154
19146
|
const end = getCurrentUnixTimestamp();
|
|
18155
19147
|
const metrics = {
|
|
@@ -18247,6 +19239,146 @@ function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
|
|
|
18247
19239
|
}
|
|
18248
19240
|
return { aggregated, metrics };
|
|
18249
19241
|
}
|
|
19242
|
+
function aggregateInteractionEvents(chunks, startTime) {
|
|
19243
|
+
const end = getCurrentUnixTimestamp();
|
|
19244
|
+
const metrics = {};
|
|
19245
|
+
if (startTime !== void 0) {
|
|
19246
|
+
metrics.start = startTime;
|
|
19247
|
+
metrics.end = end;
|
|
19248
|
+
metrics.duration = end - startTime;
|
|
19249
|
+
}
|
|
19250
|
+
let latestInteraction;
|
|
19251
|
+
let latestUsage;
|
|
19252
|
+
let status;
|
|
19253
|
+
let outputText = "";
|
|
19254
|
+
const steps = /* @__PURE__ */ new Map();
|
|
19255
|
+
for (const chunk of chunks) {
|
|
19256
|
+
const event = tryToDict(chunk);
|
|
19257
|
+
if (!event) {
|
|
19258
|
+
continue;
|
|
19259
|
+
}
|
|
19260
|
+
const usage = extractInteractionUsageFromEvent(event);
|
|
19261
|
+
if (usage) {
|
|
19262
|
+
latestUsage = usage;
|
|
19263
|
+
}
|
|
19264
|
+
const interaction = tryToDict(event.interaction);
|
|
19265
|
+
if (interaction) {
|
|
19266
|
+
latestInteraction = serializeInteractionValue(interaction);
|
|
19267
|
+
if (typeof interaction.status === "string") {
|
|
19268
|
+
status = interaction.status;
|
|
19269
|
+
}
|
|
19270
|
+
}
|
|
19271
|
+
if (typeof event.status === "string") {
|
|
19272
|
+
status = event.status;
|
|
19273
|
+
}
|
|
19274
|
+
const index = typeof event.index === "number" ? event.index : void 0;
|
|
19275
|
+
if (index === void 0) {
|
|
19276
|
+
continue;
|
|
19277
|
+
}
|
|
19278
|
+
if (event.event_type === "step.start") {
|
|
19279
|
+
const compact = compactInteractionStep(event.step);
|
|
19280
|
+
compact.index = index;
|
|
19281
|
+
steps.set(index, compact);
|
|
19282
|
+
continue;
|
|
19283
|
+
}
|
|
19284
|
+
if (event.event_type === "step.delta") {
|
|
19285
|
+
const step = steps.get(index) ?? { index };
|
|
19286
|
+
const textDelta = applyInteractionDelta(step, event.delta);
|
|
19287
|
+
if (textDelta) {
|
|
19288
|
+
outputText += textDelta;
|
|
19289
|
+
}
|
|
19290
|
+
steps.set(index, step);
|
|
19291
|
+
}
|
|
19292
|
+
}
|
|
19293
|
+
if (latestUsage) {
|
|
19294
|
+
populateInteractionUsageMetrics(metrics, latestUsage);
|
|
19295
|
+
}
|
|
19296
|
+
const output = latestInteraction ? { ...latestInteraction } : {};
|
|
19297
|
+
if (status) {
|
|
19298
|
+
output.status = status;
|
|
19299
|
+
}
|
|
19300
|
+
if (outputText) {
|
|
19301
|
+
output.output_text = outputText;
|
|
19302
|
+
}
|
|
19303
|
+
if (latestUsage) {
|
|
19304
|
+
output.usage = serializeInteractionValue(latestUsage);
|
|
19305
|
+
}
|
|
19306
|
+
const compactSteps = Array.from(steps.values()).sort(
|
|
19307
|
+
(left, right) => Number(left.index ?? 0) - Number(right.index ?? 0)
|
|
19308
|
+
);
|
|
19309
|
+
if (compactSteps.length > 0) {
|
|
19310
|
+
output.steps = compactSteps;
|
|
19311
|
+
}
|
|
19312
|
+
const metadata = {};
|
|
19313
|
+
if (typeof output.id === "string") {
|
|
19314
|
+
metadata.interaction_id = output.id;
|
|
19315
|
+
}
|
|
19316
|
+
if (typeof output.status === "string") {
|
|
19317
|
+
metadata.status = output.status;
|
|
19318
|
+
}
|
|
19319
|
+
return {
|
|
19320
|
+
output,
|
|
19321
|
+
metrics: cleanMetrics3(metrics),
|
|
19322
|
+
...Object.keys(metadata).length > 0 ? { metadata } : {}
|
|
19323
|
+
};
|
|
19324
|
+
}
|
|
19325
|
+
function extractInteractionUsageFromEvent(event) {
|
|
19326
|
+
const metadata = tryToDict(event.metadata);
|
|
19327
|
+
const metadataUsage = tryToDict(metadata?.usage);
|
|
19328
|
+
if (metadataUsage) {
|
|
19329
|
+
return metadataUsage;
|
|
19330
|
+
}
|
|
19331
|
+
const metadataTotalUsage = tryToDict(metadata?.total_usage);
|
|
19332
|
+
if (metadataTotalUsage) {
|
|
19333
|
+
return metadataTotalUsage;
|
|
19334
|
+
}
|
|
19335
|
+
const interaction = tryToDict(event.interaction);
|
|
19336
|
+
const interactionUsage = tryToDict(interaction?.usage);
|
|
19337
|
+
return interactionUsage ? interactionUsage : void 0;
|
|
19338
|
+
}
|
|
19339
|
+
function compactInteractionStep(step) {
|
|
19340
|
+
const stepDict = tryToDict(step);
|
|
19341
|
+
if (!stepDict) {
|
|
19342
|
+
return {};
|
|
19343
|
+
}
|
|
19344
|
+
const compact = {};
|
|
19345
|
+
for (const key of [
|
|
19346
|
+
"type",
|
|
19347
|
+
"content",
|
|
19348
|
+
"name",
|
|
19349
|
+
"server_name",
|
|
19350
|
+
"arguments",
|
|
19351
|
+
"result",
|
|
19352
|
+
"is_error"
|
|
19353
|
+
]) {
|
|
19354
|
+
if (stepDict[key] !== void 0) {
|
|
19355
|
+
compact[key] = serializeInteractionValue(stepDict[key]);
|
|
19356
|
+
}
|
|
19357
|
+
}
|
|
19358
|
+
return Object.keys(compact).length > 0 ? compact : serializeInteractionValue(stepDict);
|
|
19359
|
+
}
|
|
19360
|
+
function applyInteractionDelta(step, delta) {
|
|
19361
|
+
const deltaDict = tryToDict(delta);
|
|
19362
|
+
if (!deltaDict) {
|
|
19363
|
+
return void 0;
|
|
19364
|
+
}
|
|
19365
|
+
const deltaType = deltaDict.type;
|
|
19366
|
+
if (typeof deltaType === "string" && typeof step.type !== "string") {
|
|
19367
|
+
step.type = deltaType === "text" ? "model_output" : deltaType;
|
|
19368
|
+
}
|
|
19369
|
+
if (deltaType === "text" && typeof deltaDict.text === "string") {
|
|
19370
|
+
step.text = `${typeof step.text === "string" ? step.text : ""}${deltaDict.text}`;
|
|
19371
|
+
return deltaDict.text;
|
|
19372
|
+
}
|
|
19373
|
+
if (deltaType === "arguments_delta" && typeof deltaDict.arguments === "string") {
|
|
19374
|
+
step.arguments = `${typeof step.arguments === "string" ? step.arguments : ""}${deltaDict.arguments}`;
|
|
19375
|
+
return void 0;
|
|
19376
|
+
}
|
|
19377
|
+
const deltas = Array.isArray(step.deltas) ? step.deltas : [];
|
|
19378
|
+
deltas.push(serializeInteractionValue(deltaDict));
|
|
19379
|
+
step.deltas = deltas;
|
|
19380
|
+
return void 0;
|
|
19381
|
+
}
|
|
18250
19382
|
function cleanMetrics3(metrics) {
|
|
18251
19383
|
const cleaned = {};
|
|
18252
19384
|
for (const [key, value] of Object.entries(metrics)) {
|
|
@@ -23843,7 +24975,8 @@ var FlueObserveBridge = class {
|
|
|
23843
24975
|
metadata
|
|
23844
24976
|
}
|
|
23845
24977
|
});
|
|
23846
|
-
|
|
24978
|
+
const activeContext = enterCurrentFlueSpan(span);
|
|
24979
|
+
this.runsById.set(event.runId, { activeContext, metadata, span });
|
|
23847
24980
|
}
|
|
23848
24981
|
handleRunEnd(event) {
|
|
23849
24982
|
const state = this.runsById.get(event.runId);
|
|
@@ -23861,6 +24994,7 @@ var FlueObserveBridge = class {
|
|
|
23861
24994
|
});
|
|
23862
24995
|
safeEnd(state.span, eventTime(event.timestamp));
|
|
23863
24996
|
this.runsById.delete(event.runId);
|
|
24997
|
+
restoreCurrentFlueSpan(state.activeContext);
|
|
23864
24998
|
}
|
|
23865
24999
|
void flush().catch((error) => {
|
|
23866
25000
|
logInstrumentationError3("Flue flush", error);
|
|
@@ -23987,7 +25121,8 @@ var FlueObserveBridge = class {
|
|
|
23987
25121
|
metadata
|
|
23988
25122
|
}
|
|
23989
25123
|
});
|
|
23990
|
-
|
|
25124
|
+
const activeContext = enterCurrentFlueSpan(span);
|
|
25125
|
+
this.toolsByKey.set(toolKey(event), { activeContext, metadata, span });
|
|
23991
25126
|
}
|
|
23992
25127
|
handleToolCall(event) {
|
|
23993
25128
|
if (!event.toolCallId) {
|
|
@@ -24010,6 +25145,7 @@ var FlueObserveBridge = class {
|
|
|
24010
25145
|
});
|
|
24011
25146
|
safeEnd(state.span, eventTime(event.timestamp));
|
|
24012
25147
|
this.toolsByKey.delete(key);
|
|
25148
|
+
restoreCurrentFlueSpan(state.activeContext);
|
|
24013
25149
|
}
|
|
24014
25150
|
handleTaskStart(event) {
|
|
24015
25151
|
if (!event.taskId) {
|
|
@@ -24414,6 +25550,34 @@ function stateMatchesRun(state, runId) {
|
|
|
24414
25550
|
function startFlueSpan(parent, args) {
|
|
24415
25551
|
return parent ? withCurrent(parent, () => startSpan(args)) : startSpan(args);
|
|
24416
25552
|
}
|
|
25553
|
+
function enterCurrentFlueSpan(span) {
|
|
25554
|
+
const contextManager = _internalGetGlobalState()?.contextManager;
|
|
25555
|
+
const store = contextManager ? Reflect.get(contextManager, BRAINTRUST_CURRENT_SPAN_STORE) : void 0;
|
|
25556
|
+
if (!contextManager || !isCurrentSpanStore(store)) {
|
|
25557
|
+
return void 0;
|
|
25558
|
+
}
|
|
25559
|
+
const previous = store.getStore();
|
|
25560
|
+
try {
|
|
25561
|
+
store.enterWith(contextManager.wrapSpanForStore(span));
|
|
25562
|
+
return { previous, store };
|
|
25563
|
+
} catch (error) {
|
|
25564
|
+
logInstrumentationError3("Flue context propagation", error);
|
|
25565
|
+
return void 0;
|
|
25566
|
+
}
|
|
25567
|
+
}
|
|
25568
|
+
function isCurrentSpanStore(value) {
|
|
25569
|
+
return isObjectLike(value) && typeof Reflect.get(value, "enterWith") === "function" && typeof Reflect.get(value, "getStore") === "function";
|
|
25570
|
+
}
|
|
25571
|
+
function restoreCurrentFlueSpan(activeContext) {
|
|
25572
|
+
if (!activeContext) {
|
|
25573
|
+
return;
|
|
25574
|
+
}
|
|
25575
|
+
try {
|
|
25576
|
+
activeContext.store.enterWith(activeContext.previous);
|
|
25577
|
+
} catch (error) {
|
|
25578
|
+
logInstrumentationError3("Flue context restoration", error);
|
|
25579
|
+
}
|
|
25580
|
+
}
|
|
24417
25581
|
function safeLog3(span, event) {
|
|
24418
25582
|
try {
|
|
24419
25583
|
span.log(event);
|
|
@@ -24879,6 +26043,879 @@ function isBraintrustHandler(handler) {
|
|
|
24879
26043
|
return Reflect.get(handler, "name") === BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
|
|
24880
26044
|
}
|
|
24881
26045
|
|
|
26046
|
+
// src/instrumentation/plugins/pi-coding-agent-plugin.ts
|
|
26047
|
+
var piStreamPatchStates = /* @__PURE__ */ new WeakMap();
|
|
26048
|
+
var piPromptContextStore;
|
|
26049
|
+
var PiCodingAgentPlugin = class extends BasePlugin {
|
|
26050
|
+
activePromptStates = /* @__PURE__ */ new Set();
|
|
26051
|
+
onEnable() {
|
|
26052
|
+
this.subscribeToPrompt();
|
|
26053
|
+
}
|
|
26054
|
+
onDisable() {
|
|
26055
|
+
for (const unsubscribe of this.unsubscribers) {
|
|
26056
|
+
unsubscribe();
|
|
26057
|
+
}
|
|
26058
|
+
this.unsubscribers = [];
|
|
26059
|
+
for (const state of [...this.activePromptStates]) {
|
|
26060
|
+
void finalizePiPromptRun(state).catch((error) => {
|
|
26061
|
+
logInstrumentationError4("Pi Coding Agent disable cleanup", error);
|
|
26062
|
+
});
|
|
26063
|
+
}
|
|
26064
|
+
}
|
|
26065
|
+
subscribeToPrompt() {
|
|
26066
|
+
const channel = piCodingAgentChannels.prompt.tracingChannel();
|
|
26067
|
+
const states = /* @__PURE__ */ new WeakMap();
|
|
26068
|
+
const unbindAutoInstrumentationSuppression = bindAutoInstrumentationSuppressionToStart(channel);
|
|
26069
|
+
const handlers = {
|
|
26070
|
+
start: (event) => {
|
|
26071
|
+
const state = startPiPromptRun(event, (state2) => {
|
|
26072
|
+
this.activePromptStates.delete(state2);
|
|
26073
|
+
});
|
|
26074
|
+
if (state) {
|
|
26075
|
+
this.activePromptStates.add(state);
|
|
26076
|
+
states.set(event, state);
|
|
26077
|
+
}
|
|
26078
|
+
},
|
|
26079
|
+
asyncEnd: async (event) => {
|
|
26080
|
+
const state = states.get(event);
|
|
26081
|
+
if (!state) {
|
|
26082
|
+
return;
|
|
26083
|
+
}
|
|
26084
|
+
states.delete(event);
|
|
26085
|
+
state.promptCallEnded = true;
|
|
26086
|
+
if (!state.finalized && state.deferCompletionUntilTurnEnd && !state.turnEnded) {
|
|
26087
|
+
if (!state.sawStreamFn) {
|
|
26088
|
+
state.queued = true;
|
|
26089
|
+
if (!state.streamPatchState.queuedPromptStates.includes(state)) {
|
|
26090
|
+
state.streamPatchState.queuedPromptStates.push(state);
|
|
26091
|
+
}
|
|
26092
|
+
}
|
|
26093
|
+
return;
|
|
26094
|
+
}
|
|
26095
|
+
await finalizePiPromptRun(state);
|
|
26096
|
+
},
|
|
26097
|
+
error: async (event) => {
|
|
26098
|
+
const state = states.get(event);
|
|
26099
|
+
if (!state) {
|
|
26100
|
+
return;
|
|
26101
|
+
}
|
|
26102
|
+
states.delete(event);
|
|
26103
|
+
await finalizePiPromptRun(state, event.error);
|
|
26104
|
+
}
|
|
26105
|
+
};
|
|
26106
|
+
channel.subscribe(handlers);
|
|
26107
|
+
this.unsubscribers.push(() => {
|
|
26108
|
+
unbindAutoInstrumentationSuppression?.();
|
|
26109
|
+
channel.unsubscribe(handlers);
|
|
26110
|
+
});
|
|
26111
|
+
}
|
|
26112
|
+
};
|
|
26113
|
+
function startPiPromptRun(event, onFinalize) {
|
|
26114
|
+
const session = extractSession(event);
|
|
26115
|
+
const agent = session?.agent;
|
|
26116
|
+
if (!session || !isPiAgent(agent)) {
|
|
26117
|
+
return void 0;
|
|
26118
|
+
}
|
|
26119
|
+
const metadata = {
|
|
26120
|
+
...extractSessionMetadata(session),
|
|
26121
|
+
...extractPromptOptionsMetadata(event.arguments[1]),
|
|
26122
|
+
"pi_coding_agent.operation": "AgentSession.prompt",
|
|
26123
|
+
provider: session.model?.provider ?? agent.state?.model?.provider ?? "pi",
|
|
26124
|
+
...session.model?.id || agent.state?.model?.id ? { model: session.model?.id ?? agent.state?.model?.id } : {},
|
|
26125
|
+
...event.moduleVersion ? { "pi_coding_agent.version": event.moduleVersion } : {}
|
|
26126
|
+
};
|
|
26127
|
+
const span = startSpan({
|
|
26128
|
+
event: {
|
|
26129
|
+
input: extractPromptInput(event.arguments[0], event.arguments[1]),
|
|
26130
|
+
metadata
|
|
26131
|
+
},
|
|
26132
|
+
name: "AgentSession.prompt",
|
|
26133
|
+
spanAttributes: { type: "task" /* TASK */ }
|
|
26134
|
+
});
|
|
26135
|
+
const streamPatchState = installPiStreamPatch(agent);
|
|
26136
|
+
const options = event.arguments[1];
|
|
26137
|
+
const promptText = event.arguments[0];
|
|
26138
|
+
const state = {
|
|
26139
|
+
activeLlmSpans: /* @__PURE__ */ new Set(),
|
|
26140
|
+
activeToolSpans: /* @__PURE__ */ new Map(),
|
|
26141
|
+
agent,
|
|
26142
|
+
collectedLlmUsageMetrics: false,
|
|
26143
|
+
deferCompletionUntilTurnEnd: options?.streamingBehavior === "followUp" || options?.streamingBehavior === "steer",
|
|
26144
|
+
finalized: false,
|
|
26145
|
+
metadata,
|
|
26146
|
+
metrics: {},
|
|
26147
|
+
onFinalize,
|
|
26148
|
+
promptCallEnded: false,
|
|
26149
|
+
...typeof promptText === "string" ? { promptText } : {},
|
|
26150
|
+
queued: false,
|
|
26151
|
+
span,
|
|
26152
|
+
sawStreamFn: false,
|
|
26153
|
+
startTime: getCurrentUnixTimestamp(),
|
|
26154
|
+
streamPatchState,
|
|
26155
|
+
turnEnded: false
|
|
26156
|
+
};
|
|
26157
|
+
state.restorePromptContext = enterPiPromptContext(state);
|
|
26158
|
+
streamPatchState.activePromptStates.add(state);
|
|
26159
|
+
try {
|
|
26160
|
+
state.unsubscribeAgent = agent.subscribe(async (agentEvent) => {
|
|
26161
|
+
try {
|
|
26162
|
+
await runWithAutoInstrumentationSuppressed(
|
|
26163
|
+
() => handlePiAgentEvent(state, agentEvent)
|
|
26164
|
+
);
|
|
26165
|
+
} catch (error) {
|
|
26166
|
+
logInstrumentationError4("Pi Coding Agent event", error);
|
|
26167
|
+
}
|
|
26168
|
+
});
|
|
26169
|
+
} catch (error) {
|
|
26170
|
+
logInstrumentationError4("Pi Coding Agent event subscription", error);
|
|
26171
|
+
}
|
|
26172
|
+
return state;
|
|
26173
|
+
}
|
|
26174
|
+
function extractSession(event) {
|
|
26175
|
+
const candidate = event.session ?? event.self;
|
|
26176
|
+
return isObject(candidate) && typeof candidate.prompt === "function" ? candidate : void 0;
|
|
26177
|
+
}
|
|
26178
|
+
function isPiAgent(value) {
|
|
26179
|
+
return isObject(value) && typeof value.streamFn === "function" && typeof value.subscribe === "function";
|
|
26180
|
+
}
|
|
26181
|
+
function promptContextStore() {
|
|
26182
|
+
piPromptContextStore ??= isomorph_default.newAsyncLocalStorage();
|
|
26183
|
+
return piPromptContextStore;
|
|
26184
|
+
}
|
|
26185
|
+
function currentPromptContextFrames() {
|
|
26186
|
+
return promptContextStore().getStore()?.frames ?? [];
|
|
26187
|
+
}
|
|
26188
|
+
function currentPiPromptState() {
|
|
26189
|
+
const frames = currentPromptContextFrames();
|
|
26190
|
+
return frames[frames.length - 1]?.state;
|
|
26191
|
+
}
|
|
26192
|
+
function enterPiPromptContext(state) {
|
|
26193
|
+
const frame = {
|
|
26194
|
+
id: /* @__PURE__ */ Symbol("braintrust.pi-coding-agent.prompt"),
|
|
26195
|
+
state
|
|
26196
|
+
};
|
|
26197
|
+
promptContextStore().enterWith({
|
|
26198
|
+
frames: [...currentPromptContextFrames(), frame]
|
|
26199
|
+
});
|
|
26200
|
+
return () => {
|
|
26201
|
+
const frames = currentPromptContextFrames().filter(
|
|
26202
|
+
(candidate) => candidate.id !== frame.id
|
|
26203
|
+
);
|
|
26204
|
+
promptContextStore().enterWith(frames.length > 0 ? { frames } : void 0);
|
|
26205
|
+
};
|
|
26206
|
+
}
|
|
26207
|
+
function installPiStreamPatch(agent) {
|
|
26208
|
+
const existing = piStreamPatchStates.get(agent);
|
|
26209
|
+
if (existing) {
|
|
26210
|
+
if (agent.streamFn !== existing.wrappedStreamFn) {
|
|
26211
|
+
debugLogger.debug(
|
|
26212
|
+
"Pi Coding Agent streamFn changed while Braintrust instrumentation was active; preserving existing patch state."
|
|
26213
|
+
);
|
|
26214
|
+
}
|
|
26215
|
+
return existing;
|
|
26216
|
+
}
|
|
26217
|
+
const patchState = {
|
|
26218
|
+
activePromptStates: /* @__PURE__ */ new Set(),
|
|
26219
|
+
agent,
|
|
26220
|
+
originalStreamFn: agent.streamFn,
|
|
26221
|
+
queuedPromptStates: [],
|
|
26222
|
+
wrappedStreamFn: agent.streamFn
|
|
26223
|
+
};
|
|
26224
|
+
patchState.wrappedStreamFn = makeSharedInstrumentedStreamFn(patchState);
|
|
26225
|
+
agent.streamFn = patchState.wrappedStreamFn;
|
|
26226
|
+
piStreamPatchStates.set(agent, patchState);
|
|
26227
|
+
return patchState;
|
|
26228
|
+
}
|
|
26229
|
+
function resolveStreamPromptState(patchState, context) {
|
|
26230
|
+
let lastUserText;
|
|
26231
|
+
if (Array.isArray(context.messages)) {
|
|
26232
|
+
for (let i = context.messages.length - 1; i >= 0; i--) {
|
|
26233
|
+
const message = context.messages[i];
|
|
26234
|
+
if (isPiUserMessage(message)) {
|
|
26235
|
+
if (typeof message.content === "string") {
|
|
26236
|
+
lastUserText = message.content;
|
|
26237
|
+
} else {
|
|
26238
|
+
lastUserText = message.content.flatMap((part) => part.type === "text" ? [part.text] : []).join("");
|
|
26239
|
+
}
|
|
26240
|
+
break;
|
|
26241
|
+
}
|
|
26242
|
+
}
|
|
26243
|
+
}
|
|
26244
|
+
if (lastUserText !== void 0) {
|
|
26245
|
+
const queuedMatch = patchState.queuedPromptStates.find(
|
|
26246
|
+
(state) => state.promptText === lastUserText
|
|
26247
|
+
);
|
|
26248
|
+
if (queuedMatch) {
|
|
26249
|
+
return queuedMatch;
|
|
26250
|
+
}
|
|
26251
|
+
const matches = [...patchState.activePromptStates].filter(
|
|
26252
|
+
(state) => state.promptText === lastUserText
|
|
26253
|
+
);
|
|
26254
|
+
if (matches.length === 1) {
|
|
26255
|
+
return matches[0];
|
|
26256
|
+
}
|
|
26257
|
+
}
|
|
26258
|
+
const contextState = currentPiPromptState();
|
|
26259
|
+
if (contextState && patchState.activePromptStates.has(contextState) && (!contextState.queued || lastUserText !== void 0 && contextState.promptText === lastUserText)) {
|
|
26260
|
+
return contextState;
|
|
26261
|
+
}
|
|
26262
|
+
if (patchState.activePromptStates.size === 1) {
|
|
26263
|
+
return [...patchState.activePromptStates][0];
|
|
26264
|
+
}
|
|
26265
|
+
return void 0;
|
|
26266
|
+
}
|
|
26267
|
+
function makeSharedInstrumentedStreamFn(patchState) {
|
|
26268
|
+
return async function instrumentedPiStreamFn(model, context, options) {
|
|
26269
|
+
const state = resolveStreamPromptState(patchState, context);
|
|
26270
|
+
if (!state) {
|
|
26271
|
+
const invokeOriginal = () => Reflect.apply(patchState.originalStreamFn, this, [
|
|
26272
|
+
model,
|
|
26273
|
+
context,
|
|
26274
|
+
options
|
|
26275
|
+
]);
|
|
26276
|
+
return patchState.activePromptStates.size > 0 ? runWithAutoInstrumentationSuppressed(invokeOriginal) : invokeOriginal();
|
|
26277
|
+
}
|
|
26278
|
+
state.sawStreamFn = true;
|
|
26279
|
+
removeQueuedPromptState(state);
|
|
26280
|
+
state.streamPatchState.eventPromptState = state;
|
|
26281
|
+
const llmState = await startPiLlmSpan(state, model, context, options);
|
|
26282
|
+
try {
|
|
26283
|
+
const stream = await runWithAutoInstrumentationSuppressed(
|
|
26284
|
+
() => Reflect.apply(patchState.originalStreamFn, this, [
|
|
26285
|
+
model,
|
|
26286
|
+
context,
|
|
26287
|
+
options
|
|
26288
|
+
])
|
|
26289
|
+
);
|
|
26290
|
+
return patchAssistantMessageStream(stream, state, llmState);
|
|
26291
|
+
} catch (error) {
|
|
26292
|
+
finishPiLlmSpan(state, llmState, void 0, error);
|
|
26293
|
+
throw error;
|
|
26294
|
+
}
|
|
26295
|
+
};
|
|
26296
|
+
}
|
|
26297
|
+
async function startPiLlmSpan(state, model, context, options) {
|
|
26298
|
+
const metadata = {
|
|
26299
|
+
...extractModelMetadata2(model),
|
|
26300
|
+
...extractStreamOptionsMetadata(options),
|
|
26301
|
+
...extractToolMetadata(context.tools),
|
|
26302
|
+
"pi_coding_agent.operation": "agent.streamFn"
|
|
26303
|
+
};
|
|
26304
|
+
const span = startSpan({
|
|
26305
|
+
event: {
|
|
26306
|
+
input: processInputAttachments(normalizePiContextInput(context)),
|
|
26307
|
+
metadata
|
|
26308
|
+
},
|
|
26309
|
+
name: getLlmSpanName(model),
|
|
26310
|
+
parent: await state.span.export(),
|
|
26311
|
+
spanAttributes: { type: "llm" /* LLM */ }
|
|
26312
|
+
});
|
|
26313
|
+
const llmState = {
|
|
26314
|
+
finalized: false,
|
|
26315
|
+
metadata,
|
|
26316
|
+
metrics: {},
|
|
26317
|
+
span,
|
|
26318
|
+
startTime: getCurrentUnixTimestamp()
|
|
26319
|
+
};
|
|
26320
|
+
state.activeLlmSpans.add(llmState);
|
|
26321
|
+
return llmState;
|
|
26322
|
+
}
|
|
26323
|
+
function patchAssistantMessageStream(stream, promptState, llmState) {
|
|
26324
|
+
if (!isObject(stream)) {
|
|
26325
|
+
return stream;
|
|
26326
|
+
}
|
|
26327
|
+
const streamRecord = stream;
|
|
26328
|
+
const originalResult = stream.result;
|
|
26329
|
+
if (typeof originalResult === "function") {
|
|
26330
|
+
streamRecord.result = function patchedPiResult() {
|
|
26331
|
+
return Promise.resolve(Reflect.apply(originalResult, this, [])).then(
|
|
26332
|
+
(message) => {
|
|
26333
|
+
finishPiLlmSpan(promptState, llmState, message);
|
|
26334
|
+
return message;
|
|
26335
|
+
},
|
|
26336
|
+
(error) => {
|
|
26337
|
+
finishPiLlmSpan(promptState, llmState, void 0, error);
|
|
26338
|
+
throw error;
|
|
26339
|
+
}
|
|
26340
|
+
);
|
|
26341
|
+
};
|
|
26342
|
+
}
|
|
26343
|
+
const originalIterator = stream[Symbol.asyncIterator];
|
|
26344
|
+
if (typeof originalIterator === "function") {
|
|
26345
|
+
streamRecord[Symbol.asyncIterator] = function patchedPiIterator() {
|
|
26346
|
+
const iterator = Reflect.apply(
|
|
26347
|
+
originalIterator,
|
|
26348
|
+
this,
|
|
26349
|
+
[]
|
|
26350
|
+
);
|
|
26351
|
+
return {
|
|
26352
|
+
async next() {
|
|
26353
|
+
try {
|
|
26354
|
+
const result = await iterator.next();
|
|
26355
|
+
if (result.done) {
|
|
26356
|
+
finishPiLlmSpan(promptState, llmState);
|
|
26357
|
+
return result;
|
|
26358
|
+
}
|
|
26359
|
+
recordPiAssistantMessageEvent(promptState, llmState, result.value);
|
|
26360
|
+
return result;
|
|
26361
|
+
} catch (error) {
|
|
26362
|
+
finishPiLlmSpan(promptState, llmState, void 0, error);
|
|
26363
|
+
if (typeof iterator.return === "function") {
|
|
26364
|
+
try {
|
|
26365
|
+
await iterator.return();
|
|
26366
|
+
} catch (cleanupError) {
|
|
26367
|
+
logInstrumentationError4(
|
|
26368
|
+
"Pi Coding Agent stream cleanup",
|
|
26369
|
+
cleanupError
|
|
26370
|
+
);
|
|
26371
|
+
}
|
|
26372
|
+
}
|
|
26373
|
+
throw error;
|
|
26374
|
+
}
|
|
26375
|
+
},
|
|
26376
|
+
async return(value) {
|
|
26377
|
+
try {
|
|
26378
|
+
if (typeof iterator.return === "function") {
|
|
26379
|
+
return await iterator.return(value);
|
|
26380
|
+
}
|
|
26381
|
+
return {
|
|
26382
|
+
done: true,
|
|
26383
|
+
value
|
|
26384
|
+
};
|
|
26385
|
+
} catch (error) {
|
|
26386
|
+
finishPiLlmSpan(promptState, llmState, void 0, error);
|
|
26387
|
+
throw error;
|
|
26388
|
+
} finally {
|
|
26389
|
+
finishPiLlmSpan(promptState, llmState);
|
|
26390
|
+
}
|
|
26391
|
+
},
|
|
26392
|
+
async throw(error) {
|
|
26393
|
+
try {
|
|
26394
|
+
if (typeof iterator.throw === "function") {
|
|
26395
|
+
return await iterator.throw(error);
|
|
26396
|
+
}
|
|
26397
|
+
throw error;
|
|
26398
|
+
} catch (thrownError) {
|
|
26399
|
+
finishPiLlmSpan(promptState, llmState, void 0, thrownError);
|
|
26400
|
+
throw thrownError;
|
|
26401
|
+
}
|
|
26402
|
+
},
|
|
26403
|
+
[Symbol.asyncIterator]() {
|
|
26404
|
+
return this;
|
|
26405
|
+
}
|
|
26406
|
+
};
|
|
26407
|
+
};
|
|
26408
|
+
}
|
|
26409
|
+
return stream;
|
|
26410
|
+
}
|
|
26411
|
+
function recordPiAssistantMessageEvent(promptState, llmState, event) {
|
|
26412
|
+
recordFirstTokenMetric(llmState, event);
|
|
26413
|
+
const message = "message" in event ? event.message : void 0;
|
|
26414
|
+
const errorMessage2 = "error" in event ? event.error : void 0;
|
|
26415
|
+
if (event.type === "done" && isPiAssistantMessage(message)) {
|
|
26416
|
+
finishPiLlmSpan(promptState, llmState, message);
|
|
26417
|
+
} else if (event.type === "error" && isPiAssistantMessage(errorMessage2)) {
|
|
26418
|
+
finishPiLlmSpan(promptState, llmState, errorMessage2);
|
|
26419
|
+
}
|
|
26420
|
+
}
|
|
26421
|
+
function recordFirstTokenMetric(state, event) {
|
|
26422
|
+
if (state.metrics.time_to_first_token !== void 0 || event.type === "start") {
|
|
26423
|
+
return;
|
|
26424
|
+
}
|
|
26425
|
+
state.metrics.time_to_first_token = getCurrentUnixTimestamp() - state.startTime;
|
|
26426
|
+
}
|
|
26427
|
+
async function handlePiAgentEvent(state, event) {
|
|
26428
|
+
if (state.finalized) {
|
|
26429
|
+
return;
|
|
26430
|
+
}
|
|
26431
|
+
const eventPromptState = state.streamPatchState.eventPromptState;
|
|
26432
|
+
if (eventPromptState && eventPromptState !== state) {
|
|
26433
|
+
return;
|
|
26434
|
+
}
|
|
26435
|
+
if (!eventPromptState && (state.queued || state.streamPatchState.activePromptStates.size > 1 && currentPiPromptState() !== state)) {
|
|
26436
|
+
return;
|
|
26437
|
+
}
|
|
26438
|
+
switch (event.type) {
|
|
26439
|
+
case "message_end":
|
|
26440
|
+
if (isPiAssistantMessage(event.message)) {
|
|
26441
|
+
state.output = extractAssistantOutput(event.message);
|
|
26442
|
+
}
|
|
26443
|
+
return;
|
|
26444
|
+
case "turn_end":
|
|
26445
|
+
state.turnEnded = true;
|
|
26446
|
+
if (isPiAssistantMessage(event.message)) {
|
|
26447
|
+
state.output = extractAssistantOutput(event.message);
|
|
26448
|
+
if (!state.collectedLlmUsageMetrics) {
|
|
26449
|
+
addMetrics(state.metrics, extractUsageMetrics2(event.message.usage));
|
|
26450
|
+
}
|
|
26451
|
+
}
|
|
26452
|
+
if (state.streamPatchState.eventPromptState === state) {
|
|
26453
|
+
state.streamPatchState.eventPromptState = void 0;
|
|
26454
|
+
}
|
|
26455
|
+
if (state.promptCallEnded && state.deferCompletionUntilTurnEnd) {
|
|
26456
|
+
await finalizePiPromptRun(state);
|
|
26457
|
+
}
|
|
26458
|
+
return;
|
|
26459
|
+
case "tool_execution_start":
|
|
26460
|
+
await startPiToolSpan(state, event);
|
|
26461
|
+
return;
|
|
26462
|
+
case "tool_execution_end":
|
|
26463
|
+
finishPiToolSpan(state, event);
|
|
26464
|
+
return;
|
|
26465
|
+
default:
|
|
26466
|
+
return;
|
|
26467
|
+
}
|
|
26468
|
+
}
|
|
26469
|
+
async function startPiToolSpan(state, event) {
|
|
26470
|
+
if (!event.toolCallId || state.activeToolSpans.has(event.toolCallId)) {
|
|
26471
|
+
return;
|
|
26472
|
+
}
|
|
26473
|
+
const restoreAutoInstrumentation = enterAutoInstrumentationAllowed();
|
|
26474
|
+
const metadata = {
|
|
26475
|
+
"gen_ai.tool.call.id": event.toolCallId,
|
|
26476
|
+
"gen_ai.tool.name": event.toolName,
|
|
26477
|
+
"pi_coding_agent.tool.name": event.toolName
|
|
26478
|
+
};
|
|
26479
|
+
try {
|
|
26480
|
+
const span = startSpan({
|
|
26481
|
+
event: {
|
|
26482
|
+
input: event.args,
|
|
26483
|
+
metadata
|
|
26484
|
+
},
|
|
26485
|
+
name: event.toolName || "tool",
|
|
26486
|
+
parent: await state.span.export(),
|
|
26487
|
+
spanAttributes: { type: "tool" /* TOOL */ }
|
|
26488
|
+
});
|
|
26489
|
+
state.activeToolSpans.set(event.toolCallId, {
|
|
26490
|
+
restoreAutoInstrumentation,
|
|
26491
|
+
span
|
|
26492
|
+
});
|
|
26493
|
+
} catch (error) {
|
|
26494
|
+
restoreAutoInstrumentation();
|
|
26495
|
+
throw error;
|
|
26496
|
+
}
|
|
26497
|
+
}
|
|
26498
|
+
function finishPiToolSpan(state, event) {
|
|
26499
|
+
const toolState = state.activeToolSpans.get(event.toolCallId);
|
|
26500
|
+
if (!toolState) {
|
|
26501
|
+
return;
|
|
26502
|
+
}
|
|
26503
|
+
state.activeToolSpans.delete(event.toolCallId);
|
|
26504
|
+
const metadata = {
|
|
26505
|
+
"gen_ai.tool.call.id": event.toolCallId,
|
|
26506
|
+
"gen_ai.tool.name": event.toolName,
|
|
26507
|
+
"pi_coding_agent.tool.name": event.toolName,
|
|
26508
|
+
"pi_coding_agent.tool.is_error": event.isError
|
|
26509
|
+
};
|
|
26510
|
+
try {
|
|
26511
|
+
safeLog4(toolState.span, {
|
|
26512
|
+
...event.isError ? { error: stringifyUnknown2(event.result) } : {},
|
|
26513
|
+
metadata,
|
|
26514
|
+
output: event.result
|
|
26515
|
+
});
|
|
26516
|
+
} finally {
|
|
26517
|
+
try {
|
|
26518
|
+
toolState.span.end();
|
|
26519
|
+
} finally {
|
|
26520
|
+
toolState.restoreAutoInstrumentation?.();
|
|
26521
|
+
}
|
|
26522
|
+
}
|
|
26523
|
+
}
|
|
26524
|
+
async function finalizePiPromptRun(state, error) {
|
|
26525
|
+
if (state.finalized) {
|
|
26526
|
+
return;
|
|
26527
|
+
}
|
|
26528
|
+
state.finalized = true;
|
|
26529
|
+
state.onFinalize?.(state);
|
|
26530
|
+
restorePiStreamFn(state);
|
|
26531
|
+
try {
|
|
26532
|
+
state.unsubscribeAgent?.();
|
|
26533
|
+
} catch (unsubscribeError) {
|
|
26534
|
+
logInstrumentationError4("Pi Coding Agent unsubscribe", unsubscribeError);
|
|
26535
|
+
}
|
|
26536
|
+
await finishOpenLlmSpans(state, error);
|
|
26537
|
+
finishOpenToolSpans(state, error);
|
|
26538
|
+
const metadata = {
|
|
26539
|
+
...state.metadata,
|
|
26540
|
+
...extractModelMetadata2(state.agent.state?.model)
|
|
26541
|
+
};
|
|
26542
|
+
try {
|
|
26543
|
+
safeLog4(state.span, {
|
|
26544
|
+
...error ? { error: stringifyUnknown2(error) } : {},
|
|
26545
|
+
metadata,
|
|
26546
|
+
metrics: {
|
|
26547
|
+
...cleanMetrics5(state.metrics),
|
|
26548
|
+
...buildDurationMetrics3(state.startTime)
|
|
26549
|
+
},
|
|
26550
|
+
output: state.output
|
|
26551
|
+
});
|
|
26552
|
+
} finally {
|
|
26553
|
+
state.span.end();
|
|
26554
|
+
}
|
|
26555
|
+
}
|
|
26556
|
+
function restorePiStreamFn(state) {
|
|
26557
|
+
const patchState = state.streamPatchState;
|
|
26558
|
+
patchState.activePromptStates.delete(state);
|
|
26559
|
+
removeQueuedPromptState(state);
|
|
26560
|
+
if (patchState.eventPromptState === state) {
|
|
26561
|
+
patchState.eventPromptState = void 0;
|
|
26562
|
+
}
|
|
26563
|
+
state.restorePromptContext?.();
|
|
26564
|
+
if (patchState.activePromptStates.size > 0) {
|
|
26565
|
+
return;
|
|
26566
|
+
}
|
|
26567
|
+
if (patchState.agent.streamFn === patchState.wrappedStreamFn) {
|
|
26568
|
+
patchState.agent.streamFn = patchState.originalStreamFn;
|
|
26569
|
+
}
|
|
26570
|
+
piStreamPatchStates.delete(patchState.agent);
|
|
26571
|
+
}
|
|
26572
|
+
function removeQueuedPromptState(state) {
|
|
26573
|
+
state.queued = false;
|
|
26574
|
+
const queuedPromptStates = state.streamPatchState.queuedPromptStates;
|
|
26575
|
+
const index = queuedPromptStates.indexOf(state);
|
|
26576
|
+
if (index >= 0) {
|
|
26577
|
+
queuedPromptStates.splice(index, 1);
|
|
26578
|
+
}
|
|
26579
|
+
}
|
|
26580
|
+
async function finishOpenLlmSpans(state, error) {
|
|
26581
|
+
for (const llmState of [...state.activeLlmSpans]) {
|
|
26582
|
+
finishPiLlmSpan(state, llmState, void 0, error);
|
|
26583
|
+
}
|
|
26584
|
+
}
|
|
26585
|
+
function finishPiLlmSpan(promptState, llmState, message, error) {
|
|
26586
|
+
if (llmState.finalized) {
|
|
26587
|
+
return;
|
|
26588
|
+
}
|
|
26589
|
+
llmState.finalized = true;
|
|
26590
|
+
promptState.activeLlmSpans.delete(llmState);
|
|
26591
|
+
const messageError = message?.stopReason === "error" && message.errorMessage;
|
|
26592
|
+
const metrics = {
|
|
26593
|
+
...extractUsageMetrics2(message?.usage),
|
|
26594
|
+
...cleanMetrics5(llmState.metrics),
|
|
26595
|
+
...buildDurationMetrics3(llmState.startTime)
|
|
26596
|
+
};
|
|
26597
|
+
const usageMetrics = extractUsageMetrics2(message?.usage);
|
|
26598
|
+
if (Object.keys(usageMetrics).length > 0) {
|
|
26599
|
+
promptState.collectedLlmUsageMetrics = true;
|
|
26600
|
+
addMetrics(promptState.metrics, usageMetrics);
|
|
26601
|
+
}
|
|
26602
|
+
try {
|
|
26603
|
+
safeLog4(llmState.span, {
|
|
26604
|
+
...error || messageError ? { error: stringifyUnknown2(error ?? messageError) } : {},
|
|
26605
|
+
metadata: {
|
|
26606
|
+
...llmState.metadata,
|
|
26607
|
+
...message ? extractAssistantMetadata(message) : {}
|
|
26608
|
+
},
|
|
26609
|
+
metrics,
|
|
26610
|
+
...message ? { output: extractAssistantOutput(message) } : {}
|
|
26611
|
+
});
|
|
26612
|
+
} finally {
|
|
26613
|
+
llmState.span.end();
|
|
26614
|
+
}
|
|
26615
|
+
}
|
|
26616
|
+
function finishOpenToolSpans(state, error) {
|
|
26617
|
+
for (const [, toolState] of state.activeToolSpans) {
|
|
26618
|
+
try {
|
|
26619
|
+
safeLog4(toolState.span, {
|
|
26620
|
+
error: error ? stringifyUnknown2(error) : "Pi tool did not complete"
|
|
26621
|
+
});
|
|
26622
|
+
toolState.span.end();
|
|
26623
|
+
} finally {
|
|
26624
|
+
toolState.restoreAutoInstrumentation?.();
|
|
26625
|
+
}
|
|
26626
|
+
}
|
|
26627
|
+
state.activeToolSpans.clear();
|
|
26628
|
+
}
|
|
26629
|
+
function normalizePiContextInput(context) {
|
|
26630
|
+
const messages = context.messages.flatMap(
|
|
26631
|
+
(message) => normalizePiMessage(message)
|
|
26632
|
+
);
|
|
26633
|
+
if (context.systemPrompt) {
|
|
26634
|
+
return [{ role: "system", content: context.systemPrompt }, ...messages];
|
|
26635
|
+
}
|
|
26636
|
+
return messages;
|
|
26637
|
+
}
|
|
26638
|
+
function normalizePiMessage(message) {
|
|
26639
|
+
if (isPiUserMessage(message)) {
|
|
26640
|
+
return [
|
|
26641
|
+
{
|
|
26642
|
+
role: "user",
|
|
26643
|
+
content: normalizeUserContent(message.content)
|
|
26644
|
+
}
|
|
26645
|
+
];
|
|
26646
|
+
}
|
|
26647
|
+
if (isPiAssistantMessage(message)) {
|
|
26648
|
+
return [normalizeAssistantMessage(message)];
|
|
26649
|
+
}
|
|
26650
|
+
if (isPiToolResultMessage(message)) {
|
|
26651
|
+
return [normalizeToolResultMessage(message)];
|
|
26652
|
+
}
|
|
26653
|
+
return [];
|
|
26654
|
+
}
|
|
26655
|
+
function normalizeAssistantMessage(message) {
|
|
26656
|
+
const text = message.content.flatMap((part) => part.type === "text" ? [part.text] : []).join("");
|
|
26657
|
+
const thinking = message.content.flatMap(
|
|
26658
|
+
(part) => part.type === "thinking" && !part.redacted ? [part.thinking] : []
|
|
26659
|
+
).join("");
|
|
26660
|
+
const toolCalls = message.content.flatMap(
|
|
26661
|
+
(part) => part.type === "toolCall" ? [normalizeToolCall(part)] : []
|
|
26662
|
+
);
|
|
26663
|
+
return {
|
|
26664
|
+
role: "assistant",
|
|
26665
|
+
content: text || (toolCalls.length > 0 ? null : ""),
|
|
26666
|
+
...thinking ? { reasoning: thinking } : {},
|
|
26667
|
+
...toolCalls.length > 0 ? { tool_calls: toolCalls } : {}
|
|
26668
|
+
};
|
|
26669
|
+
}
|
|
26670
|
+
function normalizeToolResultMessage(message) {
|
|
26671
|
+
return {
|
|
26672
|
+
role: "tool",
|
|
26673
|
+
tool_call_id: message.toolCallId,
|
|
26674
|
+
content: normalizeUserContent(message.content)
|
|
26675
|
+
};
|
|
26676
|
+
}
|
|
26677
|
+
function normalizeUserContent(content) {
|
|
26678
|
+
if (typeof content === "string") {
|
|
26679
|
+
return content;
|
|
26680
|
+
}
|
|
26681
|
+
return content.map((part) => {
|
|
26682
|
+
if (part.type === "text") {
|
|
26683
|
+
return { type: "text", text: part.text };
|
|
26684
|
+
}
|
|
26685
|
+
if (part.type === "image") {
|
|
26686
|
+
return {
|
|
26687
|
+
type: "image_url",
|
|
26688
|
+
image_url: {
|
|
26689
|
+
url: `data:${part.mimeType};base64,${part.data}`
|
|
26690
|
+
}
|
|
26691
|
+
};
|
|
26692
|
+
}
|
|
26693
|
+
return part;
|
|
26694
|
+
});
|
|
26695
|
+
}
|
|
26696
|
+
function normalizeToolCall(toolCall) {
|
|
26697
|
+
return {
|
|
26698
|
+
id: toolCall.id,
|
|
26699
|
+
type: "function",
|
|
26700
|
+
function: {
|
|
26701
|
+
name: toolCall.name,
|
|
26702
|
+
arguments: stringifyArguments(toolCall.arguments)
|
|
26703
|
+
}
|
|
26704
|
+
};
|
|
26705
|
+
}
|
|
26706
|
+
function extractAssistantOutput(message) {
|
|
26707
|
+
return processInputAttachments([
|
|
26708
|
+
{
|
|
26709
|
+
finish_reason: normalizeStopReason(message.stopReason),
|
|
26710
|
+
index: 0,
|
|
26711
|
+
message: normalizeAssistantMessage(message)
|
|
26712
|
+
}
|
|
26713
|
+
]);
|
|
26714
|
+
}
|
|
26715
|
+
function isPiUserMessage(message) {
|
|
26716
|
+
return message.role === "user" && "content" in message;
|
|
26717
|
+
}
|
|
26718
|
+
function isPiAssistantMessage(message) {
|
|
26719
|
+
return isObject(message) && message.role === "assistant" && Array.isArray(message.content);
|
|
26720
|
+
}
|
|
26721
|
+
function isPiToolResultMessage(message) {
|
|
26722
|
+
return message.role === "toolResult" && Array.isArray(message.content);
|
|
26723
|
+
}
|
|
26724
|
+
function normalizeStopReason(reason) {
|
|
26725
|
+
switch (reason) {
|
|
26726
|
+
case "toolUse":
|
|
26727
|
+
return "tool_calls";
|
|
26728
|
+
case "length":
|
|
26729
|
+
case "stop":
|
|
26730
|
+
return reason;
|
|
26731
|
+
default:
|
|
26732
|
+
return reason ?? "stop";
|
|
26733
|
+
}
|
|
26734
|
+
}
|
|
26735
|
+
function extractPromptInput(text, options) {
|
|
26736
|
+
const images = options?.images;
|
|
26737
|
+
if (!images || images.length === 0) {
|
|
26738
|
+
return text;
|
|
26739
|
+
}
|
|
26740
|
+
return processInputAttachments([
|
|
26741
|
+
{
|
|
26742
|
+
role: "user",
|
|
26743
|
+
content: [
|
|
26744
|
+
{ type: "text", text: text ?? "" },
|
|
26745
|
+
...images.map((image) => ({
|
|
26746
|
+
type: "image_url",
|
|
26747
|
+
image_url: {
|
|
26748
|
+
url: `data:${image.mimeType};base64,${image.data}`
|
|
26749
|
+
}
|
|
26750
|
+
}))
|
|
26751
|
+
]
|
|
26752
|
+
}
|
|
26753
|
+
]);
|
|
26754
|
+
}
|
|
26755
|
+
function extractToolMetadata(tools) {
|
|
26756
|
+
if (!tools || tools.length === 0) {
|
|
26757
|
+
return {};
|
|
26758
|
+
}
|
|
26759
|
+
return {
|
|
26760
|
+
tools: tools.map((tool) => ({
|
|
26761
|
+
type: "function",
|
|
26762
|
+
function: {
|
|
26763
|
+
name: tool.name,
|
|
26764
|
+
...tool.description ? { description: tool.description } : {},
|
|
26765
|
+
...tool.parameters ? { parameters: tool.parameters } : {}
|
|
26766
|
+
}
|
|
26767
|
+
}))
|
|
26768
|
+
};
|
|
26769
|
+
}
|
|
26770
|
+
function extractModelMetadata2(model) {
|
|
26771
|
+
if (!model) {
|
|
26772
|
+
return {};
|
|
26773
|
+
}
|
|
26774
|
+
return {
|
|
26775
|
+
...model.provider ? { provider: model.provider } : {},
|
|
26776
|
+
...model.id ? { model: model.id, "pi_coding_agent.model": model.id } : {},
|
|
26777
|
+
...model.api ? { "pi_coding_agent.api": model.api } : {},
|
|
26778
|
+
...model.name ? { "pi_coding_agent.model_name": model.name } : {}
|
|
26779
|
+
};
|
|
26780
|
+
}
|
|
26781
|
+
function extractAssistantMetadata(message) {
|
|
26782
|
+
return {
|
|
26783
|
+
...message.provider ? { provider: message.provider } : {},
|
|
26784
|
+
...message.responseModel || message.model ? { model: message.responseModel ?? message.model } : {},
|
|
26785
|
+
...message.api ? { "pi_coding_agent.api": message.api } : {},
|
|
26786
|
+
...message.model ? { "pi_coding_agent.model": message.model } : {},
|
|
26787
|
+
...message.responseModel ? { "pi_coding_agent.response_model": message.responseModel } : {},
|
|
26788
|
+
...message.responseId ? { "pi_coding_agent.response_id": message.responseId } : {},
|
|
26789
|
+
...message.stopReason ? { "pi_coding_agent.stop_reason": message.stopReason } : {}
|
|
26790
|
+
};
|
|
26791
|
+
}
|
|
26792
|
+
function extractSessionMetadata(session) {
|
|
26793
|
+
return {
|
|
26794
|
+
...extractModelMetadata2(session.model),
|
|
26795
|
+
...session.sessionId ? { "pi_coding_agent.session_id": session.sessionId } : {},
|
|
26796
|
+
...session.sessionName ? { "pi_coding_agent.session_name": session.sessionName } : {},
|
|
26797
|
+
...session.thinkingLevel ? { "pi_coding_agent.thinking_level": session.thinkingLevel } : {},
|
|
26798
|
+
...typeof session.getActiveToolNames === "function" ? { "pi_coding_agent.active_tools": session.getActiveToolNames() } : {}
|
|
26799
|
+
};
|
|
26800
|
+
}
|
|
26801
|
+
function extractPromptOptionsMetadata(options) {
|
|
26802
|
+
if (!options) {
|
|
26803
|
+
return {};
|
|
26804
|
+
}
|
|
26805
|
+
return {
|
|
26806
|
+
...options.source ? { "pi_coding_agent.source": options.source } : {},
|
|
26807
|
+
...options.streamingBehavior ? { "pi_coding_agent.streaming_behavior": options.streamingBehavior } : {},
|
|
26808
|
+
...options.expandPromptTemplates !== void 0 ? {
|
|
26809
|
+
"pi_coding_agent.expand_prompt_templates": options.expandPromptTemplates
|
|
26810
|
+
} : {}
|
|
26811
|
+
};
|
|
26812
|
+
}
|
|
26813
|
+
function extractStreamOptionsMetadata(options) {
|
|
26814
|
+
if (!options) {
|
|
26815
|
+
return {};
|
|
26816
|
+
}
|
|
26817
|
+
return {
|
|
26818
|
+
...options.temperature !== void 0 ? { temperature: options.temperature } : {},
|
|
26819
|
+
...options.maxTokens !== void 0 ? { max_tokens: options.maxTokens } : {},
|
|
26820
|
+
...options.reasoning ? { "pi_coding_agent.reasoning": options.reasoning } : {},
|
|
26821
|
+
...options.transport ? { "pi_coding_agent.transport": options.transport } : {},
|
|
26822
|
+
...options.cacheRetention ? { "pi_coding_agent.cache_retention": options.cacheRetention } : {},
|
|
26823
|
+
...options.sessionId ? { "pi_coding_agent.session_id": options.sessionId } : {},
|
|
26824
|
+
...options.timeoutMs !== void 0 ? { "pi_coding_agent.timeout_ms": options.timeoutMs } : {},
|
|
26825
|
+
...options.maxRetries !== void 0 ? { "pi_coding_agent.max_retries": options.maxRetries } : {},
|
|
26826
|
+
...options.maxRetryDelayMs !== void 0 ? { "pi_coding_agent.max_retry_delay_ms": options.maxRetryDelayMs } : {},
|
|
26827
|
+
...options.metadata ? { "pi_coding_agent.metadata": options.metadata } : {}
|
|
26828
|
+
};
|
|
26829
|
+
}
|
|
26830
|
+
function getLlmSpanName(model) {
|
|
26831
|
+
switch (model.api) {
|
|
26832
|
+
case "anthropic-messages":
|
|
26833
|
+
return "anthropic.messages.create";
|
|
26834
|
+
case "openai-completions":
|
|
26835
|
+
return "Chat Completion";
|
|
26836
|
+
case "openai-responses":
|
|
26837
|
+
case "azure-openai-responses":
|
|
26838
|
+
case "openai-codex-responses":
|
|
26839
|
+
return "openai.responses.create";
|
|
26840
|
+
case "google-generative-ai":
|
|
26841
|
+
case "google-vertex":
|
|
26842
|
+
return "generate_content";
|
|
26843
|
+
case "mistral-conversations":
|
|
26844
|
+
return "mistral.chat.stream";
|
|
26845
|
+
case "bedrock-converse-stream":
|
|
26846
|
+
return "bedrock.converse_stream";
|
|
26847
|
+
default:
|
|
26848
|
+
return "pi_ai.streamSimple";
|
|
26849
|
+
}
|
|
26850
|
+
}
|
|
26851
|
+
function extractUsageMetrics2(usage) {
|
|
26852
|
+
if (!usage) {
|
|
26853
|
+
return {};
|
|
26854
|
+
}
|
|
26855
|
+
return cleanMetrics5({
|
|
26856
|
+
completion_tokens: usage.output,
|
|
26857
|
+
prompt_cache_creation_tokens: usage.cacheWrite,
|
|
26858
|
+
prompt_cached_tokens: usage.cacheRead,
|
|
26859
|
+
prompt_tokens: usage.input,
|
|
26860
|
+
tokens: usage.totalTokens ?? usage.tokens
|
|
26861
|
+
});
|
|
26862
|
+
}
|
|
26863
|
+
function addMetrics(target, source) {
|
|
26864
|
+
for (const [key, value] of Object.entries(source)) {
|
|
26865
|
+
target[key] = (target[key] ?? 0) + value;
|
|
26866
|
+
}
|
|
26867
|
+
}
|
|
26868
|
+
function buildDurationMetrics3(startTime) {
|
|
26869
|
+
const end = getCurrentUnixTimestamp();
|
|
26870
|
+
return {
|
|
26871
|
+
duration: end - startTime,
|
|
26872
|
+
end,
|
|
26873
|
+
start: startTime
|
|
26874
|
+
};
|
|
26875
|
+
}
|
|
26876
|
+
function cleanMetrics5(metrics) {
|
|
26877
|
+
const cleaned = {};
|
|
26878
|
+
for (const [key, value] of Object.entries(metrics)) {
|
|
26879
|
+
if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
|
|
26880
|
+
cleaned[key] = value;
|
|
26881
|
+
}
|
|
26882
|
+
}
|
|
26883
|
+
return cleaned;
|
|
26884
|
+
}
|
|
26885
|
+
function stringifyArguments(value) {
|
|
26886
|
+
if (typeof value === "string") {
|
|
26887
|
+
return value;
|
|
26888
|
+
}
|
|
26889
|
+
try {
|
|
26890
|
+
return JSON.stringify(value);
|
|
26891
|
+
} catch {
|
|
26892
|
+
return stringifyUnknown2(value);
|
|
26893
|
+
}
|
|
26894
|
+
}
|
|
26895
|
+
function stringifyUnknown2(value) {
|
|
26896
|
+
if (value instanceof Error) {
|
|
26897
|
+
return value.message;
|
|
26898
|
+
}
|
|
26899
|
+
if (typeof value === "string") {
|
|
26900
|
+
return value;
|
|
26901
|
+
}
|
|
26902
|
+
try {
|
|
26903
|
+
return JSON.stringify(value);
|
|
26904
|
+
} catch {
|
|
26905
|
+
return String(value);
|
|
26906
|
+
}
|
|
26907
|
+
}
|
|
26908
|
+
function safeLog4(span, event) {
|
|
26909
|
+
try {
|
|
26910
|
+
span.log(event);
|
|
26911
|
+
} catch (error) {
|
|
26912
|
+
logInstrumentationError4("Pi Coding Agent span log", error);
|
|
26913
|
+
}
|
|
26914
|
+
}
|
|
26915
|
+
function logInstrumentationError4(context, error) {
|
|
26916
|
+
debugLogger.debug(`${context}:`, error);
|
|
26917
|
+
}
|
|
26918
|
+
|
|
24882
26919
|
// src/instrumentation/braintrust-plugin.ts
|
|
24883
26920
|
function getIntegrationConfig(integrations, key) {
|
|
24884
26921
|
return integrations[key];
|
|
@@ -24904,6 +26941,7 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
24904
26941
|
gitHubCopilotPlugin = null;
|
|
24905
26942
|
fluePlugin = null;
|
|
24906
26943
|
langChainPlugin = null;
|
|
26944
|
+
piCodingAgentPlugin = null;
|
|
24907
26945
|
constructor(config = {}) {
|
|
24908
26946
|
super();
|
|
24909
26947
|
this.config = config;
|
|
@@ -24978,6 +27016,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
24978
27016
|
this.gitHubCopilotPlugin = new GitHubCopilotPlugin();
|
|
24979
27017
|
this.gitHubCopilotPlugin.enable();
|
|
24980
27018
|
}
|
|
27019
|
+
if (integrations.piCodingAgent !== false) {
|
|
27020
|
+
this.piCodingAgentPlugin = new PiCodingAgentPlugin();
|
|
27021
|
+
this.piCodingAgentPlugin.enable();
|
|
27022
|
+
}
|
|
24981
27023
|
if (getIntegrationConfig(integrations, "flue") !== false) {
|
|
24982
27024
|
this.fluePlugin = new FluePlugin();
|
|
24983
27025
|
this.fluePlugin.enable();
|
|
@@ -25056,6 +27098,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
25056
27098
|
this.gitHubCopilotPlugin.disable();
|
|
25057
27099
|
this.gitHubCopilotPlugin = null;
|
|
25058
27100
|
}
|
|
27101
|
+
if (this.piCodingAgentPlugin) {
|
|
27102
|
+
this.piCodingAgentPlugin.disable();
|
|
27103
|
+
this.piCodingAgentPlugin = null;
|
|
27104
|
+
}
|
|
25059
27105
|
if (this.fluePlugin) {
|
|
25060
27106
|
this.fluePlugin.disable();
|
|
25061
27107
|
this.fluePlugin = null;
|
|
@@ -25510,6 +27556,7 @@ __export(exports_exports, {
|
|
|
25510
27556
|
_internalIso: () => isomorph_default,
|
|
25511
27557
|
_internalSetInitialState: () => _internalSetInitialState,
|
|
25512
27558
|
addAzureBlobHeaders: () => addAzureBlobHeaders,
|
|
27559
|
+
braintrustAISDKTelemetry: () => braintrustAISDKTelemetry,
|
|
25513
27560
|
braintrustFlueObserver: () => braintrustFlueObserver,
|
|
25514
27561
|
braintrustStreamChunkSchema: () => braintrustStreamChunkSchema,
|
|
25515
27562
|
buildLocalSummary: () => buildLocalSummary,
|
|
@@ -25602,6 +27649,7 @@ __export(exports_exports, {
|
|
|
25602
27649
|
wrapOpenAIv4: () => wrapOpenAIv4,
|
|
25603
27650
|
wrapOpenRouter: () => wrapOpenRouter,
|
|
25604
27651
|
wrapOpenRouterAgent: () => wrapOpenRouterAgent,
|
|
27652
|
+
wrapPiCodingAgentSDK: () => wrapPiCodingAgentSDK,
|
|
25605
27653
|
wrapTraced: () => wrapTraced,
|
|
25606
27654
|
wrapVitest: () => wrapVitest
|
|
25607
27655
|
});
|
|
@@ -27467,6 +29515,54 @@ function wrapCursorAgent(agent) {
|
|
|
27467
29515
|
return proxy;
|
|
27468
29516
|
}
|
|
27469
29517
|
|
|
29518
|
+
// src/wrappers/pi-coding-agent.ts
|
|
29519
|
+
var WRAPPED_PROMPT = /* @__PURE__ */ Symbol.for("braintrust.pi-coding-agent.wrapped-prompt");
|
|
29520
|
+
function wrapPiCodingAgentSDK(sdk) {
|
|
29521
|
+
if (!sdk || typeof sdk !== "object") {
|
|
29522
|
+
return sdk;
|
|
29523
|
+
}
|
|
29524
|
+
const maybeSDK = sdk;
|
|
29525
|
+
if (!maybeSDK.AgentSession || typeof maybeSDK.AgentSession !== "function") {
|
|
29526
|
+
console.warn("Unsupported Pi Coding Agent SDK. Not wrapping.");
|
|
29527
|
+
return sdk;
|
|
29528
|
+
}
|
|
29529
|
+
patchAgentSessionClass(
|
|
29530
|
+
maybeSDK.AgentSession
|
|
29531
|
+
);
|
|
29532
|
+
return sdk;
|
|
29533
|
+
}
|
|
29534
|
+
function patchAgentSessionClass(AgentSession) {
|
|
29535
|
+
const prototype = AgentSession.prototype;
|
|
29536
|
+
if (!prototype || prototype[WRAPPED_PROMPT]) {
|
|
29537
|
+
return;
|
|
29538
|
+
}
|
|
29539
|
+
const descriptor = Object.getOwnPropertyDescriptor(prototype, "prompt");
|
|
29540
|
+
if (!descriptor || typeof descriptor.value !== "function") {
|
|
29541
|
+
console.warn("Unsupported Pi Coding Agent SDK. Not wrapping.");
|
|
29542
|
+
return;
|
|
29543
|
+
}
|
|
29544
|
+
const originalPrompt = descriptor.value;
|
|
29545
|
+
Object.defineProperty(prototype, "prompt", {
|
|
29546
|
+
...descriptor,
|
|
29547
|
+
value: function wrappedPiCodingAgentPrompt(text, options) {
|
|
29548
|
+
const args = [text, options];
|
|
29549
|
+
return piCodingAgentChannels.prompt.tracePromise(
|
|
29550
|
+
() => Reflect.apply(originalPrompt, this, args),
|
|
29551
|
+
{
|
|
29552
|
+
arguments: args,
|
|
29553
|
+
self: this,
|
|
29554
|
+
session: this
|
|
29555
|
+
}
|
|
29556
|
+
);
|
|
29557
|
+
}
|
|
29558
|
+
});
|
|
29559
|
+
Object.defineProperty(prototype, WRAPPED_PROMPT, {
|
|
29560
|
+
configurable: false,
|
|
29561
|
+
enumerable: false,
|
|
29562
|
+
value: true
|
|
29563
|
+
});
|
|
29564
|
+
}
|
|
29565
|
+
|
|
27470
29566
|
// src/wrappers/google-genai.ts
|
|
27471
29567
|
function wrapGoogleGenAI(googleGenAI) {
|
|
27472
29568
|
if (!googleGenAI || typeof googleGenAI !== "object") {
|
|
@@ -27503,12 +29599,25 @@ function wrapGoogleGenAIClass(OriginalGoogleGenAI) {
|
|
|
27503
29599
|
}
|
|
27504
29600
|
function wrapGoogleGenAIInstance(instance) {
|
|
27505
29601
|
const wrappedModels = wrapModels(instance.models);
|
|
29602
|
+
let originalInteractions;
|
|
29603
|
+
let wrappedInteractions;
|
|
27506
29604
|
patchGoogleGenAIChats(instance, wrappedModels);
|
|
27507
29605
|
return new Proxy(instance, {
|
|
27508
29606
|
get(target, prop, receiver) {
|
|
27509
29607
|
if (prop === "models") {
|
|
27510
29608
|
return wrappedModels;
|
|
27511
29609
|
}
|
|
29610
|
+
if (prop === "interactions") {
|
|
29611
|
+
const interactions = Reflect.get(target, prop, receiver);
|
|
29612
|
+
if (!isObject(interactions) || typeof interactions.create !== "function") {
|
|
29613
|
+
return interactions;
|
|
29614
|
+
}
|
|
29615
|
+
if (interactions !== originalInteractions) {
|
|
29616
|
+
originalInteractions = interactions;
|
|
29617
|
+
wrappedInteractions = wrapInteractions(interactions);
|
|
29618
|
+
}
|
|
29619
|
+
return wrappedInteractions;
|
|
29620
|
+
}
|
|
27512
29621
|
return Reflect.get(target, prop, receiver);
|
|
27513
29622
|
}
|
|
27514
29623
|
});
|
|
@@ -27535,6 +29644,16 @@ function wrapModels(models) {
|
|
|
27535
29644
|
}
|
|
27536
29645
|
});
|
|
27537
29646
|
}
|
|
29647
|
+
function wrapInteractions(interactions) {
|
|
29648
|
+
return new Proxy(interactions, {
|
|
29649
|
+
get(target, prop, receiver) {
|
|
29650
|
+
if (prop === "create") {
|
|
29651
|
+
return wrapInteractionCreate(target.create.bind(target));
|
|
29652
|
+
}
|
|
29653
|
+
return Reflect.get(target, prop, receiver);
|
|
29654
|
+
}
|
|
29655
|
+
});
|
|
29656
|
+
}
|
|
27538
29657
|
function wrapGenerateContent(original) {
|
|
27539
29658
|
return function(params) {
|
|
27540
29659
|
return googleGenAIChannels.generateContent.tracePromise(
|
|
@@ -27559,6 +29678,18 @@ function wrapEmbedContent(original) {
|
|
|
27559
29678
|
);
|
|
27560
29679
|
};
|
|
27561
29680
|
}
|
|
29681
|
+
function wrapInteractionCreate(original) {
|
|
29682
|
+
return function(params, options) {
|
|
29683
|
+
if (params.background === true) {
|
|
29684
|
+
return options === void 0 ? original(params) : original(params, options);
|
|
29685
|
+
}
|
|
29686
|
+
const traceContext = options === void 0 ? { arguments: [params] } : { arguments: [params, options] };
|
|
29687
|
+
return googleGenAIChannels.interactionsCreate.tracePromise(
|
|
29688
|
+
() => options === void 0 ? original(params) : original(params, options),
|
|
29689
|
+
traceContext
|
|
29690
|
+
);
|
|
29691
|
+
};
|
|
29692
|
+
}
|
|
27562
29693
|
|
|
27563
29694
|
// src/wrappers/google-adk.ts
|
|
27564
29695
|
function wrapGoogleADK(adkModule) {
|
|
@@ -31076,6 +33207,13 @@ var EvalResultWithSummary = class {
|
|
|
31076
33207
|
};
|
|
31077
33208
|
}
|
|
31078
33209
|
};
|
|
33210
|
+
async function getPersistedBaseExperimentId(experiment) {
|
|
33211
|
+
try {
|
|
33212
|
+
return await experiment._getBaseExperimentId();
|
|
33213
|
+
} catch {
|
|
33214
|
+
return void 0;
|
|
33215
|
+
}
|
|
33216
|
+
}
|
|
31079
33217
|
function makeEvalName(projectName, experimentName) {
|
|
31080
33218
|
let out = projectName;
|
|
31081
33219
|
if (experimentName) {
|
|
@@ -31458,6 +33596,14 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
|
|
|
31458
33596
|
return;
|
|
31459
33597
|
}
|
|
31460
33598
|
const eventDataset = experiment ? experiment.dataset : Dataset2.isDataset(evaluator.data) ? evaluator.data : void 0;
|
|
33599
|
+
const inlineOrigin = datum.origin === void 0 ? void 0 : ObjectReference.parse(datum.origin);
|
|
33600
|
+
const origin = inlineOrigin ?? (eventDataset && datum.id && datum._xact_id ? {
|
|
33601
|
+
object_type: "dataset",
|
|
33602
|
+
object_id: await eventDataset.id,
|
|
33603
|
+
id: datum.id,
|
|
33604
|
+
created: datum.created,
|
|
33605
|
+
_xact_id: datum._xact_id
|
|
33606
|
+
} : void 0);
|
|
31461
33607
|
const baseEvent = {
|
|
31462
33608
|
name: "eval",
|
|
31463
33609
|
spanAttributes: {
|
|
@@ -31467,13 +33613,7 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
|
|
|
31467
33613
|
input: datum.input,
|
|
31468
33614
|
expected: "expected" in datum ? datum.expected : void 0,
|
|
31469
33615
|
tags: datum.tags,
|
|
31470
|
-
origin
|
|
31471
|
-
object_type: "dataset",
|
|
31472
|
-
object_id: await eventDataset.id,
|
|
31473
|
-
id: datum.id,
|
|
31474
|
-
created: datum.created,
|
|
31475
|
-
_xact_id: datum._xact_id
|
|
31476
|
-
} : void 0,
|
|
33616
|
+
origin,
|
|
31477
33617
|
...datum.upsert_id ? { id: datum.upsert_id } : {}
|
|
31478
33618
|
}
|
|
31479
33619
|
};
|
|
@@ -31830,8 +33970,10 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
|
|
|
31830
33970
|
collectedResults.length = 0;
|
|
31831
33971
|
}
|
|
31832
33972
|
}
|
|
33973
|
+
const comparisonExperimentId = experiment ? evaluator.baseExperimentId ?? await getPersistedBaseExperimentId(experiment) : void 0;
|
|
31833
33974
|
const summary = experiment ? await experiment.summarize({
|
|
31834
|
-
summarizeScores: evaluator.summarizeScores
|
|
33975
|
+
summarizeScores: evaluator.summarizeScores,
|
|
33976
|
+
...comparisonExperimentId !== void 0 ? { comparisonExperimentId } : {}
|
|
31835
33977
|
}) : buildLocalSummary(
|
|
31836
33978
|
evaluator,
|
|
31837
33979
|
collectResults ? collectedResults : [],
|
|
@@ -32060,6 +34202,7 @@ var Project2 = class {
|
|
|
32060
34202
|
prompts;
|
|
32061
34203
|
parameters;
|
|
32062
34204
|
scorers;
|
|
34205
|
+
classifiers;
|
|
32063
34206
|
_publishableCodeFunctions = [];
|
|
32064
34207
|
_publishablePrompts = [];
|
|
32065
34208
|
_publishableParameters = [];
|
|
@@ -32071,6 +34214,7 @@ var Project2 = class {
|
|
|
32071
34214
|
this.prompts = new PromptBuilder(this);
|
|
32072
34215
|
this.parameters = new ParametersBuilder(this);
|
|
32073
34216
|
this.scorers = new ScorerBuilder(this);
|
|
34217
|
+
this.classifiers = new ClassifierBuilder(this);
|
|
32074
34218
|
}
|
|
32075
34219
|
addPrompt(prompt) {
|
|
32076
34220
|
this._publishablePrompts.push(prompt);
|
|
@@ -32205,6 +34349,28 @@ var ScorerBuilder = class {
|
|
|
32205
34349
|
}
|
|
32206
34350
|
}
|
|
32207
34351
|
};
|
|
34352
|
+
var ClassifierBuilder = class {
|
|
34353
|
+
constructor(project) {
|
|
34354
|
+
this.project = project;
|
|
34355
|
+
}
|
|
34356
|
+
taskCounter = 0;
|
|
34357
|
+
create(opts) {
|
|
34358
|
+
this.taskCounter++;
|
|
34359
|
+
let resolvedName = opts.name ?? opts.handler.name;
|
|
34360
|
+
if (!resolvedName || resolvedName.trim().length === 0) {
|
|
34361
|
+
resolvedName = `Classifier ${isomorph_default.basename(currentFilename)} ${this.taskCounter}`;
|
|
34362
|
+
}
|
|
34363
|
+
const slug = opts.slug ?? slugify(resolvedName, { lower: true, strict: true });
|
|
34364
|
+
const classifier = new CodeFunction(this.project, {
|
|
34365
|
+
...opts,
|
|
34366
|
+
name: resolvedName,
|
|
34367
|
+
slug,
|
|
34368
|
+
type: "classifier"
|
|
34369
|
+
});
|
|
34370
|
+
this.project.addCodeFunction(classifier);
|
|
34371
|
+
return classifier;
|
|
34372
|
+
}
|
|
34373
|
+
};
|
|
32208
34374
|
var CodeFunction = class {
|
|
32209
34375
|
constructor(project, opts) {
|
|
32210
34376
|
this.project = project;
|
|
@@ -32554,7 +34720,7 @@ var serializedParametersContainerSchema = z13.union([
|
|
|
32554
34720
|
staticParametersSchema
|
|
32555
34721
|
]);
|
|
32556
34722
|
var evaluatorDefinitionSchema = z13.object({
|
|
32557
|
-
parameters: serializedParametersContainerSchema.
|
|
34723
|
+
parameters: serializedParametersContainerSchema.nullish(),
|
|
32558
34724
|
scores: z13.array(z13.object({ name: z13.string() })).optional(),
|
|
32559
34725
|
classifiers: z13.array(z13.object({ name: z13.string() })).optional()
|
|
32560
34726
|
});
|
|
@@ -32622,6 +34788,7 @@ export {
|
|
|
32622
34788
|
isomorph_default as _internalIso,
|
|
32623
34789
|
_internalSetInitialState,
|
|
32624
34790
|
addAzureBlobHeaders,
|
|
34791
|
+
braintrustAISDKTelemetry,
|
|
32625
34792
|
braintrustFlueObserver,
|
|
32626
34793
|
braintrustStreamChunkSchema,
|
|
32627
34794
|
buildLocalSummary,
|
|
@@ -32715,6 +34882,7 @@ export {
|
|
|
32715
34882
|
wrapOpenAIv4,
|
|
32716
34883
|
wrapOpenRouter,
|
|
32717
34884
|
wrapOpenRouterAgent,
|
|
34885
|
+
wrapPiCodingAgentSDK,
|
|
32718
34886
|
wrapTraced,
|
|
32719
34887
|
wrapVitest
|
|
32720
34888
|
};
|