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
|
@@ -7133,6 +7133,10 @@ var Experiment2 = class extends ObjectFetcher {
|
|
|
7133
7133
|
return (await this.lazyMetadata.get()).project;
|
|
7134
7134
|
})();
|
|
7135
7135
|
}
|
|
7136
|
+
async _getBaseExperimentId() {
|
|
7137
|
+
const baseExperimentId = (await this.lazyMetadata.get()).experiment.fullInfo["base_exp_id"];
|
|
7138
|
+
return typeof baseExperimentId === "string" && baseExperimentId ? baseExperimentId : void 0;
|
|
7139
|
+
}
|
|
7136
7140
|
parentObjectType() {
|
|
7137
7141
|
return 1 /* EXPERIMENT */;
|
|
7138
7142
|
}
|
|
@@ -7273,6 +7277,14 @@ var Experiment2 = class extends ObjectFetcher {
|
|
|
7273
7277
|
comparisonExperimentId = baseExperiment.id;
|
|
7274
7278
|
comparisonExperimentName = baseExperiment.name;
|
|
7275
7279
|
}
|
|
7280
|
+
} else {
|
|
7281
|
+
try {
|
|
7282
|
+
const comparisonExperiment = await state.apiConn().get_json(`v1/experiment/${comparisonExperimentId}`);
|
|
7283
|
+
if (typeof comparisonExperiment["name"] === "string") {
|
|
7284
|
+
comparisonExperimentName = comparisonExperiment["name"];
|
|
7285
|
+
}
|
|
7286
|
+
} catch {
|
|
7287
|
+
}
|
|
7276
7288
|
}
|
|
7277
7289
|
try {
|
|
7278
7290
|
const results = await state.apiConn().get_json(
|
|
@@ -8532,6 +8544,64 @@ function isValidChannelName(channelName) {
|
|
|
8532
8544
|
return /^braintrust:[^:]+:.+$/.test(channelName);
|
|
8533
8545
|
}
|
|
8534
8546
|
|
|
8547
|
+
// src/instrumentation/auto-instrumentation-suppression.ts
|
|
8548
|
+
var autoInstrumentationSuppressionStore;
|
|
8549
|
+
function suppressionStore() {
|
|
8550
|
+
autoInstrumentationSuppressionStore ??= isomorph_default.newAsyncLocalStorage();
|
|
8551
|
+
return autoInstrumentationSuppressionStore;
|
|
8552
|
+
}
|
|
8553
|
+
function currentFrames() {
|
|
8554
|
+
return suppressionStore().getStore()?.frames ?? [];
|
|
8555
|
+
}
|
|
8556
|
+
function isAutoInstrumentationSuppressed() {
|
|
8557
|
+
const frames = currentFrames();
|
|
8558
|
+
return frames[frames.length - 1]?.mode === "suppress";
|
|
8559
|
+
}
|
|
8560
|
+
function runWithAutoInstrumentationSuppressed(callback) {
|
|
8561
|
+
const frame = {
|
|
8562
|
+
id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
|
|
8563
|
+
mode: "suppress"
|
|
8564
|
+
};
|
|
8565
|
+
return suppressionStore().run(
|
|
8566
|
+
{ frames: [...currentFrames(), frame] },
|
|
8567
|
+
callback
|
|
8568
|
+
);
|
|
8569
|
+
}
|
|
8570
|
+
function bindAutoInstrumentationSuppressionToStart(tracingChannel) {
|
|
8571
|
+
const startChannel = tracingChannel.start;
|
|
8572
|
+
if (!startChannel) {
|
|
8573
|
+
return void 0;
|
|
8574
|
+
}
|
|
8575
|
+
const store = suppressionStore();
|
|
8576
|
+
startChannel.bindStore(store, () => ({
|
|
8577
|
+
frames: [
|
|
8578
|
+
...currentFrames(),
|
|
8579
|
+
{
|
|
8580
|
+
id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
|
|
8581
|
+
mode: "suppress"
|
|
8582
|
+
}
|
|
8583
|
+
]
|
|
8584
|
+
}));
|
|
8585
|
+
return () => {
|
|
8586
|
+
startChannel.unbindStore(store);
|
|
8587
|
+
};
|
|
8588
|
+
}
|
|
8589
|
+
function enterAutoInstrumentationAllowed() {
|
|
8590
|
+
const frame = {
|
|
8591
|
+
id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-allow"),
|
|
8592
|
+
mode: "allow"
|
|
8593
|
+
};
|
|
8594
|
+
suppressionStore().enterWith({
|
|
8595
|
+
frames: [...currentFrames(), frame]
|
|
8596
|
+
});
|
|
8597
|
+
return () => {
|
|
8598
|
+
const frames = currentFrames().filter(
|
|
8599
|
+
(candidate) => candidate.id !== frame.id
|
|
8600
|
+
);
|
|
8601
|
+
suppressionStore().enterWith(frames.length > 0 ? { frames } : void 0);
|
|
8602
|
+
};
|
|
8603
|
+
}
|
|
8604
|
+
|
|
8535
8605
|
// src/instrumentation/core/channel-tracing.ts
|
|
8536
8606
|
function isSyncStreamLike(value) {
|
|
8537
8607
|
return !!value && typeof value === "object" && typeof value.on === "function";
|
|
@@ -8563,16 +8633,33 @@ function startSpanForEvent(config, event, channelName) {
|
|
|
8563
8633
|
metadata: mergeInputMetadata(metadata, spanInfoMetadata)
|
|
8564
8634
|
});
|
|
8565
8635
|
} catch (error) {
|
|
8566
|
-
|
|
8636
|
+
debugLogger.error(`Error extracting input for ${channelName}:`, error);
|
|
8567
8637
|
}
|
|
8568
8638
|
return { span, startTime };
|
|
8569
8639
|
}
|
|
8640
|
+
function shouldTraceEvent(config, event, channelName) {
|
|
8641
|
+
if (!config.shouldTrace) {
|
|
8642
|
+
return true;
|
|
8643
|
+
}
|
|
8644
|
+
try {
|
|
8645
|
+
return config.shouldTrace(event.arguments, event);
|
|
8646
|
+
} catch (error) {
|
|
8647
|
+
debugLogger.error(
|
|
8648
|
+
`Error checking trace predicate for ${channelName}:`,
|
|
8649
|
+
error
|
|
8650
|
+
);
|
|
8651
|
+
return true;
|
|
8652
|
+
}
|
|
8653
|
+
}
|
|
8570
8654
|
function ensureSpanStateForEvent(states, config, event, channelName) {
|
|
8571
8655
|
const key = event;
|
|
8572
8656
|
const existing = states.get(key);
|
|
8573
8657
|
if (existing) {
|
|
8574
8658
|
return existing;
|
|
8575
8659
|
}
|
|
8660
|
+
if (!shouldTraceEvent(config, event, channelName)) {
|
|
8661
|
+
return void 0;
|
|
8662
|
+
}
|
|
8576
8663
|
const created = startSpanForEvent(config, event, channelName);
|
|
8577
8664
|
states.set(key, created);
|
|
8578
8665
|
return created;
|
|
@@ -8588,13 +8675,16 @@ function bindCurrentSpanStoreToStart(tracingChannel, states, config, channelName
|
|
|
8588
8675
|
startChannel.bindStore(
|
|
8589
8676
|
currentSpanStore,
|
|
8590
8677
|
(event) => {
|
|
8591
|
-
|
|
8678
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
8679
|
+
return currentSpanStore.getStore();
|
|
8680
|
+
}
|
|
8681
|
+
const spanState = ensureSpanStateForEvent(
|
|
8592
8682
|
states,
|
|
8593
8683
|
config,
|
|
8594
8684
|
event,
|
|
8595
8685
|
channelName
|
|
8596
|
-
)
|
|
8597
|
-
return contextManager.wrapSpanForStore(span);
|
|
8686
|
+
);
|
|
8687
|
+
return spanState ? contextManager.wrapSpanForStore(spanState.span) : currentSpanStore.getStore();
|
|
8598
8688
|
}
|
|
8599
8689
|
);
|
|
8600
8690
|
return () => {
|
|
@@ -8629,7 +8719,10 @@ function runStreamingCompletionHook(args) {
|
|
|
8629
8719
|
startTime: args.startTime
|
|
8630
8720
|
});
|
|
8631
8721
|
} catch (error) {
|
|
8632
|
-
|
|
8722
|
+
debugLogger.error(
|
|
8723
|
+
`Error in onComplete hook for ${args.channelName}:`,
|
|
8724
|
+
error
|
|
8725
|
+
);
|
|
8633
8726
|
}
|
|
8634
8727
|
}
|
|
8635
8728
|
function traceAsyncChannel(channel2, config) {
|
|
@@ -8644,6 +8737,9 @@ function traceAsyncChannel(channel2, config) {
|
|
|
8644
8737
|
);
|
|
8645
8738
|
const handlers = {
|
|
8646
8739
|
start: (event) => {
|
|
8740
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
8741
|
+
return;
|
|
8742
|
+
}
|
|
8647
8743
|
ensureSpanStateForEvent(
|
|
8648
8744
|
states,
|
|
8649
8745
|
config,
|
|
@@ -8678,7 +8774,7 @@ function traceAsyncChannel(channel2, config) {
|
|
|
8678
8774
|
metrics
|
|
8679
8775
|
});
|
|
8680
8776
|
} catch (error) {
|
|
8681
|
-
|
|
8777
|
+
debugLogger.error(`Error extracting output for ${channelName}:`, error);
|
|
8682
8778
|
} finally {
|
|
8683
8779
|
span.end();
|
|
8684
8780
|
states.delete(event);
|
|
@@ -8706,6 +8802,9 @@ function traceStreamingChannel(channel2, config) {
|
|
|
8706
8802
|
);
|
|
8707
8803
|
const handlers = {
|
|
8708
8804
|
start: (event) => {
|
|
8805
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
8806
|
+
return;
|
|
8807
|
+
}
|
|
8709
8808
|
ensureSpanStateForEvent(
|
|
8710
8809
|
states,
|
|
8711
8810
|
config,
|
|
@@ -8777,7 +8876,7 @@ function traceStreamingChannel(channel2, config) {
|
|
|
8777
8876
|
metrics
|
|
8778
8877
|
});
|
|
8779
8878
|
} catch (error) {
|
|
8780
|
-
|
|
8879
|
+
debugLogger.error(
|
|
8781
8880
|
`Error extracting output for ${channelName}:`,
|
|
8782
8881
|
error
|
|
8783
8882
|
);
|
|
@@ -8837,7 +8936,7 @@ function traceStreamingChannel(channel2, config) {
|
|
|
8837
8936
|
metrics
|
|
8838
8937
|
});
|
|
8839
8938
|
} catch (error) {
|
|
8840
|
-
|
|
8939
|
+
debugLogger.error(`Error extracting output for ${channelName}:`, error);
|
|
8841
8940
|
} finally {
|
|
8842
8941
|
span.end();
|
|
8843
8942
|
states.delete(event);
|
|
@@ -8865,6 +8964,9 @@ function traceSyncStreamChannel(channel2, config) {
|
|
|
8865
8964
|
);
|
|
8866
8965
|
const handlers = {
|
|
8867
8966
|
start: (event) => {
|
|
8967
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
8968
|
+
return;
|
|
8969
|
+
}
|
|
8868
8970
|
ensureSpanStateForEvent(
|
|
8869
8971
|
states,
|
|
8870
8972
|
config,
|
|
@@ -8918,7 +9020,7 @@ function traceSyncStreamChannel(channel2, config) {
|
|
|
8918
9020
|
});
|
|
8919
9021
|
}
|
|
8920
9022
|
} catch (error) {
|
|
8921
|
-
|
|
9023
|
+
debugLogger.error(
|
|
8922
9024
|
`Error extracting chatCompletion for ${channelName}:`,
|
|
8923
9025
|
error
|
|
8924
9026
|
);
|
|
@@ -8942,7 +9044,10 @@ function traceSyncStreamChannel(channel2, config) {
|
|
|
8942
9044
|
span.log(extracted);
|
|
8943
9045
|
}
|
|
8944
9046
|
} catch (error) {
|
|
8945
|
-
|
|
9047
|
+
debugLogger.error(
|
|
9048
|
+
`Error extracting event for ${channelName}:`,
|
|
9049
|
+
error
|
|
9050
|
+
);
|
|
8946
9051
|
}
|
|
8947
9052
|
});
|
|
8948
9053
|
stream.on("end", () => {
|
|
@@ -10471,6 +10576,9 @@ var AnthropicPlugin = class extends BasePlugin {
|
|
|
10471
10576
|
const states = /* @__PURE__ */ new WeakMap();
|
|
10472
10577
|
const handlers = {
|
|
10473
10578
|
start: (event) => {
|
|
10579
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
10580
|
+
return;
|
|
10581
|
+
}
|
|
10474
10582
|
const params = event.arguments[0] ?? {};
|
|
10475
10583
|
const span = startSpan({
|
|
10476
10584
|
name: "anthropic.beta.messages.toolRunner",
|
|
@@ -11200,6 +11308,520 @@ function serializeAISDKToolsForLogging(tools) {
|
|
|
11200
11308
|
return serialized;
|
|
11201
11309
|
}
|
|
11202
11310
|
|
|
11311
|
+
// src/wrappers/ai-sdk/telemetry.ts
|
|
11312
|
+
function braintrustAISDKTelemetry() {
|
|
11313
|
+
const operations = /* @__PURE__ */ new Map();
|
|
11314
|
+
const modelSpans = /* @__PURE__ */ new Map();
|
|
11315
|
+
const objectSpans = /* @__PURE__ */ new Map();
|
|
11316
|
+
const embedSpans = /* @__PURE__ */ new Map();
|
|
11317
|
+
const rerankSpans = /* @__PURE__ */ new Map();
|
|
11318
|
+
const toolSpans = /* @__PURE__ */ new Map();
|
|
11319
|
+
const runSafely = (name, callback) => {
|
|
11320
|
+
try {
|
|
11321
|
+
callback();
|
|
11322
|
+
} catch (error) {
|
|
11323
|
+
console.error(`Error in Braintrust AI SDK telemetry ${name}:`, error);
|
|
11324
|
+
}
|
|
11325
|
+
};
|
|
11326
|
+
const startChildSpan = (callId, name, type, event) => {
|
|
11327
|
+
const parent = operations.get(callId)?.span;
|
|
11328
|
+
const spanArgs = {
|
|
11329
|
+
name,
|
|
11330
|
+
spanAttributes: { type },
|
|
11331
|
+
...event ? { event } : {}
|
|
11332
|
+
};
|
|
11333
|
+
const span = parent ? parent.startSpan(spanArgs) : startSpan(spanArgs);
|
|
11334
|
+
const state = operations.get(callId);
|
|
11335
|
+
if (state && type === "llm" /* LLM */) {
|
|
11336
|
+
state.hadModelChild = true;
|
|
11337
|
+
}
|
|
11338
|
+
return span;
|
|
11339
|
+
};
|
|
11340
|
+
return {
|
|
11341
|
+
onStart(event) {
|
|
11342
|
+
runSafely("onStart", () => {
|
|
11343
|
+
const operationName = operationNameFromId(event.operationId);
|
|
11344
|
+
const span = startSpan({
|
|
11345
|
+
name: operationName,
|
|
11346
|
+
spanAttributes: { type: "function" /* FUNCTION */ }
|
|
11347
|
+
});
|
|
11348
|
+
operations.set(event.callId, {
|
|
11349
|
+
hadModelChild: false,
|
|
11350
|
+
operationName,
|
|
11351
|
+
span,
|
|
11352
|
+
startTime: getCurrentUnixTimestamp()
|
|
11353
|
+
});
|
|
11354
|
+
const metadata = metadataFromEvent(event);
|
|
11355
|
+
const logPayload = { metadata };
|
|
11356
|
+
if (shouldRecordInputs(event)) {
|
|
11357
|
+
const { input, outputPromise } = processAISDKCallInput(
|
|
11358
|
+
operationInput(event, operationName)
|
|
11359
|
+
);
|
|
11360
|
+
logPayload.input = input;
|
|
11361
|
+
if (outputPromise && input && typeof input === "object") {
|
|
11362
|
+
outputPromise.then((resolvedData) => {
|
|
11363
|
+
span.log({
|
|
11364
|
+
input: {
|
|
11365
|
+
...input,
|
|
11366
|
+
...resolvedData
|
|
11367
|
+
}
|
|
11368
|
+
});
|
|
11369
|
+
}).catch(() => {
|
|
11370
|
+
});
|
|
11371
|
+
}
|
|
11372
|
+
}
|
|
11373
|
+
span.log(logPayload);
|
|
11374
|
+
});
|
|
11375
|
+
},
|
|
11376
|
+
onLanguageModelCallStart(event) {
|
|
11377
|
+
runSafely("onLanguageModelCallStart", () => {
|
|
11378
|
+
const state = operations.get(event.callId);
|
|
11379
|
+
const openSpans = modelSpans.get(event.callId);
|
|
11380
|
+
if (openSpans) {
|
|
11381
|
+
for (const span2 of openSpans) {
|
|
11382
|
+
span2.end();
|
|
11383
|
+
}
|
|
11384
|
+
modelSpans.delete(event.callId);
|
|
11385
|
+
}
|
|
11386
|
+
const span = startChildSpan(
|
|
11387
|
+
event.callId,
|
|
11388
|
+
state?.operationName === "streamText" ? "doStream" : "doGenerate",
|
|
11389
|
+
"llm" /* LLM */,
|
|
11390
|
+
{
|
|
11391
|
+
...shouldRecordInputs(event) ? {
|
|
11392
|
+
input: processAISDKCallInput(
|
|
11393
|
+
operationInput(
|
|
11394
|
+
event,
|
|
11395
|
+
state?.operationName ?? "generateText"
|
|
11396
|
+
)
|
|
11397
|
+
).input
|
|
11398
|
+
} : {},
|
|
11399
|
+
metadata: metadataFromEvent(event)
|
|
11400
|
+
}
|
|
11401
|
+
);
|
|
11402
|
+
const spans = modelSpans.get(event.callId) ?? [];
|
|
11403
|
+
spans.push(span);
|
|
11404
|
+
modelSpans.set(event.callId, spans);
|
|
11405
|
+
});
|
|
11406
|
+
},
|
|
11407
|
+
onLanguageModelCallEnd(event) {
|
|
11408
|
+
runSafely("onLanguageModelCallEnd", () => {
|
|
11409
|
+
const span = shiftModelSpan(modelSpans, event.callId);
|
|
11410
|
+
if (!span) {
|
|
11411
|
+
return;
|
|
11412
|
+
}
|
|
11413
|
+
const result = {
|
|
11414
|
+
...event,
|
|
11415
|
+
response: event.responseId ? { id: event.responseId } : void 0
|
|
11416
|
+
};
|
|
11417
|
+
span.log({
|
|
11418
|
+
...shouldRecordOutputs(event) ? {
|
|
11419
|
+
output: processAISDKOutput(result, DEFAULT_DENY_OUTPUT_PATHS)
|
|
11420
|
+
} : {},
|
|
11421
|
+
metrics: extractTokenMetrics(result)
|
|
11422
|
+
});
|
|
11423
|
+
span.end();
|
|
11424
|
+
});
|
|
11425
|
+
},
|
|
11426
|
+
onObjectStepStart(event) {
|
|
11427
|
+
runSafely("onObjectStepStart", () => {
|
|
11428
|
+
const state = operations.get(event.callId);
|
|
11429
|
+
const openSpan = objectSpans.get(event.callId);
|
|
11430
|
+
if (openSpan) {
|
|
11431
|
+
openSpan.end();
|
|
11432
|
+
objectSpans.delete(event.callId);
|
|
11433
|
+
}
|
|
11434
|
+
const span = startChildSpan(
|
|
11435
|
+
event.callId,
|
|
11436
|
+
state?.operationName === "streamObject" ? "doStream" : "doGenerate",
|
|
11437
|
+
"llm" /* LLM */,
|
|
11438
|
+
{
|
|
11439
|
+
...shouldRecordInputs(event) ? {
|
|
11440
|
+
input: {
|
|
11441
|
+
prompt: event.promptMessages
|
|
11442
|
+
}
|
|
11443
|
+
} : {},
|
|
11444
|
+
metadata: metadataFromEvent(event)
|
|
11445
|
+
}
|
|
11446
|
+
);
|
|
11447
|
+
objectSpans.set(event.callId, span);
|
|
11448
|
+
});
|
|
11449
|
+
},
|
|
11450
|
+
onObjectStepFinish(event) {
|
|
11451
|
+
runSafely("onObjectStepFinish", () => {
|
|
11452
|
+
const span = objectSpans.get(event.callId);
|
|
11453
|
+
if (!span) {
|
|
11454
|
+
return;
|
|
11455
|
+
}
|
|
11456
|
+
const result = {
|
|
11457
|
+
...event,
|
|
11458
|
+
text: event.objectText
|
|
11459
|
+
};
|
|
11460
|
+
span.log({
|
|
11461
|
+
...shouldRecordOutputs(event) ? {
|
|
11462
|
+
output: processAISDKOutput(result, DEFAULT_DENY_OUTPUT_PATHS)
|
|
11463
|
+
} : {},
|
|
11464
|
+
metrics: extractTokenMetrics(result)
|
|
11465
|
+
});
|
|
11466
|
+
span.end();
|
|
11467
|
+
objectSpans.delete(event.callId);
|
|
11468
|
+
});
|
|
11469
|
+
},
|
|
11470
|
+
onEmbedStart(event) {
|
|
11471
|
+
runSafely("onEmbedStart", () => {
|
|
11472
|
+
const state = operations.get(event.callId);
|
|
11473
|
+
for (const [embedCallId, embedState] of embedSpans) {
|
|
11474
|
+
if (embedState.callId === event.callId && (state?.operationName === "embed" || embedState.values === event.values)) {
|
|
11475
|
+
embedState.span.end();
|
|
11476
|
+
embedSpans.delete(embedCallId);
|
|
11477
|
+
}
|
|
11478
|
+
}
|
|
11479
|
+
const span = startChildSpan(
|
|
11480
|
+
event.callId,
|
|
11481
|
+
"doEmbed",
|
|
11482
|
+
"llm" /* LLM */,
|
|
11483
|
+
{
|
|
11484
|
+
...shouldRecordInputs(event) ? {
|
|
11485
|
+
input: {
|
|
11486
|
+
values: event.values
|
|
11487
|
+
}
|
|
11488
|
+
} : {},
|
|
11489
|
+
metadata: metadataFromEvent(event)
|
|
11490
|
+
}
|
|
11491
|
+
);
|
|
11492
|
+
embedSpans.set(event.embedCallId, {
|
|
11493
|
+
callId: event.callId,
|
|
11494
|
+
span,
|
|
11495
|
+
values: event.values
|
|
11496
|
+
});
|
|
11497
|
+
});
|
|
11498
|
+
},
|
|
11499
|
+
onEmbedFinish(event) {
|
|
11500
|
+
runSafely("onEmbedFinish", () => {
|
|
11501
|
+
const state = embedSpans.get(event.embedCallId);
|
|
11502
|
+
if (!state) {
|
|
11503
|
+
return;
|
|
11504
|
+
}
|
|
11505
|
+
const result = {
|
|
11506
|
+
...event,
|
|
11507
|
+
embeddings: event.embeddings
|
|
11508
|
+
};
|
|
11509
|
+
state.span.log({
|
|
11510
|
+
...shouldRecordOutputs(event) ? {
|
|
11511
|
+
output: processAISDKEmbeddingOutput(
|
|
11512
|
+
result,
|
|
11513
|
+
DEFAULT_DENY_OUTPUT_PATHS
|
|
11514
|
+
)
|
|
11515
|
+
} : {},
|
|
11516
|
+
metrics: extractTokenMetrics(result)
|
|
11517
|
+
});
|
|
11518
|
+
state.span.end();
|
|
11519
|
+
embedSpans.delete(event.embedCallId);
|
|
11520
|
+
});
|
|
11521
|
+
},
|
|
11522
|
+
onRerankStart(event) {
|
|
11523
|
+
runSafely("onRerankStart", () => {
|
|
11524
|
+
const openSpan = rerankSpans.get(event.callId);
|
|
11525
|
+
if (openSpan) {
|
|
11526
|
+
openSpan.end();
|
|
11527
|
+
rerankSpans.delete(event.callId);
|
|
11528
|
+
}
|
|
11529
|
+
const span = startChildSpan(
|
|
11530
|
+
event.callId,
|
|
11531
|
+
"doRerank",
|
|
11532
|
+
"llm" /* LLM */,
|
|
11533
|
+
{
|
|
11534
|
+
...shouldRecordInputs(event) ? {
|
|
11535
|
+
input: {
|
|
11536
|
+
documents: event.documents,
|
|
11537
|
+
query: event.query,
|
|
11538
|
+
topN: event.topN
|
|
11539
|
+
}
|
|
11540
|
+
} : {},
|
|
11541
|
+
metadata: metadataFromEvent(event)
|
|
11542
|
+
}
|
|
11543
|
+
);
|
|
11544
|
+
rerankSpans.set(event.callId, span);
|
|
11545
|
+
});
|
|
11546
|
+
},
|
|
11547
|
+
onRerankFinish(event) {
|
|
11548
|
+
runSafely("onRerankFinish", () => {
|
|
11549
|
+
const span = rerankSpans.get(event.callId);
|
|
11550
|
+
if (!span) {
|
|
11551
|
+
return;
|
|
11552
|
+
}
|
|
11553
|
+
const result = {
|
|
11554
|
+
ranking: event.ranking?.map((entry) => ({
|
|
11555
|
+
originalIndex: entry.index,
|
|
11556
|
+
score: entry.relevanceScore
|
|
11557
|
+
}))
|
|
11558
|
+
};
|
|
11559
|
+
span.log({
|
|
11560
|
+
...shouldRecordOutputs(event) ? {
|
|
11561
|
+
output: processAISDKRerankOutput(
|
|
11562
|
+
result,
|
|
11563
|
+
DEFAULT_DENY_OUTPUT_PATHS
|
|
11564
|
+
)
|
|
11565
|
+
} : {}
|
|
11566
|
+
});
|
|
11567
|
+
span.end();
|
|
11568
|
+
rerankSpans.delete(event.callId);
|
|
11569
|
+
});
|
|
11570
|
+
},
|
|
11571
|
+
onToolExecutionStart(event) {
|
|
11572
|
+
runSafely("onToolExecutionStart", () => {
|
|
11573
|
+
const toolCallId = event.toolCall.toolCallId;
|
|
11574
|
+
if (!toolCallId) {
|
|
11575
|
+
return;
|
|
11576
|
+
}
|
|
11577
|
+
const span = startChildSpan(
|
|
11578
|
+
event.callId,
|
|
11579
|
+
event.toolCall.toolName || "tool",
|
|
11580
|
+
"tool" /* TOOL */,
|
|
11581
|
+
{
|
|
11582
|
+
...shouldRecordInputs(event) ? {
|
|
11583
|
+
input: event.toolCall.input
|
|
11584
|
+
} : {},
|
|
11585
|
+
metadata: {
|
|
11586
|
+
...createAISDKIntegrationMetadata(),
|
|
11587
|
+
toolCallId,
|
|
11588
|
+
...typeof event.toolCall.toolName === "string" ? { toolName: event.toolCall.toolName } : {}
|
|
11589
|
+
}
|
|
11590
|
+
}
|
|
11591
|
+
);
|
|
11592
|
+
toolSpans.set(toolCallId, { callId: event.callId, span });
|
|
11593
|
+
});
|
|
11594
|
+
},
|
|
11595
|
+
onToolExecutionEnd(event) {
|
|
11596
|
+
runSafely("onToolExecutionEnd", () => {
|
|
11597
|
+
const toolCallId = event.toolCall.toolCallId;
|
|
11598
|
+
const state = toolCallId ? toolSpans.get(toolCallId) : void 0;
|
|
11599
|
+
if (!toolCallId || !state) {
|
|
11600
|
+
return;
|
|
11601
|
+
}
|
|
11602
|
+
const toolOutput = event.toolOutput;
|
|
11603
|
+
if (toolOutput?.type === "tool-error") {
|
|
11604
|
+
state.span.log({
|
|
11605
|
+
error: toolOutput.error instanceof Error ? toolOutput.error.message : String(toolOutput?.error),
|
|
11606
|
+
metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } : {}
|
|
11607
|
+
});
|
|
11608
|
+
} else {
|
|
11609
|
+
state.span.log({
|
|
11610
|
+
...shouldRecordOutputs(event) ? { output: toolOutput?.output } : {},
|
|
11611
|
+
metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } : {}
|
|
11612
|
+
});
|
|
11613
|
+
}
|
|
11614
|
+
state.span.end();
|
|
11615
|
+
toolSpans.delete(toolCallId);
|
|
11616
|
+
});
|
|
11617
|
+
},
|
|
11618
|
+
onChunk(event) {
|
|
11619
|
+
runSafely("onChunk", () => {
|
|
11620
|
+
const callId = event.chunk?.callId;
|
|
11621
|
+
if (!callId) {
|
|
11622
|
+
return;
|
|
11623
|
+
}
|
|
11624
|
+
const state = operations.get(callId);
|
|
11625
|
+
if (!state || state.firstChunkTime !== void 0) {
|
|
11626
|
+
return;
|
|
11627
|
+
}
|
|
11628
|
+
state.firstChunkTime = getCurrentUnixTimestamp();
|
|
11629
|
+
});
|
|
11630
|
+
},
|
|
11631
|
+
onFinish(event) {
|
|
11632
|
+
runSafely("onFinish", () => {
|
|
11633
|
+
const state = operations.get(event.callId);
|
|
11634
|
+
if (!state) {
|
|
11635
|
+
return;
|
|
11636
|
+
}
|
|
11637
|
+
const result = finishResult(event, state.operationName);
|
|
11638
|
+
const metrics = state.hadModelChild ? {} : extractTokenMetrics(result);
|
|
11639
|
+
if (state.firstChunkTime !== void 0) {
|
|
11640
|
+
metrics.time_to_first_token = state.firstChunkTime - state.startTime;
|
|
11641
|
+
}
|
|
11642
|
+
state.span.log({
|
|
11643
|
+
...shouldRecordOutputs(event) ? {
|
|
11644
|
+
output: finishOutput(result, state.operationName)
|
|
11645
|
+
} : {},
|
|
11646
|
+
metrics
|
|
11647
|
+
});
|
|
11648
|
+
state.span.end();
|
|
11649
|
+
operations.delete(event.callId);
|
|
11650
|
+
});
|
|
11651
|
+
},
|
|
11652
|
+
onError(event) {
|
|
11653
|
+
runSafely("onError", () => {
|
|
11654
|
+
const errorEvent = isObject(event) ? event : {};
|
|
11655
|
+
const callId = typeof errorEvent.callId === "string" ? errorEvent.callId : void 0;
|
|
11656
|
+
if (!callId) {
|
|
11657
|
+
return;
|
|
11658
|
+
}
|
|
11659
|
+
const state = operations.get(callId);
|
|
11660
|
+
if (!state) {
|
|
11661
|
+
return;
|
|
11662
|
+
}
|
|
11663
|
+
const error = errorEvent.error ?? event;
|
|
11664
|
+
const openModelSpans = modelSpans.get(callId);
|
|
11665
|
+
if (openModelSpans) {
|
|
11666
|
+
for (const span of openModelSpans) {
|
|
11667
|
+
logError(span, error);
|
|
11668
|
+
span.end();
|
|
11669
|
+
}
|
|
11670
|
+
modelSpans.delete(callId);
|
|
11671
|
+
}
|
|
11672
|
+
const openObjectSpan = objectSpans.get(callId);
|
|
11673
|
+
if (openObjectSpan) {
|
|
11674
|
+
logError(openObjectSpan, error);
|
|
11675
|
+
openObjectSpan.end();
|
|
11676
|
+
objectSpans.delete(callId);
|
|
11677
|
+
}
|
|
11678
|
+
for (const [embedCallId, embedState] of embedSpans) {
|
|
11679
|
+
if (embedState.callId === callId) {
|
|
11680
|
+
logError(embedState.span, error);
|
|
11681
|
+
embedState.span.end();
|
|
11682
|
+
embedSpans.delete(embedCallId);
|
|
11683
|
+
}
|
|
11684
|
+
}
|
|
11685
|
+
const openRerankSpan = rerankSpans.get(callId);
|
|
11686
|
+
if (openRerankSpan) {
|
|
11687
|
+
logError(openRerankSpan, error);
|
|
11688
|
+
openRerankSpan.end();
|
|
11689
|
+
rerankSpans.delete(callId);
|
|
11690
|
+
}
|
|
11691
|
+
for (const [toolCallId, toolState] of toolSpans) {
|
|
11692
|
+
if (toolState.callId === callId) {
|
|
11693
|
+
logError(toolState.span, error);
|
|
11694
|
+
toolState.span.end();
|
|
11695
|
+
toolSpans.delete(toolCallId);
|
|
11696
|
+
}
|
|
11697
|
+
}
|
|
11698
|
+
logError(state.span, error);
|
|
11699
|
+
state.span.end();
|
|
11700
|
+
operations.delete(callId);
|
|
11701
|
+
});
|
|
11702
|
+
},
|
|
11703
|
+
executeTool({ toolCallId, execute }) {
|
|
11704
|
+
const state = toolSpans.get(toolCallId);
|
|
11705
|
+
return state ? withCurrent(state.span, () => execute()) : execute();
|
|
11706
|
+
}
|
|
11707
|
+
};
|
|
11708
|
+
}
|
|
11709
|
+
function shouldRecordInputs(event) {
|
|
11710
|
+
return event.recordInputs !== false;
|
|
11711
|
+
}
|
|
11712
|
+
function shouldRecordOutputs(event) {
|
|
11713
|
+
return event.recordOutputs !== false;
|
|
11714
|
+
}
|
|
11715
|
+
function operationNameFromId(operationId) {
|
|
11716
|
+
return operationId?.startsWith("ai.") ? operationId.slice("ai.".length) : operationId || "ai-sdk";
|
|
11717
|
+
}
|
|
11718
|
+
function modelFromEvent(event) {
|
|
11719
|
+
return event.modelId ? {
|
|
11720
|
+
modelId: event.modelId,
|
|
11721
|
+
...event.provider ? { provider: event.provider } : {}
|
|
11722
|
+
} : void 0;
|
|
11723
|
+
}
|
|
11724
|
+
function metadataFromEvent(event) {
|
|
11725
|
+
const metadata = createAISDKIntegrationMetadata();
|
|
11726
|
+
const { model, provider } = serializeModelWithProvider(modelFromEvent(event));
|
|
11727
|
+
if (model) {
|
|
11728
|
+
metadata.model = model;
|
|
11729
|
+
}
|
|
11730
|
+
if (provider) {
|
|
11731
|
+
metadata.provider = provider;
|
|
11732
|
+
}
|
|
11733
|
+
if (typeof event.functionId === "string") {
|
|
11734
|
+
metadata.functionId = event.functionId;
|
|
11735
|
+
}
|
|
11736
|
+
return metadata;
|
|
11737
|
+
}
|
|
11738
|
+
function operationInput(event, operationName) {
|
|
11739
|
+
if (operationName === "embed") {
|
|
11740
|
+
return {
|
|
11741
|
+
model: modelFromEvent(event),
|
|
11742
|
+
value: event.value
|
|
11743
|
+
};
|
|
11744
|
+
}
|
|
11745
|
+
if (operationName === "embedMany") {
|
|
11746
|
+
return {
|
|
11747
|
+
model: modelFromEvent(event),
|
|
11748
|
+
values: Array.isArray(event.value) ? event.value ?? [] : void 0
|
|
11749
|
+
};
|
|
11750
|
+
}
|
|
11751
|
+
if (operationName === "rerank") {
|
|
11752
|
+
return {
|
|
11753
|
+
model: modelFromEvent(event),
|
|
11754
|
+
documents: event.documents,
|
|
11755
|
+
query: event.query,
|
|
11756
|
+
topN: event.topN
|
|
11757
|
+
};
|
|
11758
|
+
}
|
|
11759
|
+
return {
|
|
11760
|
+
model: modelFromEvent(event),
|
|
11761
|
+
system: event.system,
|
|
11762
|
+
prompt: event.prompt,
|
|
11763
|
+
messages: event.messages,
|
|
11764
|
+
tools: event.tools,
|
|
11765
|
+
toolChoice: event.toolChoice,
|
|
11766
|
+
activeTools: event.activeTools,
|
|
11767
|
+
output: event.output,
|
|
11768
|
+
schema: event.schema,
|
|
11769
|
+
schemaName: event.schemaName,
|
|
11770
|
+
schemaDescription: event.schemaDescription,
|
|
11771
|
+
maxOutputTokens: event.maxOutputTokens,
|
|
11772
|
+
temperature: event.temperature,
|
|
11773
|
+
topP: event.topP,
|
|
11774
|
+
topK: event.topK,
|
|
11775
|
+
presencePenalty: event.presencePenalty,
|
|
11776
|
+
frequencyPenalty: event.frequencyPenalty,
|
|
11777
|
+
seed: event.seed,
|
|
11778
|
+
maxRetries: event.maxRetries,
|
|
11779
|
+
headers: event.headers,
|
|
11780
|
+
providerOptions: event.providerOptions
|
|
11781
|
+
};
|
|
11782
|
+
}
|
|
11783
|
+
function shiftModelSpan(modelSpans, callId) {
|
|
11784
|
+
const spans = modelSpans.get(callId);
|
|
11785
|
+
const span = spans?.shift();
|
|
11786
|
+
if (spans && spans.length === 0) {
|
|
11787
|
+
modelSpans.delete(callId);
|
|
11788
|
+
}
|
|
11789
|
+
return span;
|
|
11790
|
+
}
|
|
11791
|
+
function finishResult(event, operationName) {
|
|
11792
|
+
if (operationName === "embed") {
|
|
11793
|
+
return {
|
|
11794
|
+
...event,
|
|
11795
|
+
embedding: event.embedding
|
|
11796
|
+
};
|
|
11797
|
+
}
|
|
11798
|
+
if (operationName === "embedMany") {
|
|
11799
|
+
return {
|
|
11800
|
+
...event,
|
|
11801
|
+
embeddings: event.embedding
|
|
11802
|
+
};
|
|
11803
|
+
}
|
|
11804
|
+
if (operationName === "rerank") {
|
|
11805
|
+
return event;
|
|
11806
|
+
}
|
|
11807
|
+
return event;
|
|
11808
|
+
}
|
|
11809
|
+
function finishOutput(result, operationName) {
|
|
11810
|
+
if (operationName === "embed" || operationName === "embedMany") {
|
|
11811
|
+
return processAISDKEmbeddingOutput(
|
|
11812
|
+
result,
|
|
11813
|
+
DEFAULT_DENY_OUTPUT_PATHS
|
|
11814
|
+
);
|
|
11815
|
+
}
|
|
11816
|
+
if (operationName === "rerank") {
|
|
11817
|
+
return processAISDKRerankOutput(
|
|
11818
|
+
result,
|
|
11819
|
+
DEFAULT_DENY_OUTPUT_PATHS
|
|
11820
|
+
);
|
|
11821
|
+
}
|
|
11822
|
+
return processAISDKOutput(result, DEFAULT_DENY_OUTPUT_PATHS);
|
|
11823
|
+
}
|
|
11824
|
+
|
|
11203
11825
|
// src/instrumentation/plugins/ai-sdk-channels.ts
|
|
11204
11826
|
var aiSDKChannels = defineChannels("ai", {
|
|
11205
11827
|
generateText: channel({
|
|
@@ -11259,6 +11881,10 @@ var aiSDKChannels = defineChannels("ai", {
|
|
|
11259
11881
|
toolLoopAgentStream: channel({
|
|
11260
11882
|
channelName: "ToolLoopAgent.stream",
|
|
11261
11883
|
kind: "async"
|
|
11884
|
+
}),
|
|
11885
|
+
v7CreateTelemetryDispatcher: channel({
|
|
11886
|
+
channelName: "createTelemetryDispatcher",
|
|
11887
|
+
kind: "sync-stream"
|
|
11262
11888
|
})
|
|
11263
11889
|
});
|
|
11264
11890
|
|
|
@@ -11279,9 +11905,30 @@ var DEFAULT_DENY_OUTPUT_PATHS = [
|
|
|
11279
11905
|
];
|
|
11280
11906
|
var AUTO_PATCHED_MODEL = /* @__PURE__ */ Symbol.for("braintrust.ai-sdk.auto-patched-model");
|
|
11281
11907
|
var AUTO_PATCHED_TOOL = /* @__PURE__ */ Symbol.for("braintrust.ai-sdk.auto-patched-tool");
|
|
11908
|
+
var AUTO_PATCHED_V7_TELEMETRY_DISPATCHER = /* @__PURE__ */ Symbol.for(
|
|
11909
|
+
"braintrust.ai-sdk.v7.auto-patched-telemetry-dispatcher"
|
|
11910
|
+
);
|
|
11282
11911
|
var RUNTIME_DENY_OUTPUT_PATHS = /* @__PURE__ */ Symbol.for(
|
|
11283
11912
|
"braintrust.ai-sdk.deny-output-paths"
|
|
11284
11913
|
);
|
|
11914
|
+
var AI_SDK_V7_TELEMETRY_CALLBACKS = [
|
|
11915
|
+
"onStart",
|
|
11916
|
+
"onStepStart",
|
|
11917
|
+
"onLanguageModelCallStart",
|
|
11918
|
+
"onLanguageModelCallEnd",
|
|
11919
|
+
"onToolExecutionStart",
|
|
11920
|
+
"onToolExecutionEnd",
|
|
11921
|
+
"onChunk",
|
|
11922
|
+
"onStepFinish",
|
|
11923
|
+
"onObjectStepStart",
|
|
11924
|
+
"onObjectStepFinish",
|
|
11925
|
+
"onEmbedStart",
|
|
11926
|
+
"onEmbedFinish",
|
|
11927
|
+
"onRerankStart",
|
|
11928
|
+
"onRerankFinish",
|
|
11929
|
+
"onFinish",
|
|
11930
|
+
"onError"
|
|
11931
|
+
];
|
|
11285
11932
|
var AISDKPlugin = class extends BasePlugin {
|
|
11286
11933
|
config;
|
|
11287
11934
|
constructor(config = {}) {
|
|
@@ -11296,6 +11943,7 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
11296
11943
|
}
|
|
11297
11944
|
subscribeToAISDK() {
|
|
11298
11945
|
const denyOutputPaths = this.config.denyOutputPaths || DEFAULT_DENY_OUTPUT_PATHS;
|
|
11946
|
+
this.unsubscribers.push(subscribeToAISDKV7TelemetryDispatcher());
|
|
11299
11947
|
this.unsubscribers.push(
|
|
11300
11948
|
traceStreamingChannel(aiSDKChannels.generateText, {
|
|
11301
11949
|
name: "generateText",
|
|
@@ -11520,17 +12168,68 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
11520
12168
|
);
|
|
11521
12169
|
}
|
|
11522
12170
|
};
|
|
11523
|
-
function
|
|
11524
|
-
|
|
11525
|
-
|
|
11526
|
-
|
|
11527
|
-
|
|
11528
|
-
|
|
11529
|
-
|
|
11530
|
-
|
|
11531
|
-
|
|
11532
|
-
|
|
11533
|
-
|
|
12171
|
+
function subscribeToAISDKV7TelemetryDispatcher() {
|
|
12172
|
+
const channel2 = aiSDKChannels.v7CreateTelemetryDispatcher.tracingChannel();
|
|
12173
|
+
const telemetry = braintrustAISDKTelemetry();
|
|
12174
|
+
const handlers = {
|
|
12175
|
+
end: (event) => {
|
|
12176
|
+
const telemetryOptions = event.arguments?.[0]?.telemetry;
|
|
12177
|
+
if (telemetryOptions?.isEnabled === false) {
|
|
12178
|
+
return;
|
|
12179
|
+
}
|
|
12180
|
+
patchAISDKV7TelemetryDispatcher(event.result, telemetry);
|
|
12181
|
+
}
|
|
12182
|
+
};
|
|
12183
|
+
channel2.subscribe(handlers);
|
|
12184
|
+
return () => {
|
|
12185
|
+
channel2.unsubscribe(handlers);
|
|
12186
|
+
};
|
|
12187
|
+
}
|
|
12188
|
+
function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry) {
|
|
12189
|
+
if (!isObject(dispatcher)) {
|
|
12190
|
+
return;
|
|
12191
|
+
}
|
|
12192
|
+
const dispatcherRecord = dispatcher;
|
|
12193
|
+
if (dispatcherRecord[AUTO_PATCHED_V7_TELEMETRY_DISPATCHER]) {
|
|
12194
|
+
return;
|
|
12195
|
+
}
|
|
12196
|
+
dispatcherRecord[AUTO_PATCHED_V7_TELEMETRY_DISPATCHER] = true;
|
|
12197
|
+
for (const key of AI_SDK_V7_TELEMETRY_CALLBACKS) {
|
|
12198
|
+
const braintrustCallback = telemetry[key];
|
|
12199
|
+
if (typeof braintrustCallback !== "function") {
|
|
12200
|
+
continue;
|
|
12201
|
+
}
|
|
12202
|
+
const existingCallback = dispatcherRecord[key];
|
|
12203
|
+
dispatcherRecord[key] = (event) => {
|
|
12204
|
+
const existingResult = typeof existingCallback === "function" ? existingCallback.call(dispatcher, event) : void 0;
|
|
12205
|
+
const braintrustResult = braintrustCallback.call(telemetry, event);
|
|
12206
|
+
const pending = [existingResult, braintrustResult].filter(isPromiseLike);
|
|
12207
|
+
if (pending.length > 0) {
|
|
12208
|
+
return Promise.allSettled(pending).then(() => void 0);
|
|
12209
|
+
}
|
|
12210
|
+
};
|
|
12211
|
+
}
|
|
12212
|
+
const braintrustExecuteTool = telemetry.executeTool;
|
|
12213
|
+
if (typeof braintrustExecuteTool !== "function") {
|
|
12214
|
+
return;
|
|
12215
|
+
}
|
|
12216
|
+
const existingExecuteTool = dispatcherRecord.executeTool;
|
|
12217
|
+
dispatcherRecord.executeTool = (args) => braintrustExecuteTool.call(telemetry, {
|
|
12218
|
+
...args,
|
|
12219
|
+
execute: () => typeof existingExecuteTool === "function" ? existingExecuteTool.call(dispatcher, args) : args.execute()
|
|
12220
|
+
});
|
|
12221
|
+
}
|
|
12222
|
+
function resolveDenyOutputPaths(event, defaultDenyOutputPaths) {
|
|
12223
|
+
if (Array.isArray(event?.denyOutputPaths)) {
|
|
12224
|
+
return event.denyOutputPaths;
|
|
12225
|
+
}
|
|
12226
|
+
const firstArgument2 = event?.arguments && event.arguments.length > 0 ? event.arguments[0] : void 0;
|
|
12227
|
+
if (!firstArgument2 || typeof firstArgument2 !== "object") {
|
|
12228
|
+
return defaultDenyOutputPaths;
|
|
12229
|
+
}
|
|
12230
|
+
const runtimeDenyOutputPaths = firstArgument2[RUNTIME_DENY_OUTPUT_PATHS];
|
|
12231
|
+
if (Array.isArray(runtimeDenyOutputPaths) && runtimeDenyOutputPaths.every((path) => typeof path === "string")) {
|
|
12232
|
+
return runtimeDenyOutputPaths;
|
|
11534
12233
|
}
|
|
11535
12234
|
return defaultDenyOutputPaths;
|
|
11536
12235
|
}
|
|
@@ -11971,11 +12670,11 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
|
|
|
11971
12670
|
metadata: baseMetadata
|
|
11972
12671
|
}
|
|
11973
12672
|
});
|
|
12673
|
+
const streamStartTime = getCurrentUnixTimestamp();
|
|
11974
12674
|
const result = await withCurrent(
|
|
11975
12675
|
span,
|
|
11976
12676
|
() => Reflect.apply(originalDoStream, resolvedModel, [options])
|
|
11977
12677
|
);
|
|
11978
|
-
const streamStartTime = getCurrentUnixTimestamp();
|
|
11979
12678
|
let firstChunkTime;
|
|
11980
12679
|
const output = {};
|
|
11981
12680
|
let text = "";
|
|
@@ -11984,7 +12683,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
|
|
|
11984
12683
|
let object = void 0;
|
|
11985
12684
|
const transformStream = new TransformStream({
|
|
11986
12685
|
transform(chunk, controller) {
|
|
11987
|
-
if (firstChunkTime === void 0) {
|
|
12686
|
+
if (firstChunkTime === void 0 && isAISDKContentStreamChunk(chunk)) {
|
|
11988
12687
|
firstChunkTime = getCurrentUnixTimestamp();
|
|
11989
12688
|
}
|
|
11990
12689
|
switch (chunk.type) {
|
|
@@ -12176,6 +12875,78 @@ function finalizeAISDKChildTracing(event) {
|
|
|
12176
12875
|
delete event.__braintrust_ai_sdk_cleanup;
|
|
12177
12876
|
}
|
|
12178
12877
|
}
|
|
12878
|
+
function extractAISDKStreamPart(chunk) {
|
|
12879
|
+
if (!isObject(chunk) || !isObject(chunk.part)) {
|
|
12880
|
+
return chunk;
|
|
12881
|
+
}
|
|
12882
|
+
return chunk.part;
|
|
12883
|
+
}
|
|
12884
|
+
function stringContent(value) {
|
|
12885
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
12886
|
+
}
|
|
12887
|
+
function rawValueHasAISDKContent(value) {
|
|
12888
|
+
if (value === void 0 || value === null) {
|
|
12889
|
+
return false;
|
|
12890
|
+
}
|
|
12891
|
+
if (typeof value === "string") {
|
|
12892
|
+
return value.length > 0;
|
|
12893
|
+
}
|
|
12894
|
+
if (!isObject(value)) {
|
|
12895
|
+
return true;
|
|
12896
|
+
}
|
|
12897
|
+
const delta = value.delta;
|
|
12898
|
+
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) => {
|
|
12899
|
+
if (!isObject(choice) || !isObject(choice.delta)) {
|
|
12900
|
+
return false;
|
|
12901
|
+
}
|
|
12902
|
+
const choiceDelta = choice.delta;
|
|
12903
|
+
if (stringContent(choiceDelta.content) || stringContent(choiceDelta.text)) {
|
|
12904
|
+
return true;
|
|
12905
|
+
}
|
|
12906
|
+
if (isObject(choiceDelta.function_call) && stringContent(choiceDelta.function_call.arguments)) {
|
|
12907
|
+
return true;
|
|
12908
|
+
}
|
|
12909
|
+
return Array.isArray(choiceDelta.tool_calls) && choiceDelta.tool_calls.some(
|
|
12910
|
+
(toolCall) => isObject(toolCall) && isObject(toolCall.function) && stringContent(toolCall.function.arguments)
|
|
12911
|
+
);
|
|
12912
|
+
})) {
|
|
12913
|
+
return true;
|
|
12914
|
+
}
|
|
12915
|
+
return false;
|
|
12916
|
+
}
|
|
12917
|
+
function isAISDKContentStreamChunk(chunk) {
|
|
12918
|
+
const part = extractAISDKStreamPart(chunk);
|
|
12919
|
+
if (typeof part === "string") {
|
|
12920
|
+
return part.length > 0;
|
|
12921
|
+
}
|
|
12922
|
+
if (!isObject(part) || typeof part.type !== "string") {
|
|
12923
|
+
return false;
|
|
12924
|
+
}
|
|
12925
|
+
switch (part.type) {
|
|
12926
|
+
case "text-delta":
|
|
12927
|
+
return stringContent(part.textDelta) !== void 0 || stringContent(part.delta) !== void 0 || stringContent(part.text) !== void 0 || stringContent(part.content) !== void 0;
|
|
12928
|
+
case "reasoning-delta":
|
|
12929
|
+
return stringContent(part.delta) !== void 0 || stringContent(part.text) !== void 0 || stringContent(part.content) !== void 0;
|
|
12930
|
+
case "tool-call":
|
|
12931
|
+
case "object":
|
|
12932
|
+
case "file":
|
|
12933
|
+
return true;
|
|
12934
|
+
case "tool-input-delta":
|
|
12935
|
+
case "tool-call-delta":
|
|
12936
|
+
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;
|
|
12937
|
+
case "raw":
|
|
12938
|
+
return rawValueHasAISDKContent(part.rawValue);
|
|
12939
|
+
default:
|
|
12940
|
+
return false;
|
|
12941
|
+
}
|
|
12942
|
+
}
|
|
12943
|
+
function isAISDKContentAsyncIterableChunk(chunk) {
|
|
12944
|
+
if (isAISDKContentStreamChunk(chunk)) {
|
|
12945
|
+
return true;
|
|
12946
|
+
}
|
|
12947
|
+
const part = extractAISDKStreamPart(chunk);
|
|
12948
|
+
return isObject(part) && typeof part.type !== "string";
|
|
12949
|
+
}
|
|
12179
12950
|
function patchAISDKStreamingResult(args) {
|
|
12180
12951
|
const { defaultDenyOutputPaths, endEvent, result, span, startTime } = args;
|
|
12181
12952
|
if (!result || typeof result !== "object") {
|
|
@@ -12188,7 +12959,7 @@ function patchAISDKStreamingResult(args) {
|
|
|
12188
12959
|
const wrappedBaseStream = resultRecord.baseStream.pipeThrough(
|
|
12189
12960
|
new TransformStream({
|
|
12190
12961
|
transform(chunk, controller) {
|
|
12191
|
-
if (firstChunkTime2 === void 0) {
|
|
12962
|
+
if (firstChunkTime2 === void 0 && isAISDKContentStreamChunk(chunk)) {
|
|
12192
12963
|
firstChunkTime2 = getCurrentUnixTimestamp();
|
|
12193
12964
|
}
|
|
12194
12965
|
controller.enqueue(chunk);
|
|
@@ -12232,8 +13003,8 @@ function patchAISDKStreamingResult(args) {
|
|
|
12232
13003
|
}
|
|
12233
13004
|
let firstChunkTime;
|
|
12234
13005
|
const wrappedStream = createPatchedAsyncIterable(streamField.stream, {
|
|
12235
|
-
onChunk: () => {
|
|
12236
|
-
if (firstChunkTime === void 0) {
|
|
13006
|
+
onChunk: (chunk) => {
|
|
13007
|
+
if (firstChunkTime === void 0 && isAISDKContentAsyncIterableChunk(chunk)) {
|
|
12237
13008
|
firstChunkTime = getCurrentUnixTimestamp();
|
|
12238
13009
|
}
|
|
12239
13010
|
},
|
|
@@ -13205,15 +13976,17 @@ function collectLocalMcpServerToolHookNames(serverName, serverConfig) {
|
|
|
13205
13976
|
|
|
13206
13977
|
// src/instrumentation/plugins/claude-agent-sdk-plugin.ts
|
|
13207
13978
|
var ROOT_LLM_PARENT_KEY = "__root__";
|
|
13979
|
+
var SUB_AGENT_PROMPT_SOURCE_PRIORITY = {
|
|
13980
|
+
delegation: 0,
|
|
13981
|
+
lifecycle: 1,
|
|
13982
|
+
sidechain: 2
|
|
13983
|
+
};
|
|
13208
13984
|
function llmParentKey(parentToolUseId) {
|
|
13209
13985
|
return parentToolUseId ?? ROOT_LLM_PARENT_KEY;
|
|
13210
13986
|
}
|
|
13211
13987
|
function isSubAgentDelegationToolName(toolName) {
|
|
13212
13988
|
return toolName === "Agent" || toolName === "Task";
|
|
13213
13989
|
}
|
|
13214
|
-
function shouldParentToolAsTaskSibling(toolName) {
|
|
13215
|
-
return toolName === "Agent" || toolName === "Task" || toolName === "Bash";
|
|
13216
|
-
}
|
|
13217
13990
|
function filterSerializableOptions(options) {
|
|
13218
13991
|
const allowedKeys = [
|
|
13219
13992
|
"model",
|
|
@@ -13350,26 +14123,39 @@ function extractUsageFromMessage(message) {
|
|
|
13350
14123
|
}
|
|
13351
14124
|
return metrics;
|
|
13352
14125
|
}
|
|
13353
|
-
function buildLLMInput(
|
|
13354
|
-
const promptMessages = [];
|
|
13355
|
-
if (typeof prompt === "string") {
|
|
13356
|
-
promptMessages.push({ content: prompt, role: "user" });
|
|
13357
|
-
} else if (capturedPromptMessages && capturedPromptMessages.length > 0) {
|
|
13358
|
-
for (const msg of capturedPromptMessages) {
|
|
13359
|
-
const role = msg.message?.role;
|
|
13360
|
-
const content = msg.message?.content;
|
|
13361
|
-
if (role && content !== void 0) {
|
|
13362
|
-
promptMessages.push({ content, role });
|
|
13363
|
-
}
|
|
13364
|
-
}
|
|
13365
|
-
}
|
|
14126
|
+
function buildLLMInput(promptMessages, conversationHistory) {
|
|
13366
14127
|
const inputParts = [...promptMessages, ...conversationHistory];
|
|
13367
14128
|
return inputParts.length > 0 ? inputParts : void 0;
|
|
13368
14129
|
}
|
|
14130
|
+
function conversationMessageFromSDKMessage(message) {
|
|
14131
|
+
const role = message.message?.role;
|
|
14132
|
+
const content = message.message?.content;
|
|
14133
|
+
if (role && content !== void 0) {
|
|
14134
|
+
return { content, role };
|
|
14135
|
+
}
|
|
14136
|
+
return void 0;
|
|
14137
|
+
}
|
|
14138
|
+
function messageContentHasBlockType(message, blockType) {
|
|
14139
|
+
const content = message.message?.content;
|
|
14140
|
+
return Array.isArray(content) && content.some(
|
|
14141
|
+
(block) => typeof block === "object" && block !== null && "type" in block && block.type === blockType
|
|
14142
|
+
);
|
|
14143
|
+
}
|
|
14144
|
+
function buildRootPromptMessages(prompt, capturedPromptMessages) {
|
|
14145
|
+
if (typeof prompt === "string") {
|
|
14146
|
+
return [{ content: prompt, role: "user" }];
|
|
14147
|
+
}
|
|
14148
|
+
if (!capturedPromptMessages || capturedPromptMessages.length === 0) {
|
|
14149
|
+
return [];
|
|
14150
|
+
}
|
|
14151
|
+
return capturedPromptMessages.map(conversationMessageFromSDKMessage).filter(
|
|
14152
|
+
(message) => message !== void 0
|
|
14153
|
+
);
|
|
14154
|
+
}
|
|
13369
14155
|
function formatCapturedMessages(messages) {
|
|
13370
14156
|
return messages.length > 0 ? messages : [];
|
|
13371
14157
|
}
|
|
13372
|
-
async function createLLMSpanForMessages(messages,
|
|
14158
|
+
async function createLLMSpanForMessages(messages, promptMessages, conversationHistory, options, startTime, parentSpan, existingSpan) {
|
|
13373
14159
|
if (messages.length === 0) {
|
|
13374
14160
|
return void 0;
|
|
13375
14161
|
}
|
|
@@ -13379,11 +14165,7 @@ async function createLLMSpanForMessages(messages, prompt, conversationHistory, o
|
|
|
13379
14165
|
}
|
|
13380
14166
|
const model = lastMessage.message.model || options.model;
|
|
13381
14167
|
const usage = extractUsageFromMessage(lastMessage);
|
|
13382
|
-
const input = buildLLMInput(
|
|
13383
|
-
prompt,
|
|
13384
|
-
conversationHistory,
|
|
13385
|
-
capturedPromptMessages
|
|
13386
|
-
);
|
|
14168
|
+
const input = buildLLMInput(promptMessages, conversationHistory);
|
|
13387
14169
|
const outputs = messages.map(
|
|
13388
14170
|
(m) => m.message?.content && m.message?.role ? { content: m.message.content, role: m.message.role } : void 0
|
|
13389
14171
|
).filter(
|
|
@@ -13514,8 +14296,7 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
|
|
|
13514
14296
|
},
|
|
13515
14297
|
name: parsed.displayName,
|
|
13516
14298
|
parent: await resolveParentSpan(toolUseID, {
|
|
13517
|
-
agentId: input.agent_id
|
|
13518
|
-
preferTaskSiblingParent: shouldParentToolAsTaskSibling(parsed.toolName)
|
|
14299
|
+
agentId: input.agent_id
|
|
13519
14300
|
}),
|
|
13520
14301
|
spanAttributes: { type: "tool" /* TOOL */ }
|
|
13521
14302
|
});
|
|
@@ -13761,12 +14542,37 @@ function injectTracingHooks(options, resolveParentSpan, activeToolSpans, localTo
|
|
|
13761
14542
|
}
|
|
13762
14543
|
};
|
|
13763
14544
|
}
|
|
14545
|
+
function setSubAgentPromptMessages(state, parentToolUseId, promptMessages, source) {
|
|
14546
|
+
if (promptMessages.length === 0) {
|
|
14547
|
+
return;
|
|
14548
|
+
}
|
|
14549
|
+
const parentKey = llmParentKey(parentToolUseId);
|
|
14550
|
+
const sourcePriority = SUB_AGENT_PROMPT_SOURCE_PRIORITY[source];
|
|
14551
|
+
const currentPriority = state.promptSourcePriorityByParentKey.get(parentKey) ?? -1;
|
|
14552
|
+
if (sourcePriority > currentPriority) {
|
|
14553
|
+
state.promptMessagesByParentKey.set(parentKey, promptMessages);
|
|
14554
|
+
state.promptSourcePriorityByParentKey.set(parentKey, sourcePriority);
|
|
14555
|
+
}
|
|
14556
|
+
}
|
|
14557
|
+
function getConversationHistory(state, parentKey) {
|
|
14558
|
+
let conversationHistory = state.conversationHistoryByParentKey.get(parentKey);
|
|
14559
|
+
if (!conversationHistory) {
|
|
14560
|
+
conversationHistory = [];
|
|
14561
|
+
state.conversationHistoryByParentKey.set(parentKey, conversationHistory);
|
|
14562
|
+
}
|
|
14563
|
+
return conversationHistory;
|
|
14564
|
+
}
|
|
13764
14565
|
async function finalizeCurrentMessageGroup(state) {
|
|
13765
14566
|
if (state.currentMessages.length === 0) {
|
|
13766
14567
|
return;
|
|
13767
14568
|
}
|
|
13768
14569
|
const parentToolUseId = state.currentMessages[0]?.parent_tool_use_id ?? null;
|
|
13769
14570
|
const parentKey = llmParentKey(parentToolUseId);
|
|
14571
|
+
const conversationHistory = getConversationHistory(state, parentKey);
|
|
14572
|
+
const promptMessages = parentToolUseId ? state.promptMessagesByParentKey.get(parentKey) ?? [] : buildRootPromptMessages(
|
|
14573
|
+
state.originalPrompt,
|
|
14574
|
+
state.capturedPromptMessages
|
|
14575
|
+
);
|
|
13770
14576
|
let parentSpan = await state.span.export();
|
|
13771
14577
|
if (parentToolUseId) {
|
|
13772
14578
|
const subAgentSpan = state.subAgentSpans.get(parentToolUseId);
|
|
@@ -13777,11 +14583,10 @@ async function finalizeCurrentMessageGroup(state) {
|
|
|
13777
14583
|
const existingLlmSpan = state.activeLlmSpansByParentToolUse.get(parentKey);
|
|
13778
14584
|
const llmSpanResult = await createLLMSpanForMessages(
|
|
13779
14585
|
state.currentMessages,
|
|
13780
|
-
|
|
13781
|
-
|
|
14586
|
+
promptMessages,
|
|
14587
|
+
conversationHistory,
|
|
13782
14588
|
state.options,
|
|
13783
14589
|
state.currentMessageStartTime,
|
|
13784
|
-
state.capturedPromptMessages,
|
|
13785
14590
|
parentSpan,
|
|
13786
14591
|
existingLlmSpan
|
|
13787
14592
|
);
|
|
@@ -13795,6 +14600,7 @@ async function finalizeCurrentMessageGroup(state) {
|
|
|
13795
14600
|
state.latestRootLlmParentRef.value = llmSpanResult.spanExport;
|
|
13796
14601
|
}
|
|
13797
14602
|
if (llmSpanResult.finalMessage) {
|
|
14603
|
+
conversationHistory.push(llmSpanResult.finalMessage);
|
|
13798
14604
|
state.finalResults.push(llmSpanResult.finalMessage);
|
|
13799
14605
|
}
|
|
13800
14606
|
}
|
|
@@ -13822,6 +14628,15 @@ function maybeTrackToolUseContext(state, message) {
|
|
|
13822
14628
|
description: getStringProperty(block.input, "description"),
|
|
13823
14629
|
toolUseId: block.id
|
|
13824
14630
|
});
|
|
14631
|
+
const prompt = getStringProperty(block.input, "prompt");
|
|
14632
|
+
if (prompt) {
|
|
14633
|
+
setSubAgentPromptMessages(
|
|
14634
|
+
state,
|
|
14635
|
+
block.id,
|
|
14636
|
+
[{ content: prompt, role: "user" }],
|
|
14637
|
+
"delegation"
|
|
14638
|
+
);
|
|
14639
|
+
}
|
|
13825
14640
|
}
|
|
13826
14641
|
}
|
|
13827
14642
|
}
|
|
@@ -13940,6 +14755,14 @@ async function maybeHandleTaskLifecycleMessage(state, message) {
|
|
|
13940
14755
|
};
|
|
13941
14756
|
if (message.subtype === "task_started") {
|
|
13942
14757
|
const prompt = getStringProperty(message, "prompt");
|
|
14758
|
+
if (prompt) {
|
|
14759
|
+
setSubAgentPromptMessages(
|
|
14760
|
+
state,
|
|
14761
|
+
toolUseId,
|
|
14762
|
+
[{ content: prompt, role: "user" }],
|
|
14763
|
+
"lifecycle"
|
|
14764
|
+
);
|
|
14765
|
+
}
|
|
13943
14766
|
subAgentSpan.log({
|
|
13944
14767
|
input: prompt,
|
|
13945
14768
|
metadata
|
|
@@ -13990,6 +14813,28 @@ async function handleStreamMessage(state, message) {
|
|
|
13990
14813
|
return;
|
|
13991
14814
|
}
|
|
13992
14815
|
await maybeStartSubAgentSpan(state, message);
|
|
14816
|
+
const messageParentToolUseId = message.parent_tool_use_id;
|
|
14817
|
+
if (messageParentToolUseId && message.type === "user") {
|
|
14818
|
+
const conversationMessage = conversationMessageFromSDKMessage(message);
|
|
14819
|
+
if (conversationMessage?.role === "user") {
|
|
14820
|
+
await finalizeCurrentMessageGroup(state);
|
|
14821
|
+
const parentKey = llmParentKey(messageParentToolUseId);
|
|
14822
|
+
const conversationHistory = getConversationHistory(state, parentKey);
|
|
14823
|
+
const currentPromptSourcePriority = state.promptSourcePriorityByParentKey.get(parentKey) ?? -1;
|
|
14824
|
+
const canUseAsInitialSidechainPrompt = conversationHistory.length === 0 && currentPromptSourcePriority < SUB_AGENT_PROMPT_SOURCE_PRIORITY.sidechain && !messageContentHasBlockType(message, "tool_result");
|
|
14825
|
+
if (!canUseAsInitialSidechainPrompt) {
|
|
14826
|
+
conversationHistory.push(conversationMessage);
|
|
14827
|
+
return;
|
|
14828
|
+
}
|
|
14829
|
+
setSubAgentPromptMessages(
|
|
14830
|
+
state,
|
|
14831
|
+
messageParentToolUseId,
|
|
14832
|
+
[conversationMessage],
|
|
14833
|
+
"sidechain"
|
|
14834
|
+
);
|
|
14835
|
+
return;
|
|
14836
|
+
}
|
|
14837
|
+
}
|
|
13993
14838
|
const messageId = message.message?.id;
|
|
13994
14839
|
if (messageId && messageId !== state.currentMessageId) {
|
|
13995
14840
|
await finalizeCurrentMessageGroup(state);
|
|
@@ -14141,6 +14986,7 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
14141
14986
|
}
|
|
14142
14987
|
const activeToolSpans = /* @__PURE__ */ new Map();
|
|
14143
14988
|
const activeLlmSpansByParentToolUse = /* @__PURE__ */ new Map();
|
|
14989
|
+
const conversationHistoryByParentKey = /* @__PURE__ */ new Map();
|
|
14144
14990
|
const subAgentSpans = /* @__PURE__ */ new Map();
|
|
14145
14991
|
const endedSubAgentSpans = /* @__PURE__ */ new Set();
|
|
14146
14992
|
const toolUseToParent = /* @__PURE__ */ new Map();
|
|
@@ -14150,6 +14996,8 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
14150
14996
|
};
|
|
14151
14997
|
const subAgentDetailsByToolUseId = /* @__PURE__ */ new Map();
|
|
14152
14998
|
const taskIdToToolUseId = /* @__PURE__ */ new Map();
|
|
14999
|
+
const promptMessagesByParentKey = /* @__PURE__ */ new Map();
|
|
15000
|
+
const promptSourcePriorityByParentKey = /* @__PURE__ */ new Map();
|
|
14153
15001
|
const localToolContext = createClaudeLocalToolContext();
|
|
14154
15002
|
const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
|
|
14155
15003
|
const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
|
|
@@ -14158,38 +15006,19 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
14158
15006
|
const parentToolUseId = trackedParentToolUseId ?? (context?.agentId ? taskIdToToolUseId.get(context.agentId) ?? null : null);
|
|
14159
15007
|
const parentKey = llmParentKey(parentToolUseId);
|
|
14160
15008
|
const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
|
|
14161
|
-
|
|
14162
|
-
|
|
14163
|
-
|
|
14164
|
-
|
|
14165
|
-
|
|
14166
|
-
|
|
14167
|
-
|
|
14168
|
-
|
|
14169
|
-
|
|
14170
|
-
|
|
14171
|
-
|
|
14172
|
-
}
|
|
14173
|
-
if (parentToolUseId) {
|
|
14174
|
-
const subAgentSpan = await ensureSubAgentSpan(
|
|
14175
|
-
subAgentDetailsByToolUseId,
|
|
14176
|
-
span,
|
|
14177
|
-
activeToolSpans,
|
|
14178
|
-
subAgentSpans,
|
|
14179
|
-
parentToolUseId
|
|
14180
|
-
);
|
|
14181
|
-
return subAgentSpan.export();
|
|
14182
|
-
}
|
|
14183
|
-
return span.export();
|
|
14184
|
-
}
|
|
14185
|
-
if (activeLlmSpan) {
|
|
14186
|
-
return activeLlmSpan.export();
|
|
15009
|
+
const latestLlmParent = parentToolUseId ? latestLlmParentBySubAgentToolUse.get(parentToolUseId) : latestRootLlmParentRef.value;
|
|
15010
|
+
if (!activeLlmSpan && !latestLlmParent) {
|
|
15011
|
+
await ensureActiveLlmSpanForParentToolUse(
|
|
15012
|
+
span,
|
|
15013
|
+
activeLlmSpansByParentToolUse,
|
|
15014
|
+
subAgentDetailsByToolUseId,
|
|
15015
|
+
activeToolSpans,
|
|
15016
|
+
subAgentSpans,
|
|
15017
|
+
parentToolUseId,
|
|
15018
|
+
getCurrentUnixTimestamp()
|
|
15019
|
+
);
|
|
14187
15020
|
}
|
|
14188
15021
|
if (parentToolUseId) {
|
|
14189
|
-
const parentLlm = latestLlmParentBySubAgentToolUse.get(parentToolUseId);
|
|
14190
|
-
if (parentLlm) {
|
|
14191
|
-
return parentLlm;
|
|
14192
|
-
}
|
|
14193
15022
|
const subAgentSpan = await ensureSubAgentSpan(
|
|
14194
15023
|
subAgentDetailsByToolUseId,
|
|
14195
15024
|
span,
|
|
@@ -14199,9 +15028,6 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
14199
15028
|
);
|
|
14200
15029
|
return subAgentSpan.export();
|
|
14201
15030
|
}
|
|
14202
|
-
if (latestRootLlmParentRef.value) {
|
|
14203
|
-
return latestRootLlmParentRef.value;
|
|
14204
|
-
}
|
|
14205
15031
|
return span.export();
|
|
14206
15032
|
};
|
|
14207
15033
|
localToolContext.resolveLocalToolParent = resolveToolUseParentSpan;
|
|
@@ -14222,6 +15048,7 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
14222
15048
|
accumulatedOutputTokens: 0,
|
|
14223
15049
|
activeLlmSpansByParentToolUse,
|
|
14224
15050
|
activeToolSpans,
|
|
15051
|
+
conversationHistoryByParentKey,
|
|
14225
15052
|
capturedPromptMessages,
|
|
14226
15053
|
currentMessageId: void 0,
|
|
14227
15054
|
currentMessageStartTime: startTime,
|
|
@@ -14232,7 +15059,9 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
14232
15059
|
originalPrompt,
|
|
14233
15060
|
processing: Promise.resolve(),
|
|
14234
15061
|
promptDone,
|
|
15062
|
+
promptMessagesByParentKey,
|
|
14235
15063
|
promptStarted: () => promptStarted,
|
|
15064
|
+
promptSourcePriorityByParentKey,
|
|
14236
15065
|
span,
|
|
14237
15066
|
subAgentDetailsByToolUseId,
|
|
14238
15067
|
subAgentSpans,
|
|
@@ -15661,6 +16490,10 @@ var googleGenAIChannels = defineChannels("@google/genai", {
|
|
|
15661
16490
|
embedContent: channel({
|
|
15662
16491
|
channelName: "models.embedContent",
|
|
15663
16492
|
kind: "async"
|
|
16493
|
+
}),
|
|
16494
|
+
interactionsCreate: channel({
|
|
16495
|
+
channelName: "interactions.create",
|
|
16496
|
+
kind: "async"
|
|
15664
16497
|
})
|
|
15665
16498
|
});
|
|
15666
16499
|
|
|
@@ -15688,6 +16521,7 @@ var GoogleGenAIPlugin = class extends BasePlugin {
|
|
|
15688
16521
|
this.subscribeToGenerateContentChannel();
|
|
15689
16522
|
this.subscribeToGenerateContentStreamChannel();
|
|
15690
16523
|
this.subscribeToEmbedContentChannel();
|
|
16524
|
+
this.subscribeToInteractionsCreateChannel();
|
|
15691
16525
|
}
|
|
15692
16526
|
subscribeToGenerateContentChannel() {
|
|
15693
16527
|
const tracingChannel = googleGenAIChannels.generateContent.tracingChannel();
|
|
@@ -15860,7 +16694,30 @@ var GoogleGenAIPlugin = class extends BasePlugin {
|
|
|
15860
16694
|
tracingChannel.unsubscribe(handlers);
|
|
15861
16695
|
});
|
|
15862
16696
|
}
|
|
16697
|
+
subscribeToInteractionsCreateChannel() {
|
|
16698
|
+
this.unsubscribers.push(
|
|
16699
|
+
traceStreamingChannel(
|
|
16700
|
+
googleGenAIChannels.interactionsCreate,
|
|
16701
|
+
{
|
|
16702
|
+
name: "create_interaction",
|
|
16703
|
+
shouldTrace: ([params]) => !isBackgroundInteractionCreate(params),
|
|
16704
|
+
type: "llm" /* LLM */,
|
|
16705
|
+
extractInput: ([params]) => ({
|
|
16706
|
+
input: serializeInteractionInput(params),
|
|
16707
|
+
metadata: extractInteractionMetadata(params)
|
|
16708
|
+
}),
|
|
16709
|
+
extractOutput: (result) => serializeInteractionValue(result),
|
|
16710
|
+
extractMetadata: (result) => extractInteractionResponseMetadata(result),
|
|
16711
|
+
extractMetrics: (result, startTime) => cleanMetrics3(extractInteractionMetrics(result, startTime)),
|
|
16712
|
+
aggregateChunks: (chunks, _result, _event, startTime) => aggregateInteractionEvents(chunks, startTime)
|
|
16713
|
+
}
|
|
16714
|
+
)
|
|
16715
|
+
);
|
|
16716
|
+
}
|
|
15863
16717
|
};
|
|
16718
|
+
function isBackgroundInteractionCreate(params) {
|
|
16719
|
+
return tryToDict(params)?.background === true;
|
|
16720
|
+
}
|
|
15864
16721
|
function ensureSpanState(states, event, create) {
|
|
15865
16722
|
const existing = states.get(event);
|
|
15866
16723
|
if (existing) {
|
|
@@ -16068,6 +16925,60 @@ function serializeEmbedContentInput(params) {
|
|
|
16068
16925
|
}
|
|
16069
16926
|
return input;
|
|
16070
16927
|
}
|
|
16928
|
+
function serializeInteractionInput(params) {
|
|
16929
|
+
const input = {
|
|
16930
|
+
input: serializeInteractionValue(params.input)
|
|
16931
|
+
};
|
|
16932
|
+
for (const key of [
|
|
16933
|
+
"model",
|
|
16934
|
+
"agent",
|
|
16935
|
+
"agent_config",
|
|
16936
|
+
"api_version",
|
|
16937
|
+
"background",
|
|
16938
|
+
"environment",
|
|
16939
|
+
"generation_config",
|
|
16940
|
+
"previous_interaction_id",
|
|
16941
|
+
"response_format",
|
|
16942
|
+
"response_mime_type",
|
|
16943
|
+
"response_modalities",
|
|
16944
|
+
"service_tier",
|
|
16945
|
+
"store",
|
|
16946
|
+
"stream",
|
|
16947
|
+
"system_instruction",
|
|
16948
|
+
"webhook_config"
|
|
16949
|
+
]) {
|
|
16950
|
+
const value = params[key];
|
|
16951
|
+
if (value !== void 0) {
|
|
16952
|
+
input[key] = serializeInteractionValue(value);
|
|
16953
|
+
}
|
|
16954
|
+
}
|
|
16955
|
+
return input;
|
|
16956
|
+
}
|
|
16957
|
+
function extractInteractionMetadata(params) {
|
|
16958
|
+
const metadata = {};
|
|
16959
|
+
for (const key of [
|
|
16960
|
+
"model",
|
|
16961
|
+
"agent",
|
|
16962
|
+
"agent_config",
|
|
16963
|
+
"generation_config",
|
|
16964
|
+
"system_instruction",
|
|
16965
|
+
"response_format",
|
|
16966
|
+
"response_mime_type",
|
|
16967
|
+
"response_modalities",
|
|
16968
|
+
"service_tier"
|
|
16969
|
+
]) {
|
|
16970
|
+
const value = params[key];
|
|
16971
|
+
if (value !== void 0) {
|
|
16972
|
+
metadata[key] = serializeInteractionValue(value);
|
|
16973
|
+
}
|
|
16974
|
+
}
|
|
16975
|
+
if (Array.isArray(params.tools)) {
|
|
16976
|
+
metadata.tools = params.tools.map(
|
|
16977
|
+
(tool) => serializeInteractionValue(tool)
|
|
16978
|
+
);
|
|
16979
|
+
}
|
|
16980
|
+
return metadata;
|
|
16981
|
+
}
|
|
16071
16982
|
function serializeContentCollection(contents) {
|
|
16072
16983
|
if (contents === null || contents === void 0) {
|
|
16073
16984
|
return null;
|
|
@@ -16098,21 +17009,8 @@ function serializePart(part) {
|
|
|
16098
17009
|
}
|
|
16099
17010
|
if (part.inlineData && part.inlineData.data) {
|
|
16100
17011
|
const { data, mimeType } = part.inlineData;
|
|
16101
|
-
|
|
16102
|
-
|
|
16103
|
-
const filename = `file.${extension}`;
|
|
16104
|
-
const buffer = typeof data === "string" ? typeof Buffer !== "undefined" ? Buffer.from(data, "base64") : new Uint8Array(
|
|
16105
|
-
atob(data).split("").map((c) => c.charCodeAt(0))
|
|
16106
|
-
) : typeof Buffer !== "undefined" ? Buffer.from(data) : new Uint8Array(data);
|
|
16107
|
-
const arrayBuffer = buffer instanceof Uint8Array ? buffer.buffer.slice(
|
|
16108
|
-
buffer.byteOffset,
|
|
16109
|
-
buffer.byteOffset + buffer.byteLength
|
|
16110
|
-
) : buffer;
|
|
16111
|
-
const attachment = new Attachment({
|
|
16112
|
-
data: arrayBuffer,
|
|
16113
|
-
filename,
|
|
16114
|
-
contentType: mimeType || "application/octet-stream"
|
|
16115
|
-
});
|
|
17012
|
+
const attachment = createAttachmentFromInlineData(data, mimeType);
|
|
17013
|
+
if (attachment) {
|
|
16116
17014
|
return {
|
|
16117
17015
|
image_url: { url: attachment }
|
|
16118
17016
|
};
|
|
@@ -16120,6 +17018,59 @@ function serializePart(part) {
|
|
|
16120
17018
|
}
|
|
16121
17019
|
return part;
|
|
16122
17020
|
}
|
|
17021
|
+
function serializeInteractionValue(value, seen = /* @__PURE__ */ new WeakSet()) {
|
|
17022
|
+
if (value === null || value === void 0 || typeof value !== "object") {
|
|
17023
|
+
return value;
|
|
17024
|
+
}
|
|
17025
|
+
if (Array.isArray(value)) {
|
|
17026
|
+
return value.map((item) => serializeInteractionValue(item, seen));
|
|
17027
|
+
}
|
|
17028
|
+
const dict = tryToDict(value);
|
|
17029
|
+
if (dict === null || dict === void 0 || typeof dict !== "object") {
|
|
17030
|
+
return dict;
|
|
17031
|
+
}
|
|
17032
|
+
if (Array.isArray(dict)) {
|
|
17033
|
+
return dict.map((item) => serializeInteractionValue(item, seen));
|
|
17034
|
+
}
|
|
17035
|
+
if (seen.has(dict)) {
|
|
17036
|
+
return "[Circular]";
|
|
17037
|
+
}
|
|
17038
|
+
seen.add(dict);
|
|
17039
|
+
try {
|
|
17040
|
+
const serialized = {};
|
|
17041
|
+
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;
|
|
17042
|
+
const attachment = mimeType && "data" in dict && dict.data !== void 0 ? createAttachmentFromInlineData(dict.data, mimeType) : null;
|
|
17043
|
+
for (const [key, entry] of Object.entries(dict)) {
|
|
17044
|
+
if (key === "data" && attachment) {
|
|
17045
|
+
serialized[key] = attachment;
|
|
17046
|
+
} else {
|
|
17047
|
+
serialized[key] = serializeInteractionValue(entry, seen);
|
|
17048
|
+
}
|
|
17049
|
+
}
|
|
17050
|
+
return serialized;
|
|
17051
|
+
} finally {
|
|
17052
|
+
seen.delete(dict);
|
|
17053
|
+
}
|
|
17054
|
+
}
|
|
17055
|
+
function createAttachmentFromInlineData(data, mimeType) {
|
|
17056
|
+
if (!(data instanceof Uint8Array || typeof Buffer !== "undefined" && Buffer.isBuffer(data) || typeof data === "string")) {
|
|
17057
|
+
return null;
|
|
17058
|
+
}
|
|
17059
|
+
const extension = mimeType ? mimeType.split("/")[1] : "bin";
|
|
17060
|
+
const filename = `file.${extension}`;
|
|
17061
|
+
const buffer = typeof data === "string" ? typeof Buffer !== "undefined" ? Buffer.from(data, "base64") : new Uint8Array(
|
|
17062
|
+
atob(data).split("").map((c) => c.charCodeAt(0))
|
|
17063
|
+
) : typeof Buffer !== "undefined" ? Buffer.from(data) : new Uint8Array(data);
|
|
17064
|
+
const arrayBuffer = buffer instanceof Uint8Array ? buffer.buffer.slice(
|
|
17065
|
+
buffer.byteOffset,
|
|
17066
|
+
buffer.byteOffset + buffer.byteLength
|
|
17067
|
+
) : buffer;
|
|
17068
|
+
return new Attachment({
|
|
17069
|
+
data: arrayBuffer,
|
|
17070
|
+
filename,
|
|
17071
|
+
contentType: mimeType || "application/octet-stream"
|
|
17072
|
+
});
|
|
17073
|
+
}
|
|
16123
17074
|
function serializeGenerateContentTools(params) {
|
|
16124
17075
|
const config = params.config ? tryToDict(params.config) : null;
|
|
16125
17076
|
const tools = config?.tools;
|
|
@@ -16204,6 +17155,33 @@ function extractEmbedContentMetrics(response, startTime) {
|
|
|
16204
17155
|
}
|
|
16205
17156
|
return metrics;
|
|
16206
17157
|
}
|
|
17158
|
+
function extractInteractionMetrics(response, startTime) {
|
|
17159
|
+
const metrics = {};
|
|
17160
|
+
if (startTime !== void 0) {
|
|
17161
|
+
const end = getCurrentUnixTimestamp();
|
|
17162
|
+
metrics.start = startTime;
|
|
17163
|
+
metrics.end = end;
|
|
17164
|
+
metrics.duration = end - startTime;
|
|
17165
|
+
}
|
|
17166
|
+
if (response?.usage) {
|
|
17167
|
+
populateInteractionUsageMetrics(metrics, response.usage);
|
|
17168
|
+
}
|
|
17169
|
+
return metrics;
|
|
17170
|
+
}
|
|
17171
|
+
function extractInteractionResponseMetadata(response) {
|
|
17172
|
+
const responseDict = tryToDict(response);
|
|
17173
|
+
if (!responseDict) {
|
|
17174
|
+
return void 0;
|
|
17175
|
+
}
|
|
17176
|
+
const metadata = {};
|
|
17177
|
+
if (typeof responseDict.id === "string") {
|
|
17178
|
+
metadata.interaction_id = responseDict.id;
|
|
17179
|
+
}
|
|
17180
|
+
if (typeof responseDict.status === "string") {
|
|
17181
|
+
metadata.status = responseDict.status;
|
|
17182
|
+
}
|
|
17183
|
+
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
17184
|
+
}
|
|
16207
17185
|
function extractEmbedPromptTokenCount(response) {
|
|
16208
17186
|
if (!response) {
|
|
16209
17187
|
return void 0;
|
|
@@ -16266,6 +17244,23 @@ function populateUsageMetrics(metrics, usage) {
|
|
|
16266
17244
|
metrics.completion_reasoning_tokens = usage.thoughtsTokenCount;
|
|
16267
17245
|
}
|
|
16268
17246
|
}
|
|
17247
|
+
function populateInteractionUsageMetrics(metrics, usage) {
|
|
17248
|
+
if (typeof usage.total_input_tokens === "number") {
|
|
17249
|
+
metrics.prompt_tokens = usage.total_input_tokens;
|
|
17250
|
+
}
|
|
17251
|
+
if (typeof usage.total_output_tokens === "number") {
|
|
17252
|
+
metrics.completion_tokens = usage.total_output_tokens;
|
|
17253
|
+
}
|
|
17254
|
+
if (typeof usage.total_tokens === "number") {
|
|
17255
|
+
metrics.tokens = usage.total_tokens;
|
|
17256
|
+
}
|
|
17257
|
+
if (typeof usage.total_cached_tokens === "number") {
|
|
17258
|
+
metrics.prompt_cached_tokens = usage.total_cached_tokens;
|
|
17259
|
+
}
|
|
17260
|
+
if (typeof usage.total_thought_tokens === "number") {
|
|
17261
|
+
metrics.completion_reasoning_tokens = usage.total_thought_tokens;
|
|
17262
|
+
}
|
|
17263
|
+
}
|
|
16269
17264
|
function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
|
|
16270
17265
|
const end = getCurrentUnixTimestamp();
|
|
16271
17266
|
const metrics = {
|
|
@@ -16363,6 +17358,146 @@ function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
|
|
|
16363
17358
|
}
|
|
16364
17359
|
return { aggregated, metrics };
|
|
16365
17360
|
}
|
|
17361
|
+
function aggregateInteractionEvents(chunks, startTime) {
|
|
17362
|
+
const end = getCurrentUnixTimestamp();
|
|
17363
|
+
const metrics = {};
|
|
17364
|
+
if (startTime !== void 0) {
|
|
17365
|
+
metrics.start = startTime;
|
|
17366
|
+
metrics.end = end;
|
|
17367
|
+
metrics.duration = end - startTime;
|
|
17368
|
+
}
|
|
17369
|
+
let latestInteraction;
|
|
17370
|
+
let latestUsage;
|
|
17371
|
+
let status;
|
|
17372
|
+
let outputText = "";
|
|
17373
|
+
const steps = /* @__PURE__ */ new Map();
|
|
17374
|
+
for (const chunk of chunks) {
|
|
17375
|
+
const event = tryToDict(chunk);
|
|
17376
|
+
if (!event) {
|
|
17377
|
+
continue;
|
|
17378
|
+
}
|
|
17379
|
+
const usage = extractInteractionUsageFromEvent(event);
|
|
17380
|
+
if (usage) {
|
|
17381
|
+
latestUsage = usage;
|
|
17382
|
+
}
|
|
17383
|
+
const interaction = tryToDict(event.interaction);
|
|
17384
|
+
if (interaction) {
|
|
17385
|
+
latestInteraction = serializeInteractionValue(interaction);
|
|
17386
|
+
if (typeof interaction.status === "string") {
|
|
17387
|
+
status = interaction.status;
|
|
17388
|
+
}
|
|
17389
|
+
}
|
|
17390
|
+
if (typeof event.status === "string") {
|
|
17391
|
+
status = event.status;
|
|
17392
|
+
}
|
|
17393
|
+
const index = typeof event.index === "number" ? event.index : void 0;
|
|
17394
|
+
if (index === void 0) {
|
|
17395
|
+
continue;
|
|
17396
|
+
}
|
|
17397
|
+
if (event.event_type === "step.start") {
|
|
17398
|
+
const compact = compactInteractionStep(event.step);
|
|
17399
|
+
compact.index = index;
|
|
17400
|
+
steps.set(index, compact);
|
|
17401
|
+
continue;
|
|
17402
|
+
}
|
|
17403
|
+
if (event.event_type === "step.delta") {
|
|
17404
|
+
const step = steps.get(index) ?? { index };
|
|
17405
|
+
const textDelta = applyInteractionDelta(step, event.delta);
|
|
17406
|
+
if (textDelta) {
|
|
17407
|
+
outputText += textDelta;
|
|
17408
|
+
}
|
|
17409
|
+
steps.set(index, step);
|
|
17410
|
+
}
|
|
17411
|
+
}
|
|
17412
|
+
if (latestUsage) {
|
|
17413
|
+
populateInteractionUsageMetrics(metrics, latestUsage);
|
|
17414
|
+
}
|
|
17415
|
+
const output = latestInteraction ? { ...latestInteraction } : {};
|
|
17416
|
+
if (status) {
|
|
17417
|
+
output.status = status;
|
|
17418
|
+
}
|
|
17419
|
+
if (outputText) {
|
|
17420
|
+
output.output_text = outputText;
|
|
17421
|
+
}
|
|
17422
|
+
if (latestUsage) {
|
|
17423
|
+
output.usage = serializeInteractionValue(latestUsage);
|
|
17424
|
+
}
|
|
17425
|
+
const compactSteps = Array.from(steps.values()).sort(
|
|
17426
|
+
(left, right) => Number(left.index ?? 0) - Number(right.index ?? 0)
|
|
17427
|
+
);
|
|
17428
|
+
if (compactSteps.length > 0) {
|
|
17429
|
+
output.steps = compactSteps;
|
|
17430
|
+
}
|
|
17431
|
+
const metadata = {};
|
|
17432
|
+
if (typeof output.id === "string") {
|
|
17433
|
+
metadata.interaction_id = output.id;
|
|
17434
|
+
}
|
|
17435
|
+
if (typeof output.status === "string") {
|
|
17436
|
+
metadata.status = output.status;
|
|
17437
|
+
}
|
|
17438
|
+
return {
|
|
17439
|
+
output,
|
|
17440
|
+
metrics: cleanMetrics3(metrics),
|
|
17441
|
+
...Object.keys(metadata).length > 0 ? { metadata } : {}
|
|
17442
|
+
};
|
|
17443
|
+
}
|
|
17444
|
+
function extractInteractionUsageFromEvent(event) {
|
|
17445
|
+
const metadata = tryToDict(event.metadata);
|
|
17446
|
+
const metadataUsage = tryToDict(metadata?.usage);
|
|
17447
|
+
if (metadataUsage) {
|
|
17448
|
+
return metadataUsage;
|
|
17449
|
+
}
|
|
17450
|
+
const metadataTotalUsage = tryToDict(metadata?.total_usage);
|
|
17451
|
+
if (metadataTotalUsage) {
|
|
17452
|
+
return metadataTotalUsage;
|
|
17453
|
+
}
|
|
17454
|
+
const interaction = tryToDict(event.interaction);
|
|
17455
|
+
const interactionUsage = tryToDict(interaction?.usage);
|
|
17456
|
+
return interactionUsage ? interactionUsage : void 0;
|
|
17457
|
+
}
|
|
17458
|
+
function compactInteractionStep(step) {
|
|
17459
|
+
const stepDict = tryToDict(step);
|
|
17460
|
+
if (!stepDict) {
|
|
17461
|
+
return {};
|
|
17462
|
+
}
|
|
17463
|
+
const compact = {};
|
|
17464
|
+
for (const key of [
|
|
17465
|
+
"type",
|
|
17466
|
+
"content",
|
|
17467
|
+
"name",
|
|
17468
|
+
"server_name",
|
|
17469
|
+
"arguments",
|
|
17470
|
+
"result",
|
|
17471
|
+
"is_error"
|
|
17472
|
+
]) {
|
|
17473
|
+
if (stepDict[key] !== void 0) {
|
|
17474
|
+
compact[key] = serializeInteractionValue(stepDict[key]);
|
|
17475
|
+
}
|
|
17476
|
+
}
|
|
17477
|
+
return Object.keys(compact).length > 0 ? compact : serializeInteractionValue(stepDict);
|
|
17478
|
+
}
|
|
17479
|
+
function applyInteractionDelta(step, delta) {
|
|
17480
|
+
const deltaDict = tryToDict(delta);
|
|
17481
|
+
if (!deltaDict) {
|
|
17482
|
+
return void 0;
|
|
17483
|
+
}
|
|
17484
|
+
const deltaType = deltaDict.type;
|
|
17485
|
+
if (typeof deltaType === "string" && typeof step.type !== "string") {
|
|
17486
|
+
step.type = deltaType === "text" ? "model_output" : deltaType;
|
|
17487
|
+
}
|
|
17488
|
+
if (deltaType === "text" && typeof deltaDict.text === "string") {
|
|
17489
|
+
step.text = `${typeof step.text === "string" ? step.text : ""}${deltaDict.text}`;
|
|
17490
|
+
return deltaDict.text;
|
|
17491
|
+
}
|
|
17492
|
+
if (deltaType === "arguments_delta" && typeof deltaDict.arguments === "string") {
|
|
17493
|
+
step.arguments = `${typeof step.arguments === "string" ? step.arguments : ""}${deltaDict.arguments}`;
|
|
17494
|
+
return void 0;
|
|
17495
|
+
}
|
|
17496
|
+
const deltas = Array.isArray(step.deltas) ? step.deltas : [];
|
|
17497
|
+
deltas.push(serializeInteractionValue(deltaDict));
|
|
17498
|
+
step.deltas = deltas;
|
|
17499
|
+
return void 0;
|
|
17500
|
+
}
|
|
16366
17501
|
function cleanMetrics3(metrics) {
|
|
16367
17502
|
const cleaned = {};
|
|
16368
17503
|
for (const [key, value] of Object.entries(metrics)) {
|
|
@@ -22189,7 +23324,8 @@ var FlueObserveBridge = class {
|
|
|
22189
23324
|
metadata
|
|
22190
23325
|
}
|
|
22191
23326
|
});
|
|
22192
|
-
|
|
23327
|
+
const activeContext = enterCurrentFlueSpan(span);
|
|
23328
|
+
this.runsById.set(event.runId, { activeContext, metadata, span });
|
|
22193
23329
|
}
|
|
22194
23330
|
handleRunEnd(event) {
|
|
22195
23331
|
const state = this.runsById.get(event.runId);
|
|
@@ -22207,6 +23343,7 @@ var FlueObserveBridge = class {
|
|
|
22207
23343
|
});
|
|
22208
23344
|
safeEnd(state.span, eventTime(event.timestamp));
|
|
22209
23345
|
this.runsById.delete(event.runId);
|
|
23346
|
+
restoreCurrentFlueSpan(state.activeContext);
|
|
22210
23347
|
}
|
|
22211
23348
|
void flush().catch((error) => {
|
|
22212
23349
|
logInstrumentationError3("Flue flush", error);
|
|
@@ -22333,7 +23470,8 @@ var FlueObserveBridge = class {
|
|
|
22333
23470
|
metadata
|
|
22334
23471
|
}
|
|
22335
23472
|
});
|
|
22336
|
-
|
|
23473
|
+
const activeContext = enterCurrentFlueSpan(span);
|
|
23474
|
+
this.toolsByKey.set(toolKey(event), { activeContext, metadata, span });
|
|
22337
23475
|
}
|
|
22338
23476
|
handleToolCall(event) {
|
|
22339
23477
|
if (!event.toolCallId) {
|
|
@@ -22356,6 +23494,7 @@ var FlueObserveBridge = class {
|
|
|
22356
23494
|
});
|
|
22357
23495
|
safeEnd(state.span, eventTime(event.timestamp));
|
|
22358
23496
|
this.toolsByKey.delete(key);
|
|
23497
|
+
restoreCurrentFlueSpan(state.activeContext);
|
|
22359
23498
|
}
|
|
22360
23499
|
handleTaskStart(event) {
|
|
22361
23500
|
if (!event.taskId) {
|
|
@@ -22760,7 +23899,35 @@ function stateMatchesRun(state, runId) {
|
|
|
22760
23899
|
function startFlueSpan(parent, args) {
|
|
22761
23900
|
return parent ? withCurrent(parent, () => startSpan(args)) : startSpan(args);
|
|
22762
23901
|
}
|
|
22763
|
-
function
|
|
23902
|
+
function enterCurrentFlueSpan(span) {
|
|
23903
|
+
const contextManager = _internalGetGlobalState()?.contextManager;
|
|
23904
|
+
const store = contextManager ? Reflect.get(contextManager, BRAINTRUST_CURRENT_SPAN_STORE) : void 0;
|
|
23905
|
+
if (!contextManager || !isCurrentSpanStore(store)) {
|
|
23906
|
+
return void 0;
|
|
23907
|
+
}
|
|
23908
|
+
const previous = store.getStore();
|
|
23909
|
+
try {
|
|
23910
|
+
store.enterWith(contextManager.wrapSpanForStore(span));
|
|
23911
|
+
return { previous, store };
|
|
23912
|
+
} catch (error) {
|
|
23913
|
+
logInstrumentationError3("Flue context propagation", error);
|
|
23914
|
+
return void 0;
|
|
23915
|
+
}
|
|
23916
|
+
}
|
|
23917
|
+
function isCurrentSpanStore(value) {
|
|
23918
|
+
return isObjectLike(value) && typeof Reflect.get(value, "enterWith") === "function" && typeof Reflect.get(value, "getStore") === "function";
|
|
23919
|
+
}
|
|
23920
|
+
function restoreCurrentFlueSpan(activeContext) {
|
|
23921
|
+
if (!activeContext) {
|
|
23922
|
+
return;
|
|
23923
|
+
}
|
|
23924
|
+
try {
|
|
23925
|
+
activeContext.store.enterWith(activeContext.previous);
|
|
23926
|
+
} catch (error) {
|
|
23927
|
+
logInstrumentationError3("Flue context restoration", error);
|
|
23928
|
+
}
|
|
23929
|
+
}
|
|
23930
|
+
function safeLog3(span, event) {
|
|
22764
23931
|
try {
|
|
22765
23932
|
span.log(event);
|
|
22766
23933
|
} catch (error) {
|
|
@@ -23237,6 +24404,890 @@ function isBraintrustHandler(handler) {
|
|
|
23237
24404
|
return Reflect.get(handler, "name") === BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
|
|
23238
24405
|
}
|
|
23239
24406
|
|
|
24407
|
+
// src/instrumentation/plugins/pi-coding-agent-channels.ts
|
|
24408
|
+
var piCodingAgentChannels = defineChannels(
|
|
24409
|
+
"@earendil-works/pi-coding-agent",
|
|
24410
|
+
{
|
|
24411
|
+
prompt: channel({
|
|
24412
|
+
channelName: "AgentSession.prompt",
|
|
24413
|
+
kind: "async"
|
|
24414
|
+
})
|
|
24415
|
+
}
|
|
24416
|
+
);
|
|
24417
|
+
|
|
24418
|
+
// src/instrumentation/plugins/pi-coding-agent-plugin.ts
|
|
24419
|
+
var piStreamPatchStates = /* @__PURE__ */ new WeakMap();
|
|
24420
|
+
var piPromptContextStore;
|
|
24421
|
+
var PiCodingAgentPlugin = class extends BasePlugin {
|
|
24422
|
+
activePromptStates = /* @__PURE__ */ new Set();
|
|
24423
|
+
onEnable() {
|
|
24424
|
+
this.subscribeToPrompt();
|
|
24425
|
+
}
|
|
24426
|
+
onDisable() {
|
|
24427
|
+
for (const unsubscribe of this.unsubscribers) {
|
|
24428
|
+
unsubscribe();
|
|
24429
|
+
}
|
|
24430
|
+
this.unsubscribers = [];
|
|
24431
|
+
for (const state of [...this.activePromptStates]) {
|
|
24432
|
+
void finalizePiPromptRun(state).catch((error) => {
|
|
24433
|
+
logInstrumentationError4("Pi Coding Agent disable cleanup", error);
|
|
24434
|
+
});
|
|
24435
|
+
}
|
|
24436
|
+
}
|
|
24437
|
+
subscribeToPrompt() {
|
|
24438
|
+
const channel2 = piCodingAgentChannels.prompt.tracingChannel();
|
|
24439
|
+
const states = /* @__PURE__ */ new WeakMap();
|
|
24440
|
+
const unbindAutoInstrumentationSuppression = bindAutoInstrumentationSuppressionToStart(channel2);
|
|
24441
|
+
const handlers = {
|
|
24442
|
+
start: (event) => {
|
|
24443
|
+
const state = startPiPromptRun(event, (state2) => {
|
|
24444
|
+
this.activePromptStates.delete(state2);
|
|
24445
|
+
});
|
|
24446
|
+
if (state) {
|
|
24447
|
+
this.activePromptStates.add(state);
|
|
24448
|
+
states.set(event, state);
|
|
24449
|
+
}
|
|
24450
|
+
},
|
|
24451
|
+
asyncEnd: async (event) => {
|
|
24452
|
+
const state = states.get(event);
|
|
24453
|
+
if (!state) {
|
|
24454
|
+
return;
|
|
24455
|
+
}
|
|
24456
|
+
states.delete(event);
|
|
24457
|
+
state.promptCallEnded = true;
|
|
24458
|
+
if (!state.finalized && state.deferCompletionUntilTurnEnd && !state.turnEnded) {
|
|
24459
|
+
if (!state.sawStreamFn) {
|
|
24460
|
+
state.queued = true;
|
|
24461
|
+
if (!state.streamPatchState.queuedPromptStates.includes(state)) {
|
|
24462
|
+
state.streamPatchState.queuedPromptStates.push(state);
|
|
24463
|
+
}
|
|
24464
|
+
}
|
|
24465
|
+
return;
|
|
24466
|
+
}
|
|
24467
|
+
await finalizePiPromptRun(state);
|
|
24468
|
+
},
|
|
24469
|
+
error: async (event) => {
|
|
24470
|
+
const state = states.get(event);
|
|
24471
|
+
if (!state) {
|
|
24472
|
+
return;
|
|
24473
|
+
}
|
|
24474
|
+
states.delete(event);
|
|
24475
|
+
await finalizePiPromptRun(state, event.error);
|
|
24476
|
+
}
|
|
24477
|
+
};
|
|
24478
|
+
channel2.subscribe(handlers);
|
|
24479
|
+
this.unsubscribers.push(() => {
|
|
24480
|
+
unbindAutoInstrumentationSuppression?.();
|
|
24481
|
+
channel2.unsubscribe(handlers);
|
|
24482
|
+
});
|
|
24483
|
+
}
|
|
24484
|
+
};
|
|
24485
|
+
function startPiPromptRun(event, onFinalize) {
|
|
24486
|
+
const session = extractSession(event);
|
|
24487
|
+
const agent = session?.agent;
|
|
24488
|
+
if (!session || !isPiAgent(agent)) {
|
|
24489
|
+
return void 0;
|
|
24490
|
+
}
|
|
24491
|
+
const metadata = {
|
|
24492
|
+
...extractSessionMetadata(session),
|
|
24493
|
+
...extractPromptOptionsMetadata(event.arguments[1]),
|
|
24494
|
+
"pi_coding_agent.operation": "AgentSession.prompt",
|
|
24495
|
+
provider: session.model?.provider ?? agent.state?.model?.provider ?? "pi",
|
|
24496
|
+
...session.model?.id || agent.state?.model?.id ? { model: session.model?.id ?? agent.state?.model?.id } : {},
|
|
24497
|
+
...event.moduleVersion ? { "pi_coding_agent.version": event.moduleVersion } : {}
|
|
24498
|
+
};
|
|
24499
|
+
const span = startSpan({
|
|
24500
|
+
event: {
|
|
24501
|
+
input: extractPromptInput(event.arguments[0], event.arguments[1]),
|
|
24502
|
+
metadata
|
|
24503
|
+
},
|
|
24504
|
+
name: "AgentSession.prompt",
|
|
24505
|
+
spanAttributes: { type: "task" /* TASK */ }
|
|
24506
|
+
});
|
|
24507
|
+
const streamPatchState = installPiStreamPatch(agent);
|
|
24508
|
+
const options = event.arguments[1];
|
|
24509
|
+
const promptText = event.arguments[0];
|
|
24510
|
+
const state = {
|
|
24511
|
+
activeLlmSpans: /* @__PURE__ */ new Set(),
|
|
24512
|
+
activeToolSpans: /* @__PURE__ */ new Map(),
|
|
24513
|
+
agent,
|
|
24514
|
+
collectedLlmUsageMetrics: false,
|
|
24515
|
+
deferCompletionUntilTurnEnd: options?.streamingBehavior === "followUp" || options?.streamingBehavior === "steer",
|
|
24516
|
+
finalized: false,
|
|
24517
|
+
metadata,
|
|
24518
|
+
metrics: {},
|
|
24519
|
+
onFinalize,
|
|
24520
|
+
promptCallEnded: false,
|
|
24521
|
+
...typeof promptText === "string" ? { promptText } : {},
|
|
24522
|
+
queued: false,
|
|
24523
|
+
span,
|
|
24524
|
+
sawStreamFn: false,
|
|
24525
|
+
startTime: getCurrentUnixTimestamp(),
|
|
24526
|
+
streamPatchState,
|
|
24527
|
+
turnEnded: false
|
|
24528
|
+
};
|
|
24529
|
+
state.restorePromptContext = enterPiPromptContext(state);
|
|
24530
|
+
streamPatchState.activePromptStates.add(state);
|
|
24531
|
+
try {
|
|
24532
|
+
state.unsubscribeAgent = agent.subscribe(async (agentEvent) => {
|
|
24533
|
+
try {
|
|
24534
|
+
await runWithAutoInstrumentationSuppressed(
|
|
24535
|
+
() => handlePiAgentEvent(state, agentEvent)
|
|
24536
|
+
);
|
|
24537
|
+
} catch (error) {
|
|
24538
|
+
logInstrumentationError4("Pi Coding Agent event", error);
|
|
24539
|
+
}
|
|
24540
|
+
});
|
|
24541
|
+
} catch (error) {
|
|
24542
|
+
logInstrumentationError4("Pi Coding Agent event subscription", error);
|
|
24543
|
+
}
|
|
24544
|
+
return state;
|
|
24545
|
+
}
|
|
24546
|
+
function extractSession(event) {
|
|
24547
|
+
const candidate = event.session ?? event.self;
|
|
24548
|
+
return isObject(candidate) && typeof candidate.prompt === "function" ? candidate : void 0;
|
|
24549
|
+
}
|
|
24550
|
+
function isPiAgent(value) {
|
|
24551
|
+
return isObject(value) && typeof value.streamFn === "function" && typeof value.subscribe === "function";
|
|
24552
|
+
}
|
|
24553
|
+
function promptContextStore() {
|
|
24554
|
+
piPromptContextStore ??= isomorph_default.newAsyncLocalStorage();
|
|
24555
|
+
return piPromptContextStore;
|
|
24556
|
+
}
|
|
24557
|
+
function currentPromptContextFrames() {
|
|
24558
|
+
return promptContextStore().getStore()?.frames ?? [];
|
|
24559
|
+
}
|
|
24560
|
+
function currentPiPromptState() {
|
|
24561
|
+
const frames = currentPromptContextFrames();
|
|
24562
|
+
return frames[frames.length - 1]?.state;
|
|
24563
|
+
}
|
|
24564
|
+
function enterPiPromptContext(state) {
|
|
24565
|
+
const frame = {
|
|
24566
|
+
id: /* @__PURE__ */ Symbol("braintrust.pi-coding-agent.prompt"),
|
|
24567
|
+
state
|
|
24568
|
+
};
|
|
24569
|
+
promptContextStore().enterWith({
|
|
24570
|
+
frames: [...currentPromptContextFrames(), frame]
|
|
24571
|
+
});
|
|
24572
|
+
return () => {
|
|
24573
|
+
const frames = currentPromptContextFrames().filter(
|
|
24574
|
+
(candidate) => candidate.id !== frame.id
|
|
24575
|
+
);
|
|
24576
|
+
promptContextStore().enterWith(frames.length > 0 ? { frames } : void 0);
|
|
24577
|
+
};
|
|
24578
|
+
}
|
|
24579
|
+
function installPiStreamPatch(agent) {
|
|
24580
|
+
const existing = piStreamPatchStates.get(agent);
|
|
24581
|
+
if (existing) {
|
|
24582
|
+
if (agent.streamFn !== existing.wrappedStreamFn) {
|
|
24583
|
+
debugLogger.debug(
|
|
24584
|
+
"Pi Coding Agent streamFn changed while Braintrust instrumentation was active; preserving existing patch state."
|
|
24585
|
+
);
|
|
24586
|
+
}
|
|
24587
|
+
return existing;
|
|
24588
|
+
}
|
|
24589
|
+
const patchState = {
|
|
24590
|
+
activePromptStates: /* @__PURE__ */ new Set(),
|
|
24591
|
+
agent,
|
|
24592
|
+
originalStreamFn: agent.streamFn,
|
|
24593
|
+
queuedPromptStates: [],
|
|
24594
|
+
wrappedStreamFn: agent.streamFn
|
|
24595
|
+
};
|
|
24596
|
+
patchState.wrappedStreamFn = makeSharedInstrumentedStreamFn(patchState);
|
|
24597
|
+
agent.streamFn = patchState.wrappedStreamFn;
|
|
24598
|
+
piStreamPatchStates.set(agent, patchState);
|
|
24599
|
+
return patchState;
|
|
24600
|
+
}
|
|
24601
|
+
function resolveStreamPromptState(patchState, context) {
|
|
24602
|
+
let lastUserText;
|
|
24603
|
+
if (Array.isArray(context.messages)) {
|
|
24604
|
+
for (let i = context.messages.length - 1; i >= 0; i--) {
|
|
24605
|
+
const message = context.messages[i];
|
|
24606
|
+
if (isPiUserMessage(message)) {
|
|
24607
|
+
if (typeof message.content === "string") {
|
|
24608
|
+
lastUserText = message.content;
|
|
24609
|
+
} else {
|
|
24610
|
+
lastUserText = message.content.flatMap((part) => part.type === "text" ? [part.text] : []).join("");
|
|
24611
|
+
}
|
|
24612
|
+
break;
|
|
24613
|
+
}
|
|
24614
|
+
}
|
|
24615
|
+
}
|
|
24616
|
+
if (lastUserText !== void 0) {
|
|
24617
|
+
const queuedMatch = patchState.queuedPromptStates.find(
|
|
24618
|
+
(state) => state.promptText === lastUserText
|
|
24619
|
+
);
|
|
24620
|
+
if (queuedMatch) {
|
|
24621
|
+
return queuedMatch;
|
|
24622
|
+
}
|
|
24623
|
+
const matches = [...patchState.activePromptStates].filter(
|
|
24624
|
+
(state) => state.promptText === lastUserText
|
|
24625
|
+
);
|
|
24626
|
+
if (matches.length === 1) {
|
|
24627
|
+
return matches[0];
|
|
24628
|
+
}
|
|
24629
|
+
}
|
|
24630
|
+
const contextState = currentPiPromptState();
|
|
24631
|
+
if (contextState && patchState.activePromptStates.has(contextState) && (!contextState.queued || lastUserText !== void 0 && contextState.promptText === lastUserText)) {
|
|
24632
|
+
return contextState;
|
|
24633
|
+
}
|
|
24634
|
+
if (patchState.activePromptStates.size === 1) {
|
|
24635
|
+
return [...patchState.activePromptStates][0];
|
|
24636
|
+
}
|
|
24637
|
+
return void 0;
|
|
24638
|
+
}
|
|
24639
|
+
function makeSharedInstrumentedStreamFn(patchState) {
|
|
24640
|
+
return async function instrumentedPiStreamFn(model, context, options) {
|
|
24641
|
+
const state = resolveStreamPromptState(patchState, context);
|
|
24642
|
+
if (!state) {
|
|
24643
|
+
const invokeOriginal = () => Reflect.apply(patchState.originalStreamFn, this, [
|
|
24644
|
+
model,
|
|
24645
|
+
context,
|
|
24646
|
+
options
|
|
24647
|
+
]);
|
|
24648
|
+
return patchState.activePromptStates.size > 0 ? runWithAutoInstrumentationSuppressed(invokeOriginal) : invokeOriginal();
|
|
24649
|
+
}
|
|
24650
|
+
state.sawStreamFn = true;
|
|
24651
|
+
removeQueuedPromptState(state);
|
|
24652
|
+
state.streamPatchState.eventPromptState = state;
|
|
24653
|
+
const llmState = await startPiLlmSpan(state, model, context, options);
|
|
24654
|
+
try {
|
|
24655
|
+
const stream = await runWithAutoInstrumentationSuppressed(
|
|
24656
|
+
() => Reflect.apply(patchState.originalStreamFn, this, [
|
|
24657
|
+
model,
|
|
24658
|
+
context,
|
|
24659
|
+
options
|
|
24660
|
+
])
|
|
24661
|
+
);
|
|
24662
|
+
return patchAssistantMessageStream(stream, state, llmState);
|
|
24663
|
+
} catch (error) {
|
|
24664
|
+
finishPiLlmSpan(state, llmState, void 0, error);
|
|
24665
|
+
throw error;
|
|
24666
|
+
}
|
|
24667
|
+
};
|
|
24668
|
+
}
|
|
24669
|
+
async function startPiLlmSpan(state, model, context, options) {
|
|
24670
|
+
const metadata = {
|
|
24671
|
+
...extractModelMetadata2(model),
|
|
24672
|
+
...extractStreamOptionsMetadata(options),
|
|
24673
|
+
...extractToolMetadata(context.tools),
|
|
24674
|
+
"pi_coding_agent.operation": "agent.streamFn"
|
|
24675
|
+
};
|
|
24676
|
+
const span = startSpan({
|
|
24677
|
+
event: {
|
|
24678
|
+
input: processInputAttachments(normalizePiContextInput(context)),
|
|
24679
|
+
metadata
|
|
24680
|
+
},
|
|
24681
|
+
name: getLlmSpanName(model),
|
|
24682
|
+
parent: await state.span.export(),
|
|
24683
|
+
spanAttributes: { type: "llm" /* LLM */ }
|
|
24684
|
+
});
|
|
24685
|
+
const llmState = {
|
|
24686
|
+
finalized: false,
|
|
24687
|
+
metadata,
|
|
24688
|
+
metrics: {},
|
|
24689
|
+
span,
|
|
24690
|
+
startTime: getCurrentUnixTimestamp()
|
|
24691
|
+
};
|
|
24692
|
+
state.activeLlmSpans.add(llmState);
|
|
24693
|
+
return llmState;
|
|
24694
|
+
}
|
|
24695
|
+
function patchAssistantMessageStream(stream, promptState, llmState) {
|
|
24696
|
+
if (!isObject(stream)) {
|
|
24697
|
+
return stream;
|
|
24698
|
+
}
|
|
24699
|
+
const streamRecord = stream;
|
|
24700
|
+
const originalResult = stream.result;
|
|
24701
|
+
if (typeof originalResult === "function") {
|
|
24702
|
+
streamRecord.result = function patchedPiResult() {
|
|
24703
|
+
return Promise.resolve(Reflect.apply(originalResult, this, [])).then(
|
|
24704
|
+
(message) => {
|
|
24705
|
+
finishPiLlmSpan(promptState, llmState, message);
|
|
24706
|
+
return message;
|
|
24707
|
+
},
|
|
24708
|
+
(error) => {
|
|
24709
|
+
finishPiLlmSpan(promptState, llmState, void 0, error);
|
|
24710
|
+
throw error;
|
|
24711
|
+
}
|
|
24712
|
+
);
|
|
24713
|
+
};
|
|
24714
|
+
}
|
|
24715
|
+
const originalIterator = stream[Symbol.asyncIterator];
|
|
24716
|
+
if (typeof originalIterator === "function") {
|
|
24717
|
+
streamRecord[Symbol.asyncIterator] = function patchedPiIterator() {
|
|
24718
|
+
const iterator = Reflect.apply(
|
|
24719
|
+
originalIterator,
|
|
24720
|
+
this,
|
|
24721
|
+
[]
|
|
24722
|
+
);
|
|
24723
|
+
return {
|
|
24724
|
+
async next() {
|
|
24725
|
+
try {
|
|
24726
|
+
const result = await iterator.next();
|
|
24727
|
+
if (result.done) {
|
|
24728
|
+
finishPiLlmSpan(promptState, llmState);
|
|
24729
|
+
return result;
|
|
24730
|
+
}
|
|
24731
|
+
recordPiAssistantMessageEvent(promptState, llmState, result.value);
|
|
24732
|
+
return result;
|
|
24733
|
+
} catch (error) {
|
|
24734
|
+
finishPiLlmSpan(promptState, llmState, void 0, error);
|
|
24735
|
+
if (typeof iterator.return === "function") {
|
|
24736
|
+
try {
|
|
24737
|
+
await iterator.return();
|
|
24738
|
+
} catch (cleanupError) {
|
|
24739
|
+
logInstrumentationError4(
|
|
24740
|
+
"Pi Coding Agent stream cleanup",
|
|
24741
|
+
cleanupError
|
|
24742
|
+
);
|
|
24743
|
+
}
|
|
24744
|
+
}
|
|
24745
|
+
throw error;
|
|
24746
|
+
}
|
|
24747
|
+
},
|
|
24748
|
+
async return(value) {
|
|
24749
|
+
try {
|
|
24750
|
+
if (typeof iterator.return === "function") {
|
|
24751
|
+
return await iterator.return(value);
|
|
24752
|
+
}
|
|
24753
|
+
return {
|
|
24754
|
+
done: true,
|
|
24755
|
+
value
|
|
24756
|
+
};
|
|
24757
|
+
} catch (error) {
|
|
24758
|
+
finishPiLlmSpan(promptState, llmState, void 0, error);
|
|
24759
|
+
throw error;
|
|
24760
|
+
} finally {
|
|
24761
|
+
finishPiLlmSpan(promptState, llmState);
|
|
24762
|
+
}
|
|
24763
|
+
},
|
|
24764
|
+
async throw(error) {
|
|
24765
|
+
try {
|
|
24766
|
+
if (typeof iterator.throw === "function") {
|
|
24767
|
+
return await iterator.throw(error);
|
|
24768
|
+
}
|
|
24769
|
+
throw error;
|
|
24770
|
+
} catch (thrownError) {
|
|
24771
|
+
finishPiLlmSpan(promptState, llmState, void 0, thrownError);
|
|
24772
|
+
throw thrownError;
|
|
24773
|
+
}
|
|
24774
|
+
},
|
|
24775
|
+
[Symbol.asyncIterator]() {
|
|
24776
|
+
return this;
|
|
24777
|
+
}
|
|
24778
|
+
};
|
|
24779
|
+
};
|
|
24780
|
+
}
|
|
24781
|
+
return stream;
|
|
24782
|
+
}
|
|
24783
|
+
function recordPiAssistantMessageEvent(promptState, llmState, event) {
|
|
24784
|
+
recordFirstTokenMetric(llmState, event);
|
|
24785
|
+
const message = "message" in event ? event.message : void 0;
|
|
24786
|
+
const errorMessage2 = "error" in event ? event.error : void 0;
|
|
24787
|
+
if (event.type === "done" && isPiAssistantMessage(message)) {
|
|
24788
|
+
finishPiLlmSpan(promptState, llmState, message);
|
|
24789
|
+
} else if (event.type === "error" && isPiAssistantMessage(errorMessage2)) {
|
|
24790
|
+
finishPiLlmSpan(promptState, llmState, errorMessage2);
|
|
24791
|
+
}
|
|
24792
|
+
}
|
|
24793
|
+
function recordFirstTokenMetric(state, event) {
|
|
24794
|
+
if (state.metrics.time_to_first_token !== void 0 || event.type === "start") {
|
|
24795
|
+
return;
|
|
24796
|
+
}
|
|
24797
|
+
state.metrics.time_to_first_token = getCurrentUnixTimestamp() - state.startTime;
|
|
24798
|
+
}
|
|
24799
|
+
async function handlePiAgentEvent(state, event) {
|
|
24800
|
+
if (state.finalized) {
|
|
24801
|
+
return;
|
|
24802
|
+
}
|
|
24803
|
+
const eventPromptState = state.streamPatchState.eventPromptState;
|
|
24804
|
+
if (eventPromptState && eventPromptState !== state) {
|
|
24805
|
+
return;
|
|
24806
|
+
}
|
|
24807
|
+
if (!eventPromptState && (state.queued || state.streamPatchState.activePromptStates.size > 1 && currentPiPromptState() !== state)) {
|
|
24808
|
+
return;
|
|
24809
|
+
}
|
|
24810
|
+
switch (event.type) {
|
|
24811
|
+
case "message_end":
|
|
24812
|
+
if (isPiAssistantMessage(event.message)) {
|
|
24813
|
+
state.output = extractAssistantOutput(event.message);
|
|
24814
|
+
}
|
|
24815
|
+
return;
|
|
24816
|
+
case "turn_end":
|
|
24817
|
+
state.turnEnded = true;
|
|
24818
|
+
if (isPiAssistantMessage(event.message)) {
|
|
24819
|
+
state.output = extractAssistantOutput(event.message);
|
|
24820
|
+
if (!state.collectedLlmUsageMetrics) {
|
|
24821
|
+
addMetrics(state.metrics, extractUsageMetrics2(event.message.usage));
|
|
24822
|
+
}
|
|
24823
|
+
}
|
|
24824
|
+
if (state.streamPatchState.eventPromptState === state) {
|
|
24825
|
+
state.streamPatchState.eventPromptState = void 0;
|
|
24826
|
+
}
|
|
24827
|
+
if (state.promptCallEnded && state.deferCompletionUntilTurnEnd) {
|
|
24828
|
+
await finalizePiPromptRun(state);
|
|
24829
|
+
}
|
|
24830
|
+
return;
|
|
24831
|
+
case "tool_execution_start":
|
|
24832
|
+
await startPiToolSpan(state, event);
|
|
24833
|
+
return;
|
|
24834
|
+
case "tool_execution_end":
|
|
24835
|
+
finishPiToolSpan(state, event);
|
|
24836
|
+
return;
|
|
24837
|
+
default:
|
|
24838
|
+
return;
|
|
24839
|
+
}
|
|
24840
|
+
}
|
|
24841
|
+
async function startPiToolSpan(state, event) {
|
|
24842
|
+
if (!event.toolCallId || state.activeToolSpans.has(event.toolCallId)) {
|
|
24843
|
+
return;
|
|
24844
|
+
}
|
|
24845
|
+
const restoreAutoInstrumentation = enterAutoInstrumentationAllowed();
|
|
24846
|
+
const metadata = {
|
|
24847
|
+
"gen_ai.tool.call.id": event.toolCallId,
|
|
24848
|
+
"gen_ai.tool.name": event.toolName,
|
|
24849
|
+
"pi_coding_agent.tool.name": event.toolName
|
|
24850
|
+
};
|
|
24851
|
+
try {
|
|
24852
|
+
const span = startSpan({
|
|
24853
|
+
event: {
|
|
24854
|
+
input: event.args,
|
|
24855
|
+
metadata
|
|
24856
|
+
},
|
|
24857
|
+
name: event.toolName || "tool",
|
|
24858
|
+
parent: await state.span.export(),
|
|
24859
|
+
spanAttributes: { type: "tool" /* TOOL */ }
|
|
24860
|
+
});
|
|
24861
|
+
state.activeToolSpans.set(event.toolCallId, {
|
|
24862
|
+
restoreAutoInstrumentation,
|
|
24863
|
+
span
|
|
24864
|
+
});
|
|
24865
|
+
} catch (error) {
|
|
24866
|
+
restoreAutoInstrumentation();
|
|
24867
|
+
throw error;
|
|
24868
|
+
}
|
|
24869
|
+
}
|
|
24870
|
+
function finishPiToolSpan(state, event) {
|
|
24871
|
+
const toolState = state.activeToolSpans.get(event.toolCallId);
|
|
24872
|
+
if (!toolState) {
|
|
24873
|
+
return;
|
|
24874
|
+
}
|
|
24875
|
+
state.activeToolSpans.delete(event.toolCallId);
|
|
24876
|
+
const metadata = {
|
|
24877
|
+
"gen_ai.tool.call.id": event.toolCallId,
|
|
24878
|
+
"gen_ai.tool.name": event.toolName,
|
|
24879
|
+
"pi_coding_agent.tool.name": event.toolName,
|
|
24880
|
+
"pi_coding_agent.tool.is_error": event.isError
|
|
24881
|
+
};
|
|
24882
|
+
try {
|
|
24883
|
+
safeLog4(toolState.span, {
|
|
24884
|
+
...event.isError ? { error: stringifyUnknown2(event.result) } : {},
|
|
24885
|
+
metadata,
|
|
24886
|
+
output: event.result
|
|
24887
|
+
});
|
|
24888
|
+
} finally {
|
|
24889
|
+
try {
|
|
24890
|
+
toolState.span.end();
|
|
24891
|
+
} finally {
|
|
24892
|
+
toolState.restoreAutoInstrumentation?.();
|
|
24893
|
+
}
|
|
24894
|
+
}
|
|
24895
|
+
}
|
|
24896
|
+
async function finalizePiPromptRun(state, error) {
|
|
24897
|
+
if (state.finalized) {
|
|
24898
|
+
return;
|
|
24899
|
+
}
|
|
24900
|
+
state.finalized = true;
|
|
24901
|
+
state.onFinalize?.(state);
|
|
24902
|
+
restorePiStreamFn(state);
|
|
24903
|
+
try {
|
|
24904
|
+
state.unsubscribeAgent?.();
|
|
24905
|
+
} catch (unsubscribeError) {
|
|
24906
|
+
logInstrumentationError4("Pi Coding Agent unsubscribe", unsubscribeError);
|
|
24907
|
+
}
|
|
24908
|
+
await finishOpenLlmSpans(state, error);
|
|
24909
|
+
finishOpenToolSpans(state, error);
|
|
24910
|
+
const metadata = {
|
|
24911
|
+
...state.metadata,
|
|
24912
|
+
...extractModelMetadata2(state.agent.state?.model)
|
|
24913
|
+
};
|
|
24914
|
+
try {
|
|
24915
|
+
safeLog4(state.span, {
|
|
24916
|
+
...error ? { error: stringifyUnknown2(error) } : {},
|
|
24917
|
+
metadata,
|
|
24918
|
+
metrics: {
|
|
24919
|
+
...cleanMetrics5(state.metrics),
|
|
24920
|
+
...buildDurationMetrics3(state.startTime)
|
|
24921
|
+
},
|
|
24922
|
+
output: state.output
|
|
24923
|
+
});
|
|
24924
|
+
} finally {
|
|
24925
|
+
state.span.end();
|
|
24926
|
+
}
|
|
24927
|
+
}
|
|
24928
|
+
function restorePiStreamFn(state) {
|
|
24929
|
+
const patchState = state.streamPatchState;
|
|
24930
|
+
patchState.activePromptStates.delete(state);
|
|
24931
|
+
removeQueuedPromptState(state);
|
|
24932
|
+
if (patchState.eventPromptState === state) {
|
|
24933
|
+
patchState.eventPromptState = void 0;
|
|
24934
|
+
}
|
|
24935
|
+
state.restorePromptContext?.();
|
|
24936
|
+
if (patchState.activePromptStates.size > 0) {
|
|
24937
|
+
return;
|
|
24938
|
+
}
|
|
24939
|
+
if (patchState.agent.streamFn === patchState.wrappedStreamFn) {
|
|
24940
|
+
patchState.agent.streamFn = patchState.originalStreamFn;
|
|
24941
|
+
}
|
|
24942
|
+
piStreamPatchStates.delete(patchState.agent);
|
|
24943
|
+
}
|
|
24944
|
+
function removeQueuedPromptState(state) {
|
|
24945
|
+
state.queued = false;
|
|
24946
|
+
const queuedPromptStates = state.streamPatchState.queuedPromptStates;
|
|
24947
|
+
const index = queuedPromptStates.indexOf(state);
|
|
24948
|
+
if (index >= 0) {
|
|
24949
|
+
queuedPromptStates.splice(index, 1);
|
|
24950
|
+
}
|
|
24951
|
+
}
|
|
24952
|
+
async function finishOpenLlmSpans(state, error) {
|
|
24953
|
+
for (const llmState of [...state.activeLlmSpans]) {
|
|
24954
|
+
finishPiLlmSpan(state, llmState, void 0, error);
|
|
24955
|
+
}
|
|
24956
|
+
}
|
|
24957
|
+
function finishPiLlmSpan(promptState, llmState, message, error) {
|
|
24958
|
+
if (llmState.finalized) {
|
|
24959
|
+
return;
|
|
24960
|
+
}
|
|
24961
|
+
llmState.finalized = true;
|
|
24962
|
+
promptState.activeLlmSpans.delete(llmState);
|
|
24963
|
+
const messageError = message?.stopReason === "error" && message.errorMessage;
|
|
24964
|
+
const metrics = {
|
|
24965
|
+
...extractUsageMetrics2(message?.usage),
|
|
24966
|
+
...cleanMetrics5(llmState.metrics),
|
|
24967
|
+
...buildDurationMetrics3(llmState.startTime)
|
|
24968
|
+
};
|
|
24969
|
+
const usageMetrics = extractUsageMetrics2(message?.usage);
|
|
24970
|
+
if (Object.keys(usageMetrics).length > 0) {
|
|
24971
|
+
promptState.collectedLlmUsageMetrics = true;
|
|
24972
|
+
addMetrics(promptState.metrics, usageMetrics);
|
|
24973
|
+
}
|
|
24974
|
+
try {
|
|
24975
|
+
safeLog4(llmState.span, {
|
|
24976
|
+
...error || messageError ? { error: stringifyUnknown2(error ?? messageError) } : {},
|
|
24977
|
+
metadata: {
|
|
24978
|
+
...llmState.metadata,
|
|
24979
|
+
...message ? extractAssistantMetadata(message) : {}
|
|
24980
|
+
},
|
|
24981
|
+
metrics,
|
|
24982
|
+
...message ? { output: extractAssistantOutput(message) } : {}
|
|
24983
|
+
});
|
|
24984
|
+
} finally {
|
|
24985
|
+
llmState.span.end();
|
|
24986
|
+
}
|
|
24987
|
+
}
|
|
24988
|
+
function finishOpenToolSpans(state, error) {
|
|
24989
|
+
for (const [, toolState] of state.activeToolSpans) {
|
|
24990
|
+
try {
|
|
24991
|
+
safeLog4(toolState.span, {
|
|
24992
|
+
error: error ? stringifyUnknown2(error) : "Pi tool did not complete"
|
|
24993
|
+
});
|
|
24994
|
+
toolState.span.end();
|
|
24995
|
+
} finally {
|
|
24996
|
+
toolState.restoreAutoInstrumentation?.();
|
|
24997
|
+
}
|
|
24998
|
+
}
|
|
24999
|
+
state.activeToolSpans.clear();
|
|
25000
|
+
}
|
|
25001
|
+
function normalizePiContextInput(context) {
|
|
25002
|
+
const messages = context.messages.flatMap(
|
|
25003
|
+
(message) => normalizePiMessage(message)
|
|
25004
|
+
);
|
|
25005
|
+
if (context.systemPrompt) {
|
|
25006
|
+
return [{ role: "system", content: context.systemPrompt }, ...messages];
|
|
25007
|
+
}
|
|
25008
|
+
return messages;
|
|
25009
|
+
}
|
|
25010
|
+
function normalizePiMessage(message) {
|
|
25011
|
+
if (isPiUserMessage(message)) {
|
|
25012
|
+
return [
|
|
25013
|
+
{
|
|
25014
|
+
role: "user",
|
|
25015
|
+
content: normalizeUserContent(message.content)
|
|
25016
|
+
}
|
|
25017
|
+
];
|
|
25018
|
+
}
|
|
25019
|
+
if (isPiAssistantMessage(message)) {
|
|
25020
|
+
return [normalizeAssistantMessage(message)];
|
|
25021
|
+
}
|
|
25022
|
+
if (isPiToolResultMessage(message)) {
|
|
25023
|
+
return [normalizeToolResultMessage(message)];
|
|
25024
|
+
}
|
|
25025
|
+
return [];
|
|
25026
|
+
}
|
|
25027
|
+
function normalizeAssistantMessage(message) {
|
|
25028
|
+
const text = message.content.flatMap((part) => part.type === "text" ? [part.text] : []).join("");
|
|
25029
|
+
const thinking = message.content.flatMap(
|
|
25030
|
+
(part) => part.type === "thinking" && !part.redacted ? [part.thinking] : []
|
|
25031
|
+
).join("");
|
|
25032
|
+
const toolCalls = message.content.flatMap(
|
|
25033
|
+
(part) => part.type === "toolCall" ? [normalizeToolCall(part)] : []
|
|
25034
|
+
);
|
|
25035
|
+
return {
|
|
25036
|
+
role: "assistant",
|
|
25037
|
+
content: text || (toolCalls.length > 0 ? null : ""),
|
|
25038
|
+
...thinking ? { reasoning: thinking } : {},
|
|
25039
|
+
...toolCalls.length > 0 ? { tool_calls: toolCalls } : {}
|
|
25040
|
+
};
|
|
25041
|
+
}
|
|
25042
|
+
function normalizeToolResultMessage(message) {
|
|
25043
|
+
return {
|
|
25044
|
+
role: "tool",
|
|
25045
|
+
tool_call_id: message.toolCallId,
|
|
25046
|
+
content: normalizeUserContent(message.content)
|
|
25047
|
+
};
|
|
25048
|
+
}
|
|
25049
|
+
function normalizeUserContent(content) {
|
|
25050
|
+
if (typeof content === "string") {
|
|
25051
|
+
return content;
|
|
25052
|
+
}
|
|
25053
|
+
return content.map((part) => {
|
|
25054
|
+
if (part.type === "text") {
|
|
25055
|
+
return { type: "text", text: part.text };
|
|
25056
|
+
}
|
|
25057
|
+
if (part.type === "image") {
|
|
25058
|
+
return {
|
|
25059
|
+
type: "image_url",
|
|
25060
|
+
image_url: {
|
|
25061
|
+
url: `data:${part.mimeType};base64,${part.data}`
|
|
25062
|
+
}
|
|
25063
|
+
};
|
|
25064
|
+
}
|
|
25065
|
+
return part;
|
|
25066
|
+
});
|
|
25067
|
+
}
|
|
25068
|
+
function normalizeToolCall(toolCall) {
|
|
25069
|
+
return {
|
|
25070
|
+
id: toolCall.id,
|
|
25071
|
+
type: "function",
|
|
25072
|
+
function: {
|
|
25073
|
+
name: toolCall.name,
|
|
25074
|
+
arguments: stringifyArguments(toolCall.arguments)
|
|
25075
|
+
}
|
|
25076
|
+
};
|
|
25077
|
+
}
|
|
25078
|
+
function extractAssistantOutput(message) {
|
|
25079
|
+
return processInputAttachments([
|
|
25080
|
+
{
|
|
25081
|
+
finish_reason: normalizeStopReason(message.stopReason),
|
|
25082
|
+
index: 0,
|
|
25083
|
+
message: normalizeAssistantMessage(message)
|
|
25084
|
+
}
|
|
25085
|
+
]);
|
|
25086
|
+
}
|
|
25087
|
+
function isPiUserMessage(message) {
|
|
25088
|
+
return message.role === "user" && "content" in message;
|
|
25089
|
+
}
|
|
25090
|
+
function isPiAssistantMessage(message) {
|
|
25091
|
+
return isObject(message) && message.role === "assistant" && Array.isArray(message.content);
|
|
25092
|
+
}
|
|
25093
|
+
function isPiToolResultMessage(message) {
|
|
25094
|
+
return message.role === "toolResult" && Array.isArray(message.content);
|
|
25095
|
+
}
|
|
25096
|
+
function normalizeStopReason(reason) {
|
|
25097
|
+
switch (reason) {
|
|
25098
|
+
case "toolUse":
|
|
25099
|
+
return "tool_calls";
|
|
25100
|
+
case "length":
|
|
25101
|
+
case "stop":
|
|
25102
|
+
return reason;
|
|
25103
|
+
default:
|
|
25104
|
+
return reason ?? "stop";
|
|
25105
|
+
}
|
|
25106
|
+
}
|
|
25107
|
+
function extractPromptInput(text, options) {
|
|
25108
|
+
const images = options?.images;
|
|
25109
|
+
if (!images || images.length === 0) {
|
|
25110
|
+
return text;
|
|
25111
|
+
}
|
|
25112
|
+
return processInputAttachments([
|
|
25113
|
+
{
|
|
25114
|
+
role: "user",
|
|
25115
|
+
content: [
|
|
25116
|
+
{ type: "text", text: text ?? "" },
|
|
25117
|
+
...images.map((image) => ({
|
|
25118
|
+
type: "image_url",
|
|
25119
|
+
image_url: {
|
|
25120
|
+
url: `data:${image.mimeType};base64,${image.data}`
|
|
25121
|
+
}
|
|
25122
|
+
}))
|
|
25123
|
+
]
|
|
25124
|
+
}
|
|
25125
|
+
]);
|
|
25126
|
+
}
|
|
25127
|
+
function extractToolMetadata(tools) {
|
|
25128
|
+
if (!tools || tools.length === 0) {
|
|
25129
|
+
return {};
|
|
25130
|
+
}
|
|
25131
|
+
return {
|
|
25132
|
+
tools: tools.map((tool) => ({
|
|
25133
|
+
type: "function",
|
|
25134
|
+
function: {
|
|
25135
|
+
name: tool.name,
|
|
25136
|
+
...tool.description ? { description: tool.description } : {},
|
|
25137
|
+
...tool.parameters ? { parameters: tool.parameters } : {}
|
|
25138
|
+
}
|
|
25139
|
+
}))
|
|
25140
|
+
};
|
|
25141
|
+
}
|
|
25142
|
+
function extractModelMetadata2(model) {
|
|
25143
|
+
if (!model) {
|
|
25144
|
+
return {};
|
|
25145
|
+
}
|
|
25146
|
+
return {
|
|
25147
|
+
...model.provider ? { provider: model.provider } : {},
|
|
25148
|
+
...model.id ? { model: model.id, "pi_coding_agent.model": model.id } : {},
|
|
25149
|
+
...model.api ? { "pi_coding_agent.api": model.api } : {},
|
|
25150
|
+
...model.name ? { "pi_coding_agent.model_name": model.name } : {}
|
|
25151
|
+
};
|
|
25152
|
+
}
|
|
25153
|
+
function extractAssistantMetadata(message) {
|
|
25154
|
+
return {
|
|
25155
|
+
...message.provider ? { provider: message.provider } : {},
|
|
25156
|
+
...message.responseModel || message.model ? { model: message.responseModel ?? message.model } : {},
|
|
25157
|
+
...message.api ? { "pi_coding_agent.api": message.api } : {},
|
|
25158
|
+
...message.model ? { "pi_coding_agent.model": message.model } : {},
|
|
25159
|
+
...message.responseModel ? { "pi_coding_agent.response_model": message.responseModel } : {},
|
|
25160
|
+
...message.responseId ? { "pi_coding_agent.response_id": message.responseId } : {},
|
|
25161
|
+
...message.stopReason ? { "pi_coding_agent.stop_reason": message.stopReason } : {}
|
|
25162
|
+
};
|
|
25163
|
+
}
|
|
25164
|
+
function extractSessionMetadata(session) {
|
|
25165
|
+
return {
|
|
25166
|
+
...extractModelMetadata2(session.model),
|
|
25167
|
+
...session.sessionId ? { "pi_coding_agent.session_id": session.sessionId } : {},
|
|
25168
|
+
...session.sessionName ? { "pi_coding_agent.session_name": session.sessionName } : {},
|
|
25169
|
+
...session.thinkingLevel ? { "pi_coding_agent.thinking_level": session.thinkingLevel } : {},
|
|
25170
|
+
...typeof session.getActiveToolNames === "function" ? { "pi_coding_agent.active_tools": session.getActiveToolNames() } : {}
|
|
25171
|
+
};
|
|
25172
|
+
}
|
|
25173
|
+
function extractPromptOptionsMetadata(options) {
|
|
25174
|
+
if (!options) {
|
|
25175
|
+
return {};
|
|
25176
|
+
}
|
|
25177
|
+
return {
|
|
25178
|
+
...options.source ? { "pi_coding_agent.source": options.source } : {},
|
|
25179
|
+
...options.streamingBehavior ? { "pi_coding_agent.streaming_behavior": options.streamingBehavior } : {},
|
|
25180
|
+
...options.expandPromptTemplates !== void 0 ? {
|
|
25181
|
+
"pi_coding_agent.expand_prompt_templates": options.expandPromptTemplates
|
|
25182
|
+
} : {}
|
|
25183
|
+
};
|
|
25184
|
+
}
|
|
25185
|
+
function extractStreamOptionsMetadata(options) {
|
|
25186
|
+
if (!options) {
|
|
25187
|
+
return {};
|
|
25188
|
+
}
|
|
25189
|
+
return {
|
|
25190
|
+
...options.temperature !== void 0 ? { temperature: options.temperature } : {},
|
|
25191
|
+
...options.maxTokens !== void 0 ? { max_tokens: options.maxTokens } : {},
|
|
25192
|
+
...options.reasoning ? { "pi_coding_agent.reasoning": options.reasoning } : {},
|
|
25193
|
+
...options.transport ? { "pi_coding_agent.transport": options.transport } : {},
|
|
25194
|
+
...options.cacheRetention ? { "pi_coding_agent.cache_retention": options.cacheRetention } : {},
|
|
25195
|
+
...options.sessionId ? { "pi_coding_agent.session_id": options.sessionId } : {},
|
|
25196
|
+
...options.timeoutMs !== void 0 ? { "pi_coding_agent.timeout_ms": options.timeoutMs } : {},
|
|
25197
|
+
...options.maxRetries !== void 0 ? { "pi_coding_agent.max_retries": options.maxRetries } : {},
|
|
25198
|
+
...options.maxRetryDelayMs !== void 0 ? { "pi_coding_agent.max_retry_delay_ms": options.maxRetryDelayMs } : {},
|
|
25199
|
+
...options.metadata ? { "pi_coding_agent.metadata": options.metadata } : {}
|
|
25200
|
+
};
|
|
25201
|
+
}
|
|
25202
|
+
function getLlmSpanName(model) {
|
|
25203
|
+
switch (model.api) {
|
|
25204
|
+
case "anthropic-messages":
|
|
25205
|
+
return "anthropic.messages.create";
|
|
25206
|
+
case "openai-completions":
|
|
25207
|
+
return "Chat Completion";
|
|
25208
|
+
case "openai-responses":
|
|
25209
|
+
case "azure-openai-responses":
|
|
25210
|
+
case "openai-codex-responses":
|
|
25211
|
+
return "openai.responses.create";
|
|
25212
|
+
case "google-generative-ai":
|
|
25213
|
+
case "google-vertex":
|
|
25214
|
+
return "generate_content";
|
|
25215
|
+
case "mistral-conversations":
|
|
25216
|
+
return "mistral.chat.stream";
|
|
25217
|
+
case "bedrock-converse-stream":
|
|
25218
|
+
return "bedrock.converse_stream";
|
|
25219
|
+
default:
|
|
25220
|
+
return "pi_ai.streamSimple";
|
|
25221
|
+
}
|
|
25222
|
+
}
|
|
25223
|
+
function extractUsageMetrics2(usage) {
|
|
25224
|
+
if (!usage) {
|
|
25225
|
+
return {};
|
|
25226
|
+
}
|
|
25227
|
+
return cleanMetrics5({
|
|
25228
|
+
completion_tokens: usage.output,
|
|
25229
|
+
prompt_cache_creation_tokens: usage.cacheWrite,
|
|
25230
|
+
prompt_cached_tokens: usage.cacheRead,
|
|
25231
|
+
prompt_tokens: usage.input,
|
|
25232
|
+
tokens: usage.totalTokens ?? usage.tokens
|
|
25233
|
+
});
|
|
25234
|
+
}
|
|
25235
|
+
function addMetrics(target, source) {
|
|
25236
|
+
for (const [key, value] of Object.entries(source)) {
|
|
25237
|
+
target[key] = (target[key] ?? 0) + value;
|
|
25238
|
+
}
|
|
25239
|
+
}
|
|
25240
|
+
function buildDurationMetrics3(startTime) {
|
|
25241
|
+
const end = getCurrentUnixTimestamp();
|
|
25242
|
+
return {
|
|
25243
|
+
duration: end - startTime,
|
|
25244
|
+
end,
|
|
25245
|
+
start: startTime
|
|
25246
|
+
};
|
|
25247
|
+
}
|
|
25248
|
+
function cleanMetrics5(metrics) {
|
|
25249
|
+
const cleaned = {};
|
|
25250
|
+
for (const [key, value] of Object.entries(metrics)) {
|
|
25251
|
+
if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
|
|
25252
|
+
cleaned[key] = value;
|
|
25253
|
+
}
|
|
25254
|
+
}
|
|
25255
|
+
return cleaned;
|
|
25256
|
+
}
|
|
25257
|
+
function stringifyArguments(value) {
|
|
25258
|
+
if (typeof value === "string") {
|
|
25259
|
+
return value;
|
|
25260
|
+
}
|
|
25261
|
+
try {
|
|
25262
|
+
return JSON.stringify(value);
|
|
25263
|
+
} catch {
|
|
25264
|
+
return stringifyUnknown2(value);
|
|
25265
|
+
}
|
|
25266
|
+
}
|
|
25267
|
+
function stringifyUnknown2(value) {
|
|
25268
|
+
if (value instanceof Error) {
|
|
25269
|
+
return value.message;
|
|
25270
|
+
}
|
|
25271
|
+
if (typeof value === "string") {
|
|
25272
|
+
return value;
|
|
25273
|
+
}
|
|
25274
|
+
try {
|
|
25275
|
+
return JSON.stringify(value);
|
|
25276
|
+
} catch {
|
|
25277
|
+
return String(value);
|
|
25278
|
+
}
|
|
25279
|
+
}
|
|
25280
|
+
function safeLog4(span, event) {
|
|
25281
|
+
try {
|
|
25282
|
+
span.log(event);
|
|
25283
|
+
} catch (error) {
|
|
25284
|
+
logInstrumentationError4("Pi Coding Agent span log", error);
|
|
25285
|
+
}
|
|
25286
|
+
}
|
|
25287
|
+
function logInstrumentationError4(context, error) {
|
|
25288
|
+
debugLogger.debug(`${context}:`, error);
|
|
25289
|
+
}
|
|
25290
|
+
|
|
23240
25291
|
// src/instrumentation/braintrust-plugin.ts
|
|
23241
25292
|
function getIntegrationConfig(integrations, key) {
|
|
23242
25293
|
return integrations[key];
|
|
@@ -23262,6 +25313,7 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
23262
25313
|
gitHubCopilotPlugin = null;
|
|
23263
25314
|
fluePlugin = null;
|
|
23264
25315
|
langChainPlugin = null;
|
|
25316
|
+
piCodingAgentPlugin = null;
|
|
23265
25317
|
constructor(config = {}) {
|
|
23266
25318
|
super();
|
|
23267
25319
|
this.config = config;
|
|
@@ -23336,6 +25388,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
23336
25388
|
this.gitHubCopilotPlugin = new GitHubCopilotPlugin();
|
|
23337
25389
|
this.gitHubCopilotPlugin.enable();
|
|
23338
25390
|
}
|
|
25391
|
+
if (integrations.piCodingAgent !== false) {
|
|
25392
|
+
this.piCodingAgentPlugin = new PiCodingAgentPlugin();
|
|
25393
|
+
this.piCodingAgentPlugin.enable();
|
|
25394
|
+
}
|
|
23339
25395
|
if (getIntegrationConfig(integrations, "flue") !== false) {
|
|
23340
25396
|
this.fluePlugin = new FluePlugin();
|
|
23341
25397
|
this.fluePlugin.enable();
|
|
@@ -23414,6 +25470,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
23414
25470
|
this.gitHubCopilotPlugin.disable();
|
|
23415
25471
|
this.gitHubCopilotPlugin = null;
|
|
23416
25472
|
}
|
|
25473
|
+
if (this.piCodingAgentPlugin) {
|
|
25474
|
+
this.piCodingAgentPlugin.disable();
|
|
25475
|
+
this.piCodingAgentPlugin = null;
|
|
25476
|
+
}
|
|
23417
25477
|
if (this.fluePlugin) {
|
|
23418
25478
|
this.fluePlugin.disable();
|
|
23419
25479
|
this.fluePlugin = null;
|
|
@@ -23433,6 +25493,11 @@ var envIntegrationAliases = {
|
|
|
23433
25493
|
openaicodexsdk: "openaiCodexSDK",
|
|
23434
25494
|
codex: "openaiCodexSDK",
|
|
23435
25495
|
"codex-sdk": "openaiCodexSDK",
|
|
25496
|
+
"pi-coding-agent": "piCodingAgent",
|
|
25497
|
+
"pi-coding-agent-sdk": "piCodingAgent",
|
|
25498
|
+
picodingagent: "piCodingAgent",
|
|
25499
|
+
picodingagentsdk: "piCodingAgent",
|
|
25500
|
+
"@earendil-works/pi-coding-agent": "piCodingAgent",
|
|
23436
25501
|
anthropic: "anthropic",
|
|
23437
25502
|
aisdk: "aisdk",
|
|
23438
25503
|
"ai-sdk": "aisdk",
|
|
@@ -23498,7 +25563,8 @@ function getDefaultInstrumentationIntegrations() {
|
|
|
23498
25563
|
genkit: true,
|
|
23499
25564
|
gitHubCopilot: true,
|
|
23500
25565
|
langchain: true,
|
|
23501
|
-
langgraph: true
|
|
25566
|
+
langgraph: true,
|
|
25567
|
+
piCodingAgent: true
|
|
23502
25568
|
};
|
|
23503
25569
|
}
|
|
23504
25570
|
function readDisabledInstrumentationEnvConfig(disabledList) {
|