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/browser.mjs
CHANGED
|
@@ -924,6 +924,11 @@ function isPromiseLike(value) {
|
|
|
924
924
|
|
|
925
925
|
// util/object_util.ts
|
|
926
926
|
var SET_UNION_FIELDS = /* @__PURE__ */ new Set(["tags"]);
|
|
927
|
+
var FORBIDDEN_MERGE_KEYS = /* @__PURE__ */ new Set([
|
|
928
|
+
"__proto__",
|
|
929
|
+
"constructor",
|
|
930
|
+
"prototype"
|
|
931
|
+
]);
|
|
927
932
|
function mergeDictsWithPaths({
|
|
928
933
|
mergeInto,
|
|
929
934
|
mergeFrom,
|
|
@@ -946,6 +951,7 @@ function mergeDictsWithPathsHelper({
|
|
|
946
951
|
mergePaths
|
|
947
952
|
}) {
|
|
948
953
|
Object.entries(mergeFrom).forEach(([k, mergeFromV]) => {
|
|
954
|
+
if (FORBIDDEN_MERGE_KEYS.has(k)) return;
|
|
949
955
|
const fullPath = path.concat([k]);
|
|
950
956
|
const fullPathSerialized = JSON.stringify(fullPath);
|
|
951
957
|
const mergeIntoV = recordFind(mergeInto, k);
|
|
@@ -5019,6 +5025,13 @@ var HTTPConnection = class _HTTPConnection {
|
|
|
5019
5025
|
debugLogger.debug(
|
|
5020
5026
|
`Retrying API request ${object_type} ${JSON.stringify(args)} ${e.status} ${e.text}`
|
|
5021
5027
|
);
|
|
5028
|
+
const sleepTimeS = HTTP_RETRY_BASE_SLEEP_TIME_S * 2 ** i;
|
|
5029
|
+
debugLogger.info(
|
|
5030
|
+
`Sleeping for ${sleepTimeS}s before retrying API request`
|
|
5031
|
+
);
|
|
5032
|
+
await new Promise(
|
|
5033
|
+
(resolve) => setTimeout(resolve, sleepTimeS * 1e3)
|
|
5034
|
+
);
|
|
5022
5035
|
continue;
|
|
5023
5036
|
}
|
|
5024
5037
|
throw e;
|
|
@@ -5668,20 +5681,7 @@ function startSpanParentArgs(args) {
|
|
|
5668
5681
|
`Mismatch between expected span parent object type ${args.parentObjectType} and provided type ${parentComponents.data.object_type}`
|
|
5669
5682
|
);
|
|
5670
5683
|
}
|
|
5671
|
-
|
|
5672
|
-
args.state,
|
|
5673
|
-
parentComponents
|
|
5674
|
-
);
|
|
5675
|
-
const computeParentObjectId = async () => {
|
|
5676
|
-
const parentComponentsObjectId = await parentComponentsObjectIdLambda();
|
|
5677
|
-
if (await args.parentObjectId.get() !== parentComponentsObjectId) {
|
|
5678
|
-
throw new Error(
|
|
5679
|
-
`Mismatch between expected span parent object id ${await args.parentObjectId.get()} and provided id ${parentComponentsObjectId}`
|
|
5680
|
-
);
|
|
5681
|
-
}
|
|
5682
|
-
return await args.parentObjectId.get();
|
|
5683
|
-
};
|
|
5684
|
-
argParentObjectId = new LazyValue(computeParentObjectId);
|
|
5684
|
+
argParentObjectId = args.parentObjectId;
|
|
5685
5685
|
if (parentComponents.data.row_id) {
|
|
5686
5686
|
argParentSpanIds = {
|
|
5687
5687
|
spanId: parentComponents.data.span_id,
|
|
@@ -6067,6 +6067,7 @@ var TestBackgroundLogger = class {
|
|
|
6067
6067
|
}
|
|
6068
6068
|
};
|
|
6069
6069
|
var BACKGROUND_LOGGER_BASE_SLEEP_TIME_S = 1;
|
|
6070
|
+
var HTTP_RETRY_BASE_SLEEP_TIME_S = 1;
|
|
6070
6071
|
var HTTPBackgroundLogger = class _HTTPBackgroundLogger {
|
|
6071
6072
|
apiConn;
|
|
6072
6073
|
queue;
|
|
@@ -6697,17 +6698,10 @@ function init(projectOrOptions, optionalOptions) {
|
|
|
6697
6698
|
if (repoInfo) {
|
|
6698
6699
|
return repoInfo;
|
|
6699
6700
|
}
|
|
6700
|
-
|
|
6701
|
-
|
|
6702
|
-
|
|
6703
|
-
|
|
6704
|
-
};
|
|
6705
|
-
if (gitMetadataSettings) {
|
|
6706
|
-
mergedGitMetadataSettings = mergeGitMetadataSettings(
|
|
6707
|
-
mergedGitMetadataSettings,
|
|
6708
|
-
gitMetadataSettings
|
|
6709
|
-
);
|
|
6710
|
-
}
|
|
6701
|
+
const mergedGitMetadataSettings = state.gitMetadataSettings == null ? gitMetadataSettings ?? { collect: "none" } : mergeGitMetadataSettings(
|
|
6702
|
+
state.gitMetadataSettings,
|
|
6703
|
+
gitMetadataSettings ?? { collect: "all" }
|
|
6704
|
+
);
|
|
6711
6705
|
return await isomorph_default.getRepoInfo(mergedGitMetadataSettings);
|
|
6712
6706
|
})();
|
|
6713
6707
|
if (repoInfoArg) {
|
|
@@ -13403,11 +13397,11 @@ function resolveDenyOutputPaths(event, defaultDenyOutputPaths) {
|
|
|
13403
13397
|
if (Array.isArray(event?.denyOutputPaths)) {
|
|
13404
13398
|
return event.denyOutputPaths;
|
|
13405
13399
|
}
|
|
13406
|
-
const
|
|
13407
|
-
if (!
|
|
13400
|
+
const firstArgument2 = event?.arguments && event.arguments.length > 0 ? event.arguments[0] : void 0;
|
|
13401
|
+
if (!firstArgument2 || typeof firstArgument2 !== "object") {
|
|
13408
13402
|
return defaultDenyOutputPaths;
|
|
13409
13403
|
}
|
|
13410
|
-
const runtimeDenyOutputPaths =
|
|
13404
|
+
const runtimeDenyOutputPaths = firstArgument2[RUNTIME_DENY_OUTPUT_PATHS];
|
|
13411
13405
|
if (Array.isArray(runtimeDenyOutputPaths) && runtimeDenyOutputPaths.every((path) => typeof path === "string")) {
|
|
13412
13406
|
return runtimeDenyOutputPaths;
|
|
13413
13407
|
}
|
|
@@ -17066,6 +17060,467 @@ function cleanMetrics2(metrics) {
|
|
|
17066
17060
|
return cleaned;
|
|
17067
17061
|
}
|
|
17068
17062
|
|
|
17063
|
+
// src/instrumentation/plugins/openai-agents-channels.ts
|
|
17064
|
+
var openAIAgentsCoreChannels = defineChannels("@openai/agents-core", {
|
|
17065
|
+
onTraceStart: channel({
|
|
17066
|
+
channelName: "tracing.processor.onTraceStart",
|
|
17067
|
+
kind: "async"
|
|
17068
|
+
}),
|
|
17069
|
+
onTraceEnd: channel({
|
|
17070
|
+
channelName: "tracing.processor.onTraceEnd",
|
|
17071
|
+
kind: "async"
|
|
17072
|
+
}),
|
|
17073
|
+
onSpanStart: channel({
|
|
17074
|
+
channelName: "tracing.processor.onSpanStart",
|
|
17075
|
+
kind: "async"
|
|
17076
|
+
}),
|
|
17077
|
+
onSpanEnd: channel({
|
|
17078
|
+
channelName: "tracing.processor.onSpanEnd",
|
|
17079
|
+
kind: "async"
|
|
17080
|
+
})
|
|
17081
|
+
});
|
|
17082
|
+
|
|
17083
|
+
// src/instrumentation/plugins/openai-agents-trace-processor.ts
|
|
17084
|
+
function isSpanData(spanData, type) {
|
|
17085
|
+
return spanData.type === type;
|
|
17086
|
+
}
|
|
17087
|
+
function spanTypeFromAgents(span) {
|
|
17088
|
+
const spanType = span.spanData.type;
|
|
17089
|
+
if (spanType === "function" || spanType === "guardrail" || spanType === "mcp_tools") {
|
|
17090
|
+
return "tool" /* TOOL */;
|
|
17091
|
+
}
|
|
17092
|
+
if (spanType === "generation" || spanType === "response" || spanType === "transcription" || spanType === "speech") {
|
|
17093
|
+
return "llm" /* LLM */;
|
|
17094
|
+
}
|
|
17095
|
+
return "task" /* TASK */;
|
|
17096
|
+
}
|
|
17097
|
+
function spanNameFromAgents(span) {
|
|
17098
|
+
const spanData = span.spanData;
|
|
17099
|
+
if ("name" in spanData && spanData.name) {
|
|
17100
|
+
return spanData.name;
|
|
17101
|
+
}
|
|
17102
|
+
switch (spanData.type) {
|
|
17103
|
+
case "generation":
|
|
17104
|
+
return "Generation";
|
|
17105
|
+
case "response":
|
|
17106
|
+
return "Response";
|
|
17107
|
+
case "handoff":
|
|
17108
|
+
return "Handoff";
|
|
17109
|
+
case "mcp_tools":
|
|
17110
|
+
return isSpanData(spanData, "mcp_tools") && spanData.server ? `List Tools (${spanData.server})` : "MCP List Tools";
|
|
17111
|
+
case "transcription":
|
|
17112
|
+
return "Transcription";
|
|
17113
|
+
case "speech":
|
|
17114
|
+
return "Speech";
|
|
17115
|
+
case "speech_group":
|
|
17116
|
+
return "Speech Group";
|
|
17117
|
+
default:
|
|
17118
|
+
return "Unknown";
|
|
17119
|
+
}
|
|
17120
|
+
}
|
|
17121
|
+
function getTimeElapsed(end, start) {
|
|
17122
|
+
if (!start || !end) {
|
|
17123
|
+
return void 0;
|
|
17124
|
+
}
|
|
17125
|
+
const startTime = new Date(start).getTime();
|
|
17126
|
+
const endTime = new Date(end).getTime();
|
|
17127
|
+
if (Number.isNaN(startTime) || Number.isNaN(endTime)) {
|
|
17128
|
+
return void 0;
|
|
17129
|
+
}
|
|
17130
|
+
return (endTime - startTime) / 1e3;
|
|
17131
|
+
}
|
|
17132
|
+
function getNumberProperty2(obj, key) {
|
|
17133
|
+
if (!isObject(obj) || !(key in obj)) {
|
|
17134
|
+
return void 0;
|
|
17135
|
+
}
|
|
17136
|
+
const value = obj[key];
|
|
17137
|
+
return typeof value === "number" ? value : void 0;
|
|
17138
|
+
}
|
|
17139
|
+
function parseUsageMetrics(usage) {
|
|
17140
|
+
const metrics = {};
|
|
17141
|
+
if (!isObject(usage)) {
|
|
17142
|
+
return metrics;
|
|
17143
|
+
}
|
|
17144
|
+
const promptTokens = getNumberProperty2(usage, "prompt_tokens") ?? getNumberProperty2(usage, "input_tokens") ?? getNumberProperty2(usage, "promptTokens") ?? getNumberProperty2(usage, "inputTokens");
|
|
17145
|
+
const completionTokens = getNumberProperty2(usage, "completion_tokens") ?? getNumberProperty2(usage, "output_tokens") ?? getNumberProperty2(usage, "completionTokens") ?? getNumberProperty2(usage, "outputTokens");
|
|
17146
|
+
const totalTokens = getNumberProperty2(usage, "total_tokens") ?? getNumberProperty2(usage, "totalTokens");
|
|
17147
|
+
if (promptTokens !== void 0) {
|
|
17148
|
+
metrics.prompt_tokens = promptTokens;
|
|
17149
|
+
}
|
|
17150
|
+
if (completionTokens !== void 0) {
|
|
17151
|
+
metrics.completion_tokens = completionTokens;
|
|
17152
|
+
}
|
|
17153
|
+
if (totalTokens !== void 0) {
|
|
17154
|
+
metrics.tokens = totalTokens;
|
|
17155
|
+
} else if (promptTokens !== void 0 && completionTokens !== void 0) {
|
|
17156
|
+
metrics.tokens = promptTokens + completionTokens;
|
|
17157
|
+
}
|
|
17158
|
+
const inputDetails = usage.input_tokens_details;
|
|
17159
|
+
const cachedTokens = getNumberProperty2(inputDetails, "cached_tokens");
|
|
17160
|
+
const cacheWriteTokens = getNumberProperty2(
|
|
17161
|
+
inputDetails,
|
|
17162
|
+
"cache_write_tokens"
|
|
17163
|
+
);
|
|
17164
|
+
if (cachedTokens !== void 0) {
|
|
17165
|
+
metrics.prompt_cached_tokens = cachedTokens;
|
|
17166
|
+
}
|
|
17167
|
+
if (cacheWriteTokens !== void 0) {
|
|
17168
|
+
metrics.prompt_cache_creation_tokens = cacheWriteTokens;
|
|
17169
|
+
}
|
|
17170
|
+
return metrics;
|
|
17171
|
+
}
|
|
17172
|
+
var OpenAIAgentsTraceProcessor = class _OpenAIAgentsTraceProcessor {
|
|
17173
|
+
static DEFAULT_MAX_TRACES = 1e4;
|
|
17174
|
+
logger;
|
|
17175
|
+
maxTraces;
|
|
17176
|
+
traceSpans = /* @__PURE__ */ new Map();
|
|
17177
|
+
traceOrder = [];
|
|
17178
|
+
_traceSpans = this.traceSpans;
|
|
17179
|
+
constructor(options = {}) {
|
|
17180
|
+
this.logger = options.logger;
|
|
17181
|
+
this.maxTraces = options.maxTraces ?? _OpenAIAgentsTraceProcessor.DEFAULT_MAX_TRACES;
|
|
17182
|
+
}
|
|
17183
|
+
evictOldestTrace() {
|
|
17184
|
+
const oldestTraceId = this.traceOrder.shift();
|
|
17185
|
+
if (oldestTraceId) {
|
|
17186
|
+
this.traceSpans.delete(oldestTraceId);
|
|
17187
|
+
}
|
|
17188
|
+
}
|
|
17189
|
+
onTraceStart(trace) {
|
|
17190
|
+
if (!trace?.traceId) {
|
|
17191
|
+
return Promise.resolve();
|
|
17192
|
+
}
|
|
17193
|
+
if (this.traceOrder.length >= this.maxTraces) {
|
|
17194
|
+
this.evictOldestTrace();
|
|
17195
|
+
}
|
|
17196
|
+
const current = currentSpan();
|
|
17197
|
+
const span = current && current !== NOOP_SPAN ? current.startSpan({
|
|
17198
|
+
name: trace.name,
|
|
17199
|
+
type: "task" /* TASK */
|
|
17200
|
+
}) : this.logger ? this.logger.startSpan({
|
|
17201
|
+
name: trace.name,
|
|
17202
|
+
type: "task" /* TASK */
|
|
17203
|
+
}) : startSpan({
|
|
17204
|
+
name: trace.name,
|
|
17205
|
+
type: "task" /* TASK */
|
|
17206
|
+
});
|
|
17207
|
+
span.log({
|
|
17208
|
+
input: "Agent workflow started",
|
|
17209
|
+
metadata: {
|
|
17210
|
+
group_id: trace.groupId,
|
|
17211
|
+
...trace.metadata || {}
|
|
17212
|
+
}
|
|
17213
|
+
});
|
|
17214
|
+
this.traceSpans.set(trace.traceId, {
|
|
17215
|
+
rootSpan: span,
|
|
17216
|
+
childSpans: /* @__PURE__ */ new Map(),
|
|
17217
|
+
metadata: {
|
|
17218
|
+
firstInput: null,
|
|
17219
|
+
lastOutput: null
|
|
17220
|
+
}
|
|
17221
|
+
});
|
|
17222
|
+
this.traceOrder.push(trace.traceId);
|
|
17223
|
+
return Promise.resolve();
|
|
17224
|
+
}
|
|
17225
|
+
async onTraceEnd(trace) {
|
|
17226
|
+
const traceData = this.traceSpans.get(trace?.traceId);
|
|
17227
|
+
if (!traceData) {
|
|
17228
|
+
return;
|
|
17229
|
+
}
|
|
17230
|
+
try {
|
|
17231
|
+
traceData.rootSpan.log({
|
|
17232
|
+
input: traceData.metadata.firstInput,
|
|
17233
|
+
output: traceData.metadata.lastOutput
|
|
17234
|
+
});
|
|
17235
|
+
traceData.rootSpan.end();
|
|
17236
|
+
await traceData.rootSpan.flush();
|
|
17237
|
+
} finally {
|
|
17238
|
+
this.traceSpans.delete(trace.traceId);
|
|
17239
|
+
const orderIndex = this.traceOrder.indexOf(trace.traceId);
|
|
17240
|
+
if (orderIndex > -1) {
|
|
17241
|
+
this.traceOrder.splice(orderIndex, 1);
|
|
17242
|
+
}
|
|
17243
|
+
}
|
|
17244
|
+
}
|
|
17245
|
+
onSpanStart(span) {
|
|
17246
|
+
if (!span?.spanId || !span.traceId) {
|
|
17247
|
+
return Promise.resolve();
|
|
17248
|
+
}
|
|
17249
|
+
const traceData = this.traceSpans.get(span.traceId);
|
|
17250
|
+
if (!traceData) {
|
|
17251
|
+
return Promise.resolve();
|
|
17252
|
+
}
|
|
17253
|
+
const parentSpan = span.parentId ? traceData.childSpans.get(span.parentId) : traceData.rootSpan;
|
|
17254
|
+
if (!parentSpan) {
|
|
17255
|
+
return Promise.resolve();
|
|
17256
|
+
}
|
|
17257
|
+
const childSpan = parentSpan.startSpan({
|
|
17258
|
+
name: spanNameFromAgents(span),
|
|
17259
|
+
type: spanTypeFromAgents(span)
|
|
17260
|
+
});
|
|
17261
|
+
traceData.childSpans.set(span.spanId, childSpan);
|
|
17262
|
+
return Promise.resolve();
|
|
17263
|
+
}
|
|
17264
|
+
onSpanEnd(span) {
|
|
17265
|
+
if (!span?.spanId || !span.traceId) {
|
|
17266
|
+
return Promise.resolve();
|
|
17267
|
+
}
|
|
17268
|
+
const traceData = this.traceSpans.get(span.traceId);
|
|
17269
|
+
if (!traceData) {
|
|
17270
|
+
return Promise.resolve();
|
|
17271
|
+
}
|
|
17272
|
+
const braintrustSpan = traceData.childSpans.get(span.spanId);
|
|
17273
|
+
if (!braintrustSpan) {
|
|
17274
|
+
return Promise.resolve();
|
|
17275
|
+
}
|
|
17276
|
+
const logData = this.extractLogData(span);
|
|
17277
|
+
braintrustSpan.log({
|
|
17278
|
+
error: span.error,
|
|
17279
|
+
...logData
|
|
17280
|
+
});
|
|
17281
|
+
braintrustSpan.end();
|
|
17282
|
+
traceData.childSpans.delete(span.spanId);
|
|
17283
|
+
const input = logData.input;
|
|
17284
|
+
const output = logData.output;
|
|
17285
|
+
if (traceData.metadata.firstInput === null && input != null) {
|
|
17286
|
+
traceData.metadata.firstInput = input;
|
|
17287
|
+
}
|
|
17288
|
+
if (output != null) {
|
|
17289
|
+
traceData.metadata.lastOutput = output;
|
|
17290
|
+
}
|
|
17291
|
+
return Promise.resolve();
|
|
17292
|
+
}
|
|
17293
|
+
async shutdown() {
|
|
17294
|
+
if (this.logger && typeof this.logger.flush === "function") {
|
|
17295
|
+
await this.logger.flush();
|
|
17296
|
+
}
|
|
17297
|
+
}
|
|
17298
|
+
async forceFlush() {
|
|
17299
|
+
if (this.logger && typeof this.logger.flush === "function") {
|
|
17300
|
+
await this.logger.flush();
|
|
17301
|
+
}
|
|
17302
|
+
}
|
|
17303
|
+
extractLogData(span) {
|
|
17304
|
+
const spanData = span.spanData;
|
|
17305
|
+
switch (spanData.type) {
|
|
17306
|
+
case "agent":
|
|
17307
|
+
return this.extractAgentLogData(spanData);
|
|
17308
|
+
case "response":
|
|
17309
|
+
return this.extractResponseLogData(spanData, span);
|
|
17310
|
+
case "function":
|
|
17311
|
+
return this.extractFunctionLogData(spanData);
|
|
17312
|
+
case "handoff":
|
|
17313
|
+
return this.extractHandoffLogData(spanData);
|
|
17314
|
+
case "guardrail":
|
|
17315
|
+
return this.extractGuardrailLogData(spanData);
|
|
17316
|
+
case "generation":
|
|
17317
|
+
return this.extractGenerationLogData(spanData, span);
|
|
17318
|
+
case "custom":
|
|
17319
|
+
return this.extractCustomLogData(spanData);
|
|
17320
|
+
case "mcp_tools":
|
|
17321
|
+
return this.extractMCPListToolsLogData(spanData);
|
|
17322
|
+
case "transcription":
|
|
17323
|
+
return this.extractTranscriptionLogData(spanData);
|
|
17324
|
+
case "speech":
|
|
17325
|
+
return this.extractSpeechLogData(spanData);
|
|
17326
|
+
case "speech_group":
|
|
17327
|
+
return this.extractSpeechGroupLogData(spanData);
|
|
17328
|
+
default:
|
|
17329
|
+
return {};
|
|
17330
|
+
}
|
|
17331
|
+
}
|
|
17332
|
+
extractAgentLogData(spanData) {
|
|
17333
|
+
return {
|
|
17334
|
+
metadata: {
|
|
17335
|
+
tools: spanData.tools,
|
|
17336
|
+
handoffs: spanData.handoffs,
|
|
17337
|
+
output_type: spanData.output_type
|
|
17338
|
+
}
|
|
17339
|
+
};
|
|
17340
|
+
}
|
|
17341
|
+
extractResponseLogData(spanData, span) {
|
|
17342
|
+
const response = spanData._response;
|
|
17343
|
+
const output = isObject(response) ? response.output : void 0;
|
|
17344
|
+
const usage = isObject(response) ? response.usage : void 0;
|
|
17345
|
+
const metrics = {
|
|
17346
|
+
...this.extractTimingMetrics(span),
|
|
17347
|
+
...parseUsageMetrics(usage)
|
|
17348
|
+
};
|
|
17349
|
+
return {
|
|
17350
|
+
input: spanData._input,
|
|
17351
|
+
output,
|
|
17352
|
+
metadata: isObject(response) ? this.omitKeys(response, ["output", "usage"]) : {},
|
|
17353
|
+
metrics
|
|
17354
|
+
};
|
|
17355
|
+
}
|
|
17356
|
+
extractFunctionLogData(spanData) {
|
|
17357
|
+
return {
|
|
17358
|
+
input: spanData.input,
|
|
17359
|
+
output: spanData.output
|
|
17360
|
+
};
|
|
17361
|
+
}
|
|
17362
|
+
extractHandoffLogData(spanData) {
|
|
17363
|
+
return {
|
|
17364
|
+
metadata: {
|
|
17365
|
+
from_agent: spanData.from_agent,
|
|
17366
|
+
to_agent: spanData.to_agent
|
|
17367
|
+
}
|
|
17368
|
+
};
|
|
17369
|
+
}
|
|
17370
|
+
extractGuardrailLogData(spanData) {
|
|
17371
|
+
return {
|
|
17372
|
+
metadata: {
|
|
17373
|
+
triggered: spanData.triggered
|
|
17374
|
+
}
|
|
17375
|
+
};
|
|
17376
|
+
}
|
|
17377
|
+
extractGenerationLogData(spanData, span) {
|
|
17378
|
+
return {
|
|
17379
|
+
input: spanData.input,
|
|
17380
|
+
output: spanData.output,
|
|
17381
|
+
metadata: {
|
|
17382
|
+
model: spanData.model,
|
|
17383
|
+
model_config: spanData.model_config
|
|
17384
|
+
},
|
|
17385
|
+
metrics: {
|
|
17386
|
+
...this.extractTimingMetrics(span),
|
|
17387
|
+
...parseUsageMetrics(spanData.usage)
|
|
17388
|
+
}
|
|
17389
|
+
};
|
|
17390
|
+
}
|
|
17391
|
+
extractCustomLogData(spanData) {
|
|
17392
|
+
return spanData.data || {};
|
|
17393
|
+
}
|
|
17394
|
+
extractMCPListToolsLogData(spanData) {
|
|
17395
|
+
return {
|
|
17396
|
+
output: spanData.result,
|
|
17397
|
+
metadata: {
|
|
17398
|
+
server: spanData.server
|
|
17399
|
+
}
|
|
17400
|
+
};
|
|
17401
|
+
}
|
|
17402
|
+
extractTranscriptionLogData(spanData) {
|
|
17403
|
+
return {
|
|
17404
|
+
input: spanData.input,
|
|
17405
|
+
output: spanData.output,
|
|
17406
|
+
metadata: {
|
|
17407
|
+
model: spanData.model,
|
|
17408
|
+
model_config: spanData.model_config
|
|
17409
|
+
}
|
|
17410
|
+
};
|
|
17411
|
+
}
|
|
17412
|
+
extractSpeechLogData(spanData) {
|
|
17413
|
+
return {
|
|
17414
|
+
input: spanData.input,
|
|
17415
|
+
output: spanData.output,
|
|
17416
|
+
metadata: {
|
|
17417
|
+
model: spanData.model,
|
|
17418
|
+
model_config: spanData.model_config
|
|
17419
|
+
}
|
|
17420
|
+
};
|
|
17421
|
+
}
|
|
17422
|
+
extractSpeechGroupLogData(spanData) {
|
|
17423
|
+
return {
|
|
17424
|
+
input: spanData.input
|
|
17425
|
+
};
|
|
17426
|
+
}
|
|
17427
|
+
extractTimingMetrics(span) {
|
|
17428
|
+
const timeToFirstToken = getTimeElapsed(
|
|
17429
|
+
span.endedAt ?? void 0,
|
|
17430
|
+
span.startedAt ?? void 0
|
|
17431
|
+
);
|
|
17432
|
+
return timeToFirstToken === void 0 ? {} : { time_to_first_token: timeToFirstToken };
|
|
17433
|
+
}
|
|
17434
|
+
omitKeys(value, keys) {
|
|
17435
|
+
const result = {};
|
|
17436
|
+
for (const [key, fieldValue] of Object.entries(value)) {
|
|
17437
|
+
if (!keys.includes(key)) {
|
|
17438
|
+
result[key] = fieldValue;
|
|
17439
|
+
}
|
|
17440
|
+
}
|
|
17441
|
+
return result;
|
|
17442
|
+
}
|
|
17443
|
+
};
|
|
17444
|
+
|
|
17445
|
+
// src/instrumentation/plugins/openai-agents-plugin.ts
|
|
17446
|
+
function firstArgument(args) {
|
|
17447
|
+
if (Array.isArray(args)) {
|
|
17448
|
+
return args[0];
|
|
17449
|
+
}
|
|
17450
|
+
if (isObject(args) && "length" in args && typeof args.length === "number" && Number.isInteger(args.length) && args.length >= 0) {
|
|
17451
|
+
return Array.from(args)[0];
|
|
17452
|
+
}
|
|
17453
|
+
return void 0;
|
|
17454
|
+
}
|
|
17455
|
+
function isOpenAIAgentsTrace(value) {
|
|
17456
|
+
return isObject(value) && value.type === "trace" && typeof value.traceId === "string";
|
|
17457
|
+
}
|
|
17458
|
+
function isOpenAIAgentsSpan(value) {
|
|
17459
|
+
return isObject(value) && value.type === "trace.span" && typeof value.traceId === "string" && typeof value.spanId === "string";
|
|
17460
|
+
}
|
|
17461
|
+
var OpenAIAgentsPlugin = class extends BasePlugin {
|
|
17462
|
+
processor = new OpenAIAgentsTraceProcessor();
|
|
17463
|
+
onEnable() {
|
|
17464
|
+
this.subscribeToTraceLifecycle();
|
|
17465
|
+
}
|
|
17466
|
+
onDisable() {
|
|
17467
|
+
this.unsubscribers = unsubscribeAll(this.unsubscribers);
|
|
17468
|
+
void this.processor.shutdown();
|
|
17469
|
+
}
|
|
17470
|
+
subscribeToTraceLifecycle() {
|
|
17471
|
+
const traceStartChannel = openAIAgentsCoreChannels.onTraceStart.tracingChannel();
|
|
17472
|
+
const traceStartHandlers = {
|
|
17473
|
+
start: (event) => {
|
|
17474
|
+
const trace = firstArgument(event.arguments);
|
|
17475
|
+
if (isOpenAIAgentsTrace(trace)) {
|
|
17476
|
+
void this.processor.onTraceStart(trace);
|
|
17477
|
+
}
|
|
17478
|
+
}
|
|
17479
|
+
};
|
|
17480
|
+
traceStartChannel.subscribe(traceStartHandlers);
|
|
17481
|
+
this.unsubscribers.push(
|
|
17482
|
+
() => traceStartChannel.unsubscribe(traceStartHandlers)
|
|
17483
|
+
);
|
|
17484
|
+
const traceEndChannel = openAIAgentsCoreChannels.onTraceEnd.tracingChannel();
|
|
17485
|
+
const traceEndHandlers = {
|
|
17486
|
+
start: (event) => {
|
|
17487
|
+
const trace = firstArgument(event.arguments);
|
|
17488
|
+
if (isOpenAIAgentsTrace(trace)) {
|
|
17489
|
+
void this.processor.onTraceEnd(trace);
|
|
17490
|
+
}
|
|
17491
|
+
}
|
|
17492
|
+
};
|
|
17493
|
+
traceEndChannel.subscribe(traceEndHandlers);
|
|
17494
|
+
this.unsubscribers.push(
|
|
17495
|
+
() => traceEndChannel.unsubscribe(traceEndHandlers)
|
|
17496
|
+
);
|
|
17497
|
+
const spanStartChannel = openAIAgentsCoreChannels.onSpanStart.tracingChannel();
|
|
17498
|
+
const spanStartHandlers = {
|
|
17499
|
+
start: (event) => {
|
|
17500
|
+
const span = firstArgument(event.arguments);
|
|
17501
|
+
if (isOpenAIAgentsSpan(span)) {
|
|
17502
|
+
void this.processor.onSpanStart(span);
|
|
17503
|
+
}
|
|
17504
|
+
}
|
|
17505
|
+
};
|
|
17506
|
+
spanStartChannel.subscribe(spanStartHandlers);
|
|
17507
|
+
this.unsubscribers.push(
|
|
17508
|
+
() => spanStartChannel.unsubscribe(spanStartHandlers)
|
|
17509
|
+
);
|
|
17510
|
+
const spanEndChannel = openAIAgentsCoreChannels.onSpanEnd.tracingChannel();
|
|
17511
|
+
const spanEndHandlers = {
|
|
17512
|
+
start: (event) => {
|
|
17513
|
+
const span = firstArgument(event.arguments);
|
|
17514
|
+
if (isOpenAIAgentsSpan(span)) {
|
|
17515
|
+
void this.processor.onSpanEnd(span);
|
|
17516
|
+
}
|
|
17517
|
+
}
|
|
17518
|
+
};
|
|
17519
|
+
spanEndChannel.subscribe(spanEndHandlers);
|
|
17520
|
+
this.unsubscribers.push(() => spanEndChannel.unsubscribe(spanEndHandlers));
|
|
17521
|
+
}
|
|
17522
|
+
};
|
|
17523
|
+
|
|
17069
17524
|
// src/instrumentation/plugins/google-genai-channels.ts
|
|
17070
17525
|
var googleGenAIChannels = defineChannels("@google/genai", {
|
|
17071
17526
|
generateContent: channel({
|
|
@@ -23358,41 +23813,1773 @@ var GitHubCopilotPlugin = class extends BasePlugin {
|
|
|
23358
23813
|
}
|
|
23359
23814
|
};
|
|
23360
23815
|
|
|
23361
|
-
// src/instrumentation/
|
|
23362
|
-
|
|
23363
|
-
|
|
23816
|
+
// src/instrumentation/plugins/flue-channels.ts
|
|
23817
|
+
var flueChannels = defineChannels("@flue/runtime", {
|
|
23818
|
+
createContext: channel({
|
|
23819
|
+
channelName: "createFlueContext",
|
|
23820
|
+
kind: "sync-stream"
|
|
23821
|
+
}),
|
|
23822
|
+
openSession: channel({
|
|
23823
|
+
channelName: "Harness.openSession",
|
|
23824
|
+
kind: "async"
|
|
23825
|
+
}),
|
|
23826
|
+
contextEvent: channel({
|
|
23827
|
+
channelName: "context.event",
|
|
23828
|
+
kind: "sync-stream"
|
|
23829
|
+
}),
|
|
23830
|
+
prompt: channel({
|
|
23831
|
+
channelName: "session.prompt",
|
|
23832
|
+
kind: "async"
|
|
23833
|
+
}),
|
|
23834
|
+
skill: channel({
|
|
23835
|
+
channelName: "session.skill",
|
|
23836
|
+
kind: "async"
|
|
23837
|
+
}),
|
|
23838
|
+
task: channel({
|
|
23839
|
+
channelName: "session.task",
|
|
23840
|
+
kind: "async"
|
|
23841
|
+
}),
|
|
23842
|
+
compact: channel({
|
|
23843
|
+
channelName: "session.compact",
|
|
23844
|
+
kind: "async"
|
|
23845
|
+
})
|
|
23846
|
+
});
|
|
23847
|
+
|
|
23848
|
+
// src/wrappers/flue.ts
|
|
23849
|
+
var WRAPPED_FLUE_CONTEXT = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-context");
|
|
23850
|
+
var WRAPPED_FLUE_HARNESS = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-harness");
|
|
23851
|
+
var WRAPPED_FLUE_SESSION = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-session");
|
|
23852
|
+
var SUBSCRIBED_FLUE_CONTEXT_EVENTS = /* @__PURE__ */ Symbol.for(
|
|
23853
|
+
"braintrust.flue.subscribed-context-events"
|
|
23854
|
+
);
|
|
23855
|
+
function wrapFlueContext(ctx) {
|
|
23856
|
+
if (!isPlausibleFlueContext(ctx)) {
|
|
23857
|
+
console.warn("Unsupported Flue context. Not wrapping.");
|
|
23858
|
+
return ctx;
|
|
23859
|
+
}
|
|
23860
|
+
const context = ctx;
|
|
23861
|
+
subscribeFlueContextEvents(context, { captureTurnSpans: true });
|
|
23862
|
+
return patchFlueContextInPlace(context);
|
|
23364
23863
|
}
|
|
23365
|
-
|
|
23366
|
-
|
|
23367
|
-
|
|
23368
|
-
|
|
23369
|
-
anthropicPlugin = null;
|
|
23370
|
-
aiSDKPlugin = null;
|
|
23371
|
-
claudeAgentSDKPlugin = null;
|
|
23372
|
-
cursorSDKPlugin = null;
|
|
23373
|
-
googleGenAIPlugin = null;
|
|
23374
|
-
huggingFacePlugin = null;
|
|
23375
|
-
openRouterPlugin = null;
|
|
23376
|
-
openRouterAgentPlugin = null;
|
|
23377
|
-
mistralPlugin = null;
|
|
23378
|
-
googleADKPlugin = null;
|
|
23379
|
-
coherePlugin = null;
|
|
23380
|
-
groqPlugin = null;
|
|
23381
|
-
genkitPlugin = null;
|
|
23382
|
-
gitHubCopilotPlugin = null;
|
|
23383
|
-
constructor(config = {}) {
|
|
23384
|
-
super();
|
|
23385
|
-
this.config = config;
|
|
23864
|
+
function patchFlueContextInPlace(ctx) {
|
|
23865
|
+
const context = ctx;
|
|
23866
|
+
if (context[WRAPPED_FLUE_CONTEXT]) {
|
|
23867
|
+
return ctx;
|
|
23386
23868
|
}
|
|
23387
|
-
|
|
23388
|
-
|
|
23389
|
-
|
|
23390
|
-
|
|
23391
|
-
|
|
23869
|
+
const originalInit = context.init.bind(context);
|
|
23870
|
+
try {
|
|
23871
|
+
Object.defineProperty(context, WRAPPED_FLUE_CONTEXT, {
|
|
23872
|
+
configurable: false,
|
|
23873
|
+
enumerable: false,
|
|
23874
|
+
value: true
|
|
23875
|
+
});
|
|
23876
|
+
Object.defineProperty(context, "init", {
|
|
23877
|
+
configurable: true,
|
|
23878
|
+
value: async function wrappedFlueInit(options) {
|
|
23879
|
+
const harness = await originalInit(options);
|
|
23880
|
+
return wrapFlueHarness(harness);
|
|
23881
|
+
},
|
|
23882
|
+
writable: true
|
|
23883
|
+
});
|
|
23884
|
+
} catch {
|
|
23885
|
+
}
|
|
23886
|
+
return ctx;
|
|
23887
|
+
}
|
|
23888
|
+
function wrapFlueSession(session) {
|
|
23889
|
+
if (!isPlausibleFlueSession(session)) {
|
|
23890
|
+
console.warn("Unsupported Flue session. Not wrapping.");
|
|
23891
|
+
return session;
|
|
23892
|
+
}
|
|
23893
|
+
return patchFlueSessionInPlace(session);
|
|
23894
|
+
}
|
|
23895
|
+
function subscribeFlueContextEvents(ctx, options = {}) {
|
|
23896
|
+
if (!ctx || typeof ctx !== "object" || typeof ctx.subscribeEvent !== "function") {
|
|
23897
|
+
return void 0;
|
|
23898
|
+
}
|
|
23899
|
+
const context = ctx;
|
|
23900
|
+
const captureTurnSpans = options.captureTurnSpans ?? true;
|
|
23901
|
+
const existingSubscription = context[SUBSCRIBED_FLUE_CONTEXT_EVENTS];
|
|
23902
|
+
if (existingSubscription) {
|
|
23903
|
+
if (existingSubscription.captureTurnSpans || !captureTurnSpans) {
|
|
23904
|
+
return void 0;
|
|
23392
23905
|
}
|
|
23393
|
-
|
|
23394
|
-
|
|
23395
|
-
|
|
23906
|
+
try {
|
|
23907
|
+
existingSubscription.unsubscribe();
|
|
23908
|
+
} catch {
|
|
23909
|
+
}
|
|
23910
|
+
}
|
|
23911
|
+
try {
|
|
23912
|
+
const unsubscribe = ctx.subscribeEvent((event) => {
|
|
23913
|
+
flueChannels.contextEvent.traceSync(() => void 0, {
|
|
23914
|
+
arguments: [event],
|
|
23915
|
+
captureTurnSpans,
|
|
23916
|
+
context: ctx
|
|
23917
|
+
});
|
|
23918
|
+
});
|
|
23919
|
+
if (existingSubscription) {
|
|
23920
|
+
existingSubscription.captureTurnSpans = captureTurnSpans;
|
|
23921
|
+
existingSubscription.unsubscribe = unsubscribe;
|
|
23922
|
+
} else {
|
|
23923
|
+
Object.defineProperty(context, SUBSCRIBED_FLUE_CONTEXT_EVENTS, {
|
|
23924
|
+
configurable: false,
|
|
23925
|
+
enumerable: false,
|
|
23926
|
+
value: {
|
|
23927
|
+
captureTurnSpans,
|
|
23928
|
+
unsubscribe
|
|
23929
|
+
}
|
|
23930
|
+
});
|
|
23931
|
+
}
|
|
23932
|
+
return unsubscribe;
|
|
23933
|
+
} catch {
|
|
23934
|
+
return void 0;
|
|
23935
|
+
}
|
|
23936
|
+
}
|
|
23937
|
+
function wrapFlueHarness(harness) {
|
|
23938
|
+
if (!isPlausibleFlueHarness(harness)) {
|
|
23939
|
+
return harness;
|
|
23940
|
+
}
|
|
23941
|
+
const target = harness;
|
|
23942
|
+
if (target[WRAPPED_FLUE_HARNESS]) {
|
|
23943
|
+
return harness;
|
|
23944
|
+
}
|
|
23945
|
+
const originalSession = target.session.bind(target);
|
|
23946
|
+
try {
|
|
23947
|
+
Object.defineProperty(target, WRAPPED_FLUE_HARNESS, {
|
|
23948
|
+
configurable: false,
|
|
23949
|
+
enumerable: false,
|
|
23950
|
+
value: true
|
|
23951
|
+
});
|
|
23952
|
+
Object.defineProperty(target, "session", {
|
|
23953
|
+
configurable: true,
|
|
23954
|
+
value: async function wrappedFlueHarnessSession(name, options) {
|
|
23955
|
+
const session = await originalSession(name, options);
|
|
23956
|
+
return patchFlueSessionInPlace(session);
|
|
23957
|
+
},
|
|
23958
|
+
writable: true
|
|
23959
|
+
});
|
|
23960
|
+
const sessions = target.sessions;
|
|
23961
|
+
if (sessions && typeof sessions === "object") {
|
|
23962
|
+
patchFlueSessionFactory(sessions, "get");
|
|
23963
|
+
patchFlueSessionFactory(sessions, "create");
|
|
23964
|
+
}
|
|
23965
|
+
} catch {
|
|
23966
|
+
}
|
|
23967
|
+
return harness;
|
|
23968
|
+
}
|
|
23969
|
+
function patchFlueSessionInPlace(session) {
|
|
23970
|
+
if (session[WRAPPED_FLUE_SESSION]) {
|
|
23971
|
+
return session;
|
|
23972
|
+
}
|
|
23973
|
+
try {
|
|
23974
|
+
Object.defineProperty(session, WRAPPED_FLUE_SESSION, {
|
|
23975
|
+
configurable: false,
|
|
23976
|
+
enumerable: false,
|
|
23977
|
+
value: true
|
|
23978
|
+
});
|
|
23979
|
+
patchCallHandleMethod(session, "prompt", flueChannels.prompt);
|
|
23980
|
+
patchCallHandleMethod(session, "skill", flueChannels.skill);
|
|
23981
|
+
patchCallHandleMethod(session, "task", flueChannels.task);
|
|
23982
|
+
patchCompact(session);
|
|
23983
|
+
} catch {
|
|
23984
|
+
}
|
|
23985
|
+
return session;
|
|
23986
|
+
}
|
|
23987
|
+
function patchFlueSessionFactory(sessions, method) {
|
|
23988
|
+
const original = sessions[method];
|
|
23989
|
+
if (typeof original !== "function") {
|
|
23990
|
+
return;
|
|
23991
|
+
}
|
|
23992
|
+
const bound = original.bind(sessions);
|
|
23993
|
+
Object.defineProperty(sessions, method, {
|
|
23994
|
+
configurable: true,
|
|
23995
|
+
value: async function wrappedFlueSessionFactory(name, options) {
|
|
23996
|
+
const session = await bound(name, options);
|
|
23997
|
+
return patchFlueSessionInPlace(session);
|
|
23998
|
+
},
|
|
23999
|
+
writable: true
|
|
24000
|
+
});
|
|
24001
|
+
}
|
|
24002
|
+
function patchCallHandleMethod(session, method, channel2) {
|
|
24003
|
+
const original = session[method];
|
|
24004
|
+
if (typeof original !== "function") {
|
|
24005
|
+
return;
|
|
24006
|
+
}
|
|
24007
|
+
const bound = original.bind(session);
|
|
24008
|
+
Object.defineProperty(session, method, {
|
|
24009
|
+
configurable: true,
|
|
24010
|
+
value(input, options) {
|
|
24011
|
+
const args = [input, options];
|
|
24012
|
+
const { originalResult, traced: traced2 } = traceFlueOperation(channel2, {
|
|
24013
|
+
context: {
|
|
24014
|
+
arguments: args,
|
|
24015
|
+
operation: method,
|
|
24016
|
+
session
|
|
24017
|
+
},
|
|
24018
|
+
run: () => bound(input, options)
|
|
24019
|
+
});
|
|
24020
|
+
return preserveCallHandle(originalResult, traced2);
|
|
24021
|
+
},
|
|
24022
|
+
writable: true
|
|
24023
|
+
});
|
|
24024
|
+
}
|
|
24025
|
+
function patchCompact(session) {
|
|
24026
|
+
const original = session.compact;
|
|
24027
|
+
if (typeof original !== "function") {
|
|
24028
|
+
return;
|
|
24029
|
+
}
|
|
24030
|
+
const bound = original.bind(session);
|
|
24031
|
+
Object.defineProperty(session, "compact", {
|
|
24032
|
+
configurable: true,
|
|
24033
|
+
value() {
|
|
24034
|
+
const context = {
|
|
24035
|
+
arguments: [],
|
|
24036
|
+
operation: "compact",
|
|
24037
|
+
session
|
|
24038
|
+
};
|
|
24039
|
+
return flueChannels.compact.tracePromise(() => bound(), context);
|
|
24040
|
+
},
|
|
24041
|
+
writable: true
|
|
24042
|
+
});
|
|
24043
|
+
}
|
|
24044
|
+
function traceFlueOperation(channel2, args) {
|
|
24045
|
+
const tracingChannel2 = channel2.tracingChannel();
|
|
24046
|
+
const context = args.context;
|
|
24047
|
+
let originalResult;
|
|
24048
|
+
let traced2;
|
|
24049
|
+
const run = () => {
|
|
24050
|
+
try {
|
|
24051
|
+
originalResult = args.run();
|
|
24052
|
+
tracingChannel2.end?.publish(context);
|
|
24053
|
+
} catch (error) {
|
|
24054
|
+
context.error = normalizeError3(error);
|
|
24055
|
+
tracingChannel2.error?.publish(context);
|
|
24056
|
+
tracingChannel2.end?.publish(context);
|
|
24057
|
+
throw error;
|
|
24058
|
+
}
|
|
24059
|
+
traced2 = Promise.resolve(originalResult).then(
|
|
24060
|
+
(result) => {
|
|
24061
|
+
context.result = result;
|
|
24062
|
+
tracingChannel2.asyncStart?.publish(context);
|
|
24063
|
+
tracingChannel2.asyncEnd?.publish(context);
|
|
24064
|
+
return result;
|
|
24065
|
+
},
|
|
24066
|
+
(error) => {
|
|
24067
|
+
context.error = normalizeError3(error);
|
|
24068
|
+
tracingChannel2.error?.publish(context);
|
|
24069
|
+
tracingChannel2.asyncStart?.publish(context);
|
|
24070
|
+
tracingChannel2.asyncEnd?.publish(context);
|
|
24071
|
+
throw error;
|
|
24072
|
+
}
|
|
24073
|
+
);
|
|
24074
|
+
};
|
|
24075
|
+
if (tracingChannel2.start?.runStores) {
|
|
24076
|
+
tracingChannel2.start.runStores(context, run);
|
|
24077
|
+
} else {
|
|
24078
|
+
tracingChannel2.start?.publish(context);
|
|
24079
|
+
run();
|
|
24080
|
+
}
|
|
24081
|
+
return { originalResult, traced: traced2 };
|
|
24082
|
+
}
|
|
24083
|
+
function normalizeError3(error) {
|
|
24084
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
24085
|
+
}
|
|
24086
|
+
function preserveCallHandle(originalHandle, traced2) {
|
|
24087
|
+
if (!isFlueCallHandle(originalHandle)) {
|
|
24088
|
+
return traced2;
|
|
24089
|
+
}
|
|
24090
|
+
const handle = originalHandle;
|
|
24091
|
+
const wrapped = {
|
|
24092
|
+
get signal() {
|
|
24093
|
+
return handle.signal;
|
|
24094
|
+
},
|
|
24095
|
+
abort(reason) {
|
|
24096
|
+
return handle.abort(reason);
|
|
24097
|
+
},
|
|
24098
|
+
then(onfulfilled, onrejected) {
|
|
24099
|
+
return traced2.then(onfulfilled, onrejected);
|
|
24100
|
+
}
|
|
24101
|
+
};
|
|
24102
|
+
return wrapped;
|
|
24103
|
+
}
|
|
24104
|
+
function isPlausibleFlueContext(value) {
|
|
24105
|
+
return !!value && typeof value === "object" && typeof value.init === "function";
|
|
24106
|
+
}
|
|
24107
|
+
function isPlausibleFlueHarness(value) {
|
|
24108
|
+
return !!value && typeof value === "object" && typeof value.session === "function";
|
|
24109
|
+
}
|
|
24110
|
+
function isPlausibleFlueSession(value) {
|
|
24111
|
+
return !!value && typeof value === "object" && typeof value.prompt === "function" && typeof value.skill === "function" && typeof value.task === "function" && typeof value.compact === "function";
|
|
24112
|
+
}
|
|
24113
|
+
function isFlueCallHandle(value) {
|
|
24114
|
+
return !!value && typeof value === "object" && typeof value.then === "function" && typeof value.abort === "function" && "signal" in value;
|
|
24115
|
+
}
|
|
24116
|
+
|
|
24117
|
+
// src/instrumentation/plugins/flue-plugin.ts
|
|
24118
|
+
var FluePlugin = class extends BasePlugin {
|
|
24119
|
+
activeOperationsById = /* @__PURE__ */ new Map();
|
|
24120
|
+
activeOperationsByScope = /* @__PURE__ */ new Map();
|
|
24121
|
+
compactionsByScope = /* @__PURE__ */ new Map();
|
|
24122
|
+
pendingOperationsByKey = /* @__PURE__ */ new Map();
|
|
24123
|
+
tasksById = /* @__PURE__ */ new Map();
|
|
24124
|
+
toolsById = /* @__PURE__ */ new Map();
|
|
24125
|
+
turnsByScope = /* @__PURE__ */ new Map();
|
|
24126
|
+
onEnable() {
|
|
24127
|
+
this.subscribeToContextCreation();
|
|
24128
|
+
this.subscribeToSessionCreation();
|
|
24129
|
+
this.subscribeToContextEvents();
|
|
24130
|
+
this.subscribeToSessionOperations();
|
|
24131
|
+
}
|
|
24132
|
+
onDisable() {
|
|
24133
|
+
for (const unsubscribe of this.unsubscribers) {
|
|
24134
|
+
unsubscribe();
|
|
24135
|
+
}
|
|
24136
|
+
this.unsubscribers = [];
|
|
24137
|
+
this.activeOperationsById.clear();
|
|
24138
|
+
this.activeOperationsByScope.clear();
|
|
24139
|
+
this.compactionsByScope.clear();
|
|
24140
|
+
this.pendingOperationsByKey.clear();
|
|
24141
|
+
this.tasksById.clear();
|
|
24142
|
+
this.toolsById.clear();
|
|
24143
|
+
this.turnsByScope.clear();
|
|
24144
|
+
}
|
|
24145
|
+
subscribeToContextCreation() {
|
|
24146
|
+
const channel2 = flueChannels.createContext.tracingChannel();
|
|
24147
|
+
const handlers = {
|
|
24148
|
+
end: (event) => {
|
|
24149
|
+
const ctx = event.result;
|
|
24150
|
+
if (!ctx) {
|
|
24151
|
+
return;
|
|
24152
|
+
}
|
|
24153
|
+
subscribeFlueContextEvents(ctx, { captureTurnSpans: false });
|
|
24154
|
+
patchFlueContextInPlace(ctx);
|
|
24155
|
+
},
|
|
24156
|
+
error: () => {
|
|
24157
|
+
}
|
|
24158
|
+
};
|
|
24159
|
+
channel2.subscribe(handlers);
|
|
24160
|
+
this.unsubscribers.push(() => {
|
|
24161
|
+
channel2.unsubscribe(handlers);
|
|
24162
|
+
});
|
|
24163
|
+
}
|
|
24164
|
+
subscribeToSessionCreation() {
|
|
24165
|
+
const channel2 = flueChannels.openSession.tracingChannel();
|
|
24166
|
+
const handlers = {
|
|
24167
|
+
asyncEnd: (event) => {
|
|
24168
|
+
if (event.result) {
|
|
24169
|
+
patchFlueSessionInPlace(
|
|
24170
|
+
event.result
|
|
24171
|
+
);
|
|
24172
|
+
}
|
|
24173
|
+
if (event.harness) {
|
|
24174
|
+
wrapFlueHarness(event.harness);
|
|
24175
|
+
}
|
|
24176
|
+
},
|
|
24177
|
+
error: () => {
|
|
24178
|
+
}
|
|
24179
|
+
};
|
|
24180
|
+
channel2.subscribe(handlers);
|
|
24181
|
+
this.unsubscribers.push(() => {
|
|
24182
|
+
channel2.unsubscribe(handlers);
|
|
24183
|
+
});
|
|
24184
|
+
}
|
|
24185
|
+
subscribeToSessionOperations() {
|
|
24186
|
+
this.subscribeToSessionOperation(flueChannels.prompt);
|
|
24187
|
+
this.subscribeToSessionOperation(flueChannels.skill);
|
|
24188
|
+
this.subscribeToSessionOperation(flueChannels.task);
|
|
24189
|
+
this.subscribeToCompact();
|
|
24190
|
+
}
|
|
24191
|
+
subscribeToSessionOperation(channel2) {
|
|
24192
|
+
const tracingChannel2 = channel2.tracingChannel();
|
|
24193
|
+
const states = /* @__PURE__ */ new WeakMap();
|
|
24194
|
+
const ensureState2 = (event) => {
|
|
24195
|
+
const existing = states.get(event);
|
|
24196
|
+
if (existing) {
|
|
24197
|
+
return existing;
|
|
24198
|
+
}
|
|
24199
|
+
const state = this.startOperationState({
|
|
24200
|
+
args: event.arguments,
|
|
24201
|
+
moduleVersion: typeof event.moduleVersion === "string" ? event.moduleVersion : void 0,
|
|
24202
|
+
operation: event.operation,
|
|
24203
|
+
session: event.session
|
|
24204
|
+
});
|
|
24205
|
+
states.set(event, state);
|
|
24206
|
+
return state;
|
|
24207
|
+
};
|
|
24208
|
+
const unbindCurrentSpanStore = this.bindCurrentSpanStoreToOperationStart(
|
|
24209
|
+
tracingChannel2,
|
|
24210
|
+
ensureState2
|
|
24211
|
+
);
|
|
24212
|
+
const handlers = {
|
|
24213
|
+
start: (event) => {
|
|
24214
|
+
ensureState2(event);
|
|
24215
|
+
},
|
|
24216
|
+
asyncEnd: (event) => {
|
|
24217
|
+
this.endOperationState(states.get(event), event.result);
|
|
24218
|
+
states.delete(event);
|
|
24219
|
+
},
|
|
24220
|
+
error: (event) => {
|
|
24221
|
+
const state = states.get(event);
|
|
24222
|
+
if (state && event.error) {
|
|
24223
|
+
safeLog3(state.span, { error: errorToString(event.error) });
|
|
24224
|
+
this.finishOperationState(state);
|
|
24225
|
+
}
|
|
24226
|
+
states.delete(event);
|
|
24227
|
+
}
|
|
24228
|
+
};
|
|
24229
|
+
tracingChannel2.subscribe(handlers);
|
|
24230
|
+
this.unsubscribers.push(() => {
|
|
24231
|
+
unbindCurrentSpanStore?.();
|
|
24232
|
+
tracingChannel2.unsubscribe(handlers);
|
|
24233
|
+
});
|
|
24234
|
+
}
|
|
24235
|
+
subscribeToCompact() {
|
|
24236
|
+
const tracingChannel2 = flueChannels.compact.tracingChannel();
|
|
24237
|
+
const states = /* @__PURE__ */ new WeakMap();
|
|
24238
|
+
const ensureState2 = (event) => {
|
|
24239
|
+
const existing = states.get(event);
|
|
24240
|
+
if (existing) {
|
|
24241
|
+
return existing;
|
|
24242
|
+
}
|
|
24243
|
+
const state = this.startOperationState({
|
|
24244
|
+
args: [],
|
|
24245
|
+
moduleVersion: typeof event.moduleVersion === "string" ? event.moduleVersion : void 0,
|
|
24246
|
+
operation: event.operation,
|
|
24247
|
+
session: event.session
|
|
24248
|
+
});
|
|
24249
|
+
states.set(event, state);
|
|
24250
|
+
return state;
|
|
24251
|
+
};
|
|
24252
|
+
const unbindCurrentSpanStore = this.bindCurrentSpanStoreToOperationStart(
|
|
24253
|
+
tracingChannel2,
|
|
24254
|
+
ensureState2
|
|
24255
|
+
);
|
|
24256
|
+
const handlers = {
|
|
24257
|
+
start: (event) => {
|
|
24258
|
+
ensureState2(event);
|
|
24259
|
+
},
|
|
24260
|
+
asyncEnd: (event) => {
|
|
24261
|
+
this.endOperationState(states.get(event), void 0);
|
|
24262
|
+
states.delete(event);
|
|
24263
|
+
},
|
|
24264
|
+
error: (event) => {
|
|
24265
|
+
const state = states.get(event);
|
|
24266
|
+
if (state && event.error) {
|
|
24267
|
+
safeLog3(state.span, { error: errorToString(event.error) });
|
|
24268
|
+
this.finishOperationState(state);
|
|
24269
|
+
}
|
|
24270
|
+
states.delete(event);
|
|
24271
|
+
}
|
|
24272
|
+
};
|
|
24273
|
+
tracingChannel2.subscribe(handlers);
|
|
24274
|
+
this.unsubscribers.push(() => {
|
|
24275
|
+
unbindCurrentSpanStore?.();
|
|
24276
|
+
tracingChannel2.unsubscribe(handlers);
|
|
24277
|
+
});
|
|
24278
|
+
}
|
|
24279
|
+
subscribeToContextEvents() {
|
|
24280
|
+
const channel2 = flueChannels.contextEvent.tracingChannel();
|
|
24281
|
+
const handlers = {
|
|
24282
|
+
start: (event) => {
|
|
24283
|
+
const flueEvent = event.arguments[0];
|
|
24284
|
+
if (!flueEvent) {
|
|
24285
|
+
return;
|
|
24286
|
+
}
|
|
24287
|
+
try {
|
|
24288
|
+
this.handleFlueEvent(flueEvent, {
|
|
24289
|
+
captureTurnSpans: event.captureTurnSpans !== false
|
|
24290
|
+
});
|
|
24291
|
+
} catch (error) {
|
|
24292
|
+
logInstrumentationError3("Flue event", error);
|
|
24293
|
+
}
|
|
24294
|
+
},
|
|
24295
|
+
error: () => {
|
|
24296
|
+
}
|
|
24297
|
+
};
|
|
24298
|
+
channel2.subscribe(handlers);
|
|
24299
|
+
this.unsubscribers.push(() => {
|
|
24300
|
+
channel2.unsubscribe(handlers);
|
|
24301
|
+
});
|
|
24302
|
+
}
|
|
24303
|
+
bindCurrentSpanStoreToOperationStart(tracingChannel2, ensureState2) {
|
|
24304
|
+
const state = _internalGetGlobalState();
|
|
24305
|
+
const startChannel = tracingChannel2.start;
|
|
24306
|
+
const contextManager = state?.contextManager;
|
|
24307
|
+
const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
|
|
24308
|
+
if (!currentSpanStore || !startChannel) {
|
|
24309
|
+
return void 0;
|
|
24310
|
+
}
|
|
24311
|
+
startChannel.bindStore(currentSpanStore, (event) => {
|
|
24312
|
+
const operationState = ensureState2(event);
|
|
24313
|
+
return contextManager.wrapSpanForStore(operationState.span);
|
|
24314
|
+
});
|
|
24315
|
+
return () => {
|
|
24316
|
+
startChannel.unbindStore(currentSpanStore);
|
|
24317
|
+
};
|
|
24318
|
+
}
|
|
24319
|
+
startOperationState(args) {
|
|
24320
|
+
const sessionName = getSessionName(args.session);
|
|
24321
|
+
const metadata = {
|
|
24322
|
+
...extractOperationInputMetadata(args.operation, args.args),
|
|
24323
|
+
...extractSessionMetadata(args.session),
|
|
24324
|
+
"flue.operation": args.operation,
|
|
24325
|
+
provider: "flue",
|
|
24326
|
+
...args.moduleVersion ? { "flue.version": args.moduleVersion } : {}
|
|
24327
|
+
};
|
|
24328
|
+
const span = startSpan({
|
|
24329
|
+
name: `flue.session.${args.operation}`,
|
|
24330
|
+
spanAttributes: { type: "task" /* TASK */ }
|
|
24331
|
+
});
|
|
24332
|
+
const state = {
|
|
24333
|
+
metadata,
|
|
24334
|
+
operation: args.operation,
|
|
24335
|
+
sessionName,
|
|
24336
|
+
span,
|
|
24337
|
+
startTime: getCurrentUnixTimestamp()
|
|
24338
|
+
};
|
|
24339
|
+
safeLog3(span, {
|
|
24340
|
+
input: extractOperationInput(args.operation, args.args),
|
|
24341
|
+
metadata
|
|
24342
|
+
});
|
|
24343
|
+
this.pendingOperationQueue(operationKey(sessionName, args.operation)).push(
|
|
24344
|
+
state
|
|
24345
|
+
);
|
|
24346
|
+
addOperationToScope(
|
|
24347
|
+
this.activeOperationsByScope,
|
|
24348
|
+
sessionName ?? "unknown",
|
|
24349
|
+
state
|
|
24350
|
+
);
|
|
24351
|
+
return state;
|
|
24352
|
+
}
|
|
24353
|
+
endOperationState(state, result) {
|
|
24354
|
+
if (!state) {
|
|
24355
|
+
return;
|
|
24356
|
+
}
|
|
24357
|
+
const metadata = {
|
|
24358
|
+
...state.metadata,
|
|
24359
|
+
...extractPromptResponseMetadata(result)
|
|
24360
|
+
};
|
|
24361
|
+
const metrics = {
|
|
24362
|
+
...buildDurationMetrics3(state.startTime),
|
|
24363
|
+
...metricsFromUsage(result?.usage)
|
|
24364
|
+
};
|
|
24365
|
+
safeLog3(state.span, {
|
|
24366
|
+
metadata,
|
|
24367
|
+
metrics,
|
|
24368
|
+
output: extractOperationOutput(result)
|
|
24369
|
+
});
|
|
24370
|
+
this.finishCompactionsForOperation(state);
|
|
24371
|
+
this.finishOperationState(state);
|
|
24372
|
+
}
|
|
24373
|
+
finishOperationState(state) {
|
|
24374
|
+
removePendingOperation(this.pendingOperationsByKey, state);
|
|
24375
|
+
if (state.operationId) {
|
|
24376
|
+
this.activeOperationsById.delete(state.operationId);
|
|
24377
|
+
}
|
|
24378
|
+
removeScopedOperation(this.activeOperationsByScope, state);
|
|
24379
|
+
state.span.end();
|
|
24380
|
+
}
|
|
24381
|
+
handleFlueEvent(event, options) {
|
|
24382
|
+
switch (event.type) {
|
|
24383
|
+
case "operation_start":
|
|
24384
|
+
this.handleOperationStart(event);
|
|
24385
|
+
return;
|
|
24386
|
+
case "operation":
|
|
24387
|
+
this.handleOperation(event);
|
|
24388
|
+
return;
|
|
24389
|
+
case "text_delta":
|
|
24390
|
+
if (!options.captureTurnSpans) {
|
|
24391
|
+
return;
|
|
24392
|
+
}
|
|
24393
|
+
this.ensureTurnState(event).text.push(
|
|
24394
|
+
typeof event.text === "string" ? event.text : ""
|
|
24395
|
+
);
|
|
24396
|
+
return;
|
|
24397
|
+
case "thinking_start":
|
|
24398
|
+
if (!options.captureTurnSpans) {
|
|
24399
|
+
return;
|
|
24400
|
+
}
|
|
24401
|
+
this.handleThinkingStart(event);
|
|
24402
|
+
return;
|
|
24403
|
+
case "thinking_delta":
|
|
24404
|
+
if (!options.captureTurnSpans) {
|
|
24405
|
+
return;
|
|
24406
|
+
}
|
|
24407
|
+
this.handleThinkingDelta(event);
|
|
24408
|
+
return;
|
|
24409
|
+
case "thinking_end":
|
|
24410
|
+
if (!options.captureTurnSpans) {
|
|
24411
|
+
return;
|
|
24412
|
+
}
|
|
24413
|
+
this.handleThinkingEnd(event);
|
|
24414
|
+
return;
|
|
24415
|
+
case "turn":
|
|
24416
|
+
if (!options.captureTurnSpans) {
|
|
24417
|
+
return;
|
|
24418
|
+
}
|
|
24419
|
+
this.handleTurn(event);
|
|
24420
|
+
return;
|
|
24421
|
+
case "tool_start":
|
|
24422
|
+
this.handleToolStart(event, options);
|
|
24423
|
+
return;
|
|
24424
|
+
case "tool_call":
|
|
24425
|
+
this.handleToolCall(event);
|
|
24426
|
+
return;
|
|
24427
|
+
case "task_start":
|
|
24428
|
+
this.handleTaskStart(event);
|
|
24429
|
+
return;
|
|
24430
|
+
case "task":
|
|
24431
|
+
this.handleTask(event);
|
|
24432
|
+
return;
|
|
24433
|
+
case "compaction_start":
|
|
24434
|
+
this.handleCompactionStart(event);
|
|
24435
|
+
return;
|
|
24436
|
+
case "compaction":
|
|
24437
|
+
this.handleCompaction(event);
|
|
24438
|
+
return;
|
|
24439
|
+
default:
|
|
24440
|
+
return;
|
|
24441
|
+
}
|
|
24442
|
+
}
|
|
24443
|
+
handleOperationStart(event) {
|
|
24444
|
+
if (!isInstrumentedOperation(event.operationKind)) {
|
|
24445
|
+
return;
|
|
24446
|
+
}
|
|
24447
|
+
const state = this.takePendingOperationForEvent(event);
|
|
24448
|
+
if (!state) {
|
|
24449
|
+
return;
|
|
24450
|
+
}
|
|
24451
|
+
state.operationId = event.operationId;
|
|
24452
|
+
this.activeOperationsById.set(event.operationId, state);
|
|
24453
|
+
addScopedOperation(this.activeOperationsByScope, event, state);
|
|
24454
|
+
state.metadata = {
|
|
24455
|
+
...state.metadata,
|
|
24456
|
+
...extractEventMetadata(event),
|
|
24457
|
+
"flue.operation_id": event.operationId
|
|
24458
|
+
};
|
|
24459
|
+
safeLog3(state.span, { metadata: state.metadata });
|
|
24460
|
+
}
|
|
24461
|
+
handleOperation(event) {
|
|
24462
|
+
const state = event.operationId ? this.activeOperationsById.get(event.operationId) : void 0;
|
|
24463
|
+
if (!state) {
|
|
24464
|
+
return;
|
|
24465
|
+
}
|
|
24466
|
+
const metadata = {
|
|
24467
|
+
...state.metadata,
|
|
24468
|
+
...extractEventMetadata(event),
|
|
24469
|
+
...typeof event.durationMs === "number" ? { "flue.duration_ms": event.durationMs } : {},
|
|
24470
|
+
...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
|
|
24471
|
+
};
|
|
24472
|
+
const metrics = metricsFromUsage(event.usage);
|
|
24473
|
+
safeLog3(state.span, {
|
|
24474
|
+
...event.error ? { error: errorToString(event.error) } : {},
|
|
24475
|
+
metadata,
|
|
24476
|
+
...Object.keys(metrics).length ? { metrics } : {}
|
|
24477
|
+
});
|
|
24478
|
+
}
|
|
24479
|
+
ensureTurnState(event) {
|
|
24480
|
+
const scope = scopeKey(event);
|
|
24481
|
+
const existing = this.turnsByScope.get(scope);
|
|
24482
|
+
if (existing) {
|
|
24483
|
+
return existing;
|
|
24484
|
+
}
|
|
24485
|
+
const parent = this.parentSpanForEvent(event);
|
|
24486
|
+
const metadata = {
|
|
24487
|
+
...extractEventMetadata(event),
|
|
24488
|
+
provider: "flue"
|
|
24489
|
+
};
|
|
24490
|
+
const span = startFlueSpan(parent, {
|
|
24491
|
+
name: "flue.turn",
|
|
24492
|
+
spanAttributes: { type: "llm" /* LLM */ }
|
|
24493
|
+
});
|
|
24494
|
+
const state = {
|
|
24495
|
+
metadata,
|
|
24496
|
+
span,
|
|
24497
|
+
hasThinking: false,
|
|
24498
|
+
startTime: getCurrentUnixTimestamp(),
|
|
24499
|
+
text: [],
|
|
24500
|
+
thinking: [],
|
|
24501
|
+
toolCalls: []
|
|
24502
|
+
};
|
|
24503
|
+
safeLog3(span, { metadata });
|
|
24504
|
+
this.turnsByScope.set(scope, state);
|
|
24505
|
+
return state;
|
|
24506
|
+
}
|
|
24507
|
+
handleTurn(event) {
|
|
24508
|
+
const scope = scopeKey(event);
|
|
24509
|
+
const state = this.ensureTurnState(event);
|
|
24510
|
+
const text = state.text.join("");
|
|
24511
|
+
const reasoning = state.finalThinking ?? state.thinking.join("");
|
|
24512
|
+
const outputReasoning = reasoning || (state.hasThinking ? "[reasoning stream present; content unavailable]" : void 0);
|
|
24513
|
+
const metadata = {
|
|
24514
|
+
...state.metadata,
|
|
24515
|
+
...extractEventMetadata(event),
|
|
24516
|
+
...event.model ? { model: event.model, "flue.model": event.model } : {},
|
|
24517
|
+
...event.stopReason ? { "flue.stop_reason": event.stopReason } : {},
|
|
24518
|
+
...event.isError !== void 0 ? { "flue.is_error": event.isError } : {},
|
|
24519
|
+
provider: "flue"
|
|
24520
|
+
};
|
|
24521
|
+
safeLog3(state.span, {
|
|
24522
|
+
...event.error ? { error: errorToString(event.error) } : {},
|
|
24523
|
+
metadata,
|
|
24524
|
+
metrics: {
|
|
24525
|
+
...durationMsMetrics(event.durationMs),
|
|
24526
|
+
...metricsFromUsage(event.usage)
|
|
24527
|
+
},
|
|
24528
|
+
output: toAssistantOutput(
|
|
24529
|
+
text,
|
|
24530
|
+
event.stopReason,
|
|
24531
|
+
outputReasoning,
|
|
24532
|
+
state.toolCalls
|
|
24533
|
+
)
|
|
24534
|
+
});
|
|
24535
|
+
state.span.end();
|
|
24536
|
+
this.turnsByScope.delete(scope);
|
|
24537
|
+
}
|
|
24538
|
+
handleThinkingDelta(event) {
|
|
24539
|
+
const delta = event.delta;
|
|
24540
|
+
if (typeof delta !== "string" || !delta) {
|
|
24541
|
+
return;
|
|
24542
|
+
}
|
|
24543
|
+
const state = this.ensureTurnState(event);
|
|
24544
|
+
state.hasThinking = true;
|
|
24545
|
+
state.metadata["flue.thinking"] = true;
|
|
24546
|
+
state.thinking.push(delta);
|
|
24547
|
+
}
|
|
24548
|
+
handleThinkingStart(event) {
|
|
24549
|
+
const state = this.ensureTurnState(event);
|
|
24550
|
+
state.hasThinking = true;
|
|
24551
|
+
state.metadata["flue.thinking"] = true;
|
|
24552
|
+
}
|
|
24553
|
+
handleThinkingEnd(event) {
|
|
24554
|
+
const state = this.ensureTurnState(event);
|
|
24555
|
+
state.hasThinking = true;
|
|
24556
|
+
state.metadata["flue.thinking"] = true;
|
|
24557
|
+
if (typeof event.content === "string" && event.content) {
|
|
24558
|
+
state.finalThinking = event.content;
|
|
24559
|
+
}
|
|
24560
|
+
}
|
|
24561
|
+
handleToolStart(event, options) {
|
|
24562
|
+
const toolCallId = event.toolCallId;
|
|
24563
|
+
if (!toolCallId) {
|
|
24564
|
+
return;
|
|
24565
|
+
}
|
|
24566
|
+
const parent = this.parentSpanForEvent(event);
|
|
24567
|
+
const scope = scopeKey(event);
|
|
24568
|
+
let turnState = this.turnsByScope.get(scope);
|
|
24569
|
+
if (!turnState && parent && options.captureTurnSpans) {
|
|
24570
|
+
turnState = this.ensureTurnState(event);
|
|
24571
|
+
}
|
|
24572
|
+
const metadata = {
|
|
24573
|
+
...extractEventMetadata(event),
|
|
24574
|
+
...event.toolName ? { "flue.tool_name": event.toolName } : {},
|
|
24575
|
+
"flue.tool_call_id": toolCallId,
|
|
24576
|
+
provider: "flue"
|
|
24577
|
+
};
|
|
24578
|
+
const span = startFlueSpan(parent, {
|
|
24579
|
+
name: `tool: ${event.toolName ?? "unknown"}`,
|
|
24580
|
+
spanAttributes: { type: "tool" /* TOOL */ }
|
|
24581
|
+
});
|
|
24582
|
+
if (turnState) {
|
|
24583
|
+
turnState.toolCalls.push({
|
|
24584
|
+
args: event.args,
|
|
24585
|
+
toolCallId,
|
|
24586
|
+
toolName: event.toolName
|
|
24587
|
+
});
|
|
24588
|
+
}
|
|
24589
|
+
safeLog3(span, {
|
|
24590
|
+
input: event.args,
|
|
24591
|
+
metadata
|
|
24592
|
+
});
|
|
24593
|
+
this.toolsById.set(toolKey(event), {
|
|
24594
|
+
metadata,
|
|
24595
|
+
span,
|
|
24596
|
+
startTime: getCurrentUnixTimestamp()
|
|
24597
|
+
});
|
|
24598
|
+
}
|
|
24599
|
+
handleToolCall(event) {
|
|
24600
|
+
const key = toolKey(event);
|
|
24601
|
+
const state = this.toolsById.get(key) ?? this.startSyntheticToolState(event, event.toolName ?? "unknown");
|
|
24602
|
+
const metadata = {
|
|
24603
|
+
...state.metadata,
|
|
24604
|
+
...extractEventMetadata(event),
|
|
24605
|
+
...event.toolName ? { "flue.tool_name": event.toolName } : {},
|
|
24606
|
+
...event.toolCallId ? { "flue.tool_call_id": event.toolCallId } : {},
|
|
24607
|
+
...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
|
|
24608
|
+
};
|
|
24609
|
+
safeLog3(state.span, {
|
|
24610
|
+
...event.isError ? { error: errorToString(event.result) } : {},
|
|
24611
|
+
metadata,
|
|
24612
|
+
metrics: durationMsMetrics(event.durationMs),
|
|
24613
|
+
output: event.result
|
|
24614
|
+
});
|
|
24615
|
+
state.span.end();
|
|
24616
|
+
this.toolsById.delete(key);
|
|
24617
|
+
}
|
|
24618
|
+
handleTaskStart(event) {
|
|
24619
|
+
const parent = this.parentSpanForEvent(event);
|
|
24620
|
+
const metadata = {
|
|
24621
|
+
...extractEventMetadata(event),
|
|
24622
|
+
...event.role ? { "flue.role": event.role } : {},
|
|
24623
|
+
...event.cwd ? { "flue.cwd": event.cwd } : {},
|
|
24624
|
+
"flue.task_id": event.taskId,
|
|
24625
|
+
provider: "flue"
|
|
24626
|
+
};
|
|
24627
|
+
const span = startFlueSpan(parent, {
|
|
24628
|
+
name: "flue.task",
|
|
24629
|
+
spanAttributes: { type: "task" /* TASK */ }
|
|
24630
|
+
});
|
|
24631
|
+
safeLog3(span, {
|
|
24632
|
+
input: event.prompt,
|
|
24633
|
+
metadata
|
|
24634
|
+
});
|
|
24635
|
+
this.tasksById.set(event.taskId, {
|
|
24636
|
+
metadata,
|
|
24637
|
+
span,
|
|
24638
|
+
startTime: getCurrentUnixTimestamp()
|
|
24639
|
+
});
|
|
24640
|
+
}
|
|
24641
|
+
handleTask(event) {
|
|
24642
|
+
const state = this.tasksById.get(event.taskId);
|
|
24643
|
+
if (!state) {
|
|
24644
|
+
return;
|
|
24645
|
+
}
|
|
24646
|
+
safeLog3(state.span, {
|
|
24647
|
+
...event.isError ? { error: errorToString(event.result) } : {},
|
|
24648
|
+
metadata: {
|
|
24649
|
+
...state.metadata,
|
|
24650
|
+
...extractEventMetadata(event),
|
|
24651
|
+
...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
|
|
24652
|
+
},
|
|
24653
|
+
metrics: durationMsMetrics(event.durationMs),
|
|
24654
|
+
output: event.result
|
|
24655
|
+
});
|
|
24656
|
+
state.span.end();
|
|
24657
|
+
this.tasksById.delete(event.taskId);
|
|
24658
|
+
}
|
|
24659
|
+
handleCompactionStart(event) {
|
|
24660
|
+
const operationState = this.operationStateForEvent(event);
|
|
24661
|
+
const parent = operationState?.span ?? this.parentSpanForEvent(event);
|
|
24662
|
+
const metadata = {
|
|
24663
|
+
...extractEventMetadata(event),
|
|
24664
|
+
...event.reason ? { "flue.compaction_reason": event.reason } : {},
|
|
24665
|
+
provider: "flue"
|
|
24666
|
+
};
|
|
24667
|
+
const input = {
|
|
24668
|
+
...typeof event.estimatedTokens === "number" ? { estimatedTokens: event.estimatedTokens } : {},
|
|
24669
|
+
...event.reason ? { reason: event.reason } : {}
|
|
24670
|
+
};
|
|
24671
|
+
const span = startFlueSpan(parent, {
|
|
24672
|
+
name: "flue.compaction",
|
|
24673
|
+
spanAttributes: { type: "task" /* TASK */ }
|
|
24674
|
+
});
|
|
24675
|
+
safeLog3(span, {
|
|
24676
|
+
input,
|
|
24677
|
+
metadata
|
|
24678
|
+
});
|
|
24679
|
+
this.compactionsByScope.set(scopeKey(event), {
|
|
24680
|
+
input,
|
|
24681
|
+
metadata,
|
|
24682
|
+
operationState,
|
|
24683
|
+
span,
|
|
24684
|
+
startTime: getCurrentUnixTimestamp()
|
|
24685
|
+
});
|
|
24686
|
+
}
|
|
24687
|
+
handleCompaction(event) {
|
|
24688
|
+
const key = scopeKey(event);
|
|
24689
|
+
const state = this.compactionsByScope.get(key) ?? this.findCompactionState(event);
|
|
24690
|
+
if (!state) {
|
|
24691
|
+
return;
|
|
24692
|
+
}
|
|
24693
|
+
safeLog3(state.span, {
|
|
24694
|
+
metadata: {
|
|
24695
|
+
...state.metadata,
|
|
24696
|
+
...extractEventMetadata(event),
|
|
24697
|
+
...typeof event.messagesBefore === "number" ? { "flue.messages_before": event.messagesBefore } : {},
|
|
24698
|
+
...typeof event.messagesAfter === "number" ? { "flue.messages_after": event.messagesAfter } : {}
|
|
24699
|
+
},
|
|
24700
|
+
metrics: {
|
|
24701
|
+
...durationMsMetrics(event.durationMs),
|
|
24702
|
+
...metricsFromUsage(event.usage)
|
|
24703
|
+
},
|
|
24704
|
+
output: {
|
|
24705
|
+
messagesAfter: event.messagesAfter,
|
|
24706
|
+
messagesBefore: event.messagesBefore
|
|
24707
|
+
}
|
|
24708
|
+
});
|
|
24709
|
+
state.span.end();
|
|
24710
|
+
this.deleteCompactionState(state);
|
|
24711
|
+
}
|
|
24712
|
+
findCompactionState(event) {
|
|
24713
|
+
const operationState = this.operationStateForEvent(event);
|
|
24714
|
+
for (const state of this.compactionsByScope.values()) {
|
|
24715
|
+
if (operationState && state.operationState === operationState) {
|
|
24716
|
+
return state;
|
|
24717
|
+
}
|
|
24718
|
+
}
|
|
24719
|
+
return void 0;
|
|
24720
|
+
}
|
|
24721
|
+
finishCompactionsForOperation(operationState) {
|
|
24722
|
+
for (const state of [...this.compactionsByScope.values()]) {
|
|
24723
|
+
if (state.operationState !== operationState) {
|
|
24724
|
+
continue;
|
|
24725
|
+
}
|
|
24726
|
+
safeLog3(state.span, {
|
|
24727
|
+
input: state.input,
|
|
24728
|
+
metadata: state.metadata,
|
|
24729
|
+
metrics: {
|
|
24730
|
+
...buildDurationMetrics3(state.startTime)
|
|
24731
|
+
},
|
|
24732
|
+
output: { completed: true }
|
|
24733
|
+
});
|
|
24734
|
+
state.span.end();
|
|
24735
|
+
this.deleteCompactionState(state);
|
|
24736
|
+
}
|
|
24737
|
+
}
|
|
24738
|
+
deleteCompactionState(state) {
|
|
24739
|
+
for (const [key, candidate] of this.compactionsByScope) {
|
|
24740
|
+
if (candidate !== state) {
|
|
24741
|
+
continue;
|
|
24742
|
+
}
|
|
24743
|
+
this.compactionsByScope.delete(key);
|
|
24744
|
+
return;
|
|
24745
|
+
}
|
|
24746
|
+
}
|
|
24747
|
+
startSyntheticToolState(event, toolName) {
|
|
24748
|
+
const parent = this.parentSpanForEvent(event);
|
|
24749
|
+
const metadata = {
|
|
24750
|
+
...extractEventMetadata(event),
|
|
24751
|
+
...event.toolCallId ? { "flue.tool_call_id": event.toolCallId } : {},
|
|
24752
|
+
"flue.tool_name": toolName,
|
|
24753
|
+
provider: "flue"
|
|
24754
|
+
};
|
|
24755
|
+
const span = startFlueSpan(parent, {
|
|
24756
|
+
name: `tool: ${toolName}`,
|
|
24757
|
+
spanAttributes: { type: "tool" /* TOOL */ }
|
|
24758
|
+
});
|
|
24759
|
+
safeLog3(span, { metadata });
|
|
24760
|
+
return { metadata, span, startTime: getCurrentUnixTimestamp() };
|
|
24761
|
+
}
|
|
24762
|
+
operationStateForEvent(event) {
|
|
24763
|
+
if (event.operationId) {
|
|
24764
|
+
const operation = this.activeOperationsById.get(event.operationId) ?? this.promotePendingOperationForEvent(event);
|
|
24765
|
+
if (operation) {
|
|
24766
|
+
return operation;
|
|
24767
|
+
}
|
|
24768
|
+
}
|
|
24769
|
+
return this.activeOperationForEventScope(event) ?? this.pendingOperationForEventScope(event);
|
|
24770
|
+
}
|
|
24771
|
+
parentSpanForEvent(event) {
|
|
24772
|
+
if (event.operationId) {
|
|
24773
|
+
const operation = this.operationStateForEvent(event);
|
|
24774
|
+
if (operation) {
|
|
24775
|
+
return operation.span;
|
|
24776
|
+
}
|
|
24777
|
+
}
|
|
24778
|
+
if (event.taskId) {
|
|
24779
|
+
return this.tasksById.get(event.taskId)?.span;
|
|
24780
|
+
}
|
|
24781
|
+
return this.operationStateForEvent(event)?.span;
|
|
24782
|
+
}
|
|
24783
|
+
promotePendingOperationForEvent(event) {
|
|
24784
|
+
if (!event.operationId) {
|
|
24785
|
+
return void 0;
|
|
24786
|
+
}
|
|
24787
|
+
const scopePrefixes = operationScopePrefixes(event);
|
|
24788
|
+
for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
|
|
24789
|
+
if (!candidateQueue.length || !operationKeyMatchesScopes(candidateKey, scopePrefixes)) {
|
|
24790
|
+
continue;
|
|
24791
|
+
}
|
|
24792
|
+
const state = candidateQueue.shift();
|
|
24793
|
+
if (!state) {
|
|
24794
|
+
return void 0;
|
|
24795
|
+
}
|
|
24796
|
+
state.operationId = event.operationId;
|
|
24797
|
+
this.activeOperationsById.set(event.operationId, state);
|
|
24798
|
+
addScopedOperation(this.activeOperationsByScope, event, state);
|
|
24799
|
+
state.metadata = {
|
|
24800
|
+
...state.metadata,
|
|
24801
|
+
...extractEventMetadata(event),
|
|
24802
|
+
"flue.operation_id": event.operationId
|
|
24803
|
+
};
|
|
24804
|
+
safeLog3(state.span, { metadata: state.metadata });
|
|
24805
|
+
return state;
|
|
24806
|
+
}
|
|
24807
|
+
return void 0;
|
|
24808
|
+
}
|
|
24809
|
+
activeOperationForEventScope(event) {
|
|
24810
|
+
for (const scope of operationScopeNames(event)) {
|
|
24811
|
+
const operations = this.activeOperationsByScope.get(scope);
|
|
24812
|
+
if (operations?.length) {
|
|
24813
|
+
return operations[operations.length - 1];
|
|
24814
|
+
}
|
|
24815
|
+
}
|
|
24816
|
+
return void 0;
|
|
24817
|
+
}
|
|
24818
|
+
pendingOperationForEventScope(event) {
|
|
24819
|
+
const scopePrefixes = operationScopePrefixes(event);
|
|
24820
|
+
for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
|
|
24821
|
+
if (!candidateQueue.length || !operationKeyMatchesScopes(candidateKey, scopePrefixes)) {
|
|
24822
|
+
continue;
|
|
24823
|
+
}
|
|
24824
|
+
return candidateQueue[0];
|
|
24825
|
+
}
|
|
24826
|
+
return void 0;
|
|
24827
|
+
}
|
|
24828
|
+
takePendingOperationForEvent(event) {
|
|
24829
|
+
const key = operationKey(event.session, event.operationKind);
|
|
24830
|
+
const queue2 = this.pendingOperationsByKey.get(key);
|
|
24831
|
+
if (queue2?.length) {
|
|
24832
|
+
return queue2.shift();
|
|
24833
|
+
}
|
|
24834
|
+
for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
|
|
24835
|
+
if (candidateKey.endsWith(`::${event.operationKind}`) && candidateQueue.length) {
|
|
24836
|
+
return candidateQueue.shift();
|
|
24837
|
+
}
|
|
24838
|
+
}
|
|
24839
|
+
return void 0;
|
|
24840
|
+
}
|
|
24841
|
+
pendingOperationQueue(key) {
|
|
24842
|
+
const existing = this.pendingOperationsByKey.get(key);
|
|
24843
|
+
if (existing) {
|
|
24844
|
+
return existing;
|
|
24845
|
+
}
|
|
24846
|
+
const queue2 = [];
|
|
24847
|
+
this.pendingOperationsByKey.set(key, queue2);
|
|
24848
|
+
return queue2;
|
|
24849
|
+
}
|
|
24850
|
+
};
|
|
24851
|
+
function isInstrumentedOperation(operation) {
|
|
24852
|
+
return operation === "prompt" || operation === "skill" || operation === "task" || operation === "compact";
|
|
24853
|
+
}
|
|
24854
|
+
function getSessionName(session) {
|
|
24855
|
+
return typeof session?.name === "string" ? session.name : void 0;
|
|
24856
|
+
}
|
|
24857
|
+
function operationKey(sessionName, operation) {
|
|
24858
|
+
return `${sessionName ?? "unknown"}::${operation}`;
|
|
24859
|
+
}
|
|
24860
|
+
function operationScopePrefixes(event) {
|
|
24861
|
+
const scopes = /* @__PURE__ */ new Set();
|
|
24862
|
+
for (const scope of operationScopeNames(event)) {
|
|
24863
|
+
scopes.add(`${scope}::`);
|
|
24864
|
+
}
|
|
24865
|
+
return scopes;
|
|
24866
|
+
}
|
|
24867
|
+
function operationKeyMatchesScopes(key, scopes) {
|
|
24868
|
+
for (const scope of scopes) {
|
|
24869
|
+
if (key.startsWith(scope)) {
|
|
24870
|
+
return true;
|
|
24871
|
+
}
|
|
24872
|
+
}
|
|
24873
|
+
return false;
|
|
24874
|
+
}
|
|
24875
|
+
function operationScopeNames(event) {
|
|
24876
|
+
const scopes = /* @__PURE__ */ new Set();
|
|
24877
|
+
if (event.session) {
|
|
24878
|
+
scopes.add(event.session);
|
|
24879
|
+
}
|
|
24880
|
+
if (event.parentSession) {
|
|
24881
|
+
scopes.add(event.parentSession);
|
|
24882
|
+
}
|
|
24883
|
+
if (!scopes.size) {
|
|
24884
|
+
scopes.add("unknown");
|
|
24885
|
+
}
|
|
24886
|
+
return scopes;
|
|
24887
|
+
}
|
|
24888
|
+
function addScopedOperation(operationsByScope, event, state) {
|
|
24889
|
+
for (const scope of operationScopeNames(event)) {
|
|
24890
|
+
addOperationToScope(operationsByScope, scope, state);
|
|
24891
|
+
}
|
|
24892
|
+
}
|
|
24893
|
+
function addOperationToScope(operationsByScope, scope, state) {
|
|
24894
|
+
const operations = operationsByScope.get(scope);
|
|
24895
|
+
if (operations) {
|
|
24896
|
+
if (!operations.includes(state)) {
|
|
24897
|
+
operations.push(state);
|
|
24898
|
+
}
|
|
24899
|
+
} else {
|
|
24900
|
+
operationsByScope.set(scope, [state]);
|
|
24901
|
+
}
|
|
24902
|
+
}
|
|
24903
|
+
function removeScopedOperation(operationsByScope, state) {
|
|
24904
|
+
for (const [scope, operations] of operationsByScope) {
|
|
24905
|
+
const index = operations.indexOf(state);
|
|
24906
|
+
if (index === -1) {
|
|
24907
|
+
continue;
|
|
24908
|
+
}
|
|
24909
|
+
operations.splice(index, 1);
|
|
24910
|
+
if (operations.length === 0) {
|
|
24911
|
+
operationsByScope.delete(scope);
|
|
24912
|
+
}
|
|
24913
|
+
}
|
|
24914
|
+
}
|
|
24915
|
+
function removePendingOperation(pendingOperationsByKey, state) {
|
|
24916
|
+
for (const [key, queue2] of pendingOperationsByKey) {
|
|
24917
|
+
const index = queue2.indexOf(state);
|
|
24918
|
+
if (index === -1) {
|
|
24919
|
+
continue;
|
|
24920
|
+
}
|
|
24921
|
+
queue2.splice(index, 1);
|
|
24922
|
+
if (queue2.length === 0) {
|
|
24923
|
+
pendingOperationsByKey.delete(key);
|
|
24924
|
+
}
|
|
24925
|
+
return;
|
|
24926
|
+
}
|
|
24927
|
+
}
|
|
24928
|
+
function extractSessionMetadata(session) {
|
|
24929
|
+
const sessionName = getSessionName(session);
|
|
24930
|
+
return sessionName ? { "flue.session": sessionName } : {};
|
|
24931
|
+
}
|
|
24932
|
+
function extractEventMetadata(event) {
|
|
24933
|
+
return {
|
|
24934
|
+
...event.runId ? { "flue.run_id": event.runId } : {},
|
|
24935
|
+
...typeof event.eventIndex === "number" ? { "flue.event_index": event.eventIndex } : {},
|
|
24936
|
+
...event.session ? { "flue.session": event.session } : {},
|
|
24937
|
+
...event.parentSession ? { "flue.parent_session": event.parentSession } : {},
|
|
24938
|
+
...event.harness ? { "flue.harness": event.harness } : {},
|
|
24939
|
+
...event.taskId ? { "flue.task_id": event.taskId } : {},
|
|
24940
|
+
...event.operationId ? { "flue.operation_id": event.operationId } : {}
|
|
24941
|
+
};
|
|
24942
|
+
}
|
|
24943
|
+
function extractOperationInput(operation, args) {
|
|
24944
|
+
switch (operation) {
|
|
24945
|
+
case "prompt":
|
|
24946
|
+
case "task":
|
|
24947
|
+
return args[0];
|
|
24948
|
+
case "skill":
|
|
24949
|
+
return {
|
|
24950
|
+
args: getOptionObject(args[1])?.args,
|
|
24951
|
+
name: args[0]
|
|
24952
|
+
};
|
|
24953
|
+
case "compact":
|
|
24954
|
+
return void 0;
|
|
24955
|
+
}
|
|
24956
|
+
}
|
|
24957
|
+
function extractOperationInputMetadata(operation, args) {
|
|
24958
|
+
const options = getOptionObject(args[1]);
|
|
24959
|
+
return {
|
|
24960
|
+
...operation === "skill" && typeof args[0] === "string" ? { "flue.skill_name": args[0] } : {},
|
|
24961
|
+
...options?.model ? { model: options.model, "flue.model": options.model } : {},
|
|
24962
|
+
...options?.role ? { "flue.role": options.role } : {},
|
|
24963
|
+
...options?.thinkingLevel ? { "flue.thinking_level": options.thinkingLevel } : {},
|
|
24964
|
+
...typeof options?.cwd === "string" ? { "flue.cwd": options.cwd } : {},
|
|
24965
|
+
...Array.isArray(options?.tools) ? {
|
|
24966
|
+
"flue.tools_count": options.tools.length,
|
|
24967
|
+
tools: summarizeTools(options.tools)
|
|
24968
|
+
} : {},
|
|
24969
|
+
...Array.isArray(options?.images) ? { "flue.images_count": options.images.length } : {},
|
|
24970
|
+
...options?.result || options?.schema ? { "flue.result_schema": true } : {}
|
|
24971
|
+
};
|
|
24972
|
+
}
|
|
24973
|
+
function getOptionObject(value) {
|
|
24974
|
+
return isObject(value) ? value : void 0;
|
|
24975
|
+
}
|
|
24976
|
+
function summarizeTools(tools) {
|
|
24977
|
+
return tools.flatMap((tool) => {
|
|
24978
|
+
if (!isObject(tool)) {
|
|
24979
|
+
return [];
|
|
24980
|
+
}
|
|
24981
|
+
const name = typeof tool.name === "string" ? tool.name : void 0;
|
|
24982
|
+
if (!name) {
|
|
24983
|
+
return [];
|
|
24984
|
+
}
|
|
24985
|
+
return [
|
|
24986
|
+
{
|
|
24987
|
+
function: {
|
|
24988
|
+
description: typeof tool.description === "string" ? tool.description : void 0,
|
|
24989
|
+
name,
|
|
24990
|
+
parameters: tool.parameters
|
|
24991
|
+
},
|
|
24992
|
+
type: "function"
|
|
24993
|
+
}
|
|
24994
|
+
];
|
|
24995
|
+
});
|
|
24996
|
+
}
|
|
24997
|
+
function extractPromptResponseMetadata(result) {
|
|
24998
|
+
const modelId = result?.model && typeof result.model.id === "string" ? result.model.id : void 0;
|
|
24999
|
+
return modelId ? {
|
|
25000
|
+
model: modelId,
|
|
25001
|
+
"flue.model": modelId
|
|
25002
|
+
} : {};
|
|
25003
|
+
}
|
|
25004
|
+
function extractOperationOutput(result) {
|
|
25005
|
+
if (!result) {
|
|
25006
|
+
return void 0;
|
|
25007
|
+
}
|
|
25008
|
+
if ("data" in result) {
|
|
25009
|
+
return result.data;
|
|
25010
|
+
}
|
|
25011
|
+
if ("text" in result) {
|
|
25012
|
+
return result.text;
|
|
25013
|
+
}
|
|
25014
|
+
return result;
|
|
25015
|
+
}
|
|
25016
|
+
function metricsFromUsage(usage) {
|
|
25017
|
+
return {
|
|
25018
|
+
...typeof usage?.input === "number" ? { prompt_tokens: usage.input } : {},
|
|
25019
|
+
...typeof usage?.output === "number" ? { completion_tokens: usage.output } : {},
|
|
25020
|
+
...typeof usage?.cacheRead === "number" ? { prompt_cached_tokens: usage.cacheRead } : {},
|
|
25021
|
+
...typeof usage?.cacheWrite === "number" ? { prompt_cache_creation_tokens: usage.cacheWrite } : {},
|
|
25022
|
+
...typeof usage?.totalTokens === "number" ? { tokens: usage.totalTokens } : {},
|
|
25023
|
+
...typeof usage?.cost?.total === "number" ? { estimated_cost: usage.cost.total } : {}
|
|
25024
|
+
};
|
|
25025
|
+
}
|
|
25026
|
+
function buildDurationMetrics3(startTime) {
|
|
25027
|
+
return {
|
|
25028
|
+
duration_ms: Math.max(0, (getCurrentUnixTimestamp() - startTime) * 1e3)
|
|
25029
|
+
};
|
|
25030
|
+
}
|
|
25031
|
+
function durationMsMetrics(durationMs) {
|
|
25032
|
+
return typeof durationMs === "number" ? { duration_ms: durationMs } : {};
|
|
25033
|
+
}
|
|
25034
|
+
function scopeKey(event) {
|
|
25035
|
+
if (event.operationId) {
|
|
25036
|
+
return `operation:${event.operationId}`;
|
|
25037
|
+
}
|
|
25038
|
+
if (event.taskId) {
|
|
25039
|
+
return `task:${event.taskId}`;
|
|
25040
|
+
}
|
|
25041
|
+
if (event.session) {
|
|
25042
|
+
return `session:${event.session}`;
|
|
25043
|
+
}
|
|
25044
|
+
return "flue:unknown";
|
|
25045
|
+
}
|
|
25046
|
+
function toolKey(event) {
|
|
25047
|
+
return `${scopeKey(event)}::tool:${event.toolCallId ?? "unknown"}`;
|
|
25048
|
+
}
|
|
25049
|
+
function toAssistantOutput(text, finishReason, reasoning, toolCalls) {
|
|
25050
|
+
return [
|
|
25051
|
+
{
|
|
25052
|
+
finish_reason: finishReason ?? "stop",
|
|
25053
|
+
index: 0,
|
|
25054
|
+
message: {
|
|
25055
|
+
content: text,
|
|
25056
|
+
...reasoning ? { reasoning } : {},
|
|
25057
|
+
role: "assistant",
|
|
25058
|
+
...toolCalls?.length ? {
|
|
25059
|
+
tool_calls: toolCalls.map((toolCall) => ({
|
|
25060
|
+
function: {
|
|
25061
|
+
arguments: toolCall.args === void 0 ? "{}" : JSON.stringify(toolCall.args),
|
|
25062
|
+
name: toolCall.toolName ?? "unknown"
|
|
25063
|
+
},
|
|
25064
|
+
...toolCall.toolCallId ? { id: toolCall.toolCallId } : {},
|
|
25065
|
+
type: "function"
|
|
25066
|
+
}))
|
|
25067
|
+
} : {}
|
|
25068
|
+
}
|
|
25069
|
+
}
|
|
25070
|
+
];
|
|
25071
|
+
}
|
|
25072
|
+
function startFlueSpan(parent, args) {
|
|
25073
|
+
return parent ? withCurrent(parent, () => startSpan(args)) : startSpan(args);
|
|
25074
|
+
}
|
|
25075
|
+
function safeLog3(span, event) {
|
|
25076
|
+
try {
|
|
25077
|
+
span.log(event);
|
|
25078
|
+
} catch (error) {
|
|
25079
|
+
logInstrumentationError3("Flue span log", error);
|
|
25080
|
+
}
|
|
25081
|
+
}
|
|
25082
|
+
function errorToString(error) {
|
|
25083
|
+
if (error instanceof Error) {
|
|
25084
|
+
return error.message;
|
|
25085
|
+
}
|
|
25086
|
+
if (typeof error === "string") {
|
|
25087
|
+
return error;
|
|
25088
|
+
}
|
|
25089
|
+
try {
|
|
25090
|
+
return JSON.stringify(error);
|
|
25091
|
+
} catch {
|
|
25092
|
+
return String(error);
|
|
25093
|
+
}
|
|
25094
|
+
}
|
|
25095
|
+
function logInstrumentationError3(label, error) {
|
|
25096
|
+
console.error(`Error in ${label} instrumentation:`, error);
|
|
25097
|
+
}
|
|
25098
|
+
|
|
25099
|
+
// src/wrappers/langchain/callback-handler.ts
|
|
25100
|
+
var BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME = "BraintrustCallbackHandler";
|
|
25101
|
+
var BraintrustLangChainCallbackHandler = class {
|
|
25102
|
+
name = BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
|
|
25103
|
+
spans = /* @__PURE__ */ new Map();
|
|
25104
|
+
skippedRuns = /* @__PURE__ */ new Set();
|
|
25105
|
+
parent;
|
|
25106
|
+
rootRunId;
|
|
25107
|
+
options;
|
|
25108
|
+
startTimes = /* @__PURE__ */ new Map();
|
|
25109
|
+
firstTokenTimes = /* @__PURE__ */ new Map();
|
|
25110
|
+
ttftMs = /* @__PURE__ */ new Map();
|
|
25111
|
+
constructor(options) {
|
|
25112
|
+
this.parent = options?.parent;
|
|
25113
|
+
this.options = {
|
|
25114
|
+
debug: options?.debug ?? false,
|
|
25115
|
+
excludeMetadataProps: options?.excludeMetadataProps ?? /^(l[sc]_|langgraph_|__pregel_|checkpoint_ns)/,
|
|
25116
|
+
logger: options?.logger
|
|
25117
|
+
};
|
|
25118
|
+
}
|
|
25119
|
+
startSpan({
|
|
25120
|
+
runId,
|
|
25121
|
+
parentRunId,
|
|
25122
|
+
...args
|
|
25123
|
+
}) {
|
|
25124
|
+
if (this.spans.has(runId)) {
|
|
25125
|
+
return;
|
|
25126
|
+
}
|
|
25127
|
+
if (!parentRunId) {
|
|
25128
|
+
this.rootRunId = runId;
|
|
25129
|
+
}
|
|
25130
|
+
const tags = args.event?.tags;
|
|
25131
|
+
const spanAttributes = args.spanAttributes || {};
|
|
25132
|
+
spanAttributes.type = args.type || spanAttributes.type || "task";
|
|
25133
|
+
args.type = spanAttributes.type;
|
|
25134
|
+
const currentParent = (typeof this.parent === "function" ? this.parent() : this.parent) ?? currentSpan();
|
|
25135
|
+
let parentSpan;
|
|
25136
|
+
if (parentRunId && this.spans.has(parentRunId)) {
|
|
25137
|
+
parentSpan = this.spans.get(parentRunId);
|
|
25138
|
+
} else if (!Object.is(currentParent, NOOP_SPAN)) {
|
|
25139
|
+
parentSpan = currentParent;
|
|
25140
|
+
} else if (this.options.logger) {
|
|
25141
|
+
parentSpan = this.options.logger;
|
|
25142
|
+
} else {
|
|
25143
|
+
parentSpan = { startSpan };
|
|
25144
|
+
}
|
|
25145
|
+
args.event = {
|
|
25146
|
+
...args.event,
|
|
25147
|
+
tags: void 0,
|
|
25148
|
+
metadata: {
|
|
25149
|
+
...tags ? { tags } : {},
|
|
25150
|
+
...args.event?.metadata,
|
|
25151
|
+
braintrust: {
|
|
25152
|
+
integration_name: "langchain-js",
|
|
25153
|
+
sdk_language: "javascript"
|
|
25154
|
+
},
|
|
25155
|
+
run_id: runId,
|
|
25156
|
+
parent_run_id: parentRunId,
|
|
25157
|
+
...this.options.debug ? { runId, parentRunId } : {}
|
|
25158
|
+
}
|
|
25159
|
+
};
|
|
25160
|
+
let span = parentSpan.startSpan(args);
|
|
25161
|
+
if (!Object.is(this.options.logger, NOOP_SPAN) && Object.is(span, NOOP_SPAN)) {
|
|
25162
|
+
span = initLogger().startSpan(args);
|
|
25163
|
+
}
|
|
25164
|
+
this.spans.set(runId, span);
|
|
25165
|
+
}
|
|
25166
|
+
endSpan({
|
|
25167
|
+
runId,
|
|
25168
|
+
parentRunId,
|
|
25169
|
+
tags,
|
|
25170
|
+
metadata,
|
|
25171
|
+
...args
|
|
25172
|
+
}) {
|
|
25173
|
+
if (!this.spans.has(runId)) {
|
|
25174
|
+
return;
|
|
25175
|
+
}
|
|
25176
|
+
if (this.skippedRuns.has(runId)) {
|
|
25177
|
+
this.skippedRuns.delete(runId);
|
|
25178
|
+
return;
|
|
25179
|
+
}
|
|
25180
|
+
const span = this.spans.get(runId);
|
|
25181
|
+
this.spans.delete(runId);
|
|
25182
|
+
if (runId === this.rootRunId) {
|
|
25183
|
+
this.rootRunId = void 0;
|
|
25184
|
+
}
|
|
25185
|
+
span.log({ ...args, metadata: { tags, ...metadata } });
|
|
25186
|
+
span.end();
|
|
25187
|
+
}
|
|
25188
|
+
async handleLLMStart(llm, prompts, runId, parentRunId, extraParams, tags, metadata, runName) {
|
|
25189
|
+
this.startSpan({
|
|
25190
|
+
runId,
|
|
25191
|
+
parentRunId,
|
|
25192
|
+
name: runName ?? getSerializedName(llm) ?? "LLM",
|
|
25193
|
+
type: "llm",
|
|
25194
|
+
event: {
|
|
25195
|
+
input: prompts,
|
|
25196
|
+
tags,
|
|
25197
|
+
metadata: {
|
|
25198
|
+
serialized: llm,
|
|
25199
|
+
name: runName,
|
|
25200
|
+
metadata,
|
|
25201
|
+
...extraParams
|
|
25202
|
+
}
|
|
25203
|
+
}
|
|
25204
|
+
});
|
|
25205
|
+
}
|
|
25206
|
+
async handleLLMError(err, runId, parentRunId, tags) {
|
|
25207
|
+
this.endSpan({ runId, parentRunId, error: err, tags });
|
|
25208
|
+
}
|
|
25209
|
+
async handleLLMEnd(output, runId, parentRunId, tags) {
|
|
25210
|
+
const metrics = getMetricsFromResponse(output);
|
|
25211
|
+
const modelName2 = getModelNameFromResponse(output);
|
|
25212
|
+
const ttft = this.ttftMs.get(runId);
|
|
25213
|
+
if (ttft !== void 0) {
|
|
25214
|
+
metrics.time_to_first_token = ttft;
|
|
25215
|
+
}
|
|
25216
|
+
this.startTimes.delete(runId);
|
|
25217
|
+
this.firstTokenTimes.delete(runId);
|
|
25218
|
+
this.ttftMs.delete(runId);
|
|
25219
|
+
this.endSpan({
|
|
25220
|
+
runId,
|
|
25221
|
+
parentRunId,
|
|
25222
|
+
output,
|
|
25223
|
+
metrics,
|
|
25224
|
+
tags,
|
|
25225
|
+
metadata: {
|
|
25226
|
+
model: modelName2
|
|
25227
|
+
}
|
|
25228
|
+
});
|
|
25229
|
+
}
|
|
25230
|
+
async handleChatModelStart(llm, messages, runId, parentRunId, extraParams, tags, metadata, runName) {
|
|
25231
|
+
this.startTimes.set(runId, Date.now());
|
|
25232
|
+
this.firstTokenTimes.delete(runId);
|
|
25233
|
+
this.ttftMs.delete(runId);
|
|
25234
|
+
this.startSpan({
|
|
25235
|
+
runId,
|
|
25236
|
+
parentRunId,
|
|
25237
|
+
name: runName ?? getSerializedName(llm) ?? "Chat Model",
|
|
25238
|
+
type: "llm",
|
|
25239
|
+
event: {
|
|
25240
|
+
input: messages,
|
|
25241
|
+
tags,
|
|
25242
|
+
metadata: {
|
|
25243
|
+
serialized: llm,
|
|
25244
|
+
name: runName,
|
|
25245
|
+
metadata,
|
|
25246
|
+
...extraParams
|
|
25247
|
+
}
|
|
25248
|
+
}
|
|
25249
|
+
});
|
|
25250
|
+
}
|
|
25251
|
+
async handleChainStart(chain, inputs, runId, parentRunId, tags, metadata, runType, runName) {
|
|
25252
|
+
if (tags?.includes("langsmith:hidden")) {
|
|
25253
|
+
this.skippedRuns.add(runId);
|
|
25254
|
+
return;
|
|
25255
|
+
}
|
|
25256
|
+
this.startSpan({
|
|
25257
|
+
runId,
|
|
25258
|
+
parentRunId,
|
|
25259
|
+
name: runName ?? getSerializedName(chain) ?? "Chain",
|
|
25260
|
+
event: {
|
|
25261
|
+
input: inputs,
|
|
25262
|
+
tags,
|
|
25263
|
+
metadata: {
|
|
25264
|
+
serialized: chain,
|
|
25265
|
+
name: runName,
|
|
25266
|
+
metadata,
|
|
25267
|
+
run_type: runType
|
|
25268
|
+
}
|
|
25269
|
+
}
|
|
25270
|
+
});
|
|
25271
|
+
}
|
|
25272
|
+
async handleChainError(err, runId, parentRunId, tags, kwargs) {
|
|
25273
|
+
this.endSpan({ runId, parentRunId, error: err, tags, metadata: kwargs });
|
|
25274
|
+
}
|
|
25275
|
+
async handleChainEnd(outputs, runId, parentRunId, tags, kwargs) {
|
|
25276
|
+
this.endSpan({
|
|
25277
|
+
runId,
|
|
25278
|
+
parentRunId,
|
|
25279
|
+
tags,
|
|
25280
|
+
output: outputs,
|
|
25281
|
+
metadata: { ...kwargs }
|
|
25282
|
+
});
|
|
25283
|
+
}
|
|
25284
|
+
async handleToolStart(tool, input, runId, parentRunId, tags, metadata, runName) {
|
|
25285
|
+
this.startSpan({
|
|
25286
|
+
runId,
|
|
25287
|
+
parentRunId,
|
|
25288
|
+
name: runName ?? getSerializedName(tool) ?? "Tool",
|
|
25289
|
+
type: "llm",
|
|
25290
|
+
event: {
|
|
25291
|
+
input: safeJsonParse(input),
|
|
25292
|
+
tags,
|
|
25293
|
+
metadata: {
|
|
25294
|
+
metadata,
|
|
25295
|
+
serialized: tool,
|
|
25296
|
+
input_str: input,
|
|
25297
|
+
input: safeJsonParse(input),
|
|
25298
|
+
name: runName
|
|
25299
|
+
}
|
|
25300
|
+
}
|
|
25301
|
+
});
|
|
25302
|
+
}
|
|
25303
|
+
async handleToolError(err, runId, parentRunId, tags) {
|
|
25304
|
+
this.endSpan({ runId, parentRunId, error: err, tags });
|
|
25305
|
+
}
|
|
25306
|
+
async handleToolEnd(output, runId, parentRunId, tags) {
|
|
25307
|
+
this.endSpan({ runId, parentRunId, output, tags });
|
|
25308
|
+
}
|
|
25309
|
+
async handleAgentAction(action, runId, parentRunId, tags) {
|
|
25310
|
+
this.startSpan({
|
|
25311
|
+
runId,
|
|
25312
|
+
parentRunId,
|
|
25313
|
+
type: "llm",
|
|
25314
|
+
name: typeof action.tool === "string" ? action.tool : "Agent",
|
|
25315
|
+
event: {
|
|
25316
|
+
input: action,
|
|
25317
|
+
tags
|
|
25318
|
+
}
|
|
25319
|
+
});
|
|
25320
|
+
}
|
|
25321
|
+
async handleAgentEnd(action, runId, parentRunId, tags) {
|
|
25322
|
+
this.endSpan({ runId, parentRunId, output: action, tags });
|
|
25323
|
+
}
|
|
25324
|
+
async handleRetrieverStart(retriever, query, runId, parentRunId, tags, metadata, name) {
|
|
25325
|
+
this.startSpan({
|
|
25326
|
+
runId,
|
|
25327
|
+
parentRunId,
|
|
25328
|
+
name: name ?? getSerializedName(retriever) ?? "Retriever",
|
|
25329
|
+
type: "function",
|
|
25330
|
+
event: {
|
|
25331
|
+
input: query,
|
|
25332
|
+
tags,
|
|
25333
|
+
metadata: {
|
|
25334
|
+
serialized: retriever,
|
|
25335
|
+
metadata,
|
|
25336
|
+
name
|
|
25337
|
+
}
|
|
25338
|
+
}
|
|
25339
|
+
});
|
|
25340
|
+
}
|
|
25341
|
+
async handleRetrieverEnd(documents, runId, parentRunId, tags) {
|
|
25342
|
+
this.endSpan({ runId, parentRunId, output: documents, tags });
|
|
25343
|
+
}
|
|
25344
|
+
async handleRetrieverError(err, runId, parentRunId, tags) {
|
|
25345
|
+
this.endSpan({ runId, parentRunId, error: err, tags });
|
|
25346
|
+
}
|
|
25347
|
+
async handleLLMNewToken(_token, _idx, runId, _parentRunId, _tags) {
|
|
25348
|
+
if (!this.firstTokenTimes.has(runId)) {
|
|
25349
|
+
const now2 = Date.now();
|
|
25350
|
+
this.firstTokenTimes.set(runId, now2);
|
|
25351
|
+
const start = this.startTimes.get(runId);
|
|
25352
|
+
if (start !== void 0) {
|
|
25353
|
+
this.ttftMs.set(runId, (now2 - start) / 1e3);
|
|
25354
|
+
}
|
|
25355
|
+
}
|
|
25356
|
+
}
|
|
25357
|
+
};
|
|
25358
|
+
function getSerializedName(serialized) {
|
|
25359
|
+
if (typeof serialized.name === "string") {
|
|
25360
|
+
return serialized.name;
|
|
25361
|
+
}
|
|
25362
|
+
const lastIdPart = serialized.id?.at(-1);
|
|
25363
|
+
return typeof lastIdPart === "string" ? lastIdPart : void 0;
|
|
25364
|
+
}
|
|
25365
|
+
function cleanObject(obj) {
|
|
25366
|
+
return Object.fromEntries(
|
|
25367
|
+
Object.entries(obj).filter(([, value]) => {
|
|
25368
|
+
if (typeof value !== "number") {
|
|
25369
|
+
return false;
|
|
25370
|
+
}
|
|
25371
|
+
return Number.isFinite(value);
|
|
25372
|
+
})
|
|
25373
|
+
);
|
|
25374
|
+
}
|
|
25375
|
+
function walkGenerations(response) {
|
|
25376
|
+
const result = [];
|
|
25377
|
+
const generations = response.generations || [];
|
|
25378
|
+
for (const batch of generations) {
|
|
25379
|
+
if (Array.isArray(batch)) {
|
|
25380
|
+
for (const generation of batch) {
|
|
25381
|
+
if (isRecord(generation)) {
|
|
25382
|
+
result.push(generation);
|
|
25383
|
+
}
|
|
25384
|
+
}
|
|
25385
|
+
} else if (isRecord(batch)) {
|
|
25386
|
+
result.push(batch);
|
|
25387
|
+
}
|
|
25388
|
+
}
|
|
25389
|
+
return result;
|
|
25390
|
+
}
|
|
25391
|
+
function getModelNameFromResponse(response) {
|
|
25392
|
+
for (const generation of walkGenerations(response)) {
|
|
25393
|
+
const message = generation.message;
|
|
25394
|
+
if (!isRecord(message)) {
|
|
25395
|
+
continue;
|
|
25396
|
+
}
|
|
25397
|
+
const responseMetadata = message.response_metadata;
|
|
25398
|
+
if (!isRecord(responseMetadata)) {
|
|
25399
|
+
continue;
|
|
25400
|
+
}
|
|
25401
|
+
const modelName3 = responseMetadata.model_name ?? responseMetadata.model;
|
|
25402
|
+
if (typeof modelName3 === "string") {
|
|
25403
|
+
return modelName3;
|
|
25404
|
+
}
|
|
25405
|
+
}
|
|
25406
|
+
const llmOutput = response.llmOutput || {};
|
|
25407
|
+
const modelName2 = llmOutput.model_name ?? llmOutput.model;
|
|
25408
|
+
return typeof modelName2 === "string" ? modelName2 : void 0;
|
|
25409
|
+
}
|
|
25410
|
+
function getMetricsFromResponse(response) {
|
|
25411
|
+
for (const generation of walkGenerations(response)) {
|
|
25412
|
+
const message = generation.message;
|
|
25413
|
+
if (!isRecord(message)) {
|
|
25414
|
+
continue;
|
|
25415
|
+
}
|
|
25416
|
+
const usageMetadata = message.usage_metadata;
|
|
25417
|
+
if (!isRecord(usageMetadata)) {
|
|
25418
|
+
continue;
|
|
25419
|
+
}
|
|
25420
|
+
const inputTokenDetails = usageMetadata.input_token_details;
|
|
25421
|
+
return cleanObject({
|
|
25422
|
+
total_tokens: usageMetadata.total_tokens,
|
|
25423
|
+
prompt_tokens: usageMetadata.input_tokens,
|
|
25424
|
+
completion_tokens: usageMetadata.output_tokens,
|
|
25425
|
+
prompt_cache_creation_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_creation : void 0,
|
|
25426
|
+
prompt_cached_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_read : void 0
|
|
25427
|
+
});
|
|
25428
|
+
}
|
|
25429
|
+
const llmOutput = response.llmOutput || {};
|
|
25430
|
+
const tokenUsage = isRecord(llmOutput.tokenUsage) ? llmOutput.tokenUsage : isRecord(llmOutput.estimatedTokens) ? llmOutput.estimatedTokens : {};
|
|
25431
|
+
return cleanObject({
|
|
25432
|
+
total_tokens: tokenUsage.totalTokens,
|
|
25433
|
+
prompt_tokens: tokenUsage.promptTokens,
|
|
25434
|
+
completion_tokens: tokenUsage.completionTokens
|
|
25435
|
+
});
|
|
25436
|
+
}
|
|
25437
|
+
function safeJsonParse(input) {
|
|
25438
|
+
try {
|
|
25439
|
+
return JSON.parse(input);
|
|
25440
|
+
} catch {
|
|
25441
|
+
return input;
|
|
25442
|
+
}
|
|
25443
|
+
}
|
|
25444
|
+
function isRecord(value) {
|
|
25445
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
25446
|
+
}
|
|
25447
|
+
|
|
25448
|
+
// src/instrumentation/plugins/langchain-channels.ts
|
|
25449
|
+
var langChainChannels = defineChannels("@langchain/core", {
|
|
25450
|
+
configure: channel({
|
|
25451
|
+
channelName: "CallbackManager.configure",
|
|
25452
|
+
kind: "sync-stream"
|
|
25453
|
+
}),
|
|
25454
|
+
configureSync: channel({
|
|
25455
|
+
channelName: "CallbackManager._configureSync",
|
|
25456
|
+
kind: "sync-stream"
|
|
25457
|
+
})
|
|
25458
|
+
});
|
|
25459
|
+
|
|
25460
|
+
// src/instrumentation/plugins/langchain-plugin.ts
|
|
25461
|
+
var LangChainPlugin = class extends BasePlugin {
|
|
25462
|
+
injectedManagers = /* @__PURE__ */ new WeakSet();
|
|
25463
|
+
onEnable() {
|
|
25464
|
+
this.subscribeToConfigure(langChainChannels.configure);
|
|
25465
|
+
this.subscribeToConfigure(langChainChannels.configureSync);
|
|
25466
|
+
}
|
|
25467
|
+
onDisable() {
|
|
25468
|
+
for (const unsubscribe of this.unsubscribers) {
|
|
25469
|
+
unsubscribe();
|
|
25470
|
+
}
|
|
25471
|
+
this.unsubscribers = [];
|
|
25472
|
+
this.injectedManagers = /* @__PURE__ */ new WeakSet();
|
|
25473
|
+
}
|
|
25474
|
+
subscribeToConfigure(channel2) {
|
|
25475
|
+
const tracingChannel2 = channel2.tracingChannel();
|
|
25476
|
+
const handlers = {
|
|
25477
|
+
start: (event) => {
|
|
25478
|
+
injectHandlerIntoArguments(event.arguments);
|
|
25479
|
+
},
|
|
25480
|
+
end: (event) => {
|
|
25481
|
+
this.injectHandler(event.result);
|
|
25482
|
+
}
|
|
25483
|
+
};
|
|
25484
|
+
tracingChannel2.subscribe(handlers);
|
|
25485
|
+
this.unsubscribers.push(() => {
|
|
25486
|
+
tracingChannel2.unsubscribe(handlers);
|
|
25487
|
+
});
|
|
25488
|
+
}
|
|
25489
|
+
injectHandler(result) {
|
|
25490
|
+
if (!isCallbackManager(result)) {
|
|
25491
|
+
return;
|
|
25492
|
+
}
|
|
25493
|
+
if (this.injectedManagers.has(result) || hasBraintrustHandler(result)) {
|
|
25494
|
+
return;
|
|
25495
|
+
}
|
|
25496
|
+
try {
|
|
25497
|
+
result.addHandler(new BraintrustLangChainCallbackHandler(), true);
|
|
25498
|
+
this.injectedManagers.add(result);
|
|
25499
|
+
} catch {
|
|
25500
|
+
}
|
|
25501
|
+
}
|
|
25502
|
+
};
|
|
25503
|
+
function isCallbackManager(value) {
|
|
25504
|
+
if (typeof value !== "object" || value === null) {
|
|
25505
|
+
return false;
|
|
25506
|
+
}
|
|
25507
|
+
const maybeManager = value;
|
|
25508
|
+
return typeof maybeManager.addHandler === "function";
|
|
25509
|
+
}
|
|
25510
|
+
function hasBraintrustHandler(manager) {
|
|
25511
|
+
return manager.handlers?.some((handler) => {
|
|
25512
|
+
if (typeof handler !== "object" || handler === null) {
|
|
25513
|
+
return false;
|
|
25514
|
+
}
|
|
25515
|
+
const name = Reflect.get(handler, "name");
|
|
25516
|
+
return name === BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
|
|
25517
|
+
}) ?? false;
|
|
25518
|
+
}
|
|
25519
|
+
function injectHandlerIntoArguments(args) {
|
|
25520
|
+
if (!isWritableArgumentsObject(args)) {
|
|
25521
|
+
return;
|
|
25522
|
+
}
|
|
25523
|
+
const inheritedHandlers = Reflect.get(args, "0");
|
|
25524
|
+
const handler = new BraintrustLangChainCallbackHandler();
|
|
25525
|
+
if (inheritedHandlers === void 0 || inheritedHandlers === null) {
|
|
25526
|
+
Reflect.set(args, "0", [handler]);
|
|
25527
|
+
return;
|
|
25528
|
+
}
|
|
25529
|
+
if (Array.isArray(inheritedHandlers)) {
|
|
25530
|
+
if (!inheritedHandlers.some(isBraintrustHandler)) {
|
|
25531
|
+
inheritedHandlers.push(handler);
|
|
25532
|
+
}
|
|
25533
|
+
}
|
|
25534
|
+
}
|
|
25535
|
+
function isWritableArgumentsObject(args) {
|
|
25536
|
+
return typeof args === "object" && args !== null;
|
|
25537
|
+
}
|
|
25538
|
+
function isBraintrustHandler(handler) {
|
|
25539
|
+
if (typeof handler !== "object" || handler === null) {
|
|
25540
|
+
return false;
|
|
25541
|
+
}
|
|
25542
|
+
return Reflect.get(handler, "name") === BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
|
|
25543
|
+
}
|
|
25544
|
+
|
|
25545
|
+
// src/instrumentation/braintrust-plugin.ts
|
|
25546
|
+
function getIntegrationConfig(integrations, key) {
|
|
25547
|
+
return integrations[key];
|
|
25548
|
+
}
|
|
25549
|
+
var BraintrustPlugin = class extends BasePlugin {
|
|
25550
|
+
config;
|
|
25551
|
+
openaiPlugin = null;
|
|
25552
|
+
openAICodexPlugin = null;
|
|
25553
|
+
anthropicPlugin = null;
|
|
25554
|
+
aiSDKPlugin = null;
|
|
25555
|
+
claudeAgentSDKPlugin = null;
|
|
25556
|
+
cursorSDKPlugin = null;
|
|
25557
|
+
openAIAgentsPlugin = null;
|
|
25558
|
+
googleGenAIPlugin = null;
|
|
25559
|
+
huggingFacePlugin = null;
|
|
25560
|
+
openRouterPlugin = null;
|
|
25561
|
+
openRouterAgentPlugin = null;
|
|
25562
|
+
mistralPlugin = null;
|
|
25563
|
+
googleADKPlugin = null;
|
|
25564
|
+
coherePlugin = null;
|
|
25565
|
+
groqPlugin = null;
|
|
25566
|
+
genkitPlugin = null;
|
|
25567
|
+
gitHubCopilotPlugin = null;
|
|
25568
|
+
fluePlugin = null;
|
|
25569
|
+
langChainPlugin = null;
|
|
25570
|
+
constructor(config = {}) {
|
|
25571
|
+
super();
|
|
25572
|
+
this.config = config;
|
|
25573
|
+
}
|
|
25574
|
+
onEnable() {
|
|
25575
|
+
const integrations = this.config.integrations || {};
|
|
25576
|
+
if (integrations.openai !== false) {
|
|
25577
|
+
this.openaiPlugin = new OpenAIPlugin();
|
|
25578
|
+
this.openaiPlugin.enable();
|
|
25579
|
+
}
|
|
25580
|
+
if (integrations.openaiCodexSDK !== false) {
|
|
25581
|
+
this.openAICodexPlugin = new OpenAICodexPlugin();
|
|
25582
|
+
this.openAICodexPlugin.enable();
|
|
23396
25583
|
}
|
|
23397
25584
|
if (integrations.anthropic !== false) {
|
|
23398
25585
|
this.anthropicPlugin = new AnthropicPlugin();
|
|
@@ -23410,6 +25597,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
23410
25597
|
this.cursorSDKPlugin = new CursorSDKPlugin();
|
|
23411
25598
|
this.cursorSDKPlugin.enable();
|
|
23412
25599
|
}
|
|
25600
|
+
if (integrations.openAIAgents !== false) {
|
|
25601
|
+
this.openAIAgentsPlugin = new OpenAIAgentsPlugin();
|
|
25602
|
+
this.openAIAgentsPlugin.enable();
|
|
25603
|
+
}
|
|
23413
25604
|
if (integrations.googleGenAI !== false && integrations.google !== false) {
|
|
23414
25605
|
this.googleGenAIPlugin = new GoogleGenAIPlugin();
|
|
23415
25606
|
this.googleGenAIPlugin.enable();
|
|
@@ -23450,6 +25641,14 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
23450
25641
|
this.gitHubCopilotPlugin = new GitHubCopilotPlugin();
|
|
23451
25642
|
this.gitHubCopilotPlugin.enable();
|
|
23452
25643
|
}
|
|
25644
|
+
if (getIntegrationConfig(integrations, "flue") !== false) {
|
|
25645
|
+
this.fluePlugin = new FluePlugin();
|
|
25646
|
+
this.fluePlugin.enable();
|
|
25647
|
+
}
|
|
25648
|
+
if (integrations.langchain !== false && integrations.langgraph !== false) {
|
|
25649
|
+
this.langChainPlugin = new LangChainPlugin();
|
|
25650
|
+
this.langChainPlugin.enable();
|
|
25651
|
+
}
|
|
23453
25652
|
}
|
|
23454
25653
|
onDisable() {
|
|
23455
25654
|
if (this.openaiPlugin) {
|
|
@@ -23476,6 +25675,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
23476
25675
|
this.cursorSDKPlugin.disable();
|
|
23477
25676
|
this.cursorSDKPlugin = null;
|
|
23478
25677
|
}
|
|
25678
|
+
if (this.openAIAgentsPlugin) {
|
|
25679
|
+
this.openAIAgentsPlugin.disable();
|
|
25680
|
+
this.openAIAgentsPlugin = null;
|
|
25681
|
+
}
|
|
23479
25682
|
if (this.googleGenAIPlugin) {
|
|
23480
25683
|
this.googleGenAIPlugin.disable();
|
|
23481
25684
|
this.googleGenAIPlugin = null;
|
|
@@ -23516,9 +25719,104 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
23516
25719
|
this.gitHubCopilotPlugin.disable();
|
|
23517
25720
|
this.gitHubCopilotPlugin = null;
|
|
23518
25721
|
}
|
|
25722
|
+
if (this.fluePlugin) {
|
|
25723
|
+
this.fluePlugin.disable();
|
|
25724
|
+
this.fluePlugin = null;
|
|
25725
|
+
}
|
|
25726
|
+
if (this.langChainPlugin) {
|
|
25727
|
+
this.langChainPlugin.disable();
|
|
25728
|
+
this.langChainPlugin = null;
|
|
25729
|
+
}
|
|
23519
25730
|
}
|
|
23520
25731
|
};
|
|
23521
25732
|
|
|
25733
|
+
// src/instrumentation/config.ts
|
|
25734
|
+
var envIntegrationAliases = {
|
|
25735
|
+
openai: "openai",
|
|
25736
|
+
"openai-codex": "openaiCodexSDK",
|
|
25737
|
+
"openai-codex-sdk": "openaiCodexSDK",
|
|
25738
|
+
openaicodexsdk: "openaiCodexSDK",
|
|
25739
|
+
codex: "openaiCodexSDK",
|
|
25740
|
+
"codex-sdk": "openaiCodexSDK",
|
|
25741
|
+
anthropic: "anthropic",
|
|
25742
|
+
aisdk: "aisdk",
|
|
25743
|
+
"ai-sdk": "aisdk",
|
|
25744
|
+
"vercel-ai": "aisdk",
|
|
25745
|
+
vercel: "vercel",
|
|
25746
|
+
claudeagentsdk: "claudeAgentSDK",
|
|
25747
|
+
"claude-agent-sdk": "claudeAgentSDK",
|
|
25748
|
+
cursor: "cursor",
|
|
25749
|
+
"cursor-sdk": "cursorSDK",
|
|
25750
|
+
cursorsdk: "cursorSDK",
|
|
25751
|
+
flue: "flue",
|
|
25752
|
+
"flue-runtime": "flue",
|
|
25753
|
+
"openai-agents": "openAIAgents",
|
|
25754
|
+
openaiagents: "openAIAgents",
|
|
25755
|
+
"openai-agents-core": "openAIAgents",
|
|
25756
|
+
openaiagentscore: "openAIAgents",
|
|
25757
|
+
google: "google",
|
|
25758
|
+
"google-genai": "googleGenAI",
|
|
25759
|
+
googlegenai: "googleGenAI",
|
|
25760
|
+
huggingface: "huggingface",
|
|
25761
|
+
openrouter: "openrouter",
|
|
25762
|
+
openrouteragent: "openrouterAgent",
|
|
25763
|
+
"openrouter-agent": "openrouterAgent",
|
|
25764
|
+
mistral: "mistral",
|
|
25765
|
+
googleadk: "googleADK",
|
|
25766
|
+
"google-adk": "googleADK",
|
|
25767
|
+
cohere: "cohere",
|
|
25768
|
+
groq: "groq",
|
|
25769
|
+
"groq-sdk": "groq",
|
|
25770
|
+
genkit: "genkit",
|
|
25771
|
+
"firebase-genkit": "genkit",
|
|
25772
|
+
githubcopilot: "gitHubCopilot",
|
|
25773
|
+
"github-copilot": "gitHubCopilot",
|
|
25774
|
+
"copilot-sdk": "gitHubCopilot",
|
|
25775
|
+
langchain: "langchain",
|
|
25776
|
+
"langchain-js": "langchain",
|
|
25777
|
+
"@langchain": "langchain",
|
|
25778
|
+
langgraph: "langgraph"
|
|
25779
|
+
};
|
|
25780
|
+
function getDefaultInstrumentationIntegrations() {
|
|
25781
|
+
return {
|
|
25782
|
+
openai: true,
|
|
25783
|
+
openaiCodexSDK: true,
|
|
25784
|
+
anthropic: true,
|
|
25785
|
+
vercel: true,
|
|
25786
|
+
aisdk: true,
|
|
25787
|
+
google: true,
|
|
25788
|
+
googleGenAI: true,
|
|
25789
|
+
googleADK: true,
|
|
25790
|
+
huggingface: true,
|
|
25791
|
+
claudeAgentSDK: true,
|
|
25792
|
+
cursor: true,
|
|
25793
|
+
cursorSDK: true,
|
|
25794
|
+
flue: true,
|
|
25795
|
+
openAIAgents: true,
|
|
25796
|
+
openrouter: true,
|
|
25797
|
+
openrouterAgent: true,
|
|
25798
|
+
mistral: true,
|
|
25799
|
+
cohere: true,
|
|
25800
|
+
groq: true,
|
|
25801
|
+
genkit: true,
|
|
25802
|
+
gitHubCopilot: true,
|
|
25803
|
+
langchain: true,
|
|
25804
|
+
langgraph: true
|
|
25805
|
+
};
|
|
25806
|
+
}
|
|
25807
|
+
function readDisabledInstrumentationEnvConfig(disabledList) {
|
|
25808
|
+
const integrations = {};
|
|
25809
|
+
if (disabledList) {
|
|
25810
|
+
for (const value of disabledList.split(",")) {
|
|
25811
|
+
const sdk = value.trim().toLowerCase();
|
|
25812
|
+
if (sdk.length > 0) {
|
|
25813
|
+
integrations[envIntegrationAliases[sdk] ?? sdk] = false;
|
|
25814
|
+
}
|
|
25815
|
+
}
|
|
25816
|
+
}
|
|
25817
|
+
return { integrations };
|
|
25818
|
+
}
|
|
25819
|
+
|
|
23522
25820
|
// src/instrumentation/registry.ts
|
|
23523
25821
|
var REGISTRY_STATE_KEY = /* @__PURE__ */ Symbol.for("braintrust.registry");
|
|
23524
25822
|
function getSharedState() {
|
|
@@ -23597,50 +25895,16 @@ var PluginRegistry = class {
|
|
|
23597
25895
|
* Get default configuration (all integrations enabled).
|
|
23598
25896
|
*/
|
|
23599
25897
|
getDefaultConfig() {
|
|
23600
|
-
return
|
|
23601
|
-
openai: true,
|
|
23602
|
-
openaiCodexSDK: true,
|
|
23603
|
-
anthropic: true,
|
|
23604
|
-
vercel: true,
|
|
23605
|
-
aisdk: true,
|
|
23606
|
-
google: true,
|
|
23607
|
-
googleGenAI: true,
|
|
23608
|
-
googleADK: true,
|
|
23609
|
-
huggingface: true,
|
|
23610
|
-
claudeAgentSDK: true,
|
|
23611
|
-
cursor: true,
|
|
23612
|
-
cursorSDK: true,
|
|
23613
|
-
openrouter: true,
|
|
23614
|
-
openrouterAgent: true,
|
|
23615
|
-
mistral: true,
|
|
23616
|
-
cohere: true,
|
|
23617
|
-
groq: true,
|
|
23618
|
-
genkit: true,
|
|
23619
|
-
gitHubCopilot: true
|
|
23620
|
-
};
|
|
25898
|
+
return getDefaultInstrumentationIntegrations();
|
|
23621
25899
|
}
|
|
23622
25900
|
/**
|
|
23623
25901
|
* Read configuration from environment variables.
|
|
23624
25902
|
* Supports: BRAINTRUST_DISABLE_INSTRUMENTATION=openai,anthropic,...
|
|
23625
25903
|
*/
|
|
23626
25904
|
readEnvConfig() {
|
|
23627
|
-
|
|
23628
|
-
|
|
23629
|
-
|
|
23630
|
-
const disabled = disabledList.split(",").map((s) => s.trim().toLowerCase()).filter((s) => s.length > 0);
|
|
23631
|
-
for (const sdk of disabled) {
|
|
23632
|
-
if (sdk === "cursor-sdk") {
|
|
23633
|
-
integrations.cursorSDK = false;
|
|
23634
|
-
} else if (sdk === "githubcopilot" || sdk === "github-copilot" || sdk === "copilot-sdk") {
|
|
23635
|
-
integrations.gitHubCopilot = false;
|
|
23636
|
-
} else if (sdk === "openai-codex-sdk") {
|
|
23637
|
-
integrations.openaiCodexSDK = false;
|
|
23638
|
-
} else {
|
|
23639
|
-
integrations[sdk] = false;
|
|
23640
|
-
}
|
|
23641
|
-
}
|
|
23642
|
-
}
|
|
23643
|
-
return { integrations };
|
|
25905
|
+
return readDisabledInstrumentationEnvConfig(
|
|
25906
|
+
isomorph_default.getEnv("BRAINTRUST_DISABLE_INSTRUMENTATION")
|
|
25907
|
+
);
|
|
23644
25908
|
}
|
|
23645
25909
|
};
|
|
23646
25910
|
var registry = new PluginRegistry();
|
|
@@ -23776,8 +26040,10 @@ __export(exports_exports, {
|
|
|
23776
26040
|
Attachment: () => Attachment,
|
|
23777
26041
|
AttachmentReference: () => AttachmentReference,
|
|
23778
26042
|
BRAINTRUST_CURRENT_SPAN_STORE: () => BRAINTRUST_CURRENT_SPAN_STORE,
|
|
26043
|
+
BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME: () => BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME,
|
|
23779
26044
|
BaseAttachment: () => BaseAttachment,
|
|
23780
26045
|
BaseExperiment: () => BaseExperiment,
|
|
26046
|
+
BraintrustLangChainCallbackHandler: () => BraintrustLangChainCallbackHandler,
|
|
23781
26047
|
BraintrustMiddleware: () => BraintrustMiddleware,
|
|
23782
26048
|
BraintrustState: () => BraintrustState,
|
|
23783
26049
|
BraintrustStream: () => BraintrustStream,
|
|
@@ -23903,6 +26169,8 @@ __export(exports_exports, {
|
|
|
23903
26169
|
wrapCohere: () => wrapCohere,
|
|
23904
26170
|
wrapCopilotClient: () => wrapCopilotClient,
|
|
23905
26171
|
wrapCursorSDK: () => wrapCursorSDK,
|
|
26172
|
+
wrapFlueContext: () => wrapFlueContext,
|
|
26173
|
+
wrapFlueSession: () => wrapFlueSession,
|
|
23906
26174
|
wrapGenkit: () => wrapGenkit,
|
|
23907
26175
|
wrapGoogleADK: () => wrapGoogleADK,
|
|
23908
26176
|
wrapGoogleGenAI: () => wrapGoogleGenAI,
|
|
@@ -25002,7 +27270,7 @@ function extractModelParameters(params, excludeKeys) {
|
|
|
25002
27270
|
}
|
|
25003
27271
|
return modelParams;
|
|
25004
27272
|
}
|
|
25005
|
-
function
|
|
27273
|
+
function getNumberProperty3(obj, key) {
|
|
25006
27274
|
if (!obj || typeof obj !== "object" || !(key in obj)) {
|
|
25007
27275
|
return void 0;
|
|
25008
27276
|
}
|
|
@@ -25011,31 +27279,31 @@ function getNumberProperty2(obj, key) {
|
|
|
25011
27279
|
}
|
|
25012
27280
|
function normalizeUsageMetrics(usage, provider, providerMetadata) {
|
|
25013
27281
|
const metrics = {};
|
|
25014
|
-
const inputTokens =
|
|
27282
|
+
const inputTokens = getNumberProperty3(usage, "inputTokens");
|
|
25015
27283
|
if (inputTokens !== void 0) {
|
|
25016
27284
|
metrics.prompt_tokens = inputTokens;
|
|
25017
27285
|
}
|
|
25018
|
-
const outputTokens =
|
|
27286
|
+
const outputTokens = getNumberProperty3(usage, "outputTokens");
|
|
25019
27287
|
if (outputTokens !== void 0) {
|
|
25020
27288
|
metrics.completion_tokens = outputTokens;
|
|
25021
27289
|
}
|
|
25022
|
-
const totalTokens =
|
|
27290
|
+
const totalTokens = getNumberProperty3(usage, "totalTokens");
|
|
25023
27291
|
if (totalTokens !== void 0) {
|
|
25024
27292
|
metrics.tokens = totalTokens;
|
|
25025
27293
|
}
|
|
25026
|
-
const reasoningTokens =
|
|
27294
|
+
const reasoningTokens = getNumberProperty3(usage, "reasoningTokens");
|
|
25027
27295
|
if (reasoningTokens !== void 0) {
|
|
25028
27296
|
metrics.completion_reasoning_tokens = reasoningTokens;
|
|
25029
27297
|
}
|
|
25030
|
-
const cachedInputTokens =
|
|
27298
|
+
const cachedInputTokens = getNumberProperty3(usage, "cachedInputTokens");
|
|
25031
27299
|
if (cachedInputTokens !== void 0) {
|
|
25032
27300
|
metrics.prompt_cached_tokens = cachedInputTokens;
|
|
25033
27301
|
}
|
|
25034
27302
|
if (provider === "anthropic") {
|
|
25035
27303
|
const anthropicMetadata = providerMetadata?.anthropic;
|
|
25036
27304
|
if (anthropicMetadata) {
|
|
25037
|
-
const cacheReadTokens =
|
|
25038
|
-
const cacheCreationTokens =
|
|
27305
|
+
const cacheReadTokens = getNumberProperty3(anthropicMetadata.usage, "cache_read_input_tokens") || 0;
|
|
27306
|
+
const cacheCreationTokens = getNumberProperty3(
|
|
25039
27307
|
anthropicMetadata.usage,
|
|
25040
27308
|
"cache_creation_input_tokens"
|
|
25041
27309
|
) || 0;
|
|
@@ -26010,17 +28278,17 @@ function wrapGenkit(genkit) {
|
|
|
26010
28278
|
console.warn("Unsupported Genkit object. Not wrapping.");
|
|
26011
28279
|
return genkit;
|
|
26012
28280
|
}
|
|
26013
|
-
function
|
|
28281
|
+
function isRecord2(value) {
|
|
26014
28282
|
return typeof value === "object" && value !== null;
|
|
26015
28283
|
}
|
|
26016
28284
|
function isPropertyBag(value) {
|
|
26017
|
-
return
|
|
28285
|
+
return isRecord2(value) || typeof value === "function";
|
|
26018
28286
|
}
|
|
26019
28287
|
function hasFunction(value, methodName) {
|
|
26020
28288
|
return isPropertyBag(value) && methodName in value && typeof value[methodName] === "function";
|
|
26021
28289
|
}
|
|
26022
28290
|
function isGenkitInstance(value) {
|
|
26023
|
-
return
|
|
28291
|
+
return isRecord2(value) && (hasFunction(value, "generate") || hasFunction(value, "generateStream") || hasFunction(value, "defineFlow") || hasFunction(value, "defineTool"));
|
|
26024
28292
|
}
|
|
26025
28293
|
function isGenkitModule(value) {
|
|
26026
28294
|
return hasFunction(value, "genkit");
|
|
@@ -26074,7 +28342,7 @@ function patchGenkitRegistry(instance) {
|
|
|
26074
28342
|
patchGenkitRegistryConstructor(registry2);
|
|
26075
28343
|
}
|
|
26076
28344
|
function patchGenkitRegistryLookup(registry2) {
|
|
26077
|
-
if (!
|
|
28345
|
+
if (!isRecord2(registry2) || hasRegistryPatchedFlag(registry2) || !hasFunction(registry2, "lookupAction")) {
|
|
26078
28346
|
return;
|
|
26079
28347
|
}
|
|
26080
28348
|
const originalLookupAction = registry2.lookupAction;
|
|
@@ -26100,7 +28368,7 @@ function patchGenkitRegistryLookup(registry2) {
|
|
|
26100
28368
|
}
|
|
26101
28369
|
}
|
|
26102
28370
|
function patchGenkitRegistryConstructor(registry2) {
|
|
26103
|
-
if (!
|
|
28371
|
+
if (!isRecord2(registry2)) {
|
|
26104
28372
|
return;
|
|
26105
28373
|
}
|
|
26106
28374
|
const constructor = registry2.constructor;
|
|
@@ -26116,7 +28384,7 @@ function patchGenkitRegistryConstructor(registry2) {
|
|
|
26116
28384
|
configurable: true,
|
|
26117
28385
|
value: (...args) => {
|
|
26118
28386
|
const childRegistry = originalWithParent.apply(constructor, args);
|
|
26119
|
-
if (args.some((arg) =>
|
|
28387
|
+
if (args.some((arg) => isRecord2(arg) && hasRegistryPatchedFlag(arg))) {
|
|
26120
28388
|
patchGenkitRegistryLookup(childRegistry);
|
|
26121
28389
|
patchGenkitRegistryConstructor(childRegistry);
|
|
26122
28390
|
}
|
|
@@ -26215,7 +28483,7 @@ function hasRegistryConstructorPatchedFlag(value) {
|
|
|
26215
28483
|
);
|
|
26216
28484
|
}
|
|
26217
28485
|
function isPromiseLike2(value) {
|
|
26218
|
-
return
|
|
28486
|
+
return isRecord2(value) && "then" in value && typeof value.then === "function";
|
|
26219
28487
|
}
|
|
26220
28488
|
|
|
26221
28489
|
// src/wrappers/huggingface.ts
|
|
@@ -26578,14 +28846,14 @@ function wrapMistral(mistral) {
|
|
|
26578
28846
|
console.warn("Unsupported Mistral library. Not wrapping.");
|
|
26579
28847
|
return mistral;
|
|
26580
28848
|
}
|
|
26581
|
-
function
|
|
28849
|
+
function isRecord3(value) {
|
|
26582
28850
|
return typeof value === "object" && value !== null;
|
|
26583
28851
|
}
|
|
26584
28852
|
function hasFunction3(value, methodName) {
|
|
26585
|
-
return
|
|
28853
|
+
return isRecord3(value) && methodName in value && typeof value[methodName] === "function";
|
|
26586
28854
|
}
|
|
26587
28855
|
function isSupportedMistralClient(value) {
|
|
26588
|
-
if (!
|
|
28856
|
+
if (!isRecord3(value)) {
|
|
26589
28857
|
return false;
|
|
26590
28858
|
}
|
|
26591
28859
|
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);
|
|
@@ -26769,14 +29037,14 @@ function wrapCohere(cohere) {
|
|
|
26769
29037
|
return cohere;
|
|
26770
29038
|
}
|
|
26771
29039
|
var cohereProxyCache = /* @__PURE__ */ new WeakMap();
|
|
26772
|
-
function
|
|
29040
|
+
function isRecord4(value) {
|
|
26773
29041
|
return typeof value === "object" && value !== null;
|
|
26774
29042
|
}
|
|
26775
29043
|
function hasFunction4(value, methodName) {
|
|
26776
|
-
return
|
|
29044
|
+
return isRecord4(value) && methodName in value && typeof value[methodName] === "function";
|
|
26777
29045
|
}
|
|
26778
29046
|
function isSupportedCohereClient(value) {
|
|
26779
|
-
if (!
|
|
29047
|
+
if (!isRecord4(value)) {
|
|
26780
29048
|
return false;
|
|
26781
29049
|
}
|
|
26782
29050
|
return hasFunction4(value, "chat") || hasFunction4(value, "chatStream") || hasFunction4(value, "embed") || hasFunction4(value, "rerank");
|
|
@@ -26836,20 +29104,20 @@ function wrapGroq(groq) {
|
|
|
26836
29104
|
console.warn("Unsupported Groq library. Not wrapping.");
|
|
26837
29105
|
return groq;
|
|
26838
29106
|
}
|
|
26839
|
-
function
|
|
29107
|
+
function isRecord5(value) {
|
|
26840
29108
|
return typeof value === "object" && value !== null;
|
|
26841
29109
|
}
|
|
26842
29110
|
function hasFunction5(value, methodName) {
|
|
26843
|
-
return
|
|
29111
|
+
return isRecord5(value) && methodName in value && typeof value[methodName] === "function";
|
|
26844
29112
|
}
|
|
26845
29113
|
function hasChat2(value) {
|
|
26846
|
-
return
|
|
29114
|
+
return isRecord5(value) && isRecord5(value.completions) && hasFunction5(value.completions, "create");
|
|
26847
29115
|
}
|
|
26848
29116
|
function hasEmbeddings2(value) {
|
|
26849
29117
|
return hasFunction5(value, "create");
|
|
26850
29118
|
}
|
|
26851
29119
|
function isSupportedGroqClient(value) {
|
|
26852
|
-
return
|
|
29120
|
+
return isRecord5(value) && (value.chat !== void 0 && hasChat2(value.chat) || value.embeddings !== void 0 && hasEmbeddings2(value.embeddings));
|
|
26853
29121
|
}
|
|
26854
29122
|
function groqProxy(groq) {
|
|
26855
29123
|
const privateMethodWorkaroundCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -30827,8 +33095,10 @@ export {
|
|
|
30827
33095
|
Attachment,
|
|
30828
33096
|
AttachmentReference,
|
|
30829
33097
|
BRAINTRUST_CURRENT_SPAN_STORE,
|
|
33098
|
+
BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME,
|
|
30830
33099
|
BaseAttachment,
|
|
30831
33100
|
BaseExperiment,
|
|
33101
|
+
BraintrustLangChainCallbackHandler,
|
|
30832
33102
|
BraintrustMiddleware,
|
|
30833
33103
|
BraintrustState,
|
|
30834
33104
|
BraintrustStream,
|
|
@@ -30955,6 +33225,8 @@ export {
|
|
|
30955
33225
|
wrapCohere,
|
|
30956
33226
|
wrapCopilotClient,
|
|
30957
33227
|
wrapCursorSDK,
|
|
33228
|
+
wrapFlueContext,
|
|
33229
|
+
wrapFlueSession,
|
|
30958
33230
|
wrapGenkit,
|
|
30959
33231
|
wrapGoogleADK,
|
|
30960
33232
|
wrapGoogleGenAI,
|