braintrust 3.17.0 → 3.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dev/dist/index.d.mts +13 -0
- package/dev/dist/index.d.ts +13 -0
- package/dev/dist/index.js +4300 -2199
- package/dev/dist/index.mjs +2211 -110
- package/dist/apply-auto-instrumentation.js +238 -186
- package/dist/apply-auto-instrumentation.mjs +68 -16
- package/dist/auto-instrumentations/bundler/esbuild.cjs +90 -15
- package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
- package/dist/auto-instrumentations/bundler/next.cjs +90 -15
- package/dist/auto-instrumentations/bundler/next.mjs +3 -3
- package/dist/auto-instrumentations/bundler/rollup.cjs +90 -15
- package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
- package/dist/auto-instrumentations/bundler/vite.cjs +90 -15
- package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
- package/dist/auto-instrumentations/bundler/webpack-loader.cjs +89 -14
- package/dist/auto-instrumentations/bundler/webpack.cjs +90 -15
- package/dist/auto-instrumentations/bundler/webpack.mjs +3 -3
- package/dist/auto-instrumentations/{chunk-VXJONZVX.mjs → chunk-GNUEZ2PE.mjs} +13 -3
- package/dist/auto-instrumentations/{chunk-CNQ7BUKN.mjs → chunk-MYCHHXOE.mjs} +1 -1
- package/dist/auto-instrumentations/{chunk-E5DUYJWK.mjs → chunk-ZYKZEMRT.mjs} +82 -15
- package/dist/auto-instrumentations/hook.mjs +102 -15
- package/dist/auto-instrumentations/index.cjs +84 -16
- package/dist/auto-instrumentations/index.d.mts +3 -1
- package/dist/auto-instrumentations/index.d.ts +3 -1
- package/dist/auto-instrumentations/index.mjs +5 -3
- package/dist/auto-instrumentations/loader/cjs-patch.cjs +1 -1
- package/dist/auto-instrumentations/loader/cjs-patch.mjs +1 -1
- package/dist/auto-instrumentations/loader/esm-hook.mjs +1 -1
- package/dist/browser.d.mts +177 -11
- package/dist/browser.d.ts +177 -11
- package/dist/browser.js +2296 -104
- package/dist/browser.mjs +2455 -263
- package/dist/{chunk-VMBQETG3.js → chunk-73IYIIOL.js} +28 -2
- package/dist/{chunk-O4ZIWXO3.mjs → chunk-BYFADLEZ.mjs} +27 -1
- package/dist/cli.js +2219 -118
- package/dist/edge-light.d.mts +1 -1
- package/dist/edge-light.d.ts +1 -1
- package/dist/edge-light.js +2296 -104
- package/dist/edge-light.mjs +2455 -263
- package/dist/index.d.mts +177 -11
- package/dist/index.d.ts +177 -11
- package/dist/index.js +3296 -1128
- package/dist/index.mjs +2272 -104
- package/dist/instrumentation/index.d.mts +3 -0
- package/dist/instrumentation/index.d.ts +3 -0
- package/dist/instrumentation/index.js +2171 -105
- package/dist/instrumentation/index.mjs +2171 -105
- package/dist/workerd.d.mts +1 -1
- package/dist/workerd.d.ts +1 -1
- package/dist/workerd.js +2296 -104
- package/dist/workerd.mjs +2455 -263
- package/package.json +10 -10
package/dev/dist/index.mjs
CHANGED
|
@@ -7936,6 +7936,10 @@ var Experiment2 = class extends ObjectFetcher {
|
|
|
7936
7936
|
return (await this.lazyMetadata.get()).project;
|
|
7937
7937
|
})();
|
|
7938
7938
|
}
|
|
7939
|
+
async _getBaseExperimentId() {
|
|
7940
|
+
const baseExperimentId = (await this.lazyMetadata.get()).experiment.fullInfo["base_exp_id"];
|
|
7941
|
+
return typeof baseExperimentId === "string" && baseExperimentId ? baseExperimentId : void 0;
|
|
7942
|
+
}
|
|
7939
7943
|
parentObjectType() {
|
|
7940
7944
|
return 1 /* EXPERIMENT */;
|
|
7941
7945
|
}
|
|
@@ -8076,6 +8080,14 @@ var Experiment2 = class extends ObjectFetcher {
|
|
|
8076
8080
|
comparisonExperimentId = baseExperiment.id;
|
|
8077
8081
|
comparisonExperimentName = baseExperiment.name;
|
|
8078
8082
|
}
|
|
8083
|
+
} else {
|
|
8084
|
+
try {
|
|
8085
|
+
const comparisonExperiment = await state.apiConn().get_json(`v1/experiment/${comparisonExperimentId}`);
|
|
8086
|
+
if (typeof comparisonExperiment["name"] === "string") {
|
|
8087
|
+
comparisonExperimentName = comparisonExperiment["name"];
|
|
8088
|
+
}
|
|
8089
|
+
} catch {
|
|
8090
|
+
}
|
|
8079
8091
|
}
|
|
8080
8092
|
try {
|
|
8081
8093
|
const results = await state.apiConn().get_json(
|
|
@@ -10021,6 +10033,64 @@ var BasePlugin = class {
|
|
|
10021
10033
|
}
|
|
10022
10034
|
};
|
|
10023
10035
|
|
|
10036
|
+
// src/instrumentation/auto-instrumentation-suppression.ts
|
|
10037
|
+
var autoInstrumentationSuppressionStore;
|
|
10038
|
+
function suppressionStore() {
|
|
10039
|
+
autoInstrumentationSuppressionStore ??= isomorph_default.newAsyncLocalStorage();
|
|
10040
|
+
return autoInstrumentationSuppressionStore;
|
|
10041
|
+
}
|
|
10042
|
+
function currentFrames() {
|
|
10043
|
+
return suppressionStore().getStore()?.frames ?? [];
|
|
10044
|
+
}
|
|
10045
|
+
function isAutoInstrumentationSuppressed() {
|
|
10046
|
+
const frames = currentFrames();
|
|
10047
|
+
return frames[frames.length - 1]?.mode === "suppress";
|
|
10048
|
+
}
|
|
10049
|
+
function runWithAutoInstrumentationSuppressed(callback) {
|
|
10050
|
+
const frame = {
|
|
10051
|
+
id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
|
|
10052
|
+
mode: "suppress"
|
|
10053
|
+
};
|
|
10054
|
+
return suppressionStore().run(
|
|
10055
|
+
{ frames: [...currentFrames(), frame] },
|
|
10056
|
+
callback
|
|
10057
|
+
);
|
|
10058
|
+
}
|
|
10059
|
+
function bindAutoInstrumentationSuppressionToStart(tracingChannel2) {
|
|
10060
|
+
const startChannel = tracingChannel2.start;
|
|
10061
|
+
if (!startChannel) {
|
|
10062
|
+
return void 0;
|
|
10063
|
+
}
|
|
10064
|
+
const store = suppressionStore();
|
|
10065
|
+
startChannel.bindStore(store, () => ({
|
|
10066
|
+
frames: [
|
|
10067
|
+
...currentFrames(),
|
|
10068
|
+
{
|
|
10069
|
+
id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
|
|
10070
|
+
mode: "suppress"
|
|
10071
|
+
}
|
|
10072
|
+
]
|
|
10073
|
+
}));
|
|
10074
|
+
return () => {
|
|
10075
|
+
startChannel.unbindStore(store);
|
|
10076
|
+
};
|
|
10077
|
+
}
|
|
10078
|
+
function enterAutoInstrumentationAllowed() {
|
|
10079
|
+
const frame = {
|
|
10080
|
+
id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-allow"),
|
|
10081
|
+
mode: "allow"
|
|
10082
|
+
};
|
|
10083
|
+
suppressionStore().enterWith({
|
|
10084
|
+
frames: [...currentFrames(), frame]
|
|
10085
|
+
});
|
|
10086
|
+
return () => {
|
|
10087
|
+
const frames = currentFrames().filter(
|
|
10088
|
+
(candidate) => candidate.id !== frame.id
|
|
10089
|
+
);
|
|
10090
|
+
suppressionStore().enterWith(frames.length > 0 ? { frames } : void 0);
|
|
10091
|
+
};
|
|
10092
|
+
}
|
|
10093
|
+
|
|
10024
10094
|
// src/instrumentation/core/channel-tracing.ts
|
|
10025
10095
|
function isSyncStreamLike(value) {
|
|
10026
10096
|
return !!value && typeof value === "object" && typeof value.on === "function";
|
|
@@ -10052,16 +10122,33 @@ function startSpanForEvent(config, event, channelName) {
|
|
|
10052
10122
|
metadata: mergeInputMetadata(metadata, spanInfoMetadata)
|
|
10053
10123
|
});
|
|
10054
10124
|
} catch (error) {
|
|
10055
|
-
|
|
10125
|
+
debugLogger.error(`Error extracting input for ${channelName}:`, error);
|
|
10056
10126
|
}
|
|
10057
10127
|
return { span, startTime };
|
|
10058
10128
|
}
|
|
10129
|
+
function shouldTraceEvent(config, event, channelName) {
|
|
10130
|
+
if (!config.shouldTrace) {
|
|
10131
|
+
return true;
|
|
10132
|
+
}
|
|
10133
|
+
try {
|
|
10134
|
+
return config.shouldTrace(event.arguments, event);
|
|
10135
|
+
} catch (error) {
|
|
10136
|
+
debugLogger.error(
|
|
10137
|
+
`Error checking trace predicate for ${channelName}:`,
|
|
10138
|
+
error
|
|
10139
|
+
);
|
|
10140
|
+
return true;
|
|
10141
|
+
}
|
|
10142
|
+
}
|
|
10059
10143
|
function ensureSpanStateForEvent(states, config, event, channelName) {
|
|
10060
10144
|
const key = event;
|
|
10061
10145
|
const existing = states.get(key);
|
|
10062
10146
|
if (existing) {
|
|
10063
10147
|
return existing;
|
|
10064
10148
|
}
|
|
10149
|
+
if (!shouldTraceEvent(config, event, channelName)) {
|
|
10150
|
+
return void 0;
|
|
10151
|
+
}
|
|
10065
10152
|
const created = startSpanForEvent(config, event, channelName);
|
|
10066
10153
|
states.set(key, created);
|
|
10067
10154
|
return created;
|
|
@@ -10077,13 +10164,16 @@ function bindCurrentSpanStoreToStart(tracingChannel2, states, config, channelNam
|
|
|
10077
10164
|
startChannel.bindStore(
|
|
10078
10165
|
currentSpanStore,
|
|
10079
10166
|
(event) => {
|
|
10080
|
-
|
|
10167
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
10168
|
+
return currentSpanStore.getStore();
|
|
10169
|
+
}
|
|
10170
|
+
const spanState = ensureSpanStateForEvent(
|
|
10081
10171
|
states,
|
|
10082
10172
|
config,
|
|
10083
10173
|
event,
|
|
10084
10174
|
channelName
|
|
10085
|
-
)
|
|
10086
|
-
return contextManager.wrapSpanForStore(span);
|
|
10175
|
+
);
|
|
10176
|
+
return spanState ? contextManager.wrapSpanForStore(spanState.span) : currentSpanStore.getStore();
|
|
10087
10177
|
}
|
|
10088
10178
|
);
|
|
10089
10179
|
return () => {
|
|
@@ -10118,7 +10208,10 @@ function runStreamingCompletionHook(args) {
|
|
|
10118
10208
|
startTime: args.startTime
|
|
10119
10209
|
});
|
|
10120
10210
|
} catch (error) {
|
|
10121
|
-
|
|
10211
|
+
debugLogger.error(
|
|
10212
|
+
`Error in onComplete hook for ${args.channelName}:`,
|
|
10213
|
+
error
|
|
10214
|
+
);
|
|
10122
10215
|
}
|
|
10123
10216
|
}
|
|
10124
10217
|
function traceAsyncChannel(channel2, config) {
|
|
@@ -10133,6 +10226,9 @@ function traceAsyncChannel(channel2, config) {
|
|
|
10133
10226
|
);
|
|
10134
10227
|
const handlers = {
|
|
10135
10228
|
start: (event) => {
|
|
10229
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
10230
|
+
return;
|
|
10231
|
+
}
|
|
10136
10232
|
ensureSpanStateForEvent(
|
|
10137
10233
|
states,
|
|
10138
10234
|
config,
|
|
@@ -10167,7 +10263,7 @@ function traceAsyncChannel(channel2, config) {
|
|
|
10167
10263
|
metrics
|
|
10168
10264
|
});
|
|
10169
10265
|
} catch (error) {
|
|
10170
|
-
|
|
10266
|
+
debugLogger.error(`Error extracting output for ${channelName}:`, error);
|
|
10171
10267
|
} finally {
|
|
10172
10268
|
span.end();
|
|
10173
10269
|
states.delete(event);
|
|
@@ -10195,6 +10291,9 @@ function traceStreamingChannel(channel2, config) {
|
|
|
10195
10291
|
);
|
|
10196
10292
|
const handlers = {
|
|
10197
10293
|
start: (event) => {
|
|
10294
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
10295
|
+
return;
|
|
10296
|
+
}
|
|
10198
10297
|
ensureSpanStateForEvent(
|
|
10199
10298
|
states,
|
|
10200
10299
|
config,
|
|
@@ -10266,7 +10365,7 @@ function traceStreamingChannel(channel2, config) {
|
|
|
10266
10365
|
metrics
|
|
10267
10366
|
});
|
|
10268
10367
|
} catch (error) {
|
|
10269
|
-
|
|
10368
|
+
debugLogger.error(
|
|
10270
10369
|
`Error extracting output for ${channelName}:`,
|
|
10271
10370
|
error
|
|
10272
10371
|
);
|
|
@@ -10326,7 +10425,7 @@ function traceStreamingChannel(channel2, config) {
|
|
|
10326
10425
|
metrics
|
|
10327
10426
|
});
|
|
10328
10427
|
} catch (error) {
|
|
10329
|
-
|
|
10428
|
+
debugLogger.error(`Error extracting output for ${channelName}:`, error);
|
|
10330
10429
|
} finally {
|
|
10331
10430
|
span.end();
|
|
10332
10431
|
states.delete(event);
|
|
@@ -10354,6 +10453,9 @@ function traceSyncStreamChannel(channel2, config) {
|
|
|
10354
10453
|
);
|
|
10355
10454
|
const handlers = {
|
|
10356
10455
|
start: (event) => {
|
|
10456
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
10457
|
+
return;
|
|
10458
|
+
}
|
|
10357
10459
|
ensureSpanStateForEvent(
|
|
10358
10460
|
states,
|
|
10359
10461
|
config,
|
|
@@ -10407,7 +10509,7 @@ function traceSyncStreamChannel(channel2, config) {
|
|
|
10407
10509
|
});
|
|
10408
10510
|
}
|
|
10409
10511
|
} catch (error) {
|
|
10410
|
-
|
|
10512
|
+
debugLogger.error(
|
|
10411
10513
|
`Error extracting chatCompletion for ${channelName}:`,
|
|
10412
10514
|
error
|
|
10413
10515
|
);
|
|
@@ -10431,7 +10533,10 @@ function traceSyncStreamChannel(channel2, config) {
|
|
|
10431
10533
|
span.log(extracted);
|
|
10432
10534
|
}
|
|
10433
10535
|
} catch (error) {
|
|
10434
|
-
|
|
10536
|
+
debugLogger.error(
|
|
10537
|
+
`Error extracting event for ${channelName}:`,
|
|
10538
|
+
error
|
|
10539
|
+
);
|
|
10435
10540
|
}
|
|
10436
10541
|
});
|
|
10437
10542
|
stream.on("end", () => {
|
|
@@ -11960,6 +12065,9 @@ var AnthropicPlugin = class extends BasePlugin {
|
|
|
11960
12065
|
const states = /* @__PURE__ */ new WeakMap();
|
|
11961
12066
|
const handlers = {
|
|
11962
12067
|
start: (event) => {
|
|
12068
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
12069
|
+
return;
|
|
12070
|
+
}
|
|
11963
12071
|
const params = event.arguments[0] ?? {};
|
|
11964
12072
|
const span = startSpan({
|
|
11965
12073
|
name: "anthropic.beta.messages.toolRunner",
|
|
@@ -12689,6 +12797,520 @@ function serializeAISDKToolsForLogging(tools) {
|
|
|
12689
12797
|
return serialized;
|
|
12690
12798
|
}
|
|
12691
12799
|
|
|
12800
|
+
// src/wrappers/ai-sdk/telemetry.ts
|
|
12801
|
+
function braintrustAISDKTelemetry() {
|
|
12802
|
+
const operations = /* @__PURE__ */ new Map();
|
|
12803
|
+
const modelSpans = /* @__PURE__ */ new Map();
|
|
12804
|
+
const objectSpans = /* @__PURE__ */ new Map();
|
|
12805
|
+
const embedSpans = /* @__PURE__ */ new Map();
|
|
12806
|
+
const rerankSpans = /* @__PURE__ */ new Map();
|
|
12807
|
+
const toolSpans = /* @__PURE__ */ new Map();
|
|
12808
|
+
const runSafely = (name, callback) => {
|
|
12809
|
+
try {
|
|
12810
|
+
callback();
|
|
12811
|
+
} catch (error) {
|
|
12812
|
+
console.error(`Error in Braintrust AI SDK telemetry ${name}:`, error);
|
|
12813
|
+
}
|
|
12814
|
+
};
|
|
12815
|
+
const startChildSpan = (callId, name, type, event) => {
|
|
12816
|
+
const parent = operations.get(callId)?.span;
|
|
12817
|
+
const spanArgs = {
|
|
12818
|
+
name,
|
|
12819
|
+
spanAttributes: { type },
|
|
12820
|
+
...event ? { event } : {}
|
|
12821
|
+
};
|
|
12822
|
+
const span = parent ? parent.startSpan(spanArgs) : startSpan(spanArgs);
|
|
12823
|
+
const state = operations.get(callId);
|
|
12824
|
+
if (state && type === "llm" /* LLM */) {
|
|
12825
|
+
state.hadModelChild = true;
|
|
12826
|
+
}
|
|
12827
|
+
return span;
|
|
12828
|
+
};
|
|
12829
|
+
return {
|
|
12830
|
+
onStart(event) {
|
|
12831
|
+
runSafely("onStart", () => {
|
|
12832
|
+
const operationName = operationNameFromId(event.operationId);
|
|
12833
|
+
const span = startSpan({
|
|
12834
|
+
name: operationName,
|
|
12835
|
+
spanAttributes: { type: "function" /* FUNCTION */ }
|
|
12836
|
+
});
|
|
12837
|
+
operations.set(event.callId, {
|
|
12838
|
+
hadModelChild: false,
|
|
12839
|
+
operationName,
|
|
12840
|
+
span,
|
|
12841
|
+
startTime: getCurrentUnixTimestamp()
|
|
12842
|
+
});
|
|
12843
|
+
const metadata = metadataFromEvent(event);
|
|
12844
|
+
const logPayload = { metadata };
|
|
12845
|
+
if (shouldRecordInputs(event)) {
|
|
12846
|
+
const { input, outputPromise } = processAISDKCallInput(
|
|
12847
|
+
operationInput(event, operationName)
|
|
12848
|
+
);
|
|
12849
|
+
logPayload.input = input;
|
|
12850
|
+
if (outputPromise && input && typeof input === "object") {
|
|
12851
|
+
outputPromise.then((resolvedData) => {
|
|
12852
|
+
span.log({
|
|
12853
|
+
input: {
|
|
12854
|
+
...input,
|
|
12855
|
+
...resolvedData
|
|
12856
|
+
}
|
|
12857
|
+
});
|
|
12858
|
+
}).catch(() => {
|
|
12859
|
+
});
|
|
12860
|
+
}
|
|
12861
|
+
}
|
|
12862
|
+
span.log(logPayload);
|
|
12863
|
+
});
|
|
12864
|
+
},
|
|
12865
|
+
onLanguageModelCallStart(event) {
|
|
12866
|
+
runSafely("onLanguageModelCallStart", () => {
|
|
12867
|
+
const state = operations.get(event.callId);
|
|
12868
|
+
const openSpans = modelSpans.get(event.callId);
|
|
12869
|
+
if (openSpans) {
|
|
12870
|
+
for (const span2 of openSpans) {
|
|
12871
|
+
span2.end();
|
|
12872
|
+
}
|
|
12873
|
+
modelSpans.delete(event.callId);
|
|
12874
|
+
}
|
|
12875
|
+
const span = startChildSpan(
|
|
12876
|
+
event.callId,
|
|
12877
|
+
state?.operationName === "streamText" ? "doStream" : "doGenerate",
|
|
12878
|
+
"llm" /* LLM */,
|
|
12879
|
+
{
|
|
12880
|
+
...shouldRecordInputs(event) ? {
|
|
12881
|
+
input: processAISDKCallInput(
|
|
12882
|
+
operationInput(
|
|
12883
|
+
event,
|
|
12884
|
+
state?.operationName ?? "generateText"
|
|
12885
|
+
)
|
|
12886
|
+
).input
|
|
12887
|
+
} : {},
|
|
12888
|
+
metadata: metadataFromEvent(event)
|
|
12889
|
+
}
|
|
12890
|
+
);
|
|
12891
|
+
const spans = modelSpans.get(event.callId) ?? [];
|
|
12892
|
+
spans.push(span);
|
|
12893
|
+
modelSpans.set(event.callId, spans);
|
|
12894
|
+
});
|
|
12895
|
+
},
|
|
12896
|
+
onLanguageModelCallEnd(event) {
|
|
12897
|
+
runSafely("onLanguageModelCallEnd", () => {
|
|
12898
|
+
const span = shiftModelSpan(modelSpans, event.callId);
|
|
12899
|
+
if (!span) {
|
|
12900
|
+
return;
|
|
12901
|
+
}
|
|
12902
|
+
const result = {
|
|
12903
|
+
...event,
|
|
12904
|
+
response: event.responseId ? { id: event.responseId } : void 0
|
|
12905
|
+
};
|
|
12906
|
+
span.log({
|
|
12907
|
+
...shouldRecordOutputs(event) ? {
|
|
12908
|
+
output: processAISDKOutput(result, DEFAULT_DENY_OUTPUT_PATHS)
|
|
12909
|
+
} : {},
|
|
12910
|
+
metrics: extractTokenMetrics(result)
|
|
12911
|
+
});
|
|
12912
|
+
span.end();
|
|
12913
|
+
});
|
|
12914
|
+
},
|
|
12915
|
+
onObjectStepStart(event) {
|
|
12916
|
+
runSafely("onObjectStepStart", () => {
|
|
12917
|
+
const state = operations.get(event.callId);
|
|
12918
|
+
const openSpan = objectSpans.get(event.callId);
|
|
12919
|
+
if (openSpan) {
|
|
12920
|
+
openSpan.end();
|
|
12921
|
+
objectSpans.delete(event.callId);
|
|
12922
|
+
}
|
|
12923
|
+
const span = startChildSpan(
|
|
12924
|
+
event.callId,
|
|
12925
|
+
state?.operationName === "streamObject" ? "doStream" : "doGenerate",
|
|
12926
|
+
"llm" /* LLM */,
|
|
12927
|
+
{
|
|
12928
|
+
...shouldRecordInputs(event) ? {
|
|
12929
|
+
input: {
|
|
12930
|
+
prompt: event.promptMessages
|
|
12931
|
+
}
|
|
12932
|
+
} : {},
|
|
12933
|
+
metadata: metadataFromEvent(event)
|
|
12934
|
+
}
|
|
12935
|
+
);
|
|
12936
|
+
objectSpans.set(event.callId, span);
|
|
12937
|
+
});
|
|
12938
|
+
},
|
|
12939
|
+
onObjectStepFinish(event) {
|
|
12940
|
+
runSafely("onObjectStepFinish", () => {
|
|
12941
|
+
const span = objectSpans.get(event.callId);
|
|
12942
|
+
if (!span) {
|
|
12943
|
+
return;
|
|
12944
|
+
}
|
|
12945
|
+
const result = {
|
|
12946
|
+
...event,
|
|
12947
|
+
text: event.objectText
|
|
12948
|
+
};
|
|
12949
|
+
span.log({
|
|
12950
|
+
...shouldRecordOutputs(event) ? {
|
|
12951
|
+
output: processAISDKOutput(result, DEFAULT_DENY_OUTPUT_PATHS)
|
|
12952
|
+
} : {},
|
|
12953
|
+
metrics: extractTokenMetrics(result)
|
|
12954
|
+
});
|
|
12955
|
+
span.end();
|
|
12956
|
+
objectSpans.delete(event.callId);
|
|
12957
|
+
});
|
|
12958
|
+
},
|
|
12959
|
+
onEmbedStart(event) {
|
|
12960
|
+
runSafely("onEmbedStart", () => {
|
|
12961
|
+
const state = operations.get(event.callId);
|
|
12962
|
+
for (const [embedCallId, embedState] of embedSpans) {
|
|
12963
|
+
if (embedState.callId === event.callId && (state?.operationName === "embed" || embedState.values === event.values)) {
|
|
12964
|
+
embedState.span.end();
|
|
12965
|
+
embedSpans.delete(embedCallId);
|
|
12966
|
+
}
|
|
12967
|
+
}
|
|
12968
|
+
const span = startChildSpan(
|
|
12969
|
+
event.callId,
|
|
12970
|
+
"doEmbed",
|
|
12971
|
+
"llm" /* LLM */,
|
|
12972
|
+
{
|
|
12973
|
+
...shouldRecordInputs(event) ? {
|
|
12974
|
+
input: {
|
|
12975
|
+
values: event.values
|
|
12976
|
+
}
|
|
12977
|
+
} : {},
|
|
12978
|
+
metadata: metadataFromEvent(event)
|
|
12979
|
+
}
|
|
12980
|
+
);
|
|
12981
|
+
embedSpans.set(event.embedCallId, {
|
|
12982
|
+
callId: event.callId,
|
|
12983
|
+
span,
|
|
12984
|
+
values: event.values
|
|
12985
|
+
});
|
|
12986
|
+
});
|
|
12987
|
+
},
|
|
12988
|
+
onEmbedFinish(event) {
|
|
12989
|
+
runSafely("onEmbedFinish", () => {
|
|
12990
|
+
const state = embedSpans.get(event.embedCallId);
|
|
12991
|
+
if (!state) {
|
|
12992
|
+
return;
|
|
12993
|
+
}
|
|
12994
|
+
const result = {
|
|
12995
|
+
...event,
|
|
12996
|
+
embeddings: event.embeddings
|
|
12997
|
+
};
|
|
12998
|
+
state.span.log({
|
|
12999
|
+
...shouldRecordOutputs(event) ? {
|
|
13000
|
+
output: processAISDKEmbeddingOutput(
|
|
13001
|
+
result,
|
|
13002
|
+
DEFAULT_DENY_OUTPUT_PATHS
|
|
13003
|
+
)
|
|
13004
|
+
} : {},
|
|
13005
|
+
metrics: extractTokenMetrics(result)
|
|
13006
|
+
});
|
|
13007
|
+
state.span.end();
|
|
13008
|
+
embedSpans.delete(event.embedCallId);
|
|
13009
|
+
});
|
|
13010
|
+
},
|
|
13011
|
+
onRerankStart(event) {
|
|
13012
|
+
runSafely("onRerankStart", () => {
|
|
13013
|
+
const openSpan = rerankSpans.get(event.callId);
|
|
13014
|
+
if (openSpan) {
|
|
13015
|
+
openSpan.end();
|
|
13016
|
+
rerankSpans.delete(event.callId);
|
|
13017
|
+
}
|
|
13018
|
+
const span = startChildSpan(
|
|
13019
|
+
event.callId,
|
|
13020
|
+
"doRerank",
|
|
13021
|
+
"llm" /* LLM */,
|
|
13022
|
+
{
|
|
13023
|
+
...shouldRecordInputs(event) ? {
|
|
13024
|
+
input: {
|
|
13025
|
+
documents: event.documents,
|
|
13026
|
+
query: event.query,
|
|
13027
|
+
topN: event.topN
|
|
13028
|
+
}
|
|
13029
|
+
} : {},
|
|
13030
|
+
metadata: metadataFromEvent(event)
|
|
13031
|
+
}
|
|
13032
|
+
);
|
|
13033
|
+
rerankSpans.set(event.callId, span);
|
|
13034
|
+
});
|
|
13035
|
+
},
|
|
13036
|
+
onRerankFinish(event) {
|
|
13037
|
+
runSafely("onRerankFinish", () => {
|
|
13038
|
+
const span = rerankSpans.get(event.callId);
|
|
13039
|
+
if (!span) {
|
|
13040
|
+
return;
|
|
13041
|
+
}
|
|
13042
|
+
const result = {
|
|
13043
|
+
ranking: event.ranking?.map((entry) => ({
|
|
13044
|
+
originalIndex: entry.index,
|
|
13045
|
+
score: entry.relevanceScore
|
|
13046
|
+
}))
|
|
13047
|
+
};
|
|
13048
|
+
span.log({
|
|
13049
|
+
...shouldRecordOutputs(event) ? {
|
|
13050
|
+
output: processAISDKRerankOutput(
|
|
13051
|
+
result,
|
|
13052
|
+
DEFAULT_DENY_OUTPUT_PATHS
|
|
13053
|
+
)
|
|
13054
|
+
} : {}
|
|
13055
|
+
});
|
|
13056
|
+
span.end();
|
|
13057
|
+
rerankSpans.delete(event.callId);
|
|
13058
|
+
});
|
|
13059
|
+
},
|
|
13060
|
+
onToolExecutionStart(event) {
|
|
13061
|
+
runSafely("onToolExecutionStart", () => {
|
|
13062
|
+
const toolCallId = event.toolCall.toolCallId;
|
|
13063
|
+
if (!toolCallId) {
|
|
13064
|
+
return;
|
|
13065
|
+
}
|
|
13066
|
+
const span = startChildSpan(
|
|
13067
|
+
event.callId,
|
|
13068
|
+
event.toolCall.toolName || "tool",
|
|
13069
|
+
"tool" /* TOOL */,
|
|
13070
|
+
{
|
|
13071
|
+
...shouldRecordInputs(event) ? {
|
|
13072
|
+
input: event.toolCall.input
|
|
13073
|
+
} : {},
|
|
13074
|
+
metadata: {
|
|
13075
|
+
...createAISDKIntegrationMetadata(),
|
|
13076
|
+
toolCallId,
|
|
13077
|
+
...typeof event.toolCall.toolName === "string" ? { toolName: event.toolCall.toolName } : {}
|
|
13078
|
+
}
|
|
13079
|
+
}
|
|
13080
|
+
);
|
|
13081
|
+
toolSpans.set(toolCallId, { callId: event.callId, span });
|
|
13082
|
+
});
|
|
13083
|
+
},
|
|
13084
|
+
onToolExecutionEnd(event) {
|
|
13085
|
+
runSafely("onToolExecutionEnd", () => {
|
|
13086
|
+
const toolCallId = event.toolCall.toolCallId;
|
|
13087
|
+
const state = toolCallId ? toolSpans.get(toolCallId) : void 0;
|
|
13088
|
+
if (!toolCallId || !state) {
|
|
13089
|
+
return;
|
|
13090
|
+
}
|
|
13091
|
+
const toolOutput = event.toolOutput;
|
|
13092
|
+
if (toolOutput?.type === "tool-error") {
|
|
13093
|
+
state.span.log({
|
|
13094
|
+
error: toolOutput.error instanceof Error ? toolOutput.error.message : String(toolOutput?.error),
|
|
13095
|
+
metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } : {}
|
|
13096
|
+
});
|
|
13097
|
+
} else {
|
|
13098
|
+
state.span.log({
|
|
13099
|
+
...shouldRecordOutputs(event) ? { output: toolOutput?.output } : {},
|
|
13100
|
+
metrics: typeof event.durationMs === "number" ? { duration_ms: event.durationMs } : {}
|
|
13101
|
+
});
|
|
13102
|
+
}
|
|
13103
|
+
state.span.end();
|
|
13104
|
+
toolSpans.delete(toolCallId);
|
|
13105
|
+
});
|
|
13106
|
+
},
|
|
13107
|
+
onChunk(event) {
|
|
13108
|
+
runSafely("onChunk", () => {
|
|
13109
|
+
const callId = event.chunk?.callId;
|
|
13110
|
+
if (!callId) {
|
|
13111
|
+
return;
|
|
13112
|
+
}
|
|
13113
|
+
const state = operations.get(callId);
|
|
13114
|
+
if (!state || state.firstChunkTime !== void 0) {
|
|
13115
|
+
return;
|
|
13116
|
+
}
|
|
13117
|
+
state.firstChunkTime = getCurrentUnixTimestamp();
|
|
13118
|
+
});
|
|
13119
|
+
},
|
|
13120
|
+
onFinish(event) {
|
|
13121
|
+
runSafely("onFinish", () => {
|
|
13122
|
+
const state = operations.get(event.callId);
|
|
13123
|
+
if (!state) {
|
|
13124
|
+
return;
|
|
13125
|
+
}
|
|
13126
|
+
const result = finishResult(event, state.operationName);
|
|
13127
|
+
const metrics = state.hadModelChild ? {} : extractTokenMetrics(result);
|
|
13128
|
+
if (state.firstChunkTime !== void 0) {
|
|
13129
|
+
metrics.time_to_first_token = state.firstChunkTime - state.startTime;
|
|
13130
|
+
}
|
|
13131
|
+
state.span.log({
|
|
13132
|
+
...shouldRecordOutputs(event) ? {
|
|
13133
|
+
output: finishOutput(result, state.operationName)
|
|
13134
|
+
} : {},
|
|
13135
|
+
metrics
|
|
13136
|
+
});
|
|
13137
|
+
state.span.end();
|
|
13138
|
+
operations.delete(event.callId);
|
|
13139
|
+
});
|
|
13140
|
+
},
|
|
13141
|
+
onError(event) {
|
|
13142
|
+
runSafely("onError", () => {
|
|
13143
|
+
const errorEvent = isObject(event) ? event : {};
|
|
13144
|
+
const callId = typeof errorEvent.callId === "string" ? errorEvent.callId : void 0;
|
|
13145
|
+
if (!callId) {
|
|
13146
|
+
return;
|
|
13147
|
+
}
|
|
13148
|
+
const state = operations.get(callId);
|
|
13149
|
+
if (!state) {
|
|
13150
|
+
return;
|
|
13151
|
+
}
|
|
13152
|
+
const error = errorEvent.error ?? event;
|
|
13153
|
+
const openModelSpans = modelSpans.get(callId);
|
|
13154
|
+
if (openModelSpans) {
|
|
13155
|
+
for (const span of openModelSpans) {
|
|
13156
|
+
logError(span, error);
|
|
13157
|
+
span.end();
|
|
13158
|
+
}
|
|
13159
|
+
modelSpans.delete(callId);
|
|
13160
|
+
}
|
|
13161
|
+
const openObjectSpan = objectSpans.get(callId);
|
|
13162
|
+
if (openObjectSpan) {
|
|
13163
|
+
logError(openObjectSpan, error);
|
|
13164
|
+
openObjectSpan.end();
|
|
13165
|
+
objectSpans.delete(callId);
|
|
13166
|
+
}
|
|
13167
|
+
for (const [embedCallId, embedState] of embedSpans) {
|
|
13168
|
+
if (embedState.callId === callId) {
|
|
13169
|
+
logError(embedState.span, error);
|
|
13170
|
+
embedState.span.end();
|
|
13171
|
+
embedSpans.delete(embedCallId);
|
|
13172
|
+
}
|
|
13173
|
+
}
|
|
13174
|
+
const openRerankSpan = rerankSpans.get(callId);
|
|
13175
|
+
if (openRerankSpan) {
|
|
13176
|
+
logError(openRerankSpan, error);
|
|
13177
|
+
openRerankSpan.end();
|
|
13178
|
+
rerankSpans.delete(callId);
|
|
13179
|
+
}
|
|
13180
|
+
for (const [toolCallId, toolState] of toolSpans) {
|
|
13181
|
+
if (toolState.callId === callId) {
|
|
13182
|
+
logError(toolState.span, error);
|
|
13183
|
+
toolState.span.end();
|
|
13184
|
+
toolSpans.delete(toolCallId);
|
|
13185
|
+
}
|
|
13186
|
+
}
|
|
13187
|
+
logError(state.span, error);
|
|
13188
|
+
state.span.end();
|
|
13189
|
+
operations.delete(callId);
|
|
13190
|
+
});
|
|
13191
|
+
},
|
|
13192
|
+
executeTool({ toolCallId, execute }) {
|
|
13193
|
+
const state = toolSpans.get(toolCallId);
|
|
13194
|
+
return state ? withCurrent(state.span, () => execute()) : execute();
|
|
13195
|
+
}
|
|
13196
|
+
};
|
|
13197
|
+
}
|
|
13198
|
+
function shouldRecordInputs(event) {
|
|
13199
|
+
return event.recordInputs !== false;
|
|
13200
|
+
}
|
|
13201
|
+
function shouldRecordOutputs(event) {
|
|
13202
|
+
return event.recordOutputs !== false;
|
|
13203
|
+
}
|
|
13204
|
+
function operationNameFromId(operationId) {
|
|
13205
|
+
return operationId?.startsWith("ai.") ? operationId.slice("ai.".length) : operationId || "ai-sdk";
|
|
13206
|
+
}
|
|
13207
|
+
function modelFromEvent(event) {
|
|
13208
|
+
return event.modelId ? {
|
|
13209
|
+
modelId: event.modelId,
|
|
13210
|
+
...event.provider ? { provider: event.provider } : {}
|
|
13211
|
+
} : void 0;
|
|
13212
|
+
}
|
|
13213
|
+
function metadataFromEvent(event) {
|
|
13214
|
+
const metadata = createAISDKIntegrationMetadata();
|
|
13215
|
+
const { model, provider } = serializeModelWithProvider(modelFromEvent(event));
|
|
13216
|
+
if (model) {
|
|
13217
|
+
metadata.model = model;
|
|
13218
|
+
}
|
|
13219
|
+
if (provider) {
|
|
13220
|
+
metadata.provider = provider;
|
|
13221
|
+
}
|
|
13222
|
+
if (typeof event.functionId === "string") {
|
|
13223
|
+
metadata.functionId = event.functionId;
|
|
13224
|
+
}
|
|
13225
|
+
return metadata;
|
|
13226
|
+
}
|
|
13227
|
+
function operationInput(event, operationName) {
|
|
13228
|
+
if (operationName === "embed") {
|
|
13229
|
+
return {
|
|
13230
|
+
model: modelFromEvent(event),
|
|
13231
|
+
value: event.value
|
|
13232
|
+
};
|
|
13233
|
+
}
|
|
13234
|
+
if (operationName === "embedMany") {
|
|
13235
|
+
return {
|
|
13236
|
+
model: modelFromEvent(event),
|
|
13237
|
+
values: Array.isArray(event.value) ? event.value ?? [] : void 0
|
|
13238
|
+
};
|
|
13239
|
+
}
|
|
13240
|
+
if (operationName === "rerank") {
|
|
13241
|
+
return {
|
|
13242
|
+
model: modelFromEvent(event),
|
|
13243
|
+
documents: event.documents,
|
|
13244
|
+
query: event.query,
|
|
13245
|
+
topN: event.topN
|
|
13246
|
+
};
|
|
13247
|
+
}
|
|
13248
|
+
return {
|
|
13249
|
+
model: modelFromEvent(event),
|
|
13250
|
+
system: event.system,
|
|
13251
|
+
prompt: event.prompt,
|
|
13252
|
+
messages: event.messages,
|
|
13253
|
+
tools: event.tools,
|
|
13254
|
+
toolChoice: event.toolChoice,
|
|
13255
|
+
activeTools: event.activeTools,
|
|
13256
|
+
output: event.output,
|
|
13257
|
+
schema: event.schema,
|
|
13258
|
+
schemaName: event.schemaName,
|
|
13259
|
+
schemaDescription: event.schemaDescription,
|
|
13260
|
+
maxOutputTokens: event.maxOutputTokens,
|
|
13261
|
+
temperature: event.temperature,
|
|
13262
|
+
topP: event.topP,
|
|
13263
|
+
topK: event.topK,
|
|
13264
|
+
presencePenalty: event.presencePenalty,
|
|
13265
|
+
frequencyPenalty: event.frequencyPenalty,
|
|
13266
|
+
seed: event.seed,
|
|
13267
|
+
maxRetries: event.maxRetries,
|
|
13268
|
+
headers: event.headers,
|
|
13269
|
+
providerOptions: event.providerOptions
|
|
13270
|
+
};
|
|
13271
|
+
}
|
|
13272
|
+
function shiftModelSpan(modelSpans, callId) {
|
|
13273
|
+
const spans = modelSpans.get(callId);
|
|
13274
|
+
const span = spans?.shift();
|
|
13275
|
+
if (spans && spans.length === 0) {
|
|
13276
|
+
modelSpans.delete(callId);
|
|
13277
|
+
}
|
|
13278
|
+
return span;
|
|
13279
|
+
}
|
|
13280
|
+
function finishResult(event, operationName) {
|
|
13281
|
+
if (operationName === "embed") {
|
|
13282
|
+
return {
|
|
13283
|
+
...event,
|
|
13284
|
+
embedding: event.embedding
|
|
13285
|
+
};
|
|
13286
|
+
}
|
|
13287
|
+
if (operationName === "embedMany") {
|
|
13288
|
+
return {
|
|
13289
|
+
...event,
|
|
13290
|
+
embeddings: event.embedding
|
|
13291
|
+
};
|
|
13292
|
+
}
|
|
13293
|
+
if (operationName === "rerank") {
|
|
13294
|
+
return event;
|
|
13295
|
+
}
|
|
13296
|
+
return event;
|
|
13297
|
+
}
|
|
13298
|
+
function finishOutput(result, operationName) {
|
|
13299
|
+
if (operationName === "embed" || operationName === "embedMany") {
|
|
13300
|
+
return processAISDKEmbeddingOutput(
|
|
13301
|
+
result,
|
|
13302
|
+
DEFAULT_DENY_OUTPUT_PATHS
|
|
13303
|
+
);
|
|
13304
|
+
}
|
|
13305
|
+
if (operationName === "rerank") {
|
|
13306
|
+
return processAISDKRerankOutput(
|
|
13307
|
+
result,
|
|
13308
|
+
DEFAULT_DENY_OUTPUT_PATHS
|
|
13309
|
+
);
|
|
13310
|
+
}
|
|
13311
|
+
return processAISDKOutput(result, DEFAULT_DENY_OUTPUT_PATHS);
|
|
13312
|
+
}
|
|
13313
|
+
|
|
12692
13314
|
// src/instrumentation/plugins/ai-sdk-channels.ts
|
|
12693
13315
|
var aiSDKChannels = defineChannels("ai", {
|
|
12694
13316
|
generateText: channel({
|
|
@@ -12748,6 +13370,10 @@ var aiSDKChannels = defineChannels("ai", {
|
|
|
12748
13370
|
toolLoopAgentStream: channel({
|
|
12749
13371
|
channelName: "ToolLoopAgent.stream",
|
|
12750
13372
|
kind: "async"
|
|
13373
|
+
}),
|
|
13374
|
+
v7CreateTelemetryDispatcher: channel({
|
|
13375
|
+
channelName: "createTelemetryDispatcher",
|
|
13376
|
+
kind: "sync-stream"
|
|
12751
13377
|
})
|
|
12752
13378
|
});
|
|
12753
13379
|
|
|
@@ -12768,9 +13394,30 @@ var DEFAULT_DENY_OUTPUT_PATHS = [
|
|
|
12768
13394
|
];
|
|
12769
13395
|
var AUTO_PATCHED_MODEL = /* @__PURE__ */ Symbol.for("braintrust.ai-sdk.auto-patched-model");
|
|
12770
13396
|
var AUTO_PATCHED_TOOL = /* @__PURE__ */ Symbol.for("braintrust.ai-sdk.auto-patched-tool");
|
|
13397
|
+
var AUTO_PATCHED_V7_TELEMETRY_DISPATCHER = /* @__PURE__ */ Symbol.for(
|
|
13398
|
+
"braintrust.ai-sdk.v7.auto-patched-telemetry-dispatcher"
|
|
13399
|
+
);
|
|
12771
13400
|
var RUNTIME_DENY_OUTPUT_PATHS = /* @__PURE__ */ Symbol.for(
|
|
12772
13401
|
"braintrust.ai-sdk.deny-output-paths"
|
|
12773
13402
|
);
|
|
13403
|
+
var AI_SDK_V7_TELEMETRY_CALLBACKS = [
|
|
13404
|
+
"onStart",
|
|
13405
|
+
"onStepStart",
|
|
13406
|
+
"onLanguageModelCallStart",
|
|
13407
|
+
"onLanguageModelCallEnd",
|
|
13408
|
+
"onToolExecutionStart",
|
|
13409
|
+
"onToolExecutionEnd",
|
|
13410
|
+
"onChunk",
|
|
13411
|
+
"onStepFinish",
|
|
13412
|
+
"onObjectStepStart",
|
|
13413
|
+
"onObjectStepFinish",
|
|
13414
|
+
"onEmbedStart",
|
|
13415
|
+
"onEmbedFinish",
|
|
13416
|
+
"onRerankStart",
|
|
13417
|
+
"onRerankFinish",
|
|
13418
|
+
"onFinish",
|
|
13419
|
+
"onError"
|
|
13420
|
+
];
|
|
12774
13421
|
var AISDKPlugin = class extends BasePlugin {
|
|
12775
13422
|
config;
|
|
12776
13423
|
constructor(config = {}) {
|
|
@@ -12785,6 +13432,7 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
12785
13432
|
}
|
|
12786
13433
|
subscribeToAISDK() {
|
|
12787
13434
|
const denyOutputPaths = this.config.denyOutputPaths || DEFAULT_DENY_OUTPUT_PATHS;
|
|
13435
|
+
this.unsubscribers.push(subscribeToAISDKV7TelemetryDispatcher());
|
|
12788
13436
|
this.unsubscribers.push(
|
|
12789
13437
|
traceStreamingChannel(aiSDKChannels.generateText, {
|
|
12790
13438
|
name: "generateText",
|
|
@@ -13009,14 +13657,65 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
13009
13657
|
);
|
|
13010
13658
|
}
|
|
13011
13659
|
};
|
|
13012
|
-
function
|
|
13013
|
-
|
|
13014
|
-
|
|
13015
|
-
|
|
13016
|
-
|
|
13017
|
-
|
|
13018
|
-
|
|
13019
|
-
|
|
13660
|
+
function subscribeToAISDKV7TelemetryDispatcher() {
|
|
13661
|
+
const channel2 = aiSDKChannels.v7CreateTelemetryDispatcher.tracingChannel();
|
|
13662
|
+
const telemetry = braintrustAISDKTelemetry();
|
|
13663
|
+
const handlers = {
|
|
13664
|
+
end: (event) => {
|
|
13665
|
+
const telemetryOptions = event.arguments?.[0]?.telemetry;
|
|
13666
|
+
if (telemetryOptions?.isEnabled === false) {
|
|
13667
|
+
return;
|
|
13668
|
+
}
|
|
13669
|
+
patchAISDKV7TelemetryDispatcher(event.result, telemetry);
|
|
13670
|
+
}
|
|
13671
|
+
};
|
|
13672
|
+
channel2.subscribe(handlers);
|
|
13673
|
+
return () => {
|
|
13674
|
+
channel2.unsubscribe(handlers);
|
|
13675
|
+
};
|
|
13676
|
+
}
|
|
13677
|
+
function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry) {
|
|
13678
|
+
if (!isObject(dispatcher)) {
|
|
13679
|
+
return;
|
|
13680
|
+
}
|
|
13681
|
+
const dispatcherRecord = dispatcher;
|
|
13682
|
+
if (dispatcherRecord[AUTO_PATCHED_V7_TELEMETRY_DISPATCHER]) {
|
|
13683
|
+
return;
|
|
13684
|
+
}
|
|
13685
|
+
dispatcherRecord[AUTO_PATCHED_V7_TELEMETRY_DISPATCHER] = true;
|
|
13686
|
+
for (const key of AI_SDK_V7_TELEMETRY_CALLBACKS) {
|
|
13687
|
+
const braintrustCallback = telemetry[key];
|
|
13688
|
+
if (typeof braintrustCallback !== "function") {
|
|
13689
|
+
continue;
|
|
13690
|
+
}
|
|
13691
|
+
const existingCallback = dispatcherRecord[key];
|
|
13692
|
+
dispatcherRecord[key] = (event) => {
|
|
13693
|
+
const existingResult = typeof existingCallback === "function" ? existingCallback.call(dispatcher, event) : void 0;
|
|
13694
|
+
const braintrustResult = braintrustCallback.call(telemetry, event);
|
|
13695
|
+
const pending = [existingResult, braintrustResult].filter(isPromiseLike);
|
|
13696
|
+
if (pending.length > 0) {
|
|
13697
|
+
return Promise.allSettled(pending).then(() => void 0);
|
|
13698
|
+
}
|
|
13699
|
+
};
|
|
13700
|
+
}
|
|
13701
|
+
const braintrustExecuteTool = telemetry.executeTool;
|
|
13702
|
+
if (typeof braintrustExecuteTool !== "function") {
|
|
13703
|
+
return;
|
|
13704
|
+
}
|
|
13705
|
+
const existingExecuteTool = dispatcherRecord.executeTool;
|
|
13706
|
+
dispatcherRecord.executeTool = (args) => braintrustExecuteTool.call(telemetry, {
|
|
13707
|
+
...args,
|
|
13708
|
+
execute: () => typeof existingExecuteTool === "function" ? existingExecuteTool.call(dispatcher, args) : args.execute()
|
|
13709
|
+
});
|
|
13710
|
+
}
|
|
13711
|
+
function resolveDenyOutputPaths(event, defaultDenyOutputPaths) {
|
|
13712
|
+
if (Array.isArray(event?.denyOutputPaths)) {
|
|
13713
|
+
return event.denyOutputPaths;
|
|
13714
|
+
}
|
|
13715
|
+
const firstArgument2 = event?.arguments && event.arguments.length > 0 ? event.arguments[0] : void 0;
|
|
13716
|
+
if (!firstArgument2 || typeof firstArgument2 !== "object") {
|
|
13717
|
+
return defaultDenyOutputPaths;
|
|
13718
|
+
}
|
|
13020
13719
|
const runtimeDenyOutputPaths = firstArgument2[RUNTIME_DENY_OUTPUT_PATHS];
|
|
13021
13720
|
if (Array.isArray(runtimeDenyOutputPaths) && runtimeDenyOutputPaths.every((path2) => typeof path2 === "string")) {
|
|
13022
13721
|
return runtimeDenyOutputPaths;
|
|
@@ -13460,11 +14159,11 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
|
|
|
13460
14159
|
metadata: baseMetadata
|
|
13461
14160
|
}
|
|
13462
14161
|
});
|
|
14162
|
+
const streamStartTime = getCurrentUnixTimestamp();
|
|
13463
14163
|
const result = await withCurrent(
|
|
13464
14164
|
span,
|
|
13465
14165
|
() => Reflect.apply(originalDoStream, resolvedModel, [options])
|
|
13466
14166
|
);
|
|
13467
|
-
const streamStartTime = getCurrentUnixTimestamp();
|
|
13468
14167
|
let firstChunkTime;
|
|
13469
14168
|
const output = {};
|
|
13470
14169
|
let text = "";
|
|
@@ -13473,7 +14172,7 @@ function prepareAISDKChildTracing(params, self, parentSpan, denyOutputPaths, aiS
|
|
|
13473
14172
|
let object = void 0;
|
|
13474
14173
|
const transformStream = new TransformStream({
|
|
13475
14174
|
transform(chunk, controller) {
|
|
13476
|
-
if (firstChunkTime === void 0) {
|
|
14175
|
+
if (firstChunkTime === void 0 && isAISDKContentStreamChunk(chunk)) {
|
|
13477
14176
|
firstChunkTime = getCurrentUnixTimestamp();
|
|
13478
14177
|
}
|
|
13479
14178
|
switch (chunk.type) {
|
|
@@ -13665,6 +14364,78 @@ function finalizeAISDKChildTracing(event) {
|
|
|
13665
14364
|
delete event.__braintrust_ai_sdk_cleanup;
|
|
13666
14365
|
}
|
|
13667
14366
|
}
|
|
14367
|
+
function extractAISDKStreamPart(chunk) {
|
|
14368
|
+
if (!isObject(chunk) || !isObject(chunk.part)) {
|
|
14369
|
+
return chunk;
|
|
14370
|
+
}
|
|
14371
|
+
return chunk.part;
|
|
14372
|
+
}
|
|
14373
|
+
function stringContent(value) {
|
|
14374
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
14375
|
+
}
|
|
14376
|
+
function rawValueHasAISDKContent(value) {
|
|
14377
|
+
if (value === void 0 || value === null) {
|
|
14378
|
+
return false;
|
|
14379
|
+
}
|
|
14380
|
+
if (typeof value === "string") {
|
|
14381
|
+
return value.length > 0;
|
|
14382
|
+
}
|
|
14383
|
+
if (!isObject(value)) {
|
|
14384
|
+
return true;
|
|
14385
|
+
}
|
|
14386
|
+
const delta = value.delta;
|
|
14387
|
+
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) => {
|
|
14388
|
+
if (!isObject(choice) || !isObject(choice.delta)) {
|
|
14389
|
+
return false;
|
|
14390
|
+
}
|
|
14391
|
+
const choiceDelta = choice.delta;
|
|
14392
|
+
if (stringContent(choiceDelta.content) || stringContent(choiceDelta.text)) {
|
|
14393
|
+
return true;
|
|
14394
|
+
}
|
|
14395
|
+
if (isObject(choiceDelta.function_call) && stringContent(choiceDelta.function_call.arguments)) {
|
|
14396
|
+
return true;
|
|
14397
|
+
}
|
|
14398
|
+
return Array.isArray(choiceDelta.tool_calls) && choiceDelta.tool_calls.some(
|
|
14399
|
+
(toolCall) => isObject(toolCall) && isObject(toolCall.function) && stringContent(toolCall.function.arguments)
|
|
14400
|
+
);
|
|
14401
|
+
})) {
|
|
14402
|
+
return true;
|
|
14403
|
+
}
|
|
14404
|
+
return false;
|
|
14405
|
+
}
|
|
14406
|
+
function isAISDKContentStreamChunk(chunk) {
|
|
14407
|
+
const part = extractAISDKStreamPart(chunk);
|
|
14408
|
+
if (typeof part === "string") {
|
|
14409
|
+
return part.length > 0;
|
|
14410
|
+
}
|
|
14411
|
+
if (!isObject(part) || typeof part.type !== "string") {
|
|
14412
|
+
return false;
|
|
14413
|
+
}
|
|
14414
|
+
switch (part.type) {
|
|
14415
|
+
case "text-delta":
|
|
14416
|
+
return stringContent(part.textDelta) !== void 0 || stringContent(part.delta) !== void 0 || stringContent(part.text) !== void 0 || stringContent(part.content) !== void 0;
|
|
14417
|
+
case "reasoning-delta":
|
|
14418
|
+
return stringContent(part.delta) !== void 0 || stringContent(part.text) !== void 0 || stringContent(part.content) !== void 0;
|
|
14419
|
+
case "tool-call":
|
|
14420
|
+
case "object":
|
|
14421
|
+
case "file":
|
|
14422
|
+
return true;
|
|
14423
|
+
case "tool-input-delta":
|
|
14424
|
+
case "tool-call-delta":
|
|
14425
|
+
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;
|
|
14426
|
+
case "raw":
|
|
14427
|
+
return rawValueHasAISDKContent(part.rawValue);
|
|
14428
|
+
default:
|
|
14429
|
+
return false;
|
|
14430
|
+
}
|
|
14431
|
+
}
|
|
14432
|
+
function isAISDKContentAsyncIterableChunk(chunk) {
|
|
14433
|
+
if (isAISDKContentStreamChunk(chunk)) {
|
|
14434
|
+
return true;
|
|
14435
|
+
}
|
|
14436
|
+
const part = extractAISDKStreamPart(chunk);
|
|
14437
|
+
return isObject(part) && typeof part.type !== "string";
|
|
14438
|
+
}
|
|
13668
14439
|
function patchAISDKStreamingResult(args) {
|
|
13669
14440
|
const { defaultDenyOutputPaths, endEvent, result, span, startTime } = args;
|
|
13670
14441
|
if (!result || typeof result !== "object") {
|
|
@@ -13677,7 +14448,7 @@ function patchAISDKStreamingResult(args) {
|
|
|
13677
14448
|
const wrappedBaseStream = resultRecord.baseStream.pipeThrough(
|
|
13678
14449
|
new TransformStream({
|
|
13679
14450
|
transform(chunk, controller) {
|
|
13680
|
-
if (firstChunkTime2 === void 0) {
|
|
14451
|
+
if (firstChunkTime2 === void 0 && isAISDKContentStreamChunk(chunk)) {
|
|
13681
14452
|
firstChunkTime2 = getCurrentUnixTimestamp();
|
|
13682
14453
|
}
|
|
13683
14454
|
controller.enqueue(chunk);
|
|
@@ -13721,8 +14492,8 @@ function patchAISDKStreamingResult(args) {
|
|
|
13721
14492
|
}
|
|
13722
14493
|
let firstChunkTime;
|
|
13723
14494
|
const wrappedStream = createPatchedAsyncIterable(streamField.stream, {
|
|
13724
|
-
onChunk: () => {
|
|
13725
|
-
if (firstChunkTime === void 0) {
|
|
14495
|
+
onChunk: (chunk) => {
|
|
14496
|
+
if (firstChunkTime === void 0 && isAISDKContentAsyncIterableChunk(chunk)) {
|
|
13726
14497
|
firstChunkTime = getCurrentUnixTimestamp();
|
|
13727
14498
|
}
|
|
13728
14499
|
},
|
|
@@ -14694,15 +15465,17 @@ function collectLocalMcpServerToolHookNames(serverName, serverConfig) {
|
|
|
14694
15465
|
|
|
14695
15466
|
// src/instrumentation/plugins/claude-agent-sdk-plugin.ts
|
|
14696
15467
|
var ROOT_LLM_PARENT_KEY = "__root__";
|
|
15468
|
+
var SUB_AGENT_PROMPT_SOURCE_PRIORITY = {
|
|
15469
|
+
delegation: 0,
|
|
15470
|
+
lifecycle: 1,
|
|
15471
|
+
sidechain: 2
|
|
15472
|
+
};
|
|
14697
15473
|
function llmParentKey(parentToolUseId) {
|
|
14698
15474
|
return parentToolUseId ?? ROOT_LLM_PARENT_KEY;
|
|
14699
15475
|
}
|
|
14700
15476
|
function isSubAgentDelegationToolName(toolName) {
|
|
14701
15477
|
return toolName === "Agent" || toolName === "Task";
|
|
14702
15478
|
}
|
|
14703
|
-
function shouldParentToolAsTaskSibling(toolName) {
|
|
14704
|
-
return toolName === "Agent" || toolName === "Task" || toolName === "Bash";
|
|
14705
|
-
}
|
|
14706
15479
|
function filterSerializableOptions(options) {
|
|
14707
15480
|
const allowedKeys = [
|
|
14708
15481
|
"model",
|
|
@@ -14839,26 +15612,39 @@ function extractUsageFromMessage(message) {
|
|
|
14839
15612
|
}
|
|
14840
15613
|
return metrics;
|
|
14841
15614
|
}
|
|
14842
|
-
function buildLLMInput(
|
|
14843
|
-
const promptMessages = [];
|
|
14844
|
-
if (typeof prompt === "string") {
|
|
14845
|
-
promptMessages.push({ content: prompt, role: "user" });
|
|
14846
|
-
} else if (capturedPromptMessages && capturedPromptMessages.length > 0) {
|
|
14847
|
-
for (const msg of capturedPromptMessages) {
|
|
14848
|
-
const role = msg.message?.role;
|
|
14849
|
-
const content = msg.message?.content;
|
|
14850
|
-
if (role && content !== void 0) {
|
|
14851
|
-
promptMessages.push({ content, role });
|
|
14852
|
-
}
|
|
14853
|
-
}
|
|
14854
|
-
}
|
|
15615
|
+
function buildLLMInput(promptMessages, conversationHistory) {
|
|
14855
15616
|
const inputParts = [...promptMessages, ...conversationHistory];
|
|
14856
15617
|
return inputParts.length > 0 ? inputParts : void 0;
|
|
14857
15618
|
}
|
|
15619
|
+
function conversationMessageFromSDKMessage(message) {
|
|
15620
|
+
const role = message.message?.role;
|
|
15621
|
+
const content = message.message?.content;
|
|
15622
|
+
if (role && content !== void 0) {
|
|
15623
|
+
return { content, role };
|
|
15624
|
+
}
|
|
15625
|
+
return void 0;
|
|
15626
|
+
}
|
|
15627
|
+
function messageContentHasBlockType(message, blockType) {
|
|
15628
|
+
const content = message.message?.content;
|
|
15629
|
+
return Array.isArray(content) && content.some(
|
|
15630
|
+
(block) => typeof block === "object" && block !== null && "type" in block && block.type === blockType
|
|
15631
|
+
);
|
|
15632
|
+
}
|
|
15633
|
+
function buildRootPromptMessages(prompt, capturedPromptMessages) {
|
|
15634
|
+
if (typeof prompt === "string") {
|
|
15635
|
+
return [{ content: prompt, role: "user" }];
|
|
15636
|
+
}
|
|
15637
|
+
if (!capturedPromptMessages || capturedPromptMessages.length === 0) {
|
|
15638
|
+
return [];
|
|
15639
|
+
}
|
|
15640
|
+
return capturedPromptMessages.map(conversationMessageFromSDKMessage).filter(
|
|
15641
|
+
(message) => message !== void 0
|
|
15642
|
+
);
|
|
15643
|
+
}
|
|
14858
15644
|
function formatCapturedMessages(messages) {
|
|
14859
15645
|
return messages.length > 0 ? messages : [];
|
|
14860
15646
|
}
|
|
14861
|
-
async function createLLMSpanForMessages(messages,
|
|
15647
|
+
async function createLLMSpanForMessages(messages, promptMessages, conversationHistory, options, startTime, parentSpan, existingSpan) {
|
|
14862
15648
|
if (messages.length === 0) {
|
|
14863
15649
|
return void 0;
|
|
14864
15650
|
}
|
|
@@ -14868,11 +15654,7 @@ async function createLLMSpanForMessages(messages, prompt, conversationHistory, o
|
|
|
14868
15654
|
}
|
|
14869
15655
|
const model = lastMessage.message.model || options.model;
|
|
14870
15656
|
const usage = extractUsageFromMessage(lastMessage);
|
|
14871
|
-
const input = buildLLMInput(
|
|
14872
|
-
prompt,
|
|
14873
|
-
conversationHistory,
|
|
14874
|
-
capturedPromptMessages
|
|
14875
|
-
);
|
|
15657
|
+
const input = buildLLMInput(promptMessages, conversationHistory);
|
|
14876
15658
|
const outputs = messages.map(
|
|
14877
15659
|
(m) => m.message?.content && m.message?.role ? { content: m.message.content, role: m.message.role } : void 0
|
|
14878
15660
|
).filter(
|
|
@@ -15003,8 +15785,7 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
|
|
|
15003
15785
|
},
|
|
15004
15786
|
name: parsed.displayName,
|
|
15005
15787
|
parent: await resolveParentSpan(toolUseID, {
|
|
15006
|
-
agentId: input.agent_id
|
|
15007
|
-
preferTaskSiblingParent: shouldParentToolAsTaskSibling(parsed.toolName)
|
|
15788
|
+
agentId: input.agent_id
|
|
15008
15789
|
}),
|
|
15009
15790
|
spanAttributes: { type: "tool" /* TOOL */ }
|
|
15010
15791
|
});
|
|
@@ -15250,12 +16031,37 @@ function injectTracingHooks(options, resolveParentSpan, activeToolSpans, localTo
|
|
|
15250
16031
|
}
|
|
15251
16032
|
};
|
|
15252
16033
|
}
|
|
16034
|
+
function setSubAgentPromptMessages(state, parentToolUseId, promptMessages, source) {
|
|
16035
|
+
if (promptMessages.length === 0) {
|
|
16036
|
+
return;
|
|
16037
|
+
}
|
|
16038
|
+
const parentKey = llmParentKey(parentToolUseId);
|
|
16039
|
+
const sourcePriority = SUB_AGENT_PROMPT_SOURCE_PRIORITY[source];
|
|
16040
|
+
const currentPriority = state.promptSourcePriorityByParentKey.get(parentKey) ?? -1;
|
|
16041
|
+
if (sourcePriority > currentPriority) {
|
|
16042
|
+
state.promptMessagesByParentKey.set(parentKey, promptMessages);
|
|
16043
|
+
state.promptSourcePriorityByParentKey.set(parentKey, sourcePriority);
|
|
16044
|
+
}
|
|
16045
|
+
}
|
|
16046
|
+
function getConversationHistory(state, parentKey) {
|
|
16047
|
+
let conversationHistory = state.conversationHistoryByParentKey.get(parentKey);
|
|
16048
|
+
if (!conversationHistory) {
|
|
16049
|
+
conversationHistory = [];
|
|
16050
|
+
state.conversationHistoryByParentKey.set(parentKey, conversationHistory);
|
|
16051
|
+
}
|
|
16052
|
+
return conversationHistory;
|
|
16053
|
+
}
|
|
15253
16054
|
async function finalizeCurrentMessageGroup(state) {
|
|
15254
16055
|
if (state.currentMessages.length === 0) {
|
|
15255
16056
|
return;
|
|
15256
16057
|
}
|
|
15257
16058
|
const parentToolUseId = state.currentMessages[0]?.parent_tool_use_id ?? null;
|
|
15258
16059
|
const parentKey = llmParentKey(parentToolUseId);
|
|
16060
|
+
const conversationHistory = getConversationHistory(state, parentKey);
|
|
16061
|
+
const promptMessages = parentToolUseId ? state.promptMessagesByParentKey.get(parentKey) ?? [] : buildRootPromptMessages(
|
|
16062
|
+
state.originalPrompt,
|
|
16063
|
+
state.capturedPromptMessages
|
|
16064
|
+
);
|
|
15259
16065
|
let parentSpan = await state.span.export();
|
|
15260
16066
|
if (parentToolUseId) {
|
|
15261
16067
|
const subAgentSpan = state.subAgentSpans.get(parentToolUseId);
|
|
@@ -15266,11 +16072,10 @@ async function finalizeCurrentMessageGroup(state) {
|
|
|
15266
16072
|
const existingLlmSpan = state.activeLlmSpansByParentToolUse.get(parentKey);
|
|
15267
16073
|
const llmSpanResult = await createLLMSpanForMessages(
|
|
15268
16074
|
state.currentMessages,
|
|
15269
|
-
|
|
15270
|
-
|
|
16075
|
+
promptMessages,
|
|
16076
|
+
conversationHistory,
|
|
15271
16077
|
state.options,
|
|
15272
16078
|
state.currentMessageStartTime,
|
|
15273
|
-
state.capturedPromptMessages,
|
|
15274
16079
|
parentSpan,
|
|
15275
16080
|
existingLlmSpan
|
|
15276
16081
|
);
|
|
@@ -15284,6 +16089,7 @@ async function finalizeCurrentMessageGroup(state) {
|
|
|
15284
16089
|
state.latestRootLlmParentRef.value = llmSpanResult.spanExport;
|
|
15285
16090
|
}
|
|
15286
16091
|
if (llmSpanResult.finalMessage) {
|
|
16092
|
+
conversationHistory.push(llmSpanResult.finalMessage);
|
|
15287
16093
|
state.finalResults.push(llmSpanResult.finalMessage);
|
|
15288
16094
|
}
|
|
15289
16095
|
}
|
|
@@ -15311,6 +16117,15 @@ function maybeTrackToolUseContext(state, message) {
|
|
|
15311
16117
|
description: getStringProperty(block.input, "description"),
|
|
15312
16118
|
toolUseId: block.id
|
|
15313
16119
|
});
|
|
16120
|
+
const prompt = getStringProperty(block.input, "prompt");
|
|
16121
|
+
if (prompt) {
|
|
16122
|
+
setSubAgentPromptMessages(
|
|
16123
|
+
state,
|
|
16124
|
+
block.id,
|
|
16125
|
+
[{ content: prompt, role: "user" }],
|
|
16126
|
+
"delegation"
|
|
16127
|
+
);
|
|
16128
|
+
}
|
|
15314
16129
|
}
|
|
15315
16130
|
}
|
|
15316
16131
|
}
|
|
@@ -15429,6 +16244,14 @@ async function maybeHandleTaskLifecycleMessage(state, message) {
|
|
|
15429
16244
|
};
|
|
15430
16245
|
if (message.subtype === "task_started") {
|
|
15431
16246
|
const prompt = getStringProperty(message, "prompt");
|
|
16247
|
+
if (prompt) {
|
|
16248
|
+
setSubAgentPromptMessages(
|
|
16249
|
+
state,
|
|
16250
|
+
toolUseId,
|
|
16251
|
+
[{ content: prompt, role: "user" }],
|
|
16252
|
+
"lifecycle"
|
|
16253
|
+
);
|
|
16254
|
+
}
|
|
15432
16255
|
subAgentSpan.log({
|
|
15433
16256
|
input: prompt,
|
|
15434
16257
|
metadata
|
|
@@ -15479,6 +16302,28 @@ async function handleStreamMessage(state, message) {
|
|
|
15479
16302
|
return;
|
|
15480
16303
|
}
|
|
15481
16304
|
await maybeStartSubAgentSpan(state, message);
|
|
16305
|
+
const messageParentToolUseId = message.parent_tool_use_id;
|
|
16306
|
+
if (messageParentToolUseId && message.type === "user") {
|
|
16307
|
+
const conversationMessage = conversationMessageFromSDKMessage(message);
|
|
16308
|
+
if (conversationMessage?.role === "user") {
|
|
16309
|
+
await finalizeCurrentMessageGroup(state);
|
|
16310
|
+
const parentKey = llmParentKey(messageParentToolUseId);
|
|
16311
|
+
const conversationHistory = getConversationHistory(state, parentKey);
|
|
16312
|
+
const currentPromptSourcePriority = state.promptSourcePriorityByParentKey.get(parentKey) ?? -1;
|
|
16313
|
+
const canUseAsInitialSidechainPrompt = conversationHistory.length === 0 && currentPromptSourcePriority < SUB_AGENT_PROMPT_SOURCE_PRIORITY.sidechain && !messageContentHasBlockType(message, "tool_result");
|
|
16314
|
+
if (!canUseAsInitialSidechainPrompt) {
|
|
16315
|
+
conversationHistory.push(conversationMessage);
|
|
16316
|
+
return;
|
|
16317
|
+
}
|
|
16318
|
+
setSubAgentPromptMessages(
|
|
16319
|
+
state,
|
|
16320
|
+
messageParentToolUseId,
|
|
16321
|
+
[conversationMessage],
|
|
16322
|
+
"sidechain"
|
|
16323
|
+
);
|
|
16324
|
+
return;
|
|
16325
|
+
}
|
|
16326
|
+
}
|
|
15482
16327
|
const messageId = message.message?.id;
|
|
15483
16328
|
if (messageId && messageId !== state.currentMessageId) {
|
|
15484
16329
|
await finalizeCurrentMessageGroup(state);
|
|
@@ -15630,6 +16475,7 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
15630
16475
|
}
|
|
15631
16476
|
const activeToolSpans = /* @__PURE__ */ new Map();
|
|
15632
16477
|
const activeLlmSpansByParentToolUse = /* @__PURE__ */ new Map();
|
|
16478
|
+
const conversationHistoryByParentKey = /* @__PURE__ */ new Map();
|
|
15633
16479
|
const subAgentSpans = /* @__PURE__ */ new Map();
|
|
15634
16480
|
const endedSubAgentSpans = /* @__PURE__ */ new Set();
|
|
15635
16481
|
const toolUseToParent = /* @__PURE__ */ new Map();
|
|
@@ -15639,6 +16485,8 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
15639
16485
|
};
|
|
15640
16486
|
const subAgentDetailsByToolUseId = /* @__PURE__ */ new Map();
|
|
15641
16487
|
const taskIdToToolUseId = /* @__PURE__ */ new Map();
|
|
16488
|
+
const promptMessagesByParentKey = /* @__PURE__ */ new Map();
|
|
16489
|
+
const promptSourcePriorityByParentKey = /* @__PURE__ */ new Map();
|
|
15642
16490
|
const localToolContext = createClaudeLocalToolContext();
|
|
15643
16491
|
const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
|
|
15644
16492
|
const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
|
|
@@ -15647,38 +16495,19 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
15647
16495
|
const parentToolUseId = trackedParentToolUseId ?? (context?.agentId ? taskIdToToolUseId.get(context.agentId) ?? null : null);
|
|
15648
16496
|
const parentKey = llmParentKey(parentToolUseId);
|
|
15649
16497
|
const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
|
|
15650
|
-
|
|
15651
|
-
|
|
15652
|
-
|
|
15653
|
-
|
|
15654
|
-
|
|
15655
|
-
|
|
15656
|
-
|
|
15657
|
-
|
|
15658
|
-
|
|
15659
|
-
|
|
15660
|
-
|
|
15661
|
-
}
|
|
15662
|
-
if (parentToolUseId) {
|
|
15663
|
-
const subAgentSpan = await ensureSubAgentSpan(
|
|
15664
|
-
subAgentDetailsByToolUseId,
|
|
15665
|
-
span,
|
|
15666
|
-
activeToolSpans,
|
|
15667
|
-
subAgentSpans,
|
|
15668
|
-
parentToolUseId
|
|
15669
|
-
);
|
|
15670
|
-
return subAgentSpan.export();
|
|
15671
|
-
}
|
|
15672
|
-
return span.export();
|
|
15673
|
-
}
|
|
15674
|
-
if (activeLlmSpan) {
|
|
15675
|
-
return activeLlmSpan.export();
|
|
16498
|
+
const latestLlmParent = parentToolUseId ? latestLlmParentBySubAgentToolUse.get(parentToolUseId) : latestRootLlmParentRef.value;
|
|
16499
|
+
if (!activeLlmSpan && !latestLlmParent) {
|
|
16500
|
+
await ensureActiveLlmSpanForParentToolUse(
|
|
16501
|
+
span,
|
|
16502
|
+
activeLlmSpansByParentToolUse,
|
|
16503
|
+
subAgentDetailsByToolUseId,
|
|
16504
|
+
activeToolSpans,
|
|
16505
|
+
subAgentSpans,
|
|
16506
|
+
parentToolUseId,
|
|
16507
|
+
getCurrentUnixTimestamp()
|
|
16508
|
+
);
|
|
15676
16509
|
}
|
|
15677
16510
|
if (parentToolUseId) {
|
|
15678
|
-
const parentLlm = latestLlmParentBySubAgentToolUse.get(parentToolUseId);
|
|
15679
|
-
if (parentLlm) {
|
|
15680
|
-
return parentLlm;
|
|
15681
|
-
}
|
|
15682
16511
|
const subAgentSpan = await ensureSubAgentSpan(
|
|
15683
16512
|
subAgentDetailsByToolUseId,
|
|
15684
16513
|
span,
|
|
@@ -15688,9 +16517,6 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
15688
16517
|
);
|
|
15689
16518
|
return subAgentSpan.export();
|
|
15690
16519
|
}
|
|
15691
|
-
if (latestRootLlmParentRef.value) {
|
|
15692
|
-
return latestRootLlmParentRef.value;
|
|
15693
|
-
}
|
|
15694
16520
|
return span.export();
|
|
15695
16521
|
};
|
|
15696
16522
|
localToolContext.resolveLocalToolParent = resolveToolUseParentSpan;
|
|
@@ -15711,6 +16537,7 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
15711
16537
|
accumulatedOutputTokens: 0,
|
|
15712
16538
|
activeLlmSpansByParentToolUse,
|
|
15713
16539
|
activeToolSpans,
|
|
16540
|
+
conversationHistoryByParentKey,
|
|
15714
16541
|
capturedPromptMessages,
|
|
15715
16542
|
currentMessageId: void 0,
|
|
15716
16543
|
currentMessageStartTime: startTime,
|
|
@@ -15721,7 +16548,9 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
15721
16548
|
originalPrompt,
|
|
15722
16549
|
processing: Promise.resolve(),
|
|
15723
16550
|
promptDone,
|
|
16551
|
+
promptMessagesByParentKey,
|
|
15724
16552
|
promptStarted: () => promptStarted,
|
|
16553
|
+
promptSourcePriorityByParentKey,
|
|
15725
16554
|
span,
|
|
15726
16555
|
subAgentDetailsByToolUseId,
|
|
15727
16556
|
subAgentSpans,
|
|
@@ -17150,6 +17979,10 @@ var googleGenAIChannels = defineChannels("@google/genai", {
|
|
|
17150
17979
|
embedContent: channel({
|
|
17151
17980
|
channelName: "models.embedContent",
|
|
17152
17981
|
kind: "async"
|
|
17982
|
+
}),
|
|
17983
|
+
interactionsCreate: channel({
|
|
17984
|
+
channelName: "interactions.create",
|
|
17985
|
+
kind: "async"
|
|
17153
17986
|
})
|
|
17154
17987
|
});
|
|
17155
17988
|
|
|
@@ -17177,6 +18010,7 @@ var GoogleGenAIPlugin = class extends BasePlugin {
|
|
|
17177
18010
|
this.subscribeToGenerateContentChannel();
|
|
17178
18011
|
this.subscribeToGenerateContentStreamChannel();
|
|
17179
18012
|
this.subscribeToEmbedContentChannel();
|
|
18013
|
+
this.subscribeToInteractionsCreateChannel();
|
|
17180
18014
|
}
|
|
17181
18015
|
subscribeToGenerateContentChannel() {
|
|
17182
18016
|
const tracingChannel2 = googleGenAIChannels.generateContent.tracingChannel();
|
|
@@ -17349,7 +18183,30 @@ var GoogleGenAIPlugin = class extends BasePlugin {
|
|
|
17349
18183
|
tracingChannel2.unsubscribe(handlers);
|
|
17350
18184
|
});
|
|
17351
18185
|
}
|
|
18186
|
+
subscribeToInteractionsCreateChannel() {
|
|
18187
|
+
this.unsubscribers.push(
|
|
18188
|
+
traceStreamingChannel(
|
|
18189
|
+
googleGenAIChannels.interactionsCreate,
|
|
18190
|
+
{
|
|
18191
|
+
name: "create_interaction",
|
|
18192
|
+
shouldTrace: ([params]) => !isBackgroundInteractionCreate(params),
|
|
18193
|
+
type: "llm" /* LLM */,
|
|
18194
|
+
extractInput: ([params]) => ({
|
|
18195
|
+
input: serializeInteractionInput(params),
|
|
18196
|
+
metadata: extractInteractionMetadata(params)
|
|
18197
|
+
}),
|
|
18198
|
+
extractOutput: (result) => serializeInteractionValue(result),
|
|
18199
|
+
extractMetadata: (result) => extractInteractionResponseMetadata(result),
|
|
18200
|
+
extractMetrics: (result, startTime) => cleanMetrics3(extractInteractionMetrics(result, startTime)),
|
|
18201
|
+
aggregateChunks: (chunks, _result, _event, startTime) => aggregateInteractionEvents(chunks, startTime)
|
|
18202
|
+
}
|
|
18203
|
+
)
|
|
18204
|
+
);
|
|
18205
|
+
}
|
|
17352
18206
|
};
|
|
18207
|
+
function isBackgroundInteractionCreate(params) {
|
|
18208
|
+
return tryToDict(params)?.background === true;
|
|
18209
|
+
}
|
|
17353
18210
|
function ensureSpanState(states, event, create) {
|
|
17354
18211
|
const existing = states.get(event);
|
|
17355
18212
|
if (existing) {
|
|
@@ -17557,6 +18414,60 @@ function serializeEmbedContentInput(params) {
|
|
|
17557
18414
|
}
|
|
17558
18415
|
return input;
|
|
17559
18416
|
}
|
|
18417
|
+
function serializeInteractionInput(params) {
|
|
18418
|
+
const input = {
|
|
18419
|
+
input: serializeInteractionValue(params.input)
|
|
18420
|
+
};
|
|
18421
|
+
for (const key of [
|
|
18422
|
+
"model",
|
|
18423
|
+
"agent",
|
|
18424
|
+
"agent_config",
|
|
18425
|
+
"api_version",
|
|
18426
|
+
"background",
|
|
18427
|
+
"environment",
|
|
18428
|
+
"generation_config",
|
|
18429
|
+
"previous_interaction_id",
|
|
18430
|
+
"response_format",
|
|
18431
|
+
"response_mime_type",
|
|
18432
|
+
"response_modalities",
|
|
18433
|
+
"service_tier",
|
|
18434
|
+
"store",
|
|
18435
|
+
"stream",
|
|
18436
|
+
"system_instruction",
|
|
18437
|
+
"webhook_config"
|
|
18438
|
+
]) {
|
|
18439
|
+
const value = params[key];
|
|
18440
|
+
if (value !== void 0) {
|
|
18441
|
+
input[key] = serializeInteractionValue(value);
|
|
18442
|
+
}
|
|
18443
|
+
}
|
|
18444
|
+
return input;
|
|
18445
|
+
}
|
|
18446
|
+
function extractInteractionMetadata(params) {
|
|
18447
|
+
const metadata = {};
|
|
18448
|
+
for (const key of [
|
|
18449
|
+
"model",
|
|
18450
|
+
"agent",
|
|
18451
|
+
"agent_config",
|
|
18452
|
+
"generation_config",
|
|
18453
|
+
"system_instruction",
|
|
18454
|
+
"response_format",
|
|
18455
|
+
"response_mime_type",
|
|
18456
|
+
"response_modalities",
|
|
18457
|
+
"service_tier"
|
|
18458
|
+
]) {
|
|
18459
|
+
const value = params[key];
|
|
18460
|
+
if (value !== void 0) {
|
|
18461
|
+
metadata[key] = serializeInteractionValue(value);
|
|
18462
|
+
}
|
|
18463
|
+
}
|
|
18464
|
+
if (Array.isArray(params.tools)) {
|
|
18465
|
+
metadata.tools = params.tools.map(
|
|
18466
|
+
(tool) => serializeInteractionValue(tool)
|
|
18467
|
+
);
|
|
18468
|
+
}
|
|
18469
|
+
return metadata;
|
|
18470
|
+
}
|
|
17560
18471
|
function serializeContentCollection(contents) {
|
|
17561
18472
|
if (contents === null || contents === void 0) {
|
|
17562
18473
|
return null;
|
|
@@ -17587,21 +18498,8 @@ function serializePart(part) {
|
|
|
17587
18498
|
}
|
|
17588
18499
|
if (part.inlineData && part.inlineData.data) {
|
|
17589
18500
|
const { data, mimeType } = part.inlineData;
|
|
17590
|
-
|
|
17591
|
-
|
|
17592
|
-
const filename = `file.${extension}`;
|
|
17593
|
-
const buffer = typeof data === "string" ? typeof Buffer !== "undefined" ? Buffer.from(data, "base64") : new Uint8Array(
|
|
17594
|
-
atob(data).split("").map((c) => c.charCodeAt(0))
|
|
17595
|
-
) : typeof Buffer !== "undefined" ? Buffer.from(data) : new Uint8Array(data);
|
|
17596
|
-
const arrayBuffer = buffer instanceof Uint8Array ? buffer.buffer.slice(
|
|
17597
|
-
buffer.byteOffset,
|
|
17598
|
-
buffer.byteOffset + buffer.byteLength
|
|
17599
|
-
) : buffer;
|
|
17600
|
-
const attachment = new Attachment({
|
|
17601
|
-
data: arrayBuffer,
|
|
17602
|
-
filename,
|
|
17603
|
-
contentType: mimeType || "application/octet-stream"
|
|
17604
|
-
});
|
|
18501
|
+
const attachment = createAttachmentFromInlineData(data, mimeType);
|
|
18502
|
+
if (attachment) {
|
|
17605
18503
|
return {
|
|
17606
18504
|
image_url: { url: attachment }
|
|
17607
18505
|
};
|
|
@@ -17609,6 +18507,59 @@ function serializePart(part) {
|
|
|
17609
18507
|
}
|
|
17610
18508
|
return part;
|
|
17611
18509
|
}
|
|
18510
|
+
function serializeInteractionValue(value, seen = /* @__PURE__ */ new WeakSet()) {
|
|
18511
|
+
if (value === null || value === void 0 || typeof value !== "object") {
|
|
18512
|
+
return value;
|
|
18513
|
+
}
|
|
18514
|
+
if (Array.isArray(value)) {
|
|
18515
|
+
return value.map((item) => serializeInteractionValue(item, seen));
|
|
18516
|
+
}
|
|
18517
|
+
const dict = tryToDict(value);
|
|
18518
|
+
if (dict === null || dict === void 0 || typeof dict !== "object") {
|
|
18519
|
+
return dict;
|
|
18520
|
+
}
|
|
18521
|
+
if (Array.isArray(dict)) {
|
|
18522
|
+
return dict.map((item) => serializeInteractionValue(item, seen));
|
|
18523
|
+
}
|
|
18524
|
+
if (seen.has(dict)) {
|
|
18525
|
+
return "[Circular]";
|
|
18526
|
+
}
|
|
18527
|
+
seen.add(dict);
|
|
18528
|
+
try {
|
|
18529
|
+
const serialized = {};
|
|
18530
|
+
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;
|
|
18531
|
+
const attachment = mimeType && "data" in dict && dict.data !== void 0 ? createAttachmentFromInlineData(dict.data, mimeType) : null;
|
|
18532
|
+
for (const [key, entry] of Object.entries(dict)) {
|
|
18533
|
+
if (key === "data" && attachment) {
|
|
18534
|
+
serialized[key] = attachment;
|
|
18535
|
+
} else {
|
|
18536
|
+
serialized[key] = serializeInteractionValue(entry, seen);
|
|
18537
|
+
}
|
|
18538
|
+
}
|
|
18539
|
+
return serialized;
|
|
18540
|
+
} finally {
|
|
18541
|
+
seen.delete(dict);
|
|
18542
|
+
}
|
|
18543
|
+
}
|
|
18544
|
+
function createAttachmentFromInlineData(data, mimeType) {
|
|
18545
|
+
if (!(data instanceof Uint8Array || typeof Buffer !== "undefined" && Buffer.isBuffer(data) || typeof data === "string")) {
|
|
18546
|
+
return null;
|
|
18547
|
+
}
|
|
18548
|
+
const extension = mimeType ? mimeType.split("/")[1] : "bin";
|
|
18549
|
+
const filename = `file.${extension}`;
|
|
18550
|
+
const buffer = typeof data === "string" ? typeof Buffer !== "undefined" ? Buffer.from(data, "base64") : new Uint8Array(
|
|
18551
|
+
atob(data).split("").map((c) => c.charCodeAt(0))
|
|
18552
|
+
) : typeof Buffer !== "undefined" ? Buffer.from(data) : new Uint8Array(data);
|
|
18553
|
+
const arrayBuffer = buffer instanceof Uint8Array ? buffer.buffer.slice(
|
|
18554
|
+
buffer.byteOffset,
|
|
18555
|
+
buffer.byteOffset + buffer.byteLength
|
|
18556
|
+
) : buffer;
|
|
18557
|
+
return new Attachment({
|
|
18558
|
+
data: arrayBuffer,
|
|
18559
|
+
filename,
|
|
18560
|
+
contentType: mimeType || "application/octet-stream"
|
|
18561
|
+
});
|
|
18562
|
+
}
|
|
17612
18563
|
function serializeGenerateContentTools(params) {
|
|
17613
18564
|
const config = params.config ? tryToDict(params.config) : null;
|
|
17614
18565
|
const tools = config?.tools;
|
|
@@ -17693,6 +18644,33 @@ function extractEmbedContentMetrics(response, startTime) {
|
|
|
17693
18644
|
}
|
|
17694
18645
|
return metrics;
|
|
17695
18646
|
}
|
|
18647
|
+
function extractInteractionMetrics(response, startTime) {
|
|
18648
|
+
const metrics = {};
|
|
18649
|
+
if (startTime !== void 0) {
|
|
18650
|
+
const end = getCurrentUnixTimestamp();
|
|
18651
|
+
metrics.start = startTime;
|
|
18652
|
+
metrics.end = end;
|
|
18653
|
+
metrics.duration = end - startTime;
|
|
18654
|
+
}
|
|
18655
|
+
if (response?.usage) {
|
|
18656
|
+
populateInteractionUsageMetrics(metrics, response.usage);
|
|
18657
|
+
}
|
|
18658
|
+
return metrics;
|
|
18659
|
+
}
|
|
18660
|
+
function extractInteractionResponseMetadata(response) {
|
|
18661
|
+
const responseDict = tryToDict(response);
|
|
18662
|
+
if (!responseDict) {
|
|
18663
|
+
return void 0;
|
|
18664
|
+
}
|
|
18665
|
+
const metadata = {};
|
|
18666
|
+
if (typeof responseDict.id === "string") {
|
|
18667
|
+
metadata.interaction_id = responseDict.id;
|
|
18668
|
+
}
|
|
18669
|
+
if (typeof responseDict.status === "string") {
|
|
18670
|
+
metadata.status = responseDict.status;
|
|
18671
|
+
}
|
|
18672
|
+
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
18673
|
+
}
|
|
17696
18674
|
function extractEmbedPromptTokenCount(response) {
|
|
17697
18675
|
if (!response) {
|
|
17698
18676
|
return void 0;
|
|
@@ -17755,6 +18733,23 @@ function populateUsageMetrics(metrics, usage) {
|
|
|
17755
18733
|
metrics.completion_reasoning_tokens = usage.thoughtsTokenCount;
|
|
17756
18734
|
}
|
|
17757
18735
|
}
|
|
18736
|
+
function populateInteractionUsageMetrics(metrics, usage) {
|
|
18737
|
+
if (typeof usage.total_input_tokens === "number") {
|
|
18738
|
+
metrics.prompt_tokens = usage.total_input_tokens;
|
|
18739
|
+
}
|
|
18740
|
+
if (typeof usage.total_output_tokens === "number") {
|
|
18741
|
+
metrics.completion_tokens = usage.total_output_tokens;
|
|
18742
|
+
}
|
|
18743
|
+
if (typeof usage.total_tokens === "number") {
|
|
18744
|
+
metrics.tokens = usage.total_tokens;
|
|
18745
|
+
}
|
|
18746
|
+
if (typeof usage.total_cached_tokens === "number") {
|
|
18747
|
+
metrics.prompt_cached_tokens = usage.total_cached_tokens;
|
|
18748
|
+
}
|
|
18749
|
+
if (typeof usage.total_thought_tokens === "number") {
|
|
18750
|
+
metrics.completion_reasoning_tokens = usage.total_thought_tokens;
|
|
18751
|
+
}
|
|
18752
|
+
}
|
|
17758
18753
|
function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
|
|
17759
18754
|
const end = getCurrentUnixTimestamp();
|
|
17760
18755
|
const metrics = {
|
|
@@ -17852,6 +18847,146 @@ function aggregateGenerateContentChunks(chunks, startTime, firstTokenTime) {
|
|
|
17852
18847
|
}
|
|
17853
18848
|
return { aggregated, metrics };
|
|
17854
18849
|
}
|
|
18850
|
+
function aggregateInteractionEvents(chunks, startTime) {
|
|
18851
|
+
const end = getCurrentUnixTimestamp();
|
|
18852
|
+
const metrics = {};
|
|
18853
|
+
if (startTime !== void 0) {
|
|
18854
|
+
metrics.start = startTime;
|
|
18855
|
+
metrics.end = end;
|
|
18856
|
+
metrics.duration = end - startTime;
|
|
18857
|
+
}
|
|
18858
|
+
let latestInteraction;
|
|
18859
|
+
let latestUsage;
|
|
18860
|
+
let status;
|
|
18861
|
+
let outputText = "";
|
|
18862
|
+
const steps = /* @__PURE__ */ new Map();
|
|
18863
|
+
for (const chunk of chunks) {
|
|
18864
|
+
const event = tryToDict(chunk);
|
|
18865
|
+
if (!event) {
|
|
18866
|
+
continue;
|
|
18867
|
+
}
|
|
18868
|
+
const usage = extractInteractionUsageFromEvent(event);
|
|
18869
|
+
if (usage) {
|
|
18870
|
+
latestUsage = usage;
|
|
18871
|
+
}
|
|
18872
|
+
const interaction = tryToDict(event.interaction);
|
|
18873
|
+
if (interaction) {
|
|
18874
|
+
latestInteraction = serializeInteractionValue(interaction);
|
|
18875
|
+
if (typeof interaction.status === "string") {
|
|
18876
|
+
status = interaction.status;
|
|
18877
|
+
}
|
|
18878
|
+
}
|
|
18879
|
+
if (typeof event.status === "string") {
|
|
18880
|
+
status = event.status;
|
|
18881
|
+
}
|
|
18882
|
+
const index = typeof event.index === "number" ? event.index : void 0;
|
|
18883
|
+
if (index === void 0) {
|
|
18884
|
+
continue;
|
|
18885
|
+
}
|
|
18886
|
+
if (event.event_type === "step.start") {
|
|
18887
|
+
const compact = compactInteractionStep(event.step);
|
|
18888
|
+
compact.index = index;
|
|
18889
|
+
steps.set(index, compact);
|
|
18890
|
+
continue;
|
|
18891
|
+
}
|
|
18892
|
+
if (event.event_type === "step.delta") {
|
|
18893
|
+
const step = steps.get(index) ?? { index };
|
|
18894
|
+
const textDelta = applyInteractionDelta(step, event.delta);
|
|
18895
|
+
if (textDelta) {
|
|
18896
|
+
outputText += textDelta;
|
|
18897
|
+
}
|
|
18898
|
+
steps.set(index, step);
|
|
18899
|
+
}
|
|
18900
|
+
}
|
|
18901
|
+
if (latestUsage) {
|
|
18902
|
+
populateInteractionUsageMetrics(metrics, latestUsage);
|
|
18903
|
+
}
|
|
18904
|
+
const output = latestInteraction ? { ...latestInteraction } : {};
|
|
18905
|
+
if (status) {
|
|
18906
|
+
output.status = status;
|
|
18907
|
+
}
|
|
18908
|
+
if (outputText) {
|
|
18909
|
+
output.output_text = outputText;
|
|
18910
|
+
}
|
|
18911
|
+
if (latestUsage) {
|
|
18912
|
+
output.usage = serializeInteractionValue(latestUsage);
|
|
18913
|
+
}
|
|
18914
|
+
const compactSteps = Array.from(steps.values()).sort(
|
|
18915
|
+
(left, right) => Number(left.index ?? 0) - Number(right.index ?? 0)
|
|
18916
|
+
);
|
|
18917
|
+
if (compactSteps.length > 0) {
|
|
18918
|
+
output.steps = compactSteps;
|
|
18919
|
+
}
|
|
18920
|
+
const metadata = {};
|
|
18921
|
+
if (typeof output.id === "string") {
|
|
18922
|
+
metadata.interaction_id = output.id;
|
|
18923
|
+
}
|
|
18924
|
+
if (typeof output.status === "string") {
|
|
18925
|
+
metadata.status = output.status;
|
|
18926
|
+
}
|
|
18927
|
+
return {
|
|
18928
|
+
output,
|
|
18929
|
+
metrics: cleanMetrics3(metrics),
|
|
18930
|
+
...Object.keys(metadata).length > 0 ? { metadata } : {}
|
|
18931
|
+
};
|
|
18932
|
+
}
|
|
18933
|
+
function extractInteractionUsageFromEvent(event) {
|
|
18934
|
+
const metadata = tryToDict(event.metadata);
|
|
18935
|
+
const metadataUsage = tryToDict(metadata?.usage);
|
|
18936
|
+
if (metadataUsage) {
|
|
18937
|
+
return metadataUsage;
|
|
18938
|
+
}
|
|
18939
|
+
const metadataTotalUsage = tryToDict(metadata?.total_usage);
|
|
18940
|
+
if (metadataTotalUsage) {
|
|
18941
|
+
return metadataTotalUsage;
|
|
18942
|
+
}
|
|
18943
|
+
const interaction = tryToDict(event.interaction);
|
|
18944
|
+
const interactionUsage = tryToDict(interaction?.usage);
|
|
18945
|
+
return interactionUsage ? interactionUsage : void 0;
|
|
18946
|
+
}
|
|
18947
|
+
function compactInteractionStep(step) {
|
|
18948
|
+
const stepDict = tryToDict(step);
|
|
18949
|
+
if (!stepDict) {
|
|
18950
|
+
return {};
|
|
18951
|
+
}
|
|
18952
|
+
const compact = {};
|
|
18953
|
+
for (const key of [
|
|
18954
|
+
"type",
|
|
18955
|
+
"content",
|
|
18956
|
+
"name",
|
|
18957
|
+
"server_name",
|
|
18958
|
+
"arguments",
|
|
18959
|
+
"result",
|
|
18960
|
+
"is_error"
|
|
18961
|
+
]) {
|
|
18962
|
+
if (stepDict[key] !== void 0) {
|
|
18963
|
+
compact[key] = serializeInteractionValue(stepDict[key]);
|
|
18964
|
+
}
|
|
18965
|
+
}
|
|
18966
|
+
return Object.keys(compact).length > 0 ? compact : serializeInteractionValue(stepDict);
|
|
18967
|
+
}
|
|
18968
|
+
function applyInteractionDelta(step, delta) {
|
|
18969
|
+
const deltaDict = tryToDict(delta);
|
|
18970
|
+
if (!deltaDict) {
|
|
18971
|
+
return void 0;
|
|
18972
|
+
}
|
|
18973
|
+
const deltaType = deltaDict.type;
|
|
18974
|
+
if (typeof deltaType === "string" && typeof step.type !== "string") {
|
|
18975
|
+
step.type = deltaType === "text" ? "model_output" : deltaType;
|
|
18976
|
+
}
|
|
18977
|
+
if (deltaType === "text" && typeof deltaDict.text === "string") {
|
|
18978
|
+
step.text = `${typeof step.text === "string" ? step.text : ""}${deltaDict.text}`;
|
|
18979
|
+
return deltaDict.text;
|
|
18980
|
+
}
|
|
18981
|
+
if (deltaType === "arguments_delta" && typeof deltaDict.arguments === "string") {
|
|
18982
|
+
step.arguments = `${typeof step.arguments === "string" ? step.arguments : ""}${deltaDict.arguments}`;
|
|
18983
|
+
return void 0;
|
|
18984
|
+
}
|
|
18985
|
+
const deltas = Array.isArray(step.deltas) ? step.deltas : [];
|
|
18986
|
+
deltas.push(serializeInteractionValue(deltaDict));
|
|
18987
|
+
step.deltas = deltas;
|
|
18988
|
+
return void 0;
|
|
18989
|
+
}
|
|
17855
18990
|
function cleanMetrics3(metrics) {
|
|
17856
18991
|
const cleaned = {};
|
|
17857
18992
|
for (const [key, value] of Object.entries(metrics)) {
|
|
@@ -23678,7 +24813,8 @@ var FlueObserveBridge = class {
|
|
|
23678
24813
|
metadata
|
|
23679
24814
|
}
|
|
23680
24815
|
});
|
|
23681
|
-
|
|
24816
|
+
const activeContext = enterCurrentFlueSpan(span);
|
|
24817
|
+
this.runsById.set(event.runId, { activeContext, metadata, span });
|
|
23682
24818
|
}
|
|
23683
24819
|
handleRunEnd(event) {
|
|
23684
24820
|
const state = this.runsById.get(event.runId);
|
|
@@ -23696,6 +24832,7 @@ var FlueObserveBridge = class {
|
|
|
23696
24832
|
});
|
|
23697
24833
|
safeEnd(state.span, eventTime(event.timestamp));
|
|
23698
24834
|
this.runsById.delete(event.runId);
|
|
24835
|
+
restoreCurrentFlueSpan(state.activeContext);
|
|
23699
24836
|
}
|
|
23700
24837
|
void flush().catch((error) => {
|
|
23701
24838
|
logInstrumentationError3("Flue flush", error);
|
|
@@ -23822,7 +24959,8 @@ var FlueObserveBridge = class {
|
|
|
23822
24959
|
metadata
|
|
23823
24960
|
}
|
|
23824
24961
|
});
|
|
23825
|
-
|
|
24962
|
+
const activeContext = enterCurrentFlueSpan(span);
|
|
24963
|
+
this.toolsByKey.set(toolKey(event), { activeContext, metadata, span });
|
|
23826
24964
|
}
|
|
23827
24965
|
handleToolCall(event) {
|
|
23828
24966
|
if (!event.toolCallId) {
|
|
@@ -23845,6 +24983,7 @@ var FlueObserveBridge = class {
|
|
|
23845
24983
|
});
|
|
23846
24984
|
safeEnd(state.span, eventTime(event.timestamp));
|
|
23847
24985
|
this.toolsByKey.delete(key);
|
|
24986
|
+
restoreCurrentFlueSpan(state.activeContext);
|
|
23848
24987
|
}
|
|
23849
24988
|
handleTaskStart(event) {
|
|
23850
24989
|
if (!event.taskId) {
|
|
@@ -24249,6 +25388,34 @@ function stateMatchesRun(state, runId) {
|
|
|
24249
25388
|
function startFlueSpan(parent, args) {
|
|
24250
25389
|
return parent ? withCurrent(parent, () => startSpan(args)) : startSpan(args);
|
|
24251
25390
|
}
|
|
25391
|
+
function enterCurrentFlueSpan(span) {
|
|
25392
|
+
const contextManager = _internalGetGlobalState()?.contextManager;
|
|
25393
|
+
const store = contextManager ? Reflect.get(contextManager, BRAINTRUST_CURRENT_SPAN_STORE) : void 0;
|
|
25394
|
+
if (!contextManager || !isCurrentSpanStore(store)) {
|
|
25395
|
+
return void 0;
|
|
25396
|
+
}
|
|
25397
|
+
const previous = store.getStore();
|
|
25398
|
+
try {
|
|
25399
|
+
store.enterWith(contextManager.wrapSpanForStore(span));
|
|
25400
|
+
return { previous, store };
|
|
25401
|
+
} catch (error) {
|
|
25402
|
+
logInstrumentationError3("Flue context propagation", error);
|
|
25403
|
+
return void 0;
|
|
25404
|
+
}
|
|
25405
|
+
}
|
|
25406
|
+
function isCurrentSpanStore(value) {
|
|
25407
|
+
return isObjectLike(value) && typeof Reflect.get(value, "enterWith") === "function" && typeof Reflect.get(value, "getStore") === "function";
|
|
25408
|
+
}
|
|
25409
|
+
function restoreCurrentFlueSpan(activeContext) {
|
|
25410
|
+
if (!activeContext) {
|
|
25411
|
+
return;
|
|
25412
|
+
}
|
|
25413
|
+
try {
|
|
25414
|
+
activeContext.store.enterWith(activeContext.previous);
|
|
25415
|
+
} catch (error) {
|
|
25416
|
+
logInstrumentationError3("Flue context restoration", error);
|
|
25417
|
+
}
|
|
25418
|
+
}
|
|
24252
25419
|
function safeLog3(span, event) {
|
|
24253
25420
|
try {
|
|
24254
25421
|
span.log(event);
|
|
@@ -24726,6 +25893,890 @@ function isBraintrustHandler(handler) {
|
|
|
24726
25893
|
return Reflect.get(handler, "name") === BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
|
|
24727
25894
|
}
|
|
24728
25895
|
|
|
25896
|
+
// src/instrumentation/plugins/pi-coding-agent-channels.ts
|
|
25897
|
+
var piCodingAgentChannels = defineChannels(
|
|
25898
|
+
"@earendil-works/pi-coding-agent",
|
|
25899
|
+
{
|
|
25900
|
+
prompt: channel({
|
|
25901
|
+
channelName: "AgentSession.prompt",
|
|
25902
|
+
kind: "async"
|
|
25903
|
+
})
|
|
25904
|
+
}
|
|
25905
|
+
);
|
|
25906
|
+
|
|
25907
|
+
// src/instrumentation/plugins/pi-coding-agent-plugin.ts
|
|
25908
|
+
var piStreamPatchStates = /* @__PURE__ */ new WeakMap();
|
|
25909
|
+
var piPromptContextStore;
|
|
25910
|
+
var PiCodingAgentPlugin = class extends BasePlugin {
|
|
25911
|
+
activePromptStates = /* @__PURE__ */ new Set();
|
|
25912
|
+
onEnable() {
|
|
25913
|
+
this.subscribeToPrompt();
|
|
25914
|
+
}
|
|
25915
|
+
onDisable() {
|
|
25916
|
+
for (const unsubscribe of this.unsubscribers) {
|
|
25917
|
+
unsubscribe();
|
|
25918
|
+
}
|
|
25919
|
+
this.unsubscribers = [];
|
|
25920
|
+
for (const state of [...this.activePromptStates]) {
|
|
25921
|
+
void finalizePiPromptRun(state).catch((error) => {
|
|
25922
|
+
logInstrumentationError4("Pi Coding Agent disable cleanup", error);
|
|
25923
|
+
});
|
|
25924
|
+
}
|
|
25925
|
+
}
|
|
25926
|
+
subscribeToPrompt() {
|
|
25927
|
+
const channel2 = piCodingAgentChannels.prompt.tracingChannel();
|
|
25928
|
+
const states = /* @__PURE__ */ new WeakMap();
|
|
25929
|
+
const unbindAutoInstrumentationSuppression = bindAutoInstrumentationSuppressionToStart(channel2);
|
|
25930
|
+
const handlers = {
|
|
25931
|
+
start: (event) => {
|
|
25932
|
+
const state = startPiPromptRun(event, (state2) => {
|
|
25933
|
+
this.activePromptStates.delete(state2);
|
|
25934
|
+
});
|
|
25935
|
+
if (state) {
|
|
25936
|
+
this.activePromptStates.add(state);
|
|
25937
|
+
states.set(event, state);
|
|
25938
|
+
}
|
|
25939
|
+
},
|
|
25940
|
+
asyncEnd: async (event) => {
|
|
25941
|
+
const state = states.get(event);
|
|
25942
|
+
if (!state) {
|
|
25943
|
+
return;
|
|
25944
|
+
}
|
|
25945
|
+
states.delete(event);
|
|
25946
|
+
state.promptCallEnded = true;
|
|
25947
|
+
if (!state.finalized && state.deferCompletionUntilTurnEnd && !state.turnEnded) {
|
|
25948
|
+
if (!state.sawStreamFn) {
|
|
25949
|
+
state.queued = true;
|
|
25950
|
+
if (!state.streamPatchState.queuedPromptStates.includes(state)) {
|
|
25951
|
+
state.streamPatchState.queuedPromptStates.push(state);
|
|
25952
|
+
}
|
|
25953
|
+
}
|
|
25954
|
+
return;
|
|
25955
|
+
}
|
|
25956
|
+
await finalizePiPromptRun(state);
|
|
25957
|
+
},
|
|
25958
|
+
error: async (event) => {
|
|
25959
|
+
const state = states.get(event);
|
|
25960
|
+
if (!state) {
|
|
25961
|
+
return;
|
|
25962
|
+
}
|
|
25963
|
+
states.delete(event);
|
|
25964
|
+
await finalizePiPromptRun(state, event.error);
|
|
25965
|
+
}
|
|
25966
|
+
};
|
|
25967
|
+
channel2.subscribe(handlers);
|
|
25968
|
+
this.unsubscribers.push(() => {
|
|
25969
|
+
unbindAutoInstrumentationSuppression?.();
|
|
25970
|
+
channel2.unsubscribe(handlers);
|
|
25971
|
+
});
|
|
25972
|
+
}
|
|
25973
|
+
};
|
|
25974
|
+
function startPiPromptRun(event, onFinalize) {
|
|
25975
|
+
const session = extractSession(event);
|
|
25976
|
+
const agent = session?.agent;
|
|
25977
|
+
if (!session || !isPiAgent(agent)) {
|
|
25978
|
+
return void 0;
|
|
25979
|
+
}
|
|
25980
|
+
const metadata = {
|
|
25981
|
+
...extractSessionMetadata(session),
|
|
25982
|
+
...extractPromptOptionsMetadata(event.arguments[1]),
|
|
25983
|
+
"pi_coding_agent.operation": "AgentSession.prompt",
|
|
25984
|
+
provider: session.model?.provider ?? agent.state?.model?.provider ?? "pi",
|
|
25985
|
+
...session.model?.id || agent.state?.model?.id ? { model: session.model?.id ?? agent.state?.model?.id } : {},
|
|
25986
|
+
...event.moduleVersion ? { "pi_coding_agent.version": event.moduleVersion } : {}
|
|
25987
|
+
};
|
|
25988
|
+
const span = startSpan({
|
|
25989
|
+
event: {
|
|
25990
|
+
input: extractPromptInput(event.arguments[0], event.arguments[1]),
|
|
25991
|
+
metadata
|
|
25992
|
+
},
|
|
25993
|
+
name: "AgentSession.prompt",
|
|
25994
|
+
spanAttributes: { type: "task" /* TASK */ }
|
|
25995
|
+
});
|
|
25996
|
+
const streamPatchState = installPiStreamPatch(agent);
|
|
25997
|
+
const options = event.arguments[1];
|
|
25998
|
+
const promptText = event.arguments[0];
|
|
25999
|
+
const state = {
|
|
26000
|
+
activeLlmSpans: /* @__PURE__ */ new Set(),
|
|
26001
|
+
activeToolSpans: /* @__PURE__ */ new Map(),
|
|
26002
|
+
agent,
|
|
26003
|
+
collectedLlmUsageMetrics: false,
|
|
26004
|
+
deferCompletionUntilTurnEnd: options?.streamingBehavior === "followUp" || options?.streamingBehavior === "steer",
|
|
26005
|
+
finalized: false,
|
|
26006
|
+
metadata,
|
|
26007
|
+
metrics: {},
|
|
26008
|
+
onFinalize,
|
|
26009
|
+
promptCallEnded: false,
|
|
26010
|
+
...typeof promptText === "string" ? { promptText } : {},
|
|
26011
|
+
queued: false,
|
|
26012
|
+
span,
|
|
26013
|
+
sawStreamFn: false,
|
|
26014
|
+
startTime: getCurrentUnixTimestamp(),
|
|
26015
|
+
streamPatchState,
|
|
26016
|
+
turnEnded: false
|
|
26017
|
+
};
|
|
26018
|
+
state.restorePromptContext = enterPiPromptContext(state);
|
|
26019
|
+
streamPatchState.activePromptStates.add(state);
|
|
26020
|
+
try {
|
|
26021
|
+
state.unsubscribeAgent = agent.subscribe(async (agentEvent) => {
|
|
26022
|
+
try {
|
|
26023
|
+
await runWithAutoInstrumentationSuppressed(
|
|
26024
|
+
() => handlePiAgentEvent(state, agentEvent)
|
|
26025
|
+
);
|
|
26026
|
+
} catch (error) {
|
|
26027
|
+
logInstrumentationError4("Pi Coding Agent event", error);
|
|
26028
|
+
}
|
|
26029
|
+
});
|
|
26030
|
+
} catch (error) {
|
|
26031
|
+
logInstrumentationError4("Pi Coding Agent event subscription", error);
|
|
26032
|
+
}
|
|
26033
|
+
return state;
|
|
26034
|
+
}
|
|
26035
|
+
function extractSession(event) {
|
|
26036
|
+
const candidate = event.session ?? event.self;
|
|
26037
|
+
return isObject(candidate) && typeof candidate.prompt === "function" ? candidate : void 0;
|
|
26038
|
+
}
|
|
26039
|
+
function isPiAgent(value) {
|
|
26040
|
+
return isObject(value) && typeof value.streamFn === "function" && typeof value.subscribe === "function";
|
|
26041
|
+
}
|
|
26042
|
+
function promptContextStore() {
|
|
26043
|
+
piPromptContextStore ??= isomorph_default.newAsyncLocalStorage();
|
|
26044
|
+
return piPromptContextStore;
|
|
26045
|
+
}
|
|
26046
|
+
function currentPromptContextFrames() {
|
|
26047
|
+
return promptContextStore().getStore()?.frames ?? [];
|
|
26048
|
+
}
|
|
26049
|
+
function currentPiPromptState() {
|
|
26050
|
+
const frames = currentPromptContextFrames();
|
|
26051
|
+
return frames[frames.length - 1]?.state;
|
|
26052
|
+
}
|
|
26053
|
+
function enterPiPromptContext(state) {
|
|
26054
|
+
const frame = {
|
|
26055
|
+
id: /* @__PURE__ */ Symbol("braintrust.pi-coding-agent.prompt"),
|
|
26056
|
+
state
|
|
26057
|
+
};
|
|
26058
|
+
promptContextStore().enterWith({
|
|
26059
|
+
frames: [...currentPromptContextFrames(), frame]
|
|
26060
|
+
});
|
|
26061
|
+
return () => {
|
|
26062
|
+
const frames = currentPromptContextFrames().filter(
|
|
26063
|
+
(candidate) => candidate.id !== frame.id
|
|
26064
|
+
);
|
|
26065
|
+
promptContextStore().enterWith(frames.length > 0 ? { frames } : void 0);
|
|
26066
|
+
};
|
|
26067
|
+
}
|
|
26068
|
+
function installPiStreamPatch(agent) {
|
|
26069
|
+
const existing = piStreamPatchStates.get(agent);
|
|
26070
|
+
if (existing) {
|
|
26071
|
+
if (agent.streamFn !== existing.wrappedStreamFn) {
|
|
26072
|
+
debugLogger.debug(
|
|
26073
|
+
"Pi Coding Agent streamFn changed while Braintrust instrumentation was active; preserving existing patch state."
|
|
26074
|
+
);
|
|
26075
|
+
}
|
|
26076
|
+
return existing;
|
|
26077
|
+
}
|
|
26078
|
+
const patchState = {
|
|
26079
|
+
activePromptStates: /* @__PURE__ */ new Set(),
|
|
26080
|
+
agent,
|
|
26081
|
+
originalStreamFn: agent.streamFn,
|
|
26082
|
+
queuedPromptStates: [],
|
|
26083
|
+
wrappedStreamFn: agent.streamFn
|
|
26084
|
+
};
|
|
26085
|
+
patchState.wrappedStreamFn = makeSharedInstrumentedStreamFn(patchState);
|
|
26086
|
+
agent.streamFn = patchState.wrappedStreamFn;
|
|
26087
|
+
piStreamPatchStates.set(agent, patchState);
|
|
26088
|
+
return patchState;
|
|
26089
|
+
}
|
|
26090
|
+
function resolveStreamPromptState(patchState, context) {
|
|
26091
|
+
let lastUserText;
|
|
26092
|
+
if (Array.isArray(context.messages)) {
|
|
26093
|
+
for (let i = context.messages.length - 1; i >= 0; i--) {
|
|
26094
|
+
const message = context.messages[i];
|
|
26095
|
+
if (isPiUserMessage(message)) {
|
|
26096
|
+
if (typeof message.content === "string") {
|
|
26097
|
+
lastUserText = message.content;
|
|
26098
|
+
} else {
|
|
26099
|
+
lastUserText = message.content.flatMap((part) => part.type === "text" ? [part.text] : []).join("");
|
|
26100
|
+
}
|
|
26101
|
+
break;
|
|
26102
|
+
}
|
|
26103
|
+
}
|
|
26104
|
+
}
|
|
26105
|
+
if (lastUserText !== void 0) {
|
|
26106
|
+
const queuedMatch = patchState.queuedPromptStates.find(
|
|
26107
|
+
(state) => state.promptText === lastUserText
|
|
26108
|
+
);
|
|
26109
|
+
if (queuedMatch) {
|
|
26110
|
+
return queuedMatch;
|
|
26111
|
+
}
|
|
26112
|
+
const matches = [...patchState.activePromptStates].filter(
|
|
26113
|
+
(state) => state.promptText === lastUserText
|
|
26114
|
+
);
|
|
26115
|
+
if (matches.length === 1) {
|
|
26116
|
+
return matches[0];
|
|
26117
|
+
}
|
|
26118
|
+
}
|
|
26119
|
+
const contextState = currentPiPromptState();
|
|
26120
|
+
if (contextState && patchState.activePromptStates.has(contextState) && (!contextState.queued || lastUserText !== void 0 && contextState.promptText === lastUserText)) {
|
|
26121
|
+
return contextState;
|
|
26122
|
+
}
|
|
26123
|
+
if (patchState.activePromptStates.size === 1) {
|
|
26124
|
+
return [...patchState.activePromptStates][0];
|
|
26125
|
+
}
|
|
26126
|
+
return void 0;
|
|
26127
|
+
}
|
|
26128
|
+
function makeSharedInstrumentedStreamFn(patchState) {
|
|
26129
|
+
return async function instrumentedPiStreamFn(model, context, options) {
|
|
26130
|
+
const state = resolveStreamPromptState(patchState, context);
|
|
26131
|
+
if (!state) {
|
|
26132
|
+
const invokeOriginal = () => Reflect.apply(patchState.originalStreamFn, this, [
|
|
26133
|
+
model,
|
|
26134
|
+
context,
|
|
26135
|
+
options
|
|
26136
|
+
]);
|
|
26137
|
+
return patchState.activePromptStates.size > 0 ? runWithAutoInstrumentationSuppressed(invokeOriginal) : invokeOriginal();
|
|
26138
|
+
}
|
|
26139
|
+
state.sawStreamFn = true;
|
|
26140
|
+
removeQueuedPromptState(state);
|
|
26141
|
+
state.streamPatchState.eventPromptState = state;
|
|
26142
|
+
const llmState = await startPiLlmSpan(state, model, context, options);
|
|
26143
|
+
try {
|
|
26144
|
+
const stream = await runWithAutoInstrumentationSuppressed(
|
|
26145
|
+
() => Reflect.apply(patchState.originalStreamFn, this, [
|
|
26146
|
+
model,
|
|
26147
|
+
context,
|
|
26148
|
+
options
|
|
26149
|
+
])
|
|
26150
|
+
);
|
|
26151
|
+
return patchAssistantMessageStream(stream, state, llmState);
|
|
26152
|
+
} catch (error) {
|
|
26153
|
+
finishPiLlmSpan(state, llmState, void 0, error);
|
|
26154
|
+
throw error;
|
|
26155
|
+
}
|
|
26156
|
+
};
|
|
26157
|
+
}
|
|
26158
|
+
async function startPiLlmSpan(state, model, context, options) {
|
|
26159
|
+
const metadata = {
|
|
26160
|
+
...extractModelMetadata2(model),
|
|
26161
|
+
...extractStreamOptionsMetadata(options),
|
|
26162
|
+
...extractToolMetadata(context.tools),
|
|
26163
|
+
"pi_coding_agent.operation": "agent.streamFn"
|
|
26164
|
+
};
|
|
26165
|
+
const span = startSpan({
|
|
26166
|
+
event: {
|
|
26167
|
+
input: processInputAttachments(normalizePiContextInput(context)),
|
|
26168
|
+
metadata
|
|
26169
|
+
},
|
|
26170
|
+
name: getLlmSpanName(model),
|
|
26171
|
+
parent: await state.span.export(),
|
|
26172
|
+
spanAttributes: { type: "llm" /* LLM */ }
|
|
26173
|
+
});
|
|
26174
|
+
const llmState = {
|
|
26175
|
+
finalized: false,
|
|
26176
|
+
metadata,
|
|
26177
|
+
metrics: {},
|
|
26178
|
+
span,
|
|
26179
|
+
startTime: getCurrentUnixTimestamp()
|
|
26180
|
+
};
|
|
26181
|
+
state.activeLlmSpans.add(llmState);
|
|
26182
|
+
return llmState;
|
|
26183
|
+
}
|
|
26184
|
+
function patchAssistantMessageStream(stream, promptState, llmState) {
|
|
26185
|
+
if (!isObject(stream)) {
|
|
26186
|
+
return stream;
|
|
26187
|
+
}
|
|
26188
|
+
const streamRecord = stream;
|
|
26189
|
+
const originalResult = stream.result;
|
|
26190
|
+
if (typeof originalResult === "function") {
|
|
26191
|
+
streamRecord.result = function patchedPiResult() {
|
|
26192
|
+
return Promise.resolve(Reflect.apply(originalResult, this, [])).then(
|
|
26193
|
+
(message) => {
|
|
26194
|
+
finishPiLlmSpan(promptState, llmState, message);
|
|
26195
|
+
return message;
|
|
26196
|
+
},
|
|
26197
|
+
(error) => {
|
|
26198
|
+
finishPiLlmSpan(promptState, llmState, void 0, error);
|
|
26199
|
+
throw error;
|
|
26200
|
+
}
|
|
26201
|
+
);
|
|
26202
|
+
};
|
|
26203
|
+
}
|
|
26204
|
+
const originalIterator = stream[Symbol.asyncIterator];
|
|
26205
|
+
if (typeof originalIterator === "function") {
|
|
26206
|
+
streamRecord[Symbol.asyncIterator] = function patchedPiIterator() {
|
|
26207
|
+
const iterator = Reflect.apply(
|
|
26208
|
+
originalIterator,
|
|
26209
|
+
this,
|
|
26210
|
+
[]
|
|
26211
|
+
);
|
|
26212
|
+
return {
|
|
26213
|
+
async next() {
|
|
26214
|
+
try {
|
|
26215
|
+
const result = await iterator.next();
|
|
26216
|
+
if (result.done) {
|
|
26217
|
+
finishPiLlmSpan(promptState, llmState);
|
|
26218
|
+
return result;
|
|
26219
|
+
}
|
|
26220
|
+
recordPiAssistantMessageEvent(promptState, llmState, result.value);
|
|
26221
|
+
return result;
|
|
26222
|
+
} catch (error) {
|
|
26223
|
+
finishPiLlmSpan(promptState, llmState, void 0, error);
|
|
26224
|
+
if (typeof iterator.return === "function") {
|
|
26225
|
+
try {
|
|
26226
|
+
await iterator.return();
|
|
26227
|
+
} catch (cleanupError) {
|
|
26228
|
+
logInstrumentationError4(
|
|
26229
|
+
"Pi Coding Agent stream cleanup",
|
|
26230
|
+
cleanupError
|
|
26231
|
+
);
|
|
26232
|
+
}
|
|
26233
|
+
}
|
|
26234
|
+
throw error;
|
|
26235
|
+
}
|
|
26236
|
+
},
|
|
26237
|
+
async return(value) {
|
|
26238
|
+
try {
|
|
26239
|
+
if (typeof iterator.return === "function") {
|
|
26240
|
+
return await iterator.return(value);
|
|
26241
|
+
}
|
|
26242
|
+
return {
|
|
26243
|
+
done: true,
|
|
26244
|
+
value
|
|
26245
|
+
};
|
|
26246
|
+
} catch (error) {
|
|
26247
|
+
finishPiLlmSpan(promptState, llmState, void 0, error);
|
|
26248
|
+
throw error;
|
|
26249
|
+
} finally {
|
|
26250
|
+
finishPiLlmSpan(promptState, llmState);
|
|
26251
|
+
}
|
|
26252
|
+
},
|
|
26253
|
+
async throw(error) {
|
|
26254
|
+
try {
|
|
26255
|
+
if (typeof iterator.throw === "function") {
|
|
26256
|
+
return await iterator.throw(error);
|
|
26257
|
+
}
|
|
26258
|
+
throw error;
|
|
26259
|
+
} catch (thrownError) {
|
|
26260
|
+
finishPiLlmSpan(promptState, llmState, void 0, thrownError);
|
|
26261
|
+
throw thrownError;
|
|
26262
|
+
}
|
|
26263
|
+
},
|
|
26264
|
+
[Symbol.asyncIterator]() {
|
|
26265
|
+
return this;
|
|
26266
|
+
}
|
|
26267
|
+
};
|
|
26268
|
+
};
|
|
26269
|
+
}
|
|
26270
|
+
return stream;
|
|
26271
|
+
}
|
|
26272
|
+
function recordPiAssistantMessageEvent(promptState, llmState, event) {
|
|
26273
|
+
recordFirstTokenMetric(llmState, event);
|
|
26274
|
+
const message = "message" in event ? event.message : void 0;
|
|
26275
|
+
const errorMessage2 = "error" in event ? event.error : void 0;
|
|
26276
|
+
if (event.type === "done" && isPiAssistantMessage(message)) {
|
|
26277
|
+
finishPiLlmSpan(promptState, llmState, message);
|
|
26278
|
+
} else if (event.type === "error" && isPiAssistantMessage(errorMessage2)) {
|
|
26279
|
+
finishPiLlmSpan(promptState, llmState, errorMessage2);
|
|
26280
|
+
}
|
|
26281
|
+
}
|
|
26282
|
+
function recordFirstTokenMetric(state, event) {
|
|
26283
|
+
if (state.metrics.time_to_first_token !== void 0 || event.type === "start") {
|
|
26284
|
+
return;
|
|
26285
|
+
}
|
|
26286
|
+
state.metrics.time_to_first_token = getCurrentUnixTimestamp() - state.startTime;
|
|
26287
|
+
}
|
|
26288
|
+
async function handlePiAgentEvent(state, event) {
|
|
26289
|
+
if (state.finalized) {
|
|
26290
|
+
return;
|
|
26291
|
+
}
|
|
26292
|
+
const eventPromptState = state.streamPatchState.eventPromptState;
|
|
26293
|
+
if (eventPromptState && eventPromptState !== state) {
|
|
26294
|
+
return;
|
|
26295
|
+
}
|
|
26296
|
+
if (!eventPromptState && (state.queued || state.streamPatchState.activePromptStates.size > 1 && currentPiPromptState() !== state)) {
|
|
26297
|
+
return;
|
|
26298
|
+
}
|
|
26299
|
+
switch (event.type) {
|
|
26300
|
+
case "message_end":
|
|
26301
|
+
if (isPiAssistantMessage(event.message)) {
|
|
26302
|
+
state.output = extractAssistantOutput(event.message);
|
|
26303
|
+
}
|
|
26304
|
+
return;
|
|
26305
|
+
case "turn_end":
|
|
26306
|
+
state.turnEnded = true;
|
|
26307
|
+
if (isPiAssistantMessage(event.message)) {
|
|
26308
|
+
state.output = extractAssistantOutput(event.message);
|
|
26309
|
+
if (!state.collectedLlmUsageMetrics) {
|
|
26310
|
+
addMetrics(state.metrics, extractUsageMetrics2(event.message.usage));
|
|
26311
|
+
}
|
|
26312
|
+
}
|
|
26313
|
+
if (state.streamPatchState.eventPromptState === state) {
|
|
26314
|
+
state.streamPatchState.eventPromptState = void 0;
|
|
26315
|
+
}
|
|
26316
|
+
if (state.promptCallEnded && state.deferCompletionUntilTurnEnd) {
|
|
26317
|
+
await finalizePiPromptRun(state);
|
|
26318
|
+
}
|
|
26319
|
+
return;
|
|
26320
|
+
case "tool_execution_start":
|
|
26321
|
+
await startPiToolSpan(state, event);
|
|
26322
|
+
return;
|
|
26323
|
+
case "tool_execution_end":
|
|
26324
|
+
finishPiToolSpan(state, event);
|
|
26325
|
+
return;
|
|
26326
|
+
default:
|
|
26327
|
+
return;
|
|
26328
|
+
}
|
|
26329
|
+
}
|
|
26330
|
+
async function startPiToolSpan(state, event) {
|
|
26331
|
+
if (!event.toolCallId || state.activeToolSpans.has(event.toolCallId)) {
|
|
26332
|
+
return;
|
|
26333
|
+
}
|
|
26334
|
+
const restoreAutoInstrumentation = enterAutoInstrumentationAllowed();
|
|
26335
|
+
const metadata = {
|
|
26336
|
+
"gen_ai.tool.call.id": event.toolCallId,
|
|
26337
|
+
"gen_ai.tool.name": event.toolName,
|
|
26338
|
+
"pi_coding_agent.tool.name": event.toolName
|
|
26339
|
+
};
|
|
26340
|
+
try {
|
|
26341
|
+
const span = startSpan({
|
|
26342
|
+
event: {
|
|
26343
|
+
input: event.args,
|
|
26344
|
+
metadata
|
|
26345
|
+
},
|
|
26346
|
+
name: event.toolName || "tool",
|
|
26347
|
+
parent: await state.span.export(),
|
|
26348
|
+
spanAttributes: { type: "tool" /* TOOL */ }
|
|
26349
|
+
});
|
|
26350
|
+
state.activeToolSpans.set(event.toolCallId, {
|
|
26351
|
+
restoreAutoInstrumentation,
|
|
26352
|
+
span
|
|
26353
|
+
});
|
|
26354
|
+
} catch (error) {
|
|
26355
|
+
restoreAutoInstrumentation();
|
|
26356
|
+
throw error;
|
|
26357
|
+
}
|
|
26358
|
+
}
|
|
26359
|
+
function finishPiToolSpan(state, event) {
|
|
26360
|
+
const toolState = state.activeToolSpans.get(event.toolCallId);
|
|
26361
|
+
if (!toolState) {
|
|
26362
|
+
return;
|
|
26363
|
+
}
|
|
26364
|
+
state.activeToolSpans.delete(event.toolCallId);
|
|
26365
|
+
const metadata = {
|
|
26366
|
+
"gen_ai.tool.call.id": event.toolCallId,
|
|
26367
|
+
"gen_ai.tool.name": event.toolName,
|
|
26368
|
+
"pi_coding_agent.tool.name": event.toolName,
|
|
26369
|
+
"pi_coding_agent.tool.is_error": event.isError
|
|
26370
|
+
};
|
|
26371
|
+
try {
|
|
26372
|
+
safeLog4(toolState.span, {
|
|
26373
|
+
...event.isError ? { error: stringifyUnknown2(event.result) } : {},
|
|
26374
|
+
metadata,
|
|
26375
|
+
output: event.result
|
|
26376
|
+
});
|
|
26377
|
+
} finally {
|
|
26378
|
+
try {
|
|
26379
|
+
toolState.span.end();
|
|
26380
|
+
} finally {
|
|
26381
|
+
toolState.restoreAutoInstrumentation?.();
|
|
26382
|
+
}
|
|
26383
|
+
}
|
|
26384
|
+
}
|
|
26385
|
+
async function finalizePiPromptRun(state, error) {
|
|
26386
|
+
if (state.finalized) {
|
|
26387
|
+
return;
|
|
26388
|
+
}
|
|
26389
|
+
state.finalized = true;
|
|
26390
|
+
state.onFinalize?.(state);
|
|
26391
|
+
restorePiStreamFn(state);
|
|
26392
|
+
try {
|
|
26393
|
+
state.unsubscribeAgent?.();
|
|
26394
|
+
} catch (unsubscribeError) {
|
|
26395
|
+
logInstrumentationError4("Pi Coding Agent unsubscribe", unsubscribeError);
|
|
26396
|
+
}
|
|
26397
|
+
await finishOpenLlmSpans(state, error);
|
|
26398
|
+
finishOpenToolSpans(state, error);
|
|
26399
|
+
const metadata = {
|
|
26400
|
+
...state.metadata,
|
|
26401
|
+
...extractModelMetadata2(state.agent.state?.model)
|
|
26402
|
+
};
|
|
26403
|
+
try {
|
|
26404
|
+
safeLog4(state.span, {
|
|
26405
|
+
...error ? { error: stringifyUnknown2(error) } : {},
|
|
26406
|
+
metadata,
|
|
26407
|
+
metrics: {
|
|
26408
|
+
...cleanMetrics5(state.metrics),
|
|
26409
|
+
...buildDurationMetrics3(state.startTime)
|
|
26410
|
+
},
|
|
26411
|
+
output: state.output
|
|
26412
|
+
});
|
|
26413
|
+
} finally {
|
|
26414
|
+
state.span.end();
|
|
26415
|
+
}
|
|
26416
|
+
}
|
|
26417
|
+
function restorePiStreamFn(state) {
|
|
26418
|
+
const patchState = state.streamPatchState;
|
|
26419
|
+
patchState.activePromptStates.delete(state);
|
|
26420
|
+
removeQueuedPromptState(state);
|
|
26421
|
+
if (patchState.eventPromptState === state) {
|
|
26422
|
+
patchState.eventPromptState = void 0;
|
|
26423
|
+
}
|
|
26424
|
+
state.restorePromptContext?.();
|
|
26425
|
+
if (patchState.activePromptStates.size > 0) {
|
|
26426
|
+
return;
|
|
26427
|
+
}
|
|
26428
|
+
if (patchState.agent.streamFn === patchState.wrappedStreamFn) {
|
|
26429
|
+
patchState.agent.streamFn = patchState.originalStreamFn;
|
|
26430
|
+
}
|
|
26431
|
+
piStreamPatchStates.delete(patchState.agent);
|
|
26432
|
+
}
|
|
26433
|
+
function removeQueuedPromptState(state) {
|
|
26434
|
+
state.queued = false;
|
|
26435
|
+
const queuedPromptStates = state.streamPatchState.queuedPromptStates;
|
|
26436
|
+
const index = queuedPromptStates.indexOf(state);
|
|
26437
|
+
if (index >= 0) {
|
|
26438
|
+
queuedPromptStates.splice(index, 1);
|
|
26439
|
+
}
|
|
26440
|
+
}
|
|
26441
|
+
async function finishOpenLlmSpans(state, error) {
|
|
26442
|
+
for (const llmState of [...state.activeLlmSpans]) {
|
|
26443
|
+
finishPiLlmSpan(state, llmState, void 0, error);
|
|
26444
|
+
}
|
|
26445
|
+
}
|
|
26446
|
+
function finishPiLlmSpan(promptState, llmState, message, error) {
|
|
26447
|
+
if (llmState.finalized) {
|
|
26448
|
+
return;
|
|
26449
|
+
}
|
|
26450
|
+
llmState.finalized = true;
|
|
26451
|
+
promptState.activeLlmSpans.delete(llmState);
|
|
26452
|
+
const messageError = message?.stopReason === "error" && message.errorMessage;
|
|
26453
|
+
const metrics = {
|
|
26454
|
+
...extractUsageMetrics2(message?.usage),
|
|
26455
|
+
...cleanMetrics5(llmState.metrics),
|
|
26456
|
+
...buildDurationMetrics3(llmState.startTime)
|
|
26457
|
+
};
|
|
26458
|
+
const usageMetrics = extractUsageMetrics2(message?.usage);
|
|
26459
|
+
if (Object.keys(usageMetrics).length > 0) {
|
|
26460
|
+
promptState.collectedLlmUsageMetrics = true;
|
|
26461
|
+
addMetrics(promptState.metrics, usageMetrics);
|
|
26462
|
+
}
|
|
26463
|
+
try {
|
|
26464
|
+
safeLog4(llmState.span, {
|
|
26465
|
+
...error || messageError ? { error: stringifyUnknown2(error ?? messageError) } : {},
|
|
26466
|
+
metadata: {
|
|
26467
|
+
...llmState.metadata,
|
|
26468
|
+
...message ? extractAssistantMetadata(message) : {}
|
|
26469
|
+
},
|
|
26470
|
+
metrics,
|
|
26471
|
+
...message ? { output: extractAssistantOutput(message) } : {}
|
|
26472
|
+
});
|
|
26473
|
+
} finally {
|
|
26474
|
+
llmState.span.end();
|
|
26475
|
+
}
|
|
26476
|
+
}
|
|
26477
|
+
function finishOpenToolSpans(state, error) {
|
|
26478
|
+
for (const [, toolState] of state.activeToolSpans) {
|
|
26479
|
+
try {
|
|
26480
|
+
safeLog4(toolState.span, {
|
|
26481
|
+
error: error ? stringifyUnknown2(error) : "Pi tool did not complete"
|
|
26482
|
+
});
|
|
26483
|
+
toolState.span.end();
|
|
26484
|
+
} finally {
|
|
26485
|
+
toolState.restoreAutoInstrumentation?.();
|
|
26486
|
+
}
|
|
26487
|
+
}
|
|
26488
|
+
state.activeToolSpans.clear();
|
|
26489
|
+
}
|
|
26490
|
+
function normalizePiContextInput(context) {
|
|
26491
|
+
const messages = context.messages.flatMap(
|
|
26492
|
+
(message) => normalizePiMessage(message)
|
|
26493
|
+
);
|
|
26494
|
+
if (context.systemPrompt) {
|
|
26495
|
+
return [{ role: "system", content: context.systemPrompt }, ...messages];
|
|
26496
|
+
}
|
|
26497
|
+
return messages;
|
|
26498
|
+
}
|
|
26499
|
+
function normalizePiMessage(message) {
|
|
26500
|
+
if (isPiUserMessage(message)) {
|
|
26501
|
+
return [
|
|
26502
|
+
{
|
|
26503
|
+
role: "user",
|
|
26504
|
+
content: normalizeUserContent(message.content)
|
|
26505
|
+
}
|
|
26506
|
+
];
|
|
26507
|
+
}
|
|
26508
|
+
if (isPiAssistantMessage(message)) {
|
|
26509
|
+
return [normalizeAssistantMessage(message)];
|
|
26510
|
+
}
|
|
26511
|
+
if (isPiToolResultMessage(message)) {
|
|
26512
|
+
return [normalizeToolResultMessage(message)];
|
|
26513
|
+
}
|
|
26514
|
+
return [];
|
|
26515
|
+
}
|
|
26516
|
+
function normalizeAssistantMessage(message) {
|
|
26517
|
+
const text = message.content.flatMap((part) => part.type === "text" ? [part.text] : []).join("");
|
|
26518
|
+
const thinking = message.content.flatMap(
|
|
26519
|
+
(part) => part.type === "thinking" && !part.redacted ? [part.thinking] : []
|
|
26520
|
+
).join("");
|
|
26521
|
+
const toolCalls = message.content.flatMap(
|
|
26522
|
+
(part) => part.type === "toolCall" ? [normalizeToolCall(part)] : []
|
|
26523
|
+
);
|
|
26524
|
+
return {
|
|
26525
|
+
role: "assistant",
|
|
26526
|
+
content: text || (toolCalls.length > 0 ? null : ""),
|
|
26527
|
+
...thinking ? { reasoning: thinking } : {},
|
|
26528
|
+
...toolCalls.length > 0 ? { tool_calls: toolCalls } : {}
|
|
26529
|
+
};
|
|
26530
|
+
}
|
|
26531
|
+
function normalizeToolResultMessage(message) {
|
|
26532
|
+
return {
|
|
26533
|
+
role: "tool",
|
|
26534
|
+
tool_call_id: message.toolCallId,
|
|
26535
|
+
content: normalizeUserContent(message.content)
|
|
26536
|
+
};
|
|
26537
|
+
}
|
|
26538
|
+
function normalizeUserContent(content) {
|
|
26539
|
+
if (typeof content === "string") {
|
|
26540
|
+
return content;
|
|
26541
|
+
}
|
|
26542
|
+
return content.map((part) => {
|
|
26543
|
+
if (part.type === "text") {
|
|
26544
|
+
return { type: "text", text: part.text };
|
|
26545
|
+
}
|
|
26546
|
+
if (part.type === "image") {
|
|
26547
|
+
return {
|
|
26548
|
+
type: "image_url",
|
|
26549
|
+
image_url: {
|
|
26550
|
+
url: `data:${part.mimeType};base64,${part.data}`
|
|
26551
|
+
}
|
|
26552
|
+
};
|
|
26553
|
+
}
|
|
26554
|
+
return part;
|
|
26555
|
+
});
|
|
26556
|
+
}
|
|
26557
|
+
function normalizeToolCall(toolCall) {
|
|
26558
|
+
return {
|
|
26559
|
+
id: toolCall.id,
|
|
26560
|
+
type: "function",
|
|
26561
|
+
function: {
|
|
26562
|
+
name: toolCall.name,
|
|
26563
|
+
arguments: stringifyArguments(toolCall.arguments)
|
|
26564
|
+
}
|
|
26565
|
+
};
|
|
26566
|
+
}
|
|
26567
|
+
function extractAssistantOutput(message) {
|
|
26568
|
+
return processInputAttachments([
|
|
26569
|
+
{
|
|
26570
|
+
finish_reason: normalizeStopReason(message.stopReason),
|
|
26571
|
+
index: 0,
|
|
26572
|
+
message: normalizeAssistantMessage(message)
|
|
26573
|
+
}
|
|
26574
|
+
]);
|
|
26575
|
+
}
|
|
26576
|
+
function isPiUserMessage(message) {
|
|
26577
|
+
return message.role === "user" && "content" in message;
|
|
26578
|
+
}
|
|
26579
|
+
function isPiAssistantMessage(message) {
|
|
26580
|
+
return isObject(message) && message.role === "assistant" && Array.isArray(message.content);
|
|
26581
|
+
}
|
|
26582
|
+
function isPiToolResultMessage(message) {
|
|
26583
|
+
return message.role === "toolResult" && Array.isArray(message.content);
|
|
26584
|
+
}
|
|
26585
|
+
function normalizeStopReason(reason) {
|
|
26586
|
+
switch (reason) {
|
|
26587
|
+
case "toolUse":
|
|
26588
|
+
return "tool_calls";
|
|
26589
|
+
case "length":
|
|
26590
|
+
case "stop":
|
|
26591
|
+
return reason;
|
|
26592
|
+
default:
|
|
26593
|
+
return reason ?? "stop";
|
|
26594
|
+
}
|
|
26595
|
+
}
|
|
26596
|
+
function extractPromptInput(text, options) {
|
|
26597
|
+
const images = options?.images;
|
|
26598
|
+
if (!images || images.length === 0) {
|
|
26599
|
+
return text;
|
|
26600
|
+
}
|
|
26601
|
+
return processInputAttachments([
|
|
26602
|
+
{
|
|
26603
|
+
role: "user",
|
|
26604
|
+
content: [
|
|
26605
|
+
{ type: "text", text: text ?? "" },
|
|
26606
|
+
...images.map((image) => ({
|
|
26607
|
+
type: "image_url",
|
|
26608
|
+
image_url: {
|
|
26609
|
+
url: `data:${image.mimeType};base64,${image.data}`
|
|
26610
|
+
}
|
|
26611
|
+
}))
|
|
26612
|
+
]
|
|
26613
|
+
}
|
|
26614
|
+
]);
|
|
26615
|
+
}
|
|
26616
|
+
function extractToolMetadata(tools) {
|
|
26617
|
+
if (!tools || tools.length === 0) {
|
|
26618
|
+
return {};
|
|
26619
|
+
}
|
|
26620
|
+
return {
|
|
26621
|
+
tools: tools.map((tool) => ({
|
|
26622
|
+
type: "function",
|
|
26623
|
+
function: {
|
|
26624
|
+
name: tool.name,
|
|
26625
|
+
...tool.description ? { description: tool.description } : {},
|
|
26626
|
+
...tool.parameters ? { parameters: tool.parameters } : {}
|
|
26627
|
+
}
|
|
26628
|
+
}))
|
|
26629
|
+
};
|
|
26630
|
+
}
|
|
26631
|
+
function extractModelMetadata2(model) {
|
|
26632
|
+
if (!model) {
|
|
26633
|
+
return {};
|
|
26634
|
+
}
|
|
26635
|
+
return {
|
|
26636
|
+
...model.provider ? { provider: model.provider } : {},
|
|
26637
|
+
...model.id ? { model: model.id, "pi_coding_agent.model": model.id } : {},
|
|
26638
|
+
...model.api ? { "pi_coding_agent.api": model.api } : {},
|
|
26639
|
+
...model.name ? { "pi_coding_agent.model_name": model.name } : {}
|
|
26640
|
+
};
|
|
26641
|
+
}
|
|
26642
|
+
function extractAssistantMetadata(message) {
|
|
26643
|
+
return {
|
|
26644
|
+
...message.provider ? { provider: message.provider } : {},
|
|
26645
|
+
...message.responseModel || message.model ? { model: message.responseModel ?? message.model } : {},
|
|
26646
|
+
...message.api ? { "pi_coding_agent.api": message.api } : {},
|
|
26647
|
+
...message.model ? { "pi_coding_agent.model": message.model } : {},
|
|
26648
|
+
...message.responseModel ? { "pi_coding_agent.response_model": message.responseModel } : {},
|
|
26649
|
+
...message.responseId ? { "pi_coding_agent.response_id": message.responseId } : {},
|
|
26650
|
+
...message.stopReason ? { "pi_coding_agent.stop_reason": message.stopReason } : {}
|
|
26651
|
+
};
|
|
26652
|
+
}
|
|
26653
|
+
function extractSessionMetadata(session) {
|
|
26654
|
+
return {
|
|
26655
|
+
...extractModelMetadata2(session.model),
|
|
26656
|
+
...session.sessionId ? { "pi_coding_agent.session_id": session.sessionId } : {},
|
|
26657
|
+
...session.sessionName ? { "pi_coding_agent.session_name": session.sessionName } : {},
|
|
26658
|
+
...session.thinkingLevel ? { "pi_coding_agent.thinking_level": session.thinkingLevel } : {},
|
|
26659
|
+
...typeof session.getActiveToolNames === "function" ? { "pi_coding_agent.active_tools": session.getActiveToolNames() } : {}
|
|
26660
|
+
};
|
|
26661
|
+
}
|
|
26662
|
+
function extractPromptOptionsMetadata(options) {
|
|
26663
|
+
if (!options) {
|
|
26664
|
+
return {};
|
|
26665
|
+
}
|
|
26666
|
+
return {
|
|
26667
|
+
...options.source ? { "pi_coding_agent.source": options.source } : {},
|
|
26668
|
+
...options.streamingBehavior ? { "pi_coding_agent.streaming_behavior": options.streamingBehavior } : {},
|
|
26669
|
+
...options.expandPromptTemplates !== void 0 ? {
|
|
26670
|
+
"pi_coding_agent.expand_prompt_templates": options.expandPromptTemplates
|
|
26671
|
+
} : {}
|
|
26672
|
+
};
|
|
26673
|
+
}
|
|
26674
|
+
function extractStreamOptionsMetadata(options) {
|
|
26675
|
+
if (!options) {
|
|
26676
|
+
return {};
|
|
26677
|
+
}
|
|
26678
|
+
return {
|
|
26679
|
+
...options.temperature !== void 0 ? { temperature: options.temperature } : {},
|
|
26680
|
+
...options.maxTokens !== void 0 ? { max_tokens: options.maxTokens } : {},
|
|
26681
|
+
...options.reasoning ? { "pi_coding_agent.reasoning": options.reasoning } : {},
|
|
26682
|
+
...options.transport ? { "pi_coding_agent.transport": options.transport } : {},
|
|
26683
|
+
...options.cacheRetention ? { "pi_coding_agent.cache_retention": options.cacheRetention } : {},
|
|
26684
|
+
...options.sessionId ? { "pi_coding_agent.session_id": options.sessionId } : {},
|
|
26685
|
+
...options.timeoutMs !== void 0 ? { "pi_coding_agent.timeout_ms": options.timeoutMs } : {},
|
|
26686
|
+
...options.maxRetries !== void 0 ? { "pi_coding_agent.max_retries": options.maxRetries } : {},
|
|
26687
|
+
...options.maxRetryDelayMs !== void 0 ? { "pi_coding_agent.max_retry_delay_ms": options.maxRetryDelayMs } : {},
|
|
26688
|
+
...options.metadata ? { "pi_coding_agent.metadata": options.metadata } : {}
|
|
26689
|
+
};
|
|
26690
|
+
}
|
|
26691
|
+
function getLlmSpanName(model) {
|
|
26692
|
+
switch (model.api) {
|
|
26693
|
+
case "anthropic-messages":
|
|
26694
|
+
return "anthropic.messages.create";
|
|
26695
|
+
case "openai-completions":
|
|
26696
|
+
return "Chat Completion";
|
|
26697
|
+
case "openai-responses":
|
|
26698
|
+
case "azure-openai-responses":
|
|
26699
|
+
case "openai-codex-responses":
|
|
26700
|
+
return "openai.responses.create";
|
|
26701
|
+
case "google-generative-ai":
|
|
26702
|
+
case "google-vertex":
|
|
26703
|
+
return "generate_content";
|
|
26704
|
+
case "mistral-conversations":
|
|
26705
|
+
return "mistral.chat.stream";
|
|
26706
|
+
case "bedrock-converse-stream":
|
|
26707
|
+
return "bedrock.converse_stream";
|
|
26708
|
+
default:
|
|
26709
|
+
return "pi_ai.streamSimple";
|
|
26710
|
+
}
|
|
26711
|
+
}
|
|
26712
|
+
function extractUsageMetrics2(usage) {
|
|
26713
|
+
if (!usage) {
|
|
26714
|
+
return {};
|
|
26715
|
+
}
|
|
26716
|
+
return cleanMetrics5({
|
|
26717
|
+
completion_tokens: usage.output,
|
|
26718
|
+
prompt_cache_creation_tokens: usage.cacheWrite,
|
|
26719
|
+
prompt_cached_tokens: usage.cacheRead,
|
|
26720
|
+
prompt_tokens: usage.input,
|
|
26721
|
+
tokens: usage.totalTokens ?? usage.tokens
|
|
26722
|
+
});
|
|
26723
|
+
}
|
|
26724
|
+
function addMetrics(target, source) {
|
|
26725
|
+
for (const [key, value] of Object.entries(source)) {
|
|
26726
|
+
target[key] = (target[key] ?? 0) + value;
|
|
26727
|
+
}
|
|
26728
|
+
}
|
|
26729
|
+
function buildDurationMetrics3(startTime) {
|
|
26730
|
+
const end = getCurrentUnixTimestamp();
|
|
26731
|
+
return {
|
|
26732
|
+
duration: end - startTime,
|
|
26733
|
+
end,
|
|
26734
|
+
start: startTime
|
|
26735
|
+
};
|
|
26736
|
+
}
|
|
26737
|
+
function cleanMetrics5(metrics) {
|
|
26738
|
+
const cleaned = {};
|
|
26739
|
+
for (const [key, value] of Object.entries(metrics)) {
|
|
26740
|
+
if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
|
|
26741
|
+
cleaned[key] = value;
|
|
26742
|
+
}
|
|
26743
|
+
}
|
|
26744
|
+
return cleaned;
|
|
26745
|
+
}
|
|
26746
|
+
function stringifyArguments(value) {
|
|
26747
|
+
if (typeof value === "string") {
|
|
26748
|
+
return value;
|
|
26749
|
+
}
|
|
26750
|
+
try {
|
|
26751
|
+
return JSON.stringify(value);
|
|
26752
|
+
} catch {
|
|
26753
|
+
return stringifyUnknown2(value);
|
|
26754
|
+
}
|
|
26755
|
+
}
|
|
26756
|
+
function stringifyUnknown2(value) {
|
|
26757
|
+
if (value instanceof Error) {
|
|
26758
|
+
return value.message;
|
|
26759
|
+
}
|
|
26760
|
+
if (typeof value === "string") {
|
|
26761
|
+
return value;
|
|
26762
|
+
}
|
|
26763
|
+
try {
|
|
26764
|
+
return JSON.stringify(value);
|
|
26765
|
+
} catch {
|
|
26766
|
+
return String(value);
|
|
26767
|
+
}
|
|
26768
|
+
}
|
|
26769
|
+
function safeLog4(span, event) {
|
|
26770
|
+
try {
|
|
26771
|
+
span.log(event);
|
|
26772
|
+
} catch (error) {
|
|
26773
|
+
logInstrumentationError4("Pi Coding Agent span log", error);
|
|
26774
|
+
}
|
|
26775
|
+
}
|
|
26776
|
+
function logInstrumentationError4(context, error) {
|
|
26777
|
+
debugLogger.debug(`${context}:`, error);
|
|
26778
|
+
}
|
|
26779
|
+
|
|
24729
26780
|
// src/instrumentation/braintrust-plugin.ts
|
|
24730
26781
|
function getIntegrationConfig(integrations, key) {
|
|
24731
26782
|
return integrations[key];
|
|
@@ -24751,6 +26802,7 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
24751
26802
|
gitHubCopilotPlugin = null;
|
|
24752
26803
|
fluePlugin = null;
|
|
24753
26804
|
langChainPlugin = null;
|
|
26805
|
+
piCodingAgentPlugin = null;
|
|
24754
26806
|
constructor(config = {}) {
|
|
24755
26807
|
super();
|
|
24756
26808
|
this.config = config;
|
|
@@ -24825,6 +26877,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
24825
26877
|
this.gitHubCopilotPlugin = new GitHubCopilotPlugin();
|
|
24826
26878
|
this.gitHubCopilotPlugin.enable();
|
|
24827
26879
|
}
|
|
26880
|
+
if (integrations.piCodingAgent !== false) {
|
|
26881
|
+
this.piCodingAgentPlugin = new PiCodingAgentPlugin();
|
|
26882
|
+
this.piCodingAgentPlugin.enable();
|
|
26883
|
+
}
|
|
24828
26884
|
if (getIntegrationConfig(integrations, "flue") !== false) {
|
|
24829
26885
|
this.fluePlugin = new FluePlugin();
|
|
24830
26886
|
this.fluePlugin.enable();
|
|
@@ -24903,6 +26959,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
24903
26959
|
this.gitHubCopilotPlugin.disable();
|
|
24904
26960
|
this.gitHubCopilotPlugin = null;
|
|
24905
26961
|
}
|
|
26962
|
+
if (this.piCodingAgentPlugin) {
|
|
26963
|
+
this.piCodingAgentPlugin.disable();
|
|
26964
|
+
this.piCodingAgentPlugin = null;
|
|
26965
|
+
}
|
|
24906
26966
|
if (this.fluePlugin) {
|
|
24907
26967
|
this.fluePlugin.disable();
|
|
24908
26968
|
this.fluePlugin = null;
|
|
@@ -24922,6 +26982,11 @@ var envIntegrationAliases = {
|
|
|
24922
26982
|
openaicodexsdk: "openaiCodexSDK",
|
|
24923
26983
|
codex: "openaiCodexSDK",
|
|
24924
26984
|
"codex-sdk": "openaiCodexSDK",
|
|
26985
|
+
"pi-coding-agent": "piCodingAgent",
|
|
26986
|
+
"pi-coding-agent-sdk": "piCodingAgent",
|
|
26987
|
+
picodingagent: "piCodingAgent",
|
|
26988
|
+
picodingagentsdk: "piCodingAgent",
|
|
26989
|
+
"@earendil-works/pi-coding-agent": "piCodingAgent",
|
|
24925
26990
|
anthropic: "anthropic",
|
|
24926
26991
|
aisdk: "aisdk",
|
|
24927
26992
|
"ai-sdk": "aisdk",
|
|
@@ -24987,7 +27052,8 @@ function getDefaultInstrumentationIntegrations() {
|
|
|
24987
27052
|
genkit: true,
|
|
24988
27053
|
gitHubCopilot: true,
|
|
24989
27054
|
langchain: true,
|
|
24990
|
-
langgraph: true
|
|
27055
|
+
langgraph: true,
|
|
27056
|
+
piCodingAgent: true
|
|
24991
27057
|
};
|
|
24992
27058
|
}
|
|
24993
27059
|
function readDisabledInstrumentationEnvConfig(disabledList) {
|
|
@@ -27048,6 +29114,13 @@ var EvalResultWithSummary = class {
|
|
|
27048
29114
|
};
|
|
27049
29115
|
}
|
|
27050
29116
|
};
|
|
29117
|
+
async function getPersistedBaseExperimentId(experiment) {
|
|
29118
|
+
try {
|
|
29119
|
+
return await experiment._getBaseExperimentId();
|
|
29120
|
+
} catch {
|
|
29121
|
+
return void 0;
|
|
29122
|
+
}
|
|
29123
|
+
}
|
|
27051
29124
|
function makeEvalName(projectName, experimentName) {
|
|
27052
29125
|
let out = projectName;
|
|
27053
29126
|
if (experimentName) {
|
|
@@ -27411,6 +29484,14 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
|
|
|
27411
29484
|
return;
|
|
27412
29485
|
}
|
|
27413
29486
|
const eventDataset = experiment ? experiment.dataset : Dataset2.isDataset(evaluator.data) ? evaluator.data : void 0;
|
|
29487
|
+
const inlineOrigin = datum.origin === void 0 ? void 0 : ObjectReference.parse(datum.origin);
|
|
29488
|
+
const origin = inlineOrigin ?? (eventDataset && datum.id && datum._xact_id ? {
|
|
29489
|
+
object_type: "dataset",
|
|
29490
|
+
object_id: await eventDataset.id,
|
|
29491
|
+
id: datum.id,
|
|
29492
|
+
created: datum.created,
|
|
29493
|
+
_xact_id: datum._xact_id
|
|
29494
|
+
} : void 0);
|
|
27414
29495
|
const baseEvent = {
|
|
27415
29496
|
name: "eval",
|
|
27416
29497
|
spanAttributes: {
|
|
@@ -27420,13 +29501,7 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
|
|
|
27420
29501
|
input: datum.input,
|
|
27421
29502
|
expected: "expected" in datum ? datum.expected : void 0,
|
|
27422
29503
|
tags: datum.tags,
|
|
27423
|
-
origin
|
|
27424
|
-
object_type: "dataset",
|
|
27425
|
-
object_id: await eventDataset.id,
|
|
27426
|
-
id: datum.id,
|
|
27427
|
-
created: datum.created,
|
|
27428
|
-
_xact_id: datum._xact_id
|
|
27429
|
-
} : void 0,
|
|
29504
|
+
origin,
|
|
27430
29505
|
...datum.upsert_id ? { id: datum.upsert_id } : {}
|
|
27431
29506
|
}
|
|
27432
29507
|
};
|
|
@@ -27783,8 +29858,10 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
|
|
|
27783
29858
|
collectedResults.length = 0;
|
|
27784
29859
|
}
|
|
27785
29860
|
}
|
|
29861
|
+
const comparisonExperimentId = experiment ? evaluator.baseExperimentId ?? await getPersistedBaseExperimentId(experiment) : void 0;
|
|
27786
29862
|
const summary = experiment ? await experiment.summarize({
|
|
27787
|
-
summarizeScores: evaluator.summarizeScores
|
|
29863
|
+
summarizeScores: evaluator.summarizeScores,
|
|
29864
|
+
...comparisonExperimentId !== void 0 ? { comparisonExperimentId } : {}
|
|
27788
29865
|
}) : buildLocalSummary(
|
|
27789
29866
|
evaluator,
|
|
27790
29867
|
collectResults ? collectedResults : [],
|
|
@@ -28221,7 +30298,7 @@ var serializedParametersContainerSchema = z12.union([
|
|
|
28221
30298
|
staticParametersSchema
|
|
28222
30299
|
]);
|
|
28223
30300
|
var evaluatorDefinitionSchema = z12.object({
|
|
28224
|
-
parameters: serializedParametersContainerSchema.
|
|
30301
|
+
parameters: serializedParametersContainerSchema.nullish(),
|
|
28225
30302
|
scores: z12.array(z12.object({ name: z12.string() })).optional(),
|
|
28226
30303
|
classifiers: z12.array(z12.object({ name: z12.string() })).optional()
|
|
28227
30304
|
});
|
|
@@ -28250,6 +30327,7 @@ var Project2 = class {
|
|
|
28250
30327
|
prompts;
|
|
28251
30328
|
parameters;
|
|
28252
30329
|
scorers;
|
|
30330
|
+
classifiers;
|
|
28253
30331
|
_publishableCodeFunctions = [];
|
|
28254
30332
|
_publishablePrompts = [];
|
|
28255
30333
|
_publishableParameters = [];
|
|
@@ -28261,6 +30339,7 @@ var Project2 = class {
|
|
|
28261
30339
|
this.prompts = new PromptBuilder(this);
|
|
28262
30340
|
this.parameters = new ParametersBuilder(this);
|
|
28263
30341
|
this.scorers = new ScorerBuilder(this);
|
|
30342
|
+
this.classifiers = new ClassifierBuilder(this);
|
|
28264
30343
|
}
|
|
28265
30344
|
addPrompt(prompt) {
|
|
28266
30345
|
this._publishablePrompts.push(prompt);
|
|
@@ -28395,6 +30474,28 @@ var ScorerBuilder = class {
|
|
|
28395
30474
|
}
|
|
28396
30475
|
}
|
|
28397
30476
|
};
|
|
30477
|
+
var ClassifierBuilder = class {
|
|
30478
|
+
constructor(project) {
|
|
30479
|
+
this.project = project;
|
|
30480
|
+
}
|
|
30481
|
+
taskCounter = 0;
|
|
30482
|
+
create(opts) {
|
|
30483
|
+
this.taskCounter++;
|
|
30484
|
+
let resolvedName = opts.name ?? opts.handler.name;
|
|
30485
|
+
if (!resolvedName || resolvedName.trim().length === 0) {
|
|
30486
|
+
resolvedName = `Classifier ${isomorph_default.basename(currentFilename)} ${this.taskCounter}`;
|
|
30487
|
+
}
|
|
30488
|
+
const slug = opts.slug ?? slugify(resolvedName, { lower: true, strict: true });
|
|
30489
|
+
const classifier = new CodeFunction(this.project, {
|
|
30490
|
+
...opts,
|
|
30491
|
+
name: resolvedName,
|
|
30492
|
+
slug,
|
|
30493
|
+
type: "classifier"
|
|
30494
|
+
});
|
|
30495
|
+
this.project.addCodeFunction(classifier);
|
|
30496
|
+
return classifier;
|
|
30497
|
+
}
|
|
30498
|
+
};
|
|
28398
30499
|
var CodeFunction = class {
|
|
28399
30500
|
constructor(project, opts) {
|
|
28400
30501
|
this.project = project;
|