braintrust 3.11.0 → 3.12.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/README.md +8 -8
- package/dev/dist/index.d.mts +1 -1
- package/dev/dist/index.d.ts +1 -1
- package/dev/dist/index.js +2607 -316
- package/dev/dist/index.mjs +2388 -97
- package/dist/apply-auto-instrumentation.browser.d.mts +2 -0
- package/dist/apply-auto-instrumentation.browser.d.ts +2 -0
- package/dist/apply-auto-instrumentation.browser.js +18 -0
- package/dist/apply-auto-instrumentation.browser.mjs +0 -0
- package/dist/apply-auto-instrumentation.d.mts +2 -0
- package/dist/apply-auto-instrumentation.d.ts +2 -0
- package/dist/apply-auto-instrumentation.js +2534 -0
- package/dist/apply-auto-instrumentation.mjs +2534 -0
- package/dist/auto-instrumentations/bundler/esbuild.cjs +1802 -1283
- package/dist/auto-instrumentations/bundler/esbuild.d.mts +9 -5
- package/dist/auto-instrumentations/bundler/esbuild.d.ts +9 -5
- package/dist/auto-instrumentations/bundler/esbuild.mjs +10 -2
- package/dist/auto-instrumentations/bundler/next.cjs +3268 -0
- package/dist/auto-instrumentations/bundler/next.d.mts +3 -0
- package/dist/auto-instrumentations/bundler/next.d.ts +3 -0
- package/dist/auto-instrumentations/bundler/next.mjs +189 -0
- package/dist/auto-instrumentations/bundler/rollup.cjs +1802 -1283
- package/dist/auto-instrumentations/bundler/rollup.d.mts +9 -5
- package/dist/auto-instrumentations/bundler/rollup.d.ts +9 -5
- package/dist/auto-instrumentations/bundler/rollup.mjs +10 -2
- package/dist/auto-instrumentations/bundler/vite.cjs +1802 -1283
- package/dist/auto-instrumentations/bundler/vite.d.mts +9 -5
- package/dist/auto-instrumentations/bundler/vite.d.ts +9 -5
- package/dist/auto-instrumentations/bundler/vite.mjs +10 -2
- package/dist/auto-instrumentations/bundler/webpack-loader.cjs +1860 -1308
- package/dist/auto-instrumentations/bundler/webpack-loader.d.ts +3 -3
- package/dist/auto-instrumentations/bundler/webpack.cjs +1802 -1283
- package/dist/auto-instrumentations/bundler/webpack.d.mts +9 -5
- package/dist/auto-instrumentations/bundler/webpack.d.ts +9 -5
- package/dist/auto-instrumentations/bundler/webpack.mjs +6 -6
- package/dist/auto-instrumentations/{chunk-DIV5TO4S.mjs → chunk-2DPA74KK.mjs} +337 -1
- package/dist/auto-instrumentations/chunk-73BZUKVI.mjs +300 -0
- package/dist/auto-instrumentations/chunk-AFXRW7I7.mjs +18 -0
- package/dist/auto-instrumentations/hook.mjs +1712 -1460
- package/dist/auto-instrumentations/index.cjs +93 -0
- package/dist/auto-instrumentations/index.d.mts +5 -1
- package/dist/auto-instrumentations/index.d.ts +5 -1
- package/dist/auto-instrumentations/index.mjs +6 -247
- package/dist/auto-instrumentations/loader/esm-hook.mjs +19 -2
- package/dist/auto-instrumentations/plugin-D7nDswtC.d.mts +44 -0
- package/dist/auto-instrumentations/plugin-D7nDswtC.d.ts +44 -0
- package/dist/browser.d.mts +120 -31
- package/dist/browser.d.ts +120 -31
- package/dist/browser.js +2395 -123
- package/dist/browser.mjs +2395 -123
- package/dist/chunk-BW4DF4CY.js +816 -0
- package/dist/chunk-MSLBGITU.mjs +816 -0
- package/dist/cli.js +2407 -96
- package/dist/edge-light.d.mts +1 -1
- package/dist/edge-light.d.ts +1 -1
- package/dist/edge-light.js +2395 -123
- package/dist/edge-light.mjs +2395 -123
- package/dist/index.d.mts +120 -31
- package/dist/index.d.ts +120 -31
- package/dist/index.js +3362 -1849
- package/dist/index.mjs +2505 -992
- package/dist/instrumentation/index.d.mts +7860 -48
- package/dist/instrumentation/index.d.ts +7860 -48
- package/dist/instrumentation/index.js +2395 -95
- package/dist/instrumentation/index.mjs +2394 -95
- package/dist/workerd.d.mts +1 -1
- package/dist/workerd.d.ts +1 -1
- package/dist/workerd.js +2395 -123
- package/dist/workerd.mjs +2395 -123
- package/package.json +23 -3
- package/util/dist/index.js +6 -0
- package/util/dist/index.mjs +6 -0
- package/dist/auto-instrumentations/chunk-G6ZWXGZB.mjs +0 -116
- package/dist/auto-instrumentations/plugin-Df3qKIl2.d.mts +0 -22
- package/dist/auto-instrumentations/plugin-Df3qKIl2.d.ts +0 -22
package/dist/workerd.mjs
CHANGED
|
@@ -921,6 +921,11 @@ function isPromiseLike(value) {
|
|
|
921
921
|
|
|
922
922
|
// util/object_util.ts
|
|
923
923
|
var SET_UNION_FIELDS = /* @__PURE__ */ new Set(["tags"]);
|
|
924
|
+
var FORBIDDEN_MERGE_KEYS = /* @__PURE__ */ new Set([
|
|
925
|
+
"__proto__",
|
|
926
|
+
"constructor",
|
|
927
|
+
"prototype"
|
|
928
|
+
]);
|
|
924
929
|
function mergeDictsWithPaths({
|
|
925
930
|
mergeInto,
|
|
926
931
|
mergeFrom,
|
|
@@ -943,6 +948,7 @@ function mergeDictsWithPathsHelper({
|
|
|
943
948
|
mergePaths
|
|
944
949
|
}) {
|
|
945
950
|
Object.entries(mergeFrom).forEach(([k, mergeFromV]) => {
|
|
951
|
+
if (FORBIDDEN_MERGE_KEYS.has(k)) return;
|
|
946
952
|
const fullPath = path.concat([k]);
|
|
947
953
|
const fullPathSerialized = JSON.stringify(fullPath);
|
|
948
954
|
const mergeIntoV = recordFind(mergeInto, k);
|
|
@@ -5016,6 +5022,13 @@ var HTTPConnection = class _HTTPConnection {
|
|
|
5016
5022
|
debugLogger.debug(
|
|
5017
5023
|
`Retrying API request ${object_type} ${JSON.stringify(args)} ${e.status} ${e.text}`
|
|
5018
5024
|
);
|
|
5025
|
+
const sleepTimeS = HTTP_RETRY_BASE_SLEEP_TIME_S * 2 ** i;
|
|
5026
|
+
debugLogger.info(
|
|
5027
|
+
`Sleeping for ${sleepTimeS}s before retrying API request`
|
|
5028
|
+
);
|
|
5029
|
+
await new Promise(
|
|
5030
|
+
(resolve) => setTimeout(resolve, sleepTimeS * 1e3)
|
|
5031
|
+
);
|
|
5019
5032
|
continue;
|
|
5020
5033
|
}
|
|
5021
5034
|
throw e;
|
|
@@ -5665,20 +5678,7 @@ function startSpanParentArgs(args) {
|
|
|
5665
5678
|
`Mismatch between expected span parent object type ${args.parentObjectType} and provided type ${parentComponents.data.object_type}`
|
|
5666
5679
|
);
|
|
5667
5680
|
}
|
|
5668
|
-
|
|
5669
|
-
args.state,
|
|
5670
|
-
parentComponents
|
|
5671
|
-
);
|
|
5672
|
-
const computeParentObjectId = async () => {
|
|
5673
|
-
const parentComponentsObjectId = await parentComponentsObjectIdLambda();
|
|
5674
|
-
if (await args.parentObjectId.get() !== parentComponentsObjectId) {
|
|
5675
|
-
throw new Error(
|
|
5676
|
-
`Mismatch between expected span parent object id ${await args.parentObjectId.get()} and provided id ${parentComponentsObjectId}`
|
|
5677
|
-
);
|
|
5678
|
-
}
|
|
5679
|
-
return await args.parentObjectId.get();
|
|
5680
|
-
};
|
|
5681
|
-
argParentObjectId = new LazyValue(computeParentObjectId);
|
|
5681
|
+
argParentObjectId = args.parentObjectId;
|
|
5682
5682
|
if (parentComponents.data.row_id) {
|
|
5683
5683
|
argParentSpanIds = {
|
|
5684
5684
|
spanId: parentComponents.data.span_id,
|
|
@@ -6064,6 +6064,7 @@ var TestBackgroundLogger = class {
|
|
|
6064
6064
|
}
|
|
6065
6065
|
};
|
|
6066
6066
|
var BACKGROUND_LOGGER_BASE_SLEEP_TIME_S = 1;
|
|
6067
|
+
var HTTP_RETRY_BASE_SLEEP_TIME_S = 1;
|
|
6067
6068
|
var HTTPBackgroundLogger = class _HTTPBackgroundLogger {
|
|
6068
6069
|
apiConn;
|
|
6069
6070
|
queue;
|
|
@@ -6694,17 +6695,10 @@ function init(projectOrOptions, optionalOptions) {
|
|
|
6694
6695
|
if (repoInfo) {
|
|
6695
6696
|
return repoInfo;
|
|
6696
6697
|
}
|
|
6697
|
-
|
|
6698
|
-
|
|
6699
|
-
|
|
6700
|
-
|
|
6701
|
-
};
|
|
6702
|
-
if (gitMetadataSettings) {
|
|
6703
|
-
mergedGitMetadataSettings = mergeGitMetadataSettings(
|
|
6704
|
-
mergedGitMetadataSettings,
|
|
6705
|
-
gitMetadataSettings
|
|
6706
|
-
);
|
|
6707
|
-
}
|
|
6698
|
+
const mergedGitMetadataSettings = state.gitMetadataSettings == null ? gitMetadataSettings ?? { collect: "none" } : mergeGitMetadataSettings(
|
|
6699
|
+
state.gitMetadataSettings,
|
|
6700
|
+
gitMetadataSettings ?? { collect: "all" }
|
|
6701
|
+
);
|
|
6708
6702
|
return await isomorph_default.getRepoInfo(mergedGitMetadataSettings);
|
|
6709
6703
|
})();
|
|
6710
6704
|
if (repoInfoArg) {
|
|
@@ -13523,11 +13517,11 @@ function resolveDenyOutputPaths(event, defaultDenyOutputPaths) {
|
|
|
13523
13517
|
if (Array.isArray(event?.denyOutputPaths)) {
|
|
13524
13518
|
return event.denyOutputPaths;
|
|
13525
13519
|
}
|
|
13526
|
-
const
|
|
13527
|
-
if (!
|
|
13520
|
+
const firstArgument2 = event?.arguments && event.arguments.length > 0 ? event.arguments[0] : void 0;
|
|
13521
|
+
if (!firstArgument2 || typeof firstArgument2 !== "object") {
|
|
13528
13522
|
return defaultDenyOutputPaths;
|
|
13529
13523
|
}
|
|
13530
|
-
const runtimeDenyOutputPaths =
|
|
13524
|
+
const runtimeDenyOutputPaths = firstArgument2[RUNTIME_DENY_OUTPUT_PATHS];
|
|
13531
13525
|
if (Array.isArray(runtimeDenyOutputPaths) && runtimeDenyOutputPaths.every((path) => typeof path === "string")) {
|
|
13532
13526
|
return runtimeDenyOutputPaths;
|
|
13533
13527
|
}
|
|
@@ -17186,6 +17180,467 @@ function cleanMetrics2(metrics) {
|
|
|
17186
17180
|
return cleaned;
|
|
17187
17181
|
}
|
|
17188
17182
|
|
|
17183
|
+
// src/instrumentation/plugins/openai-agents-channels.ts
|
|
17184
|
+
var openAIAgentsCoreChannels = defineChannels("@openai/agents-core", {
|
|
17185
|
+
onTraceStart: channel({
|
|
17186
|
+
channelName: "tracing.processor.onTraceStart",
|
|
17187
|
+
kind: "async"
|
|
17188
|
+
}),
|
|
17189
|
+
onTraceEnd: channel({
|
|
17190
|
+
channelName: "tracing.processor.onTraceEnd",
|
|
17191
|
+
kind: "async"
|
|
17192
|
+
}),
|
|
17193
|
+
onSpanStart: channel({
|
|
17194
|
+
channelName: "tracing.processor.onSpanStart",
|
|
17195
|
+
kind: "async"
|
|
17196
|
+
}),
|
|
17197
|
+
onSpanEnd: channel({
|
|
17198
|
+
channelName: "tracing.processor.onSpanEnd",
|
|
17199
|
+
kind: "async"
|
|
17200
|
+
})
|
|
17201
|
+
});
|
|
17202
|
+
|
|
17203
|
+
// src/instrumentation/plugins/openai-agents-trace-processor.ts
|
|
17204
|
+
function isSpanData(spanData, type) {
|
|
17205
|
+
return spanData.type === type;
|
|
17206
|
+
}
|
|
17207
|
+
function spanTypeFromAgents(span) {
|
|
17208
|
+
const spanType = span.spanData.type;
|
|
17209
|
+
if (spanType === "function" || spanType === "guardrail" || spanType === "mcp_tools") {
|
|
17210
|
+
return "tool" /* TOOL */;
|
|
17211
|
+
}
|
|
17212
|
+
if (spanType === "generation" || spanType === "response" || spanType === "transcription" || spanType === "speech") {
|
|
17213
|
+
return "llm" /* LLM */;
|
|
17214
|
+
}
|
|
17215
|
+
return "task" /* TASK */;
|
|
17216
|
+
}
|
|
17217
|
+
function spanNameFromAgents(span) {
|
|
17218
|
+
const spanData = span.spanData;
|
|
17219
|
+
if ("name" in spanData && spanData.name) {
|
|
17220
|
+
return spanData.name;
|
|
17221
|
+
}
|
|
17222
|
+
switch (spanData.type) {
|
|
17223
|
+
case "generation":
|
|
17224
|
+
return "Generation";
|
|
17225
|
+
case "response":
|
|
17226
|
+
return "Response";
|
|
17227
|
+
case "handoff":
|
|
17228
|
+
return "Handoff";
|
|
17229
|
+
case "mcp_tools":
|
|
17230
|
+
return isSpanData(spanData, "mcp_tools") && spanData.server ? `List Tools (${spanData.server})` : "MCP List Tools";
|
|
17231
|
+
case "transcription":
|
|
17232
|
+
return "Transcription";
|
|
17233
|
+
case "speech":
|
|
17234
|
+
return "Speech";
|
|
17235
|
+
case "speech_group":
|
|
17236
|
+
return "Speech Group";
|
|
17237
|
+
default:
|
|
17238
|
+
return "Unknown";
|
|
17239
|
+
}
|
|
17240
|
+
}
|
|
17241
|
+
function getTimeElapsed(end, start) {
|
|
17242
|
+
if (!start || !end) {
|
|
17243
|
+
return void 0;
|
|
17244
|
+
}
|
|
17245
|
+
const startTime = new Date(start).getTime();
|
|
17246
|
+
const endTime = new Date(end).getTime();
|
|
17247
|
+
if (Number.isNaN(startTime) || Number.isNaN(endTime)) {
|
|
17248
|
+
return void 0;
|
|
17249
|
+
}
|
|
17250
|
+
return (endTime - startTime) / 1e3;
|
|
17251
|
+
}
|
|
17252
|
+
function getNumberProperty2(obj, key) {
|
|
17253
|
+
if (!isObject(obj) || !(key in obj)) {
|
|
17254
|
+
return void 0;
|
|
17255
|
+
}
|
|
17256
|
+
const value = obj[key];
|
|
17257
|
+
return typeof value === "number" ? value : void 0;
|
|
17258
|
+
}
|
|
17259
|
+
function parseUsageMetrics(usage) {
|
|
17260
|
+
const metrics = {};
|
|
17261
|
+
if (!isObject(usage)) {
|
|
17262
|
+
return metrics;
|
|
17263
|
+
}
|
|
17264
|
+
const promptTokens = getNumberProperty2(usage, "prompt_tokens") ?? getNumberProperty2(usage, "input_tokens") ?? getNumberProperty2(usage, "promptTokens") ?? getNumberProperty2(usage, "inputTokens");
|
|
17265
|
+
const completionTokens = getNumberProperty2(usage, "completion_tokens") ?? getNumberProperty2(usage, "output_tokens") ?? getNumberProperty2(usage, "completionTokens") ?? getNumberProperty2(usage, "outputTokens");
|
|
17266
|
+
const totalTokens = getNumberProperty2(usage, "total_tokens") ?? getNumberProperty2(usage, "totalTokens");
|
|
17267
|
+
if (promptTokens !== void 0) {
|
|
17268
|
+
metrics.prompt_tokens = promptTokens;
|
|
17269
|
+
}
|
|
17270
|
+
if (completionTokens !== void 0) {
|
|
17271
|
+
metrics.completion_tokens = completionTokens;
|
|
17272
|
+
}
|
|
17273
|
+
if (totalTokens !== void 0) {
|
|
17274
|
+
metrics.tokens = totalTokens;
|
|
17275
|
+
} else if (promptTokens !== void 0 && completionTokens !== void 0) {
|
|
17276
|
+
metrics.tokens = promptTokens + completionTokens;
|
|
17277
|
+
}
|
|
17278
|
+
const inputDetails = usage.input_tokens_details;
|
|
17279
|
+
const cachedTokens = getNumberProperty2(inputDetails, "cached_tokens");
|
|
17280
|
+
const cacheWriteTokens = getNumberProperty2(
|
|
17281
|
+
inputDetails,
|
|
17282
|
+
"cache_write_tokens"
|
|
17283
|
+
);
|
|
17284
|
+
if (cachedTokens !== void 0) {
|
|
17285
|
+
metrics.prompt_cached_tokens = cachedTokens;
|
|
17286
|
+
}
|
|
17287
|
+
if (cacheWriteTokens !== void 0) {
|
|
17288
|
+
metrics.prompt_cache_creation_tokens = cacheWriteTokens;
|
|
17289
|
+
}
|
|
17290
|
+
return metrics;
|
|
17291
|
+
}
|
|
17292
|
+
var OpenAIAgentsTraceProcessor = class _OpenAIAgentsTraceProcessor {
|
|
17293
|
+
static DEFAULT_MAX_TRACES = 1e4;
|
|
17294
|
+
logger;
|
|
17295
|
+
maxTraces;
|
|
17296
|
+
traceSpans = /* @__PURE__ */ new Map();
|
|
17297
|
+
traceOrder = [];
|
|
17298
|
+
_traceSpans = this.traceSpans;
|
|
17299
|
+
constructor(options = {}) {
|
|
17300
|
+
this.logger = options.logger;
|
|
17301
|
+
this.maxTraces = options.maxTraces ?? _OpenAIAgentsTraceProcessor.DEFAULT_MAX_TRACES;
|
|
17302
|
+
}
|
|
17303
|
+
evictOldestTrace() {
|
|
17304
|
+
const oldestTraceId = this.traceOrder.shift();
|
|
17305
|
+
if (oldestTraceId) {
|
|
17306
|
+
this.traceSpans.delete(oldestTraceId);
|
|
17307
|
+
}
|
|
17308
|
+
}
|
|
17309
|
+
onTraceStart(trace) {
|
|
17310
|
+
if (!trace?.traceId) {
|
|
17311
|
+
return Promise.resolve();
|
|
17312
|
+
}
|
|
17313
|
+
if (this.traceOrder.length >= this.maxTraces) {
|
|
17314
|
+
this.evictOldestTrace();
|
|
17315
|
+
}
|
|
17316
|
+
const current = currentSpan();
|
|
17317
|
+
const span = current && current !== NOOP_SPAN ? current.startSpan({
|
|
17318
|
+
name: trace.name,
|
|
17319
|
+
type: "task" /* TASK */
|
|
17320
|
+
}) : this.logger ? this.logger.startSpan({
|
|
17321
|
+
name: trace.name,
|
|
17322
|
+
type: "task" /* TASK */
|
|
17323
|
+
}) : startSpan({
|
|
17324
|
+
name: trace.name,
|
|
17325
|
+
type: "task" /* TASK */
|
|
17326
|
+
});
|
|
17327
|
+
span.log({
|
|
17328
|
+
input: "Agent workflow started",
|
|
17329
|
+
metadata: {
|
|
17330
|
+
group_id: trace.groupId,
|
|
17331
|
+
...trace.metadata || {}
|
|
17332
|
+
}
|
|
17333
|
+
});
|
|
17334
|
+
this.traceSpans.set(trace.traceId, {
|
|
17335
|
+
rootSpan: span,
|
|
17336
|
+
childSpans: /* @__PURE__ */ new Map(),
|
|
17337
|
+
metadata: {
|
|
17338
|
+
firstInput: null,
|
|
17339
|
+
lastOutput: null
|
|
17340
|
+
}
|
|
17341
|
+
});
|
|
17342
|
+
this.traceOrder.push(trace.traceId);
|
|
17343
|
+
return Promise.resolve();
|
|
17344
|
+
}
|
|
17345
|
+
async onTraceEnd(trace) {
|
|
17346
|
+
const traceData = this.traceSpans.get(trace?.traceId);
|
|
17347
|
+
if (!traceData) {
|
|
17348
|
+
return;
|
|
17349
|
+
}
|
|
17350
|
+
try {
|
|
17351
|
+
traceData.rootSpan.log({
|
|
17352
|
+
input: traceData.metadata.firstInput,
|
|
17353
|
+
output: traceData.metadata.lastOutput
|
|
17354
|
+
});
|
|
17355
|
+
traceData.rootSpan.end();
|
|
17356
|
+
await traceData.rootSpan.flush();
|
|
17357
|
+
} finally {
|
|
17358
|
+
this.traceSpans.delete(trace.traceId);
|
|
17359
|
+
const orderIndex = this.traceOrder.indexOf(trace.traceId);
|
|
17360
|
+
if (orderIndex > -1) {
|
|
17361
|
+
this.traceOrder.splice(orderIndex, 1);
|
|
17362
|
+
}
|
|
17363
|
+
}
|
|
17364
|
+
}
|
|
17365
|
+
onSpanStart(span) {
|
|
17366
|
+
if (!span?.spanId || !span.traceId) {
|
|
17367
|
+
return Promise.resolve();
|
|
17368
|
+
}
|
|
17369
|
+
const traceData = this.traceSpans.get(span.traceId);
|
|
17370
|
+
if (!traceData) {
|
|
17371
|
+
return Promise.resolve();
|
|
17372
|
+
}
|
|
17373
|
+
const parentSpan = span.parentId ? traceData.childSpans.get(span.parentId) : traceData.rootSpan;
|
|
17374
|
+
if (!parentSpan) {
|
|
17375
|
+
return Promise.resolve();
|
|
17376
|
+
}
|
|
17377
|
+
const childSpan = parentSpan.startSpan({
|
|
17378
|
+
name: spanNameFromAgents(span),
|
|
17379
|
+
type: spanTypeFromAgents(span)
|
|
17380
|
+
});
|
|
17381
|
+
traceData.childSpans.set(span.spanId, childSpan);
|
|
17382
|
+
return Promise.resolve();
|
|
17383
|
+
}
|
|
17384
|
+
onSpanEnd(span) {
|
|
17385
|
+
if (!span?.spanId || !span.traceId) {
|
|
17386
|
+
return Promise.resolve();
|
|
17387
|
+
}
|
|
17388
|
+
const traceData = this.traceSpans.get(span.traceId);
|
|
17389
|
+
if (!traceData) {
|
|
17390
|
+
return Promise.resolve();
|
|
17391
|
+
}
|
|
17392
|
+
const braintrustSpan = traceData.childSpans.get(span.spanId);
|
|
17393
|
+
if (!braintrustSpan) {
|
|
17394
|
+
return Promise.resolve();
|
|
17395
|
+
}
|
|
17396
|
+
const logData = this.extractLogData(span);
|
|
17397
|
+
braintrustSpan.log({
|
|
17398
|
+
error: span.error,
|
|
17399
|
+
...logData
|
|
17400
|
+
});
|
|
17401
|
+
braintrustSpan.end();
|
|
17402
|
+
traceData.childSpans.delete(span.spanId);
|
|
17403
|
+
const input = logData.input;
|
|
17404
|
+
const output = logData.output;
|
|
17405
|
+
if (traceData.metadata.firstInput === null && input != null) {
|
|
17406
|
+
traceData.metadata.firstInput = input;
|
|
17407
|
+
}
|
|
17408
|
+
if (output != null) {
|
|
17409
|
+
traceData.metadata.lastOutput = output;
|
|
17410
|
+
}
|
|
17411
|
+
return Promise.resolve();
|
|
17412
|
+
}
|
|
17413
|
+
async shutdown() {
|
|
17414
|
+
if (this.logger && typeof this.logger.flush === "function") {
|
|
17415
|
+
await this.logger.flush();
|
|
17416
|
+
}
|
|
17417
|
+
}
|
|
17418
|
+
async forceFlush() {
|
|
17419
|
+
if (this.logger && typeof this.logger.flush === "function") {
|
|
17420
|
+
await this.logger.flush();
|
|
17421
|
+
}
|
|
17422
|
+
}
|
|
17423
|
+
extractLogData(span) {
|
|
17424
|
+
const spanData = span.spanData;
|
|
17425
|
+
switch (spanData.type) {
|
|
17426
|
+
case "agent":
|
|
17427
|
+
return this.extractAgentLogData(spanData);
|
|
17428
|
+
case "response":
|
|
17429
|
+
return this.extractResponseLogData(spanData, span);
|
|
17430
|
+
case "function":
|
|
17431
|
+
return this.extractFunctionLogData(spanData);
|
|
17432
|
+
case "handoff":
|
|
17433
|
+
return this.extractHandoffLogData(spanData);
|
|
17434
|
+
case "guardrail":
|
|
17435
|
+
return this.extractGuardrailLogData(spanData);
|
|
17436
|
+
case "generation":
|
|
17437
|
+
return this.extractGenerationLogData(spanData, span);
|
|
17438
|
+
case "custom":
|
|
17439
|
+
return this.extractCustomLogData(spanData);
|
|
17440
|
+
case "mcp_tools":
|
|
17441
|
+
return this.extractMCPListToolsLogData(spanData);
|
|
17442
|
+
case "transcription":
|
|
17443
|
+
return this.extractTranscriptionLogData(spanData);
|
|
17444
|
+
case "speech":
|
|
17445
|
+
return this.extractSpeechLogData(spanData);
|
|
17446
|
+
case "speech_group":
|
|
17447
|
+
return this.extractSpeechGroupLogData(spanData);
|
|
17448
|
+
default:
|
|
17449
|
+
return {};
|
|
17450
|
+
}
|
|
17451
|
+
}
|
|
17452
|
+
extractAgentLogData(spanData) {
|
|
17453
|
+
return {
|
|
17454
|
+
metadata: {
|
|
17455
|
+
tools: spanData.tools,
|
|
17456
|
+
handoffs: spanData.handoffs,
|
|
17457
|
+
output_type: spanData.output_type
|
|
17458
|
+
}
|
|
17459
|
+
};
|
|
17460
|
+
}
|
|
17461
|
+
extractResponseLogData(spanData, span) {
|
|
17462
|
+
const response = spanData._response;
|
|
17463
|
+
const output = isObject(response) ? response.output : void 0;
|
|
17464
|
+
const usage = isObject(response) ? response.usage : void 0;
|
|
17465
|
+
const metrics = {
|
|
17466
|
+
...this.extractTimingMetrics(span),
|
|
17467
|
+
...parseUsageMetrics(usage)
|
|
17468
|
+
};
|
|
17469
|
+
return {
|
|
17470
|
+
input: spanData._input,
|
|
17471
|
+
output,
|
|
17472
|
+
metadata: isObject(response) ? this.omitKeys(response, ["output", "usage"]) : {},
|
|
17473
|
+
metrics
|
|
17474
|
+
};
|
|
17475
|
+
}
|
|
17476
|
+
extractFunctionLogData(spanData) {
|
|
17477
|
+
return {
|
|
17478
|
+
input: spanData.input,
|
|
17479
|
+
output: spanData.output
|
|
17480
|
+
};
|
|
17481
|
+
}
|
|
17482
|
+
extractHandoffLogData(spanData) {
|
|
17483
|
+
return {
|
|
17484
|
+
metadata: {
|
|
17485
|
+
from_agent: spanData.from_agent,
|
|
17486
|
+
to_agent: spanData.to_agent
|
|
17487
|
+
}
|
|
17488
|
+
};
|
|
17489
|
+
}
|
|
17490
|
+
extractGuardrailLogData(spanData) {
|
|
17491
|
+
return {
|
|
17492
|
+
metadata: {
|
|
17493
|
+
triggered: spanData.triggered
|
|
17494
|
+
}
|
|
17495
|
+
};
|
|
17496
|
+
}
|
|
17497
|
+
extractGenerationLogData(spanData, span) {
|
|
17498
|
+
return {
|
|
17499
|
+
input: spanData.input,
|
|
17500
|
+
output: spanData.output,
|
|
17501
|
+
metadata: {
|
|
17502
|
+
model: spanData.model,
|
|
17503
|
+
model_config: spanData.model_config
|
|
17504
|
+
},
|
|
17505
|
+
metrics: {
|
|
17506
|
+
...this.extractTimingMetrics(span),
|
|
17507
|
+
...parseUsageMetrics(spanData.usage)
|
|
17508
|
+
}
|
|
17509
|
+
};
|
|
17510
|
+
}
|
|
17511
|
+
extractCustomLogData(spanData) {
|
|
17512
|
+
return spanData.data || {};
|
|
17513
|
+
}
|
|
17514
|
+
extractMCPListToolsLogData(spanData) {
|
|
17515
|
+
return {
|
|
17516
|
+
output: spanData.result,
|
|
17517
|
+
metadata: {
|
|
17518
|
+
server: spanData.server
|
|
17519
|
+
}
|
|
17520
|
+
};
|
|
17521
|
+
}
|
|
17522
|
+
extractTranscriptionLogData(spanData) {
|
|
17523
|
+
return {
|
|
17524
|
+
input: spanData.input,
|
|
17525
|
+
output: spanData.output,
|
|
17526
|
+
metadata: {
|
|
17527
|
+
model: spanData.model,
|
|
17528
|
+
model_config: spanData.model_config
|
|
17529
|
+
}
|
|
17530
|
+
};
|
|
17531
|
+
}
|
|
17532
|
+
extractSpeechLogData(spanData) {
|
|
17533
|
+
return {
|
|
17534
|
+
input: spanData.input,
|
|
17535
|
+
output: spanData.output,
|
|
17536
|
+
metadata: {
|
|
17537
|
+
model: spanData.model,
|
|
17538
|
+
model_config: spanData.model_config
|
|
17539
|
+
}
|
|
17540
|
+
};
|
|
17541
|
+
}
|
|
17542
|
+
extractSpeechGroupLogData(spanData) {
|
|
17543
|
+
return {
|
|
17544
|
+
input: spanData.input
|
|
17545
|
+
};
|
|
17546
|
+
}
|
|
17547
|
+
extractTimingMetrics(span) {
|
|
17548
|
+
const timeToFirstToken = getTimeElapsed(
|
|
17549
|
+
span.endedAt ?? void 0,
|
|
17550
|
+
span.startedAt ?? void 0
|
|
17551
|
+
);
|
|
17552
|
+
return timeToFirstToken === void 0 ? {} : { time_to_first_token: timeToFirstToken };
|
|
17553
|
+
}
|
|
17554
|
+
omitKeys(value, keys) {
|
|
17555
|
+
const result = {};
|
|
17556
|
+
for (const [key, fieldValue] of Object.entries(value)) {
|
|
17557
|
+
if (!keys.includes(key)) {
|
|
17558
|
+
result[key] = fieldValue;
|
|
17559
|
+
}
|
|
17560
|
+
}
|
|
17561
|
+
return result;
|
|
17562
|
+
}
|
|
17563
|
+
};
|
|
17564
|
+
|
|
17565
|
+
// src/instrumentation/plugins/openai-agents-plugin.ts
|
|
17566
|
+
function firstArgument(args) {
|
|
17567
|
+
if (Array.isArray(args)) {
|
|
17568
|
+
return args[0];
|
|
17569
|
+
}
|
|
17570
|
+
if (isObject(args) && "length" in args && typeof args.length === "number" && Number.isInteger(args.length) && args.length >= 0) {
|
|
17571
|
+
return Array.from(args)[0];
|
|
17572
|
+
}
|
|
17573
|
+
return void 0;
|
|
17574
|
+
}
|
|
17575
|
+
function isOpenAIAgentsTrace(value) {
|
|
17576
|
+
return isObject(value) && value.type === "trace" && typeof value.traceId === "string";
|
|
17577
|
+
}
|
|
17578
|
+
function isOpenAIAgentsSpan(value) {
|
|
17579
|
+
return isObject(value) && value.type === "trace.span" && typeof value.traceId === "string" && typeof value.spanId === "string";
|
|
17580
|
+
}
|
|
17581
|
+
var OpenAIAgentsPlugin = class extends BasePlugin {
|
|
17582
|
+
processor = new OpenAIAgentsTraceProcessor();
|
|
17583
|
+
onEnable() {
|
|
17584
|
+
this.subscribeToTraceLifecycle();
|
|
17585
|
+
}
|
|
17586
|
+
onDisable() {
|
|
17587
|
+
this.unsubscribers = unsubscribeAll(this.unsubscribers);
|
|
17588
|
+
void this.processor.shutdown();
|
|
17589
|
+
}
|
|
17590
|
+
subscribeToTraceLifecycle() {
|
|
17591
|
+
const traceStartChannel = openAIAgentsCoreChannels.onTraceStart.tracingChannel();
|
|
17592
|
+
const traceStartHandlers = {
|
|
17593
|
+
start: (event) => {
|
|
17594
|
+
const trace = firstArgument(event.arguments);
|
|
17595
|
+
if (isOpenAIAgentsTrace(trace)) {
|
|
17596
|
+
void this.processor.onTraceStart(trace);
|
|
17597
|
+
}
|
|
17598
|
+
}
|
|
17599
|
+
};
|
|
17600
|
+
traceStartChannel.subscribe(traceStartHandlers);
|
|
17601
|
+
this.unsubscribers.push(
|
|
17602
|
+
() => traceStartChannel.unsubscribe(traceStartHandlers)
|
|
17603
|
+
);
|
|
17604
|
+
const traceEndChannel = openAIAgentsCoreChannels.onTraceEnd.tracingChannel();
|
|
17605
|
+
const traceEndHandlers = {
|
|
17606
|
+
start: (event) => {
|
|
17607
|
+
const trace = firstArgument(event.arguments);
|
|
17608
|
+
if (isOpenAIAgentsTrace(trace)) {
|
|
17609
|
+
void this.processor.onTraceEnd(trace);
|
|
17610
|
+
}
|
|
17611
|
+
}
|
|
17612
|
+
};
|
|
17613
|
+
traceEndChannel.subscribe(traceEndHandlers);
|
|
17614
|
+
this.unsubscribers.push(
|
|
17615
|
+
() => traceEndChannel.unsubscribe(traceEndHandlers)
|
|
17616
|
+
);
|
|
17617
|
+
const spanStartChannel = openAIAgentsCoreChannels.onSpanStart.tracingChannel();
|
|
17618
|
+
const spanStartHandlers = {
|
|
17619
|
+
start: (event) => {
|
|
17620
|
+
const span = firstArgument(event.arguments);
|
|
17621
|
+
if (isOpenAIAgentsSpan(span)) {
|
|
17622
|
+
void this.processor.onSpanStart(span);
|
|
17623
|
+
}
|
|
17624
|
+
}
|
|
17625
|
+
};
|
|
17626
|
+
spanStartChannel.subscribe(spanStartHandlers);
|
|
17627
|
+
this.unsubscribers.push(
|
|
17628
|
+
() => spanStartChannel.unsubscribe(spanStartHandlers)
|
|
17629
|
+
);
|
|
17630
|
+
const spanEndChannel = openAIAgentsCoreChannels.onSpanEnd.tracingChannel();
|
|
17631
|
+
const spanEndHandlers = {
|
|
17632
|
+
start: (event) => {
|
|
17633
|
+
const span = firstArgument(event.arguments);
|
|
17634
|
+
if (isOpenAIAgentsSpan(span)) {
|
|
17635
|
+
void this.processor.onSpanEnd(span);
|
|
17636
|
+
}
|
|
17637
|
+
}
|
|
17638
|
+
};
|
|
17639
|
+
spanEndChannel.subscribe(spanEndHandlers);
|
|
17640
|
+
this.unsubscribers.push(() => spanEndChannel.unsubscribe(spanEndHandlers));
|
|
17641
|
+
}
|
|
17642
|
+
};
|
|
17643
|
+
|
|
17189
17644
|
// src/instrumentation/plugins/google-genai-channels.ts
|
|
17190
17645
|
var googleGenAIChannels = defineChannels("@google/genai", {
|
|
17191
17646
|
generateContent: channel({
|
|
@@ -23478,41 +23933,1773 @@ var GitHubCopilotPlugin = class extends BasePlugin {
|
|
|
23478
23933
|
}
|
|
23479
23934
|
};
|
|
23480
23935
|
|
|
23481
|
-
// src/instrumentation/
|
|
23482
|
-
|
|
23483
|
-
|
|
23936
|
+
// src/instrumentation/plugins/flue-channels.ts
|
|
23937
|
+
var flueChannels = defineChannels("@flue/runtime", {
|
|
23938
|
+
createContext: channel({
|
|
23939
|
+
channelName: "createFlueContext",
|
|
23940
|
+
kind: "sync-stream"
|
|
23941
|
+
}),
|
|
23942
|
+
openSession: channel({
|
|
23943
|
+
channelName: "Harness.openSession",
|
|
23944
|
+
kind: "async"
|
|
23945
|
+
}),
|
|
23946
|
+
contextEvent: channel({
|
|
23947
|
+
channelName: "context.event",
|
|
23948
|
+
kind: "sync-stream"
|
|
23949
|
+
}),
|
|
23950
|
+
prompt: channel({
|
|
23951
|
+
channelName: "session.prompt",
|
|
23952
|
+
kind: "async"
|
|
23953
|
+
}),
|
|
23954
|
+
skill: channel({
|
|
23955
|
+
channelName: "session.skill",
|
|
23956
|
+
kind: "async"
|
|
23957
|
+
}),
|
|
23958
|
+
task: channel({
|
|
23959
|
+
channelName: "session.task",
|
|
23960
|
+
kind: "async"
|
|
23961
|
+
}),
|
|
23962
|
+
compact: channel({
|
|
23963
|
+
channelName: "session.compact",
|
|
23964
|
+
kind: "async"
|
|
23965
|
+
})
|
|
23966
|
+
});
|
|
23967
|
+
|
|
23968
|
+
// src/wrappers/flue.ts
|
|
23969
|
+
var WRAPPED_FLUE_CONTEXT = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-context");
|
|
23970
|
+
var WRAPPED_FLUE_HARNESS = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-harness");
|
|
23971
|
+
var WRAPPED_FLUE_SESSION = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-session");
|
|
23972
|
+
var SUBSCRIBED_FLUE_CONTEXT_EVENTS = /* @__PURE__ */ Symbol.for(
|
|
23973
|
+
"braintrust.flue.subscribed-context-events"
|
|
23974
|
+
);
|
|
23975
|
+
function wrapFlueContext(ctx) {
|
|
23976
|
+
if (!isPlausibleFlueContext(ctx)) {
|
|
23977
|
+
console.warn("Unsupported Flue context. Not wrapping.");
|
|
23978
|
+
return ctx;
|
|
23979
|
+
}
|
|
23980
|
+
const context = ctx;
|
|
23981
|
+
subscribeFlueContextEvents(context, { captureTurnSpans: true });
|
|
23982
|
+
return patchFlueContextInPlace(context);
|
|
23484
23983
|
}
|
|
23485
|
-
|
|
23486
|
-
|
|
23487
|
-
|
|
23488
|
-
|
|
23489
|
-
anthropicPlugin = null;
|
|
23490
|
-
aiSDKPlugin = null;
|
|
23491
|
-
claudeAgentSDKPlugin = null;
|
|
23492
|
-
cursorSDKPlugin = null;
|
|
23493
|
-
googleGenAIPlugin = null;
|
|
23494
|
-
huggingFacePlugin = null;
|
|
23495
|
-
openRouterPlugin = null;
|
|
23496
|
-
openRouterAgentPlugin = null;
|
|
23497
|
-
mistralPlugin = null;
|
|
23498
|
-
googleADKPlugin = null;
|
|
23499
|
-
coherePlugin = null;
|
|
23500
|
-
groqPlugin = null;
|
|
23501
|
-
genkitPlugin = null;
|
|
23502
|
-
gitHubCopilotPlugin = null;
|
|
23503
|
-
constructor(config = {}) {
|
|
23504
|
-
super();
|
|
23505
|
-
this.config = config;
|
|
23984
|
+
function patchFlueContextInPlace(ctx) {
|
|
23985
|
+
const context = ctx;
|
|
23986
|
+
if (context[WRAPPED_FLUE_CONTEXT]) {
|
|
23987
|
+
return ctx;
|
|
23506
23988
|
}
|
|
23507
|
-
|
|
23508
|
-
|
|
23509
|
-
|
|
23510
|
-
|
|
23511
|
-
|
|
23989
|
+
const originalInit = context.init.bind(context);
|
|
23990
|
+
try {
|
|
23991
|
+
Object.defineProperty(context, WRAPPED_FLUE_CONTEXT, {
|
|
23992
|
+
configurable: false,
|
|
23993
|
+
enumerable: false,
|
|
23994
|
+
value: true
|
|
23995
|
+
});
|
|
23996
|
+
Object.defineProperty(context, "init", {
|
|
23997
|
+
configurable: true,
|
|
23998
|
+
value: async function wrappedFlueInit(options) {
|
|
23999
|
+
const harness = await originalInit(options);
|
|
24000
|
+
return wrapFlueHarness(harness);
|
|
24001
|
+
},
|
|
24002
|
+
writable: true
|
|
24003
|
+
});
|
|
24004
|
+
} catch {
|
|
24005
|
+
}
|
|
24006
|
+
return ctx;
|
|
24007
|
+
}
|
|
24008
|
+
function wrapFlueSession(session) {
|
|
24009
|
+
if (!isPlausibleFlueSession(session)) {
|
|
24010
|
+
console.warn("Unsupported Flue session. Not wrapping.");
|
|
24011
|
+
return session;
|
|
24012
|
+
}
|
|
24013
|
+
return patchFlueSessionInPlace(session);
|
|
24014
|
+
}
|
|
24015
|
+
function subscribeFlueContextEvents(ctx, options = {}) {
|
|
24016
|
+
if (!ctx || typeof ctx !== "object" || typeof ctx.subscribeEvent !== "function") {
|
|
24017
|
+
return void 0;
|
|
24018
|
+
}
|
|
24019
|
+
const context = ctx;
|
|
24020
|
+
const captureTurnSpans = options.captureTurnSpans ?? true;
|
|
24021
|
+
const existingSubscription = context[SUBSCRIBED_FLUE_CONTEXT_EVENTS];
|
|
24022
|
+
if (existingSubscription) {
|
|
24023
|
+
if (existingSubscription.captureTurnSpans || !captureTurnSpans) {
|
|
24024
|
+
return void 0;
|
|
23512
24025
|
}
|
|
23513
|
-
|
|
23514
|
-
|
|
23515
|
-
|
|
24026
|
+
try {
|
|
24027
|
+
existingSubscription.unsubscribe();
|
|
24028
|
+
} catch {
|
|
24029
|
+
}
|
|
24030
|
+
}
|
|
24031
|
+
try {
|
|
24032
|
+
const unsubscribe = ctx.subscribeEvent((event) => {
|
|
24033
|
+
flueChannels.contextEvent.traceSync(() => void 0, {
|
|
24034
|
+
arguments: [event],
|
|
24035
|
+
captureTurnSpans,
|
|
24036
|
+
context: ctx
|
|
24037
|
+
});
|
|
24038
|
+
});
|
|
24039
|
+
if (existingSubscription) {
|
|
24040
|
+
existingSubscription.captureTurnSpans = captureTurnSpans;
|
|
24041
|
+
existingSubscription.unsubscribe = unsubscribe;
|
|
24042
|
+
} else {
|
|
24043
|
+
Object.defineProperty(context, SUBSCRIBED_FLUE_CONTEXT_EVENTS, {
|
|
24044
|
+
configurable: false,
|
|
24045
|
+
enumerable: false,
|
|
24046
|
+
value: {
|
|
24047
|
+
captureTurnSpans,
|
|
24048
|
+
unsubscribe
|
|
24049
|
+
}
|
|
24050
|
+
});
|
|
24051
|
+
}
|
|
24052
|
+
return unsubscribe;
|
|
24053
|
+
} catch {
|
|
24054
|
+
return void 0;
|
|
24055
|
+
}
|
|
24056
|
+
}
|
|
24057
|
+
function wrapFlueHarness(harness) {
|
|
24058
|
+
if (!isPlausibleFlueHarness(harness)) {
|
|
24059
|
+
return harness;
|
|
24060
|
+
}
|
|
24061
|
+
const target = harness;
|
|
24062
|
+
if (target[WRAPPED_FLUE_HARNESS]) {
|
|
24063
|
+
return harness;
|
|
24064
|
+
}
|
|
24065
|
+
const originalSession = target.session.bind(target);
|
|
24066
|
+
try {
|
|
24067
|
+
Object.defineProperty(target, WRAPPED_FLUE_HARNESS, {
|
|
24068
|
+
configurable: false,
|
|
24069
|
+
enumerable: false,
|
|
24070
|
+
value: true
|
|
24071
|
+
});
|
|
24072
|
+
Object.defineProperty(target, "session", {
|
|
24073
|
+
configurable: true,
|
|
24074
|
+
value: async function wrappedFlueHarnessSession(name, options) {
|
|
24075
|
+
const session = await originalSession(name, options);
|
|
24076
|
+
return patchFlueSessionInPlace(session);
|
|
24077
|
+
},
|
|
24078
|
+
writable: true
|
|
24079
|
+
});
|
|
24080
|
+
const sessions = target.sessions;
|
|
24081
|
+
if (sessions && typeof sessions === "object") {
|
|
24082
|
+
patchFlueSessionFactory(sessions, "get");
|
|
24083
|
+
patchFlueSessionFactory(sessions, "create");
|
|
24084
|
+
}
|
|
24085
|
+
} catch {
|
|
24086
|
+
}
|
|
24087
|
+
return harness;
|
|
24088
|
+
}
|
|
24089
|
+
function patchFlueSessionInPlace(session) {
|
|
24090
|
+
if (session[WRAPPED_FLUE_SESSION]) {
|
|
24091
|
+
return session;
|
|
24092
|
+
}
|
|
24093
|
+
try {
|
|
24094
|
+
Object.defineProperty(session, WRAPPED_FLUE_SESSION, {
|
|
24095
|
+
configurable: false,
|
|
24096
|
+
enumerable: false,
|
|
24097
|
+
value: true
|
|
24098
|
+
});
|
|
24099
|
+
patchCallHandleMethod(session, "prompt", flueChannels.prompt);
|
|
24100
|
+
patchCallHandleMethod(session, "skill", flueChannels.skill);
|
|
24101
|
+
patchCallHandleMethod(session, "task", flueChannels.task);
|
|
24102
|
+
patchCompact(session);
|
|
24103
|
+
} catch {
|
|
24104
|
+
}
|
|
24105
|
+
return session;
|
|
24106
|
+
}
|
|
24107
|
+
function patchFlueSessionFactory(sessions, method) {
|
|
24108
|
+
const original = sessions[method];
|
|
24109
|
+
if (typeof original !== "function") {
|
|
24110
|
+
return;
|
|
24111
|
+
}
|
|
24112
|
+
const bound = original.bind(sessions);
|
|
24113
|
+
Object.defineProperty(sessions, method, {
|
|
24114
|
+
configurable: true,
|
|
24115
|
+
value: async function wrappedFlueSessionFactory(name, options) {
|
|
24116
|
+
const session = await bound(name, options);
|
|
24117
|
+
return patchFlueSessionInPlace(session);
|
|
24118
|
+
},
|
|
24119
|
+
writable: true
|
|
24120
|
+
});
|
|
24121
|
+
}
|
|
24122
|
+
function patchCallHandleMethod(session, method, channel2) {
|
|
24123
|
+
const original = session[method];
|
|
24124
|
+
if (typeof original !== "function") {
|
|
24125
|
+
return;
|
|
24126
|
+
}
|
|
24127
|
+
const bound = original.bind(session);
|
|
24128
|
+
Object.defineProperty(session, method, {
|
|
24129
|
+
configurable: true,
|
|
24130
|
+
value(input, options) {
|
|
24131
|
+
const args = [input, options];
|
|
24132
|
+
const { originalResult, traced: traced2 } = traceFlueOperation(channel2, {
|
|
24133
|
+
context: {
|
|
24134
|
+
arguments: args,
|
|
24135
|
+
operation: method,
|
|
24136
|
+
session
|
|
24137
|
+
},
|
|
24138
|
+
run: () => bound(input, options)
|
|
24139
|
+
});
|
|
24140
|
+
return preserveCallHandle(originalResult, traced2);
|
|
24141
|
+
},
|
|
24142
|
+
writable: true
|
|
24143
|
+
});
|
|
24144
|
+
}
|
|
24145
|
+
function patchCompact(session) {
|
|
24146
|
+
const original = session.compact;
|
|
24147
|
+
if (typeof original !== "function") {
|
|
24148
|
+
return;
|
|
24149
|
+
}
|
|
24150
|
+
const bound = original.bind(session);
|
|
24151
|
+
Object.defineProperty(session, "compact", {
|
|
24152
|
+
configurable: true,
|
|
24153
|
+
value() {
|
|
24154
|
+
const context = {
|
|
24155
|
+
arguments: [],
|
|
24156
|
+
operation: "compact",
|
|
24157
|
+
session
|
|
24158
|
+
};
|
|
24159
|
+
return flueChannels.compact.tracePromise(() => bound(), context);
|
|
24160
|
+
},
|
|
24161
|
+
writable: true
|
|
24162
|
+
});
|
|
24163
|
+
}
|
|
24164
|
+
function traceFlueOperation(channel2, args) {
|
|
24165
|
+
const tracingChannel2 = channel2.tracingChannel();
|
|
24166
|
+
const context = args.context;
|
|
24167
|
+
let originalResult;
|
|
24168
|
+
let traced2;
|
|
24169
|
+
const run = () => {
|
|
24170
|
+
try {
|
|
24171
|
+
originalResult = args.run();
|
|
24172
|
+
tracingChannel2.end?.publish(context);
|
|
24173
|
+
} catch (error) {
|
|
24174
|
+
context.error = normalizeError3(error);
|
|
24175
|
+
tracingChannel2.error?.publish(context);
|
|
24176
|
+
tracingChannel2.end?.publish(context);
|
|
24177
|
+
throw error;
|
|
24178
|
+
}
|
|
24179
|
+
traced2 = Promise.resolve(originalResult).then(
|
|
24180
|
+
(result) => {
|
|
24181
|
+
context.result = result;
|
|
24182
|
+
tracingChannel2.asyncStart?.publish(context);
|
|
24183
|
+
tracingChannel2.asyncEnd?.publish(context);
|
|
24184
|
+
return result;
|
|
24185
|
+
},
|
|
24186
|
+
(error) => {
|
|
24187
|
+
context.error = normalizeError3(error);
|
|
24188
|
+
tracingChannel2.error?.publish(context);
|
|
24189
|
+
tracingChannel2.asyncStart?.publish(context);
|
|
24190
|
+
tracingChannel2.asyncEnd?.publish(context);
|
|
24191
|
+
throw error;
|
|
24192
|
+
}
|
|
24193
|
+
);
|
|
24194
|
+
};
|
|
24195
|
+
if (tracingChannel2.start?.runStores) {
|
|
24196
|
+
tracingChannel2.start.runStores(context, run);
|
|
24197
|
+
} else {
|
|
24198
|
+
tracingChannel2.start?.publish(context);
|
|
24199
|
+
run();
|
|
24200
|
+
}
|
|
24201
|
+
return { originalResult, traced: traced2 };
|
|
24202
|
+
}
|
|
24203
|
+
function normalizeError3(error) {
|
|
24204
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
24205
|
+
}
|
|
24206
|
+
function preserveCallHandle(originalHandle, traced2) {
|
|
24207
|
+
if (!isFlueCallHandle(originalHandle)) {
|
|
24208
|
+
return traced2;
|
|
24209
|
+
}
|
|
24210
|
+
const handle = originalHandle;
|
|
24211
|
+
const wrapped = {
|
|
24212
|
+
get signal() {
|
|
24213
|
+
return handle.signal;
|
|
24214
|
+
},
|
|
24215
|
+
abort(reason) {
|
|
24216
|
+
return handle.abort(reason);
|
|
24217
|
+
},
|
|
24218
|
+
then(onfulfilled, onrejected) {
|
|
24219
|
+
return traced2.then(onfulfilled, onrejected);
|
|
24220
|
+
}
|
|
24221
|
+
};
|
|
24222
|
+
return wrapped;
|
|
24223
|
+
}
|
|
24224
|
+
function isPlausibleFlueContext(value) {
|
|
24225
|
+
return !!value && typeof value === "object" && typeof value.init === "function";
|
|
24226
|
+
}
|
|
24227
|
+
function isPlausibleFlueHarness(value) {
|
|
24228
|
+
return !!value && typeof value === "object" && typeof value.session === "function";
|
|
24229
|
+
}
|
|
24230
|
+
function isPlausibleFlueSession(value) {
|
|
24231
|
+
return !!value && typeof value === "object" && typeof value.prompt === "function" && typeof value.skill === "function" && typeof value.task === "function" && typeof value.compact === "function";
|
|
24232
|
+
}
|
|
24233
|
+
function isFlueCallHandle(value) {
|
|
24234
|
+
return !!value && typeof value === "object" && typeof value.then === "function" && typeof value.abort === "function" && "signal" in value;
|
|
24235
|
+
}
|
|
24236
|
+
|
|
24237
|
+
// src/instrumentation/plugins/flue-plugin.ts
|
|
24238
|
+
var FluePlugin = class extends BasePlugin {
|
|
24239
|
+
activeOperationsById = /* @__PURE__ */ new Map();
|
|
24240
|
+
activeOperationsByScope = /* @__PURE__ */ new Map();
|
|
24241
|
+
compactionsByScope = /* @__PURE__ */ new Map();
|
|
24242
|
+
pendingOperationsByKey = /* @__PURE__ */ new Map();
|
|
24243
|
+
tasksById = /* @__PURE__ */ new Map();
|
|
24244
|
+
toolsById = /* @__PURE__ */ new Map();
|
|
24245
|
+
turnsByScope = /* @__PURE__ */ new Map();
|
|
24246
|
+
onEnable() {
|
|
24247
|
+
this.subscribeToContextCreation();
|
|
24248
|
+
this.subscribeToSessionCreation();
|
|
24249
|
+
this.subscribeToContextEvents();
|
|
24250
|
+
this.subscribeToSessionOperations();
|
|
24251
|
+
}
|
|
24252
|
+
onDisable() {
|
|
24253
|
+
for (const unsubscribe of this.unsubscribers) {
|
|
24254
|
+
unsubscribe();
|
|
24255
|
+
}
|
|
24256
|
+
this.unsubscribers = [];
|
|
24257
|
+
this.activeOperationsById.clear();
|
|
24258
|
+
this.activeOperationsByScope.clear();
|
|
24259
|
+
this.compactionsByScope.clear();
|
|
24260
|
+
this.pendingOperationsByKey.clear();
|
|
24261
|
+
this.tasksById.clear();
|
|
24262
|
+
this.toolsById.clear();
|
|
24263
|
+
this.turnsByScope.clear();
|
|
24264
|
+
}
|
|
24265
|
+
subscribeToContextCreation() {
|
|
24266
|
+
const channel2 = flueChannels.createContext.tracingChannel();
|
|
24267
|
+
const handlers = {
|
|
24268
|
+
end: (event) => {
|
|
24269
|
+
const ctx = event.result;
|
|
24270
|
+
if (!ctx) {
|
|
24271
|
+
return;
|
|
24272
|
+
}
|
|
24273
|
+
subscribeFlueContextEvents(ctx, { captureTurnSpans: false });
|
|
24274
|
+
patchFlueContextInPlace(ctx);
|
|
24275
|
+
},
|
|
24276
|
+
error: () => {
|
|
24277
|
+
}
|
|
24278
|
+
};
|
|
24279
|
+
channel2.subscribe(handlers);
|
|
24280
|
+
this.unsubscribers.push(() => {
|
|
24281
|
+
channel2.unsubscribe(handlers);
|
|
24282
|
+
});
|
|
24283
|
+
}
|
|
24284
|
+
subscribeToSessionCreation() {
|
|
24285
|
+
const channel2 = flueChannels.openSession.tracingChannel();
|
|
24286
|
+
const handlers = {
|
|
24287
|
+
asyncEnd: (event) => {
|
|
24288
|
+
if (event.result) {
|
|
24289
|
+
patchFlueSessionInPlace(
|
|
24290
|
+
event.result
|
|
24291
|
+
);
|
|
24292
|
+
}
|
|
24293
|
+
if (event.harness) {
|
|
24294
|
+
wrapFlueHarness(event.harness);
|
|
24295
|
+
}
|
|
24296
|
+
},
|
|
24297
|
+
error: () => {
|
|
24298
|
+
}
|
|
24299
|
+
};
|
|
24300
|
+
channel2.subscribe(handlers);
|
|
24301
|
+
this.unsubscribers.push(() => {
|
|
24302
|
+
channel2.unsubscribe(handlers);
|
|
24303
|
+
});
|
|
24304
|
+
}
|
|
24305
|
+
subscribeToSessionOperations() {
|
|
24306
|
+
this.subscribeToSessionOperation(flueChannels.prompt);
|
|
24307
|
+
this.subscribeToSessionOperation(flueChannels.skill);
|
|
24308
|
+
this.subscribeToSessionOperation(flueChannels.task);
|
|
24309
|
+
this.subscribeToCompact();
|
|
24310
|
+
}
|
|
24311
|
+
subscribeToSessionOperation(channel2) {
|
|
24312
|
+
const tracingChannel2 = channel2.tracingChannel();
|
|
24313
|
+
const states = /* @__PURE__ */ new WeakMap();
|
|
24314
|
+
const ensureState2 = (event) => {
|
|
24315
|
+
const existing = states.get(event);
|
|
24316
|
+
if (existing) {
|
|
24317
|
+
return existing;
|
|
24318
|
+
}
|
|
24319
|
+
const state = this.startOperationState({
|
|
24320
|
+
args: event.arguments,
|
|
24321
|
+
moduleVersion: typeof event.moduleVersion === "string" ? event.moduleVersion : void 0,
|
|
24322
|
+
operation: event.operation,
|
|
24323
|
+
session: event.session
|
|
24324
|
+
});
|
|
24325
|
+
states.set(event, state);
|
|
24326
|
+
return state;
|
|
24327
|
+
};
|
|
24328
|
+
const unbindCurrentSpanStore = this.bindCurrentSpanStoreToOperationStart(
|
|
24329
|
+
tracingChannel2,
|
|
24330
|
+
ensureState2
|
|
24331
|
+
);
|
|
24332
|
+
const handlers = {
|
|
24333
|
+
start: (event) => {
|
|
24334
|
+
ensureState2(event);
|
|
24335
|
+
},
|
|
24336
|
+
asyncEnd: (event) => {
|
|
24337
|
+
this.endOperationState(states.get(event), event.result);
|
|
24338
|
+
states.delete(event);
|
|
24339
|
+
},
|
|
24340
|
+
error: (event) => {
|
|
24341
|
+
const state = states.get(event);
|
|
24342
|
+
if (state && event.error) {
|
|
24343
|
+
safeLog3(state.span, { error: errorToString(event.error) });
|
|
24344
|
+
this.finishOperationState(state);
|
|
24345
|
+
}
|
|
24346
|
+
states.delete(event);
|
|
24347
|
+
}
|
|
24348
|
+
};
|
|
24349
|
+
tracingChannel2.subscribe(handlers);
|
|
24350
|
+
this.unsubscribers.push(() => {
|
|
24351
|
+
unbindCurrentSpanStore?.();
|
|
24352
|
+
tracingChannel2.unsubscribe(handlers);
|
|
24353
|
+
});
|
|
24354
|
+
}
|
|
24355
|
+
subscribeToCompact() {
|
|
24356
|
+
const tracingChannel2 = flueChannels.compact.tracingChannel();
|
|
24357
|
+
const states = /* @__PURE__ */ new WeakMap();
|
|
24358
|
+
const ensureState2 = (event) => {
|
|
24359
|
+
const existing = states.get(event);
|
|
24360
|
+
if (existing) {
|
|
24361
|
+
return existing;
|
|
24362
|
+
}
|
|
24363
|
+
const state = this.startOperationState({
|
|
24364
|
+
args: [],
|
|
24365
|
+
moduleVersion: typeof event.moduleVersion === "string" ? event.moduleVersion : void 0,
|
|
24366
|
+
operation: event.operation,
|
|
24367
|
+
session: event.session
|
|
24368
|
+
});
|
|
24369
|
+
states.set(event, state);
|
|
24370
|
+
return state;
|
|
24371
|
+
};
|
|
24372
|
+
const unbindCurrentSpanStore = this.bindCurrentSpanStoreToOperationStart(
|
|
24373
|
+
tracingChannel2,
|
|
24374
|
+
ensureState2
|
|
24375
|
+
);
|
|
24376
|
+
const handlers = {
|
|
24377
|
+
start: (event) => {
|
|
24378
|
+
ensureState2(event);
|
|
24379
|
+
},
|
|
24380
|
+
asyncEnd: (event) => {
|
|
24381
|
+
this.endOperationState(states.get(event), void 0);
|
|
24382
|
+
states.delete(event);
|
|
24383
|
+
},
|
|
24384
|
+
error: (event) => {
|
|
24385
|
+
const state = states.get(event);
|
|
24386
|
+
if (state && event.error) {
|
|
24387
|
+
safeLog3(state.span, { error: errorToString(event.error) });
|
|
24388
|
+
this.finishOperationState(state);
|
|
24389
|
+
}
|
|
24390
|
+
states.delete(event);
|
|
24391
|
+
}
|
|
24392
|
+
};
|
|
24393
|
+
tracingChannel2.subscribe(handlers);
|
|
24394
|
+
this.unsubscribers.push(() => {
|
|
24395
|
+
unbindCurrentSpanStore?.();
|
|
24396
|
+
tracingChannel2.unsubscribe(handlers);
|
|
24397
|
+
});
|
|
24398
|
+
}
|
|
24399
|
+
subscribeToContextEvents() {
|
|
24400
|
+
const channel2 = flueChannels.contextEvent.tracingChannel();
|
|
24401
|
+
const handlers = {
|
|
24402
|
+
start: (event) => {
|
|
24403
|
+
const flueEvent = event.arguments[0];
|
|
24404
|
+
if (!flueEvent) {
|
|
24405
|
+
return;
|
|
24406
|
+
}
|
|
24407
|
+
try {
|
|
24408
|
+
this.handleFlueEvent(flueEvent, {
|
|
24409
|
+
captureTurnSpans: event.captureTurnSpans !== false
|
|
24410
|
+
});
|
|
24411
|
+
} catch (error) {
|
|
24412
|
+
logInstrumentationError3("Flue event", error);
|
|
24413
|
+
}
|
|
24414
|
+
},
|
|
24415
|
+
error: () => {
|
|
24416
|
+
}
|
|
24417
|
+
};
|
|
24418
|
+
channel2.subscribe(handlers);
|
|
24419
|
+
this.unsubscribers.push(() => {
|
|
24420
|
+
channel2.unsubscribe(handlers);
|
|
24421
|
+
});
|
|
24422
|
+
}
|
|
24423
|
+
bindCurrentSpanStoreToOperationStart(tracingChannel2, ensureState2) {
|
|
24424
|
+
const state = _internalGetGlobalState();
|
|
24425
|
+
const startChannel = tracingChannel2.start;
|
|
24426
|
+
const contextManager = state?.contextManager;
|
|
24427
|
+
const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
|
|
24428
|
+
if (!currentSpanStore || !startChannel) {
|
|
24429
|
+
return void 0;
|
|
24430
|
+
}
|
|
24431
|
+
startChannel.bindStore(currentSpanStore, (event) => {
|
|
24432
|
+
const operationState = ensureState2(event);
|
|
24433
|
+
return contextManager.wrapSpanForStore(operationState.span);
|
|
24434
|
+
});
|
|
24435
|
+
return () => {
|
|
24436
|
+
startChannel.unbindStore(currentSpanStore);
|
|
24437
|
+
};
|
|
24438
|
+
}
|
|
24439
|
+
startOperationState(args) {
|
|
24440
|
+
const sessionName = getSessionName(args.session);
|
|
24441
|
+
const metadata = {
|
|
24442
|
+
...extractOperationInputMetadata(args.operation, args.args),
|
|
24443
|
+
...extractSessionMetadata(args.session),
|
|
24444
|
+
"flue.operation": args.operation,
|
|
24445
|
+
provider: "flue",
|
|
24446
|
+
...args.moduleVersion ? { "flue.version": args.moduleVersion } : {}
|
|
24447
|
+
};
|
|
24448
|
+
const span = startSpan({
|
|
24449
|
+
name: `flue.session.${args.operation}`,
|
|
24450
|
+
spanAttributes: { type: "task" /* TASK */ }
|
|
24451
|
+
});
|
|
24452
|
+
const state = {
|
|
24453
|
+
metadata,
|
|
24454
|
+
operation: args.operation,
|
|
24455
|
+
sessionName,
|
|
24456
|
+
span,
|
|
24457
|
+
startTime: getCurrentUnixTimestamp()
|
|
24458
|
+
};
|
|
24459
|
+
safeLog3(span, {
|
|
24460
|
+
input: extractOperationInput(args.operation, args.args),
|
|
24461
|
+
metadata
|
|
24462
|
+
});
|
|
24463
|
+
this.pendingOperationQueue(operationKey(sessionName, args.operation)).push(
|
|
24464
|
+
state
|
|
24465
|
+
);
|
|
24466
|
+
addOperationToScope(
|
|
24467
|
+
this.activeOperationsByScope,
|
|
24468
|
+
sessionName ?? "unknown",
|
|
24469
|
+
state
|
|
24470
|
+
);
|
|
24471
|
+
return state;
|
|
24472
|
+
}
|
|
24473
|
+
endOperationState(state, result) {
|
|
24474
|
+
if (!state) {
|
|
24475
|
+
return;
|
|
24476
|
+
}
|
|
24477
|
+
const metadata = {
|
|
24478
|
+
...state.metadata,
|
|
24479
|
+
...extractPromptResponseMetadata(result)
|
|
24480
|
+
};
|
|
24481
|
+
const metrics = {
|
|
24482
|
+
...buildDurationMetrics3(state.startTime),
|
|
24483
|
+
...metricsFromUsage(result?.usage)
|
|
24484
|
+
};
|
|
24485
|
+
safeLog3(state.span, {
|
|
24486
|
+
metadata,
|
|
24487
|
+
metrics,
|
|
24488
|
+
output: extractOperationOutput(result)
|
|
24489
|
+
});
|
|
24490
|
+
this.finishCompactionsForOperation(state);
|
|
24491
|
+
this.finishOperationState(state);
|
|
24492
|
+
}
|
|
24493
|
+
finishOperationState(state) {
|
|
24494
|
+
removePendingOperation(this.pendingOperationsByKey, state);
|
|
24495
|
+
if (state.operationId) {
|
|
24496
|
+
this.activeOperationsById.delete(state.operationId);
|
|
24497
|
+
}
|
|
24498
|
+
removeScopedOperation(this.activeOperationsByScope, state);
|
|
24499
|
+
state.span.end();
|
|
24500
|
+
}
|
|
24501
|
+
handleFlueEvent(event, options) {
|
|
24502
|
+
switch (event.type) {
|
|
24503
|
+
case "operation_start":
|
|
24504
|
+
this.handleOperationStart(event);
|
|
24505
|
+
return;
|
|
24506
|
+
case "operation":
|
|
24507
|
+
this.handleOperation(event);
|
|
24508
|
+
return;
|
|
24509
|
+
case "text_delta":
|
|
24510
|
+
if (!options.captureTurnSpans) {
|
|
24511
|
+
return;
|
|
24512
|
+
}
|
|
24513
|
+
this.ensureTurnState(event).text.push(
|
|
24514
|
+
typeof event.text === "string" ? event.text : ""
|
|
24515
|
+
);
|
|
24516
|
+
return;
|
|
24517
|
+
case "thinking_start":
|
|
24518
|
+
if (!options.captureTurnSpans) {
|
|
24519
|
+
return;
|
|
24520
|
+
}
|
|
24521
|
+
this.handleThinkingStart(event);
|
|
24522
|
+
return;
|
|
24523
|
+
case "thinking_delta":
|
|
24524
|
+
if (!options.captureTurnSpans) {
|
|
24525
|
+
return;
|
|
24526
|
+
}
|
|
24527
|
+
this.handleThinkingDelta(event);
|
|
24528
|
+
return;
|
|
24529
|
+
case "thinking_end":
|
|
24530
|
+
if (!options.captureTurnSpans) {
|
|
24531
|
+
return;
|
|
24532
|
+
}
|
|
24533
|
+
this.handleThinkingEnd(event);
|
|
24534
|
+
return;
|
|
24535
|
+
case "turn":
|
|
24536
|
+
if (!options.captureTurnSpans) {
|
|
24537
|
+
return;
|
|
24538
|
+
}
|
|
24539
|
+
this.handleTurn(event);
|
|
24540
|
+
return;
|
|
24541
|
+
case "tool_start":
|
|
24542
|
+
this.handleToolStart(event, options);
|
|
24543
|
+
return;
|
|
24544
|
+
case "tool_call":
|
|
24545
|
+
this.handleToolCall(event);
|
|
24546
|
+
return;
|
|
24547
|
+
case "task_start":
|
|
24548
|
+
this.handleTaskStart(event);
|
|
24549
|
+
return;
|
|
24550
|
+
case "task":
|
|
24551
|
+
this.handleTask(event);
|
|
24552
|
+
return;
|
|
24553
|
+
case "compaction_start":
|
|
24554
|
+
this.handleCompactionStart(event);
|
|
24555
|
+
return;
|
|
24556
|
+
case "compaction":
|
|
24557
|
+
this.handleCompaction(event);
|
|
24558
|
+
return;
|
|
24559
|
+
default:
|
|
24560
|
+
return;
|
|
24561
|
+
}
|
|
24562
|
+
}
|
|
24563
|
+
handleOperationStart(event) {
|
|
24564
|
+
if (!isInstrumentedOperation(event.operationKind)) {
|
|
24565
|
+
return;
|
|
24566
|
+
}
|
|
24567
|
+
const state = this.takePendingOperationForEvent(event);
|
|
24568
|
+
if (!state) {
|
|
24569
|
+
return;
|
|
24570
|
+
}
|
|
24571
|
+
state.operationId = event.operationId;
|
|
24572
|
+
this.activeOperationsById.set(event.operationId, state);
|
|
24573
|
+
addScopedOperation(this.activeOperationsByScope, event, state);
|
|
24574
|
+
state.metadata = {
|
|
24575
|
+
...state.metadata,
|
|
24576
|
+
...extractEventMetadata(event),
|
|
24577
|
+
"flue.operation_id": event.operationId
|
|
24578
|
+
};
|
|
24579
|
+
safeLog3(state.span, { metadata: state.metadata });
|
|
24580
|
+
}
|
|
24581
|
+
handleOperation(event) {
|
|
24582
|
+
const state = event.operationId ? this.activeOperationsById.get(event.operationId) : void 0;
|
|
24583
|
+
if (!state) {
|
|
24584
|
+
return;
|
|
24585
|
+
}
|
|
24586
|
+
const metadata = {
|
|
24587
|
+
...state.metadata,
|
|
24588
|
+
...extractEventMetadata(event),
|
|
24589
|
+
...typeof event.durationMs === "number" ? { "flue.duration_ms": event.durationMs } : {},
|
|
24590
|
+
...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
|
|
24591
|
+
};
|
|
24592
|
+
const metrics = metricsFromUsage(event.usage);
|
|
24593
|
+
safeLog3(state.span, {
|
|
24594
|
+
...event.error ? { error: errorToString(event.error) } : {},
|
|
24595
|
+
metadata,
|
|
24596
|
+
...Object.keys(metrics).length ? { metrics } : {}
|
|
24597
|
+
});
|
|
24598
|
+
}
|
|
24599
|
+
ensureTurnState(event) {
|
|
24600
|
+
const scope = scopeKey(event);
|
|
24601
|
+
const existing = this.turnsByScope.get(scope);
|
|
24602
|
+
if (existing) {
|
|
24603
|
+
return existing;
|
|
24604
|
+
}
|
|
24605
|
+
const parent = this.parentSpanForEvent(event);
|
|
24606
|
+
const metadata = {
|
|
24607
|
+
...extractEventMetadata(event),
|
|
24608
|
+
provider: "flue"
|
|
24609
|
+
};
|
|
24610
|
+
const span = startFlueSpan(parent, {
|
|
24611
|
+
name: "flue.turn",
|
|
24612
|
+
spanAttributes: { type: "llm" /* LLM */ }
|
|
24613
|
+
});
|
|
24614
|
+
const state = {
|
|
24615
|
+
metadata,
|
|
24616
|
+
span,
|
|
24617
|
+
hasThinking: false,
|
|
24618
|
+
startTime: getCurrentUnixTimestamp(),
|
|
24619
|
+
text: [],
|
|
24620
|
+
thinking: [],
|
|
24621
|
+
toolCalls: []
|
|
24622
|
+
};
|
|
24623
|
+
safeLog3(span, { metadata });
|
|
24624
|
+
this.turnsByScope.set(scope, state);
|
|
24625
|
+
return state;
|
|
24626
|
+
}
|
|
24627
|
+
handleTurn(event) {
|
|
24628
|
+
const scope = scopeKey(event);
|
|
24629
|
+
const state = this.ensureTurnState(event);
|
|
24630
|
+
const text = state.text.join("");
|
|
24631
|
+
const reasoning = state.finalThinking ?? state.thinking.join("");
|
|
24632
|
+
const outputReasoning = reasoning || (state.hasThinking ? "[reasoning stream present; content unavailable]" : void 0);
|
|
24633
|
+
const metadata = {
|
|
24634
|
+
...state.metadata,
|
|
24635
|
+
...extractEventMetadata(event),
|
|
24636
|
+
...event.model ? { model: event.model, "flue.model": event.model } : {},
|
|
24637
|
+
...event.stopReason ? { "flue.stop_reason": event.stopReason } : {},
|
|
24638
|
+
...event.isError !== void 0 ? { "flue.is_error": event.isError } : {},
|
|
24639
|
+
provider: "flue"
|
|
24640
|
+
};
|
|
24641
|
+
safeLog3(state.span, {
|
|
24642
|
+
...event.error ? { error: errorToString(event.error) } : {},
|
|
24643
|
+
metadata,
|
|
24644
|
+
metrics: {
|
|
24645
|
+
...durationMsMetrics(event.durationMs),
|
|
24646
|
+
...metricsFromUsage(event.usage)
|
|
24647
|
+
},
|
|
24648
|
+
output: toAssistantOutput(
|
|
24649
|
+
text,
|
|
24650
|
+
event.stopReason,
|
|
24651
|
+
outputReasoning,
|
|
24652
|
+
state.toolCalls
|
|
24653
|
+
)
|
|
24654
|
+
});
|
|
24655
|
+
state.span.end();
|
|
24656
|
+
this.turnsByScope.delete(scope);
|
|
24657
|
+
}
|
|
24658
|
+
handleThinkingDelta(event) {
|
|
24659
|
+
const delta = event.delta;
|
|
24660
|
+
if (typeof delta !== "string" || !delta) {
|
|
24661
|
+
return;
|
|
24662
|
+
}
|
|
24663
|
+
const state = this.ensureTurnState(event);
|
|
24664
|
+
state.hasThinking = true;
|
|
24665
|
+
state.metadata["flue.thinking"] = true;
|
|
24666
|
+
state.thinking.push(delta);
|
|
24667
|
+
}
|
|
24668
|
+
handleThinkingStart(event) {
|
|
24669
|
+
const state = this.ensureTurnState(event);
|
|
24670
|
+
state.hasThinking = true;
|
|
24671
|
+
state.metadata["flue.thinking"] = true;
|
|
24672
|
+
}
|
|
24673
|
+
handleThinkingEnd(event) {
|
|
24674
|
+
const state = this.ensureTurnState(event);
|
|
24675
|
+
state.hasThinking = true;
|
|
24676
|
+
state.metadata["flue.thinking"] = true;
|
|
24677
|
+
if (typeof event.content === "string" && event.content) {
|
|
24678
|
+
state.finalThinking = event.content;
|
|
24679
|
+
}
|
|
24680
|
+
}
|
|
24681
|
+
handleToolStart(event, options) {
|
|
24682
|
+
const toolCallId = event.toolCallId;
|
|
24683
|
+
if (!toolCallId) {
|
|
24684
|
+
return;
|
|
24685
|
+
}
|
|
24686
|
+
const parent = this.parentSpanForEvent(event);
|
|
24687
|
+
const scope = scopeKey(event);
|
|
24688
|
+
let turnState = this.turnsByScope.get(scope);
|
|
24689
|
+
if (!turnState && parent && options.captureTurnSpans) {
|
|
24690
|
+
turnState = this.ensureTurnState(event);
|
|
24691
|
+
}
|
|
24692
|
+
const metadata = {
|
|
24693
|
+
...extractEventMetadata(event),
|
|
24694
|
+
...event.toolName ? { "flue.tool_name": event.toolName } : {},
|
|
24695
|
+
"flue.tool_call_id": toolCallId,
|
|
24696
|
+
provider: "flue"
|
|
24697
|
+
};
|
|
24698
|
+
const span = startFlueSpan(parent, {
|
|
24699
|
+
name: `tool: ${event.toolName ?? "unknown"}`,
|
|
24700
|
+
spanAttributes: { type: "tool" /* TOOL */ }
|
|
24701
|
+
});
|
|
24702
|
+
if (turnState) {
|
|
24703
|
+
turnState.toolCalls.push({
|
|
24704
|
+
args: event.args,
|
|
24705
|
+
toolCallId,
|
|
24706
|
+
toolName: event.toolName
|
|
24707
|
+
});
|
|
24708
|
+
}
|
|
24709
|
+
safeLog3(span, {
|
|
24710
|
+
input: event.args,
|
|
24711
|
+
metadata
|
|
24712
|
+
});
|
|
24713
|
+
this.toolsById.set(toolKey(event), {
|
|
24714
|
+
metadata,
|
|
24715
|
+
span,
|
|
24716
|
+
startTime: getCurrentUnixTimestamp()
|
|
24717
|
+
});
|
|
24718
|
+
}
|
|
24719
|
+
handleToolCall(event) {
|
|
24720
|
+
const key = toolKey(event);
|
|
24721
|
+
const state = this.toolsById.get(key) ?? this.startSyntheticToolState(event, event.toolName ?? "unknown");
|
|
24722
|
+
const metadata = {
|
|
24723
|
+
...state.metadata,
|
|
24724
|
+
...extractEventMetadata(event),
|
|
24725
|
+
...event.toolName ? { "flue.tool_name": event.toolName } : {},
|
|
24726
|
+
...event.toolCallId ? { "flue.tool_call_id": event.toolCallId } : {},
|
|
24727
|
+
...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
|
|
24728
|
+
};
|
|
24729
|
+
safeLog3(state.span, {
|
|
24730
|
+
...event.isError ? { error: errorToString(event.result) } : {},
|
|
24731
|
+
metadata,
|
|
24732
|
+
metrics: durationMsMetrics(event.durationMs),
|
|
24733
|
+
output: event.result
|
|
24734
|
+
});
|
|
24735
|
+
state.span.end();
|
|
24736
|
+
this.toolsById.delete(key);
|
|
24737
|
+
}
|
|
24738
|
+
handleTaskStart(event) {
|
|
24739
|
+
const parent = this.parentSpanForEvent(event);
|
|
24740
|
+
const metadata = {
|
|
24741
|
+
...extractEventMetadata(event),
|
|
24742
|
+
...event.role ? { "flue.role": event.role } : {},
|
|
24743
|
+
...event.cwd ? { "flue.cwd": event.cwd } : {},
|
|
24744
|
+
"flue.task_id": event.taskId,
|
|
24745
|
+
provider: "flue"
|
|
24746
|
+
};
|
|
24747
|
+
const span = startFlueSpan(parent, {
|
|
24748
|
+
name: "flue.task",
|
|
24749
|
+
spanAttributes: { type: "task" /* TASK */ }
|
|
24750
|
+
});
|
|
24751
|
+
safeLog3(span, {
|
|
24752
|
+
input: event.prompt,
|
|
24753
|
+
metadata
|
|
24754
|
+
});
|
|
24755
|
+
this.tasksById.set(event.taskId, {
|
|
24756
|
+
metadata,
|
|
24757
|
+
span,
|
|
24758
|
+
startTime: getCurrentUnixTimestamp()
|
|
24759
|
+
});
|
|
24760
|
+
}
|
|
24761
|
+
handleTask(event) {
|
|
24762
|
+
const state = this.tasksById.get(event.taskId);
|
|
24763
|
+
if (!state) {
|
|
24764
|
+
return;
|
|
24765
|
+
}
|
|
24766
|
+
safeLog3(state.span, {
|
|
24767
|
+
...event.isError ? { error: errorToString(event.result) } : {},
|
|
24768
|
+
metadata: {
|
|
24769
|
+
...state.metadata,
|
|
24770
|
+
...extractEventMetadata(event),
|
|
24771
|
+
...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
|
|
24772
|
+
},
|
|
24773
|
+
metrics: durationMsMetrics(event.durationMs),
|
|
24774
|
+
output: event.result
|
|
24775
|
+
});
|
|
24776
|
+
state.span.end();
|
|
24777
|
+
this.tasksById.delete(event.taskId);
|
|
24778
|
+
}
|
|
24779
|
+
handleCompactionStart(event) {
|
|
24780
|
+
const operationState = this.operationStateForEvent(event);
|
|
24781
|
+
const parent = operationState?.span ?? this.parentSpanForEvent(event);
|
|
24782
|
+
const metadata = {
|
|
24783
|
+
...extractEventMetadata(event),
|
|
24784
|
+
...event.reason ? { "flue.compaction_reason": event.reason } : {},
|
|
24785
|
+
provider: "flue"
|
|
24786
|
+
};
|
|
24787
|
+
const input = {
|
|
24788
|
+
...typeof event.estimatedTokens === "number" ? { estimatedTokens: event.estimatedTokens } : {},
|
|
24789
|
+
...event.reason ? { reason: event.reason } : {}
|
|
24790
|
+
};
|
|
24791
|
+
const span = startFlueSpan(parent, {
|
|
24792
|
+
name: "flue.compaction",
|
|
24793
|
+
spanAttributes: { type: "task" /* TASK */ }
|
|
24794
|
+
});
|
|
24795
|
+
safeLog3(span, {
|
|
24796
|
+
input,
|
|
24797
|
+
metadata
|
|
24798
|
+
});
|
|
24799
|
+
this.compactionsByScope.set(scopeKey(event), {
|
|
24800
|
+
input,
|
|
24801
|
+
metadata,
|
|
24802
|
+
operationState,
|
|
24803
|
+
span,
|
|
24804
|
+
startTime: getCurrentUnixTimestamp()
|
|
24805
|
+
});
|
|
24806
|
+
}
|
|
24807
|
+
handleCompaction(event) {
|
|
24808
|
+
const key = scopeKey(event);
|
|
24809
|
+
const state = this.compactionsByScope.get(key) ?? this.findCompactionState(event);
|
|
24810
|
+
if (!state) {
|
|
24811
|
+
return;
|
|
24812
|
+
}
|
|
24813
|
+
safeLog3(state.span, {
|
|
24814
|
+
metadata: {
|
|
24815
|
+
...state.metadata,
|
|
24816
|
+
...extractEventMetadata(event),
|
|
24817
|
+
...typeof event.messagesBefore === "number" ? { "flue.messages_before": event.messagesBefore } : {},
|
|
24818
|
+
...typeof event.messagesAfter === "number" ? { "flue.messages_after": event.messagesAfter } : {}
|
|
24819
|
+
},
|
|
24820
|
+
metrics: {
|
|
24821
|
+
...durationMsMetrics(event.durationMs),
|
|
24822
|
+
...metricsFromUsage(event.usage)
|
|
24823
|
+
},
|
|
24824
|
+
output: {
|
|
24825
|
+
messagesAfter: event.messagesAfter,
|
|
24826
|
+
messagesBefore: event.messagesBefore
|
|
24827
|
+
}
|
|
24828
|
+
});
|
|
24829
|
+
state.span.end();
|
|
24830
|
+
this.deleteCompactionState(state);
|
|
24831
|
+
}
|
|
24832
|
+
findCompactionState(event) {
|
|
24833
|
+
const operationState = this.operationStateForEvent(event);
|
|
24834
|
+
for (const state of this.compactionsByScope.values()) {
|
|
24835
|
+
if (operationState && state.operationState === operationState) {
|
|
24836
|
+
return state;
|
|
24837
|
+
}
|
|
24838
|
+
}
|
|
24839
|
+
return void 0;
|
|
24840
|
+
}
|
|
24841
|
+
finishCompactionsForOperation(operationState) {
|
|
24842
|
+
for (const state of [...this.compactionsByScope.values()]) {
|
|
24843
|
+
if (state.operationState !== operationState) {
|
|
24844
|
+
continue;
|
|
24845
|
+
}
|
|
24846
|
+
safeLog3(state.span, {
|
|
24847
|
+
input: state.input,
|
|
24848
|
+
metadata: state.metadata,
|
|
24849
|
+
metrics: {
|
|
24850
|
+
...buildDurationMetrics3(state.startTime)
|
|
24851
|
+
},
|
|
24852
|
+
output: { completed: true }
|
|
24853
|
+
});
|
|
24854
|
+
state.span.end();
|
|
24855
|
+
this.deleteCompactionState(state);
|
|
24856
|
+
}
|
|
24857
|
+
}
|
|
24858
|
+
deleteCompactionState(state) {
|
|
24859
|
+
for (const [key, candidate] of this.compactionsByScope) {
|
|
24860
|
+
if (candidate !== state) {
|
|
24861
|
+
continue;
|
|
24862
|
+
}
|
|
24863
|
+
this.compactionsByScope.delete(key);
|
|
24864
|
+
return;
|
|
24865
|
+
}
|
|
24866
|
+
}
|
|
24867
|
+
startSyntheticToolState(event, toolName) {
|
|
24868
|
+
const parent = this.parentSpanForEvent(event);
|
|
24869
|
+
const metadata = {
|
|
24870
|
+
...extractEventMetadata(event),
|
|
24871
|
+
...event.toolCallId ? { "flue.tool_call_id": event.toolCallId } : {},
|
|
24872
|
+
"flue.tool_name": toolName,
|
|
24873
|
+
provider: "flue"
|
|
24874
|
+
};
|
|
24875
|
+
const span = startFlueSpan(parent, {
|
|
24876
|
+
name: `tool: ${toolName}`,
|
|
24877
|
+
spanAttributes: { type: "tool" /* TOOL */ }
|
|
24878
|
+
});
|
|
24879
|
+
safeLog3(span, { metadata });
|
|
24880
|
+
return { metadata, span, startTime: getCurrentUnixTimestamp() };
|
|
24881
|
+
}
|
|
24882
|
+
operationStateForEvent(event) {
|
|
24883
|
+
if (event.operationId) {
|
|
24884
|
+
const operation = this.activeOperationsById.get(event.operationId) ?? this.promotePendingOperationForEvent(event);
|
|
24885
|
+
if (operation) {
|
|
24886
|
+
return operation;
|
|
24887
|
+
}
|
|
24888
|
+
}
|
|
24889
|
+
return this.activeOperationForEventScope(event) ?? this.pendingOperationForEventScope(event);
|
|
24890
|
+
}
|
|
24891
|
+
parentSpanForEvent(event) {
|
|
24892
|
+
if (event.operationId) {
|
|
24893
|
+
const operation = this.operationStateForEvent(event);
|
|
24894
|
+
if (operation) {
|
|
24895
|
+
return operation.span;
|
|
24896
|
+
}
|
|
24897
|
+
}
|
|
24898
|
+
if (event.taskId) {
|
|
24899
|
+
return this.tasksById.get(event.taskId)?.span;
|
|
24900
|
+
}
|
|
24901
|
+
return this.operationStateForEvent(event)?.span;
|
|
24902
|
+
}
|
|
24903
|
+
promotePendingOperationForEvent(event) {
|
|
24904
|
+
if (!event.operationId) {
|
|
24905
|
+
return void 0;
|
|
24906
|
+
}
|
|
24907
|
+
const scopePrefixes = operationScopePrefixes(event);
|
|
24908
|
+
for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
|
|
24909
|
+
if (!candidateQueue.length || !operationKeyMatchesScopes(candidateKey, scopePrefixes)) {
|
|
24910
|
+
continue;
|
|
24911
|
+
}
|
|
24912
|
+
const state = candidateQueue.shift();
|
|
24913
|
+
if (!state) {
|
|
24914
|
+
return void 0;
|
|
24915
|
+
}
|
|
24916
|
+
state.operationId = event.operationId;
|
|
24917
|
+
this.activeOperationsById.set(event.operationId, state);
|
|
24918
|
+
addScopedOperation(this.activeOperationsByScope, event, state);
|
|
24919
|
+
state.metadata = {
|
|
24920
|
+
...state.metadata,
|
|
24921
|
+
...extractEventMetadata(event),
|
|
24922
|
+
"flue.operation_id": event.operationId
|
|
24923
|
+
};
|
|
24924
|
+
safeLog3(state.span, { metadata: state.metadata });
|
|
24925
|
+
return state;
|
|
24926
|
+
}
|
|
24927
|
+
return void 0;
|
|
24928
|
+
}
|
|
24929
|
+
activeOperationForEventScope(event) {
|
|
24930
|
+
for (const scope of operationScopeNames(event)) {
|
|
24931
|
+
const operations = this.activeOperationsByScope.get(scope);
|
|
24932
|
+
if (operations?.length) {
|
|
24933
|
+
return operations[operations.length - 1];
|
|
24934
|
+
}
|
|
24935
|
+
}
|
|
24936
|
+
return void 0;
|
|
24937
|
+
}
|
|
24938
|
+
pendingOperationForEventScope(event) {
|
|
24939
|
+
const scopePrefixes = operationScopePrefixes(event);
|
|
24940
|
+
for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
|
|
24941
|
+
if (!candidateQueue.length || !operationKeyMatchesScopes(candidateKey, scopePrefixes)) {
|
|
24942
|
+
continue;
|
|
24943
|
+
}
|
|
24944
|
+
return candidateQueue[0];
|
|
24945
|
+
}
|
|
24946
|
+
return void 0;
|
|
24947
|
+
}
|
|
24948
|
+
takePendingOperationForEvent(event) {
|
|
24949
|
+
const key = operationKey(event.session, event.operationKind);
|
|
24950
|
+
const queue2 = this.pendingOperationsByKey.get(key);
|
|
24951
|
+
if (queue2?.length) {
|
|
24952
|
+
return queue2.shift();
|
|
24953
|
+
}
|
|
24954
|
+
for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
|
|
24955
|
+
if (candidateKey.endsWith(`::${event.operationKind}`) && candidateQueue.length) {
|
|
24956
|
+
return candidateQueue.shift();
|
|
24957
|
+
}
|
|
24958
|
+
}
|
|
24959
|
+
return void 0;
|
|
24960
|
+
}
|
|
24961
|
+
pendingOperationQueue(key) {
|
|
24962
|
+
const existing = this.pendingOperationsByKey.get(key);
|
|
24963
|
+
if (existing) {
|
|
24964
|
+
return existing;
|
|
24965
|
+
}
|
|
24966
|
+
const queue2 = [];
|
|
24967
|
+
this.pendingOperationsByKey.set(key, queue2);
|
|
24968
|
+
return queue2;
|
|
24969
|
+
}
|
|
24970
|
+
};
|
|
24971
|
+
function isInstrumentedOperation(operation) {
|
|
24972
|
+
return operation === "prompt" || operation === "skill" || operation === "task" || operation === "compact";
|
|
24973
|
+
}
|
|
24974
|
+
function getSessionName(session) {
|
|
24975
|
+
return typeof session?.name === "string" ? session.name : void 0;
|
|
24976
|
+
}
|
|
24977
|
+
function operationKey(sessionName, operation) {
|
|
24978
|
+
return `${sessionName ?? "unknown"}::${operation}`;
|
|
24979
|
+
}
|
|
24980
|
+
function operationScopePrefixes(event) {
|
|
24981
|
+
const scopes = /* @__PURE__ */ new Set();
|
|
24982
|
+
for (const scope of operationScopeNames(event)) {
|
|
24983
|
+
scopes.add(`${scope}::`);
|
|
24984
|
+
}
|
|
24985
|
+
return scopes;
|
|
24986
|
+
}
|
|
24987
|
+
function operationKeyMatchesScopes(key, scopes) {
|
|
24988
|
+
for (const scope of scopes) {
|
|
24989
|
+
if (key.startsWith(scope)) {
|
|
24990
|
+
return true;
|
|
24991
|
+
}
|
|
24992
|
+
}
|
|
24993
|
+
return false;
|
|
24994
|
+
}
|
|
24995
|
+
function operationScopeNames(event) {
|
|
24996
|
+
const scopes = /* @__PURE__ */ new Set();
|
|
24997
|
+
if (event.session) {
|
|
24998
|
+
scopes.add(event.session);
|
|
24999
|
+
}
|
|
25000
|
+
if (event.parentSession) {
|
|
25001
|
+
scopes.add(event.parentSession);
|
|
25002
|
+
}
|
|
25003
|
+
if (!scopes.size) {
|
|
25004
|
+
scopes.add("unknown");
|
|
25005
|
+
}
|
|
25006
|
+
return scopes;
|
|
25007
|
+
}
|
|
25008
|
+
function addScopedOperation(operationsByScope, event, state) {
|
|
25009
|
+
for (const scope of operationScopeNames(event)) {
|
|
25010
|
+
addOperationToScope(operationsByScope, scope, state);
|
|
25011
|
+
}
|
|
25012
|
+
}
|
|
25013
|
+
function addOperationToScope(operationsByScope, scope, state) {
|
|
25014
|
+
const operations = operationsByScope.get(scope);
|
|
25015
|
+
if (operations) {
|
|
25016
|
+
if (!operations.includes(state)) {
|
|
25017
|
+
operations.push(state);
|
|
25018
|
+
}
|
|
25019
|
+
} else {
|
|
25020
|
+
operationsByScope.set(scope, [state]);
|
|
25021
|
+
}
|
|
25022
|
+
}
|
|
25023
|
+
function removeScopedOperation(operationsByScope, state) {
|
|
25024
|
+
for (const [scope, operations] of operationsByScope) {
|
|
25025
|
+
const index = operations.indexOf(state);
|
|
25026
|
+
if (index === -1) {
|
|
25027
|
+
continue;
|
|
25028
|
+
}
|
|
25029
|
+
operations.splice(index, 1);
|
|
25030
|
+
if (operations.length === 0) {
|
|
25031
|
+
operationsByScope.delete(scope);
|
|
25032
|
+
}
|
|
25033
|
+
}
|
|
25034
|
+
}
|
|
25035
|
+
function removePendingOperation(pendingOperationsByKey, state) {
|
|
25036
|
+
for (const [key, queue2] of pendingOperationsByKey) {
|
|
25037
|
+
const index = queue2.indexOf(state);
|
|
25038
|
+
if (index === -1) {
|
|
25039
|
+
continue;
|
|
25040
|
+
}
|
|
25041
|
+
queue2.splice(index, 1);
|
|
25042
|
+
if (queue2.length === 0) {
|
|
25043
|
+
pendingOperationsByKey.delete(key);
|
|
25044
|
+
}
|
|
25045
|
+
return;
|
|
25046
|
+
}
|
|
25047
|
+
}
|
|
25048
|
+
function extractSessionMetadata(session) {
|
|
25049
|
+
const sessionName = getSessionName(session);
|
|
25050
|
+
return sessionName ? { "flue.session": sessionName } : {};
|
|
25051
|
+
}
|
|
25052
|
+
function extractEventMetadata(event) {
|
|
25053
|
+
return {
|
|
25054
|
+
...event.runId ? { "flue.run_id": event.runId } : {},
|
|
25055
|
+
...typeof event.eventIndex === "number" ? { "flue.event_index": event.eventIndex } : {},
|
|
25056
|
+
...event.session ? { "flue.session": event.session } : {},
|
|
25057
|
+
...event.parentSession ? { "flue.parent_session": event.parentSession } : {},
|
|
25058
|
+
...event.harness ? { "flue.harness": event.harness } : {},
|
|
25059
|
+
...event.taskId ? { "flue.task_id": event.taskId } : {},
|
|
25060
|
+
...event.operationId ? { "flue.operation_id": event.operationId } : {}
|
|
25061
|
+
};
|
|
25062
|
+
}
|
|
25063
|
+
function extractOperationInput(operation, args) {
|
|
25064
|
+
switch (operation) {
|
|
25065
|
+
case "prompt":
|
|
25066
|
+
case "task":
|
|
25067
|
+
return args[0];
|
|
25068
|
+
case "skill":
|
|
25069
|
+
return {
|
|
25070
|
+
args: getOptionObject(args[1])?.args,
|
|
25071
|
+
name: args[0]
|
|
25072
|
+
};
|
|
25073
|
+
case "compact":
|
|
25074
|
+
return void 0;
|
|
25075
|
+
}
|
|
25076
|
+
}
|
|
25077
|
+
function extractOperationInputMetadata(operation, args) {
|
|
25078
|
+
const options = getOptionObject(args[1]);
|
|
25079
|
+
return {
|
|
25080
|
+
...operation === "skill" && typeof args[0] === "string" ? { "flue.skill_name": args[0] } : {},
|
|
25081
|
+
...options?.model ? { model: options.model, "flue.model": options.model } : {},
|
|
25082
|
+
...options?.role ? { "flue.role": options.role } : {},
|
|
25083
|
+
...options?.thinkingLevel ? { "flue.thinking_level": options.thinkingLevel } : {},
|
|
25084
|
+
...typeof options?.cwd === "string" ? { "flue.cwd": options.cwd } : {},
|
|
25085
|
+
...Array.isArray(options?.tools) ? {
|
|
25086
|
+
"flue.tools_count": options.tools.length,
|
|
25087
|
+
tools: summarizeTools(options.tools)
|
|
25088
|
+
} : {},
|
|
25089
|
+
...Array.isArray(options?.images) ? { "flue.images_count": options.images.length } : {},
|
|
25090
|
+
...options?.result || options?.schema ? { "flue.result_schema": true } : {}
|
|
25091
|
+
};
|
|
25092
|
+
}
|
|
25093
|
+
function getOptionObject(value) {
|
|
25094
|
+
return isObject(value) ? value : void 0;
|
|
25095
|
+
}
|
|
25096
|
+
function summarizeTools(tools) {
|
|
25097
|
+
return tools.flatMap((tool) => {
|
|
25098
|
+
if (!isObject(tool)) {
|
|
25099
|
+
return [];
|
|
25100
|
+
}
|
|
25101
|
+
const name = typeof tool.name === "string" ? tool.name : void 0;
|
|
25102
|
+
if (!name) {
|
|
25103
|
+
return [];
|
|
25104
|
+
}
|
|
25105
|
+
return [
|
|
25106
|
+
{
|
|
25107
|
+
function: {
|
|
25108
|
+
description: typeof tool.description === "string" ? tool.description : void 0,
|
|
25109
|
+
name,
|
|
25110
|
+
parameters: tool.parameters
|
|
25111
|
+
},
|
|
25112
|
+
type: "function"
|
|
25113
|
+
}
|
|
25114
|
+
];
|
|
25115
|
+
});
|
|
25116
|
+
}
|
|
25117
|
+
function extractPromptResponseMetadata(result) {
|
|
25118
|
+
const modelId = result?.model && typeof result.model.id === "string" ? result.model.id : void 0;
|
|
25119
|
+
return modelId ? {
|
|
25120
|
+
model: modelId,
|
|
25121
|
+
"flue.model": modelId
|
|
25122
|
+
} : {};
|
|
25123
|
+
}
|
|
25124
|
+
function extractOperationOutput(result) {
|
|
25125
|
+
if (!result) {
|
|
25126
|
+
return void 0;
|
|
25127
|
+
}
|
|
25128
|
+
if ("data" in result) {
|
|
25129
|
+
return result.data;
|
|
25130
|
+
}
|
|
25131
|
+
if ("text" in result) {
|
|
25132
|
+
return result.text;
|
|
25133
|
+
}
|
|
25134
|
+
return result;
|
|
25135
|
+
}
|
|
25136
|
+
function metricsFromUsage(usage) {
|
|
25137
|
+
return {
|
|
25138
|
+
...typeof usage?.input === "number" ? { prompt_tokens: usage.input } : {},
|
|
25139
|
+
...typeof usage?.output === "number" ? { completion_tokens: usage.output } : {},
|
|
25140
|
+
...typeof usage?.cacheRead === "number" ? { prompt_cached_tokens: usage.cacheRead } : {},
|
|
25141
|
+
...typeof usage?.cacheWrite === "number" ? { prompt_cache_creation_tokens: usage.cacheWrite } : {},
|
|
25142
|
+
...typeof usage?.totalTokens === "number" ? { tokens: usage.totalTokens } : {},
|
|
25143
|
+
...typeof usage?.cost?.total === "number" ? { estimated_cost: usage.cost.total } : {}
|
|
25144
|
+
};
|
|
25145
|
+
}
|
|
25146
|
+
function buildDurationMetrics3(startTime) {
|
|
25147
|
+
return {
|
|
25148
|
+
duration_ms: Math.max(0, (getCurrentUnixTimestamp() - startTime) * 1e3)
|
|
25149
|
+
};
|
|
25150
|
+
}
|
|
25151
|
+
function durationMsMetrics(durationMs) {
|
|
25152
|
+
return typeof durationMs === "number" ? { duration_ms: durationMs } : {};
|
|
25153
|
+
}
|
|
25154
|
+
function scopeKey(event) {
|
|
25155
|
+
if (event.operationId) {
|
|
25156
|
+
return `operation:${event.operationId}`;
|
|
25157
|
+
}
|
|
25158
|
+
if (event.taskId) {
|
|
25159
|
+
return `task:${event.taskId}`;
|
|
25160
|
+
}
|
|
25161
|
+
if (event.session) {
|
|
25162
|
+
return `session:${event.session}`;
|
|
25163
|
+
}
|
|
25164
|
+
return "flue:unknown";
|
|
25165
|
+
}
|
|
25166
|
+
function toolKey(event) {
|
|
25167
|
+
return `${scopeKey(event)}::tool:${event.toolCallId ?? "unknown"}`;
|
|
25168
|
+
}
|
|
25169
|
+
function toAssistantOutput(text, finishReason, reasoning, toolCalls) {
|
|
25170
|
+
return [
|
|
25171
|
+
{
|
|
25172
|
+
finish_reason: finishReason ?? "stop",
|
|
25173
|
+
index: 0,
|
|
25174
|
+
message: {
|
|
25175
|
+
content: text,
|
|
25176
|
+
...reasoning ? { reasoning } : {},
|
|
25177
|
+
role: "assistant",
|
|
25178
|
+
...toolCalls?.length ? {
|
|
25179
|
+
tool_calls: toolCalls.map((toolCall) => ({
|
|
25180
|
+
function: {
|
|
25181
|
+
arguments: toolCall.args === void 0 ? "{}" : JSON.stringify(toolCall.args),
|
|
25182
|
+
name: toolCall.toolName ?? "unknown"
|
|
25183
|
+
},
|
|
25184
|
+
...toolCall.toolCallId ? { id: toolCall.toolCallId } : {},
|
|
25185
|
+
type: "function"
|
|
25186
|
+
}))
|
|
25187
|
+
} : {}
|
|
25188
|
+
}
|
|
25189
|
+
}
|
|
25190
|
+
];
|
|
25191
|
+
}
|
|
25192
|
+
function startFlueSpan(parent, args) {
|
|
25193
|
+
return parent ? withCurrent(parent, () => startSpan(args)) : startSpan(args);
|
|
25194
|
+
}
|
|
25195
|
+
function safeLog3(span, event) {
|
|
25196
|
+
try {
|
|
25197
|
+
span.log(event);
|
|
25198
|
+
} catch (error) {
|
|
25199
|
+
logInstrumentationError3("Flue span log", error);
|
|
25200
|
+
}
|
|
25201
|
+
}
|
|
25202
|
+
function errorToString(error) {
|
|
25203
|
+
if (error instanceof Error) {
|
|
25204
|
+
return error.message;
|
|
25205
|
+
}
|
|
25206
|
+
if (typeof error === "string") {
|
|
25207
|
+
return error;
|
|
25208
|
+
}
|
|
25209
|
+
try {
|
|
25210
|
+
return JSON.stringify(error);
|
|
25211
|
+
} catch {
|
|
25212
|
+
return String(error);
|
|
25213
|
+
}
|
|
25214
|
+
}
|
|
25215
|
+
function logInstrumentationError3(label, error) {
|
|
25216
|
+
console.error(`Error in ${label} instrumentation:`, error);
|
|
25217
|
+
}
|
|
25218
|
+
|
|
25219
|
+
// src/wrappers/langchain/callback-handler.ts
|
|
25220
|
+
var BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME = "BraintrustCallbackHandler";
|
|
25221
|
+
var BraintrustLangChainCallbackHandler = class {
|
|
25222
|
+
name = BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
|
|
25223
|
+
spans = /* @__PURE__ */ new Map();
|
|
25224
|
+
skippedRuns = /* @__PURE__ */ new Set();
|
|
25225
|
+
parent;
|
|
25226
|
+
rootRunId;
|
|
25227
|
+
options;
|
|
25228
|
+
startTimes = /* @__PURE__ */ new Map();
|
|
25229
|
+
firstTokenTimes = /* @__PURE__ */ new Map();
|
|
25230
|
+
ttftMs = /* @__PURE__ */ new Map();
|
|
25231
|
+
constructor(options) {
|
|
25232
|
+
this.parent = options?.parent;
|
|
25233
|
+
this.options = {
|
|
25234
|
+
debug: options?.debug ?? false,
|
|
25235
|
+
excludeMetadataProps: options?.excludeMetadataProps ?? /^(l[sc]_|langgraph_|__pregel_|checkpoint_ns)/,
|
|
25236
|
+
logger: options?.logger
|
|
25237
|
+
};
|
|
25238
|
+
}
|
|
25239
|
+
startSpan({
|
|
25240
|
+
runId,
|
|
25241
|
+
parentRunId,
|
|
25242
|
+
...args
|
|
25243
|
+
}) {
|
|
25244
|
+
if (this.spans.has(runId)) {
|
|
25245
|
+
return;
|
|
25246
|
+
}
|
|
25247
|
+
if (!parentRunId) {
|
|
25248
|
+
this.rootRunId = runId;
|
|
25249
|
+
}
|
|
25250
|
+
const tags = args.event?.tags;
|
|
25251
|
+
const spanAttributes = args.spanAttributes || {};
|
|
25252
|
+
spanAttributes.type = args.type || spanAttributes.type || "task";
|
|
25253
|
+
args.type = spanAttributes.type;
|
|
25254
|
+
const currentParent = (typeof this.parent === "function" ? this.parent() : this.parent) ?? currentSpan();
|
|
25255
|
+
let parentSpan;
|
|
25256
|
+
if (parentRunId && this.spans.has(parentRunId)) {
|
|
25257
|
+
parentSpan = this.spans.get(parentRunId);
|
|
25258
|
+
} else if (!Object.is(currentParent, NOOP_SPAN)) {
|
|
25259
|
+
parentSpan = currentParent;
|
|
25260
|
+
} else if (this.options.logger) {
|
|
25261
|
+
parentSpan = this.options.logger;
|
|
25262
|
+
} else {
|
|
25263
|
+
parentSpan = { startSpan };
|
|
25264
|
+
}
|
|
25265
|
+
args.event = {
|
|
25266
|
+
...args.event,
|
|
25267
|
+
tags: void 0,
|
|
25268
|
+
metadata: {
|
|
25269
|
+
...tags ? { tags } : {},
|
|
25270
|
+
...args.event?.metadata,
|
|
25271
|
+
braintrust: {
|
|
25272
|
+
integration_name: "langchain-js",
|
|
25273
|
+
sdk_language: "javascript"
|
|
25274
|
+
},
|
|
25275
|
+
run_id: runId,
|
|
25276
|
+
parent_run_id: parentRunId,
|
|
25277
|
+
...this.options.debug ? { runId, parentRunId } : {}
|
|
25278
|
+
}
|
|
25279
|
+
};
|
|
25280
|
+
let span = parentSpan.startSpan(args);
|
|
25281
|
+
if (!Object.is(this.options.logger, NOOP_SPAN) && Object.is(span, NOOP_SPAN)) {
|
|
25282
|
+
span = initLogger().startSpan(args);
|
|
25283
|
+
}
|
|
25284
|
+
this.spans.set(runId, span);
|
|
25285
|
+
}
|
|
25286
|
+
endSpan({
|
|
25287
|
+
runId,
|
|
25288
|
+
parentRunId,
|
|
25289
|
+
tags,
|
|
25290
|
+
metadata,
|
|
25291
|
+
...args
|
|
25292
|
+
}) {
|
|
25293
|
+
if (!this.spans.has(runId)) {
|
|
25294
|
+
return;
|
|
25295
|
+
}
|
|
25296
|
+
if (this.skippedRuns.has(runId)) {
|
|
25297
|
+
this.skippedRuns.delete(runId);
|
|
25298
|
+
return;
|
|
25299
|
+
}
|
|
25300
|
+
const span = this.spans.get(runId);
|
|
25301
|
+
this.spans.delete(runId);
|
|
25302
|
+
if (runId === this.rootRunId) {
|
|
25303
|
+
this.rootRunId = void 0;
|
|
25304
|
+
}
|
|
25305
|
+
span.log({ ...args, metadata: { tags, ...metadata } });
|
|
25306
|
+
span.end();
|
|
25307
|
+
}
|
|
25308
|
+
async handleLLMStart(llm, prompts, runId, parentRunId, extraParams, tags, metadata, runName) {
|
|
25309
|
+
this.startSpan({
|
|
25310
|
+
runId,
|
|
25311
|
+
parentRunId,
|
|
25312
|
+
name: runName ?? getSerializedName(llm) ?? "LLM",
|
|
25313
|
+
type: "llm",
|
|
25314
|
+
event: {
|
|
25315
|
+
input: prompts,
|
|
25316
|
+
tags,
|
|
25317
|
+
metadata: {
|
|
25318
|
+
serialized: llm,
|
|
25319
|
+
name: runName,
|
|
25320
|
+
metadata,
|
|
25321
|
+
...extraParams
|
|
25322
|
+
}
|
|
25323
|
+
}
|
|
25324
|
+
});
|
|
25325
|
+
}
|
|
25326
|
+
async handleLLMError(err, runId, parentRunId, tags) {
|
|
25327
|
+
this.endSpan({ runId, parentRunId, error: err, tags });
|
|
25328
|
+
}
|
|
25329
|
+
async handleLLMEnd(output, runId, parentRunId, tags) {
|
|
25330
|
+
const metrics = getMetricsFromResponse(output);
|
|
25331
|
+
const modelName2 = getModelNameFromResponse(output);
|
|
25332
|
+
const ttft = this.ttftMs.get(runId);
|
|
25333
|
+
if (ttft !== void 0) {
|
|
25334
|
+
metrics.time_to_first_token = ttft;
|
|
25335
|
+
}
|
|
25336
|
+
this.startTimes.delete(runId);
|
|
25337
|
+
this.firstTokenTimes.delete(runId);
|
|
25338
|
+
this.ttftMs.delete(runId);
|
|
25339
|
+
this.endSpan({
|
|
25340
|
+
runId,
|
|
25341
|
+
parentRunId,
|
|
25342
|
+
output,
|
|
25343
|
+
metrics,
|
|
25344
|
+
tags,
|
|
25345
|
+
metadata: {
|
|
25346
|
+
model: modelName2
|
|
25347
|
+
}
|
|
25348
|
+
});
|
|
25349
|
+
}
|
|
25350
|
+
async handleChatModelStart(llm, messages, runId, parentRunId, extraParams, tags, metadata, runName) {
|
|
25351
|
+
this.startTimes.set(runId, Date.now());
|
|
25352
|
+
this.firstTokenTimes.delete(runId);
|
|
25353
|
+
this.ttftMs.delete(runId);
|
|
25354
|
+
this.startSpan({
|
|
25355
|
+
runId,
|
|
25356
|
+
parentRunId,
|
|
25357
|
+
name: runName ?? getSerializedName(llm) ?? "Chat Model",
|
|
25358
|
+
type: "llm",
|
|
25359
|
+
event: {
|
|
25360
|
+
input: messages,
|
|
25361
|
+
tags,
|
|
25362
|
+
metadata: {
|
|
25363
|
+
serialized: llm,
|
|
25364
|
+
name: runName,
|
|
25365
|
+
metadata,
|
|
25366
|
+
...extraParams
|
|
25367
|
+
}
|
|
25368
|
+
}
|
|
25369
|
+
});
|
|
25370
|
+
}
|
|
25371
|
+
async handleChainStart(chain, inputs, runId, parentRunId, tags, metadata, runType, runName) {
|
|
25372
|
+
if (tags?.includes("langsmith:hidden")) {
|
|
25373
|
+
this.skippedRuns.add(runId);
|
|
25374
|
+
return;
|
|
25375
|
+
}
|
|
25376
|
+
this.startSpan({
|
|
25377
|
+
runId,
|
|
25378
|
+
parentRunId,
|
|
25379
|
+
name: runName ?? getSerializedName(chain) ?? "Chain",
|
|
25380
|
+
event: {
|
|
25381
|
+
input: inputs,
|
|
25382
|
+
tags,
|
|
25383
|
+
metadata: {
|
|
25384
|
+
serialized: chain,
|
|
25385
|
+
name: runName,
|
|
25386
|
+
metadata,
|
|
25387
|
+
run_type: runType
|
|
25388
|
+
}
|
|
25389
|
+
}
|
|
25390
|
+
});
|
|
25391
|
+
}
|
|
25392
|
+
async handleChainError(err, runId, parentRunId, tags, kwargs) {
|
|
25393
|
+
this.endSpan({ runId, parentRunId, error: err, tags, metadata: kwargs });
|
|
25394
|
+
}
|
|
25395
|
+
async handleChainEnd(outputs, runId, parentRunId, tags, kwargs) {
|
|
25396
|
+
this.endSpan({
|
|
25397
|
+
runId,
|
|
25398
|
+
parentRunId,
|
|
25399
|
+
tags,
|
|
25400
|
+
output: outputs,
|
|
25401
|
+
metadata: { ...kwargs }
|
|
25402
|
+
});
|
|
25403
|
+
}
|
|
25404
|
+
async handleToolStart(tool, input, runId, parentRunId, tags, metadata, runName) {
|
|
25405
|
+
this.startSpan({
|
|
25406
|
+
runId,
|
|
25407
|
+
parentRunId,
|
|
25408
|
+
name: runName ?? getSerializedName(tool) ?? "Tool",
|
|
25409
|
+
type: "llm",
|
|
25410
|
+
event: {
|
|
25411
|
+
input: safeJsonParse(input),
|
|
25412
|
+
tags,
|
|
25413
|
+
metadata: {
|
|
25414
|
+
metadata,
|
|
25415
|
+
serialized: tool,
|
|
25416
|
+
input_str: input,
|
|
25417
|
+
input: safeJsonParse(input),
|
|
25418
|
+
name: runName
|
|
25419
|
+
}
|
|
25420
|
+
}
|
|
25421
|
+
});
|
|
25422
|
+
}
|
|
25423
|
+
async handleToolError(err, runId, parentRunId, tags) {
|
|
25424
|
+
this.endSpan({ runId, parentRunId, error: err, tags });
|
|
25425
|
+
}
|
|
25426
|
+
async handleToolEnd(output, runId, parentRunId, tags) {
|
|
25427
|
+
this.endSpan({ runId, parentRunId, output, tags });
|
|
25428
|
+
}
|
|
25429
|
+
async handleAgentAction(action, runId, parentRunId, tags) {
|
|
25430
|
+
this.startSpan({
|
|
25431
|
+
runId,
|
|
25432
|
+
parentRunId,
|
|
25433
|
+
type: "llm",
|
|
25434
|
+
name: typeof action.tool === "string" ? action.tool : "Agent",
|
|
25435
|
+
event: {
|
|
25436
|
+
input: action,
|
|
25437
|
+
tags
|
|
25438
|
+
}
|
|
25439
|
+
});
|
|
25440
|
+
}
|
|
25441
|
+
async handleAgentEnd(action, runId, parentRunId, tags) {
|
|
25442
|
+
this.endSpan({ runId, parentRunId, output: action, tags });
|
|
25443
|
+
}
|
|
25444
|
+
async handleRetrieverStart(retriever, query, runId, parentRunId, tags, metadata, name) {
|
|
25445
|
+
this.startSpan({
|
|
25446
|
+
runId,
|
|
25447
|
+
parentRunId,
|
|
25448
|
+
name: name ?? getSerializedName(retriever) ?? "Retriever",
|
|
25449
|
+
type: "function",
|
|
25450
|
+
event: {
|
|
25451
|
+
input: query,
|
|
25452
|
+
tags,
|
|
25453
|
+
metadata: {
|
|
25454
|
+
serialized: retriever,
|
|
25455
|
+
metadata,
|
|
25456
|
+
name
|
|
25457
|
+
}
|
|
25458
|
+
}
|
|
25459
|
+
});
|
|
25460
|
+
}
|
|
25461
|
+
async handleRetrieverEnd(documents, runId, parentRunId, tags) {
|
|
25462
|
+
this.endSpan({ runId, parentRunId, output: documents, tags });
|
|
25463
|
+
}
|
|
25464
|
+
async handleRetrieverError(err, runId, parentRunId, tags) {
|
|
25465
|
+
this.endSpan({ runId, parentRunId, error: err, tags });
|
|
25466
|
+
}
|
|
25467
|
+
async handleLLMNewToken(_token, _idx, runId, _parentRunId, _tags) {
|
|
25468
|
+
if (!this.firstTokenTimes.has(runId)) {
|
|
25469
|
+
const now2 = Date.now();
|
|
25470
|
+
this.firstTokenTimes.set(runId, now2);
|
|
25471
|
+
const start = this.startTimes.get(runId);
|
|
25472
|
+
if (start !== void 0) {
|
|
25473
|
+
this.ttftMs.set(runId, (now2 - start) / 1e3);
|
|
25474
|
+
}
|
|
25475
|
+
}
|
|
25476
|
+
}
|
|
25477
|
+
};
|
|
25478
|
+
function getSerializedName(serialized) {
|
|
25479
|
+
if (typeof serialized.name === "string") {
|
|
25480
|
+
return serialized.name;
|
|
25481
|
+
}
|
|
25482
|
+
const lastIdPart = serialized.id?.at(-1);
|
|
25483
|
+
return typeof lastIdPart === "string" ? lastIdPart : void 0;
|
|
25484
|
+
}
|
|
25485
|
+
function cleanObject(obj) {
|
|
25486
|
+
return Object.fromEntries(
|
|
25487
|
+
Object.entries(obj).filter(([, value]) => {
|
|
25488
|
+
if (typeof value !== "number") {
|
|
25489
|
+
return false;
|
|
25490
|
+
}
|
|
25491
|
+
return Number.isFinite(value);
|
|
25492
|
+
})
|
|
25493
|
+
);
|
|
25494
|
+
}
|
|
25495
|
+
function walkGenerations(response) {
|
|
25496
|
+
const result = [];
|
|
25497
|
+
const generations = response.generations || [];
|
|
25498
|
+
for (const batch of generations) {
|
|
25499
|
+
if (Array.isArray(batch)) {
|
|
25500
|
+
for (const generation of batch) {
|
|
25501
|
+
if (isRecord(generation)) {
|
|
25502
|
+
result.push(generation);
|
|
25503
|
+
}
|
|
25504
|
+
}
|
|
25505
|
+
} else if (isRecord(batch)) {
|
|
25506
|
+
result.push(batch);
|
|
25507
|
+
}
|
|
25508
|
+
}
|
|
25509
|
+
return result;
|
|
25510
|
+
}
|
|
25511
|
+
function getModelNameFromResponse(response) {
|
|
25512
|
+
for (const generation of walkGenerations(response)) {
|
|
25513
|
+
const message = generation.message;
|
|
25514
|
+
if (!isRecord(message)) {
|
|
25515
|
+
continue;
|
|
25516
|
+
}
|
|
25517
|
+
const responseMetadata = message.response_metadata;
|
|
25518
|
+
if (!isRecord(responseMetadata)) {
|
|
25519
|
+
continue;
|
|
25520
|
+
}
|
|
25521
|
+
const modelName3 = responseMetadata.model_name ?? responseMetadata.model;
|
|
25522
|
+
if (typeof modelName3 === "string") {
|
|
25523
|
+
return modelName3;
|
|
25524
|
+
}
|
|
25525
|
+
}
|
|
25526
|
+
const llmOutput = response.llmOutput || {};
|
|
25527
|
+
const modelName2 = llmOutput.model_name ?? llmOutput.model;
|
|
25528
|
+
return typeof modelName2 === "string" ? modelName2 : void 0;
|
|
25529
|
+
}
|
|
25530
|
+
function getMetricsFromResponse(response) {
|
|
25531
|
+
for (const generation of walkGenerations(response)) {
|
|
25532
|
+
const message = generation.message;
|
|
25533
|
+
if (!isRecord(message)) {
|
|
25534
|
+
continue;
|
|
25535
|
+
}
|
|
25536
|
+
const usageMetadata = message.usage_metadata;
|
|
25537
|
+
if (!isRecord(usageMetadata)) {
|
|
25538
|
+
continue;
|
|
25539
|
+
}
|
|
25540
|
+
const inputTokenDetails = usageMetadata.input_token_details;
|
|
25541
|
+
return cleanObject({
|
|
25542
|
+
total_tokens: usageMetadata.total_tokens,
|
|
25543
|
+
prompt_tokens: usageMetadata.input_tokens,
|
|
25544
|
+
completion_tokens: usageMetadata.output_tokens,
|
|
25545
|
+
prompt_cache_creation_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_creation : void 0,
|
|
25546
|
+
prompt_cached_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_read : void 0
|
|
25547
|
+
});
|
|
25548
|
+
}
|
|
25549
|
+
const llmOutput = response.llmOutput || {};
|
|
25550
|
+
const tokenUsage = isRecord(llmOutput.tokenUsage) ? llmOutput.tokenUsage : isRecord(llmOutput.estimatedTokens) ? llmOutput.estimatedTokens : {};
|
|
25551
|
+
return cleanObject({
|
|
25552
|
+
total_tokens: tokenUsage.totalTokens,
|
|
25553
|
+
prompt_tokens: tokenUsage.promptTokens,
|
|
25554
|
+
completion_tokens: tokenUsage.completionTokens
|
|
25555
|
+
});
|
|
25556
|
+
}
|
|
25557
|
+
function safeJsonParse(input) {
|
|
25558
|
+
try {
|
|
25559
|
+
return JSON.parse(input);
|
|
25560
|
+
} catch {
|
|
25561
|
+
return input;
|
|
25562
|
+
}
|
|
25563
|
+
}
|
|
25564
|
+
function isRecord(value) {
|
|
25565
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
25566
|
+
}
|
|
25567
|
+
|
|
25568
|
+
// src/instrumentation/plugins/langchain-channels.ts
|
|
25569
|
+
var langChainChannels = defineChannels("@langchain/core", {
|
|
25570
|
+
configure: channel({
|
|
25571
|
+
channelName: "CallbackManager.configure",
|
|
25572
|
+
kind: "sync-stream"
|
|
25573
|
+
}),
|
|
25574
|
+
configureSync: channel({
|
|
25575
|
+
channelName: "CallbackManager._configureSync",
|
|
25576
|
+
kind: "sync-stream"
|
|
25577
|
+
})
|
|
25578
|
+
});
|
|
25579
|
+
|
|
25580
|
+
// src/instrumentation/plugins/langchain-plugin.ts
|
|
25581
|
+
var LangChainPlugin = class extends BasePlugin {
|
|
25582
|
+
injectedManagers = /* @__PURE__ */ new WeakSet();
|
|
25583
|
+
onEnable() {
|
|
25584
|
+
this.subscribeToConfigure(langChainChannels.configure);
|
|
25585
|
+
this.subscribeToConfigure(langChainChannels.configureSync);
|
|
25586
|
+
}
|
|
25587
|
+
onDisable() {
|
|
25588
|
+
for (const unsubscribe of this.unsubscribers) {
|
|
25589
|
+
unsubscribe();
|
|
25590
|
+
}
|
|
25591
|
+
this.unsubscribers = [];
|
|
25592
|
+
this.injectedManagers = /* @__PURE__ */ new WeakSet();
|
|
25593
|
+
}
|
|
25594
|
+
subscribeToConfigure(channel2) {
|
|
25595
|
+
const tracingChannel2 = channel2.tracingChannel();
|
|
25596
|
+
const handlers = {
|
|
25597
|
+
start: (event) => {
|
|
25598
|
+
injectHandlerIntoArguments(event.arguments);
|
|
25599
|
+
},
|
|
25600
|
+
end: (event) => {
|
|
25601
|
+
this.injectHandler(event.result);
|
|
25602
|
+
}
|
|
25603
|
+
};
|
|
25604
|
+
tracingChannel2.subscribe(handlers);
|
|
25605
|
+
this.unsubscribers.push(() => {
|
|
25606
|
+
tracingChannel2.unsubscribe(handlers);
|
|
25607
|
+
});
|
|
25608
|
+
}
|
|
25609
|
+
injectHandler(result) {
|
|
25610
|
+
if (!isCallbackManager(result)) {
|
|
25611
|
+
return;
|
|
25612
|
+
}
|
|
25613
|
+
if (this.injectedManagers.has(result) || hasBraintrustHandler(result)) {
|
|
25614
|
+
return;
|
|
25615
|
+
}
|
|
25616
|
+
try {
|
|
25617
|
+
result.addHandler(new BraintrustLangChainCallbackHandler(), true);
|
|
25618
|
+
this.injectedManagers.add(result);
|
|
25619
|
+
} catch {
|
|
25620
|
+
}
|
|
25621
|
+
}
|
|
25622
|
+
};
|
|
25623
|
+
function isCallbackManager(value) {
|
|
25624
|
+
if (typeof value !== "object" || value === null) {
|
|
25625
|
+
return false;
|
|
25626
|
+
}
|
|
25627
|
+
const maybeManager = value;
|
|
25628
|
+
return typeof maybeManager.addHandler === "function";
|
|
25629
|
+
}
|
|
25630
|
+
function hasBraintrustHandler(manager) {
|
|
25631
|
+
return manager.handlers?.some((handler) => {
|
|
25632
|
+
if (typeof handler !== "object" || handler === null) {
|
|
25633
|
+
return false;
|
|
25634
|
+
}
|
|
25635
|
+
const name = Reflect.get(handler, "name");
|
|
25636
|
+
return name === BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
|
|
25637
|
+
}) ?? false;
|
|
25638
|
+
}
|
|
25639
|
+
function injectHandlerIntoArguments(args) {
|
|
25640
|
+
if (!isWritableArgumentsObject(args)) {
|
|
25641
|
+
return;
|
|
25642
|
+
}
|
|
25643
|
+
const inheritedHandlers = Reflect.get(args, "0");
|
|
25644
|
+
const handler = new BraintrustLangChainCallbackHandler();
|
|
25645
|
+
if (inheritedHandlers === void 0 || inheritedHandlers === null) {
|
|
25646
|
+
Reflect.set(args, "0", [handler]);
|
|
25647
|
+
return;
|
|
25648
|
+
}
|
|
25649
|
+
if (Array.isArray(inheritedHandlers)) {
|
|
25650
|
+
if (!inheritedHandlers.some(isBraintrustHandler)) {
|
|
25651
|
+
inheritedHandlers.push(handler);
|
|
25652
|
+
}
|
|
25653
|
+
}
|
|
25654
|
+
}
|
|
25655
|
+
function isWritableArgumentsObject(args) {
|
|
25656
|
+
return typeof args === "object" && args !== null;
|
|
25657
|
+
}
|
|
25658
|
+
function isBraintrustHandler(handler) {
|
|
25659
|
+
if (typeof handler !== "object" || handler === null) {
|
|
25660
|
+
return false;
|
|
25661
|
+
}
|
|
25662
|
+
return Reflect.get(handler, "name") === BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
|
|
25663
|
+
}
|
|
25664
|
+
|
|
25665
|
+
// src/instrumentation/braintrust-plugin.ts
|
|
25666
|
+
function getIntegrationConfig(integrations, key) {
|
|
25667
|
+
return integrations[key];
|
|
25668
|
+
}
|
|
25669
|
+
var BraintrustPlugin = class extends BasePlugin {
|
|
25670
|
+
config;
|
|
25671
|
+
openaiPlugin = null;
|
|
25672
|
+
openAICodexPlugin = null;
|
|
25673
|
+
anthropicPlugin = null;
|
|
25674
|
+
aiSDKPlugin = null;
|
|
25675
|
+
claudeAgentSDKPlugin = null;
|
|
25676
|
+
cursorSDKPlugin = null;
|
|
25677
|
+
openAIAgentsPlugin = null;
|
|
25678
|
+
googleGenAIPlugin = null;
|
|
25679
|
+
huggingFacePlugin = null;
|
|
25680
|
+
openRouterPlugin = null;
|
|
25681
|
+
openRouterAgentPlugin = null;
|
|
25682
|
+
mistralPlugin = null;
|
|
25683
|
+
googleADKPlugin = null;
|
|
25684
|
+
coherePlugin = null;
|
|
25685
|
+
groqPlugin = null;
|
|
25686
|
+
genkitPlugin = null;
|
|
25687
|
+
gitHubCopilotPlugin = null;
|
|
25688
|
+
fluePlugin = null;
|
|
25689
|
+
langChainPlugin = null;
|
|
25690
|
+
constructor(config = {}) {
|
|
25691
|
+
super();
|
|
25692
|
+
this.config = config;
|
|
25693
|
+
}
|
|
25694
|
+
onEnable() {
|
|
25695
|
+
const integrations = this.config.integrations || {};
|
|
25696
|
+
if (integrations.openai !== false) {
|
|
25697
|
+
this.openaiPlugin = new OpenAIPlugin();
|
|
25698
|
+
this.openaiPlugin.enable();
|
|
25699
|
+
}
|
|
25700
|
+
if (integrations.openaiCodexSDK !== false) {
|
|
25701
|
+
this.openAICodexPlugin = new OpenAICodexPlugin();
|
|
25702
|
+
this.openAICodexPlugin.enable();
|
|
23516
25703
|
}
|
|
23517
25704
|
if (integrations.anthropic !== false) {
|
|
23518
25705
|
this.anthropicPlugin = new AnthropicPlugin();
|
|
@@ -23530,6 +25717,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
23530
25717
|
this.cursorSDKPlugin = new CursorSDKPlugin();
|
|
23531
25718
|
this.cursorSDKPlugin.enable();
|
|
23532
25719
|
}
|
|
25720
|
+
if (integrations.openAIAgents !== false) {
|
|
25721
|
+
this.openAIAgentsPlugin = new OpenAIAgentsPlugin();
|
|
25722
|
+
this.openAIAgentsPlugin.enable();
|
|
25723
|
+
}
|
|
23533
25724
|
if (integrations.googleGenAI !== false && integrations.google !== false) {
|
|
23534
25725
|
this.googleGenAIPlugin = new GoogleGenAIPlugin();
|
|
23535
25726
|
this.googleGenAIPlugin.enable();
|
|
@@ -23570,6 +25761,14 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
23570
25761
|
this.gitHubCopilotPlugin = new GitHubCopilotPlugin();
|
|
23571
25762
|
this.gitHubCopilotPlugin.enable();
|
|
23572
25763
|
}
|
|
25764
|
+
if (getIntegrationConfig(integrations, "flue") !== false) {
|
|
25765
|
+
this.fluePlugin = new FluePlugin();
|
|
25766
|
+
this.fluePlugin.enable();
|
|
25767
|
+
}
|
|
25768
|
+
if (integrations.langchain !== false && integrations.langgraph !== false) {
|
|
25769
|
+
this.langChainPlugin = new LangChainPlugin();
|
|
25770
|
+
this.langChainPlugin.enable();
|
|
25771
|
+
}
|
|
23573
25772
|
}
|
|
23574
25773
|
onDisable() {
|
|
23575
25774
|
if (this.openaiPlugin) {
|
|
@@ -23596,6 +25795,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
23596
25795
|
this.cursorSDKPlugin.disable();
|
|
23597
25796
|
this.cursorSDKPlugin = null;
|
|
23598
25797
|
}
|
|
25798
|
+
if (this.openAIAgentsPlugin) {
|
|
25799
|
+
this.openAIAgentsPlugin.disable();
|
|
25800
|
+
this.openAIAgentsPlugin = null;
|
|
25801
|
+
}
|
|
23599
25802
|
if (this.googleGenAIPlugin) {
|
|
23600
25803
|
this.googleGenAIPlugin.disable();
|
|
23601
25804
|
this.googleGenAIPlugin = null;
|
|
@@ -23636,9 +25839,104 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
23636
25839
|
this.gitHubCopilotPlugin.disable();
|
|
23637
25840
|
this.gitHubCopilotPlugin = null;
|
|
23638
25841
|
}
|
|
25842
|
+
if (this.fluePlugin) {
|
|
25843
|
+
this.fluePlugin.disable();
|
|
25844
|
+
this.fluePlugin = null;
|
|
25845
|
+
}
|
|
25846
|
+
if (this.langChainPlugin) {
|
|
25847
|
+
this.langChainPlugin.disable();
|
|
25848
|
+
this.langChainPlugin = null;
|
|
25849
|
+
}
|
|
23639
25850
|
}
|
|
23640
25851
|
};
|
|
23641
25852
|
|
|
25853
|
+
// src/instrumentation/config.ts
|
|
25854
|
+
var envIntegrationAliases = {
|
|
25855
|
+
openai: "openai",
|
|
25856
|
+
"openai-codex": "openaiCodexSDK",
|
|
25857
|
+
"openai-codex-sdk": "openaiCodexSDK",
|
|
25858
|
+
openaicodexsdk: "openaiCodexSDK",
|
|
25859
|
+
codex: "openaiCodexSDK",
|
|
25860
|
+
"codex-sdk": "openaiCodexSDK",
|
|
25861
|
+
anthropic: "anthropic",
|
|
25862
|
+
aisdk: "aisdk",
|
|
25863
|
+
"ai-sdk": "aisdk",
|
|
25864
|
+
"vercel-ai": "aisdk",
|
|
25865
|
+
vercel: "vercel",
|
|
25866
|
+
claudeagentsdk: "claudeAgentSDK",
|
|
25867
|
+
"claude-agent-sdk": "claudeAgentSDK",
|
|
25868
|
+
cursor: "cursor",
|
|
25869
|
+
"cursor-sdk": "cursorSDK",
|
|
25870
|
+
cursorsdk: "cursorSDK",
|
|
25871
|
+
flue: "flue",
|
|
25872
|
+
"flue-runtime": "flue",
|
|
25873
|
+
"openai-agents": "openAIAgents",
|
|
25874
|
+
openaiagents: "openAIAgents",
|
|
25875
|
+
"openai-agents-core": "openAIAgents",
|
|
25876
|
+
openaiagentscore: "openAIAgents",
|
|
25877
|
+
google: "google",
|
|
25878
|
+
"google-genai": "googleGenAI",
|
|
25879
|
+
googlegenai: "googleGenAI",
|
|
25880
|
+
huggingface: "huggingface",
|
|
25881
|
+
openrouter: "openrouter",
|
|
25882
|
+
openrouteragent: "openrouterAgent",
|
|
25883
|
+
"openrouter-agent": "openrouterAgent",
|
|
25884
|
+
mistral: "mistral",
|
|
25885
|
+
googleadk: "googleADK",
|
|
25886
|
+
"google-adk": "googleADK",
|
|
25887
|
+
cohere: "cohere",
|
|
25888
|
+
groq: "groq",
|
|
25889
|
+
"groq-sdk": "groq",
|
|
25890
|
+
genkit: "genkit",
|
|
25891
|
+
"firebase-genkit": "genkit",
|
|
25892
|
+
githubcopilot: "gitHubCopilot",
|
|
25893
|
+
"github-copilot": "gitHubCopilot",
|
|
25894
|
+
"copilot-sdk": "gitHubCopilot",
|
|
25895
|
+
langchain: "langchain",
|
|
25896
|
+
"langchain-js": "langchain",
|
|
25897
|
+
"@langchain": "langchain",
|
|
25898
|
+
langgraph: "langgraph"
|
|
25899
|
+
};
|
|
25900
|
+
function getDefaultInstrumentationIntegrations() {
|
|
25901
|
+
return {
|
|
25902
|
+
openai: true,
|
|
25903
|
+
openaiCodexSDK: true,
|
|
25904
|
+
anthropic: true,
|
|
25905
|
+
vercel: true,
|
|
25906
|
+
aisdk: true,
|
|
25907
|
+
google: true,
|
|
25908
|
+
googleGenAI: true,
|
|
25909
|
+
googleADK: true,
|
|
25910
|
+
huggingface: true,
|
|
25911
|
+
claudeAgentSDK: true,
|
|
25912
|
+
cursor: true,
|
|
25913
|
+
cursorSDK: true,
|
|
25914
|
+
flue: true,
|
|
25915
|
+
openAIAgents: true,
|
|
25916
|
+
openrouter: true,
|
|
25917
|
+
openrouterAgent: true,
|
|
25918
|
+
mistral: true,
|
|
25919
|
+
cohere: true,
|
|
25920
|
+
groq: true,
|
|
25921
|
+
genkit: true,
|
|
25922
|
+
gitHubCopilot: true,
|
|
25923
|
+
langchain: true,
|
|
25924
|
+
langgraph: true
|
|
25925
|
+
};
|
|
25926
|
+
}
|
|
25927
|
+
function readDisabledInstrumentationEnvConfig(disabledList) {
|
|
25928
|
+
const integrations = {};
|
|
25929
|
+
if (disabledList) {
|
|
25930
|
+
for (const value of disabledList.split(",")) {
|
|
25931
|
+
const sdk = value.trim().toLowerCase();
|
|
25932
|
+
if (sdk.length > 0) {
|
|
25933
|
+
integrations[envIntegrationAliases[sdk] ?? sdk] = false;
|
|
25934
|
+
}
|
|
25935
|
+
}
|
|
25936
|
+
}
|
|
25937
|
+
return { integrations };
|
|
25938
|
+
}
|
|
25939
|
+
|
|
23642
25940
|
// src/instrumentation/registry.ts
|
|
23643
25941
|
var REGISTRY_STATE_KEY = /* @__PURE__ */ Symbol.for("braintrust.registry");
|
|
23644
25942
|
function getSharedState() {
|
|
@@ -23717,50 +26015,16 @@ var PluginRegistry = class {
|
|
|
23717
26015
|
* Get default configuration (all integrations enabled).
|
|
23718
26016
|
*/
|
|
23719
26017
|
getDefaultConfig() {
|
|
23720
|
-
return
|
|
23721
|
-
openai: true,
|
|
23722
|
-
openaiCodexSDK: true,
|
|
23723
|
-
anthropic: true,
|
|
23724
|
-
vercel: true,
|
|
23725
|
-
aisdk: true,
|
|
23726
|
-
google: true,
|
|
23727
|
-
googleGenAI: true,
|
|
23728
|
-
googleADK: true,
|
|
23729
|
-
huggingface: true,
|
|
23730
|
-
claudeAgentSDK: true,
|
|
23731
|
-
cursor: true,
|
|
23732
|
-
cursorSDK: true,
|
|
23733
|
-
openrouter: true,
|
|
23734
|
-
openrouterAgent: true,
|
|
23735
|
-
mistral: true,
|
|
23736
|
-
cohere: true,
|
|
23737
|
-
groq: true,
|
|
23738
|
-
genkit: true,
|
|
23739
|
-
gitHubCopilot: true
|
|
23740
|
-
};
|
|
26018
|
+
return getDefaultInstrumentationIntegrations();
|
|
23741
26019
|
}
|
|
23742
26020
|
/**
|
|
23743
26021
|
* Read configuration from environment variables.
|
|
23744
26022
|
* Supports: BRAINTRUST_DISABLE_INSTRUMENTATION=openai,anthropic,...
|
|
23745
26023
|
*/
|
|
23746
26024
|
readEnvConfig() {
|
|
23747
|
-
|
|
23748
|
-
|
|
23749
|
-
|
|
23750
|
-
const disabled = disabledList.split(",").map((s) => s.trim().toLowerCase()).filter((s) => s.length > 0);
|
|
23751
|
-
for (const sdk of disabled) {
|
|
23752
|
-
if (sdk === "cursor-sdk") {
|
|
23753
|
-
integrations.cursorSDK = false;
|
|
23754
|
-
} else if (sdk === "githubcopilot" || sdk === "github-copilot" || sdk === "copilot-sdk") {
|
|
23755
|
-
integrations.gitHubCopilot = false;
|
|
23756
|
-
} else if (sdk === "openai-codex-sdk") {
|
|
23757
|
-
integrations.openaiCodexSDK = false;
|
|
23758
|
-
} else {
|
|
23759
|
-
integrations[sdk] = false;
|
|
23760
|
-
}
|
|
23761
|
-
}
|
|
23762
|
-
}
|
|
23763
|
-
return { integrations };
|
|
26025
|
+
return readDisabledInstrumentationEnvConfig(
|
|
26026
|
+
isomorph_default.getEnv("BRAINTRUST_DISABLE_INSTRUMENTATION")
|
|
26027
|
+
);
|
|
23764
26028
|
}
|
|
23765
26029
|
};
|
|
23766
26030
|
var registry = new PluginRegistry();
|
|
@@ -23811,8 +26075,10 @@ __export(exports_exports, {
|
|
|
23811
26075
|
Attachment: () => Attachment,
|
|
23812
26076
|
AttachmentReference: () => AttachmentReference,
|
|
23813
26077
|
BRAINTRUST_CURRENT_SPAN_STORE: () => BRAINTRUST_CURRENT_SPAN_STORE,
|
|
26078
|
+
BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME: () => BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME,
|
|
23814
26079
|
BaseAttachment: () => BaseAttachment,
|
|
23815
26080
|
BaseExperiment: () => BaseExperiment,
|
|
26081
|
+
BraintrustLangChainCallbackHandler: () => BraintrustLangChainCallbackHandler,
|
|
23816
26082
|
BraintrustMiddleware: () => BraintrustMiddleware,
|
|
23817
26083
|
BraintrustState: () => BraintrustState,
|
|
23818
26084
|
BraintrustStream: () => BraintrustStream,
|
|
@@ -23938,6 +26204,8 @@ __export(exports_exports, {
|
|
|
23938
26204
|
wrapCohere: () => wrapCohere,
|
|
23939
26205
|
wrapCopilotClient: () => wrapCopilotClient,
|
|
23940
26206
|
wrapCursorSDK: () => wrapCursorSDK,
|
|
26207
|
+
wrapFlueContext: () => wrapFlueContext,
|
|
26208
|
+
wrapFlueSession: () => wrapFlueSession,
|
|
23941
26209
|
wrapGenkit: () => wrapGenkit,
|
|
23942
26210
|
wrapGoogleADK: () => wrapGoogleADK,
|
|
23943
26211
|
wrapGoogleGenAI: () => wrapGoogleGenAI,
|
|
@@ -25037,7 +27305,7 @@ function extractModelParameters(params, excludeKeys) {
|
|
|
25037
27305
|
}
|
|
25038
27306
|
return modelParams;
|
|
25039
27307
|
}
|
|
25040
|
-
function
|
|
27308
|
+
function getNumberProperty3(obj, key) {
|
|
25041
27309
|
if (!obj || typeof obj !== "object" || !(key in obj)) {
|
|
25042
27310
|
return void 0;
|
|
25043
27311
|
}
|
|
@@ -25046,31 +27314,31 @@ function getNumberProperty2(obj, key) {
|
|
|
25046
27314
|
}
|
|
25047
27315
|
function normalizeUsageMetrics(usage, provider, providerMetadata) {
|
|
25048
27316
|
const metrics = {};
|
|
25049
|
-
const inputTokens =
|
|
27317
|
+
const inputTokens = getNumberProperty3(usage, "inputTokens");
|
|
25050
27318
|
if (inputTokens !== void 0) {
|
|
25051
27319
|
metrics.prompt_tokens = inputTokens;
|
|
25052
27320
|
}
|
|
25053
|
-
const outputTokens =
|
|
27321
|
+
const outputTokens = getNumberProperty3(usage, "outputTokens");
|
|
25054
27322
|
if (outputTokens !== void 0) {
|
|
25055
27323
|
metrics.completion_tokens = outputTokens;
|
|
25056
27324
|
}
|
|
25057
|
-
const totalTokens =
|
|
27325
|
+
const totalTokens = getNumberProperty3(usage, "totalTokens");
|
|
25058
27326
|
if (totalTokens !== void 0) {
|
|
25059
27327
|
metrics.tokens = totalTokens;
|
|
25060
27328
|
}
|
|
25061
|
-
const reasoningTokens =
|
|
27329
|
+
const reasoningTokens = getNumberProperty3(usage, "reasoningTokens");
|
|
25062
27330
|
if (reasoningTokens !== void 0) {
|
|
25063
27331
|
metrics.completion_reasoning_tokens = reasoningTokens;
|
|
25064
27332
|
}
|
|
25065
|
-
const cachedInputTokens =
|
|
27333
|
+
const cachedInputTokens = getNumberProperty3(usage, "cachedInputTokens");
|
|
25066
27334
|
if (cachedInputTokens !== void 0) {
|
|
25067
27335
|
metrics.prompt_cached_tokens = cachedInputTokens;
|
|
25068
27336
|
}
|
|
25069
27337
|
if (provider === "anthropic") {
|
|
25070
27338
|
const anthropicMetadata = providerMetadata?.anthropic;
|
|
25071
27339
|
if (anthropicMetadata) {
|
|
25072
|
-
const cacheReadTokens =
|
|
25073
|
-
const cacheCreationTokens =
|
|
27340
|
+
const cacheReadTokens = getNumberProperty3(anthropicMetadata.usage, "cache_read_input_tokens") || 0;
|
|
27341
|
+
const cacheCreationTokens = getNumberProperty3(
|
|
25074
27342
|
anthropicMetadata.usage,
|
|
25075
27343
|
"cache_creation_input_tokens"
|
|
25076
27344
|
) || 0;
|
|
@@ -26045,17 +28313,17 @@ function wrapGenkit(genkit) {
|
|
|
26045
28313
|
console.warn("Unsupported Genkit object. Not wrapping.");
|
|
26046
28314
|
return genkit;
|
|
26047
28315
|
}
|
|
26048
|
-
function
|
|
28316
|
+
function isRecord2(value) {
|
|
26049
28317
|
return typeof value === "object" && value !== null;
|
|
26050
28318
|
}
|
|
26051
28319
|
function isPropertyBag(value) {
|
|
26052
|
-
return
|
|
28320
|
+
return isRecord2(value) || typeof value === "function";
|
|
26053
28321
|
}
|
|
26054
28322
|
function hasFunction(value, methodName) {
|
|
26055
28323
|
return isPropertyBag(value) && methodName in value && typeof value[methodName] === "function";
|
|
26056
28324
|
}
|
|
26057
28325
|
function isGenkitInstance(value) {
|
|
26058
|
-
return
|
|
28326
|
+
return isRecord2(value) && (hasFunction(value, "generate") || hasFunction(value, "generateStream") || hasFunction(value, "defineFlow") || hasFunction(value, "defineTool"));
|
|
26059
28327
|
}
|
|
26060
28328
|
function isGenkitModule(value) {
|
|
26061
28329
|
return hasFunction(value, "genkit");
|
|
@@ -26109,7 +28377,7 @@ function patchGenkitRegistry(instance) {
|
|
|
26109
28377
|
patchGenkitRegistryConstructor(registry2);
|
|
26110
28378
|
}
|
|
26111
28379
|
function patchGenkitRegistryLookup(registry2) {
|
|
26112
|
-
if (!
|
|
28380
|
+
if (!isRecord2(registry2) || hasRegistryPatchedFlag(registry2) || !hasFunction(registry2, "lookupAction")) {
|
|
26113
28381
|
return;
|
|
26114
28382
|
}
|
|
26115
28383
|
const originalLookupAction = registry2.lookupAction;
|
|
@@ -26135,7 +28403,7 @@ function patchGenkitRegistryLookup(registry2) {
|
|
|
26135
28403
|
}
|
|
26136
28404
|
}
|
|
26137
28405
|
function patchGenkitRegistryConstructor(registry2) {
|
|
26138
|
-
if (!
|
|
28406
|
+
if (!isRecord2(registry2)) {
|
|
26139
28407
|
return;
|
|
26140
28408
|
}
|
|
26141
28409
|
const constructor = registry2.constructor;
|
|
@@ -26151,7 +28419,7 @@ function patchGenkitRegistryConstructor(registry2) {
|
|
|
26151
28419
|
configurable: true,
|
|
26152
28420
|
value: (...args) => {
|
|
26153
28421
|
const childRegistry = originalWithParent.apply(constructor, args);
|
|
26154
|
-
if (args.some((arg) =>
|
|
28422
|
+
if (args.some((arg) => isRecord2(arg) && hasRegistryPatchedFlag(arg))) {
|
|
26155
28423
|
patchGenkitRegistryLookup(childRegistry);
|
|
26156
28424
|
patchGenkitRegistryConstructor(childRegistry);
|
|
26157
28425
|
}
|
|
@@ -26250,7 +28518,7 @@ function hasRegistryConstructorPatchedFlag(value) {
|
|
|
26250
28518
|
);
|
|
26251
28519
|
}
|
|
26252
28520
|
function isPromiseLike2(value) {
|
|
26253
|
-
return
|
|
28521
|
+
return isRecord2(value) && "then" in value && typeof value.then === "function";
|
|
26254
28522
|
}
|
|
26255
28523
|
|
|
26256
28524
|
// src/wrappers/huggingface.ts
|
|
@@ -26613,14 +28881,14 @@ function wrapMistral(mistral) {
|
|
|
26613
28881
|
console.warn("Unsupported Mistral library. Not wrapping.");
|
|
26614
28882
|
return mistral;
|
|
26615
28883
|
}
|
|
26616
|
-
function
|
|
28884
|
+
function isRecord3(value) {
|
|
26617
28885
|
return typeof value === "object" && value !== null;
|
|
26618
28886
|
}
|
|
26619
28887
|
function hasFunction3(value, methodName) {
|
|
26620
|
-
return
|
|
28888
|
+
return isRecord3(value) && methodName in value && typeof value[methodName] === "function";
|
|
26621
28889
|
}
|
|
26622
28890
|
function isSupportedMistralClient(value) {
|
|
26623
|
-
if (!
|
|
28891
|
+
if (!isRecord3(value)) {
|
|
26624
28892
|
return false;
|
|
26625
28893
|
}
|
|
26626
28894
|
return value.chat !== void 0 && hasChat(value.chat) || value.embeddings !== void 0 && hasEmbeddings(value.embeddings) || value.fim !== void 0 && hasFim(value.fim) || value.agents !== void 0 && hasAgents(value.agents) || value.classifiers !== void 0 && hasClassifiers(value.classifiers);
|
|
@@ -26804,14 +29072,14 @@ function wrapCohere(cohere) {
|
|
|
26804
29072
|
return cohere;
|
|
26805
29073
|
}
|
|
26806
29074
|
var cohereProxyCache = /* @__PURE__ */ new WeakMap();
|
|
26807
|
-
function
|
|
29075
|
+
function isRecord4(value) {
|
|
26808
29076
|
return typeof value === "object" && value !== null;
|
|
26809
29077
|
}
|
|
26810
29078
|
function hasFunction4(value, methodName) {
|
|
26811
|
-
return
|
|
29079
|
+
return isRecord4(value) && methodName in value && typeof value[methodName] === "function";
|
|
26812
29080
|
}
|
|
26813
29081
|
function isSupportedCohereClient(value) {
|
|
26814
|
-
if (!
|
|
29082
|
+
if (!isRecord4(value)) {
|
|
26815
29083
|
return false;
|
|
26816
29084
|
}
|
|
26817
29085
|
return hasFunction4(value, "chat") || hasFunction4(value, "chatStream") || hasFunction4(value, "embed") || hasFunction4(value, "rerank");
|
|
@@ -26871,20 +29139,20 @@ function wrapGroq(groq) {
|
|
|
26871
29139
|
console.warn("Unsupported Groq library. Not wrapping.");
|
|
26872
29140
|
return groq;
|
|
26873
29141
|
}
|
|
26874
|
-
function
|
|
29142
|
+
function isRecord5(value) {
|
|
26875
29143
|
return typeof value === "object" && value !== null;
|
|
26876
29144
|
}
|
|
26877
29145
|
function hasFunction5(value, methodName) {
|
|
26878
|
-
return
|
|
29146
|
+
return isRecord5(value) && methodName in value && typeof value[methodName] === "function";
|
|
26879
29147
|
}
|
|
26880
29148
|
function hasChat2(value) {
|
|
26881
|
-
return
|
|
29149
|
+
return isRecord5(value) && isRecord5(value.completions) && hasFunction5(value.completions, "create");
|
|
26882
29150
|
}
|
|
26883
29151
|
function hasEmbeddings2(value) {
|
|
26884
29152
|
return hasFunction5(value, "create");
|
|
26885
29153
|
}
|
|
26886
29154
|
function isSupportedGroqClient(value) {
|
|
26887
|
-
return
|
|
29155
|
+
return isRecord5(value) && (value.chat !== void 0 && hasChat2(value.chat) || value.embeddings !== void 0 && hasEmbeddings2(value.embeddings));
|
|
26888
29156
|
}
|
|
26889
29157
|
function groqProxy(groq) {
|
|
26890
29158
|
const privateMethodWorkaroundCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -30862,8 +33130,10 @@ export {
|
|
|
30862
33130
|
Attachment,
|
|
30863
33131
|
AttachmentReference,
|
|
30864
33132
|
BRAINTRUST_CURRENT_SPAN_STORE,
|
|
33133
|
+
BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME,
|
|
30865
33134
|
BaseAttachment,
|
|
30866
33135
|
BaseExperiment,
|
|
33136
|
+
BraintrustLangChainCallbackHandler,
|
|
30867
33137
|
BraintrustMiddleware,
|
|
30868
33138
|
BraintrustState,
|
|
30869
33139
|
BraintrustStream,
|
|
@@ -30990,6 +33260,8 @@ export {
|
|
|
30990
33260
|
wrapCohere,
|
|
30991
33261
|
wrapCopilotClient,
|
|
30992
33262
|
wrapCursorSDK,
|
|
33263
|
+
wrapFlueContext,
|
|
33264
|
+
wrapFlueSession,
|
|
30993
33265
|
wrapGenkit,
|
|
30994
33266
|
wrapGoogleADK,
|
|
30995
33267
|
wrapGoogleGenAI,
|