braintrust 3.17.0 → 3.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dev/dist/index.d.mts +13 -0
- package/dev/dist/index.d.ts +13 -0
- package/dev/dist/index.js +4300 -2199
- package/dev/dist/index.mjs +2211 -110
- package/dist/apply-auto-instrumentation.js +238 -186
- package/dist/apply-auto-instrumentation.mjs +68 -16
- package/dist/auto-instrumentations/bundler/esbuild.cjs +90 -15
- package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
- package/dist/auto-instrumentations/bundler/next.cjs +90 -15
- package/dist/auto-instrumentations/bundler/next.mjs +3 -3
- package/dist/auto-instrumentations/bundler/rollup.cjs +90 -15
- package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
- package/dist/auto-instrumentations/bundler/vite.cjs +90 -15
- package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
- package/dist/auto-instrumentations/bundler/webpack-loader.cjs +89 -14
- package/dist/auto-instrumentations/bundler/webpack.cjs +90 -15
- package/dist/auto-instrumentations/bundler/webpack.mjs +3 -3
- package/dist/auto-instrumentations/{chunk-VXJONZVX.mjs → chunk-GNUEZ2PE.mjs} +13 -3
- package/dist/auto-instrumentations/{chunk-CNQ7BUKN.mjs → chunk-MYCHHXOE.mjs} +1 -1
- package/dist/auto-instrumentations/{chunk-E5DUYJWK.mjs → chunk-ZYKZEMRT.mjs} +82 -15
- package/dist/auto-instrumentations/hook.mjs +102 -15
- package/dist/auto-instrumentations/index.cjs +84 -16
- package/dist/auto-instrumentations/index.d.mts +3 -1
- package/dist/auto-instrumentations/index.d.ts +3 -1
- package/dist/auto-instrumentations/index.mjs +5 -3
- package/dist/auto-instrumentations/loader/cjs-patch.cjs +1 -1
- package/dist/auto-instrumentations/loader/cjs-patch.mjs +1 -1
- package/dist/auto-instrumentations/loader/esm-hook.mjs +1 -1
- package/dist/browser.d.mts +177 -11
- package/dist/browser.d.ts +177 -11
- package/dist/browser.js +2296 -104
- package/dist/browser.mjs +2455 -263
- package/dist/{chunk-VMBQETG3.js → chunk-73IYIIOL.js} +28 -2
- package/dist/{chunk-O4ZIWXO3.mjs → chunk-BYFADLEZ.mjs} +27 -1
- package/dist/cli.js +2219 -118
- package/dist/edge-light.d.mts +1 -1
- package/dist/edge-light.d.ts +1 -1
- package/dist/edge-light.js +2296 -104
- package/dist/edge-light.mjs +2455 -263
- package/dist/index.d.mts +177 -11
- package/dist/index.d.ts +177 -11
- package/dist/index.js +3296 -1128
- package/dist/index.mjs +2272 -104
- package/dist/instrumentation/index.d.mts +3 -0
- package/dist/instrumentation/index.d.ts +3 -0
- package/dist/instrumentation/index.js +2171 -105
- package/dist/instrumentation/index.mjs +2171 -105
- package/dist/workerd.d.mts +1 -1
- package/dist/workerd.d.ts +1 -1
- package/dist/workerd.js +2296 -104
- package/dist/workerd.mjs +2455 -263
- package/package.json +10 -10
|
@@ -7174,6 +7174,10 @@ var Experiment2 = class extends ObjectFetcher {
|
|
|
7174
7174
|
return (await this.lazyMetadata.get()).project;
|
|
7175
7175
|
})();
|
|
7176
7176
|
}
|
|
7177
|
+
async _getBaseExperimentId() {
|
|
7178
|
+
const baseExperimentId = (await this.lazyMetadata.get()).experiment.fullInfo["base_exp_id"];
|
|
7179
|
+
return typeof baseExperimentId === "string" && baseExperimentId ? baseExperimentId : void 0;
|
|
7180
|
+
}
|
|
7177
7181
|
parentObjectType() {
|
|
7178
7182
|
return 1 /* EXPERIMENT */;
|
|
7179
7183
|
}
|
|
@@ -7314,6 +7318,14 @@ var Experiment2 = class extends ObjectFetcher {
|
|
|
7314
7318
|
comparisonExperimentId = baseExperiment.id;
|
|
7315
7319
|
comparisonExperimentName = baseExperiment.name;
|
|
7316
7320
|
}
|
|
7321
|
+
} else {
|
|
7322
|
+
try {
|
|
7323
|
+
const comparisonExperiment = await state.apiConn().get_json(`v1/experiment/${comparisonExperimentId}`);
|
|
7324
|
+
if (typeof comparisonExperiment["name"] === "string") {
|
|
7325
|
+
comparisonExperimentName = comparisonExperiment["name"];
|
|
7326
|
+
}
|
|
7327
|
+
} catch {
|
|
7328
|
+
}
|
|
7317
7329
|
}
|
|
7318
7330
|
try {
|
|
7319
7331
|
const results = await state.apiConn().get_json(
|
|
@@ -8573,6 +8585,64 @@ function isValidChannelName(channelName) {
|
|
|
8573
8585
|
return /^braintrust:[^:]+:.+$/.test(channelName);
|
|
8574
8586
|
}
|
|
8575
8587
|
|
|
8588
|
+
// src/instrumentation/auto-instrumentation-suppression.ts
|
|
8589
|
+
var autoInstrumentationSuppressionStore;
|
|
8590
|
+
function suppressionStore() {
|
|
8591
|
+
autoInstrumentationSuppressionStore ??= isomorph_default.newAsyncLocalStorage();
|
|
8592
|
+
return autoInstrumentationSuppressionStore;
|
|
8593
|
+
}
|
|
8594
|
+
function currentFrames() {
|
|
8595
|
+
return suppressionStore().getStore()?.frames ?? [];
|
|
8596
|
+
}
|
|
8597
|
+
function isAutoInstrumentationSuppressed() {
|
|
8598
|
+
const frames = currentFrames();
|
|
8599
|
+
return frames[frames.length - 1]?.mode === "suppress";
|
|
8600
|
+
}
|
|
8601
|
+
function runWithAutoInstrumentationSuppressed(callback) {
|
|
8602
|
+
const frame = {
|
|
8603
|
+
id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
|
|
8604
|
+
mode: "suppress"
|
|
8605
|
+
};
|
|
8606
|
+
return suppressionStore().run(
|
|
8607
|
+
{ frames: [...currentFrames(), frame] },
|
|
8608
|
+
callback
|
|
8609
|
+
);
|
|
8610
|
+
}
|
|
8611
|
+
function bindAutoInstrumentationSuppressionToStart(tracingChannel) {
|
|
8612
|
+
const startChannel = tracingChannel.start;
|
|
8613
|
+
if (!startChannel) {
|
|
8614
|
+
return void 0;
|
|
8615
|
+
}
|
|
8616
|
+
const store = suppressionStore();
|
|
8617
|
+
startChannel.bindStore(store, () => ({
|
|
8618
|
+
frames: [
|
|
8619
|
+
...currentFrames(),
|
|
8620
|
+
{
|
|
8621
|
+
id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
|
|
8622
|
+
mode: "suppress"
|
|
8623
|
+
}
|
|
8624
|
+
]
|
|
8625
|
+
}));
|
|
8626
|
+
return () => {
|
|
8627
|
+
startChannel.unbindStore(store);
|
|
8628
|
+
};
|
|
8629
|
+
}
|
|
8630
|
+
function enterAutoInstrumentationAllowed() {
|
|
8631
|
+
const frame = {
|
|
8632
|
+
id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-allow"),
|
|
8633
|
+
mode: "allow"
|
|
8634
|
+
};
|
|
8635
|
+
suppressionStore().enterWith({
|
|
8636
|
+
frames: [...currentFrames(), frame]
|
|
8637
|
+
});
|
|
8638
|
+
return () => {
|
|
8639
|
+
const frames = currentFrames().filter(
|
|
8640
|
+
(candidate) => candidate.id !== frame.id
|
|
8641
|
+
);
|
|
8642
|
+
suppressionStore().enterWith(frames.length > 0 ? { frames } : void 0);
|
|
8643
|
+
};
|
|
8644
|
+
}
|
|
8645
|
+
|
|
8576
8646
|
// src/instrumentation/core/channel-tracing.ts
|
|
8577
8647
|
function isSyncStreamLike(value) {
|
|
8578
8648
|
return !!value && typeof value === "object" && typeof value.on === "function";
|
|
@@ -8604,16 +8674,33 @@ function startSpanForEvent(config, event, channelName) {
|
|
|
8604
8674
|
metadata: mergeInputMetadata(metadata, spanInfoMetadata)
|
|
8605
8675
|
});
|
|
8606
8676
|
} catch (error) {
|
|
8607
|
-
|
|
8677
|
+
debugLogger.error(`Error extracting input for ${channelName}:`, error);
|
|
8608
8678
|
}
|
|
8609
8679
|
return { span, startTime };
|
|
8610
8680
|
}
|
|
8681
|
+
function shouldTraceEvent(config, event, channelName) {
|
|
8682
|
+
if (!config.shouldTrace) {
|
|
8683
|
+
return true;
|
|
8684
|
+
}
|
|
8685
|
+
try {
|
|
8686
|
+
return config.shouldTrace(event.arguments, event);
|
|
8687
|
+
} catch (error) {
|
|
8688
|
+
debugLogger.error(
|
|
8689
|
+
`Error checking trace predicate for ${channelName}:`,
|
|
8690
|
+
error
|
|
8691
|
+
);
|
|
8692
|
+
return true;
|
|
8693
|
+
}
|
|
8694
|
+
}
|
|
8611
8695
|
function ensureSpanStateForEvent(states, config, event, channelName) {
|
|
8612
8696
|
const key = event;
|
|
8613
8697
|
const existing = states.get(key);
|
|
8614
8698
|
if (existing) {
|
|
8615
8699
|
return existing;
|
|
8616
8700
|
}
|
|
8701
|
+
if (!shouldTraceEvent(config, event, channelName)) {
|
|
8702
|
+
return void 0;
|
|
8703
|
+
}
|
|
8617
8704
|
const created = startSpanForEvent(config, event, channelName);
|
|
8618
8705
|
states.set(key, created);
|
|
8619
8706
|
return created;
|
|
@@ -8629,13 +8716,16 @@ function bindCurrentSpanStoreToStart(tracingChannel, states, config, channelName
|
|
|
8629
8716
|
startChannel.bindStore(
|
|
8630
8717
|
currentSpanStore,
|
|
8631
8718
|
(event) => {
|
|
8632
|
-
|
|
8719
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
8720
|
+
return currentSpanStore.getStore();
|
|
8721
|
+
}
|
|
8722
|
+
const spanState = ensureSpanStateForEvent(
|
|
8633
8723
|
states,
|
|
8634
8724
|
config,
|
|
8635
8725
|
event,
|
|
8636
8726
|
channelName
|
|
8637
|
-
)
|
|
8638
|
-
return contextManager.wrapSpanForStore(span);
|
|
8727
|
+
);
|
|
8728
|
+
return spanState ? contextManager.wrapSpanForStore(spanState.span) : currentSpanStore.getStore();
|
|
8639
8729
|
}
|
|
8640
8730
|
);
|
|
8641
8731
|
return () => {
|
|
@@ -8670,7 +8760,10 @@ function runStreamingCompletionHook(args) {
|
|
|
8670
8760
|
startTime: args.startTime
|
|
8671
8761
|
});
|
|
8672
8762
|
} catch (error) {
|
|
8673
|
-
|
|
8763
|
+
debugLogger.error(
|
|
8764
|
+
`Error in onComplete hook for ${args.channelName}:`,
|
|
8765
|
+
error
|
|
8766
|
+
);
|
|
8674
8767
|
}
|
|
8675
8768
|
}
|
|
8676
8769
|
function traceAsyncChannel(channel2, config) {
|
|
@@ -8685,6 +8778,9 @@ function traceAsyncChannel(channel2, config) {
|
|
|
8685
8778
|
);
|
|
8686
8779
|
const handlers = {
|
|
8687
8780
|
start: (event) => {
|
|
8781
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
8782
|
+
return;
|
|
8783
|
+
}
|
|
8688
8784
|
ensureSpanStateForEvent(
|
|
8689
8785
|
states,
|
|
8690
8786
|
config,
|
|
@@ -8719,7 +8815,7 @@ function traceAsyncChannel(channel2, config) {
|
|
|
8719
8815
|
metrics
|
|
8720
8816
|
});
|
|
8721
8817
|
} catch (error) {
|
|
8722
|
-
|
|
8818
|
+
debugLogger.error(`Error extracting output for ${channelName}:`, error);
|
|
8723
8819
|
} finally {
|
|
8724
8820
|
span.end();
|
|
8725
8821
|
states.delete(event);
|
|
@@ -8747,6 +8843,9 @@ function traceStreamingChannel(channel2, config) {
|
|
|
8747
8843
|
);
|
|
8748
8844
|
const handlers = {
|
|
8749
8845
|
start: (event) => {
|
|
8846
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
8847
|
+
return;
|
|
8848
|
+
}
|
|
8750
8849
|
ensureSpanStateForEvent(
|
|
8751
8850
|
states,
|
|
8752
8851
|
config,
|
|
@@ -8818,7 +8917,7 @@ function traceStreamingChannel(channel2, config) {
|
|
|
8818
8917
|
metrics
|
|
8819
8918
|
});
|
|
8820
8919
|
} catch (error) {
|
|
8821
|
-
|
|
8920
|
+
debugLogger.error(
|
|
8822
8921
|
`Error extracting output for ${channelName}:`,
|
|
8823
8922
|
error
|
|
8824
8923
|
);
|
|
@@ -8878,7 +8977,7 @@ function traceStreamingChannel(channel2, config) {
|
|
|
8878
8977
|
metrics
|
|
8879
8978
|
});
|
|
8880
8979
|
} catch (error) {
|
|
8881
|
-
|
|
8980
|
+
debugLogger.error(`Error extracting output for ${channelName}:`, error);
|
|
8882
8981
|
} finally {
|
|
8883
8982
|
span.end();
|
|
8884
8983
|
states.delete(event);
|
|
@@ -8906,6 +9005,9 @@ function traceSyncStreamChannel(channel2, config) {
|
|
|
8906
9005
|
);
|
|
8907
9006
|
const handlers = {
|
|
8908
9007
|
start: (event) => {
|
|
9008
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
9009
|
+
return;
|
|
9010
|
+
}
|
|
8909
9011
|
ensureSpanStateForEvent(
|
|
8910
9012
|
states,
|
|
8911
9013
|
config,
|
|
@@ -8959,7 +9061,7 @@ function traceSyncStreamChannel(channel2, config) {
|
|
|
8959
9061
|
});
|
|
8960
9062
|
}
|
|
8961
9063
|
} catch (error) {
|
|
8962
|
-
|
|
9064
|
+
debugLogger.error(
|
|
8963
9065
|
`Error extracting chatCompletion for ${channelName}:`,
|
|
8964
9066
|
error
|
|
8965
9067
|
);
|
|
@@ -8983,7 +9085,10 @@ function traceSyncStreamChannel(channel2, config) {
|
|
|
8983
9085
|
span.log(extracted);
|
|
8984
9086
|
}
|
|
8985
9087
|
} catch (error) {
|
|
8986
|
-
|
|
9088
|
+
debugLogger.error(
|
|
9089
|
+
`Error extracting event for ${channelName}:`,
|
|
9090
|
+
error
|
|
9091
|
+
);
|
|
8987
9092
|
}
|
|
8988
9093
|
});
|
|
8989
9094
|
stream.on("end", () => {
|
|
@@ -10512,6 +10617,9 @@ var AnthropicPlugin = class extends BasePlugin {
|
|
|
10512
10617
|
const states = /* @__PURE__ */ new WeakMap();
|
|
10513
10618
|
const handlers = {
|
|
10514
10619
|
start: (event) => {
|
|
10620
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
10621
|
+
return;
|
|
10622
|
+
}
|
|
10515
10623
|
const params = event.arguments[0] ?? {};
|
|
10516
10624
|
const span = startSpan({
|
|
10517
10625
|
name: "anthropic.beta.messages.toolRunner",
|
|
@@ -11241,6 +11349,520 @@ function serializeAISDKToolsForLogging(tools) {
|
|
|
11241
11349
|
return serialized;
|
|
11242
11350
|
}
|
|
11243
11351
|
|
|
11352
|
+
// src/wrappers/ai-sdk/telemetry.ts
|
|
11353
|
+
function braintrustAISDKTelemetry() {
|
|
11354
|
+
const operations = /* @__PURE__ */ new Map();
|
|
11355
|
+
const modelSpans = /* @__PURE__ */ new Map();
|
|
11356
|
+
const objectSpans = /* @__PURE__ */ new Map();
|
|
11357
|
+
const embedSpans = /* @__PURE__ */ new Map();
|
|
11358
|
+
const rerankSpans = /* @__PURE__ */ new Map();
|
|
11359
|
+
const toolSpans = /* @__PURE__ */ new Map();
|
|
11360
|
+
const runSafely = (name, callback) => {
|
|
11361
|
+
try {
|
|
11362
|
+
callback();
|
|
11363
|
+
} catch (error) {
|
|
11364
|
+
console.error(`Error in Braintrust AI SDK telemetry ${name}:`, error);
|
|
11365
|
+
}
|
|
11366
|
+
};
|
|
11367
|
+
const startChildSpan = (callId, name, type, event) => {
|
|
11368
|
+
const parent = operations.get(callId)?.span;
|
|
11369
|
+
const spanArgs = {
|
|
11370
|
+
name,
|
|
11371
|
+
spanAttributes: { type },
|
|
11372
|
+
...event ? { event } : {}
|
|
11373
|
+
};
|
|
11374
|
+
const span = parent ? parent.startSpan(spanArgs) : startSpan(spanArgs);
|
|
11375
|
+
const state = operations.get(callId);
|
|
11376
|
+
if (state && type === "llm" /* LLM */) {
|
|
11377
|
+
state.hadModelChild = true;
|
|
11378
|
+
}
|
|
11379
|
+
return span;
|
|
11380
|
+
};
|
|
11381
|
+
return {
|
|
11382
|
+
onStart(event) {
|
|
11383
|
+
runSafely("onStart", () => {
|
|
11384
|
+
const operationName = operationNameFromId(event.operationId);
|
|
11385
|
+
const span = startSpan({
|
|
11386
|
+
name: operationName,
|
|
11387
|
+
spanAttributes: { type: "function" /* FUNCTION */ }
|
|
11388
|
+
});
|
|
11389
|
+
operations.set(event.callId, {
|
|
11390
|
+
hadModelChild: false,
|
|
11391
|
+
operationName,
|
|
11392
|
+
span,
|
|
11393
|
+
startTime: getCurrentUnixTimestamp()
|
|
11394
|
+
});
|
|
11395
|
+
const metadata = metadataFromEvent(event);
|
|
11396
|
+
const logPayload = { metadata };
|
|
11397
|
+
if (shouldRecordInputs(event)) {
|
|
11398
|
+
const { input, outputPromise } = processAISDKCallInput(
|
|
11399
|
+
operationInput(event, operationName)
|
|
11400
|
+
);
|
|
11401
|
+
logPayload.input = input;
|
|
11402
|
+
if (outputPromise && input && typeof input === "object") {
|
|
11403
|
+
outputPromise.then((resolvedData) => {
|
|
11404
|
+
span.log({
|
|
11405
|
+
input: {
|
|
11406
|
+
...input,
|
|
11407
|
+
...resolvedData
|
|
11408
|
+
}
|
|
11409
|
+
});
|
|
11410
|
+
}).catch(() => {
|
|
11411
|
+
});
|
|
11412
|
+
}
|
|
11413
|
+
}
|
|
11414
|
+
span.log(logPayload);
|
|
11415
|
+
});
|
|
11416
|
+
},
|
|
11417
|
+
onLanguageModelCallStart(event) {
|
|
11418
|
+
runSafely("onLanguageModelCallStart", () => {
|
|
11419
|
+
const state = operations.get(event.callId);
|
|
11420
|
+
const openSpans = modelSpans.get(event.callId);
|
|
11421
|
+
if (openSpans) {
|
|
11422
|
+
for (const span2 of openSpans) {
|
|
11423
|
+
span2.end();
|
|
11424
|
+
}
|
|
11425
|
+
modelSpans.delete(event.callId);
|
|
11426
|
+
}
|
|
11427
|
+
const span = startChildSpan(
|
|
11428
|
+
event.callId,
|
|
11429
|
+
state?.operationName === "streamText" ? "doStream" : "doGenerate",
|
|
11430
|
+
"llm" /* LLM */,
|
|
11431
|
+
{
|
|
11432
|
+
...shouldRecordInputs(event) ? {
|
|
11433
|
+
input: processAISDKCallInput(
|
|
11434
|
+
operationInput(
|
|
11435
|
+
event,
|
|
11436
|
+
state?.operationName ?? "generateText"
|
|
11437
|
+
)
|
|
11438
|
+
).input
|
|
11439
|
+
} : {},
|
|
11440
|
+
metadata: metadataFromEvent(event)
|
|
11441
|
+
}
|
|
11442
|
+
);
|
|
11443
|
+
const spans = modelSpans.get(event.callId) ?? [];
|
|
11444
|
+
spans.push(span);
|
|
11445
|
+
modelSpans.set(event.callId, spans);
|
|
11446
|
+
});
|
|
11447
|
+
},
|
|
11448
|
+
onLanguageModelCallEnd(event) {
|
|
11449
|
+
runSafely("onLanguageModelCallEnd", () => {
|
|
11450
|
+
const span = shiftModelSpan(modelSpans, event.callId);
|
|
11451
|
+
if (!span) {
|
|
11452
|
+
return;
|
|
11453
|
+
}
|
|
11454
|
+
const result = {
|
|
11455
|
+
...event,
|
|
11456
|
+
response: event.responseId ? { id: event.responseId } : void 0
|
|
11457
|
+
};
|
|
11458
|
+
span.log({
|
|
11459
|
+
...shouldRecordOutputs(event) ? {
|
|
11460
|
+
output: processAISDKOutput(result, DEFAULT_DENY_OUTPUT_PATHS)
|
|
11461
|
+
} : {},
|
|
11462
|
+
metrics: extractTokenMetrics(result)
|
|
11463
|
+
});
|
|
11464
|
+
span.end();
|
|
11465
|
+
});
|
|
11466
|
+
},
|
|
11467
|
+
onObjectStepStart(event) {
|
|
11468
|
+
runSafely("onObjectStepStart", () => {
|
|
11469
|
+
const state = operations.get(event.callId);
|
|
11470
|
+
const openSpan = objectSpans.get(event.callId);
|
|
11471
|
+
if (openSpan) {
|
|
11472
|
+
openSpan.end();
|
|
11473
|
+
objectSpans.delete(event.callId);
|
|
11474
|
+
}
|
|
11475
|
+
const span = startChildSpan(
|
|
11476
|
+
event.callId,
|
|
11477
|
+
state?.operationName === "streamObject" ? "doStream" : "doGenerate",
|
|
11478
|
+
"llm" /* LLM */,
|
|
11479
|
+
{
|
|
11480
|
+
...shouldRecordInputs(event) ? {
|
|
11481
|
+
input: {
|
|
11482
|
+
prompt: event.promptMessages
|
|
11483
|
+
}
|
|
11484
|
+
} : {},
|
|
11485
|
+
metadata: metadataFromEvent(event)
|
|
11486
|
+
}
|
|
11487
|
+
);
|
|
11488
|
+
objectSpans.set(event.callId, span);
|
|
11489
|
+
});
|
|
11490
|
+
},
|
|
11491
|
+
onObjectStepFinish(event) {
|
|
11492
|
+
runSafely("onObjectStepFinish", () => {
|
|
11493
|
+
const span = objectSpans.get(event.callId);
|
|
11494
|
+
if (!span) {
|
|
11495
|
+
return;
|
|
11496
|
+
}
|
|
11497
|
+
const result = {
|
|
11498
|
+
...event,
|
|
11499
|
+
text: event.objectText
|
|
11500
|
+
};
|
|
11501
|
+
span.log({
|
|
11502
|
+
...shouldRecordOutputs(event) ? {
|
|
11503
|
+
output: processAISDKOutput(result, DEFAULT_DENY_OUTPUT_PATHS)
|
|
11504
|
+
} : {},
|
|
11505
|
+
metrics: extractTokenMetrics(result)
|
|
11506
|
+
});
|
|
11507
|
+
span.end();
|
|
11508
|
+
objectSpans.delete(event.callId);
|
|
11509
|
+
});
|
|
11510
|
+
},
|
|
11511
|
+
onEmbedStart(event) {
|
|
11512
|
+
runSafely("onEmbedStart", () => {
|
|
11513
|
+
const state = operations.get(event.callId);
|
|
11514
|
+
for (const [embedCallId, embedState] of embedSpans) {
|
|
11515
|
+
if (embedState.callId === event.callId && (state?.operationName === "embed" || embedState.values === event.values)) {
|
|
11516
|
+
embedState.span.end();
|
|
11517
|
+
embedSpans.delete(embedCallId);
|
|
11518
|
+
}
|
|
11519
|
+
}
|
|
11520
|
+
const span = startChildSpan(
|
|
11521
|
+
event.callId,
|
|
11522
|
+
"doEmbed",
|
|
11523
|
+
"llm" /* LLM */,
|
|
11524
|
+
{
|
|
11525
|
+
...shouldRecordInputs(event) ? {
|
|
11526
|
+
input: {
|
|
11527
|
+
values: event.values
|
|
11528
|
+
}
|
|
11529
|
+
} : {},
|
|
11530
|
+
metadata: metadataFromEvent(event)
|
|
11531
|
+
}
|
|
11532
|
+
);
|
|
11533
|
+
embedSpans.set(event.embedCallId, {
|
|
11534
|
+
callId: event.callId,
|
|
11535
|
+
span,
|
|
11536
|
+
values: event.values
|
|
11537
|
+
});
|
|
11538
|
+
});
|
|
11539
|
+
},
|
|
11540
|
+
onEmbedFinish(event) {
|
|
11541
|
+
runSafely("onEmbedFinish", () => {
|
|
11542
|
+
const state = embedSpans.get(event.embedCallId);
|
|
11543
|
+
if (!state) {
|
|
11544
|
+
return;
|
|
11545
|
+
}
|
|
11546
|
+
const result = {
|
|
11547
|
+
...event,
|
|
11548
|
+
embeddings: event.embeddings
|
|
11549
|
+
};
|
|
11550
|
+
state.span.log({
|
|
11551
|
+
...shouldRecordOutputs(event) ? {
|
|
11552
|
+
output: processAISDKEmbeddingOutput(
|
|
11553
|
+
result,
|
|
11554
|
+
DEFAULT_DENY_OUTPUT_PATHS
|
|
11555
|
+
)
|
|
11556
|
+
} : {},
|
|
11557
|
+
metrics: extractTokenMetrics(result)
|
|
11558
|
+
});
|
|
11559
|
+
state.span.end();
|
|
11560
|
+
embedSpans.delete(event.embedCallId);
|
|
11561
|
+
});
|
|
11562
|
+
},
|
|
11563
|
+
onRerankStart(event) {
|
|
11564
|
+
runSafely("onRerankStart", () => {
|
|
11565
|
+
const openSpan = rerankSpans.get(event.callId);
|
|
11566
|
+
if (openSpan) {
|
|
11567
|
+
openSpan.end();
|
|
11568
|
+
rerankSpans.delete(event.callId);
|
|
11569
|
+
}
|
|
11570
|
+
const span = startChildSpan(
|
|
11571
|
+
event.callId,
|
|
11572
|
+
"doRerank",
|
|
11573
|
+
"llm" /* LLM */,
|
|
11574
|
+
{
|
|
11575
|
+
...shouldRecordInputs(event) ? {
|
|
11576
|
+
input: {
|
|
11577
|
+
documents: event.documents,
|
|
11578
|
+
query: event.query,
|
|
11579
|
+
topN: event.topN
|
|
11580
|
+
}
|
|
11581
|
+
} : {},
|
|
11582
|
+
metadata: metadataFromEvent(event)
|
|
11583
|
+
}
|
|
11584
|
+
);
|
|
11585
|
+
rerankSpans.set(event.callId, span);
|
|
11586
|
+
});
|
|
11587
|
+
},
|
|
11588
|
+
onRerankFinish(event) {
|
|
11589
|
+
runSafely("onRerankFinish", () => {
|
|
11590
|
+
const span = rerankSpans.get(event.callId);
|
|
11591
|
+
if (!span) {
|
|
11592
|
+
return;
|
|
11593
|
+
}
|
|
11594
|
+
const result = {
|
|
11595
|
+
ranking: event.ranking?.map((entry) => ({
|
|
11596
|
+
originalIndex: entry.index,
|
|
11597
|
+
score: entry.relevanceScore
|
|
11598
|
+
}))
|
|
11599
|
+
};
|
|
11600
|
+
span.log({
|
|
11601
|
+
...shouldRecordOutputs(event) ? {
|
|
11602
|
+
output: processAISDKRerankOutput(
|
|
11603
|
+
result,
|
|
11604
|
+
DEFAULT_DENY_OUTPUT_PATHS
|
|
11605
|
+
)
|
|
11606
|
+
} : {}
|
|
11607
|
+
});
|
|
11608
|
+
span.end();
|
|
11609
|
+
rerankSpans.delete(event.callId);
|
|
11610
|
+
});
|
|
11611
|
+
},
|
|
11612
|
+
onToolExecutionStart(event) {
|
|
11613
|
+
runSafely("onToolExecutionStart", () => {
|
|
11614
|
+
const toolCallId = event.toolCall.toolCallId;
|
|
11615
|
+
if (!toolCallId) {
|
|
11616
|
+
return;
|
|
11617
|
+
}
|
|
11618
|
+
const span = startChildSpan(
|
|
11619
|
+
event.callId,
|
|
11620
|
+
event.toolCall.toolName || "tool",
|
|
11621
|
+
"tool" /* TOOL */,
|
|
11622
|
+
{
|
|
11623
|
+
...shouldRecordInputs(event) ? {
|
|
11624
|
+
input: event.toolCall.input
|
|
11625
|
+
} : {},
|
|
11626
|
+
metadata: {
|
|
11627
|
+
...createAISDKIntegrationMetadata(),
|
|
11628
|
+
toolCallId,
|
|
11629
|
+
...typeof event.toolCall.toolName === "string" ? { toolName: event.toolCall.toolName } : {}
|
|
11630
|
+
}
|
|
11631
|
+
}
|
|
11632
|
+
);
|
|
11633
|
+
toolSpans.set(toolCallId, { callId: event.callId, span });
|
|
11634
|
+
});
|
|
11635
|
+
},
|
|
11636
|
+
onToolExecutionEnd(event) {
|
|
11637
|
+
runSafely("onToolExecutionEnd", () => {
|
|
11638
|
+
const toolCallId = event.toolCall.toolCallId;
|
|
11639
|
+
const state = toolCallId ? toolSpans.get(toolCallId) : void 0;
|
|
11640
|
+
if (!toolCallId || !state) {
|
|
11641
|
+
return;
|
|
11642
|
+
}
|
|
11643
|
+
const toolOutput = event.toolOutput;
|
|
11644
|
+
if (toolOutput?.type === "tool-error") {
|
|
11645
|
+
state.span.log({
|
|
11646
|
+
error: toolOutput.error instanceof Error ? toolOutput.error.message : String(toolOutput?.error),
|
|
11647
|
+
metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } : {}
|
|
11648
|
+
});
|
|
11649
|
+
} else {
|
|
11650
|
+
state.span.log({
|
|
11651
|
+
...shouldRecordOutputs(event) ? { output: toolOutput?.output } : {},
|
|
11652
|
+
metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } : {}
|
|
11653
|
+
});
|
|
11654
|
+
}
|
|
11655
|
+
state.span.end();
|
|
11656
|
+
toolSpans.delete(toolCallId);
|
|
11657
|
+
});
|
|
11658
|
+
},
|
|
11659
|
+
onChunk(event) {
|
|
11660
|
+
runSafely("onChunk", () => {
|
|
11661
|
+
const callId = event.chunk?.callId;
|
|
11662
|
+
if (!callId) {
|
|
11663
|
+
return;
|
|
11664
|
+
}
|
|
11665
|
+
const state = operations.get(callId);
|
|
11666
|
+
if (!state || state.firstChunkTime !== void 0) {
|
|
11667
|
+
return;
|
|
11668
|
+
}
|
|
11669
|
+
state.firstChunkTime = getCurrentUnixTimestamp();
|
|
11670
|
+
});
|
|
11671
|
+
},
|
|
11672
|
+
onFinish(event) {
|
|
11673
|
+
runSafely("onFinish", () => {
|
|
11674
|
+
const state = operations.get(event.callId);
|
|
11675
|
+
if (!state) {
|
|
11676
|
+
return;
|
|
11677
|
+
}
|
|
11678
|
+
const result = finishResult(event, state.operationName);
|
|
11679
|
+
const metrics = state.hadModelChild ? {} : extractTokenMetrics(result);
|
|
11680
|
+
if (state.firstChunkTime !== void 0) {
|
|
11681
|
+
metrics.time_to_first_token = state.firstChunkTime - state.startTime;
|
|
11682
|
+
}
|
|
11683
|
+
state.span.log({
|
|
11684
|
+
...shouldRecordOutputs(event) ? {
|
|
11685
|
+
output: finishOutput(result, state.operationName)
|
|
11686
|
+
} : {},
|
|
11687
|
+
metrics
|
|
11688
|
+
});
|
|
11689
|
+
state.span.end();
|
|
11690
|
+
operations.delete(event.callId);
|
|
11691
|
+
});
|
|
11692
|
+
},
|
|
11693
|
+
onError(event) {
|
|
11694
|
+
runSafely("onError", () => {
|
|
11695
|
+
const errorEvent = isObject(event) ? event : {};
|
|
11696
|
+
const callId = typeof errorEvent.callId === "string" ? errorEvent.callId : void 0;
|
|
11697
|
+
if (!callId) {
|
|
11698
|
+
return;
|
|
11699
|
+
}
|
|
11700
|
+
const state = operations.get(callId);
|
|
11701
|
+
if (!state) {
|
|
11702
|
+
return;
|
|
11703
|
+
}
|
|
11704
|
+
const error = errorEvent.error ?? event;
|
|
11705
|
+
const openModelSpans = modelSpans.get(callId);
|
|
11706
|
+
if (openModelSpans) {
|
|
11707
|
+
for (const span of openModelSpans) {
|
|
11708
|
+
logError(span, error);
|
|
11709
|
+
span.end();
|
|
11710
|
+
}
|
|
11711
|
+
modelSpans.delete(callId);
|
|
11712
|
+
}
|
|
11713
|
+
const openObjectSpan = objectSpans.get(callId);
|
|
11714
|
+
if (openObjectSpan) {
|
|
11715
|
+
logError(openObjectSpan, error);
|
|
11716
|
+
openObjectSpan.end();
|
|
11717
|
+
objectSpans.delete(callId);
|
|
11718
|
+
}
|
|
11719
|
+
for (const [embedCallId, embedState] of embedSpans) {
|
|
11720
|
+
if (embedState.callId === callId) {
|
|
11721
|
+
logError(embedState.span, error);
|
|
11722
|
+
embedState.span.end();
|
|
11723
|
+
embedSpans.delete(embedCallId);
|
|
11724
|
+
}
|
|
11725
|
+
}
|
|
11726
|
+
const openRerankSpan = rerankSpans.get(callId);
|
|
11727
|
+
if (openRerankSpan) {
|
|
11728
|
+
logError(openRerankSpan, error);
|
|
11729
|
+
openRerankSpan.end();
|
|
11730
|
+
rerankSpans.delete(callId);
|
|
11731
|
+
}
|
|
11732
|
+
for (const [toolCallId, toolState] of toolSpans) {
|
|
11733
|
+
if (toolState.callId === callId) {
|
|
11734
|
+
logError(toolState.span, error);
|
|
11735
|
+
toolState.span.end();
|
|
11736
|
+
toolSpans.delete(toolCallId);
|
|
11737
|
+
}
|
|
11738
|
+
}
|
|
11739
|
+
logError(state.span, error);
|
|
11740
|
+
state.span.end();
|
|
11741
|
+
operations.delete(callId);
|
|
11742
|
+
});
|
|
11743
|
+
},
|
|
11744
|
+
executeTool({ toolCallId, execute }) {
|
|
11745
|
+
const state = toolSpans.get(toolCallId);
|
|
11746
|
+
return state ? withCurrent(state.span, () => execute()) : execute();
|
|
11747
|
+
}
|
|
11748
|
+
};
|
|
11749
|
+
}
|
|
11750
|
+
function shouldRecordInputs(event) {
|
|
11751
|
+
return event.recordInputs !== false;
|
|
11752
|
+
}
|
|
11753
|
+
function shouldRecordOutputs(event) {
|
|
11754
|
+
return event.recordOutputs !== false;
|
|
11755
|
+
}
|
|
11756
|
+
function operationNameFromId(operationId) {
|
|
11757
|
+
return operationId?.startsWith("ai.") ? operationId.slice("ai.".length) : operationId || "ai-sdk";
|
|
11758
|
+
}
|
|
11759
|
+
function modelFromEvent(event) {
|
|
11760
|
+
return event.modelId ? {
|
|
11761
|
+
modelId: event.modelId,
|
|
11762
|
+
...event.provider ? { provider: event.provider } : {}
|
|
11763
|
+
} : void 0;
|
|
11764
|
+
}
|
|
11765
|
+
function metadataFromEvent(event) {
|
|
11766
|
+
const metadata = createAISDKIntegrationMetadata();
|
|
11767
|
+
const { model, provider } = serializeModelWithProvider(modelFromEvent(event));
|
|
11768
|
+
if (model) {
|
|
11769
|
+
metadata.model = model;
|
|
11770
|
+
}
|
|
11771
|
+
if (provider) {
|
|
11772
|
+
metadata.provider = provider;
|
|
11773
|
+
}
|
|
11774
|
+
if (typeof event.functionId === "string") {
|
|
11775
|
+
metadata.functionId = event.functionId;
|
|
11776
|
+
}
|
|
11777
|
+
return metadata;
|
|
11778
|
+
}
|
|
11779
|
+
function operationInput(event, operationName) {
|
|
11780
|
+
if (operationName === "embed") {
|
|
11781
|
+
return {
|
|
11782
|
+
model: modelFromEvent(event),
|
|
11783
|
+
value: event.value
|
|
11784
|
+
};
|
|
11785
|
+
}
|
|
11786
|
+
if (operationName === "embedMany") {
|
|
11787
|
+
return {
|
|
11788
|
+
model: modelFromEvent(event),
|
|
11789
|
+
values: Array.isArray(event.value) ? event.value ?? [] : void 0
|
|
11790
|
+
};
|
|
11791
|
+
}
|
|
11792
|
+
if (operationName === "rerank") {
|
|
11793
|
+
return {
|
|
11794
|
+
model: modelFromEvent(event),
|
|
11795
|
+
documents: event.documents,
|
|
11796
|
+
query: event.query,
|
|
11797
|
+
topN: event.topN
|
|
11798
|
+
};
|
|
11799
|
+
}
|
|
11800
|
+
return {
|
|
11801
|
+
model: modelFromEvent(event),
|
|
11802
|
+
system: event.system,
|
|
11803
|
+
prompt: event.prompt,
|
|
11804
|
+
messages: event.messages,
|
|
11805
|
+
tools: event.tools,
|
|
11806
|
+
toolChoice: event.toolChoice,
|
|
11807
|
+
activeTools: event.activeTools,
|
|
11808
|
+
output: event.output,
|
|
11809
|
+
schema: event.schema,
|
|
11810
|
+
schemaName: event.schemaName,
|
|
11811
|
+
schemaDescription: event.schemaDescription,
|
|
11812
|
+
maxOutputTokens: event.maxOutputTokens,
|
|
11813
|
+
temperature: event.temperature,
|
|
11814
|
+
topP: event.topP,
|
|
11815
|
+
topK: event.topK,
|
|
11816
|
+
presencePenalty: event.presencePenalty,
|
|
11817
|
+
frequencyPenalty: event.frequencyPenalty,
|
|
11818
|
+
seed: event.seed,
|
|
11819
|
+
maxRetries: event.maxRetries,
|
|
11820
|
+
headers: event.headers,
|
|
11821
|
+
providerOptions: event.providerOptions
|
|
11822
|
+
};
|
|
11823
|
+
}
|
|
11824
|
+
function shiftModelSpan(modelSpans, callId) {
|
|
11825
|
+
const spans = modelSpans.get(callId);
|
|
11826
|
+
const span = spans?.shift();
|
|
11827
|
+
if (spans && spans.length === 0) {
|
|
11828
|
+
modelSpans.delete(callId);
|
|
11829
|
+
}
|
|
11830
|
+
return span;
|
|
11831
|
+
}
|
|
11832
|
+
function finishResult(event, operationName) {
|
|
11833
|
+
if (operationName === "embed") {
|
|
11834
|
+
return {
|
|
11835
|
+
...event,
|
|
11836
|
+
embedding: event.embedding
|
|
11837
|
+
};
|
|
11838
|
+
}
|
|
11839
|
+
if (operationName === "embedMany") {
|
|
11840
|
+
return {
|
|
11841
|
+
...event,
|
|
11842
|
+
embeddings: event.embedding
|
|
11843
|
+
};
|
|
11844
|
+
}
|
|
11845
|
+
if (operationName === "rerank") {
|
|
11846
|
+
return event;
|
|
11847
|
+
}
|
|
11848
|
+
return event;
|
|
11849
|
+
}
|
|
11850
|
+
function finishOutput(result, operationName) {
|
|
11851
|
+
if (operationName === "embed" || operationName === "embedMany") {
|
|
11852
|
+
return processAISDKEmbeddingOutput(
|
|
11853
|
+
result,
|
|
11854
|
+
DEFAULT_DENY_OUTPUT_PATHS
|
|
11855
|
+
);
|
|
11856
|
+
}
|
|
11857
|
+
if (operationName === "rerank") {
|
|
11858
|
+
return processAISDKRerankOutput(
|
|
11859
|
+
result,
|
|
11860
|
+
DEFAULT_DENY_OUTPUT_PATHS
|
|
11861
|
+
);
|
|
11862
|
+
}
|
|
11863
|
+
return processAISDKOutput(result, DEFAULT_DENY_OUTPUT_PATHS);
|
|
11864
|
+
}
|
|
11865
|
+
|
|
11244
11866
|
// src/instrumentation/plugins/ai-sdk-channels.ts
|
|
11245
11867
|
var aiSDKChannels = defineChannels("ai", {
|
|
11246
11868
|
generateText: channel({
|
|
@@ -11300,6 +11922,10 @@ var aiSDKChannels = defineChannels("ai", {
|
|
|
11300
11922
|
toolLoopAgentStream: channel({
|
|
11301
11923
|
channelName: "ToolLoopAgent.stream",
|
|
11302
11924
|
kind: "async"
|
|
11925
|
+
}),
|
|
11926
|
+
v7CreateTelemetryDispatcher: channel({
|
|
11927
|
+
channelName: "createTelemetryDispatcher",
|
|
11928
|
+
kind: "sync-stream"
|
|
11303
11929
|
})
|
|
11304
11930
|
});
|
|
11305
11931
|
|
|
@@ -11320,9 +11946,30 @@ var DEFAULT_DENY_OUTPUT_PATHS = [
|
|
|
11320
11946
|
];
|
|
11321
11947
|
var AUTO_PATCHED_MODEL = /* @__PURE__ */ Symbol.for("braintrust.ai-sdk.auto-patched-model");
|
|
11322
11948
|
var AUTO_PATCHED_TOOL = /* @__PURE__ */ Symbol.for("braintrust.ai-sdk.auto-patched-tool");
|
|
11949
|
+
var AUTO_PATCHED_V7_TELEMETRY_DISPATCHER = /* @__PURE__ */ Symbol.for(
|
|
11950
|
+
"braintrust.ai-sdk.v7.auto-patched-telemetry-dispatcher"
|
|
11951
|
+
);
|
|
11323
11952
|
var RUNTIME_DENY_OUTPUT_PATHS = /* @__PURE__ */ Symbol.for(
|
|
11324
11953
|
"braintrust.ai-sdk.deny-output-paths"
|
|
11325
11954
|
);
|
|
11955
|
+
var AI_SDK_V7_TELEMETRY_CALLBACKS = [
|
|
11956
|
+
"onStart",
|
|
11957
|
+
"onStepStart",
|
|
11958
|
+
"onLanguageModelCallStart",
|
|
11959
|
+
"onLanguageModelCallEnd",
|
|
11960
|
+
"onToolExecutionStart",
|
|
11961
|
+
"onToolExecutionEnd",
|
|
11962
|
+
"onChunk",
|
|
11963
|
+
"onStepFinish",
|
|
11964
|
+
"onObjectStepStart",
|
|
11965
|
+
"onObjectStepFinish",
|
|
11966
|
+
"onEmbedStart",
|
|
11967
|
+
"onEmbedFinish",
|
|
11968
|
+
"onRerankStart",
|
|
11969
|
+
"onRerankFinish",
|
|
11970
|
+
"onFinish",
|
|
11971
|
+
"onError"
|
|
11972
|
+
];
|
|
11326
11973
|
var AISDKPlugin = class extends BasePlugin {
|
|
11327
11974
|
config;
|
|
11328
11975
|
constructor(config = {}) {
|
|
@@ -11337,6 +11984,7 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
11337
11984
|
}
|
|
11338
11985
|
subscribeToAISDK() {
|
|
11339
11986
|
const denyOutputPaths = this.config.denyOutputPaths || DEFAULT_DENY_OUTPUT_PATHS;
|
|
11987
|
+
this.unsubscribers.push(subscribeToAISDKV7TelemetryDispatcher());
|
|
11340
11988
|
this.unsubscribers.push(
|
|
11341
11989
|
traceStreamingChannel(aiSDKChannels.generateText, {
|
|
11342
11990
|
name: "generateText",
|
|
@@ -11561,17 +12209,68 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
11561
12209
|
);
|
|
11562
12210
|
}
|
|
11563
12211
|
};
|
|
11564
|
-
function
|
|
11565
|
-
|
|
11566
|
-
|
|
11567
|
-
|
|
11568
|
-
|
|
11569
|
-
|
|
11570
|
-
|
|
11571
|
-
|
|
11572
|
-
|
|
11573
|
-
|
|
11574
|
-
|
|
12212
|
+
function subscribeToAISDKV7TelemetryDispatcher() {
|
|
12213
|
+
const channel2 = aiSDKChannels.v7CreateTelemetryDispatcher.tracingChannel();
|
|
12214
|
+
const telemetry = braintrustAISDKTelemetry();
|
|
12215
|
+
const handlers = {
|
|
12216
|
+
end: (event) => {
|
|
12217
|
+
const telemetryOptions = event.arguments?.[0]?.telemetry;
|
|
12218
|
+
if (telemetryOptions?.isEnabled === false) {
|
|
12219
|
+
return;
|
|
12220
|
+
}
|
|
12221
|
+
patchAISDKV7TelemetryDispatcher(event.result, telemetry);
|
|
12222
|
+
}
|
|
12223
|
+
};
|
|
12224
|
+
channel2.subscribe(handlers);
|
|
12225
|
+
return () => {
|
|
12226
|
+
channel2.unsubscribe(handlers);
|
|
12227
|
+
};
|
|
12228
|
+
}
|
|
12229
|
+
function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry) {
|
|
12230
|
+
if (!isObject(dispatcher)) {
|
|
12231
|
+
return;
|
|
12232
|
+
}
|
|
12233
|
+
const dispatcherRecord = dispatcher;
|
|
12234
|
+
if (dispatcherRecord[AUTO_PATCHED_V7_TELEMETRY_DISPATCHER]) {
|
|
12235
|
+
return;
|
|
12236
|
+
}
|
|
12237
|
+
dispatcherRecord[AUTO_PATCHED_V7_TELEMETRY_DISPATCHER] = true;
|
|
12238
|
+
for (const key of AI_SDK_V7_TELEMETRY_CALLBACKS) {
|
|
12239
|
+
const braintrustCallback = telemetry[key];
|
|
12240
|
+
if (typeof braintrustCallback !== "function") {
|
|
12241
|
+
continue;
|
|
12242
|
+
}
|
|
12243
|
+
const existingCallback = dispatcherRecord[key];
|
|
12244
|
+
dispatcherRecord[key] = (event) => {
|
|
12245
|
+
const existingResult = typeof existingCallback === "function" ? existingCallback.call(dispatcher, event) : void 0;
|
|
12246
|
+
const braintrustResult = braintrustCallback.call(telemetry, event);
|
|
12247
|
+
const pending = [existingResult, braintrustResult].filter(isPromiseLike);
|
|
12248
|
+
if (pending.length > 0) {
|
|
12249
|
+
return Promise.allSettled(pending).then(() => void 0);
|
|
12250
|
+
}
|
|
12251
|
+
};
|
|
12252
|
+
}
|
|
12253
|
+
const braintrustExecuteTool = telemetry.executeTool;
|
|
12254
|
+
if (typeof braintrustExecuteTool !== "function") {
|
|
12255
|
+
return;
|
|
12256
|
+
}
|
|
12257
|
+
const existingExecuteTool = dispatcherRecord.executeTool;
|
|
12258
|
+
dispatcherRecord.executeTool = (args) => braintrustExecuteTool.call(telemetry, {
|
|
12259
|
+
...args,
|
|
12260
|
+
execute: () => typeof existingExecuteTool === "function" ? existingExecuteTool.call(dispatcher, args) : args.execute()
|
|
12261
|
+
});
|
|
12262
|
+
}
|
|
12263
|
+
function resolveDenyOutputPaths(event, defaultDenyOutputPaths) {
|
|
12264
|
+
if (Array.isArray(event?.denyOutputPaths)) {
|
|
12265
|
+
return event.denyOutputPaths;
|
|
12266
|
+
}
|
|
12267
|
+
const firstArgument2 = event?.arguments && event.arguments.length > 0 ? event.arguments[0] : void 0;
|
|
12268
|
+
if (!firstArgument2 || typeof firstArgument2 !== "object") {
|
|
12269
|
+
return defaultDenyOutputPaths;
|
|
12270
|
+
}
|
|
12271
|
+
const runtimeDenyOutputPaths = firstArgument2[RUNTIME_DENY_OUTPUT_PATHS];
|
|
12272
|
+
if (Array.isArray(runtimeDenyOutputPaths) && runtimeDenyOutputPaths.every((path) => typeof path === "string")) {
|
|
12273
|
+
return runtimeDenyOutputPaths;
|
|
11575
12274
|
}
|
|
11576
12275
|
return defaultDenyOutputPaths;
|
|
11577
12276
|
}
|
|
@@ -12012,11 +12711,11 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
|
|
|
12012
12711
|
metadata: baseMetadata
|
|
12013
12712
|
}
|
|
12014
12713
|
});
|
|
12714
|
+
const streamStartTime = getCurrentUnixTimestamp();
|
|
12015
12715
|
const result = await withCurrent(
|
|
12016
12716
|
span,
|
|
12017
12717
|
() => Reflect.apply(originalDoStream, resolvedModel, [options])
|
|
12018
12718
|
);
|
|
12019
|
-
const streamStartTime = getCurrentUnixTimestamp();
|
|
12020
12719
|
let firstChunkTime;
|
|
12021
12720
|
const output = {};
|
|
12022
12721
|
let text = "";
|
|
@@ -12025,7 +12724,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
|
|
|
12025
12724
|
let object = void 0;
|
|
12026
12725
|
const transformStream = new TransformStream({
|
|
12027
12726
|
transform(chunk, controller) {
|
|
12028
|
-
if (firstChunkTime === void 0) {
|
|
12727
|
+
if (firstChunkTime === void 0 && isAISDKContentStreamChunk(chunk)) {
|
|
12029
12728
|
firstChunkTime = getCurrentUnixTimestamp();
|
|
12030
12729
|
}
|
|
12031
12730
|
switch (chunk.type) {
|
|
@@ -12217,6 +12916,78 @@ function finalizeAISDKChildTracing(event) {
|
|
|
12217
12916
|
delete event.__braintrust_ai_sdk_cleanup;
|
|
12218
12917
|
}
|
|
12219
12918
|
}
|
|
12919
|
+
function extractAISDKStreamPart(chunk) {
|
|
12920
|
+
if (!isObject(chunk) || !isObject(chunk.part)) {
|
|
12921
|
+
return chunk;
|
|
12922
|
+
}
|
|
12923
|
+
return chunk.part;
|
|
12924
|
+
}
|
|
12925
|
+
function stringContent(value) {
|
|
12926
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
12927
|
+
}
|
|
12928
|
+
function rawValueHasAISDKContent(value) {
|
|
12929
|
+
if (value === void 0 || value === null) {
|
|
12930
|
+
return false;
|
|
12931
|
+
}
|
|
12932
|
+
if (typeof value === "string") {
|
|
12933
|
+
return value.length > 0;
|
|
12934
|
+
}
|
|
12935
|
+
if (!isObject(value)) {
|
|
12936
|
+
return true;
|
|
12937
|
+
}
|
|
12938
|
+
const delta = value.delta;
|
|
12939
|
+
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) => {
|
|
12940
|
+
if (!isObject(choice) || !isObject(choice.delta)) {
|
|
12941
|
+
return false;
|
|
12942
|
+
}
|
|
12943
|
+
const choiceDelta = choice.delta;
|
|
12944
|
+
if (stringContent(choiceDelta.content) || stringContent(choiceDelta.text)) {
|
|
12945
|
+
return true;
|
|
12946
|
+
}
|
|
12947
|
+
if (isObject(choiceDelta.function_call) && stringContent(choiceDelta.function_call.arguments)) {
|
|
12948
|
+
return true;
|
|
12949
|
+
}
|
|
12950
|
+
return Array.isArray(choiceDelta.tool_calls) && choiceDelta.tool_calls.some(
|
|
12951
|
+
(toolCall) => isObject(toolCall) && isObject(toolCall.function) && stringContent(toolCall.function.arguments)
|
|
12952
|
+
);
|
|
12953
|
+
})) {
|
|
12954
|
+
return true;
|
|
12955
|
+
}
|
|
12956
|
+
return false;
|
|
12957
|
+
}
|
|
12958
|
+
function isAISDKContentStreamChunk(chunk) {
|
|
12959
|
+
const part = extractAISDKStreamPart(chunk);
|
|
12960
|
+
if (typeof part === "string") {
|
|
12961
|
+
return part.length > 0;
|
|
12962
|
+
}
|
|
12963
|
+
if (!isObject(part) || typeof part.type !== "string") {
|
|
12964
|
+
return false;
|
|
12965
|
+
}
|
|
12966
|
+
switch (part.type) {
|
|
12967
|
+
case "text-delta":
|
|
12968
|
+
return stringContent(part.textDelta) !== void 0 || stringContent(part.delta) !== void 0 || stringContent(part.text) !== void 0 || stringContent(part.content) !== void 0;
|
|
12969
|
+
case "reasoning-delta":
|
|
12970
|
+
return stringContent(part.delta) !== void 0 || stringContent(part.text) !== void 0 || stringContent(part.content) !== void 0;
|
|
12971
|
+
case "tool-call":
|
|
12972
|
+
case "object":
|
|
12973
|
+
case "file":
|
|
12974
|
+
return true;
|
|
12975
|
+
case "tool-input-delta":
|
|
12976
|
+
case "tool-call-delta":
|
|
12977
|
+
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;
|
|
12978
|
+
case "raw":
|
|
12979
|
+
return rawValueHasAISDKContent(part.rawValue);
|
|
12980
|
+
default:
|
|
12981
|
+
return false;
|
|
12982
|
+
}
|
|
12983
|
+
}
|
|
12984
|
+
function isAISDKContentAsyncIterableChunk(chunk) {
|
|
12985
|
+
if (isAISDKContentStreamChunk(chunk)) {
|
|
12986
|
+
return true;
|
|
12987
|
+
}
|
|
12988
|
+
const part = extractAISDKStreamPart(chunk);
|
|
12989
|
+
return isObject(part) && typeof part.type !== "string";
|
|
12990
|
+
}
|
|
12220
12991
|
function patchAISDKStreamingResult(args) {
|
|
12221
12992
|
const { defaultDenyOutputPaths, endEvent, result, span, startTime } = args;
|
|
12222
12993
|
if (!result || typeof result !== "object") {
|
|
@@ -12229,7 +13000,7 @@ function patchAISDKStreamingResult(args) {
|
|
|
12229
13000
|
const wrappedBaseStream = resultRecord.baseStream.pipeThrough(
|
|
12230
13001
|
new TransformStream({
|
|
12231
13002
|
transform(chunk, controller) {
|
|
12232
|
-
if (firstChunkTime2 === void 0) {
|
|
13003
|
+
if (firstChunkTime2 === void 0 && isAISDKContentStreamChunk(chunk)) {
|
|
12233
13004
|
firstChunkTime2 = getCurrentUnixTimestamp();
|
|
12234
13005
|
}
|
|
12235
13006
|
controller.enqueue(chunk);
|
|
@@ -12273,8 +13044,8 @@ function patchAISDKStreamingResult(args) {
|
|
|
12273
13044
|
}
|
|
12274
13045
|
let firstChunkTime;
|
|
12275
13046
|
const wrappedStream = createPatchedAsyncIterable(streamField.stream, {
|
|
12276
|
-
onChunk: () => {
|
|
12277
|
-
if (firstChunkTime === void 0) {
|
|
13047
|
+
onChunk: (chunk) => {
|
|
13048
|
+
if (firstChunkTime === void 0 && isAISDKContentAsyncIterableChunk(chunk)) {
|
|
12278
13049
|
firstChunkTime = getCurrentUnixTimestamp();
|
|
12279
13050
|
}
|
|
12280
13051
|
},
|
|
@@ -13246,15 +14017,17 @@ function collectLocalMcpServerToolHookNames(serverName, serverConfig) {
|
|
|
13246
14017
|
|
|
13247
14018
|
// src/instrumentation/plugins/claude-agent-sdk-plugin.ts
|
|
13248
14019
|
var ROOT_LLM_PARENT_KEY = "__root__";
|
|
14020
|
+
var SUB_AGENT_PROMPT_SOURCE_PRIORITY = {
|
|
14021
|
+
delegation: 0,
|
|
14022
|
+
lifecycle: 1,
|
|
14023
|
+
sidechain: 2
|
|
14024
|
+
};
|
|
13249
14025
|
function llmParentKey(parentToolUseId) {
|
|
13250
14026
|
return parentToolUseId ?? ROOT_LLM_PARENT_KEY;
|
|
13251
14027
|
}
|
|
13252
14028
|
function isSubAgentDelegationToolName(toolName) {
|
|
13253
14029
|
return toolName === "Agent" || toolName === "Task";
|
|
13254
14030
|
}
|
|
13255
|
-
function shouldParentToolAsTaskSibling(toolName) {
|
|
13256
|
-
return toolName === "Agent" || toolName === "Task" || toolName === "Bash";
|
|
13257
|
-
}
|
|
13258
14031
|
function filterSerializableOptions(options) {
|
|
13259
14032
|
const allowedKeys = [
|
|
13260
14033
|
"model",
|
|
@@ -13391,26 +14164,39 @@ function extractUsageFromMessage(message) {
|
|
|
13391
14164
|
}
|
|
13392
14165
|
return metrics;
|
|
13393
14166
|
}
|
|
13394
|
-
function buildLLMInput(
|
|
13395
|
-
const promptMessages = [];
|
|
13396
|
-
if (typeof prompt === "string") {
|
|
13397
|
-
promptMessages.push({ content: prompt, role: "user" });
|
|
13398
|
-
} else if (capturedPromptMessages && capturedPromptMessages.length > 0) {
|
|
13399
|
-
for (const msg of capturedPromptMessages) {
|
|
13400
|
-
const role = msg.message?.role;
|
|
13401
|
-
const content = msg.message?.content;
|
|
13402
|
-
if (role && content !== void 0) {
|
|
13403
|
-
promptMessages.push({ content, role });
|
|
13404
|
-
}
|
|
13405
|
-
}
|
|
13406
|
-
}
|
|
14167
|
+
function buildLLMInput(promptMessages, conversationHistory) {
|
|
13407
14168
|
const inputParts = [...promptMessages, ...conversationHistory];
|
|
13408
14169
|
return inputParts.length > 0 ? inputParts : void 0;
|
|
13409
14170
|
}
|
|
14171
|
+
function conversationMessageFromSDKMessage(message) {
|
|
14172
|
+
const role = message.message?.role;
|
|
14173
|
+
const content = message.message?.content;
|
|
14174
|
+
if (role && content !== void 0) {
|
|
14175
|
+
return { content, role };
|
|
14176
|
+
}
|
|
14177
|
+
return void 0;
|
|
14178
|
+
}
|
|
14179
|
+
function messageContentHasBlockType(message, blockType) {
|
|
14180
|
+
const content = message.message?.content;
|
|
14181
|
+
return Array.isArray(content) && content.some(
|
|
14182
|
+
(block) => typeof block === "object" && block !== null && "type" in block && block.type === blockType
|
|
14183
|
+
);
|
|
14184
|
+
}
|
|
14185
|
+
function buildRootPromptMessages(prompt, capturedPromptMessages) {
|
|
14186
|
+
if (typeof prompt === "string") {
|
|
14187
|
+
return [{ content: prompt, role: "user" }];
|
|
14188
|
+
}
|
|
14189
|
+
if (!capturedPromptMessages || capturedPromptMessages.length === 0) {
|
|
14190
|
+
return [];
|
|
14191
|
+
}
|
|
14192
|
+
return capturedPromptMessages.map(conversationMessageFromSDKMessage).filter(
|
|
14193
|
+
(message) => message !== void 0
|
|
14194
|
+
);
|
|
14195
|
+
}
|
|
13410
14196
|
function formatCapturedMessages(messages) {
|
|
13411
14197
|
return messages.length > 0 ? messages : [];
|
|
13412
14198
|
}
|
|
13413
|
-
async function createLLMSpanForMessages(messages,
|
|
14199
|
+
async function createLLMSpanForMessages(messages, promptMessages, conversationHistory, options, startTime, parentSpan, existingSpan) {
|
|
13414
14200
|
if (messages.length === 0) {
|
|
13415
14201
|
return void 0;
|
|
13416
14202
|
}
|
|
@@ -13420,11 +14206,7 @@ async function createLLMSpanForMessages(messages, prompt, conversationHistory, o
|
|
|
13420
14206
|
}
|
|
13421
14207
|
const model = lastMessage.message.model || options.model;
|
|
13422
14208
|
const usage = extractUsageFromMessage(lastMessage);
|
|
13423
|
-
const input = buildLLMInput(
|
|
13424
|
-
prompt,
|
|
13425
|
-
conversationHistory,
|
|
13426
|
-
capturedPromptMessages
|
|
13427
|
-
);
|
|
14209
|
+
const input = buildLLMInput(promptMessages, conversationHistory);
|
|
13428
14210
|
const outputs = messages.map(
|
|
13429
14211
|
(m) => m.message?.content && m.message?.role ? { content: m.message.content, role: m.message.role } : void 0
|
|
13430
14212
|
).filter(
|
|
@@ -13555,8 +14337,7 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
|
|
|
13555
14337
|
},
|
|
13556
14338
|
name: parsed.displayName,
|
|
13557
14339
|
parent: await resolveParentSpan(toolUseID, {
|
|
13558
|
-
agentId: input.agent_id
|
|
13559
|
-
preferTaskSiblingParent: shouldParentToolAsTaskSibling(parsed.toolName)
|
|
14340
|
+
agentId: input.agent_id
|
|
13560
14341
|
}),
|
|
13561
14342
|
spanAttributes: { type: "tool" /* TOOL */ }
|
|
13562
14343
|
});
|
|
@@ -13802,12 +14583,37 @@ function injectTracingHooks(options, resolveParentSpan, activeToolSpans, localTo
|
|
|
13802
14583
|
}
|
|
13803
14584
|
};
|
|
13804
14585
|
}
|
|
14586
|
+
function setSubAgentPromptMessages(state, parentToolUseId, promptMessages, source) {
|
|
14587
|
+
if (promptMessages.length === 0) {
|
|
14588
|
+
return;
|
|
14589
|
+
}
|
|
14590
|
+
const parentKey = llmParentKey(parentToolUseId);
|
|
14591
|
+
const sourcePriority = SUB_AGENT_PROMPT_SOURCE_PRIORITY[source];
|
|
14592
|
+
const currentPriority = state.promptSourcePriorityByParentKey.get(parentKey) ?? -1;
|
|
14593
|
+
if (sourcePriority > currentPriority) {
|
|
14594
|
+
state.promptMessagesByParentKey.set(parentKey, promptMessages);
|
|
14595
|
+
state.promptSourcePriorityByParentKey.set(parentKey, sourcePriority);
|
|
14596
|
+
}
|
|
14597
|
+
}
|
|
14598
|
+
function getConversationHistory(state, parentKey) {
|
|
14599
|
+
let conversationHistory = state.conversationHistoryByParentKey.get(parentKey);
|
|
14600
|
+
if (!conversationHistory) {
|
|
14601
|
+
conversationHistory = [];
|
|
14602
|
+
state.conversationHistoryByParentKey.set(parentKey, conversationHistory);
|
|
14603
|
+
}
|
|
14604
|
+
return conversationHistory;
|
|
14605
|
+
}
|
|
13805
14606
|
async function finalizeCurrentMessageGroup(state) {
|
|
13806
14607
|
if (state.currentMessages.length === 0) {
|
|
13807
14608
|
return;
|
|
13808
14609
|
}
|
|
13809
14610
|
const parentToolUseId = state.currentMessages[0]?.parent_tool_use_id ?? null;
|
|
13810
14611
|
const parentKey = llmParentKey(parentToolUseId);
|
|
14612
|
+
const conversationHistory = getConversationHistory(state, parentKey);
|
|
14613
|
+
const promptMessages = parentToolUseId ? state.promptMessagesByParentKey.get(parentKey) ?? [] : buildRootPromptMessages(
|
|
14614
|
+
state.originalPrompt,
|
|
14615
|
+
state.capturedPromptMessages
|
|
14616
|
+
);
|
|
13811
14617
|
let parentSpan = await state.span.export();
|
|
13812
14618
|
if (parentToolUseId) {
|
|
13813
14619
|
const subAgentSpan = state.subAgentSpans.get(parentToolUseId);
|
|
@@ -13818,11 +14624,10 @@ async function finalizeCurrentMessageGroup(state) {
|
|
|
13818
14624
|
const existingLlmSpan = state.activeLlmSpansByParentToolUse.get(parentKey);
|
|
13819
14625
|
const llmSpanResult = await createLLMSpanForMessages(
|
|
13820
14626
|
state.currentMessages,
|
|
13821
|
-
|
|
13822
|
-
|
|
14627
|
+
promptMessages,
|
|
14628
|
+
conversationHistory,
|
|
13823
14629
|
state.options,
|
|
13824
14630
|
state.currentMessageStartTime,
|
|
13825
|
-
state.capturedPromptMessages,
|
|
13826
14631
|
parentSpan,
|
|
13827
14632
|
existingLlmSpan
|
|
13828
14633
|
);
|
|
@@ -13836,6 +14641,7 @@ async function finalizeCurrentMessageGroup(state) {
|
|
|
13836
14641
|
state.latestRootLlmParentRef.value = llmSpanResult.spanExport;
|
|
13837
14642
|
}
|
|
13838
14643
|
if (llmSpanResult.finalMessage) {
|
|
14644
|
+
conversationHistory.push(llmSpanResult.finalMessage);
|
|
13839
14645
|
state.finalResults.push(llmSpanResult.finalMessage);
|
|
13840
14646
|
}
|
|
13841
14647
|
}
|
|
@@ -13863,6 +14669,15 @@ function maybeTrackToolUseContext(state, message) {
|
|
|
13863
14669
|
description: getStringProperty(block.input, "description"),
|
|
13864
14670
|
toolUseId: block.id
|
|
13865
14671
|
});
|
|
14672
|
+
const prompt = getStringProperty(block.input, "prompt");
|
|
14673
|
+
if (prompt) {
|
|
14674
|
+
setSubAgentPromptMessages(
|
|
14675
|
+
state,
|
|
14676
|
+
block.id,
|
|
14677
|
+
[{ content: prompt, role: "user" }],
|
|
14678
|
+
"delegation"
|
|
14679
|
+
);
|
|
14680
|
+
}
|
|
13866
14681
|
}
|
|
13867
14682
|
}
|
|
13868
14683
|
}
|
|
@@ -13981,6 +14796,14 @@ async function maybeHandleTaskLifecycleMessage(state, message) {
|
|
|
13981
14796
|
};
|
|
13982
14797
|
if (message.subtype === "task_started") {
|
|
13983
14798
|
const prompt = getStringProperty(message, "prompt");
|
|
14799
|
+
if (prompt) {
|
|
14800
|
+
setSubAgentPromptMessages(
|
|
14801
|
+
state,
|
|
14802
|
+
toolUseId,
|
|
14803
|
+
[{ content: prompt, role: "user" }],
|
|
14804
|
+
"lifecycle"
|
|
14805
|
+
);
|
|
14806
|
+
}
|
|
13984
14807
|
subAgentSpan.log({
|
|
13985
14808
|
input: prompt,
|
|
13986
14809
|
metadata
|
|
@@ -14031,6 +14854,28 @@ async function handleStreamMessage(state, message) {
|
|
|
14031
14854
|
return;
|
|
14032
14855
|
}
|
|
14033
14856
|
await maybeStartSubAgentSpan(state, message);
|
|
14857
|
+
const messageParentToolUseId = message.parent_tool_use_id;
|
|
14858
|
+
if (messageParentToolUseId && message.type === "user") {
|
|
14859
|
+
const conversationMessage = conversationMessageFromSDKMessage(message);
|
|
14860
|
+
if (conversationMessage?.role === "user") {
|
|
14861
|
+
await finalizeCurrentMessageGroup(state);
|
|
14862
|
+
const parentKey = llmParentKey(messageParentToolUseId);
|
|
14863
|
+
const conversationHistory = getConversationHistory(state, parentKey);
|
|
14864
|
+
const currentPromptSourcePriority = state.promptSourcePriorityByParentKey.get(parentKey) ?? -1;
|
|
14865
|
+
const canUseAsInitialSidechainPrompt = conversationHistory.length === 0 && currentPromptSourcePriority < SUB_AGENT_PROMPT_SOURCE_PRIORITY.sidechain && !messageContentHasBlockType(message, "tool_result");
|
|
14866
|
+
if (!canUseAsInitialSidechainPrompt) {
|
|
14867
|
+
conversationHistory.push(conversationMessage);
|
|
14868
|
+
return;
|
|
14869
|
+
}
|
|
14870
|
+
setSubAgentPromptMessages(
|
|
14871
|
+
state,
|
|
14872
|
+
messageParentToolUseId,
|
|
14873
|
+
[conversationMessage],
|
|
14874
|
+
"sidechain"
|
|
14875
|
+
);
|
|
14876
|
+
return;
|
|
14877
|
+
}
|
|
14878
|
+
}
|
|
14034
14879
|
const messageId = message.message?.id;
|
|
14035
14880
|
if (messageId && messageId !== state.currentMessageId) {
|
|
14036
14881
|
await finalizeCurrentMessageGroup(state);
|
|
@@ -14182,6 +15027,7 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
14182
15027
|
}
|
|
14183
15028
|
const activeToolSpans = /* @__PURE__ */ new Map();
|
|
14184
15029
|
const activeLlmSpansByParentToolUse = /* @__PURE__ */ new Map();
|
|
15030
|
+
const conversationHistoryByParentKey = /* @__PURE__ */ new Map();
|
|
14185
15031
|
const subAgentSpans = /* @__PURE__ */ new Map();
|
|
14186
15032
|
const endedSubAgentSpans = /* @__PURE__ */ new Set();
|
|
14187
15033
|
const toolUseToParent = /* @__PURE__ */ new Map();
|
|
@@ -14191,6 +15037,8 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
14191
15037
|
};
|
|
14192
15038
|
const subAgentDetailsByToolUseId = /* @__PURE__ */ new Map();
|
|
14193
15039
|
const taskIdToToolUseId = /* @__PURE__ */ new Map();
|
|
15040
|
+
const promptMessagesByParentKey = /* @__PURE__ */ new Map();
|
|
15041
|
+
const promptSourcePriorityByParentKey = /* @__PURE__ */ new Map();
|
|
14194
15042
|
const localToolContext = createClaudeLocalToolContext();
|
|
14195
15043
|
const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
|
|
14196
15044
|
const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
|
|
@@ -14199,38 +15047,19 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
14199
15047
|
const parentToolUseId = trackedParentToolUseId ?? (context?.agentId ? taskIdToToolUseId.get(context.agentId) ?? null : null);
|
|
14200
15048
|
const parentKey = llmParentKey(parentToolUseId);
|
|
14201
15049
|
const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
|
|
14202
|
-
|
|
14203
|
-
|
|
14204
|
-
|
|
14205
|
-
|
|
14206
|
-
|
|
14207
|
-
|
|
14208
|
-
|
|
14209
|
-
|
|
14210
|
-
|
|
14211
|
-
|
|
14212
|
-
|
|
14213
|
-
}
|
|
14214
|
-
if (parentToolUseId) {
|
|
14215
|
-
const subAgentSpan = await ensureSubAgentSpan(
|
|
14216
|
-
subAgentDetailsByToolUseId,
|
|
14217
|
-
span,
|
|
14218
|
-
activeToolSpans,
|
|
14219
|
-
subAgentSpans,
|
|
14220
|
-
parentToolUseId
|
|
14221
|
-
);
|
|
14222
|
-
return subAgentSpan.export();
|
|
14223
|
-
}
|
|
14224
|
-
return span.export();
|
|
14225
|
-
}
|
|
14226
|
-
if (activeLlmSpan) {
|
|
14227
|
-
return activeLlmSpan.export();
|
|
15050
|
+
const latestLlmParent = parentToolUseId ? latestLlmParentBySubAgentToolUse.get(parentToolUseId) : latestRootLlmParentRef.value;
|
|
15051
|
+
if (!activeLlmSpan && !latestLlmParent) {
|
|
15052
|
+
await ensureActiveLlmSpanForParentToolUse(
|
|
15053
|
+
span,
|
|
15054
|
+
activeLlmSpansByParentToolUse,
|
|
15055
|
+
subAgentDetailsByToolUseId,
|
|
15056
|
+
activeToolSpans,
|
|
15057
|
+
subAgentSpans,
|
|
15058
|
+
parentToolUseId,
|
|
15059
|
+
getCurrentUnixTimestamp()
|
|
15060
|
+
);
|
|
14228
15061
|
}
|
|
14229
15062
|
if (parentToolUseId) {
|
|
14230
|
-
const parentLlm = latestLlmParentBySubAgentToolUse.get(parentToolUseId);
|
|
14231
|
-
if (parentLlm) {
|
|
14232
|
-
return parentLlm;
|
|
14233
|
-
}
|
|
14234
15063
|
const subAgentSpan = await ensureSubAgentSpan(
|
|
14235
15064
|
subAgentDetailsByToolUseId,
|
|
14236
15065
|
span,
|
|
@@ -14240,9 +15069,6 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
14240
15069
|
);
|
|
14241
15070
|
return subAgentSpan.export();
|
|
14242
15071
|
}
|
|
14243
|
-
if (latestRootLlmParentRef.value) {
|
|
14244
|
-
return latestRootLlmParentRef.value;
|
|
14245
|
-
}
|
|
14246
15072
|
return span.export();
|
|
14247
15073
|
};
|
|
14248
15074
|
localToolContext.resolveLocalToolParent = resolveToolUseParentSpan;
|
|
@@ -14263,6 +15089,7 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
14263
15089
|
accumulatedOutputTokens: 0,
|
|
14264
15090
|
activeLlmSpansByParentToolUse,
|
|
14265
15091
|
activeToolSpans,
|
|
15092
|
+
conversationHistoryByParentKey,
|
|
14266
15093
|
capturedPromptMessages,
|
|
14267
15094
|
currentMessageId: void 0,
|
|
14268
15095
|
currentMessageStartTime: startTime,
|
|
@@ -14273,7 +15100,9 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
14273
15100
|
originalPrompt,
|
|
14274
15101
|
processing: Promise.resolve(),
|
|
14275
15102
|
promptDone,
|
|
15103
|
+
promptMessagesByParentKey,
|
|
14276
15104
|
promptStarted: () => promptStarted,
|
|
15105
|
+
promptSourcePriorityByParentKey,
|
|
14277
15106
|
span,
|
|
14278
15107
|
subAgentDetailsByToolUseId,
|
|
14279
15108
|
subAgentSpans,
|
|
@@ -15702,6 +16531,10 @@ var googleGenAIChannels = defineChannels("@google/genai", {
|
|
|
15702
16531
|
embedContent: channel({
|
|
15703
16532
|
channelName: "models.embedContent",
|
|
15704
16533
|
kind: "async"
|
|
16534
|
+
}),
|
|
16535
|
+
interactionsCreate: channel({
|
|
16536
|
+
channelName: "interactions.create",
|
|
16537
|
+
kind: "async"
|
|
15705
16538
|
})
|
|
15706
16539
|
});
|
|
15707
16540
|
|
|
@@ -15729,6 +16562,7 @@ var GoogleGenAIPlugin = class extends BasePlugin {
|
|
|
15729
16562
|
this.subscribeToGenerateContentChannel();
|
|
15730
16563
|
this.subscribeToGenerateContentStreamChannel();
|
|
15731
16564
|
this.subscribeToEmbedContentChannel();
|
|
16565
|
+
this.subscribeToInteractionsCreateChannel();
|
|
15732
16566
|
}
|
|
15733
16567
|
subscribeToGenerateContentChannel() {
|
|
15734
16568
|
const tracingChannel = googleGenAIChannels.generateContent.tracingChannel();
|
|
@@ -15901,7 +16735,30 @@ var GoogleGenAIPlugin = class extends BasePlugin {
|
|
|
15901
16735
|
tracingChannel.unsubscribe(handlers);
|
|
15902
16736
|
});
|
|
15903
16737
|
}
|
|
16738
|
+
subscribeToInteractionsCreateChannel() {
|
|
16739
|
+
this.unsubscribers.push(
|
|
16740
|
+
traceStreamingChannel(
|
|
16741
|
+
googleGenAIChannels.interactionsCreate,
|
|
16742
|
+
{
|
|
16743
|
+
name: "create_interaction",
|
|
16744
|
+
shouldTrace: ([params]) => !isBackgroundInteractionCreate(params),
|
|
16745
|
+
type: "llm" /* LLM */,
|
|
16746
|
+
extractInput: ([params]) => ({
|
|
16747
|
+
input: serializeInteractionInput(params),
|
|
16748
|
+
metadata: extractInteractionMetadata(params)
|
|
16749
|
+
}),
|
|
16750
|
+
extractOutput: (result) => serializeInteractionValue(result),
|
|
16751
|
+
extractMetadata: (result) => extractInteractionResponseMetadata(result),
|
|
16752
|
+
extractMetrics: (result, startTime) => cleanMetrics3(extractInteractionMetrics(result, startTime)),
|
|
16753
|
+
aggregateChunks: (chunks, _result, _event, startTime) => aggregateInteractionEvents(chunks, startTime)
|
|
16754
|
+
}
|
|
16755
|
+
)
|
|
16756
|
+
);
|
|
16757
|
+
}
|
|
15904
16758
|
};
|
|
16759
|
+
function isBackgroundInteractionCreate(params) {
|
|
16760
|
+
return tryToDict(params)?.background === true;
|
|
16761
|
+
}
|
|
15905
16762
|
function ensureSpanState(states, event, create) {
|
|
15906
16763
|
const existing = states.get(event);
|
|
15907
16764
|
if (existing) {
|
|
@@ -16109,6 +16966,60 @@ function serializeEmbedContentInput(params) {
|
|
|
16109
16966
|
}
|
|
16110
16967
|
return input;
|
|
16111
16968
|
}
|
|
16969
|
+
function serializeInteractionInput(params) {
|
|
16970
|
+
const input = {
|
|
16971
|
+
input: serializeInteractionValue(params.input)
|
|
16972
|
+
};
|
|
16973
|
+
for (const key of [
|
|
16974
|
+
"model",
|
|
16975
|
+
"agent",
|
|
16976
|
+
"agent_config",
|
|
16977
|
+
"api_version",
|
|
16978
|
+
"background",
|
|
16979
|
+
"environment",
|
|
16980
|
+
"generation_config",
|
|
16981
|
+
"previous_interaction_id",
|
|
16982
|
+
"response_format",
|
|
16983
|
+
"response_mime_type",
|
|
16984
|
+
"response_modalities",
|
|
16985
|
+
"service_tier",
|
|
16986
|
+
"store",
|
|
16987
|
+
"stream",
|
|
16988
|
+
"system_instruction",
|
|
16989
|
+
"webhook_config"
|
|
16990
|
+
]) {
|
|
16991
|
+
const value = params[key];
|
|
16992
|
+
if (value !== void 0) {
|
|
16993
|
+
input[key] = serializeInteractionValue(value);
|
|
16994
|
+
}
|
|
16995
|
+
}
|
|
16996
|
+
return input;
|
|
16997
|
+
}
|
|
16998
|
+
function extractInteractionMetadata(params) {
|
|
16999
|
+
const metadata = {};
|
|
17000
|
+
for (const key of [
|
|
17001
|
+
"model",
|
|
17002
|
+
"agent",
|
|
17003
|
+
"agent_config",
|
|
17004
|
+
"generation_config",
|
|
17005
|
+
"system_instruction",
|
|
17006
|
+
"response_format",
|
|
17007
|
+
"response_mime_type",
|
|
17008
|
+
"response_modalities",
|
|
17009
|
+
"service_tier"
|
|
17010
|
+
]) {
|
|
17011
|
+
const value = params[key];
|
|
17012
|
+
if (value !== void 0) {
|
|
17013
|
+
metadata[key] = serializeInteractionValue(value);
|
|
17014
|
+
}
|
|
17015
|
+
}
|
|
17016
|
+
if (Array.isArray(params.tools)) {
|
|
17017
|
+
metadata.tools = params.tools.map(
|
|
17018
|
+
(tool) => serializeInteractionValue(tool)
|
|
17019
|
+
);
|
|
17020
|
+
}
|
|
17021
|
+
return metadata;
|
|
17022
|
+
}
|
|
16112
17023
|
function serializeContentCollection(contents) {
|
|
16113
17024
|
if (contents === null || contents === void 0) {
|
|
16114
17025
|
return null;
|
|
@@ -16139,21 +17050,8 @@ function serializePart(part) {
|
|
|
16139
17050
|
}
|
|
16140
17051
|
if (part.inlineData && part.inlineData.data) {
|
|
16141
17052
|
const { data, mimeType } = part.inlineData;
|
|
16142
|
-
|
|
16143
|
-
|
|
16144
|
-
const filename = `file.${extension}`;
|
|
16145
|
-
const buffer = typeof data === "string" ? typeof Buffer !== "undefined" ? Buffer.from(data, "base64") : new Uint8Array(
|
|
16146
|
-
atob(data).split("").map((c) => c.charCodeAt(0))
|
|
16147
|
-
) : typeof Buffer !== "undefined" ? Buffer.from(data) : new Uint8Array(data);
|
|
16148
|
-
const arrayBuffer = buffer instanceof Uint8Array ? buffer.buffer.slice(
|
|
16149
|
-
buffer.byteOffset,
|
|
16150
|
-
buffer.byteOffset + buffer.byteLength
|
|
16151
|
-
) : buffer;
|
|
16152
|
-
const attachment = new Attachment({
|
|
16153
|
-
data: arrayBuffer,
|
|
16154
|
-
filename,
|
|
16155
|
-
contentType: mimeType || "application/octet-stream"
|
|
16156
|
-
});
|
|
17053
|
+
const attachment = createAttachmentFromInlineData(data, mimeType);
|
|
17054
|
+
if (attachment) {
|
|
16157
17055
|
return {
|
|
16158
17056
|
image_url: { url: attachment }
|
|
16159
17057
|
};
|
|
@@ -16161,6 +17059,59 @@ function serializePart(part) {
|
|
|
16161
17059
|
}
|
|
16162
17060
|
return part;
|
|
16163
17061
|
}
|
|
17062
|
+
function serializeInteractionValue(value, seen = /* @__PURE__ */ new WeakSet()) {
|
|
17063
|
+
if (value === null || value === void 0 || typeof value !== "object") {
|
|
17064
|
+
return value;
|
|
17065
|
+
}
|
|
17066
|
+
if (Array.isArray(value)) {
|
|
17067
|
+
return value.map((item) => serializeInteractionValue(item, seen));
|
|
17068
|
+
}
|
|
17069
|
+
const dict = tryToDict(value);
|
|
17070
|
+
if (dict === null || dict === void 0 || typeof dict !== "object") {
|
|
17071
|
+
return dict;
|
|
17072
|
+
}
|
|
17073
|
+
if (Array.isArray(dict)) {
|
|
17074
|
+
return dict.map((item) => serializeInteractionValue(item, seen));
|
|
17075
|
+
}
|
|
17076
|
+
if (seen.has(dict)) {
|
|
17077
|
+
return "[Circular]";
|
|
17078
|
+
}
|
|
17079
|
+
seen.add(dict);
|
|
17080
|
+
try {
|
|
17081
|
+
const serialized = {};
|
|
17082
|
+
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;
|
|
17083
|
+
const attachment = mimeType && "data" in dict && dict.data !== void 0 ? createAttachmentFromInlineData(dict.data, mimeType) : null;
|
|
17084
|
+
for (const [key, entry] of Object.entries(dict)) {
|
|
17085
|
+
if (key === "data" && attachment) {
|
|
17086
|
+
serialized[key] = attachment;
|
|
17087
|
+
} else {
|
|
17088
|
+
serialized[key] = serializeInteractionValue(entry, seen);
|
|
17089
|
+
}
|
|
17090
|
+
}
|
|
17091
|
+
return serialized;
|
|
17092
|
+
} finally {
|
|
17093
|
+
seen.delete(dict);
|
|
17094
|
+
}
|
|
17095
|
+
}
|
|
17096
|
+
function createAttachmentFromInlineData(data, mimeType) {
|
|
17097
|
+
if (!(data instanceof Uint8Array || typeof Buffer !== "undefined" && Buffer.isBuffer(data) || typeof data === "string")) {
|
|
17098
|
+
return null;
|
|
17099
|
+
}
|
|
17100
|
+
const extension = mimeType ? mimeType.split("/")[1] : "bin";
|
|
17101
|
+
const filename = `file.${extension}`;
|
|
17102
|
+
const buffer = typeof data === "string" ? typeof Buffer !== "undefined" ? Buffer.from(data, "base64") : new Uint8Array(
|
|
17103
|
+
atob(data).split("").map((c) => c.charCodeAt(0))
|
|
17104
|
+
) : typeof Buffer !== "undefined" ? Buffer.from(data) : new Uint8Array(data);
|
|
17105
|
+
const arrayBuffer = buffer instanceof Uint8Array ? buffer.buffer.slice(
|
|
17106
|
+
buffer.byteOffset,
|
|
17107
|
+
buffer.byteOffset + buffer.byteLength
|
|
17108
|
+
) : buffer;
|
|
17109
|
+
return new Attachment({
|
|
17110
|
+
data: arrayBuffer,
|
|
17111
|
+
filename,
|
|
17112
|
+
contentType: mimeType || "application/octet-stream"
|
|
17113
|
+
});
|
|
17114
|
+
}
|
|
16164
17115
|
function serializeGenerateContentTools(params) {
|
|
16165
17116
|
const config = params.config ? tryToDict(params.config) : null;
|
|
16166
17117
|
const tools = config?.tools;
|
|
@@ -16245,6 +17196,33 @@ function extractEmbedContentMetrics(response, startTime) {
|
|
|
16245
17196
|
}
|
|
16246
17197
|
return metrics;
|
|
16247
17198
|
}
|
|
17199
|
+
function extractInteractionMetrics(response, startTime) {
|
|
17200
|
+
const metrics = {};
|
|
17201
|
+
if (startTime !== void 0) {
|
|
17202
|
+
const end = getCurrentUnixTimestamp();
|
|
17203
|
+
metrics.start = startTime;
|
|
17204
|
+
metrics.end = end;
|
|
17205
|
+
metrics.duration = end - startTime;
|
|
17206
|
+
}
|
|
17207
|
+
if (response?.usage) {
|
|
17208
|
+
populateInteractionUsageMetrics(metrics, response.usage);
|
|
17209
|
+
}
|
|
17210
|
+
return metrics;
|
|
17211
|
+
}
|
|
17212
|
+
function extractInteractionResponseMetadata(response) {
|
|
17213
|
+
const responseDict = tryToDict(response);
|
|
17214
|
+
if (!responseDict) {
|
|
17215
|
+
return void 0;
|
|
17216
|
+
}
|
|
17217
|
+
const metadata = {};
|
|
17218
|
+
if (typeof responseDict.id === "string") {
|
|
17219
|
+
metadata.interaction_id = responseDict.id;
|
|
17220
|
+
}
|
|
17221
|
+
if (typeof responseDict.status === "string") {
|
|
17222
|
+
metadata.status = responseDict.status;
|
|
17223
|
+
}
|
|
17224
|
+
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
17225
|
+
}
|
|
16248
17226
|
function extractEmbedPromptTokenCount(response) {
|
|
16249
17227
|
if (!response) {
|
|
16250
17228
|
return void 0;
|
|
@@ -16307,6 +17285,23 @@ function populateUsageMetrics(metrics, usage) {
|
|
|
16307
17285
|
metrics.completion_reasoning_tokens = usage.thoughtsTokenCount;
|
|
16308
17286
|
}
|
|
16309
17287
|
}
|
|
17288
|
+
function populateInteractionUsageMetrics(metrics, usage) {
|
|
17289
|
+
if (typeof usage.total_input_tokens === "number") {
|
|
17290
|
+
metrics.prompt_tokens = usage.total_input_tokens;
|
|
17291
|
+
}
|
|
17292
|
+
if (typeof usage.total_output_tokens === "number") {
|
|
17293
|
+
metrics.completion_tokens = usage.total_output_tokens;
|
|
17294
|
+
}
|
|
17295
|
+
if (typeof usage.total_tokens === "number") {
|
|
17296
|
+
metrics.tokens = usage.total_tokens;
|
|
17297
|
+
}
|
|
17298
|
+
if (typeof usage.total_cached_tokens === "number") {
|
|
17299
|
+
metrics.prompt_cached_tokens = usage.total_cached_tokens;
|
|
17300
|
+
}
|
|
17301
|
+
if (typeof usage.total_thought_tokens === "number") {
|
|
17302
|
+
metrics.completion_reasoning_tokens = usage.total_thought_tokens;
|
|
17303
|
+
}
|
|
17304
|
+
}
|
|
16310
17305
|
function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
|
|
16311
17306
|
const end = getCurrentUnixTimestamp();
|
|
16312
17307
|
const metrics = {
|
|
@@ -16404,6 +17399,146 @@ function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
|
|
|
16404
17399
|
}
|
|
16405
17400
|
return { aggregated, metrics };
|
|
16406
17401
|
}
|
|
17402
|
+
function aggregateInteractionEvents(chunks, startTime) {
|
|
17403
|
+
const end = getCurrentUnixTimestamp();
|
|
17404
|
+
const metrics = {};
|
|
17405
|
+
if (startTime !== void 0) {
|
|
17406
|
+
metrics.start = startTime;
|
|
17407
|
+
metrics.end = end;
|
|
17408
|
+
metrics.duration = end - startTime;
|
|
17409
|
+
}
|
|
17410
|
+
let latestInteraction;
|
|
17411
|
+
let latestUsage;
|
|
17412
|
+
let status;
|
|
17413
|
+
let outputText = "";
|
|
17414
|
+
const steps = /* @__PURE__ */ new Map();
|
|
17415
|
+
for (const chunk of chunks) {
|
|
17416
|
+
const event = tryToDict(chunk);
|
|
17417
|
+
if (!event) {
|
|
17418
|
+
continue;
|
|
17419
|
+
}
|
|
17420
|
+
const usage = extractInteractionUsageFromEvent(event);
|
|
17421
|
+
if (usage) {
|
|
17422
|
+
latestUsage = usage;
|
|
17423
|
+
}
|
|
17424
|
+
const interaction = tryToDict(event.interaction);
|
|
17425
|
+
if (interaction) {
|
|
17426
|
+
latestInteraction = serializeInteractionValue(interaction);
|
|
17427
|
+
if (typeof interaction.status === "string") {
|
|
17428
|
+
status = interaction.status;
|
|
17429
|
+
}
|
|
17430
|
+
}
|
|
17431
|
+
if (typeof event.status === "string") {
|
|
17432
|
+
status = event.status;
|
|
17433
|
+
}
|
|
17434
|
+
const index = typeof event.index === "number" ? event.index : void 0;
|
|
17435
|
+
if (index === void 0) {
|
|
17436
|
+
continue;
|
|
17437
|
+
}
|
|
17438
|
+
if (event.event_type === "step.start") {
|
|
17439
|
+
const compact = compactInteractionStep(event.step);
|
|
17440
|
+
compact.index = index;
|
|
17441
|
+
steps.set(index, compact);
|
|
17442
|
+
continue;
|
|
17443
|
+
}
|
|
17444
|
+
if (event.event_type === "step.delta") {
|
|
17445
|
+
const step = steps.get(index) ?? { index };
|
|
17446
|
+
const textDelta = applyInteractionDelta(step, event.delta);
|
|
17447
|
+
if (textDelta) {
|
|
17448
|
+
outputText += textDelta;
|
|
17449
|
+
}
|
|
17450
|
+
steps.set(index, step);
|
|
17451
|
+
}
|
|
17452
|
+
}
|
|
17453
|
+
if (latestUsage) {
|
|
17454
|
+
populateInteractionUsageMetrics(metrics, latestUsage);
|
|
17455
|
+
}
|
|
17456
|
+
const output = latestInteraction ? { ...latestInteraction } : {};
|
|
17457
|
+
if (status) {
|
|
17458
|
+
output.status = status;
|
|
17459
|
+
}
|
|
17460
|
+
if (outputText) {
|
|
17461
|
+
output.output_text = outputText;
|
|
17462
|
+
}
|
|
17463
|
+
if (latestUsage) {
|
|
17464
|
+
output.usage = serializeInteractionValue(latestUsage);
|
|
17465
|
+
}
|
|
17466
|
+
const compactSteps = Array.from(steps.values()).sort(
|
|
17467
|
+
(left, right) => Number(left.index ?? 0) - Number(right.index ?? 0)
|
|
17468
|
+
);
|
|
17469
|
+
if (compactSteps.length > 0) {
|
|
17470
|
+
output.steps = compactSteps;
|
|
17471
|
+
}
|
|
17472
|
+
const metadata = {};
|
|
17473
|
+
if (typeof output.id === "string") {
|
|
17474
|
+
metadata.interaction_id = output.id;
|
|
17475
|
+
}
|
|
17476
|
+
if (typeof output.status === "string") {
|
|
17477
|
+
metadata.status = output.status;
|
|
17478
|
+
}
|
|
17479
|
+
return {
|
|
17480
|
+
output,
|
|
17481
|
+
metrics: cleanMetrics3(metrics),
|
|
17482
|
+
...Object.keys(metadata).length > 0 ? { metadata } : {}
|
|
17483
|
+
};
|
|
17484
|
+
}
|
|
17485
|
+
function extractInteractionUsageFromEvent(event) {
|
|
17486
|
+
const metadata = tryToDict(event.metadata);
|
|
17487
|
+
const metadataUsage = tryToDict(metadata?.usage);
|
|
17488
|
+
if (metadataUsage) {
|
|
17489
|
+
return metadataUsage;
|
|
17490
|
+
}
|
|
17491
|
+
const metadataTotalUsage = tryToDict(metadata?.total_usage);
|
|
17492
|
+
if (metadataTotalUsage) {
|
|
17493
|
+
return metadataTotalUsage;
|
|
17494
|
+
}
|
|
17495
|
+
const interaction = tryToDict(event.interaction);
|
|
17496
|
+
const interactionUsage = tryToDict(interaction?.usage);
|
|
17497
|
+
return interactionUsage ? interactionUsage : void 0;
|
|
17498
|
+
}
|
|
17499
|
+
function compactInteractionStep(step) {
|
|
17500
|
+
const stepDict = tryToDict(step);
|
|
17501
|
+
if (!stepDict) {
|
|
17502
|
+
return {};
|
|
17503
|
+
}
|
|
17504
|
+
const compact = {};
|
|
17505
|
+
for (const key of [
|
|
17506
|
+
"type",
|
|
17507
|
+
"content",
|
|
17508
|
+
"name",
|
|
17509
|
+
"server_name",
|
|
17510
|
+
"arguments",
|
|
17511
|
+
"result",
|
|
17512
|
+
"is_error"
|
|
17513
|
+
]) {
|
|
17514
|
+
if (stepDict[key] !== void 0) {
|
|
17515
|
+
compact[key] = serializeInteractionValue(stepDict[key]);
|
|
17516
|
+
}
|
|
17517
|
+
}
|
|
17518
|
+
return Object.keys(compact).length > 0 ? compact : serializeInteractionValue(stepDict);
|
|
17519
|
+
}
|
|
17520
|
+
function applyInteractionDelta(step, delta) {
|
|
17521
|
+
const deltaDict = tryToDict(delta);
|
|
17522
|
+
if (!deltaDict) {
|
|
17523
|
+
return void 0;
|
|
17524
|
+
}
|
|
17525
|
+
const deltaType = deltaDict.type;
|
|
17526
|
+
if (typeof deltaType === "string" && typeof step.type !== "string") {
|
|
17527
|
+
step.type = deltaType === "text" ? "model_output" : deltaType;
|
|
17528
|
+
}
|
|
17529
|
+
if (deltaType === "text" && typeof deltaDict.text === "string") {
|
|
17530
|
+
step.text = `${typeof step.text === "string" ? step.text : ""}${deltaDict.text}`;
|
|
17531
|
+
return deltaDict.text;
|
|
17532
|
+
}
|
|
17533
|
+
if (deltaType === "arguments_delta" && typeof deltaDict.arguments === "string") {
|
|
17534
|
+
step.arguments = `${typeof step.arguments === "string" ? step.arguments : ""}${deltaDict.arguments}`;
|
|
17535
|
+
return void 0;
|
|
17536
|
+
}
|
|
17537
|
+
const deltas = Array.isArray(step.deltas) ? step.deltas : [];
|
|
17538
|
+
deltas.push(serializeInteractionValue(deltaDict));
|
|
17539
|
+
step.deltas = deltas;
|
|
17540
|
+
return void 0;
|
|
17541
|
+
}
|
|
16407
17542
|
function cleanMetrics3(metrics) {
|
|
16408
17543
|
const cleaned = {};
|
|
16409
17544
|
for (const [key, value] of Object.entries(metrics)) {
|
|
@@ -22230,7 +23365,8 @@ var FlueObserveBridge = class {
|
|
|
22230
23365
|
metadata
|
|
22231
23366
|
}
|
|
22232
23367
|
});
|
|
22233
|
-
|
|
23368
|
+
const activeContext = enterCurrentFlueSpan(span);
|
|
23369
|
+
this.runsById.set(event.runId, { activeContext, metadata, span });
|
|
22234
23370
|
}
|
|
22235
23371
|
handleRunEnd(event) {
|
|
22236
23372
|
const state = this.runsById.get(event.runId);
|
|
@@ -22248,6 +23384,7 @@ var FlueObserveBridge = class {
|
|
|
22248
23384
|
});
|
|
22249
23385
|
safeEnd(state.span, eventTime(event.timestamp));
|
|
22250
23386
|
this.runsById.delete(event.runId);
|
|
23387
|
+
restoreCurrentFlueSpan(state.activeContext);
|
|
22251
23388
|
}
|
|
22252
23389
|
void flush().catch((error) => {
|
|
22253
23390
|
logInstrumentationError3("Flue flush", error);
|
|
@@ -22374,7 +23511,8 @@ var FlueObserveBridge = class {
|
|
|
22374
23511
|
metadata
|
|
22375
23512
|
}
|
|
22376
23513
|
});
|
|
22377
|
-
|
|
23514
|
+
const activeContext = enterCurrentFlueSpan(span);
|
|
23515
|
+
this.toolsByKey.set(toolKey(event), { activeContext, metadata, span });
|
|
22378
23516
|
}
|
|
22379
23517
|
handleToolCall(event) {
|
|
22380
23518
|
if (!event.toolCallId) {
|
|
@@ -22397,6 +23535,7 @@ var FlueObserveBridge = class {
|
|
|
22397
23535
|
});
|
|
22398
23536
|
safeEnd(state.span, eventTime(event.timestamp));
|
|
22399
23537
|
this.toolsByKey.delete(key);
|
|
23538
|
+
restoreCurrentFlueSpan(state.activeContext);
|
|
22400
23539
|
}
|
|
22401
23540
|
handleTaskStart(event) {
|
|
22402
23541
|
if (!event.taskId) {
|
|
@@ -22801,7 +23940,35 @@ function stateMatchesRun(state, runId) {
|
|
|
22801
23940
|
function startFlueSpan(parent, args) {
|
|
22802
23941
|
return parent ? withCurrent(parent, () => startSpan(args)) : startSpan(args);
|
|
22803
23942
|
}
|
|
22804
|
-
function
|
|
23943
|
+
function enterCurrentFlueSpan(span) {
|
|
23944
|
+
const contextManager = _internalGetGlobalState()?.contextManager;
|
|
23945
|
+
const store = contextManager ? Reflect.get(contextManager, BRAINTRUST_CURRENT_SPAN_STORE) : void 0;
|
|
23946
|
+
if (!contextManager || !isCurrentSpanStore(store)) {
|
|
23947
|
+
return void 0;
|
|
23948
|
+
}
|
|
23949
|
+
const previous = store.getStore();
|
|
23950
|
+
try {
|
|
23951
|
+
store.enterWith(contextManager.wrapSpanForStore(span));
|
|
23952
|
+
return { previous, store };
|
|
23953
|
+
} catch (error) {
|
|
23954
|
+
logInstrumentationError3("Flue context propagation", error);
|
|
23955
|
+
return void 0;
|
|
23956
|
+
}
|
|
23957
|
+
}
|
|
23958
|
+
function isCurrentSpanStore(value) {
|
|
23959
|
+
return isObjectLike(value) && typeof Reflect.get(value, "enterWith") === "function" && typeof Reflect.get(value, "getStore") === "function";
|
|
23960
|
+
}
|
|
23961
|
+
function restoreCurrentFlueSpan(activeContext) {
|
|
23962
|
+
if (!activeContext) {
|
|
23963
|
+
return;
|
|
23964
|
+
}
|
|
23965
|
+
try {
|
|
23966
|
+
activeContext.store.enterWith(activeContext.previous);
|
|
23967
|
+
} catch (error) {
|
|
23968
|
+
logInstrumentationError3("Flue context restoration", error);
|
|
23969
|
+
}
|
|
23970
|
+
}
|
|
23971
|
+
function safeLog3(span, event) {
|
|
22805
23972
|
try {
|
|
22806
23973
|
span.log(event);
|
|
22807
23974
|
} catch (error) {
|
|
@@ -23278,6 +24445,890 @@ function isBraintrustHandler(handler) {
|
|
|
23278
24445
|
return Reflect.get(handler, "name") === BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
|
|
23279
24446
|
}
|
|
23280
24447
|
|
|
24448
|
+
// src/instrumentation/plugins/pi-coding-agent-channels.ts
|
|
24449
|
+
var piCodingAgentChannels = defineChannels(
|
|
24450
|
+
"@earendil-works/pi-coding-agent",
|
|
24451
|
+
{
|
|
24452
|
+
prompt: channel({
|
|
24453
|
+
channelName: "AgentSession.prompt",
|
|
24454
|
+
kind: "async"
|
|
24455
|
+
})
|
|
24456
|
+
}
|
|
24457
|
+
);
|
|
24458
|
+
|
|
24459
|
+
// src/instrumentation/plugins/pi-coding-agent-plugin.ts
|
|
24460
|
+
var piStreamPatchStates = /* @__PURE__ */ new WeakMap();
|
|
24461
|
+
var piPromptContextStore;
|
|
24462
|
+
var PiCodingAgentPlugin = class extends BasePlugin {
|
|
24463
|
+
activePromptStates = /* @__PURE__ */ new Set();
|
|
24464
|
+
onEnable() {
|
|
24465
|
+
this.subscribeToPrompt();
|
|
24466
|
+
}
|
|
24467
|
+
onDisable() {
|
|
24468
|
+
for (const unsubscribe of this.unsubscribers) {
|
|
24469
|
+
unsubscribe();
|
|
24470
|
+
}
|
|
24471
|
+
this.unsubscribers = [];
|
|
24472
|
+
for (const state of [...this.activePromptStates]) {
|
|
24473
|
+
void finalizePiPromptRun(state).catch((error) => {
|
|
24474
|
+
logInstrumentationError4("Pi Coding Agent disable cleanup", error);
|
|
24475
|
+
});
|
|
24476
|
+
}
|
|
24477
|
+
}
|
|
24478
|
+
subscribeToPrompt() {
|
|
24479
|
+
const channel2 = piCodingAgentChannels.prompt.tracingChannel();
|
|
24480
|
+
const states = /* @__PURE__ */ new WeakMap();
|
|
24481
|
+
const unbindAutoInstrumentationSuppression = bindAutoInstrumentationSuppressionToStart(channel2);
|
|
24482
|
+
const handlers = {
|
|
24483
|
+
start: (event) => {
|
|
24484
|
+
const state = startPiPromptRun(event, (state2) => {
|
|
24485
|
+
this.activePromptStates.delete(state2);
|
|
24486
|
+
});
|
|
24487
|
+
if (state) {
|
|
24488
|
+
this.activePromptStates.add(state);
|
|
24489
|
+
states.set(event, state);
|
|
24490
|
+
}
|
|
24491
|
+
},
|
|
24492
|
+
asyncEnd: async (event) => {
|
|
24493
|
+
const state = states.get(event);
|
|
24494
|
+
if (!state) {
|
|
24495
|
+
return;
|
|
24496
|
+
}
|
|
24497
|
+
states.delete(event);
|
|
24498
|
+
state.promptCallEnded = true;
|
|
24499
|
+
if (!state.finalized && state.deferCompletionUntilTurnEnd && !state.turnEnded) {
|
|
24500
|
+
if (!state.sawStreamFn) {
|
|
24501
|
+
state.queued = true;
|
|
24502
|
+
if (!state.streamPatchState.queuedPromptStates.includes(state)) {
|
|
24503
|
+
state.streamPatchState.queuedPromptStates.push(state);
|
|
24504
|
+
}
|
|
24505
|
+
}
|
|
24506
|
+
return;
|
|
24507
|
+
}
|
|
24508
|
+
await finalizePiPromptRun(state);
|
|
24509
|
+
},
|
|
24510
|
+
error: async (event) => {
|
|
24511
|
+
const state = states.get(event);
|
|
24512
|
+
if (!state) {
|
|
24513
|
+
return;
|
|
24514
|
+
}
|
|
24515
|
+
states.delete(event);
|
|
24516
|
+
await finalizePiPromptRun(state, event.error);
|
|
24517
|
+
}
|
|
24518
|
+
};
|
|
24519
|
+
channel2.subscribe(handlers);
|
|
24520
|
+
this.unsubscribers.push(() => {
|
|
24521
|
+
unbindAutoInstrumentationSuppression?.();
|
|
24522
|
+
channel2.unsubscribe(handlers);
|
|
24523
|
+
});
|
|
24524
|
+
}
|
|
24525
|
+
};
|
|
24526
|
+
function startPiPromptRun(event, onFinalize) {
|
|
24527
|
+
const session = extractSession(event);
|
|
24528
|
+
const agent = session?.agent;
|
|
24529
|
+
if (!session || !isPiAgent(agent)) {
|
|
24530
|
+
return void 0;
|
|
24531
|
+
}
|
|
24532
|
+
const metadata = {
|
|
24533
|
+
...extractSessionMetadata(session),
|
|
24534
|
+
...extractPromptOptionsMetadata(event.arguments[1]),
|
|
24535
|
+
"pi_coding_agent.operation": "AgentSession.prompt",
|
|
24536
|
+
provider: session.model?.provider ?? agent.state?.model?.provider ?? "pi",
|
|
24537
|
+
...session.model?.id || agent.state?.model?.id ? { model: session.model?.id ?? agent.state?.model?.id } : {},
|
|
24538
|
+
...event.moduleVersion ? { "pi_coding_agent.version": event.moduleVersion } : {}
|
|
24539
|
+
};
|
|
24540
|
+
const span = startSpan({
|
|
24541
|
+
event: {
|
|
24542
|
+
input: extractPromptInput(event.arguments[0], event.arguments[1]),
|
|
24543
|
+
metadata
|
|
24544
|
+
},
|
|
24545
|
+
name: "AgentSession.prompt",
|
|
24546
|
+
spanAttributes: { type: "task" /* TASK */ }
|
|
24547
|
+
});
|
|
24548
|
+
const streamPatchState = installPiStreamPatch(agent);
|
|
24549
|
+
const options = event.arguments[1];
|
|
24550
|
+
const promptText = event.arguments[0];
|
|
24551
|
+
const state = {
|
|
24552
|
+
activeLlmSpans: /* @__PURE__ */ new Set(),
|
|
24553
|
+
activeToolSpans: /* @__PURE__ */ new Map(),
|
|
24554
|
+
agent,
|
|
24555
|
+
collectedLlmUsageMetrics: false,
|
|
24556
|
+
deferCompletionUntilTurnEnd: options?.streamingBehavior === "followUp" || options?.streamingBehavior === "steer",
|
|
24557
|
+
finalized: false,
|
|
24558
|
+
metadata,
|
|
24559
|
+
metrics: {},
|
|
24560
|
+
onFinalize,
|
|
24561
|
+
promptCallEnded: false,
|
|
24562
|
+
...typeof promptText === "string" ? { promptText } : {},
|
|
24563
|
+
queued: false,
|
|
24564
|
+
span,
|
|
24565
|
+
sawStreamFn: false,
|
|
24566
|
+
startTime: getCurrentUnixTimestamp(),
|
|
24567
|
+
streamPatchState,
|
|
24568
|
+
turnEnded: false
|
|
24569
|
+
};
|
|
24570
|
+
state.restorePromptContext = enterPiPromptContext(state);
|
|
24571
|
+
streamPatchState.activePromptStates.add(state);
|
|
24572
|
+
try {
|
|
24573
|
+
state.unsubscribeAgent = agent.subscribe(async (agentEvent) => {
|
|
24574
|
+
try {
|
|
24575
|
+
await runWithAutoInstrumentationSuppressed(
|
|
24576
|
+
() => handlePiAgentEvent(state, agentEvent)
|
|
24577
|
+
);
|
|
24578
|
+
} catch (error) {
|
|
24579
|
+
logInstrumentationError4("Pi Coding Agent event", error);
|
|
24580
|
+
}
|
|
24581
|
+
});
|
|
24582
|
+
} catch (error) {
|
|
24583
|
+
logInstrumentationError4("Pi Coding Agent event subscription", error);
|
|
24584
|
+
}
|
|
24585
|
+
return state;
|
|
24586
|
+
}
|
|
24587
|
+
function extractSession(event) {
|
|
24588
|
+
const candidate = event.session ?? event.self;
|
|
24589
|
+
return isObject(candidate) && typeof candidate.prompt === "function" ? candidate : void 0;
|
|
24590
|
+
}
|
|
24591
|
+
function isPiAgent(value) {
|
|
24592
|
+
return isObject(value) && typeof value.streamFn === "function" && typeof value.subscribe === "function";
|
|
24593
|
+
}
|
|
24594
|
+
function promptContextStore() {
|
|
24595
|
+
piPromptContextStore ??= isomorph_default.newAsyncLocalStorage();
|
|
24596
|
+
return piPromptContextStore;
|
|
24597
|
+
}
|
|
24598
|
+
function currentPromptContextFrames() {
|
|
24599
|
+
return promptContextStore().getStore()?.frames ?? [];
|
|
24600
|
+
}
|
|
24601
|
+
function currentPiPromptState() {
|
|
24602
|
+
const frames = currentPromptContextFrames();
|
|
24603
|
+
return frames[frames.length - 1]?.state;
|
|
24604
|
+
}
|
|
24605
|
+
function enterPiPromptContext(state) {
|
|
24606
|
+
const frame = {
|
|
24607
|
+
id: /* @__PURE__ */ Symbol("braintrust.pi-coding-agent.prompt"),
|
|
24608
|
+
state
|
|
24609
|
+
};
|
|
24610
|
+
promptContextStore().enterWith({
|
|
24611
|
+
frames: [...currentPromptContextFrames(), frame]
|
|
24612
|
+
});
|
|
24613
|
+
return () => {
|
|
24614
|
+
const frames = currentPromptContextFrames().filter(
|
|
24615
|
+
(candidate) => candidate.id !== frame.id
|
|
24616
|
+
);
|
|
24617
|
+
promptContextStore().enterWith(frames.length > 0 ? { frames } : void 0);
|
|
24618
|
+
};
|
|
24619
|
+
}
|
|
24620
|
+
function installPiStreamPatch(agent) {
|
|
24621
|
+
const existing = piStreamPatchStates.get(agent);
|
|
24622
|
+
if (existing) {
|
|
24623
|
+
if (agent.streamFn !== existing.wrappedStreamFn) {
|
|
24624
|
+
debugLogger.debug(
|
|
24625
|
+
"Pi Coding Agent streamFn changed while Braintrust instrumentation was active; preserving existing patch state."
|
|
24626
|
+
);
|
|
24627
|
+
}
|
|
24628
|
+
return existing;
|
|
24629
|
+
}
|
|
24630
|
+
const patchState = {
|
|
24631
|
+
activePromptStates: /* @__PURE__ */ new Set(),
|
|
24632
|
+
agent,
|
|
24633
|
+
originalStreamFn: agent.streamFn,
|
|
24634
|
+
queuedPromptStates: [],
|
|
24635
|
+
wrappedStreamFn: agent.streamFn
|
|
24636
|
+
};
|
|
24637
|
+
patchState.wrappedStreamFn = makeSharedInstrumentedStreamFn(patchState);
|
|
24638
|
+
agent.streamFn = patchState.wrappedStreamFn;
|
|
24639
|
+
piStreamPatchStates.set(agent, patchState);
|
|
24640
|
+
return patchState;
|
|
24641
|
+
}
|
|
24642
|
+
function resolveStreamPromptState(patchState, context) {
|
|
24643
|
+
let lastUserText;
|
|
24644
|
+
if (Array.isArray(context.messages)) {
|
|
24645
|
+
for (let i = context.messages.length - 1; i >= 0; i--) {
|
|
24646
|
+
const message = context.messages[i];
|
|
24647
|
+
if (isPiUserMessage(message)) {
|
|
24648
|
+
if (typeof message.content === "string") {
|
|
24649
|
+
lastUserText = message.content;
|
|
24650
|
+
} else {
|
|
24651
|
+
lastUserText = message.content.flatMap((part) => part.type === "text" ? [part.text] : []).join("");
|
|
24652
|
+
}
|
|
24653
|
+
break;
|
|
24654
|
+
}
|
|
24655
|
+
}
|
|
24656
|
+
}
|
|
24657
|
+
if (lastUserText !== void 0) {
|
|
24658
|
+
const queuedMatch = patchState.queuedPromptStates.find(
|
|
24659
|
+
(state) => state.promptText === lastUserText
|
|
24660
|
+
);
|
|
24661
|
+
if (queuedMatch) {
|
|
24662
|
+
return queuedMatch;
|
|
24663
|
+
}
|
|
24664
|
+
const matches = [...patchState.activePromptStates].filter(
|
|
24665
|
+
(state) => state.promptText === lastUserText
|
|
24666
|
+
);
|
|
24667
|
+
if (matches.length === 1) {
|
|
24668
|
+
return matches[0];
|
|
24669
|
+
}
|
|
24670
|
+
}
|
|
24671
|
+
const contextState = currentPiPromptState();
|
|
24672
|
+
if (contextState && patchState.activePromptStates.has(contextState) && (!contextState.queued || lastUserText !== void 0 && contextState.promptText === lastUserText)) {
|
|
24673
|
+
return contextState;
|
|
24674
|
+
}
|
|
24675
|
+
if (patchState.activePromptStates.size === 1) {
|
|
24676
|
+
return [...patchState.activePromptStates][0];
|
|
24677
|
+
}
|
|
24678
|
+
return void 0;
|
|
24679
|
+
}
|
|
24680
|
+
function makeSharedInstrumentedStreamFn(patchState) {
|
|
24681
|
+
return async function instrumentedPiStreamFn(model, context, options) {
|
|
24682
|
+
const state = resolveStreamPromptState(patchState, context);
|
|
24683
|
+
if (!state) {
|
|
24684
|
+
const invokeOriginal = () => Reflect.apply(patchState.originalStreamFn, this, [
|
|
24685
|
+
model,
|
|
24686
|
+
context,
|
|
24687
|
+
options
|
|
24688
|
+
]);
|
|
24689
|
+
return patchState.activePromptStates.size > 0 ? runWithAutoInstrumentationSuppressed(invokeOriginal) : invokeOriginal();
|
|
24690
|
+
}
|
|
24691
|
+
state.sawStreamFn = true;
|
|
24692
|
+
removeQueuedPromptState(state);
|
|
24693
|
+
state.streamPatchState.eventPromptState = state;
|
|
24694
|
+
const llmState = await startPiLlmSpan(state, model, context, options);
|
|
24695
|
+
try {
|
|
24696
|
+
const stream = await runWithAutoInstrumentationSuppressed(
|
|
24697
|
+
() => Reflect.apply(patchState.originalStreamFn, this, [
|
|
24698
|
+
model,
|
|
24699
|
+
context,
|
|
24700
|
+
options
|
|
24701
|
+
])
|
|
24702
|
+
);
|
|
24703
|
+
return patchAssistantMessageStream(stream, state, llmState);
|
|
24704
|
+
} catch (error) {
|
|
24705
|
+
finishPiLlmSpan(state, llmState, void 0, error);
|
|
24706
|
+
throw error;
|
|
24707
|
+
}
|
|
24708
|
+
};
|
|
24709
|
+
}
|
|
24710
|
+
async function startPiLlmSpan(state, model, context, options) {
|
|
24711
|
+
const metadata = {
|
|
24712
|
+
...extractModelMetadata2(model),
|
|
24713
|
+
...extractStreamOptionsMetadata(options),
|
|
24714
|
+
...extractToolMetadata(context.tools),
|
|
24715
|
+
"pi_coding_agent.operation": "agent.streamFn"
|
|
24716
|
+
};
|
|
24717
|
+
const span = startSpan({
|
|
24718
|
+
event: {
|
|
24719
|
+
input: processInputAttachments(normalizePiContextInput(context)),
|
|
24720
|
+
metadata
|
|
24721
|
+
},
|
|
24722
|
+
name: getLlmSpanName(model),
|
|
24723
|
+
parent: await state.span.export(),
|
|
24724
|
+
spanAttributes: { type: "llm" /* LLM */ }
|
|
24725
|
+
});
|
|
24726
|
+
const llmState = {
|
|
24727
|
+
finalized: false,
|
|
24728
|
+
metadata,
|
|
24729
|
+
metrics: {},
|
|
24730
|
+
span,
|
|
24731
|
+
startTime: getCurrentUnixTimestamp()
|
|
24732
|
+
};
|
|
24733
|
+
state.activeLlmSpans.add(llmState);
|
|
24734
|
+
return llmState;
|
|
24735
|
+
}
|
|
24736
|
+
function patchAssistantMessageStream(stream, promptState, llmState) {
|
|
24737
|
+
if (!isObject(stream)) {
|
|
24738
|
+
return stream;
|
|
24739
|
+
}
|
|
24740
|
+
const streamRecord = stream;
|
|
24741
|
+
const originalResult = stream.result;
|
|
24742
|
+
if (typeof originalResult === "function") {
|
|
24743
|
+
streamRecord.result = function patchedPiResult() {
|
|
24744
|
+
return Promise.resolve(Reflect.apply(originalResult, this, [])).then(
|
|
24745
|
+
(message) => {
|
|
24746
|
+
finishPiLlmSpan(promptState, llmState, message);
|
|
24747
|
+
return message;
|
|
24748
|
+
},
|
|
24749
|
+
(error) => {
|
|
24750
|
+
finishPiLlmSpan(promptState, llmState, void 0, error);
|
|
24751
|
+
throw error;
|
|
24752
|
+
}
|
|
24753
|
+
);
|
|
24754
|
+
};
|
|
24755
|
+
}
|
|
24756
|
+
const originalIterator = stream[Symbol.asyncIterator];
|
|
24757
|
+
if (typeof originalIterator === "function") {
|
|
24758
|
+
streamRecord[Symbol.asyncIterator] = function patchedPiIterator() {
|
|
24759
|
+
const iterator = Reflect.apply(
|
|
24760
|
+
originalIterator,
|
|
24761
|
+
this,
|
|
24762
|
+
[]
|
|
24763
|
+
);
|
|
24764
|
+
return {
|
|
24765
|
+
async next() {
|
|
24766
|
+
try {
|
|
24767
|
+
const result = await iterator.next();
|
|
24768
|
+
if (result.done) {
|
|
24769
|
+
finishPiLlmSpan(promptState, llmState);
|
|
24770
|
+
return result;
|
|
24771
|
+
}
|
|
24772
|
+
recordPiAssistantMessageEvent(promptState, llmState, result.value);
|
|
24773
|
+
return result;
|
|
24774
|
+
} catch (error) {
|
|
24775
|
+
finishPiLlmSpan(promptState, llmState, void 0, error);
|
|
24776
|
+
if (typeof iterator.return === "function") {
|
|
24777
|
+
try {
|
|
24778
|
+
await iterator.return();
|
|
24779
|
+
} catch (cleanupError) {
|
|
24780
|
+
logInstrumentationError4(
|
|
24781
|
+
"Pi Coding Agent stream cleanup",
|
|
24782
|
+
cleanupError
|
|
24783
|
+
);
|
|
24784
|
+
}
|
|
24785
|
+
}
|
|
24786
|
+
throw error;
|
|
24787
|
+
}
|
|
24788
|
+
},
|
|
24789
|
+
async return(value) {
|
|
24790
|
+
try {
|
|
24791
|
+
if (typeof iterator.return === "function") {
|
|
24792
|
+
return await iterator.return(value);
|
|
24793
|
+
}
|
|
24794
|
+
return {
|
|
24795
|
+
done: true,
|
|
24796
|
+
value
|
|
24797
|
+
};
|
|
24798
|
+
} catch (error) {
|
|
24799
|
+
finishPiLlmSpan(promptState, llmState, void 0, error);
|
|
24800
|
+
throw error;
|
|
24801
|
+
} finally {
|
|
24802
|
+
finishPiLlmSpan(promptState, llmState);
|
|
24803
|
+
}
|
|
24804
|
+
},
|
|
24805
|
+
async throw(error) {
|
|
24806
|
+
try {
|
|
24807
|
+
if (typeof iterator.throw === "function") {
|
|
24808
|
+
return await iterator.throw(error);
|
|
24809
|
+
}
|
|
24810
|
+
throw error;
|
|
24811
|
+
} catch (thrownError) {
|
|
24812
|
+
finishPiLlmSpan(promptState, llmState, void 0, thrownError);
|
|
24813
|
+
throw thrownError;
|
|
24814
|
+
}
|
|
24815
|
+
},
|
|
24816
|
+
[Symbol.asyncIterator]() {
|
|
24817
|
+
return this;
|
|
24818
|
+
}
|
|
24819
|
+
};
|
|
24820
|
+
};
|
|
24821
|
+
}
|
|
24822
|
+
return stream;
|
|
24823
|
+
}
|
|
24824
|
+
function recordPiAssistantMessageEvent(promptState, llmState, event) {
|
|
24825
|
+
recordFirstTokenMetric(llmState, event);
|
|
24826
|
+
const message = "message" in event ? event.message : void 0;
|
|
24827
|
+
const errorMessage2 = "error" in event ? event.error : void 0;
|
|
24828
|
+
if (event.type === "done" && isPiAssistantMessage(message)) {
|
|
24829
|
+
finishPiLlmSpan(promptState, llmState, message);
|
|
24830
|
+
} else if (event.type === "error" && isPiAssistantMessage(errorMessage2)) {
|
|
24831
|
+
finishPiLlmSpan(promptState, llmState, errorMessage2);
|
|
24832
|
+
}
|
|
24833
|
+
}
|
|
24834
|
+
function recordFirstTokenMetric(state, event) {
|
|
24835
|
+
if (state.metrics.time_to_first_token !== void 0 || event.type === "start") {
|
|
24836
|
+
return;
|
|
24837
|
+
}
|
|
24838
|
+
state.metrics.time_to_first_token = getCurrentUnixTimestamp() - state.startTime;
|
|
24839
|
+
}
|
|
24840
|
+
async function handlePiAgentEvent(state, event) {
|
|
24841
|
+
if (state.finalized) {
|
|
24842
|
+
return;
|
|
24843
|
+
}
|
|
24844
|
+
const eventPromptState = state.streamPatchState.eventPromptState;
|
|
24845
|
+
if (eventPromptState && eventPromptState !== state) {
|
|
24846
|
+
return;
|
|
24847
|
+
}
|
|
24848
|
+
if (!eventPromptState && (state.queued || state.streamPatchState.activePromptStates.size > 1 && currentPiPromptState() !== state)) {
|
|
24849
|
+
return;
|
|
24850
|
+
}
|
|
24851
|
+
switch (event.type) {
|
|
24852
|
+
case "message_end":
|
|
24853
|
+
if (isPiAssistantMessage(event.message)) {
|
|
24854
|
+
state.output = extractAssistantOutput(event.message);
|
|
24855
|
+
}
|
|
24856
|
+
return;
|
|
24857
|
+
case "turn_end":
|
|
24858
|
+
state.turnEnded = true;
|
|
24859
|
+
if (isPiAssistantMessage(event.message)) {
|
|
24860
|
+
state.output = extractAssistantOutput(event.message);
|
|
24861
|
+
if (!state.collectedLlmUsageMetrics) {
|
|
24862
|
+
addMetrics(state.metrics, extractUsageMetrics2(event.message.usage));
|
|
24863
|
+
}
|
|
24864
|
+
}
|
|
24865
|
+
if (state.streamPatchState.eventPromptState === state) {
|
|
24866
|
+
state.streamPatchState.eventPromptState = void 0;
|
|
24867
|
+
}
|
|
24868
|
+
if (state.promptCallEnded && state.deferCompletionUntilTurnEnd) {
|
|
24869
|
+
await finalizePiPromptRun(state);
|
|
24870
|
+
}
|
|
24871
|
+
return;
|
|
24872
|
+
case "tool_execution_start":
|
|
24873
|
+
await startPiToolSpan(state, event);
|
|
24874
|
+
return;
|
|
24875
|
+
case "tool_execution_end":
|
|
24876
|
+
finishPiToolSpan(state, event);
|
|
24877
|
+
return;
|
|
24878
|
+
default:
|
|
24879
|
+
return;
|
|
24880
|
+
}
|
|
24881
|
+
}
|
|
24882
|
+
async function startPiToolSpan(state, event) {
|
|
24883
|
+
if (!event.toolCallId || state.activeToolSpans.has(event.toolCallId)) {
|
|
24884
|
+
return;
|
|
24885
|
+
}
|
|
24886
|
+
const restoreAutoInstrumentation = enterAutoInstrumentationAllowed();
|
|
24887
|
+
const metadata = {
|
|
24888
|
+
"gen_ai.tool.call.id": event.toolCallId,
|
|
24889
|
+
"gen_ai.tool.name": event.toolName,
|
|
24890
|
+
"pi_coding_agent.tool.name": event.toolName
|
|
24891
|
+
};
|
|
24892
|
+
try {
|
|
24893
|
+
const span = startSpan({
|
|
24894
|
+
event: {
|
|
24895
|
+
input: event.args,
|
|
24896
|
+
metadata
|
|
24897
|
+
},
|
|
24898
|
+
name: event.toolName || "tool",
|
|
24899
|
+
parent: await state.span.export(),
|
|
24900
|
+
spanAttributes: { type: "tool" /* TOOL */ }
|
|
24901
|
+
});
|
|
24902
|
+
state.activeToolSpans.set(event.toolCallId, {
|
|
24903
|
+
restoreAutoInstrumentation,
|
|
24904
|
+
span
|
|
24905
|
+
});
|
|
24906
|
+
} catch (error) {
|
|
24907
|
+
restoreAutoInstrumentation();
|
|
24908
|
+
throw error;
|
|
24909
|
+
}
|
|
24910
|
+
}
|
|
24911
|
+
function finishPiToolSpan(state, event) {
|
|
24912
|
+
const toolState = state.activeToolSpans.get(event.toolCallId);
|
|
24913
|
+
if (!toolState) {
|
|
24914
|
+
return;
|
|
24915
|
+
}
|
|
24916
|
+
state.activeToolSpans.delete(event.toolCallId);
|
|
24917
|
+
const metadata = {
|
|
24918
|
+
"gen_ai.tool.call.id": event.toolCallId,
|
|
24919
|
+
"gen_ai.tool.name": event.toolName,
|
|
24920
|
+
"pi_coding_agent.tool.name": event.toolName,
|
|
24921
|
+
"pi_coding_agent.tool.is_error": event.isError
|
|
24922
|
+
};
|
|
24923
|
+
try {
|
|
24924
|
+
safeLog4(toolState.span, {
|
|
24925
|
+
...event.isError ? { error: stringifyUnknown2(event.result) } : {},
|
|
24926
|
+
metadata,
|
|
24927
|
+
output: event.result
|
|
24928
|
+
});
|
|
24929
|
+
} finally {
|
|
24930
|
+
try {
|
|
24931
|
+
toolState.span.end();
|
|
24932
|
+
} finally {
|
|
24933
|
+
toolState.restoreAutoInstrumentation?.();
|
|
24934
|
+
}
|
|
24935
|
+
}
|
|
24936
|
+
}
|
|
24937
|
+
async function finalizePiPromptRun(state, error) {
|
|
24938
|
+
if (state.finalized) {
|
|
24939
|
+
return;
|
|
24940
|
+
}
|
|
24941
|
+
state.finalized = true;
|
|
24942
|
+
state.onFinalize?.(state);
|
|
24943
|
+
restorePiStreamFn(state);
|
|
24944
|
+
try {
|
|
24945
|
+
state.unsubscribeAgent?.();
|
|
24946
|
+
} catch (unsubscribeError) {
|
|
24947
|
+
logInstrumentationError4("Pi Coding Agent unsubscribe", unsubscribeError);
|
|
24948
|
+
}
|
|
24949
|
+
await finishOpenLlmSpans(state, error);
|
|
24950
|
+
finishOpenToolSpans(state, error);
|
|
24951
|
+
const metadata = {
|
|
24952
|
+
...state.metadata,
|
|
24953
|
+
...extractModelMetadata2(state.agent.state?.model)
|
|
24954
|
+
};
|
|
24955
|
+
try {
|
|
24956
|
+
safeLog4(state.span, {
|
|
24957
|
+
...error ? { error: stringifyUnknown2(error) } : {},
|
|
24958
|
+
metadata,
|
|
24959
|
+
metrics: {
|
|
24960
|
+
...cleanMetrics5(state.metrics),
|
|
24961
|
+
...buildDurationMetrics3(state.startTime)
|
|
24962
|
+
},
|
|
24963
|
+
output: state.output
|
|
24964
|
+
});
|
|
24965
|
+
} finally {
|
|
24966
|
+
state.span.end();
|
|
24967
|
+
}
|
|
24968
|
+
}
|
|
24969
|
+
function restorePiStreamFn(state) {
|
|
24970
|
+
const patchState = state.streamPatchState;
|
|
24971
|
+
patchState.activePromptStates.delete(state);
|
|
24972
|
+
removeQueuedPromptState(state);
|
|
24973
|
+
if (patchState.eventPromptState === state) {
|
|
24974
|
+
patchState.eventPromptState = void 0;
|
|
24975
|
+
}
|
|
24976
|
+
state.restorePromptContext?.();
|
|
24977
|
+
if (patchState.activePromptStates.size > 0) {
|
|
24978
|
+
return;
|
|
24979
|
+
}
|
|
24980
|
+
if (patchState.agent.streamFn === patchState.wrappedStreamFn) {
|
|
24981
|
+
patchState.agent.streamFn = patchState.originalStreamFn;
|
|
24982
|
+
}
|
|
24983
|
+
piStreamPatchStates.delete(patchState.agent);
|
|
24984
|
+
}
|
|
24985
|
+
function removeQueuedPromptState(state) {
|
|
24986
|
+
state.queued = false;
|
|
24987
|
+
const queuedPromptStates = state.streamPatchState.queuedPromptStates;
|
|
24988
|
+
const index = queuedPromptStates.indexOf(state);
|
|
24989
|
+
if (index >= 0) {
|
|
24990
|
+
queuedPromptStates.splice(index, 1);
|
|
24991
|
+
}
|
|
24992
|
+
}
|
|
24993
|
+
async function finishOpenLlmSpans(state, error) {
|
|
24994
|
+
for (const llmState of [...state.activeLlmSpans]) {
|
|
24995
|
+
finishPiLlmSpan(state, llmState, void 0, error);
|
|
24996
|
+
}
|
|
24997
|
+
}
|
|
24998
|
+
function finishPiLlmSpan(promptState, llmState, message, error) {
|
|
24999
|
+
if (llmState.finalized) {
|
|
25000
|
+
return;
|
|
25001
|
+
}
|
|
25002
|
+
llmState.finalized = true;
|
|
25003
|
+
promptState.activeLlmSpans.delete(llmState);
|
|
25004
|
+
const messageError = message?.stopReason === "error" && message.errorMessage;
|
|
25005
|
+
const metrics = {
|
|
25006
|
+
...extractUsageMetrics2(message?.usage),
|
|
25007
|
+
...cleanMetrics5(llmState.metrics),
|
|
25008
|
+
...buildDurationMetrics3(llmState.startTime)
|
|
25009
|
+
};
|
|
25010
|
+
const usageMetrics = extractUsageMetrics2(message?.usage);
|
|
25011
|
+
if (Object.keys(usageMetrics).length > 0) {
|
|
25012
|
+
promptState.collectedLlmUsageMetrics = true;
|
|
25013
|
+
addMetrics(promptState.metrics, usageMetrics);
|
|
25014
|
+
}
|
|
25015
|
+
try {
|
|
25016
|
+
safeLog4(llmState.span, {
|
|
25017
|
+
...error || messageError ? { error: stringifyUnknown2(error ?? messageError) } : {},
|
|
25018
|
+
metadata: {
|
|
25019
|
+
...llmState.metadata,
|
|
25020
|
+
...message ? extractAssistantMetadata(message) : {}
|
|
25021
|
+
},
|
|
25022
|
+
metrics,
|
|
25023
|
+
...message ? { output: extractAssistantOutput(message) } : {}
|
|
25024
|
+
});
|
|
25025
|
+
} finally {
|
|
25026
|
+
llmState.span.end();
|
|
25027
|
+
}
|
|
25028
|
+
}
|
|
25029
|
+
function finishOpenToolSpans(state, error) {
|
|
25030
|
+
for (const [, toolState] of state.activeToolSpans) {
|
|
25031
|
+
try {
|
|
25032
|
+
safeLog4(toolState.span, {
|
|
25033
|
+
error: error ? stringifyUnknown2(error) : "Pi tool did not complete"
|
|
25034
|
+
});
|
|
25035
|
+
toolState.span.end();
|
|
25036
|
+
} finally {
|
|
25037
|
+
toolState.restoreAutoInstrumentation?.();
|
|
25038
|
+
}
|
|
25039
|
+
}
|
|
25040
|
+
state.activeToolSpans.clear();
|
|
25041
|
+
}
|
|
25042
|
+
function normalizePiContextInput(context) {
|
|
25043
|
+
const messages = context.messages.flatMap(
|
|
25044
|
+
(message) => normalizePiMessage(message)
|
|
25045
|
+
);
|
|
25046
|
+
if (context.systemPrompt) {
|
|
25047
|
+
return [{ role: "system", content: context.systemPrompt }, ...messages];
|
|
25048
|
+
}
|
|
25049
|
+
return messages;
|
|
25050
|
+
}
|
|
25051
|
+
function normalizePiMessage(message) {
|
|
25052
|
+
if (isPiUserMessage(message)) {
|
|
25053
|
+
return [
|
|
25054
|
+
{
|
|
25055
|
+
role: "user",
|
|
25056
|
+
content: normalizeUserContent(message.content)
|
|
25057
|
+
}
|
|
25058
|
+
];
|
|
25059
|
+
}
|
|
25060
|
+
if (isPiAssistantMessage(message)) {
|
|
25061
|
+
return [normalizeAssistantMessage(message)];
|
|
25062
|
+
}
|
|
25063
|
+
if (isPiToolResultMessage(message)) {
|
|
25064
|
+
return [normalizeToolResultMessage(message)];
|
|
25065
|
+
}
|
|
25066
|
+
return [];
|
|
25067
|
+
}
|
|
25068
|
+
function normalizeAssistantMessage(message) {
|
|
25069
|
+
const text = message.content.flatMap((part) => part.type === "text" ? [part.text] : []).join("");
|
|
25070
|
+
const thinking = message.content.flatMap(
|
|
25071
|
+
(part) => part.type === "thinking" && !part.redacted ? [part.thinking] : []
|
|
25072
|
+
).join("");
|
|
25073
|
+
const toolCalls = message.content.flatMap(
|
|
25074
|
+
(part) => part.type === "toolCall" ? [normalizeToolCall(part)] : []
|
|
25075
|
+
);
|
|
25076
|
+
return {
|
|
25077
|
+
role: "assistant",
|
|
25078
|
+
content: text || (toolCalls.length > 0 ? null : ""),
|
|
25079
|
+
...thinking ? { reasoning: thinking } : {},
|
|
25080
|
+
...toolCalls.length > 0 ? { tool_calls: toolCalls } : {}
|
|
25081
|
+
};
|
|
25082
|
+
}
|
|
25083
|
+
function normalizeToolResultMessage(message) {
|
|
25084
|
+
return {
|
|
25085
|
+
role: "tool",
|
|
25086
|
+
tool_call_id: message.toolCallId,
|
|
25087
|
+
content: normalizeUserContent(message.content)
|
|
25088
|
+
};
|
|
25089
|
+
}
|
|
25090
|
+
function normalizeUserContent(content) {
|
|
25091
|
+
if (typeof content === "string") {
|
|
25092
|
+
return content;
|
|
25093
|
+
}
|
|
25094
|
+
return content.map((part) => {
|
|
25095
|
+
if (part.type === "text") {
|
|
25096
|
+
return { type: "text", text: part.text };
|
|
25097
|
+
}
|
|
25098
|
+
if (part.type === "image") {
|
|
25099
|
+
return {
|
|
25100
|
+
type: "image_url",
|
|
25101
|
+
image_url: {
|
|
25102
|
+
url: `data:${part.mimeType};base64,${part.data}`
|
|
25103
|
+
}
|
|
25104
|
+
};
|
|
25105
|
+
}
|
|
25106
|
+
return part;
|
|
25107
|
+
});
|
|
25108
|
+
}
|
|
25109
|
+
function normalizeToolCall(toolCall) {
|
|
25110
|
+
return {
|
|
25111
|
+
id: toolCall.id,
|
|
25112
|
+
type: "function",
|
|
25113
|
+
function: {
|
|
25114
|
+
name: toolCall.name,
|
|
25115
|
+
arguments: stringifyArguments(toolCall.arguments)
|
|
25116
|
+
}
|
|
25117
|
+
};
|
|
25118
|
+
}
|
|
25119
|
+
function extractAssistantOutput(message) {
|
|
25120
|
+
return processInputAttachments([
|
|
25121
|
+
{
|
|
25122
|
+
finish_reason: normalizeStopReason(message.stopReason),
|
|
25123
|
+
index: 0,
|
|
25124
|
+
message: normalizeAssistantMessage(message)
|
|
25125
|
+
}
|
|
25126
|
+
]);
|
|
25127
|
+
}
|
|
25128
|
+
function isPiUserMessage(message) {
|
|
25129
|
+
return message.role === "user" && "content" in message;
|
|
25130
|
+
}
|
|
25131
|
+
function isPiAssistantMessage(message) {
|
|
25132
|
+
return isObject(message) && message.role === "assistant" && Array.isArray(message.content);
|
|
25133
|
+
}
|
|
25134
|
+
function isPiToolResultMessage(message) {
|
|
25135
|
+
return message.role === "toolResult" && Array.isArray(message.content);
|
|
25136
|
+
}
|
|
25137
|
+
function normalizeStopReason(reason) {
|
|
25138
|
+
switch (reason) {
|
|
25139
|
+
case "toolUse":
|
|
25140
|
+
return "tool_calls";
|
|
25141
|
+
case "length":
|
|
25142
|
+
case "stop":
|
|
25143
|
+
return reason;
|
|
25144
|
+
default:
|
|
25145
|
+
return reason ?? "stop";
|
|
25146
|
+
}
|
|
25147
|
+
}
|
|
25148
|
+
function extractPromptInput(text, options) {
|
|
25149
|
+
const images = options?.images;
|
|
25150
|
+
if (!images || images.length === 0) {
|
|
25151
|
+
return text;
|
|
25152
|
+
}
|
|
25153
|
+
return processInputAttachments([
|
|
25154
|
+
{
|
|
25155
|
+
role: "user",
|
|
25156
|
+
content: [
|
|
25157
|
+
{ type: "text", text: text ?? "" },
|
|
25158
|
+
...images.map((image) => ({
|
|
25159
|
+
type: "image_url",
|
|
25160
|
+
image_url: {
|
|
25161
|
+
url: `data:${image.mimeType};base64,${image.data}`
|
|
25162
|
+
}
|
|
25163
|
+
}))
|
|
25164
|
+
]
|
|
25165
|
+
}
|
|
25166
|
+
]);
|
|
25167
|
+
}
|
|
25168
|
+
function extractToolMetadata(tools) {
|
|
25169
|
+
if (!tools || tools.length === 0) {
|
|
25170
|
+
return {};
|
|
25171
|
+
}
|
|
25172
|
+
return {
|
|
25173
|
+
tools: tools.map((tool) => ({
|
|
25174
|
+
type: "function",
|
|
25175
|
+
function: {
|
|
25176
|
+
name: tool.name,
|
|
25177
|
+
...tool.description ? { description: tool.description } : {},
|
|
25178
|
+
...tool.parameters ? { parameters: tool.parameters } : {}
|
|
25179
|
+
}
|
|
25180
|
+
}))
|
|
25181
|
+
};
|
|
25182
|
+
}
|
|
25183
|
+
function extractModelMetadata2(model) {
|
|
25184
|
+
if (!model) {
|
|
25185
|
+
return {};
|
|
25186
|
+
}
|
|
25187
|
+
return {
|
|
25188
|
+
...model.provider ? { provider: model.provider } : {},
|
|
25189
|
+
...model.id ? { model: model.id, "pi_coding_agent.model": model.id } : {},
|
|
25190
|
+
...model.api ? { "pi_coding_agent.api": model.api } : {},
|
|
25191
|
+
...model.name ? { "pi_coding_agent.model_name": model.name } : {}
|
|
25192
|
+
};
|
|
25193
|
+
}
|
|
25194
|
+
function extractAssistantMetadata(message) {
|
|
25195
|
+
return {
|
|
25196
|
+
...message.provider ? { provider: message.provider } : {},
|
|
25197
|
+
...message.responseModel || message.model ? { model: message.responseModel ?? message.model } : {},
|
|
25198
|
+
...message.api ? { "pi_coding_agent.api": message.api } : {},
|
|
25199
|
+
...message.model ? { "pi_coding_agent.model": message.model } : {},
|
|
25200
|
+
...message.responseModel ? { "pi_coding_agent.response_model": message.responseModel } : {},
|
|
25201
|
+
...message.responseId ? { "pi_coding_agent.response_id": message.responseId } : {},
|
|
25202
|
+
...message.stopReason ? { "pi_coding_agent.stop_reason": message.stopReason } : {}
|
|
25203
|
+
};
|
|
25204
|
+
}
|
|
25205
|
+
function extractSessionMetadata(session) {
|
|
25206
|
+
return {
|
|
25207
|
+
...extractModelMetadata2(session.model),
|
|
25208
|
+
...session.sessionId ? { "pi_coding_agent.session_id": session.sessionId } : {},
|
|
25209
|
+
...session.sessionName ? { "pi_coding_agent.session_name": session.sessionName } : {},
|
|
25210
|
+
...session.thinkingLevel ? { "pi_coding_agent.thinking_level": session.thinkingLevel } : {},
|
|
25211
|
+
...typeof session.getActiveToolNames === "function" ? { "pi_coding_agent.active_tools": session.getActiveToolNames() } : {}
|
|
25212
|
+
};
|
|
25213
|
+
}
|
|
25214
|
+
function extractPromptOptionsMetadata(options) {
|
|
25215
|
+
if (!options) {
|
|
25216
|
+
return {};
|
|
25217
|
+
}
|
|
25218
|
+
return {
|
|
25219
|
+
...options.source ? { "pi_coding_agent.source": options.source } : {},
|
|
25220
|
+
...options.streamingBehavior ? { "pi_coding_agent.streaming_behavior": options.streamingBehavior } : {},
|
|
25221
|
+
...options.expandPromptTemplates !== void 0 ? {
|
|
25222
|
+
"pi_coding_agent.expand_prompt_templates": options.expandPromptTemplates
|
|
25223
|
+
} : {}
|
|
25224
|
+
};
|
|
25225
|
+
}
|
|
25226
|
+
function extractStreamOptionsMetadata(options) {
|
|
25227
|
+
if (!options) {
|
|
25228
|
+
return {};
|
|
25229
|
+
}
|
|
25230
|
+
return {
|
|
25231
|
+
...options.temperature !== void 0 ? { temperature: options.temperature } : {},
|
|
25232
|
+
...options.maxTokens !== void 0 ? { max_tokens: options.maxTokens } : {},
|
|
25233
|
+
...options.reasoning ? { "pi_coding_agent.reasoning": options.reasoning } : {},
|
|
25234
|
+
...options.transport ? { "pi_coding_agent.transport": options.transport } : {},
|
|
25235
|
+
...options.cacheRetention ? { "pi_coding_agent.cache_retention": options.cacheRetention } : {},
|
|
25236
|
+
...options.sessionId ? { "pi_coding_agent.session_id": options.sessionId } : {},
|
|
25237
|
+
...options.timeoutMs !== void 0 ? { "pi_coding_agent.timeout_ms": options.timeoutMs } : {},
|
|
25238
|
+
...options.maxRetries !== void 0 ? { "pi_coding_agent.max_retries": options.maxRetries } : {},
|
|
25239
|
+
...options.maxRetryDelayMs !== void 0 ? { "pi_coding_agent.max_retry_delay_ms": options.maxRetryDelayMs } : {},
|
|
25240
|
+
...options.metadata ? { "pi_coding_agent.metadata": options.metadata } : {}
|
|
25241
|
+
};
|
|
25242
|
+
}
|
|
25243
|
+
function getLlmSpanName(model) {
|
|
25244
|
+
switch (model.api) {
|
|
25245
|
+
case "anthropic-messages":
|
|
25246
|
+
return "anthropic.messages.create";
|
|
25247
|
+
case "openai-completions":
|
|
25248
|
+
return "Chat Completion";
|
|
25249
|
+
case "openai-responses":
|
|
25250
|
+
case "azure-openai-responses":
|
|
25251
|
+
case "openai-codex-responses":
|
|
25252
|
+
return "openai.responses.create";
|
|
25253
|
+
case "google-generative-ai":
|
|
25254
|
+
case "google-vertex":
|
|
25255
|
+
return "generate_content";
|
|
25256
|
+
case "mistral-conversations":
|
|
25257
|
+
return "mistral.chat.stream";
|
|
25258
|
+
case "bedrock-converse-stream":
|
|
25259
|
+
return "bedrock.converse_stream";
|
|
25260
|
+
default:
|
|
25261
|
+
return "pi_ai.streamSimple";
|
|
25262
|
+
}
|
|
25263
|
+
}
|
|
25264
|
+
function extractUsageMetrics2(usage) {
|
|
25265
|
+
if (!usage) {
|
|
25266
|
+
return {};
|
|
25267
|
+
}
|
|
25268
|
+
return cleanMetrics5({
|
|
25269
|
+
completion_tokens: usage.output,
|
|
25270
|
+
prompt_cache_creation_tokens: usage.cacheWrite,
|
|
25271
|
+
prompt_cached_tokens: usage.cacheRead,
|
|
25272
|
+
prompt_tokens: usage.input,
|
|
25273
|
+
tokens: usage.totalTokens ?? usage.tokens
|
|
25274
|
+
});
|
|
25275
|
+
}
|
|
25276
|
+
function addMetrics(target, source) {
|
|
25277
|
+
for (const [key, value] of Object.entries(source)) {
|
|
25278
|
+
target[key] = (target[key] ?? 0) + value;
|
|
25279
|
+
}
|
|
25280
|
+
}
|
|
25281
|
+
function buildDurationMetrics3(startTime) {
|
|
25282
|
+
const end = getCurrentUnixTimestamp();
|
|
25283
|
+
return {
|
|
25284
|
+
duration: end - startTime,
|
|
25285
|
+
end,
|
|
25286
|
+
start: startTime
|
|
25287
|
+
};
|
|
25288
|
+
}
|
|
25289
|
+
function cleanMetrics5(metrics) {
|
|
25290
|
+
const cleaned = {};
|
|
25291
|
+
for (const [key, value] of Object.entries(metrics)) {
|
|
25292
|
+
if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
|
|
25293
|
+
cleaned[key] = value;
|
|
25294
|
+
}
|
|
25295
|
+
}
|
|
25296
|
+
return cleaned;
|
|
25297
|
+
}
|
|
25298
|
+
function stringifyArguments(value) {
|
|
25299
|
+
if (typeof value === "string") {
|
|
25300
|
+
return value;
|
|
25301
|
+
}
|
|
25302
|
+
try {
|
|
25303
|
+
return JSON.stringify(value);
|
|
25304
|
+
} catch {
|
|
25305
|
+
return stringifyUnknown2(value);
|
|
25306
|
+
}
|
|
25307
|
+
}
|
|
25308
|
+
function stringifyUnknown2(value) {
|
|
25309
|
+
if (value instanceof Error) {
|
|
25310
|
+
return value.message;
|
|
25311
|
+
}
|
|
25312
|
+
if (typeof value === "string") {
|
|
25313
|
+
return value;
|
|
25314
|
+
}
|
|
25315
|
+
try {
|
|
25316
|
+
return JSON.stringify(value);
|
|
25317
|
+
} catch {
|
|
25318
|
+
return String(value);
|
|
25319
|
+
}
|
|
25320
|
+
}
|
|
25321
|
+
function safeLog4(span, event) {
|
|
25322
|
+
try {
|
|
25323
|
+
span.log(event);
|
|
25324
|
+
} catch (error) {
|
|
25325
|
+
logInstrumentationError4("Pi Coding Agent span log", error);
|
|
25326
|
+
}
|
|
25327
|
+
}
|
|
25328
|
+
function logInstrumentationError4(context, error) {
|
|
25329
|
+
debugLogger.debug(`${context}:`, error);
|
|
25330
|
+
}
|
|
25331
|
+
|
|
23281
25332
|
// src/instrumentation/braintrust-plugin.ts
|
|
23282
25333
|
function getIntegrationConfig(integrations, key) {
|
|
23283
25334
|
return integrations[key];
|
|
@@ -23303,6 +25354,7 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
23303
25354
|
gitHubCopilotPlugin = null;
|
|
23304
25355
|
fluePlugin = null;
|
|
23305
25356
|
langChainPlugin = null;
|
|
25357
|
+
piCodingAgentPlugin = null;
|
|
23306
25358
|
constructor(config = {}) {
|
|
23307
25359
|
super();
|
|
23308
25360
|
this.config = config;
|
|
@@ -23377,6 +25429,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
23377
25429
|
this.gitHubCopilotPlugin = new GitHubCopilotPlugin();
|
|
23378
25430
|
this.gitHubCopilotPlugin.enable();
|
|
23379
25431
|
}
|
|
25432
|
+
if (integrations.piCodingAgent !== false) {
|
|
25433
|
+
this.piCodingAgentPlugin = new PiCodingAgentPlugin();
|
|
25434
|
+
this.piCodingAgentPlugin.enable();
|
|
25435
|
+
}
|
|
23380
25436
|
if (getIntegrationConfig(integrations, "flue") !== false) {
|
|
23381
25437
|
this.fluePlugin = new FluePlugin();
|
|
23382
25438
|
this.fluePlugin.enable();
|
|
@@ -23455,6 +25511,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
23455
25511
|
this.gitHubCopilotPlugin.disable();
|
|
23456
25512
|
this.gitHubCopilotPlugin = null;
|
|
23457
25513
|
}
|
|
25514
|
+
if (this.piCodingAgentPlugin) {
|
|
25515
|
+
this.piCodingAgentPlugin.disable();
|
|
25516
|
+
this.piCodingAgentPlugin = null;
|
|
25517
|
+
}
|
|
23458
25518
|
if (this.fluePlugin) {
|
|
23459
25519
|
this.fluePlugin.disable();
|
|
23460
25520
|
this.fluePlugin = null;
|
|
@@ -23474,6 +25534,11 @@ var envIntegrationAliases = {
|
|
|
23474
25534
|
openaicodexsdk: "openaiCodexSDK",
|
|
23475
25535
|
codex: "openaiCodexSDK",
|
|
23476
25536
|
"codex-sdk": "openaiCodexSDK",
|
|
25537
|
+
"pi-coding-agent": "piCodingAgent",
|
|
25538
|
+
"pi-coding-agent-sdk": "piCodingAgent",
|
|
25539
|
+
picodingagent: "piCodingAgent",
|
|
25540
|
+
picodingagentsdk: "piCodingAgent",
|
|
25541
|
+
"@earendil-works/pi-coding-agent": "piCodingAgent",
|
|
23477
25542
|
anthropic: "anthropic",
|
|
23478
25543
|
aisdk: "aisdk",
|
|
23479
25544
|
"ai-sdk": "aisdk",
|
|
@@ -23539,7 +25604,8 @@ function getDefaultInstrumentationIntegrations() {
|
|
|
23539
25604
|
genkit: true,
|
|
23540
25605
|
gitHubCopilot: true,
|
|
23541
25606
|
langchain: true,
|
|
23542
|
-
langgraph: true
|
|
25607
|
+
langgraph: true,
|
|
25608
|
+
piCodingAgent: true
|
|
23543
25609
|
};
|
|
23544
25610
|
}
|
|
23545
25611
|
function readDisabledInstrumentationEnvConfig(disabledList) {
|