braintrust 3.11.0 → 3.13.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 +26 -7
- package/dev/dist/index.d.ts +26 -7
- package/dev/dist/index.js +2717 -335
- package/dev/dist/index.mjs +2499 -117
- 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 +1803 -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 +3269 -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 +1803 -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 +1803 -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 +1861 -1308
- package/dist/auto-instrumentations/bundler/webpack-loader.d.ts +3 -3
- package/dist/auto-instrumentations/bundler/webpack.cjs +1803 -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-E5DUYJWK.mjs} +338 -1
- package/dist/auto-instrumentations/chunk-GJOO4ESL.mjs +300 -0
- package/dist/auto-instrumentations/chunk-WFEUJACP.mjs +18 -0
- package/dist/auto-instrumentations/hook.mjs +1713 -1460
- package/dist/auto-instrumentations/index.cjs +94 -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 +264 -47
- package/dist/browser.d.ts +264 -47
- package/dist/browser.js +2521 -159
- package/dist/browser.mjs +2521 -159
- package/dist/chunk-26JGOELH.js +817 -0
- package/dist/chunk-75IQCUB2.mjs +817 -0
- package/dist/cli.js +2510 -122
- package/dist/edge-light.d.mts +1 -1
- package/dist/edge-light.d.ts +1 -1
- package/dist/edge-light.js +2521 -159
- package/dist/edge-light.mjs +2521 -159
- package/dist/index.d.mts +264 -47
- package/dist/index.d.ts +264 -47
- package/dist/index.js +3498 -1850
- package/dist/index.mjs +2635 -987
- package/dist/instrumentation/index.d.mts +7897 -48
- package/dist/instrumentation/index.d.ts +7897 -48
- package/dist/instrumentation/index.js +2408 -95
- package/dist/instrumentation/index.mjs +2407 -95
- package/dist/workerd.d.mts +1 -1
- package/dist/workerd.d.ts +1 -1
- package/dist/workerd.js +2521 -159
- package/dist/workerd.mjs +2521 -159
- package/package.json +23 -17
- package/util/dist/index.d.mts +3 -1
- package/util/dist/index.d.ts +3 -1
- 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
|
@@ -83,6 +83,7 @@ var iso = {
|
|
|
83
83
|
getRepoInfo: async (_settings) => void 0,
|
|
84
84
|
getPastNAncestors: async () => [],
|
|
85
85
|
getEnv: (_name) => void 0,
|
|
86
|
+
getBraintrustApiKey: async () => void 0,
|
|
86
87
|
getCallerLocation: () => void 0,
|
|
87
88
|
newAsyncLocalStorage: () => new DefaultAsyncLocalStorage(),
|
|
88
89
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -1126,6 +1127,11 @@ function isPromiseLike(value) {
|
|
|
1126
1127
|
|
|
1127
1128
|
// util/object_util.ts
|
|
1128
1129
|
var SET_UNION_FIELDS = /* @__PURE__ */ new Set(["tags"]);
|
|
1130
|
+
var FORBIDDEN_MERGE_KEYS = /* @__PURE__ */ new Set([
|
|
1131
|
+
"__proto__",
|
|
1132
|
+
"constructor",
|
|
1133
|
+
"prototype"
|
|
1134
|
+
]);
|
|
1129
1135
|
function mergeDictsWithPaths({
|
|
1130
1136
|
mergeInto,
|
|
1131
1137
|
mergeFrom,
|
|
@@ -1148,6 +1154,7 @@ function mergeDictsWithPathsHelper({
|
|
|
1148
1154
|
mergePaths
|
|
1149
1155
|
}) {
|
|
1150
1156
|
Object.entries(mergeFrom).forEach(([k, mergeFromV]) => {
|
|
1157
|
+
if (FORBIDDEN_MERGE_KEYS.has(k)) return;
|
|
1151
1158
|
const fullPath = path.concat([k]);
|
|
1152
1159
|
const fullPathSerialized = JSON.stringify(fullPath);
|
|
1153
1160
|
const mergeIntoV = recordFind(mergeInto, k);
|
|
@@ -5019,6 +5026,13 @@ var HTTPConnection = class _HTTPConnection {
|
|
|
5019
5026
|
debugLogger.debug(
|
|
5020
5027
|
`Retrying API request ${object_type} ${JSON.stringify(args)} ${e.status} ${e.text}`
|
|
5021
5028
|
);
|
|
5029
|
+
const sleepTimeS = HTTP_RETRY_BASE_SLEEP_TIME_S * 2 ** i;
|
|
5030
|
+
debugLogger.info(
|
|
5031
|
+
`Sleeping for ${sleepTimeS}s before retrying API request`
|
|
5032
|
+
);
|
|
5033
|
+
await new Promise(
|
|
5034
|
+
(resolve) => setTimeout(resolve, sleepTimeS * 1e3)
|
|
5035
|
+
);
|
|
5022
5036
|
continue;
|
|
5023
5037
|
}
|
|
5024
5038
|
throw e;
|
|
@@ -5541,20 +5555,7 @@ function startSpanParentArgs(args) {
|
|
|
5541
5555
|
`Mismatch between expected span parent object type ${args.parentObjectType} and provided type ${parentComponents.data.object_type}`
|
|
5542
5556
|
);
|
|
5543
5557
|
}
|
|
5544
|
-
|
|
5545
|
-
args.state,
|
|
5546
|
-
parentComponents
|
|
5547
|
-
);
|
|
5548
|
-
const computeParentObjectId = async () => {
|
|
5549
|
-
const parentComponentsObjectId = await parentComponentsObjectIdLambda();
|
|
5550
|
-
if (await args.parentObjectId.get() !== parentComponentsObjectId) {
|
|
5551
|
-
throw new Error(
|
|
5552
|
-
`Mismatch between expected span parent object id ${await args.parentObjectId.get()} and provided id ${parentComponentsObjectId}`
|
|
5553
|
-
);
|
|
5554
|
-
}
|
|
5555
|
-
return await args.parentObjectId.get();
|
|
5556
|
-
};
|
|
5557
|
-
argParentObjectId = new LazyValue(computeParentObjectId);
|
|
5558
|
+
argParentObjectId = args.parentObjectId;
|
|
5558
5559
|
if (parentComponents.data.row_id) {
|
|
5559
5560
|
argParentSpanIds = {
|
|
5560
5561
|
spanId: parentComponents.data.span_id,
|
|
@@ -5883,6 +5884,7 @@ function now() {
|
|
|
5883
5884
|
}
|
|
5884
5885
|
var DEFAULT_FLUSH_BACKPRESSURE_BYTES = 10 * 1024 * 1024;
|
|
5885
5886
|
var BACKGROUND_LOGGER_BASE_SLEEP_TIME_S = 1;
|
|
5887
|
+
var HTTP_RETRY_BASE_SLEEP_TIME_S = 1;
|
|
5886
5888
|
var HTTPBackgroundLogger = class _HTTPBackgroundLogger {
|
|
5887
5889
|
apiConn;
|
|
5888
5890
|
queue;
|
|
@@ -6455,13 +6457,63 @@ async function computeLoggerMetadata(state, {
|
|
|
6455
6457
|
};
|
|
6456
6458
|
}
|
|
6457
6459
|
}
|
|
6460
|
+
function initLogger(options = {}) {
|
|
6461
|
+
const {
|
|
6462
|
+
projectName,
|
|
6463
|
+
projectId,
|
|
6464
|
+
asyncFlush: asyncFlushArg,
|
|
6465
|
+
appUrl,
|
|
6466
|
+
apiKey,
|
|
6467
|
+
orgName,
|
|
6468
|
+
forceLogin,
|
|
6469
|
+
debugLogLevel,
|
|
6470
|
+
fetch: fetch2,
|
|
6471
|
+
state: stateArg
|
|
6472
|
+
} = options || {};
|
|
6473
|
+
const asyncFlush = asyncFlushArg === void 0 ? true : asyncFlushArg;
|
|
6474
|
+
const computeMetadataArgs = {
|
|
6475
|
+
project_name: projectName,
|
|
6476
|
+
project_id: projectId
|
|
6477
|
+
};
|
|
6478
|
+
const linkArgs = {
|
|
6479
|
+
org_name: orgName,
|
|
6480
|
+
app_url: appUrl,
|
|
6481
|
+
project_name: projectName,
|
|
6482
|
+
project_id: projectId
|
|
6483
|
+
};
|
|
6484
|
+
const state = stateArg ?? _globalState;
|
|
6485
|
+
state.setDebugLogLevel(debugLogLevel);
|
|
6486
|
+
state.enforceQueueSizeLimit(true);
|
|
6487
|
+
const lazyMetadata = new LazyValue(
|
|
6488
|
+
async () => {
|
|
6489
|
+
await state.login({
|
|
6490
|
+
orgName,
|
|
6491
|
+
apiKey,
|
|
6492
|
+
appUrl,
|
|
6493
|
+
forceLogin,
|
|
6494
|
+
fetch: fetch2
|
|
6495
|
+
});
|
|
6496
|
+
return computeLoggerMetadata(state, computeMetadataArgs);
|
|
6497
|
+
}
|
|
6498
|
+
);
|
|
6499
|
+
const ret = new Logger(state, lazyMetadata, {
|
|
6500
|
+
asyncFlush,
|
|
6501
|
+
computeMetadataArgs,
|
|
6502
|
+
linkArgs
|
|
6503
|
+
});
|
|
6504
|
+
if (options.setCurrent ?? true) {
|
|
6505
|
+
state.currentLogger = ret;
|
|
6506
|
+
}
|
|
6507
|
+
return ret;
|
|
6508
|
+
}
|
|
6458
6509
|
async function loginToState(options = {}) {
|
|
6459
6510
|
const {
|
|
6460
6511
|
appUrl = isomorph_default.getEnv("BRAINTRUST_APP_URL") || "https://www.braintrust.dev",
|
|
6461
|
-
apiKey
|
|
6512
|
+
apiKey: apiKeyArg,
|
|
6462
6513
|
orgName = isomorph_default.getEnv("BRAINTRUST_ORG_NAME"),
|
|
6463
6514
|
fetch: fetch2 = globalThis.fetch
|
|
6464
6515
|
} = options || {};
|
|
6516
|
+
const apiKey = apiKeyArg !== void 0 ? apiKeyArg : await isomorph_default.getBraintrustApiKey();
|
|
6465
6517
|
const appPublicUrl = isomorph_default.getEnv("BRAINTRUST_APP_PUBLIC_URL") || appUrl;
|
|
6466
6518
|
const state = new BraintrustState(options);
|
|
6467
6519
|
state.resetLoginInfo();
|
|
@@ -7392,9 +7444,15 @@ var SpanImpl = class _SpanImpl {
|
|
|
7392
7444
|
const cachedSpan = {
|
|
7393
7445
|
input: partialRecord.input,
|
|
7394
7446
|
output: partialRecord.output,
|
|
7447
|
+
expected: partialRecord.expected,
|
|
7448
|
+
error: partialRecord.error,
|
|
7449
|
+
scores: partialRecord.scores,
|
|
7450
|
+
metrics: partialRecord.metrics,
|
|
7395
7451
|
metadata: partialRecord.metadata,
|
|
7452
|
+
tags: partialRecord.tags,
|
|
7396
7453
|
span_id: this._spanId,
|
|
7397
7454
|
span_parents: this._spanParents,
|
|
7455
|
+
is_root: this._spanId === this._rootSpanId,
|
|
7398
7456
|
span_attributes: partialRecord.span_attributes
|
|
7399
7457
|
};
|
|
7400
7458
|
this._state.spanCache.queueWrite(
|
|
@@ -7730,6 +7788,7 @@ var Dataset2 = class extends ObjectFetcher {
|
|
|
7730
7788
|
metadata,
|
|
7731
7789
|
tags,
|
|
7732
7790
|
output,
|
|
7791
|
+
origin,
|
|
7733
7792
|
isMerge
|
|
7734
7793
|
}) {
|
|
7735
7794
|
return new LazyValue(async () => {
|
|
@@ -7744,6 +7803,7 @@ var Dataset2 = class extends ObjectFetcher {
|
|
|
7744
7803
|
created: !isMerge ? (/* @__PURE__ */ new Date()).toISOString() : void 0,
|
|
7745
7804
|
//if we're merging/updating an event we will not add this ts
|
|
7746
7805
|
metadata,
|
|
7806
|
+
origin,
|
|
7747
7807
|
...!!isMerge ? {
|
|
7748
7808
|
[IS_MERGE_FIELD]: true
|
|
7749
7809
|
} : {}
|
|
@@ -7763,6 +7823,7 @@ var Dataset2 = class extends ObjectFetcher {
|
|
|
7763
7823
|
* about anything else that's relevant, that you can use to help find and analyze examples later. For example, you could log the
|
|
7764
7824
|
* `prompt`, example's `id`, or anything else that would be useful to slice/dice later. The values in `metadata` can be any
|
|
7765
7825
|
* JSON-serializable type, but its keys must be strings.
|
|
7826
|
+
* @param event.origin (Optional) a reference to the source object this dataset record was derived from.
|
|
7766
7827
|
* @param event.id (Optional) a unique identifier for the event. If you don't provide one, Braintrust will generate one for you.
|
|
7767
7828
|
* @param event.output: (Deprecated) The output of your application. Use `expected` instead.
|
|
7768
7829
|
* @returns The `id` of the logged record.
|
|
@@ -7773,7 +7834,8 @@ var Dataset2 = class extends ObjectFetcher {
|
|
|
7773
7834
|
metadata,
|
|
7774
7835
|
tags,
|
|
7775
7836
|
id,
|
|
7776
|
-
output
|
|
7837
|
+
output,
|
|
7838
|
+
origin
|
|
7777
7839
|
}) {
|
|
7778
7840
|
this.validateEvent({ metadata, expected, output, tags });
|
|
7779
7841
|
const rowId = id || uuidv42();
|
|
@@ -7785,6 +7847,7 @@ var Dataset2 = class extends ObjectFetcher {
|
|
|
7785
7847
|
metadata,
|
|
7786
7848
|
tags,
|
|
7787
7849
|
output,
|
|
7850
|
+
origin,
|
|
7788
7851
|
isMerge: false
|
|
7789
7852
|
})
|
|
7790
7853
|
);
|
|
@@ -11378,11 +11441,11 @@ function resolveDenyOutputPaths(event, defaultDenyOutputPaths) {
|
|
|
11378
11441
|
if (Array.isArray(event?.denyOutputPaths)) {
|
|
11379
11442
|
return event.denyOutputPaths;
|
|
11380
11443
|
}
|
|
11381
|
-
const
|
|
11382
|
-
if (!
|
|
11444
|
+
const firstArgument2 = event?.arguments && event.arguments.length > 0 ? event.arguments[0] : void 0;
|
|
11445
|
+
if (!firstArgument2 || typeof firstArgument2 !== "object") {
|
|
11383
11446
|
return defaultDenyOutputPaths;
|
|
11384
11447
|
}
|
|
11385
|
-
const runtimeDenyOutputPaths =
|
|
11448
|
+
const runtimeDenyOutputPaths = firstArgument2[RUNTIME_DENY_OUTPUT_PATHS];
|
|
11386
11449
|
if (Array.isArray(runtimeDenyOutputPaths) && runtimeDenyOutputPaths.every((path) => typeof path === "string")) {
|
|
11387
11450
|
return runtimeDenyOutputPaths;
|
|
11388
11451
|
}
|
|
@@ -15041,6 +15104,467 @@ function cleanMetrics2(metrics) {
|
|
|
15041
15104
|
return cleaned;
|
|
15042
15105
|
}
|
|
15043
15106
|
|
|
15107
|
+
// src/instrumentation/plugins/openai-agents-channels.ts
|
|
15108
|
+
var openAIAgentsCoreChannels = defineChannels("@openai/agents-core", {
|
|
15109
|
+
onTraceStart: channel({
|
|
15110
|
+
channelName: "tracing.processor.onTraceStart",
|
|
15111
|
+
kind: "async"
|
|
15112
|
+
}),
|
|
15113
|
+
onTraceEnd: channel({
|
|
15114
|
+
channelName: "tracing.processor.onTraceEnd",
|
|
15115
|
+
kind: "async"
|
|
15116
|
+
}),
|
|
15117
|
+
onSpanStart: channel({
|
|
15118
|
+
channelName: "tracing.processor.onSpanStart",
|
|
15119
|
+
kind: "async"
|
|
15120
|
+
}),
|
|
15121
|
+
onSpanEnd: channel({
|
|
15122
|
+
channelName: "tracing.processor.onSpanEnd",
|
|
15123
|
+
kind: "async"
|
|
15124
|
+
})
|
|
15125
|
+
});
|
|
15126
|
+
|
|
15127
|
+
// src/instrumentation/plugins/openai-agents-trace-processor.ts
|
|
15128
|
+
function isSpanData(spanData, type) {
|
|
15129
|
+
return spanData.type === type;
|
|
15130
|
+
}
|
|
15131
|
+
function spanTypeFromAgents(span) {
|
|
15132
|
+
const spanType = span.spanData.type;
|
|
15133
|
+
if (spanType === "function" || spanType === "guardrail" || spanType === "mcp_tools") {
|
|
15134
|
+
return "tool" /* TOOL */;
|
|
15135
|
+
}
|
|
15136
|
+
if (spanType === "generation" || spanType === "response" || spanType === "transcription" || spanType === "speech") {
|
|
15137
|
+
return "llm" /* LLM */;
|
|
15138
|
+
}
|
|
15139
|
+
return "task" /* TASK */;
|
|
15140
|
+
}
|
|
15141
|
+
function spanNameFromAgents(span) {
|
|
15142
|
+
const spanData = span.spanData;
|
|
15143
|
+
if ("name" in spanData && spanData.name) {
|
|
15144
|
+
return spanData.name;
|
|
15145
|
+
}
|
|
15146
|
+
switch (spanData.type) {
|
|
15147
|
+
case "generation":
|
|
15148
|
+
return "Generation";
|
|
15149
|
+
case "response":
|
|
15150
|
+
return "Response";
|
|
15151
|
+
case "handoff":
|
|
15152
|
+
return "Handoff";
|
|
15153
|
+
case "mcp_tools":
|
|
15154
|
+
return isSpanData(spanData, "mcp_tools") && spanData.server ? `List Tools (${spanData.server})` : "MCP List Tools";
|
|
15155
|
+
case "transcription":
|
|
15156
|
+
return "Transcription";
|
|
15157
|
+
case "speech":
|
|
15158
|
+
return "Speech";
|
|
15159
|
+
case "speech_group":
|
|
15160
|
+
return "Speech Group";
|
|
15161
|
+
default:
|
|
15162
|
+
return "Unknown";
|
|
15163
|
+
}
|
|
15164
|
+
}
|
|
15165
|
+
function getTimeElapsed(end, start) {
|
|
15166
|
+
if (!start || !end) {
|
|
15167
|
+
return void 0;
|
|
15168
|
+
}
|
|
15169
|
+
const startTime = new Date(start).getTime();
|
|
15170
|
+
const endTime = new Date(end).getTime();
|
|
15171
|
+
if (Number.isNaN(startTime) || Number.isNaN(endTime)) {
|
|
15172
|
+
return void 0;
|
|
15173
|
+
}
|
|
15174
|
+
return (endTime - startTime) / 1e3;
|
|
15175
|
+
}
|
|
15176
|
+
function getNumberProperty2(obj, key) {
|
|
15177
|
+
if (!isObject(obj) || !(key in obj)) {
|
|
15178
|
+
return void 0;
|
|
15179
|
+
}
|
|
15180
|
+
const value = obj[key];
|
|
15181
|
+
return typeof value === "number" ? value : void 0;
|
|
15182
|
+
}
|
|
15183
|
+
function parseUsageMetrics(usage) {
|
|
15184
|
+
const metrics = {};
|
|
15185
|
+
if (!isObject(usage)) {
|
|
15186
|
+
return metrics;
|
|
15187
|
+
}
|
|
15188
|
+
const promptTokens = getNumberProperty2(usage, "prompt_tokens") ?? getNumberProperty2(usage, "input_tokens") ?? getNumberProperty2(usage, "promptTokens") ?? getNumberProperty2(usage, "inputTokens");
|
|
15189
|
+
const completionTokens = getNumberProperty2(usage, "completion_tokens") ?? getNumberProperty2(usage, "output_tokens") ?? getNumberProperty2(usage, "completionTokens") ?? getNumberProperty2(usage, "outputTokens");
|
|
15190
|
+
const totalTokens = getNumberProperty2(usage, "total_tokens") ?? getNumberProperty2(usage, "totalTokens");
|
|
15191
|
+
if (promptTokens !== void 0) {
|
|
15192
|
+
metrics.prompt_tokens = promptTokens;
|
|
15193
|
+
}
|
|
15194
|
+
if (completionTokens !== void 0) {
|
|
15195
|
+
metrics.completion_tokens = completionTokens;
|
|
15196
|
+
}
|
|
15197
|
+
if (totalTokens !== void 0) {
|
|
15198
|
+
metrics.tokens = totalTokens;
|
|
15199
|
+
} else if (promptTokens !== void 0 && completionTokens !== void 0) {
|
|
15200
|
+
metrics.tokens = promptTokens + completionTokens;
|
|
15201
|
+
}
|
|
15202
|
+
const inputDetails = usage.input_tokens_details;
|
|
15203
|
+
const cachedTokens = getNumberProperty2(inputDetails, "cached_tokens");
|
|
15204
|
+
const cacheWriteTokens = getNumberProperty2(
|
|
15205
|
+
inputDetails,
|
|
15206
|
+
"cache_write_tokens"
|
|
15207
|
+
);
|
|
15208
|
+
if (cachedTokens !== void 0) {
|
|
15209
|
+
metrics.prompt_cached_tokens = cachedTokens;
|
|
15210
|
+
}
|
|
15211
|
+
if (cacheWriteTokens !== void 0) {
|
|
15212
|
+
metrics.prompt_cache_creation_tokens = cacheWriteTokens;
|
|
15213
|
+
}
|
|
15214
|
+
return metrics;
|
|
15215
|
+
}
|
|
15216
|
+
var OpenAIAgentsTraceProcessor = class _OpenAIAgentsTraceProcessor {
|
|
15217
|
+
static DEFAULT_MAX_TRACES = 1e4;
|
|
15218
|
+
logger;
|
|
15219
|
+
maxTraces;
|
|
15220
|
+
traceSpans = /* @__PURE__ */ new Map();
|
|
15221
|
+
traceOrder = [];
|
|
15222
|
+
_traceSpans = this.traceSpans;
|
|
15223
|
+
constructor(options = {}) {
|
|
15224
|
+
this.logger = options.logger;
|
|
15225
|
+
this.maxTraces = options.maxTraces ?? _OpenAIAgentsTraceProcessor.DEFAULT_MAX_TRACES;
|
|
15226
|
+
}
|
|
15227
|
+
evictOldestTrace() {
|
|
15228
|
+
const oldestTraceId = this.traceOrder.shift();
|
|
15229
|
+
if (oldestTraceId) {
|
|
15230
|
+
this.traceSpans.delete(oldestTraceId);
|
|
15231
|
+
}
|
|
15232
|
+
}
|
|
15233
|
+
onTraceStart(trace) {
|
|
15234
|
+
if (!trace?.traceId) {
|
|
15235
|
+
return Promise.resolve();
|
|
15236
|
+
}
|
|
15237
|
+
if (this.traceOrder.length >= this.maxTraces) {
|
|
15238
|
+
this.evictOldestTrace();
|
|
15239
|
+
}
|
|
15240
|
+
const current = currentSpan();
|
|
15241
|
+
const span = current && current !== NOOP_SPAN ? current.startSpan({
|
|
15242
|
+
name: trace.name,
|
|
15243
|
+
type: "task" /* TASK */
|
|
15244
|
+
}) : this.logger ? this.logger.startSpan({
|
|
15245
|
+
name: trace.name,
|
|
15246
|
+
type: "task" /* TASK */
|
|
15247
|
+
}) : startSpan({
|
|
15248
|
+
name: trace.name,
|
|
15249
|
+
type: "task" /* TASK */
|
|
15250
|
+
});
|
|
15251
|
+
span.log({
|
|
15252
|
+
input: "Agent workflow started",
|
|
15253
|
+
metadata: {
|
|
15254
|
+
group_id: trace.groupId,
|
|
15255
|
+
...trace.metadata || {}
|
|
15256
|
+
}
|
|
15257
|
+
});
|
|
15258
|
+
this.traceSpans.set(trace.traceId, {
|
|
15259
|
+
rootSpan: span,
|
|
15260
|
+
childSpans: /* @__PURE__ */ new Map(),
|
|
15261
|
+
metadata: {
|
|
15262
|
+
firstInput: null,
|
|
15263
|
+
lastOutput: null
|
|
15264
|
+
}
|
|
15265
|
+
});
|
|
15266
|
+
this.traceOrder.push(trace.traceId);
|
|
15267
|
+
return Promise.resolve();
|
|
15268
|
+
}
|
|
15269
|
+
async onTraceEnd(trace) {
|
|
15270
|
+
const traceData = this.traceSpans.get(trace?.traceId);
|
|
15271
|
+
if (!traceData) {
|
|
15272
|
+
return;
|
|
15273
|
+
}
|
|
15274
|
+
try {
|
|
15275
|
+
traceData.rootSpan.log({
|
|
15276
|
+
input: traceData.metadata.firstInput,
|
|
15277
|
+
output: traceData.metadata.lastOutput
|
|
15278
|
+
});
|
|
15279
|
+
traceData.rootSpan.end();
|
|
15280
|
+
await traceData.rootSpan.flush();
|
|
15281
|
+
} finally {
|
|
15282
|
+
this.traceSpans.delete(trace.traceId);
|
|
15283
|
+
const orderIndex = this.traceOrder.indexOf(trace.traceId);
|
|
15284
|
+
if (orderIndex > -1) {
|
|
15285
|
+
this.traceOrder.splice(orderIndex, 1);
|
|
15286
|
+
}
|
|
15287
|
+
}
|
|
15288
|
+
}
|
|
15289
|
+
onSpanStart(span) {
|
|
15290
|
+
if (!span?.spanId || !span.traceId) {
|
|
15291
|
+
return Promise.resolve();
|
|
15292
|
+
}
|
|
15293
|
+
const traceData = this.traceSpans.get(span.traceId);
|
|
15294
|
+
if (!traceData) {
|
|
15295
|
+
return Promise.resolve();
|
|
15296
|
+
}
|
|
15297
|
+
const parentSpan = span.parentId ? traceData.childSpans.get(span.parentId) : traceData.rootSpan;
|
|
15298
|
+
if (!parentSpan) {
|
|
15299
|
+
return Promise.resolve();
|
|
15300
|
+
}
|
|
15301
|
+
const childSpan = parentSpan.startSpan({
|
|
15302
|
+
name: spanNameFromAgents(span),
|
|
15303
|
+
type: spanTypeFromAgents(span)
|
|
15304
|
+
});
|
|
15305
|
+
traceData.childSpans.set(span.spanId, childSpan);
|
|
15306
|
+
return Promise.resolve();
|
|
15307
|
+
}
|
|
15308
|
+
onSpanEnd(span) {
|
|
15309
|
+
if (!span?.spanId || !span.traceId) {
|
|
15310
|
+
return Promise.resolve();
|
|
15311
|
+
}
|
|
15312
|
+
const traceData = this.traceSpans.get(span.traceId);
|
|
15313
|
+
if (!traceData) {
|
|
15314
|
+
return Promise.resolve();
|
|
15315
|
+
}
|
|
15316
|
+
const braintrustSpan = traceData.childSpans.get(span.spanId);
|
|
15317
|
+
if (!braintrustSpan) {
|
|
15318
|
+
return Promise.resolve();
|
|
15319
|
+
}
|
|
15320
|
+
const logData = this.extractLogData(span);
|
|
15321
|
+
braintrustSpan.log({
|
|
15322
|
+
error: span.error,
|
|
15323
|
+
...logData
|
|
15324
|
+
});
|
|
15325
|
+
braintrustSpan.end();
|
|
15326
|
+
traceData.childSpans.delete(span.spanId);
|
|
15327
|
+
const input = logData.input;
|
|
15328
|
+
const output = logData.output;
|
|
15329
|
+
if (traceData.metadata.firstInput === null && input != null) {
|
|
15330
|
+
traceData.metadata.firstInput = input;
|
|
15331
|
+
}
|
|
15332
|
+
if (output != null) {
|
|
15333
|
+
traceData.metadata.lastOutput = output;
|
|
15334
|
+
}
|
|
15335
|
+
return Promise.resolve();
|
|
15336
|
+
}
|
|
15337
|
+
async shutdown() {
|
|
15338
|
+
if (this.logger && typeof this.logger.flush === "function") {
|
|
15339
|
+
await this.logger.flush();
|
|
15340
|
+
}
|
|
15341
|
+
}
|
|
15342
|
+
async forceFlush() {
|
|
15343
|
+
if (this.logger && typeof this.logger.flush === "function") {
|
|
15344
|
+
await this.logger.flush();
|
|
15345
|
+
}
|
|
15346
|
+
}
|
|
15347
|
+
extractLogData(span) {
|
|
15348
|
+
const spanData = span.spanData;
|
|
15349
|
+
switch (spanData.type) {
|
|
15350
|
+
case "agent":
|
|
15351
|
+
return this.extractAgentLogData(spanData);
|
|
15352
|
+
case "response":
|
|
15353
|
+
return this.extractResponseLogData(spanData, span);
|
|
15354
|
+
case "function":
|
|
15355
|
+
return this.extractFunctionLogData(spanData);
|
|
15356
|
+
case "handoff":
|
|
15357
|
+
return this.extractHandoffLogData(spanData);
|
|
15358
|
+
case "guardrail":
|
|
15359
|
+
return this.extractGuardrailLogData(spanData);
|
|
15360
|
+
case "generation":
|
|
15361
|
+
return this.extractGenerationLogData(spanData, span);
|
|
15362
|
+
case "custom":
|
|
15363
|
+
return this.extractCustomLogData(spanData);
|
|
15364
|
+
case "mcp_tools":
|
|
15365
|
+
return this.extractMCPListToolsLogData(spanData);
|
|
15366
|
+
case "transcription":
|
|
15367
|
+
return this.extractTranscriptionLogData(spanData);
|
|
15368
|
+
case "speech":
|
|
15369
|
+
return this.extractSpeechLogData(spanData);
|
|
15370
|
+
case "speech_group":
|
|
15371
|
+
return this.extractSpeechGroupLogData(spanData);
|
|
15372
|
+
default:
|
|
15373
|
+
return {};
|
|
15374
|
+
}
|
|
15375
|
+
}
|
|
15376
|
+
extractAgentLogData(spanData) {
|
|
15377
|
+
return {
|
|
15378
|
+
metadata: {
|
|
15379
|
+
tools: spanData.tools,
|
|
15380
|
+
handoffs: spanData.handoffs,
|
|
15381
|
+
output_type: spanData.output_type
|
|
15382
|
+
}
|
|
15383
|
+
};
|
|
15384
|
+
}
|
|
15385
|
+
extractResponseLogData(spanData, span) {
|
|
15386
|
+
const response = spanData._response;
|
|
15387
|
+
const output = isObject(response) ? response.output : void 0;
|
|
15388
|
+
const usage = isObject(response) ? response.usage : void 0;
|
|
15389
|
+
const metrics = {
|
|
15390
|
+
...this.extractTimingMetrics(span),
|
|
15391
|
+
...parseUsageMetrics(usage)
|
|
15392
|
+
};
|
|
15393
|
+
return {
|
|
15394
|
+
input: spanData._input,
|
|
15395
|
+
output,
|
|
15396
|
+
metadata: isObject(response) ? this.omitKeys(response, ["output", "usage"]) : {},
|
|
15397
|
+
metrics
|
|
15398
|
+
};
|
|
15399
|
+
}
|
|
15400
|
+
extractFunctionLogData(spanData) {
|
|
15401
|
+
return {
|
|
15402
|
+
input: spanData.input,
|
|
15403
|
+
output: spanData.output
|
|
15404
|
+
};
|
|
15405
|
+
}
|
|
15406
|
+
extractHandoffLogData(spanData) {
|
|
15407
|
+
return {
|
|
15408
|
+
metadata: {
|
|
15409
|
+
from_agent: spanData.from_agent,
|
|
15410
|
+
to_agent: spanData.to_agent
|
|
15411
|
+
}
|
|
15412
|
+
};
|
|
15413
|
+
}
|
|
15414
|
+
extractGuardrailLogData(spanData) {
|
|
15415
|
+
return {
|
|
15416
|
+
metadata: {
|
|
15417
|
+
triggered: spanData.triggered
|
|
15418
|
+
}
|
|
15419
|
+
};
|
|
15420
|
+
}
|
|
15421
|
+
extractGenerationLogData(spanData, span) {
|
|
15422
|
+
return {
|
|
15423
|
+
input: spanData.input,
|
|
15424
|
+
output: spanData.output,
|
|
15425
|
+
metadata: {
|
|
15426
|
+
model: spanData.model,
|
|
15427
|
+
model_config: spanData.model_config
|
|
15428
|
+
},
|
|
15429
|
+
metrics: {
|
|
15430
|
+
...this.extractTimingMetrics(span),
|
|
15431
|
+
...parseUsageMetrics(spanData.usage)
|
|
15432
|
+
}
|
|
15433
|
+
};
|
|
15434
|
+
}
|
|
15435
|
+
extractCustomLogData(spanData) {
|
|
15436
|
+
return spanData.data || {};
|
|
15437
|
+
}
|
|
15438
|
+
extractMCPListToolsLogData(spanData) {
|
|
15439
|
+
return {
|
|
15440
|
+
output: spanData.result,
|
|
15441
|
+
metadata: {
|
|
15442
|
+
server: spanData.server
|
|
15443
|
+
}
|
|
15444
|
+
};
|
|
15445
|
+
}
|
|
15446
|
+
extractTranscriptionLogData(spanData) {
|
|
15447
|
+
return {
|
|
15448
|
+
input: spanData.input,
|
|
15449
|
+
output: spanData.output,
|
|
15450
|
+
metadata: {
|
|
15451
|
+
model: spanData.model,
|
|
15452
|
+
model_config: spanData.model_config
|
|
15453
|
+
}
|
|
15454
|
+
};
|
|
15455
|
+
}
|
|
15456
|
+
extractSpeechLogData(spanData) {
|
|
15457
|
+
return {
|
|
15458
|
+
input: spanData.input,
|
|
15459
|
+
output: spanData.output,
|
|
15460
|
+
metadata: {
|
|
15461
|
+
model: spanData.model,
|
|
15462
|
+
model_config: spanData.model_config
|
|
15463
|
+
}
|
|
15464
|
+
};
|
|
15465
|
+
}
|
|
15466
|
+
extractSpeechGroupLogData(spanData) {
|
|
15467
|
+
return {
|
|
15468
|
+
input: spanData.input
|
|
15469
|
+
};
|
|
15470
|
+
}
|
|
15471
|
+
extractTimingMetrics(span) {
|
|
15472
|
+
const timeToFirstToken = getTimeElapsed(
|
|
15473
|
+
span.endedAt ?? void 0,
|
|
15474
|
+
span.startedAt ?? void 0
|
|
15475
|
+
);
|
|
15476
|
+
return timeToFirstToken === void 0 ? {} : { time_to_first_token: timeToFirstToken };
|
|
15477
|
+
}
|
|
15478
|
+
omitKeys(value, keys) {
|
|
15479
|
+
const result = {};
|
|
15480
|
+
for (const [key, fieldValue] of Object.entries(value)) {
|
|
15481
|
+
if (!keys.includes(key)) {
|
|
15482
|
+
result[key] = fieldValue;
|
|
15483
|
+
}
|
|
15484
|
+
}
|
|
15485
|
+
return result;
|
|
15486
|
+
}
|
|
15487
|
+
};
|
|
15488
|
+
|
|
15489
|
+
// src/instrumentation/plugins/openai-agents-plugin.ts
|
|
15490
|
+
function firstArgument(args) {
|
|
15491
|
+
if (Array.isArray(args)) {
|
|
15492
|
+
return args[0];
|
|
15493
|
+
}
|
|
15494
|
+
if (isObject(args) && "length" in args && typeof args.length === "number" && Number.isInteger(args.length) && args.length >= 0) {
|
|
15495
|
+
return Array.from(args)[0];
|
|
15496
|
+
}
|
|
15497
|
+
return void 0;
|
|
15498
|
+
}
|
|
15499
|
+
function isOpenAIAgentsTrace(value) {
|
|
15500
|
+
return isObject(value) && value.type === "trace" && typeof value.traceId === "string";
|
|
15501
|
+
}
|
|
15502
|
+
function isOpenAIAgentsSpan(value) {
|
|
15503
|
+
return isObject(value) && value.type === "trace.span" && typeof value.traceId === "string" && typeof value.spanId === "string";
|
|
15504
|
+
}
|
|
15505
|
+
var OpenAIAgentsPlugin = class extends BasePlugin {
|
|
15506
|
+
processor = new OpenAIAgentsTraceProcessor();
|
|
15507
|
+
onEnable() {
|
|
15508
|
+
this.subscribeToTraceLifecycle();
|
|
15509
|
+
}
|
|
15510
|
+
onDisable() {
|
|
15511
|
+
this.unsubscribers = unsubscribeAll(this.unsubscribers);
|
|
15512
|
+
void this.processor.shutdown();
|
|
15513
|
+
}
|
|
15514
|
+
subscribeToTraceLifecycle() {
|
|
15515
|
+
const traceStartChannel = openAIAgentsCoreChannels.onTraceStart.tracingChannel();
|
|
15516
|
+
const traceStartHandlers = {
|
|
15517
|
+
start: (event) => {
|
|
15518
|
+
const trace = firstArgument(event.arguments);
|
|
15519
|
+
if (isOpenAIAgentsTrace(trace)) {
|
|
15520
|
+
void this.processor.onTraceStart(trace);
|
|
15521
|
+
}
|
|
15522
|
+
}
|
|
15523
|
+
};
|
|
15524
|
+
traceStartChannel.subscribe(traceStartHandlers);
|
|
15525
|
+
this.unsubscribers.push(
|
|
15526
|
+
() => traceStartChannel.unsubscribe(traceStartHandlers)
|
|
15527
|
+
);
|
|
15528
|
+
const traceEndChannel = openAIAgentsCoreChannels.onTraceEnd.tracingChannel();
|
|
15529
|
+
const traceEndHandlers = {
|
|
15530
|
+
start: (event) => {
|
|
15531
|
+
const trace = firstArgument(event.arguments);
|
|
15532
|
+
if (isOpenAIAgentsTrace(trace)) {
|
|
15533
|
+
void this.processor.onTraceEnd(trace);
|
|
15534
|
+
}
|
|
15535
|
+
}
|
|
15536
|
+
};
|
|
15537
|
+
traceEndChannel.subscribe(traceEndHandlers);
|
|
15538
|
+
this.unsubscribers.push(
|
|
15539
|
+
() => traceEndChannel.unsubscribe(traceEndHandlers)
|
|
15540
|
+
);
|
|
15541
|
+
const spanStartChannel = openAIAgentsCoreChannels.onSpanStart.tracingChannel();
|
|
15542
|
+
const spanStartHandlers = {
|
|
15543
|
+
start: (event) => {
|
|
15544
|
+
const span = firstArgument(event.arguments);
|
|
15545
|
+
if (isOpenAIAgentsSpan(span)) {
|
|
15546
|
+
void this.processor.onSpanStart(span);
|
|
15547
|
+
}
|
|
15548
|
+
}
|
|
15549
|
+
};
|
|
15550
|
+
spanStartChannel.subscribe(spanStartHandlers);
|
|
15551
|
+
this.unsubscribers.push(
|
|
15552
|
+
() => spanStartChannel.unsubscribe(spanStartHandlers)
|
|
15553
|
+
);
|
|
15554
|
+
const spanEndChannel = openAIAgentsCoreChannels.onSpanEnd.tracingChannel();
|
|
15555
|
+
const spanEndHandlers = {
|
|
15556
|
+
start: (event) => {
|
|
15557
|
+
const span = firstArgument(event.arguments);
|
|
15558
|
+
if (isOpenAIAgentsSpan(span)) {
|
|
15559
|
+
void this.processor.onSpanEnd(span);
|
|
15560
|
+
}
|
|
15561
|
+
}
|
|
15562
|
+
};
|
|
15563
|
+
spanEndChannel.subscribe(spanEndHandlers);
|
|
15564
|
+
this.unsubscribers.push(() => spanEndChannel.unsubscribe(spanEndHandlers));
|
|
15565
|
+
}
|
|
15566
|
+
};
|
|
15567
|
+
|
|
15044
15568
|
// src/instrumentation/plugins/google-genai-channels.ts
|
|
15045
15569
|
var googleGenAIChannels = defineChannels("@google/genai", {
|
|
15046
15570
|
generateContent: channel({
|
|
@@ -21333,49 +21857,1759 @@ var GitHubCopilotPlugin = class extends BasePlugin {
|
|
|
21333
21857
|
}
|
|
21334
21858
|
};
|
|
21335
21859
|
|
|
21336
|
-
// src/instrumentation/
|
|
21337
|
-
|
|
21338
|
-
|
|
21860
|
+
// src/instrumentation/plugins/flue-channels.ts
|
|
21861
|
+
var flueChannels = defineChannels("@flue/runtime", {
|
|
21862
|
+
createContext: channel({
|
|
21863
|
+
channelName: "createFlueContext",
|
|
21864
|
+
kind: "sync-stream"
|
|
21865
|
+
}),
|
|
21866
|
+
openSession: channel({
|
|
21867
|
+
channelName: "Harness.openSession",
|
|
21868
|
+
kind: "async"
|
|
21869
|
+
}),
|
|
21870
|
+
contextEvent: channel({
|
|
21871
|
+
channelName: "context.event",
|
|
21872
|
+
kind: "sync-stream"
|
|
21873
|
+
}),
|
|
21874
|
+
prompt: channel({
|
|
21875
|
+
channelName: "session.prompt",
|
|
21876
|
+
kind: "async"
|
|
21877
|
+
}),
|
|
21878
|
+
skill: channel({
|
|
21879
|
+
channelName: "session.skill",
|
|
21880
|
+
kind: "async"
|
|
21881
|
+
}),
|
|
21882
|
+
task: channel({
|
|
21883
|
+
channelName: "session.task",
|
|
21884
|
+
kind: "async"
|
|
21885
|
+
}),
|
|
21886
|
+
compact: channel({
|
|
21887
|
+
channelName: "session.compact",
|
|
21888
|
+
kind: "async"
|
|
21889
|
+
})
|
|
21890
|
+
});
|
|
21891
|
+
|
|
21892
|
+
// src/wrappers/flue.ts
|
|
21893
|
+
var WRAPPED_FLUE_CONTEXT = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-context");
|
|
21894
|
+
var WRAPPED_FLUE_HARNESS = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-harness");
|
|
21895
|
+
var WRAPPED_FLUE_SESSION = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-session");
|
|
21896
|
+
var SUBSCRIBED_FLUE_CONTEXT_EVENTS = /* @__PURE__ */ Symbol.for(
|
|
21897
|
+
"braintrust.flue.subscribed-context-events"
|
|
21898
|
+
);
|
|
21899
|
+
function patchFlueContextInPlace(ctx) {
|
|
21900
|
+
const context = ctx;
|
|
21901
|
+
if (context[WRAPPED_FLUE_CONTEXT]) {
|
|
21902
|
+
return ctx;
|
|
21903
|
+
}
|
|
21904
|
+
const originalInit = context.init.bind(context);
|
|
21905
|
+
try {
|
|
21906
|
+
Object.defineProperty(context, WRAPPED_FLUE_CONTEXT, {
|
|
21907
|
+
configurable: false,
|
|
21908
|
+
enumerable: false,
|
|
21909
|
+
value: true
|
|
21910
|
+
});
|
|
21911
|
+
Object.defineProperty(context, "init", {
|
|
21912
|
+
configurable: true,
|
|
21913
|
+
value: async function wrappedFlueInit(options) {
|
|
21914
|
+
const harness = await originalInit(options);
|
|
21915
|
+
return wrapFlueHarness(harness);
|
|
21916
|
+
},
|
|
21917
|
+
writable: true
|
|
21918
|
+
});
|
|
21919
|
+
} catch {
|
|
21920
|
+
}
|
|
21921
|
+
return ctx;
|
|
21339
21922
|
}
|
|
21340
|
-
|
|
21341
|
-
|
|
21342
|
-
|
|
21343
|
-
openAICodexPlugin = null;
|
|
21344
|
-
anthropicPlugin = null;
|
|
21345
|
-
aiSDKPlugin = null;
|
|
21346
|
-
claudeAgentSDKPlugin = null;
|
|
21347
|
-
cursorSDKPlugin = null;
|
|
21348
|
-
googleGenAIPlugin = null;
|
|
21349
|
-
huggingFacePlugin = null;
|
|
21350
|
-
openRouterPlugin = null;
|
|
21351
|
-
openRouterAgentPlugin = null;
|
|
21352
|
-
mistralPlugin = null;
|
|
21353
|
-
googleADKPlugin = null;
|
|
21354
|
-
coherePlugin = null;
|
|
21355
|
-
groqPlugin = null;
|
|
21356
|
-
genkitPlugin = null;
|
|
21357
|
-
gitHubCopilotPlugin = null;
|
|
21358
|
-
constructor(config = {}) {
|
|
21359
|
-
super();
|
|
21360
|
-
this.config = config;
|
|
21923
|
+
function subscribeFlueContextEvents(ctx, options = {}) {
|
|
21924
|
+
if (!ctx || typeof ctx !== "object" || typeof ctx.subscribeEvent !== "function") {
|
|
21925
|
+
return void 0;
|
|
21361
21926
|
}
|
|
21362
|
-
|
|
21363
|
-
|
|
21364
|
-
|
|
21365
|
-
|
|
21366
|
-
|
|
21927
|
+
const context = ctx;
|
|
21928
|
+
const captureTurnSpans = options.captureTurnSpans ?? true;
|
|
21929
|
+
const existingSubscription = context[SUBSCRIBED_FLUE_CONTEXT_EVENTS];
|
|
21930
|
+
if (existingSubscription) {
|
|
21931
|
+
if (existingSubscription.captureTurnSpans || !captureTurnSpans) {
|
|
21932
|
+
return void 0;
|
|
21367
21933
|
}
|
|
21368
|
-
|
|
21369
|
-
|
|
21370
|
-
|
|
21934
|
+
try {
|
|
21935
|
+
existingSubscription.unsubscribe();
|
|
21936
|
+
} catch {
|
|
21371
21937
|
}
|
|
21372
|
-
|
|
21373
|
-
|
|
21374
|
-
|
|
21938
|
+
}
|
|
21939
|
+
try {
|
|
21940
|
+
const unsubscribe = ctx.subscribeEvent((event) => {
|
|
21941
|
+
flueChannels.contextEvent.traceSync(() => void 0, {
|
|
21942
|
+
arguments: [event],
|
|
21943
|
+
captureTurnSpans,
|
|
21944
|
+
context: ctx
|
|
21945
|
+
});
|
|
21946
|
+
});
|
|
21947
|
+
if (existingSubscription) {
|
|
21948
|
+
existingSubscription.captureTurnSpans = captureTurnSpans;
|
|
21949
|
+
existingSubscription.unsubscribe = unsubscribe;
|
|
21950
|
+
} else {
|
|
21951
|
+
Object.defineProperty(context, SUBSCRIBED_FLUE_CONTEXT_EVENTS, {
|
|
21952
|
+
configurable: false,
|
|
21953
|
+
enumerable: false,
|
|
21954
|
+
value: {
|
|
21955
|
+
captureTurnSpans,
|
|
21956
|
+
unsubscribe
|
|
21957
|
+
}
|
|
21958
|
+
});
|
|
21375
21959
|
}
|
|
21376
|
-
|
|
21377
|
-
|
|
21378
|
-
|
|
21960
|
+
return unsubscribe;
|
|
21961
|
+
} catch {
|
|
21962
|
+
return void 0;
|
|
21963
|
+
}
|
|
21964
|
+
}
|
|
21965
|
+
function wrapFlueHarness(harness) {
|
|
21966
|
+
if (!isPlausibleFlueHarness(harness)) {
|
|
21967
|
+
return harness;
|
|
21968
|
+
}
|
|
21969
|
+
const target = harness;
|
|
21970
|
+
if (target[WRAPPED_FLUE_HARNESS]) {
|
|
21971
|
+
return harness;
|
|
21972
|
+
}
|
|
21973
|
+
const originalSession = target.session.bind(target);
|
|
21974
|
+
try {
|
|
21975
|
+
Object.defineProperty(target, WRAPPED_FLUE_HARNESS, {
|
|
21976
|
+
configurable: false,
|
|
21977
|
+
enumerable: false,
|
|
21978
|
+
value: true
|
|
21979
|
+
});
|
|
21980
|
+
Object.defineProperty(target, "session", {
|
|
21981
|
+
configurable: true,
|
|
21982
|
+
value: async function wrappedFlueHarnessSession(name, options) {
|
|
21983
|
+
const session = await originalSession(name, options);
|
|
21984
|
+
return patchFlueSessionInPlace(session);
|
|
21985
|
+
},
|
|
21986
|
+
writable: true
|
|
21987
|
+
});
|
|
21988
|
+
const sessions = target.sessions;
|
|
21989
|
+
if (sessions && typeof sessions === "object") {
|
|
21990
|
+
patchFlueSessionFactory(sessions, "get");
|
|
21991
|
+
patchFlueSessionFactory(sessions, "create");
|
|
21992
|
+
}
|
|
21993
|
+
} catch {
|
|
21994
|
+
}
|
|
21995
|
+
return harness;
|
|
21996
|
+
}
|
|
21997
|
+
function patchFlueSessionInPlace(session) {
|
|
21998
|
+
if (session[WRAPPED_FLUE_SESSION]) {
|
|
21999
|
+
return session;
|
|
22000
|
+
}
|
|
22001
|
+
try {
|
|
22002
|
+
Object.defineProperty(session, WRAPPED_FLUE_SESSION, {
|
|
22003
|
+
configurable: false,
|
|
22004
|
+
enumerable: false,
|
|
22005
|
+
value: true
|
|
22006
|
+
});
|
|
22007
|
+
patchCallHandleMethod(session, "prompt", flueChannels.prompt);
|
|
22008
|
+
patchCallHandleMethod(session, "skill", flueChannels.skill);
|
|
22009
|
+
patchCallHandleMethod(session, "task", flueChannels.task);
|
|
22010
|
+
patchCompact(session);
|
|
22011
|
+
} catch {
|
|
22012
|
+
}
|
|
22013
|
+
return session;
|
|
22014
|
+
}
|
|
22015
|
+
function patchFlueSessionFactory(sessions, method) {
|
|
22016
|
+
const original = sessions[method];
|
|
22017
|
+
if (typeof original !== "function") {
|
|
22018
|
+
return;
|
|
22019
|
+
}
|
|
22020
|
+
const bound = original.bind(sessions);
|
|
22021
|
+
Object.defineProperty(sessions, method, {
|
|
22022
|
+
configurable: true,
|
|
22023
|
+
value: async function wrappedFlueSessionFactory(name, options) {
|
|
22024
|
+
const session = await bound(name, options);
|
|
22025
|
+
return patchFlueSessionInPlace(session);
|
|
22026
|
+
},
|
|
22027
|
+
writable: true
|
|
22028
|
+
});
|
|
22029
|
+
}
|
|
22030
|
+
function patchCallHandleMethod(session, method, channel2) {
|
|
22031
|
+
const original = session[method];
|
|
22032
|
+
if (typeof original !== "function") {
|
|
22033
|
+
return;
|
|
22034
|
+
}
|
|
22035
|
+
const bound = original.bind(session);
|
|
22036
|
+
Object.defineProperty(session, method, {
|
|
22037
|
+
configurable: true,
|
|
22038
|
+
value(input, options) {
|
|
22039
|
+
const args = [input, options];
|
|
22040
|
+
const { originalResult, traced } = traceFlueOperation(channel2, {
|
|
22041
|
+
context: {
|
|
22042
|
+
arguments: args,
|
|
22043
|
+
operation: method,
|
|
22044
|
+
session
|
|
22045
|
+
},
|
|
22046
|
+
run: () => bound(input, options)
|
|
22047
|
+
});
|
|
22048
|
+
return preserveCallHandle(originalResult, traced);
|
|
22049
|
+
},
|
|
22050
|
+
writable: true
|
|
22051
|
+
});
|
|
22052
|
+
}
|
|
22053
|
+
function patchCompact(session) {
|
|
22054
|
+
const original = session.compact;
|
|
22055
|
+
if (typeof original !== "function") {
|
|
22056
|
+
return;
|
|
22057
|
+
}
|
|
22058
|
+
const bound = original.bind(session);
|
|
22059
|
+
Object.defineProperty(session, "compact", {
|
|
22060
|
+
configurable: true,
|
|
22061
|
+
value() {
|
|
22062
|
+
const context = {
|
|
22063
|
+
arguments: [],
|
|
22064
|
+
operation: "compact",
|
|
22065
|
+
session
|
|
22066
|
+
};
|
|
22067
|
+
return flueChannels.compact.tracePromise(() => bound(), context);
|
|
22068
|
+
},
|
|
22069
|
+
writable: true
|
|
22070
|
+
});
|
|
22071
|
+
}
|
|
22072
|
+
function traceFlueOperation(channel2, args) {
|
|
22073
|
+
const tracingChannel = channel2.tracingChannel();
|
|
22074
|
+
const context = args.context;
|
|
22075
|
+
let originalResult;
|
|
22076
|
+
let traced;
|
|
22077
|
+
const run = () => {
|
|
22078
|
+
try {
|
|
22079
|
+
originalResult = args.run();
|
|
22080
|
+
tracingChannel.end?.publish(context);
|
|
22081
|
+
} catch (error) {
|
|
22082
|
+
context.error = normalizeError3(error);
|
|
22083
|
+
tracingChannel.error?.publish(context);
|
|
22084
|
+
tracingChannel.end?.publish(context);
|
|
22085
|
+
throw error;
|
|
22086
|
+
}
|
|
22087
|
+
traced = Promise.resolve(originalResult).then(
|
|
22088
|
+
(result) => {
|
|
22089
|
+
context.result = result;
|
|
22090
|
+
tracingChannel.asyncStart?.publish(context);
|
|
22091
|
+
tracingChannel.asyncEnd?.publish(context);
|
|
22092
|
+
return result;
|
|
22093
|
+
},
|
|
22094
|
+
(error) => {
|
|
22095
|
+
context.error = normalizeError3(error);
|
|
22096
|
+
tracingChannel.error?.publish(context);
|
|
22097
|
+
tracingChannel.asyncStart?.publish(context);
|
|
22098
|
+
tracingChannel.asyncEnd?.publish(context);
|
|
22099
|
+
throw error;
|
|
22100
|
+
}
|
|
22101
|
+
);
|
|
22102
|
+
};
|
|
22103
|
+
if (tracingChannel.start?.runStores) {
|
|
22104
|
+
tracingChannel.start.runStores(context, run);
|
|
22105
|
+
} else {
|
|
22106
|
+
tracingChannel.start?.publish(context);
|
|
22107
|
+
run();
|
|
22108
|
+
}
|
|
22109
|
+
return { originalResult, traced };
|
|
22110
|
+
}
|
|
22111
|
+
function normalizeError3(error) {
|
|
22112
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
22113
|
+
}
|
|
22114
|
+
function preserveCallHandle(originalHandle, traced) {
|
|
22115
|
+
if (!isFlueCallHandle(originalHandle)) {
|
|
22116
|
+
return traced;
|
|
22117
|
+
}
|
|
22118
|
+
const handle = originalHandle;
|
|
22119
|
+
const wrapped = {
|
|
22120
|
+
get signal() {
|
|
22121
|
+
return handle.signal;
|
|
22122
|
+
},
|
|
22123
|
+
abort(reason) {
|
|
22124
|
+
return handle.abort(reason);
|
|
22125
|
+
},
|
|
22126
|
+
then(onfulfilled, onrejected) {
|
|
22127
|
+
return traced.then(onfulfilled, onrejected);
|
|
22128
|
+
}
|
|
22129
|
+
};
|
|
22130
|
+
return wrapped;
|
|
22131
|
+
}
|
|
22132
|
+
function isPlausibleFlueHarness(value) {
|
|
22133
|
+
return !!value && typeof value === "object" && typeof value.session === "function";
|
|
22134
|
+
}
|
|
22135
|
+
function isFlueCallHandle(value) {
|
|
22136
|
+
return !!value && typeof value === "object" && typeof value.then === "function" && typeof value.abort === "function" && "signal" in value;
|
|
22137
|
+
}
|
|
22138
|
+
|
|
22139
|
+
// src/instrumentation/plugins/flue-plugin.ts
|
|
22140
|
+
var FluePlugin = class extends BasePlugin {
|
|
22141
|
+
activeOperationsById = /* @__PURE__ */ new Map();
|
|
22142
|
+
activeOperationsByScope = /* @__PURE__ */ new Map();
|
|
22143
|
+
compactionsByScope = /* @__PURE__ */ new Map();
|
|
22144
|
+
pendingOperationsByKey = /* @__PURE__ */ new Map();
|
|
22145
|
+
tasksById = /* @__PURE__ */ new Map();
|
|
22146
|
+
toolsById = /* @__PURE__ */ new Map();
|
|
22147
|
+
turnsByScope = /* @__PURE__ */ new Map();
|
|
22148
|
+
onEnable() {
|
|
22149
|
+
this.subscribeToContextCreation();
|
|
22150
|
+
this.subscribeToSessionCreation();
|
|
22151
|
+
this.subscribeToContextEvents();
|
|
22152
|
+
this.subscribeToSessionOperations();
|
|
22153
|
+
}
|
|
22154
|
+
onDisable() {
|
|
22155
|
+
for (const unsubscribe of this.unsubscribers) {
|
|
22156
|
+
unsubscribe();
|
|
22157
|
+
}
|
|
22158
|
+
this.unsubscribers = [];
|
|
22159
|
+
this.activeOperationsById.clear();
|
|
22160
|
+
this.activeOperationsByScope.clear();
|
|
22161
|
+
this.compactionsByScope.clear();
|
|
22162
|
+
this.pendingOperationsByKey.clear();
|
|
22163
|
+
this.tasksById.clear();
|
|
22164
|
+
this.toolsById.clear();
|
|
22165
|
+
this.turnsByScope.clear();
|
|
22166
|
+
}
|
|
22167
|
+
subscribeToContextCreation() {
|
|
22168
|
+
const channel2 = flueChannels.createContext.tracingChannel();
|
|
22169
|
+
const handlers = {
|
|
22170
|
+
end: (event) => {
|
|
22171
|
+
const ctx = event.result;
|
|
22172
|
+
if (!ctx) {
|
|
22173
|
+
return;
|
|
22174
|
+
}
|
|
22175
|
+
subscribeFlueContextEvents(ctx, { captureTurnSpans: false });
|
|
22176
|
+
patchFlueContextInPlace(ctx);
|
|
22177
|
+
},
|
|
22178
|
+
error: () => {
|
|
22179
|
+
}
|
|
22180
|
+
};
|
|
22181
|
+
channel2.subscribe(handlers);
|
|
22182
|
+
this.unsubscribers.push(() => {
|
|
22183
|
+
channel2.unsubscribe(handlers);
|
|
22184
|
+
});
|
|
22185
|
+
}
|
|
22186
|
+
subscribeToSessionCreation() {
|
|
22187
|
+
const channel2 = flueChannels.openSession.tracingChannel();
|
|
22188
|
+
const handlers = {
|
|
22189
|
+
asyncEnd: (event) => {
|
|
22190
|
+
if (event.result) {
|
|
22191
|
+
patchFlueSessionInPlace(
|
|
22192
|
+
event.result
|
|
22193
|
+
);
|
|
22194
|
+
}
|
|
22195
|
+
if (event.harness) {
|
|
22196
|
+
wrapFlueHarness(event.harness);
|
|
22197
|
+
}
|
|
22198
|
+
},
|
|
22199
|
+
error: () => {
|
|
22200
|
+
}
|
|
22201
|
+
};
|
|
22202
|
+
channel2.subscribe(handlers);
|
|
22203
|
+
this.unsubscribers.push(() => {
|
|
22204
|
+
channel2.unsubscribe(handlers);
|
|
22205
|
+
});
|
|
22206
|
+
}
|
|
22207
|
+
subscribeToSessionOperations() {
|
|
22208
|
+
this.subscribeToSessionOperation(flueChannels.prompt);
|
|
22209
|
+
this.subscribeToSessionOperation(flueChannels.skill);
|
|
22210
|
+
this.subscribeToSessionOperation(flueChannels.task);
|
|
22211
|
+
this.subscribeToCompact();
|
|
22212
|
+
}
|
|
22213
|
+
subscribeToSessionOperation(channel2) {
|
|
22214
|
+
const tracingChannel = channel2.tracingChannel();
|
|
22215
|
+
const states = /* @__PURE__ */ new WeakMap();
|
|
22216
|
+
const ensureState2 = (event) => {
|
|
22217
|
+
const existing = states.get(event);
|
|
22218
|
+
if (existing) {
|
|
22219
|
+
return existing;
|
|
22220
|
+
}
|
|
22221
|
+
const state = this.startOperationState({
|
|
22222
|
+
args: event.arguments,
|
|
22223
|
+
moduleVersion: typeof event.moduleVersion === "string" ? event.moduleVersion : void 0,
|
|
22224
|
+
operation: event.operation,
|
|
22225
|
+
session: event.session
|
|
22226
|
+
});
|
|
22227
|
+
states.set(event, state);
|
|
22228
|
+
return state;
|
|
22229
|
+
};
|
|
22230
|
+
const unbindCurrentSpanStore = this.bindCurrentSpanStoreToOperationStart(
|
|
22231
|
+
tracingChannel,
|
|
22232
|
+
ensureState2
|
|
22233
|
+
);
|
|
22234
|
+
const handlers = {
|
|
22235
|
+
start: (event) => {
|
|
22236
|
+
ensureState2(event);
|
|
22237
|
+
},
|
|
22238
|
+
asyncEnd: (event) => {
|
|
22239
|
+
this.endOperationState(states.get(event), event.result);
|
|
22240
|
+
states.delete(event);
|
|
22241
|
+
},
|
|
22242
|
+
error: (event) => {
|
|
22243
|
+
const state = states.get(event);
|
|
22244
|
+
if (state && event.error) {
|
|
22245
|
+
safeLog3(state.span, { error: errorToString(event.error) });
|
|
22246
|
+
this.finishOperationState(state);
|
|
22247
|
+
}
|
|
22248
|
+
states.delete(event);
|
|
22249
|
+
}
|
|
22250
|
+
};
|
|
22251
|
+
tracingChannel.subscribe(handlers);
|
|
22252
|
+
this.unsubscribers.push(() => {
|
|
22253
|
+
unbindCurrentSpanStore?.();
|
|
22254
|
+
tracingChannel.unsubscribe(handlers);
|
|
22255
|
+
});
|
|
22256
|
+
}
|
|
22257
|
+
subscribeToCompact() {
|
|
22258
|
+
const tracingChannel = flueChannels.compact.tracingChannel();
|
|
22259
|
+
const states = /* @__PURE__ */ new WeakMap();
|
|
22260
|
+
const ensureState2 = (event) => {
|
|
22261
|
+
const existing = states.get(event);
|
|
22262
|
+
if (existing) {
|
|
22263
|
+
return existing;
|
|
22264
|
+
}
|
|
22265
|
+
const state = this.startOperationState({
|
|
22266
|
+
args: [],
|
|
22267
|
+
moduleVersion: typeof event.moduleVersion === "string" ? event.moduleVersion : void 0,
|
|
22268
|
+
operation: event.operation,
|
|
22269
|
+
session: event.session
|
|
22270
|
+
});
|
|
22271
|
+
states.set(event, state);
|
|
22272
|
+
return state;
|
|
22273
|
+
};
|
|
22274
|
+
const unbindCurrentSpanStore = this.bindCurrentSpanStoreToOperationStart(
|
|
22275
|
+
tracingChannel,
|
|
22276
|
+
ensureState2
|
|
22277
|
+
);
|
|
22278
|
+
const handlers = {
|
|
22279
|
+
start: (event) => {
|
|
22280
|
+
ensureState2(event);
|
|
22281
|
+
},
|
|
22282
|
+
asyncEnd: (event) => {
|
|
22283
|
+
this.endOperationState(states.get(event), void 0);
|
|
22284
|
+
states.delete(event);
|
|
22285
|
+
},
|
|
22286
|
+
error: (event) => {
|
|
22287
|
+
const state = states.get(event);
|
|
22288
|
+
if (state && event.error) {
|
|
22289
|
+
safeLog3(state.span, { error: errorToString(event.error) });
|
|
22290
|
+
this.finishOperationState(state);
|
|
22291
|
+
}
|
|
22292
|
+
states.delete(event);
|
|
22293
|
+
}
|
|
22294
|
+
};
|
|
22295
|
+
tracingChannel.subscribe(handlers);
|
|
22296
|
+
this.unsubscribers.push(() => {
|
|
22297
|
+
unbindCurrentSpanStore?.();
|
|
22298
|
+
tracingChannel.unsubscribe(handlers);
|
|
22299
|
+
});
|
|
22300
|
+
}
|
|
22301
|
+
subscribeToContextEvents() {
|
|
22302
|
+
const channel2 = flueChannels.contextEvent.tracingChannel();
|
|
22303
|
+
const handlers = {
|
|
22304
|
+
start: (event) => {
|
|
22305
|
+
const flueEvent = event.arguments[0];
|
|
22306
|
+
if (!flueEvent) {
|
|
22307
|
+
return;
|
|
22308
|
+
}
|
|
22309
|
+
try {
|
|
22310
|
+
this.handleFlueEvent(flueEvent, {
|
|
22311
|
+
captureTurnSpans: event.captureTurnSpans !== false
|
|
22312
|
+
});
|
|
22313
|
+
} catch (error) {
|
|
22314
|
+
logInstrumentationError3("Flue event", error);
|
|
22315
|
+
}
|
|
22316
|
+
},
|
|
22317
|
+
error: () => {
|
|
22318
|
+
}
|
|
22319
|
+
};
|
|
22320
|
+
channel2.subscribe(handlers);
|
|
22321
|
+
this.unsubscribers.push(() => {
|
|
22322
|
+
channel2.unsubscribe(handlers);
|
|
22323
|
+
});
|
|
22324
|
+
}
|
|
22325
|
+
bindCurrentSpanStoreToOperationStart(tracingChannel, ensureState2) {
|
|
22326
|
+
const state = _internalGetGlobalState();
|
|
22327
|
+
const startChannel = tracingChannel.start;
|
|
22328
|
+
const contextManager = state?.contextManager;
|
|
22329
|
+
const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
|
|
22330
|
+
if (!currentSpanStore || !startChannel) {
|
|
22331
|
+
return void 0;
|
|
22332
|
+
}
|
|
22333
|
+
startChannel.bindStore(currentSpanStore, (event) => {
|
|
22334
|
+
const operationState = ensureState2(event);
|
|
22335
|
+
return contextManager.wrapSpanForStore(operationState.span);
|
|
22336
|
+
});
|
|
22337
|
+
return () => {
|
|
22338
|
+
startChannel.unbindStore(currentSpanStore);
|
|
22339
|
+
};
|
|
22340
|
+
}
|
|
22341
|
+
startOperationState(args) {
|
|
22342
|
+
const sessionName = getSessionName(args.session);
|
|
22343
|
+
const metadata = {
|
|
22344
|
+
...extractOperationInputMetadata(args.operation, args.args),
|
|
22345
|
+
...extractSessionMetadata(args.session),
|
|
22346
|
+
"flue.operation": args.operation,
|
|
22347
|
+
provider: "flue",
|
|
22348
|
+
...args.moduleVersion ? { "flue.version": args.moduleVersion } : {}
|
|
22349
|
+
};
|
|
22350
|
+
const span = startSpan({
|
|
22351
|
+
name: `flue.session.${args.operation}`,
|
|
22352
|
+
spanAttributes: { type: "task" /* TASK */ }
|
|
22353
|
+
});
|
|
22354
|
+
const state = {
|
|
22355
|
+
metadata,
|
|
22356
|
+
operation: args.operation,
|
|
22357
|
+
sessionName,
|
|
22358
|
+
span,
|
|
22359
|
+
startTime: getCurrentUnixTimestamp()
|
|
22360
|
+
};
|
|
22361
|
+
safeLog3(span, {
|
|
22362
|
+
input: extractOperationInput(args.operation, args.args),
|
|
22363
|
+
metadata
|
|
22364
|
+
});
|
|
22365
|
+
this.pendingOperationQueue(operationKey(sessionName, args.operation)).push(
|
|
22366
|
+
state
|
|
22367
|
+
);
|
|
22368
|
+
addOperationToScope(
|
|
22369
|
+
this.activeOperationsByScope,
|
|
22370
|
+
sessionName ?? "unknown",
|
|
22371
|
+
state
|
|
22372
|
+
);
|
|
22373
|
+
return state;
|
|
22374
|
+
}
|
|
22375
|
+
endOperationState(state, result) {
|
|
22376
|
+
if (!state) {
|
|
22377
|
+
return;
|
|
22378
|
+
}
|
|
22379
|
+
const metadata = {
|
|
22380
|
+
...state.metadata,
|
|
22381
|
+
...extractPromptResponseMetadata(result)
|
|
22382
|
+
};
|
|
22383
|
+
const metrics = {
|
|
22384
|
+
...buildDurationMetrics3(state.startTime),
|
|
22385
|
+
...metricsFromUsage(result?.usage)
|
|
22386
|
+
};
|
|
22387
|
+
safeLog3(state.span, {
|
|
22388
|
+
metadata,
|
|
22389
|
+
metrics,
|
|
22390
|
+
output: extractOperationOutput(result)
|
|
22391
|
+
});
|
|
22392
|
+
this.finishCompactionsForOperation(state);
|
|
22393
|
+
this.finishOperationState(state);
|
|
22394
|
+
}
|
|
22395
|
+
finishOperationState(state) {
|
|
22396
|
+
removePendingOperation(this.pendingOperationsByKey, state);
|
|
22397
|
+
if (state.operationId) {
|
|
22398
|
+
this.activeOperationsById.delete(state.operationId);
|
|
22399
|
+
}
|
|
22400
|
+
removeScopedOperation(this.activeOperationsByScope, state);
|
|
22401
|
+
state.span.end();
|
|
22402
|
+
}
|
|
22403
|
+
handleFlueEvent(event, options) {
|
|
22404
|
+
switch (event.type) {
|
|
22405
|
+
case "operation_start":
|
|
22406
|
+
this.handleOperationStart(event);
|
|
22407
|
+
return;
|
|
22408
|
+
case "operation":
|
|
22409
|
+
this.handleOperation(event);
|
|
22410
|
+
return;
|
|
22411
|
+
case "text_delta":
|
|
22412
|
+
if (!options.captureTurnSpans) {
|
|
22413
|
+
return;
|
|
22414
|
+
}
|
|
22415
|
+
this.ensureTurnState(event).text.push(
|
|
22416
|
+
typeof event.text === "string" ? event.text : ""
|
|
22417
|
+
);
|
|
22418
|
+
return;
|
|
22419
|
+
case "thinking_start":
|
|
22420
|
+
if (!options.captureTurnSpans) {
|
|
22421
|
+
return;
|
|
22422
|
+
}
|
|
22423
|
+
this.handleThinkingStart(event);
|
|
22424
|
+
return;
|
|
22425
|
+
case "thinking_delta":
|
|
22426
|
+
if (!options.captureTurnSpans) {
|
|
22427
|
+
return;
|
|
22428
|
+
}
|
|
22429
|
+
this.handleThinkingDelta(event);
|
|
22430
|
+
return;
|
|
22431
|
+
case "thinking_end":
|
|
22432
|
+
if (!options.captureTurnSpans) {
|
|
22433
|
+
return;
|
|
22434
|
+
}
|
|
22435
|
+
this.handleThinkingEnd(event);
|
|
22436
|
+
return;
|
|
22437
|
+
case "turn":
|
|
22438
|
+
if (!options.captureTurnSpans) {
|
|
22439
|
+
return;
|
|
22440
|
+
}
|
|
22441
|
+
this.handleTurn(event);
|
|
22442
|
+
return;
|
|
22443
|
+
case "tool_start":
|
|
22444
|
+
this.handleToolStart(event, options);
|
|
22445
|
+
return;
|
|
22446
|
+
case "tool_call":
|
|
22447
|
+
this.handleToolCall(event);
|
|
22448
|
+
return;
|
|
22449
|
+
case "task_start":
|
|
22450
|
+
this.handleTaskStart(event);
|
|
22451
|
+
return;
|
|
22452
|
+
case "task":
|
|
22453
|
+
this.handleTask(event);
|
|
22454
|
+
return;
|
|
22455
|
+
case "compaction_start":
|
|
22456
|
+
this.handleCompactionStart(event);
|
|
22457
|
+
return;
|
|
22458
|
+
case "compaction":
|
|
22459
|
+
this.handleCompaction(event);
|
|
22460
|
+
return;
|
|
22461
|
+
default:
|
|
22462
|
+
return;
|
|
22463
|
+
}
|
|
22464
|
+
}
|
|
22465
|
+
handleOperationStart(event) {
|
|
22466
|
+
if (!isInstrumentedOperation(event.operationKind)) {
|
|
22467
|
+
return;
|
|
22468
|
+
}
|
|
22469
|
+
const state = this.takePendingOperationForEvent(event);
|
|
22470
|
+
if (!state) {
|
|
22471
|
+
return;
|
|
22472
|
+
}
|
|
22473
|
+
state.operationId = event.operationId;
|
|
22474
|
+
this.activeOperationsById.set(event.operationId, state);
|
|
22475
|
+
addScopedOperation(this.activeOperationsByScope, event, state);
|
|
22476
|
+
state.metadata = {
|
|
22477
|
+
...state.metadata,
|
|
22478
|
+
...extractEventMetadata(event),
|
|
22479
|
+
"flue.operation_id": event.operationId
|
|
22480
|
+
};
|
|
22481
|
+
safeLog3(state.span, { metadata: state.metadata });
|
|
22482
|
+
}
|
|
22483
|
+
handleOperation(event) {
|
|
22484
|
+
const state = event.operationId ? this.activeOperationsById.get(event.operationId) : void 0;
|
|
22485
|
+
if (!state) {
|
|
22486
|
+
return;
|
|
22487
|
+
}
|
|
22488
|
+
const metadata = {
|
|
22489
|
+
...state.metadata,
|
|
22490
|
+
...extractEventMetadata(event),
|
|
22491
|
+
...typeof event.durationMs === "number" ? { "flue.duration_ms": event.durationMs } : {},
|
|
22492
|
+
...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
|
|
22493
|
+
};
|
|
22494
|
+
const metrics = metricsFromUsage(event.usage);
|
|
22495
|
+
safeLog3(state.span, {
|
|
22496
|
+
...event.error ? { error: errorToString(event.error) } : {},
|
|
22497
|
+
metadata,
|
|
22498
|
+
...Object.keys(metrics).length ? { metrics } : {}
|
|
22499
|
+
});
|
|
22500
|
+
}
|
|
22501
|
+
ensureTurnState(event) {
|
|
22502
|
+
const scope = scopeKey(event);
|
|
22503
|
+
const existing = this.turnsByScope.get(scope);
|
|
22504
|
+
if (existing) {
|
|
22505
|
+
return existing;
|
|
22506
|
+
}
|
|
22507
|
+
const parent = this.parentSpanForEvent(event);
|
|
22508
|
+
const metadata = {
|
|
22509
|
+
...extractEventMetadata(event),
|
|
22510
|
+
provider: "flue"
|
|
22511
|
+
};
|
|
22512
|
+
const span = startFlueSpan(parent, {
|
|
22513
|
+
name: "flue.turn",
|
|
22514
|
+
spanAttributes: { type: "llm" /* LLM */ }
|
|
22515
|
+
});
|
|
22516
|
+
const state = {
|
|
22517
|
+
metadata,
|
|
22518
|
+
span,
|
|
22519
|
+
hasThinking: false,
|
|
22520
|
+
startTime: getCurrentUnixTimestamp(),
|
|
22521
|
+
text: [],
|
|
22522
|
+
thinking: [],
|
|
22523
|
+
toolCalls: []
|
|
22524
|
+
};
|
|
22525
|
+
safeLog3(span, { metadata });
|
|
22526
|
+
this.turnsByScope.set(scope, state);
|
|
22527
|
+
return state;
|
|
22528
|
+
}
|
|
22529
|
+
handleTurn(event) {
|
|
22530
|
+
const scope = scopeKey(event);
|
|
22531
|
+
const state = this.ensureTurnState(event);
|
|
22532
|
+
const text = state.text.join("");
|
|
22533
|
+
const reasoning = state.finalThinking ?? state.thinking.join("");
|
|
22534
|
+
const outputReasoning = reasoning || (state.hasThinking ? "[reasoning stream present; content unavailable]" : void 0);
|
|
22535
|
+
const metadata = {
|
|
22536
|
+
...state.metadata,
|
|
22537
|
+
...extractEventMetadata(event),
|
|
22538
|
+
...event.model ? { model: event.model, "flue.model": event.model } : {},
|
|
22539
|
+
...event.stopReason ? { "flue.stop_reason": event.stopReason } : {},
|
|
22540
|
+
...event.isError !== void 0 ? { "flue.is_error": event.isError } : {},
|
|
22541
|
+
provider: "flue"
|
|
22542
|
+
};
|
|
22543
|
+
safeLog3(state.span, {
|
|
22544
|
+
...event.error ? { error: errorToString(event.error) } : {},
|
|
22545
|
+
metadata,
|
|
22546
|
+
metrics: {
|
|
22547
|
+
...durationMsMetrics(event.durationMs),
|
|
22548
|
+
...metricsFromUsage(event.usage)
|
|
22549
|
+
},
|
|
22550
|
+
output: toAssistantOutput(
|
|
22551
|
+
text,
|
|
22552
|
+
event.stopReason,
|
|
22553
|
+
outputReasoning,
|
|
22554
|
+
state.toolCalls
|
|
22555
|
+
)
|
|
22556
|
+
});
|
|
22557
|
+
state.span.end();
|
|
22558
|
+
this.turnsByScope.delete(scope);
|
|
22559
|
+
}
|
|
22560
|
+
handleThinkingDelta(event) {
|
|
22561
|
+
const delta = event.delta;
|
|
22562
|
+
if (typeof delta !== "string" || !delta) {
|
|
22563
|
+
return;
|
|
22564
|
+
}
|
|
22565
|
+
const state = this.ensureTurnState(event);
|
|
22566
|
+
state.hasThinking = true;
|
|
22567
|
+
state.metadata["flue.thinking"] = true;
|
|
22568
|
+
state.thinking.push(delta);
|
|
22569
|
+
}
|
|
22570
|
+
handleThinkingStart(event) {
|
|
22571
|
+
const state = this.ensureTurnState(event);
|
|
22572
|
+
state.hasThinking = true;
|
|
22573
|
+
state.metadata["flue.thinking"] = true;
|
|
22574
|
+
}
|
|
22575
|
+
handleThinkingEnd(event) {
|
|
22576
|
+
const state = this.ensureTurnState(event);
|
|
22577
|
+
state.hasThinking = true;
|
|
22578
|
+
state.metadata["flue.thinking"] = true;
|
|
22579
|
+
if (typeof event.content === "string" && event.content) {
|
|
22580
|
+
state.finalThinking = event.content;
|
|
22581
|
+
}
|
|
22582
|
+
}
|
|
22583
|
+
handleToolStart(event, options) {
|
|
22584
|
+
const toolCallId = event.toolCallId;
|
|
22585
|
+
if (!toolCallId) {
|
|
22586
|
+
return;
|
|
22587
|
+
}
|
|
22588
|
+
const parent = this.parentSpanForEvent(event);
|
|
22589
|
+
const scope = scopeKey(event);
|
|
22590
|
+
let turnState = this.turnsByScope.get(scope);
|
|
22591
|
+
if (!turnState && parent && options.captureTurnSpans) {
|
|
22592
|
+
turnState = this.ensureTurnState(event);
|
|
22593
|
+
}
|
|
22594
|
+
const metadata = {
|
|
22595
|
+
...extractEventMetadata(event),
|
|
22596
|
+
...event.toolName ? { "flue.tool_name": event.toolName } : {},
|
|
22597
|
+
"flue.tool_call_id": toolCallId,
|
|
22598
|
+
provider: "flue"
|
|
22599
|
+
};
|
|
22600
|
+
const span = startFlueSpan(parent, {
|
|
22601
|
+
name: `tool: ${event.toolName ?? "unknown"}`,
|
|
22602
|
+
spanAttributes: { type: "tool" /* TOOL */ }
|
|
22603
|
+
});
|
|
22604
|
+
if (turnState) {
|
|
22605
|
+
turnState.toolCalls.push({
|
|
22606
|
+
args: event.args,
|
|
22607
|
+
toolCallId,
|
|
22608
|
+
toolName: event.toolName
|
|
22609
|
+
});
|
|
22610
|
+
}
|
|
22611
|
+
safeLog3(span, {
|
|
22612
|
+
input: event.args,
|
|
22613
|
+
metadata
|
|
22614
|
+
});
|
|
22615
|
+
this.toolsById.set(toolKey(event), {
|
|
22616
|
+
metadata,
|
|
22617
|
+
span,
|
|
22618
|
+
startTime: getCurrentUnixTimestamp()
|
|
22619
|
+
});
|
|
22620
|
+
}
|
|
22621
|
+
handleToolCall(event) {
|
|
22622
|
+
const key = toolKey(event);
|
|
22623
|
+
const state = this.toolsById.get(key) ?? this.startSyntheticToolState(event, event.toolName ?? "unknown");
|
|
22624
|
+
const metadata = {
|
|
22625
|
+
...state.metadata,
|
|
22626
|
+
...extractEventMetadata(event),
|
|
22627
|
+
...event.toolName ? { "flue.tool_name": event.toolName } : {},
|
|
22628
|
+
...event.toolCallId ? { "flue.tool_call_id": event.toolCallId } : {},
|
|
22629
|
+
...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
|
|
22630
|
+
};
|
|
22631
|
+
safeLog3(state.span, {
|
|
22632
|
+
...event.isError ? { error: errorToString(event.result) } : {},
|
|
22633
|
+
metadata,
|
|
22634
|
+
metrics: durationMsMetrics(event.durationMs),
|
|
22635
|
+
output: event.result
|
|
22636
|
+
});
|
|
22637
|
+
state.span.end();
|
|
22638
|
+
this.toolsById.delete(key);
|
|
22639
|
+
}
|
|
22640
|
+
handleTaskStart(event) {
|
|
22641
|
+
const parent = this.parentSpanForEvent(event);
|
|
22642
|
+
const metadata = {
|
|
22643
|
+
...extractEventMetadata(event),
|
|
22644
|
+
...event.role ? { "flue.role": event.role } : {},
|
|
22645
|
+
...event.cwd ? { "flue.cwd": event.cwd } : {},
|
|
22646
|
+
"flue.task_id": event.taskId,
|
|
22647
|
+
provider: "flue"
|
|
22648
|
+
};
|
|
22649
|
+
const span = startFlueSpan(parent, {
|
|
22650
|
+
name: "flue.task",
|
|
22651
|
+
spanAttributes: { type: "task" /* TASK */ }
|
|
22652
|
+
});
|
|
22653
|
+
safeLog3(span, {
|
|
22654
|
+
input: event.prompt,
|
|
22655
|
+
metadata
|
|
22656
|
+
});
|
|
22657
|
+
this.tasksById.set(event.taskId, {
|
|
22658
|
+
metadata,
|
|
22659
|
+
span,
|
|
22660
|
+
startTime: getCurrentUnixTimestamp()
|
|
22661
|
+
});
|
|
22662
|
+
}
|
|
22663
|
+
handleTask(event) {
|
|
22664
|
+
const state = this.tasksById.get(event.taskId);
|
|
22665
|
+
if (!state) {
|
|
22666
|
+
return;
|
|
22667
|
+
}
|
|
22668
|
+
safeLog3(state.span, {
|
|
22669
|
+
...event.isError ? { error: errorToString(event.result) } : {},
|
|
22670
|
+
metadata: {
|
|
22671
|
+
...state.metadata,
|
|
22672
|
+
...extractEventMetadata(event),
|
|
22673
|
+
...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
|
|
22674
|
+
},
|
|
22675
|
+
metrics: durationMsMetrics(event.durationMs),
|
|
22676
|
+
output: event.result
|
|
22677
|
+
});
|
|
22678
|
+
state.span.end();
|
|
22679
|
+
this.tasksById.delete(event.taskId);
|
|
22680
|
+
}
|
|
22681
|
+
handleCompactionStart(event) {
|
|
22682
|
+
const operationState = this.operationStateForEvent(event);
|
|
22683
|
+
const parent = operationState?.span ?? this.parentSpanForEvent(event);
|
|
22684
|
+
const metadata = {
|
|
22685
|
+
...extractEventMetadata(event),
|
|
22686
|
+
...event.reason ? { "flue.compaction_reason": event.reason } : {},
|
|
22687
|
+
provider: "flue"
|
|
22688
|
+
};
|
|
22689
|
+
const input = {
|
|
22690
|
+
...typeof event.estimatedTokens === "number" ? { estimatedTokens: event.estimatedTokens } : {},
|
|
22691
|
+
...event.reason ? { reason: event.reason } : {}
|
|
22692
|
+
};
|
|
22693
|
+
const span = startFlueSpan(parent, {
|
|
22694
|
+
name: "flue.compaction",
|
|
22695
|
+
spanAttributes: { type: "task" /* TASK */ }
|
|
22696
|
+
});
|
|
22697
|
+
safeLog3(span, {
|
|
22698
|
+
input,
|
|
22699
|
+
metadata
|
|
22700
|
+
});
|
|
22701
|
+
this.compactionsByScope.set(scopeKey(event), {
|
|
22702
|
+
input,
|
|
22703
|
+
metadata,
|
|
22704
|
+
operationState,
|
|
22705
|
+
span,
|
|
22706
|
+
startTime: getCurrentUnixTimestamp()
|
|
22707
|
+
});
|
|
22708
|
+
}
|
|
22709
|
+
handleCompaction(event) {
|
|
22710
|
+
const key = scopeKey(event);
|
|
22711
|
+
const state = this.compactionsByScope.get(key) ?? this.findCompactionState(event);
|
|
22712
|
+
if (!state) {
|
|
22713
|
+
return;
|
|
22714
|
+
}
|
|
22715
|
+
safeLog3(state.span, {
|
|
22716
|
+
metadata: {
|
|
22717
|
+
...state.metadata,
|
|
22718
|
+
...extractEventMetadata(event),
|
|
22719
|
+
...typeof event.messagesBefore === "number" ? { "flue.messages_before": event.messagesBefore } : {},
|
|
22720
|
+
...typeof event.messagesAfter === "number" ? { "flue.messages_after": event.messagesAfter } : {}
|
|
22721
|
+
},
|
|
22722
|
+
metrics: {
|
|
22723
|
+
...durationMsMetrics(event.durationMs),
|
|
22724
|
+
...metricsFromUsage(event.usage)
|
|
22725
|
+
},
|
|
22726
|
+
output: {
|
|
22727
|
+
messagesAfter: event.messagesAfter,
|
|
22728
|
+
messagesBefore: event.messagesBefore
|
|
22729
|
+
}
|
|
22730
|
+
});
|
|
22731
|
+
state.span.end();
|
|
22732
|
+
this.deleteCompactionState(state);
|
|
22733
|
+
}
|
|
22734
|
+
findCompactionState(event) {
|
|
22735
|
+
const operationState = this.operationStateForEvent(event);
|
|
22736
|
+
for (const state of this.compactionsByScope.values()) {
|
|
22737
|
+
if (operationState && state.operationState === operationState) {
|
|
22738
|
+
return state;
|
|
22739
|
+
}
|
|
22740
|
+
}
|
|
22741
|
+
return void 0;
|
|
22742
|
+
}
|
|
22743
|
+
finishCompactionsForOperation(operationState) {
|
|
22744
|
+
for (const state of [...this.compactionsByScope.values()]) {
|
|
22745
|
+
if (state.operationState !== operationState) {
|
|
22746
|
+
continue;
|
|
22747
|
+
}
|
|
22748
|
+
safeLog3(state.span, {
|
|
22749
|
+
input: state.input,
|
|
22750
|
+
metadata: state.metadata,
|
|
22751
|
+
metrics: {
|
|
22752
|
+
...buildDurationMetrics3(state.startTime)
|
|
22753
|
+
},
|
|
22754
|
+
output: { completed: true }
|
|
22755
|
+
});
|
|
22756
|
+
state.span.end();
|
|
22757
|
+
this.deleteCompactionState(state);
|
|
22758
|
+
}
|
|
22759
|
+
}
|
|
22760
|
+
deleteCompactionState(state) {
|
|
22761
|
+
for (const [key, candidate] of this.compactionsByScope) {
|
|
22762
|
+
if (candidate !== state) {
|
|
22763
|
+
continue;
|
|
22764
|
+
}
|
|
22765
|
+
this.compactionsByScope.delete(key);
|
|
22766
|
+
return;
|
|
22767
|
+
}
|
|
22768
|
+
}
|
|
22769
|
+
startSyntheticToolState(event, toolName) {
|
|
22770
|
+
const parent = this.parentSpanForEvent(event);
|
|
22771
|
+
const metadata = {
|
|
22772
|
+
...extractEventMetadata(event),
|
|
22773
|
+
...event.toolCallId ? { "flue.tool_call_id": event.toolCallId } : {},
|
|
22774
|
+
"flue.tool_name": toolName,
|
|
22775
|
+
provider: "flue"
|
|
22776
|
+
};
|
|
22777
|
+
const span = startFlueSpan(parent, {
|
|
22778
|
+
name: `tool: ${toolName}`,
|
|
22779
|
+
spanAttributes: { type: "tool" /* TOOL */ }
|
|
22780
|
+
});
|
|
22781
|
+
safeLog3(span, { metadata });
|
|
22782
|
+
return { metadata, span, startTime: getCurrentUnixTimestamp() };
|
|
22783
|
+
}
|
|
22784
|
+
operationStateForEvent(event) {
|
|
22785
|
+
if (event.operationId) {
|
|
22786
|
+
const operation = this.activeOperationsById.get(event.operationId) ?? this.promotePendingOperationForEvent(event);
|
|
22787
|
+
if (operation) {
|
|
22788
|
+
return operation;
|
|
22789
|
+
}
|
|
22790
|
+
}
|
|
22791
|
+
return this.activeOperationForEventScope(event) ?? this.pendingOperationForEventScope(event);
|
|
22792
|
+
}
|
|
22793
|
+
parentSpanForEvent(event) {
|
|
22794
|
+
if (event.operationId) {
|
|
22795
|
+
const operation = this.operationStateForEvent(event);
|
|
22796
|
+
if (operation) {
|
|
22797
|
+
return operation.span;
|
|
22798
|
+
}
|
|
22799
|
+
}
|
|
22800
|
+
if (event.taskId) {
|
|
22801
|
+
return this.tasksById.get(event.taskId)?.span;
|
|
22802
|
+
}
|
|
22803
|
+
return this.operationStateForEvent(event)?.span;
|
|
22804
|
+
}
|
|
22805
|
+
promotePendingOperationForEvent(event) {
|
|
22806
|
+
if (!event.operationId) {
|
|
22807
|
+
return void 0;
|
|
22808
|
+
}
|
|
22809
|
+
const scopePrefixes = operationScopePrefixes(event);
|
|
22810
|
+
for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
|
|
22811
|
+
if (!candidateQueue.length || !operationKeyMatchesScopes(candidateKey, scopePrefixes)) {
|
|
22812
|
+
continue;
|
|
22813
|
+
}
|
|
22814
|
+
const state = candidateQueue.shift();
|
|
22815
|
+
if (!state) {
|
|
22816
|
+
return void 0;
|
|
22817
|
+
}
|
|
22818
|
+
state.operationId = event.operationId;
|
|
22819
|
+
this.activeOperationsById.set(event.operationId, state);
|
|
22820
|
+
addScopedOperation(this.activeOperationsByScope, event, state);
|
|
22821
|
+
state.metadata = {
|
|
22822
|
+
...state.metadata,
|
|
22823
|
+
...extractEventMetadata(event),
|
|
22824
|
+
"flue.operation_id": event.operationId
|
|
22825
|
+
};
|
|
22826
|
+
safeLog3(state.span, { metadata: state.metadata });
|
|
22827
|
+
return state;
|
|
22828
|
+
}
|
|
22829
|
+
return void 0;
|
|
22830
|
+
}
|
|
22831
|
+
activeOperationForEventScope(event) {
|
|
22832
|
+
for (const scope of operationScopeNames(event)) {
|
|
22833
|
+
const operations = this.activeOperationsByScope.get(scope);
|
|
22834
|
+
if (operations?.length) {
|
|
22835
|
+
return operations[operations.length - 1];
|
|
22836
|
+
}
|
|
22837
|
+
}
|
|
22838
|
+
return void 0;
|
|
22839
|
+
}
|
|
22840
|
+
pendingOperationForEventScope(event) {
|
|
22841
|
+
const scopePrefixes = operationScopePrefixes(event);
|
|
22842
|
+
for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
|
|
22843
|
+
if (!candidateQueue.length || !operationKeyMatchesScopes(candidateKey, scopePrefixes)) {
|
|
22844
|
+
continue;
|
|
22845
|
+
}
|
|
22846
|
+
return candidateQueue[0];
|
|
22847
|
+
}
|
|
22848
|
+
return void 0;
|
|
22849
|
+
}
|
|
22850
|
+
takePendingOperationForEvent(event) {
|
|
22851
|
+
const key = operationKey(event.session, event.operationKind);
|
|
22852
|
+
const queue = this.pendingOperationsByKey.get(key);
|
|
22853
|
+
if (queue?.length) {
|
|
22854
|
+
return queue.shift();
|
|
22855
|
+
}
|
|
22856
|
+
for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
|
|
22857
|
+
if (candidateKey.endsWith(`::${event.operationKind}`) && candidateQueue.length) {
|
|
22858
|
+
return candidateQueue.shift();
|
|
22859
|
+
}
|
|
22860
|
+
}
|
|
22861
|
+
return void 0;
|
|
22862
|
+
}
|
|
22863
|
+
pendingOperationQueue(key) {
|
|
22864
|
+
const existing = this.pendingOperationsByKey.get(key);
|
|
22865
|
+
if (existing) {
|
|
22866
|
+
return existing;
|
|
22867
|
+
}
|
|
22868
|
+
const queue = [];
|
|
22869
|
+
this.pendingOperationsByKey.set(key, queue);
|
|
22870
|
+
return queue;
|
|
22871
|
+
}
|
|
22872
|
+
};
|
|
22873
|
+
function isInstrumentedOperation(operation) {
|
|
22874
|
+
return operation === "prompt" || operation === "skill" || operation === "task" || operation === "compact";
|
|
22875
|
+
}
|
|
22876
|
+
function getSessionName(session) {
|
|
22877
|
+
return typeof session?.name === "string" ? session.name : void 0;
|
|
22878
|
+
}
|
|
22879
|
+
function operationKey(sessionName, operation) {
|
|
22880
|
+
return `${sessionName ?? "unknown"}::${operation}`;
|
|
22881
|
+
}
|
|
22882
|
+
function operationScopePrefixes(event) {
|
|
22883
|
+
const scopes = /* @__PURE__ */ new Set();
|
|
22884
|
+
for (const scope of operationScopeNames(event)) {
|
|
22885
|
+
scopes.add(`${scope}::`);
|
|
22886
|
+
}
|
|
22887
|
+
return scopes;
|
|
22888
|
+
}
|
|
22889
|
+
function operationKeyMatchesScopes(key, scopes) {
|
|
22890
|
+
for (const scope of scopes) {
|
|
22891
|
+
if (key.startsWith(scope)) {
|
|
22892
|
+
return true;
|
|
22893
|
+
}
|
|
22894
|
+
}
|
|
22895
|
+
return false;
|
|
22896
|
+
}
|
|
22897
|
+
function operationScopeNames(event) {
|
|
22898
|
+
const scopes = /* @__PURE__ */ new Set();
|
|
22899
|
+
if (event.session) {
|
|
22900
|
+
scopes.add(event.session);
|
|
22901
|
+
}
|
|
22902
|
+
if (event.parentSession) {
|
|
22903
|
+
scopes.add(event.parentSession);
|
|
22904
|
+
}
|
|
22905
|
+
if (!scopes.size) {
|
|
22906
|
+
scopes.add("unknown");
|
|
22907
|
+
}
|
|
22908
|
+
return scopes;
|
|
22909
|
+
}
|
|
22910
|
+
function addScopedOperation(operationsByScope, event, state) {
|
|
22911
|
+
for (const scope of operationScopeNames(event)) {
|
|
22912
|
+
addOperationToScope(operationsByScope, scope, state);
|
|
22913
|
+
}
|
|
22914
|
+
}
|
|
22915
|
+
function addOperationToScope(operationsByScope, scope, state) {
|
|
22916
|
+
const operations = operationsByScope.get(scope);
|
|
22917
|
+
if (operations) {
|
|
22918
|
+
if (!operations.includes(state)) {
|
|
22919
|
+
operations.push(state);
|
|
22920
|
+
}
|
|
22921
|
+
} else {
|
|
22922
|
+
operationsByScope.set(scope, [state]);
|
|
22923
|
+
}
|
|
22924
|
+
}
|
|
22925
|
+
function removeScopedOperation(operationsByScope, state) {
|
|
22926
|
+
for (const [scope, operations] of operationsByScope) {
|
|
22927
|
+
const index = operations.indexOf(state);
|
|
22928
|
+
if (index === -1) {
|
|
22929
|
+
continue;
|
|
22930
|
+
}
|
|
22931
|
+
operations.splice(index, 1);
|
|
22932
|
+
if (operations.length === 0) {
|
|
22933
|
+
operationsByScope.delete(scope);
|
|
22934
|
+
}
|
|
22935
|
+
}
|
|
22936
|
+
}
|
|
22937
|
+
function removePendingOperation(pendingOperationsByKey, state) {
|
|
22938
|
+
for (const [key, queue] of pendingOperationsByKey) {
|
|
22939
|
+
const index = queue.indexOf(state);
|
|
22940
|
+
if (index === -1) {
|
|
22941
|
+
continue;
|
|
22942
|
+
}
|
|
22943
|
+
queue.splice(index, 1);
|
|
22944
|
+
if (queue.length === 0) {
|
|
22945
|
+
pendingOperationsByKey.delete(key);
|
|
22946
|
+
}
|
|
22947
|
+
return;
|
|
22948
|
+
}
|
|
22949
|
+
}
|
|
22950
|
+
function extractSessionMetadata(session) {
|
|
22951
|
+
const sessionName = getSessionName(session);
|
|
22952
|
+
return sessionName ? { "flue.session": sessionName } : {};
|
|
22953
|
+
}
|
|
22954
|
+
function extractEventMetadata(event) {
|
|
22955
|
+
return {
|
|
22956
|
+
...event.runId ? { "flue.run_id": event.runId } : {},
|
|
22957
|
+
...typeof event.eventIndex === "number" ? { "flue.event_index": event.eventIndex } : {},
|
|
22958
|
+
...event.session ? { "flue.session": event.session } : {},
|
|
22959
|
+
...event.parentSession ? { "flue.parent_session": event.parentSession } : {},
|
|
22960
|
+
...event.harness ? { "flue.harness": event.harness } : {},
|
|
22961
|
+
...event.taskId ? { "flue.task_id": event.taskId } : {},
|
|
22962
|
+
...event.operationId ? { "flue.operation_id": event.operationId } : {}
|
|
22963
|
+
};
|
|
22964
|
+
}
|
|
22965
|
+
function extractOperationInput(operation, args) {
|
|
22966
|
+
switch (operation) {
|
|
22967
|
+
case "prompt":
|
|
22968
|
+
case "task":
|
|
22969
|
+
return args[0];
|
|
22970
|
+
case "skill":
|
|
22971
|
+
return {
|
|
22972
|
+
args: getOptionObject(args[1])?.args,
|
|
22973
|
+
name: args[0]
|
|
22974
|
+
};
|
|
22975
|
+
case "compact":
|
|
22976
|
+
return void 0;
|
|
22977
|
+
}
|
|
22978
|
+
}
|
|
22979
|
+
function extractOperationInputMetadata(operation, args) {
|
|
22980
|
+
const options = getOptionObject(args[1]);
|
|
22981
|
+
return {
|
|
22982
|
+
...operation === "skill" && typeof args[0] === "string" ? { "flue.skill_name": args[0] } : {},
|
|
22983
|
+
...options?.model ? { model: options.model, "flue.model": options.model } : {},
|
|
22984
|
+
...options?.role ? { "flue.role": options.role } : {},
|
|
22985
|
+
...options?.thinkingLevel ? { "flue.thinking_level": options.thinkingLevel } : {},
|
|
22986
|
+
...typeof options?.cwd === "string" ? { "flue.cwd": options.cwd } : {},
|
|
22987
|
+
...Array.isArray(options?.tools) ? {
|
|
22988
|
+
"flue.tools_count": options.tools.length,
|
|
22989
|
+
tools: summarizeTools(options.tools)
|
|
22990
|
+
} : {},
|
|
22991
|
+
...Array.isArray(options?.images) ? { "flue.images_count": options.images.length } : {},
|
|
22992
|
+
...options?.result || options?.schema ? { "flue.result_schema": true } : {}
|
|
22993
|
+
};
|
|
22994
|
+
}
|
|
22995
|
+
function getOptionObject(value) {
|
|
22996
|
+
return isObject(value) ? value : void 0;
|
|
22997
|
+
}
|
|
22998
|
+
function summarizeTools(tools) {
|
|
22999
|
+
return tools.flatMap((tool) => {
|
|
23000
|
+
if (!isObject(tool)) {
|
|
23001
|
+
return [];
|
|
23002
|
+
}
|
|
23003
|
+
const name = typeof tool.name === "string" ? tool.name : void 0;
|
|
23004
|
+
if (!name) {
|
|
23005
|
+
return [];
|
|
23006
|
+
}
|
|
23007
|
+
return [
|
|
23008
|
+
{
|
|
23009
|
+
function: {
|
|
23010
|
+
description: typeof tool.description === "string" ? tool.description : void 0,
|
|
23011
|
+
name,
|
|
23012
|
+
parameters: tool.parameters
|
|
23013
|
+
},
|
|
23014
|
+
type: "function"
|
|
23015
|
+
}
|
|
23016
|
+
];
|
|
23017
|
+
});
|
|
23018
|
+
}
|
|
23019
|
+
function extractPromptResponseMetadata(result) {
|
|
23020
|
+
const modelId = result?.model && typeof result.model.id === "string" ? result.model.id : void 0;
|
|
23021
|
+
return modelId ? {
|
|
23022
|
+
model: modelId,
|
|
23023
|
+
"flue.model": modelId
|
|
23024
|
+
} : {};
|
|
23025
|
+
}
|
|
23026
|
+
function extractOperationOutput(result) {
|
|
23027
|
+
if (!result) {
|
|
23028
|
+
return void 0;
|
|
23029
|
+
}
|
|
23030
|
+
if ("data" in result) {
|
|
23031
|
+
return result.data;
|
|
23032
|
+
}
|
|
23033
|
+
if ("text" in result) {
|
|
23034
|
+
return result.text;
|
|
23035
|
+
}
|
|
23036
|
+
return result;
|
|
23037
|
+
}
|
|
23038
|
+
function metricsFromUsage(usage) {
|
|
23039
|
+
return {
|
|
23040
|
+
...typeof usage?.input === "number" ? { prompt_tokens: usage.input } : {},
|
|
23041
|
+
...typeof usage?.output === "number" ? { completion_tokens: usage.output } : {},
|
|
23042
|
+
...typeof usage?.cacheRead === "number" ? { prompt_cached_tokens: usage.cacheRead } : {},
|
|
23043
|
+
...typeof usage?.cacheWrite === "number" ? { prompt_cache_creation_tokens: usage.cacheWrite } : {},
|
|
23044
|
+
...typeof usage?.totalTokens === "number" ? { tokens: usage.totalTokens } : {},
|
|
23045
|
+
...typeof usage?.cost?.total === "number" ? { estimated_cost: usage.cost.total } : {}
|
|
23046
|
+
};
|
|
23047
|
+
}
|
|
23048
|
+
function buildDurationMetrics3(startTime) {
|
|
23049
|
+
return {
|
|
23050
|
+
duration_ms: Math.max(0, (getCurrentUnixTimestamp() - startTime) * 1e3)
|
|
23051
|
+
};
|
|
23052
|
+
}
|
|
23053
|
+
function durationMsMetrics(durationMs) {
|
|
23054
|
+
return typeof durationMs === "number" ? { duration_ms: durationMs } : {};
|
|
23055
|
+
}
|
|
23056
|
+
function scopeKey(event) {
|
|
23057
|
+
if (event.operationId) {
|
|
23058
|
+
return `operation:${event.operationId}`;
|
|
23059
|
+
}
|
|
23060
|
+
if (event.taskId) {
|
|
23061
|
+
return `task:${event.taskId}`;
|
|
23062
|
+
}
|
|
23063
|
+
if (event.session) {
|
|
23064
|
+
return `session:${event.session}`;
|
|
23065
|
+
}
|
|
23066
|
+
return "flue:unknown";
|
|
23067
|
+
}
|
|
23068
|
+
function toolKey(event) {
|
|
23069
|
+
return `${scopeKey(event)}::tool:${event.toolCallId ?? "unknown"}`;
|
|
23070
|
+
}
|
|
23071
|
+
function toAssistantOutput(text, finishReason, reasoning, toolCalls) {
|
|
23072
|
+
return [
|
|
23073
|
+
{
|
|
23074
|
+
finish_reason: finishReason ?? "stop",
|
|
23075
|
+
index: 0,
|
|
23076
|
+
message: {
|
|
23077
|
+
content: text,
|
|
23078
|
+
...reasoning ? { reasoning } : {},
|
|
23079
|
+
role: "assistant",
|
|
23080
|
+
...toolCalls?.length ? {
|
|
23081
|
+
tool_calls: toolCalls.map((toolCall) => ({
|
|
23082
|
+
function: {
|
|
23083
|
+
arguments: toolCall.args === void 0 ? "{}" : JSON.stringify(toolCall.args),
|
|
23084
|
+
name: toolCall.toolName ?? "unknown"
|
|
23085
|
+
},
|
|
23086
|
+
...toolCall.toolCallId ? { id: toolCall.toolCallId } : {},
|
|
23087
|
+
type: "function"
|
|
23088
|
+
}))
|
|
23089
|
+
} : {}
|
|
23090
|
+
}
|
|
23091
|
+
}
|
|
23092
|
+
];
|
|
23093
|
+
}
|
|
23094
|
+
function startFlueSpan(parent, args) {
|
|
23095
|
+
return parent ? withCurrent(parent, () => startSpan(args)) : startSpan(args);
|
|
23096
|
+
}
|
|
23097
|
+
function safeLog3(span, event) {
|
|
23098
|
+
try {
|
|
23099
|
+
span.log(event);
|
|
23100
|
+
} catch (error) {
|
|
23101
|
+
logInstrumentationError3("Flue span log", error);
|
|
23102
|
+
}
|
|
23103
|
+
}
|
|
23104
|
+
function errorToString(error) {
|
|
23105
|
+
if (error instanceof Error) {
|
|
23106
|
+
return error.message;
|
|
23107
|
+
}
|
|
23108
|
+
if (typeof error === "string") {
|
|
23109
|
+
return error;
|
|
23110
|
+
}
|
|
23111
|
+
try {
|
|
23112
|
+
return JSON.stringify(error);
|
|
23113
|
+
} catch {
|
|
23114
|
+
return String(error);
|
|
23115
|
+
}
|
|
23116
|
+
}
|
|
23117
|
+
function logInstrumentationError3(label, error) {
|
|
23118
|
+
console.error(`Error in ${label} instrumentation:`, error);
|
|
23119
|
+
}
|
|
23120
|
+
|
|
23121
|
+
// src/wrappers/langchain/callback-handler.ts
|
|
23122
|
+
var BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME = "BraintrustCallbackHandler";
|
|
23123
|
+
var BraintrustLangChainCallbackHandler = class {
|
|
23124
|
+
name = BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
|
|
23125
|
+
spans = /* @__PURE__ */ new Map();
|
|
23126
|
+
skippedRuns = /* @__PURE__ */ new Set();
|
|
23127
|
+
parent;
|
|
23128
|
+
rootRunId;
|
|
23129
|
+
options;
|
|
23130
|
+
startTimes = /* @__PURE__ */ new Map();
|
|
23131
|
+
firstTokenTimes = /* @__PURE__ */ new Map();
|
|
23132
|
+
ttftMs = /* @__PURE__ */ new Map();
|
|
23133
|
+
constructor(options) {
|
|
23134
|
+
this.parent = options?.parent;
|
|
23135
|
+
this.options = {
|
|
23136
|
+
debug: options?.debug ?? false,
|
|
23137
|
+
excludeMetadataProps: options?.excludeMetadataProps ?? /^(l[sc]_|langgraph_|__pregel_|checkpoint_ns)/,
|
|
23138
|
+
logger: options?.logger
|
|
23139
|
+
};
|
|
23140
|
+
}
|
|
23141
|
+
startSpan({
|
|
23142
|
+
runId,
|
|
23143
|
+
parentRunId,
|
|
23144
|
+
...args
|
|
23145
|
+
}) {
|
|
23146
|
+
if (this.spans.has(runId)) {
|
|
23147
|
+
return;
|
|
23148
|
+
}
|
|
23149
|
+
if (!parentRunId) {
|
|
23150
|
+
this.rootRunId = runId;
|
|
23151
|
+
}
|
|
23152
|
+
const tags = args.event?.tags;
|
|
23153
|
+
const spanAttributes = args.spanAttributes || {};
|
|
23154
|
+
spanAttributes.type = args.type || spanAttributes.type || "task";
|
|
23155
|
+
args.type = spanAttributes.type;
|
|
23156
|
+
const currentParent = (typeof this.parent === "function" ? this.parent() : this.parent) ?? currentSpan();
|
|
23157
|
+
let parentSpan;
|
|
23158
|
+
if (parentRunId && this.spans.has(parentRunId)) {
|
|
23159
|
+
parentSpan = this.spans.get(parentRunId);
|
|
23160
|
+
} else if (!Object.is(currentParent, NOOP_SPAN)) {
|
|
23161
|
+
parentSpan = currentParent;
|
|
23162
|
+
} else if (this.options.logger) {
|
|
23163
|
+
parentSpan = this.options.logger;
|
|
23164
|
+
} else {
|
|
23165
|
+
parentSpan = { startSpan };
|
|
23166
|
+
}
|
|
23167
|
+
args.event = {
|
|
23168
|
+
...args.event,
|
|
23169
|
+
tags: void 0,
|
|
23170
|
+
metadata: {
|
|
23171
|
+
...tags ? { tags } : {},
|
|
23172
|
+
...args.event?.metadata,
|
|
23173
|
+
braintrust: {
|
|
23174
|
+
integration_name: "langchain-js",
|
|
23175
|
+
sdk_language: "javascript"
|
|
23176
|
+
},
|
|
23177
|
+
run_id: runId,
|
|
23178
|
+
parent_run_id: parentRunId,
|
|
23179
|
+
...this.options.debug ? { runId, parentRunId } : {}
|
|
23180
|
+
}
|
|
23181
|
+
};
|
|
23182
|
+
let span = parentSpan.startSpan(args);
|
|
23183
|
+
if (!Object.is(this.options.logger, NOOP_SPAN) && Object.is(span, NOOP_SPAN)) {
|
|
23184
|
+
span = initLogger().startSpan(args);
|
|
23185
|
+
}
|
|
23186
|
+
this.spans.set(runId, span);
|
|
23187
|
+
}
|
|
23188
|
+
endSpan({
|
|
23189
|
+
runId,
|
|
23190
|
+
parentRunId,
|
|
23191
|
+
tags,
|
|
23192
|
+
metadata,
|
|
23193
|
+
...args
|
|
23194
|
+
}) {
|
|
23195
|
+
if (!this.spans.has(runId)) {
|
|
23196
|
+
return;
|
|
23197
|
+
}
|
|
23198
|
+
if (this.skippedRuns.has(runId)) {
|
|
23199
|
+
this.skippedRuns.delete(runId);
|
|
23200
|
+
return;
|
|
23201
|
+
}
|
|
23202
|
+
const span = this.spans.get(runId);
|
|
23203
|
+
this.spans.delete(runId);
|
|
23204
|
+
if (runId === this.rootRunId) {
|
|
23205
|
+
this.rootRunId = void 0;
|
|
23206
|
+
}
|
|
23207
|
+
span.log({ ...args, metadata: { tags, ...metadata } });
|
|
23208
|
+
span.end();
|
|
23209
|
+
}
|
|
23210
|
+
async handleLLMStart(llm, prompts, runId, parentRunId, extraParams, tags, metadata, runName) {
|
|
23211
|
+
this.startSpan({
|
|
23212
|
+
runId,
|
|
23213
|
+
parentRunId,
|
|
23214
|
+
name: runName ?? getSerializedName(llm) ?? "LLM",
|
|
23215
|
+
type: "llm",
|
|
23216
|
+
event: {
|
|
23217
|
+
input: prompts,
|
|
23218
|
+
tags,
|
|
23219
|
+
metadata: {
|
|
23220
|
+
serialized: llm,
|
|
23221
|
+
name: runName,
|
|
23222
|
+
metadata,
|
|
23223
|
+
...extraParams
|
|
23224
|
+
}
|
|
23225
|
+
}
|
|
23226
|
+
});
|
|
23227
|
+
}
|
|
23228
|
+
async handleLLMError(err, runId, parentRunId, tags) {
|
|
23229
|
+
this.endSpan({ runId, parentRunId, error: err, tags });
|
|
23230
|
+
}
|
|
23231
|
+
async handleLLMEnd(output, runId, parentRunId, tags) {
|
|
23232
|
+
const metrics = getMetricsFromResponse(output);
|
|
23233
|
+
const modelName2 = getModelNameFromResponse(output);
|
|
23234
|
+
const ttft = this.ttftMs.get(runId);
|
|
23235
|
+
if (ttft !== void 0) {
|
|
23236
|
+
metrics.time_to_first_token = ttft;
|
|
23237
|
+
}
|
|
23238
|
+
this.startTimes.delete(runId);
|
|
23239
|
+
this.firstTokenTimes.delete(runId);
|
|
23240
|
+
this.ttftMs.delete(runId);
|
|
23241
|
+
this.endSpan({
|
|
23242
|
+
runId,
|
|
23243
|
+
parentRunId,
|
|
23244
|
+
output,
|
|
23245
|
+
metrics,
|
|
23246
|
+
tags,
|
|
23247
|
+
metadata: {
|
|
23248
|
+
model: modelName2
|
|
23249
|
+
}
|
|
23250
|
+
});
|
|
23251
|
+
}
|
|
23252
|
+
async handleChatModelStart(llm, messages, runId, parentRunId, extraParams, tags, metadata, runName) {
|
|
23253
|
+
this.startTimes.set(runId, Date.now());
|
|
23254
|
+
this.firstTokenTimes.delete(runId);
|
|
23255
|
+
this.ttftMs.delete(runId);
|
|
23256
|
+
this.startSpan({
|
|
23257
|
+
runId,
|
|
23258
|
+
parentRunId,
|
|
23259
|
+
name: runName ?? getSerializedName(llm) ?? "Chat Model",
|
|
23260
|
+
type: "llm",
|
|
23261
|
+
event: {
|
|
23262
|
+
input: messages,
|
|
23263
|
+
tags,
|
|
23264
|
+
metadata: {
|
|
23265
|
+
serialized: llm,
|
|
23266
|
+
name: runName,
|
|
23267
|
+
metadata,
|
|
23268
|
+
...extraParams
|
|
23269
|
+
}
|
|
23270
|
+
}
|
|
23271
|
+
});
|
|
23272
|
+
}
|
|
23273
|
+
async handleChainStart(chain, inputs, runId, parentRunId, tags, metadata, runType, runName) {
|
|
23274
|
+
if (tags?.includes("langsmith:hidden")) {
|
|
23275
|
+
this.skippedRuns.add(runId);
|
|
23276
|
+
return;
|
|
23277
|
+
}
|
|
23278
|
+
this.startSpan({
|
|
23279
|
+
runId,
|
|
23280
|
+
parentRunId,
|
|
23281
|
+
name: runName ?? getSerializedName(chain) ?? "Chain",
|
|
23282
|
+
event: {
|
|
23283
|
+
input: inputs,
|
|
23284
|
+
tags,
|
|
23285
|
+
metadata: {
|
|
23286
|
+
serialized: chain,
|
|
23287
|
+
name: runName,
|
|
23288
|
+
metadata,
|
|
23289
|
+
run_type: runType
|
|
23290
|
+
}
|
|
23291
|
+
}
|
|
23292
|
+
});
|
|
23293
|
+
}
|
|
23294
|
+
async handleChainError(err, runId, parentRunId, tags, kwargs) {
|
|
23295
|
+
this.endSpan({ runId, parentRunId, error: err, tags, metadata: kwargs });
|
|
23296
|
+
}
|
|
23297
|
+
async handleChainEnd(outputs, runId, parentRunId, tags, kwargs) {
|
|
23298
|
+
this.endSpan({
|
|
23299
|
+
runId,
|
|
23300
|
+
parentRunId,
|
|
23301
|
+
tags,
|
|
23302
|
+
output: outputs,
|
|
23303
|
+
metadata: { ...kwargs }
|
|
23304
|
+
});
|
|
23305
|
+
}
|
|
23306
|
+
async handleToolStart(tool, input, runId, parentRunId, tags, metadata, runName) {
|
|
23307
|
+
this.startSpan({
|
|
23308
|
+
runId,
|
|
23309
|
+
parentRunId,
|
|
23310
|
+
name: runName ?? getSerializedName(tool) ?? "Tool",
|
|
23311
|
+
type: "llm",
|
|
23312
|
+
event: {
|
|
23313
|
+
input: safeJsonParse(input),
|
|
23314
|
+
tags,
|
|
23315
|
+
metadata: {
|
|
23316
|
+
metadata,
|
|
23317
|
+
serialized: tool,
|
|
23318
|
+
input_str: input,
|
|
23319
|
+
input: safeJsonParse(input),
|
|
23320
|
+
name: runName
|
|
23321
|
+
}
|
|
23322
|
+
}
|
|
23323
|
+
});
|
|
23324
|
+
}
|
|
23325
|
+
async handleToolError(err, runId, parentRunId, tags) {
|
|
23326
|
+
this.endSpan({ runId, parentRunId, error: err, tags });
|
|
23327
|
+
}
|
|
23328
|
+
async handleToolEnd(output, runId, parentRunId, tags) {
|
|
23329
|
+
this.endSpan({ runId, parentRunId, output, tags });
|
|
23330
|
+
}
|
|
23331
|
+
async handleAgentAction(action, runId, parentRunId, tags) {
|
|
23332
|
+
this.startSpan({
|
|
23333
|
+
runId,
|
|
23334
|
+
parentRunId,
|
|
23335
|
+
type: "llm",
|
|
23336
|
+
name: typeof action.tool === "string" ? action.tool : "Agent",
|
|
23337
|
+
event: {
|
|
23338
|
+
input: action,
|
|
23339
|
+
tags
|
|
23340
|
+
}
|
|
23341
|
+
});
|
|
23342
|
+
}
|
|
23343
|
+
async handleAgentEnd(action, runId, parentRunId, tags) {
|
|
23344
|
+
this.endSpan({ runId, parentRunId, output: action, tags });
|
|
23345
|
+
}
|
|
23346
|
+
async handleRetrieverStart(retriever, query, runId, parentRunId, tags, metadata, name) {
|
|
23347
|
+
this.startSpan({
|
|
23348
|
+
runId,
|
|
23349
|
+
parentRunId,
|
|
23350
|
+
name: name ?? getSerializedName(retriever) ?? "Retriever",
|
|
23351
|
+
type: "function",
|
|
23352
|
+
event: {
|
|
23353
|
+
input: query,
|
|
23354
|
+
tags,
|
|
23355
|
+
metadata: {
|
|
23356
|
+
serialized: retriever,
|
|
23357
|
+
metadata,
|
|
23358
|
+
name
|
|
23359
|
+
}
|
|
23360
|
+
}
|
|
23361
|
+
});
|
|
23362
|
+
}
|
|
23363
|
+
async handleRetrieverEnd(documents, runId, parentRunId, tags) {
|
|
23364
|
+
this.endSpan({ runId, parentRunId, output: documents, tags });
|
|
23365
|
+
}
|
|
23366
|
+
async handleRetrieverError(err, runId, parentRunId, tags) {
|
|
23367
|
+
this.endSpan({ runId, parentRunId, error: err, tags });
|
|
23368
|
+
}
|
|
23369
|
+
async handleLLMNewToken(_token, _idx, runId, _parentRunId, _tags) {
|
|
23370
|
+
if (!this.firstTokenTimes.has(runId)) {
|
|
23371
|
+
const now2 = Date.now();
|
|
23372
|
+
this.firstTokenTimes.set(runId, now2);
|
|
23373
|
+
const start = this.startTimes.get(runId);
|
|
23374
|
+
if (start !== void 0) {
|
|
23375
|
+
this.ttftMs.set(runId, (now2 - start) / 1e3);
|
|
23376
|
+
}
|
|
23377
|
+
}
|
|
23378
|
+
}
|
|
23379
|
+
};
|
|
23380
|
+
function getSerializedName(serialized) {
|
|
23381
|
+
if (typeof serialized.name === "string") {
|
|
23382
|
+
return serialized.name;
|
|
23383
|
+
}
|
|
23384
|
+
const lastIdPart = serialized.id?.at(-1);
|
|
23385
|
+
return typeof lastIdPart === "string" ? lastIdPart : void 0;
|
|
23386
|
+
}
|
|
23387
|
+
function cleanObject(obj) {
|
|
23388
|
+
return Object.fromEntries(
|
|
23389
|
+
Object.entries(obj).filter(([, value]) => {
|
|
23390
|
+
if (typeof value !== "number") {
|
|
23391
|
+
return false;
|
|
23392
|
+
}
|
|
23393
|
+
return Number.isFinite(value);
|
|
23394
|
+
})
|
|
23395
|
+
);
|
|
23396
|
+
}
|
|
23397
|
+
function walkGenerations(response) {
|
|
23398
|
+
const result = [];
|
|
23399
|
+
const generations = response.generations || [];
|
|
23400
|
+
for (const batch of generations) {
|
|
23401
|
+
if (Array.isArray(batch)) {
|
|
23402
|
+
for (const generation of batch) {
|
|
23403
|
+
if (isRecord(generation)) {
|
|
23404
|
+
result.push(generation);
|
|
23405
|
+
}
|
|
23406
|
+
}
|
|
23407
|
+
} else if (isRecord(batch)) {
|
|
23408
|
+
result.push(batch);
|
|
23409
|
+
}
|
|
23410
|
+
}
|
|
23411
|
+
return result;
|
|
23412
|
+
}
|
|
23413
|
+
function getModelNameFromResponse(response) {
|
|
23414
|
+
for (const generation of walkGenerations(response)) {
|
|
23415
|
+
const message = generation.message;
|
|
23416
|
+
if (!isRecord(message)) {
|
|
23417
|
+
continue;
|
|
23418
|
+
}
|
|
23419
|
+
const responseMetadata = message.response_metadata;
|
|
23420
|
+
if (!isRecord(responseMetadata)) {
|
|
23421
|
+
continue;
|
|
23422
|
+
}
|
|
23423
|
+
const modelName3 = responseMetadata.model_name ?? responseMetadata.model;
|
|
23424
|
+
if (typeof modelName3 === "string") {
|
|
23425
|
+
return modelName3;
|
|
23426
|
+
}
|
|
23427
|
+
}
|
|
23428
|
+
const llmOutput = response.llmOutput || {};
|
|
23429
|
+
const modelName2 = llmOutput.model_name ?? llmOutput.model;
|
|
23430
|
+
return typeof modelName2 === "string" ? modelName2 : void 0;
|
|
23431
|
+
}
|
|
23432
|
+
function getMetricsFromResponse(response) {
|
|
23433
|
+
for (const generation of walkGenerations(response)) {
|
|
23434
|
+
const message = generation.message;
|
|
23435
|
+
if (!isRecord(message)) {
|
|
23436
|
+
continue;
|
|
23437
|
+
}
|
|
23438
|
+
const usageMetadata = message.usage_metadata;
|
|
23439
|
+
if (!isRecord(usageMetadata)) {
|
|
23440
|
+
continue;
|
|
23441
|
+
}
|
|
23442
|
+
const inputTokenDetails = usageMetadata.input_token_details;
|
|
23443
|
+
return cleanObject({
|
|
23444
|
+
total_tokens: usageMetadata.total_tokens,
|
|
23445
|
+
prompt_tokens: usageMetadata.input_tokens,
|
|
23446
|
+
completion_tokens: usageMetadata.output_tokens,
|
|
23447
|
+
prompt_cache_creation_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_creation : void 0,
|
|
23448
|
+
prompt_cached_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_read : void 0
|
|
23449
|
+
});
|
|
23450
|
+
}
|
|
23451
|
+
const llmOutput = response.llmOutput || {};
|
|
23452
|
+
const tokenUsage = isRecord(llmOutput.tokenUsage) ? llmOutput.tokenUsage : isRecord(llmOutput.estimatedTokens) ? llmOutput.estimatedTokens : {};
|
|
23453
|
+
return cleanObject({
|
|
23454
|
+
total_tokens: tokenUsage.totalTokens,
|
|
23455
|
+
prompt_tokens: tokenUsage.promptTokens,
|
|
23456
|
+
completion_tokens: tokenUsage.completionTokens
|
|
23457
|
+
});
|
|
23458
|
+
}
|
|
23459
|
+
function safeJsonParse(input) {
|
|
23460
|
+
try {
|
|
23461
|
+
return JSON.parse(input);
|
|
23462
|
+
} catch {
|
|
23463
|
+
return input;
|
|
23464
|
+
}
|
|
23465
|
+
}
|
|
23466
|
+
function isRecord(value) {
|
|
23467
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
23468
|
+
}
|
|
23469
|
+
|
|
23470
|
+
// src/instrumentation/plugins/langchain-channels.ts
|
|
23471
|
+
var langChainChannels = defineChannels("@langchain/core", {
|
|
23472
|
+
configure: channel({
|
|
23473
|
+
channelName: "CallbackManager.configure",
|
|
23474
|
+
kind: "sync-stream"
|
|
23475
|
+
}),
|
|
23476
|
+
configureSync: channel({
|
|
23477
|
+
channelName: "CallbackManager._configureSync",
|
|
23478
|
+
kind: "sync-stream"
|
|
23479
|
+
})
|
|
23480
|
+
});
|
|
23481
|
+
|
|
23482
|
+
// src/instrumentation/plugins/langchain-plugin.ts
|
|
23483
|
+
var LangChainPlugin = class extends BasePlugin {
|
|
23484
|
+
injectedManagers = /* @__PURE__ */ new WeakSet();
|
|
23485
|
+
onEnable() {
|
|
23486
|
+
this.subscribeToConfigure(langChainChannels.configure);
|
|
23487
|
+
this.subscribeToConfigure(langChainChannels.configureSync);
|
|
23488
|
+
}
|
|
23489
|
+
onDisable() {
|
|
23490
|
+
for (const unsubscribe of this.unsubscribers) {
|
|
23491
|
+
unsubscribe();
|
|
23492
|
+
}
|
|
23493
|
+
this.unsubscribers = [];
|
|
23494
|
+
this.injectedManagers = /* @__PURE__ */ new WeakSet();
|
|
23495
|
+
}
|
|
23496
|
+
subscribeToConfigure(channel2) {
|
|
23497
|
+
const tracingChannel = channel2.tracingChannel();
|
|
23498
|
+
const handlers = {
|
|
23499
|
+
start: (event) => {
|
|
23500
|
+
injectHandlerIntoArguments(event.arguments);
|
|
23501
|
+
},
|
|
23502
|
+
end: (event) => {
|
|
23503
|
+
this.injectHandler(event.result);
|
|
23504
|
+
}
|
|
23505
|
+
};
|
|
23506
|
+
tracingChannel.subscribe(handlers);
|
|
23507
|
+
this.unsubscribers.push(() => {
|
|
23508
|
+
tracingChannel.unsubscribe(handlers);
|
|
23509
|
+
});
|
|
23510
|
+
}
|
|
23511
|
+
injectHandler(result) {
|
|
23512
|
+
if (!isCallbackManager(result)) {
|
|
23513
|
+
return;
|
|
23514
|
+
}
|
|
23515
|
+
if (this.injectedManagers.has(result) || hasBraintrustHandler(result)) {
|
|
23516
|
+
return;
|
|
23517
|
+
}
|
|
23518
|
+
try {
|
|
23519
|
+
result.addHandler(new BraintrustLangChainCallbackHandler(), true);
|
|
23520
|
+
this.injectedManagers.add(result);
|
|
23521
|
+
} catch {
|
|
23522
|
+
}
|
|
23523
|
+
}
|
|
23524
|
+
};
|
|
23525
|
+
function isCallbackManager(value) {
|
|
23526
|
+
if (typeof value !== "object" || value === null) {
|
|
23527
|
+
return false;
|
|
23528
|
+
}
|
|
23529
|
+
const maybeManager = value;
|
|
23530
|
+
return typeof maybeManager.addHandler === "function";
|
|
23531
|
+
}
|
|
23532
|
+
function hasBraintrustHandler(manager) {
|
|
23533
|
+
return manager.handlers?.some((handler) => {
|
|
23534
|
+
if (typeof handler !== "object" || handler === null) {
|
|
23535
|
+
return false;
|
|
23536
|
+
}
|
|
23537
|
+
const name = Reflect.get(handler, "name");
|
|
23538
|
+
return name === BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
|
|
23539
|
+
}) ?? false;
|
|
23540
|
+
}
|
|
23541
|
+
function injectHandlerIntoArguments(args) {
|
|
23542
|
+
if (!isWritableArgumentsObject(args)) {
|
|
23543
|
+
return;
|
|
23544
|
+
}
|
|
23545
|
+
const inheritedHandlers = Reflect.get(args, "0");
|
|
23546
|
+
const handler = new BraintrustLangChainCallbackHandler();
|
|
23547
|
+
if (inheritedHandlers === void 0 || inheritedHandlers === null) {
|
|
23548
|
+
Reflect.set(args, "0", [handler]);
|
|
23549
|
+
return;
|
|
23550
|
+
}
|
|
23551
|
+
if (Array.isArray(inheritedHandlers)) {
|
|
23552
|
+
if (!inheritedHandlers.some(isBraintrustHandler)) {
|
|
23553
|
+
inheritedHandlers.push(handler);
|
|
23554
|
+
}
|
|
23555
|
+
}
|
|
23556
|
+
}
|
|
23557
|
+
function isWritableArgumentsObject(args) {
|
|
23558
|
+
return typeof args === "object" && args !== null;
|
|
23559
|
+
}
|
|
23560
|
+
function isBraintrustHandler(handler) {
|
|
23561
|
+
if (typeof handler !== "object" || handler === null) {
|
|
23562
|
+
return false;
|
|
23563
|
+
}
|
|
23564
|
+
return Reflect.get(handler, "name") === BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
|
|
23565
|
+
}
|
|
23566
|
+
|
|
23567
|
+
// src/instrumentation/braintrust-plugin.ts
|
|
23568
|
+
function getIntegrationConfig(integrations, key) {
|
|
23569
|
+
return integrations[key];
|
|
23570
|
+
}
|
|
23571
|
+
var BraintrustPlugin = class extends BasePlugin {
|
|
23572
|
+
config;
|
|
23573
|
+
openaiPlugin = null;
|
|
23574
|
+
openAICodexPlugin = null;
|
|
23575
|
+
anthropicPlugin = null;
|
|
23576
|
+
aiSDKPlugin = null;
|
|
23577
|
+
claudeAgentSDKPlugin = null;
|
|
23578
|
+
cursorSDKPlugin = null;
|
|
23579
|
+
openAIAgentsPlugin = null;
|
|
23580
|
+
googleGenAIPlugin = null;
|
|
23581
|
+
huggingFacePlugin = null;
|
|
23582
|
+
openRouterPlugin = null;
|
|
23583
|
+
openRouterAgentPlugin = null;
|
|
23584
|
+
mistralPlugin = null;
|
|
23585
|
+
googleADKPlugin = null;
|
|
23586
|
+
coherePlugin = null;
|
|
23587
|
+
groqPlugin = null;
|
|
23588
|
+
genkitPlugin = null;
|
|
23589
|
+
gitHubCopilotPlugin = null;
|
|
23590
|
+
fluePlugin = null;
|
|
23591
|
+
langChainPlugin = null;
|
|
23592
|
+
constructor(config = {}) {
|
|
23593
|
+
super();
|
|
23594
|
+
this.config = config;
|
|
23595
|
+
}
|
|
23596
|
+
onEnable() {
|
|
23597
|
+
const integrations = this.config.integrations || {};
|
|
23598
|
+
if (integrations.openai !== false) {
|
|
23599
|
+
this.openaiPlugin = new OpenAIPlugin();
|
|
23600
|
+
this.openaiPlugin.enable();
|
|
23601
|
+
}
|
|
23602
|
+
if (integrations.openaiCodexSDK !== false) {
|
|
23603
|
+
this.openAICodexPlugin = new OpenAICodexPlugin();
|
|
23604
|
+
this.openAICodexPlugin.enable();
|
|
23605
|
+
}
|
|
23606
|
+
if (integrations.anthropic !== false) {
|
|
23607
|
+
this.anthropicPlugin = new AnthropicPlugin();
|
|
23608
|
+
this.anthropicPlugin.enable();
|
|
23609
|
+
}
|
|
23610
|
+
if (integrations.aisdk !== false && integrations.vercel !== false) {
|
|
23611
|
+
this.aiSDKPlugin = new AISDKPlugin();
|
|
23612
|
+
this.aiSDKPlugin.enable();
|
|
21379
23613
|
}
|
|
21380
23614
|
if (integrations.claudeAgentSDK !== false) {
|
|
21381
23615
|
this.claudeAgentSDKPlugin = new ClaudeAgentSDKPlugin();
|
|
@@ -21385,6 +23619,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
21385
23619
|
this.cursorSDKPlugin = new CursorSDKPlugin();
|
|
21386
23620
|
this.cursorSDKPlugin.enable();
|
|
21387
23621
|
}
|
|
23622
|
+
if (integrations.openAIAgents !== false) {
|
|
23623
|
+
this.openAIAgentsPlugin = new OpenAIAgentsPlugin();
|
|
23624
|
+
this.openAIAgentsPlugin.enable();
|
|
23625
|
+
}
|
|
21388
23626
|
if (integrations.googleGenAI !== false && integrations.google !== false) {
|
|
21389
23627
|
this.googleGenAIPlugin = new GoogleGenAIPlugin();
|
|
21390
23628
|
this.googleGenAIPlugin.enable();
|
|
@@ -21425,6 +23663,14 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
21425
23663
|
this.gitHubCopilotPlugin = new GitHubCopilotPlugin();
|
|
21426
23664
|
this.gitHubCopilotPlugin.enable();
|
|
21427
23665
|
}
|
|
23666
|
+
if (getIntegrationConfig(integrations, "flue") !== false) {
|
|
23667
|
+
this.fluePlugin = new FluePlugin();
|
|
23668
|
+
this.fluePlugin.enable();
|
|
23669
|
+
}
|
|
23670
|
+
if (integrations.langchain !== false && integrations.langgraph !== false) {
|
|
23671
|
+
this.langChainPlugin = new LangChainPlugin();
|
|
23672
|
+
this.langChainPlugin.enable();
|
|
23673
|
+
}
|
|
21428
23674
|
}
|
|
21429
23675
|
onDisable() {
|
|
21430
23676
|
if (this.openaiPlugin) {
|
|
@@ -21451,6 +23697,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
21451
23697
|
this.cursorSDKPlugin.disable();
|
|
21452
23698
|
this.cursorSDKPlugin = null;
|
|
21453
23699
|
}
|
|
23700
|
+
if (this.openAIAgentsPlugin) {
|
|
23701
|
+
this.openAIAgentsPlugin.disable();
|
|
23702
|
+
this.openAIAgentsPlugin = null;
|
|
23703
|
+
}
|
|
21454
23704
|
if (this.googleGenAIPlugin) {
|
|
21455
23705
|
this.googleGenAIPlugin.disable();
|
|
21456
23706
|
this.googleGenAIPlugin = null;
|
|
@@ -21491,9 +23741,104 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
21491
23741
|
this.gitHubCopilotPlugin.disable();
|
|
21492
23742
|
this.gitHubCopilotPlugin = null;
|
|
21493
23743
|
}
|
|
23744
|
+
if (this.fluePlugin) {
|
|
23745
|
+
this.fluePlugin.disable();
|
|
23746
|
+
this.fluePlugin = null;
|
|
23747
|
+
}
|
|
23748
|
+
if (this.langChainPlugin) {
|
|
23749
|
+
this.langChainPlugin.disable();
|
|
23750
|
+
this.langChainPlugin = null;
|
|
23751
|
+
}
|
|
21494
23752
|
}
|
|
21495
23753
|
};
|
|
21496
23754
|
|
|
23755
|
+
// src/instrumentation/config.ts
|
|
23756
|
+
var envIntegrationAliases = {
|
|
23757
|
+
openai: "openai",
|
|
23758
|
+
"openai-codex": "openaiCodexSDK",
|
|
23759
|
+
"openai-codex-sdk": "openaiCodexSDK",
|
|
23760
|
+
openaicodexsdk: "openaiCodexSDK",
|
|
23761
|
+
codex: "openaiCodexSDK",
|
|
23762
|
+
"codex-sdk": "openaiCodexSDK",
|
|
23763
|
+
anthropic: "anthropic",
|
|
23764
|
+
aisdk: "aisdk",
|
|
23765
|
+
"ai-sdk": "aisdk",
|
|
23766
|
+
"vercel-ai": "aisdk",
|
|
23767
|
+
vercel: "vercel",
|
|
23768
|
+
claudeagentsdk: "claudeAgentSDK",
|
|
23769
|
+
"claude-agent-sdk": "claudeAgentSDK",
|
|
23770
|
+
cursor: "cursor",
|
|
23771
|
+
"cursor-sdk": "cursorSDK",
|
|
23772
|
+
cursorsdk: "cursorSDK",
|
|
23773
|
+
flue: "flue",
|
|
23774
|
+
"flue-runtime": "flue",
|
|
23775
|
+
"openai-agents": "openAIAgents",
|
|
23776
|
+
openaiagents: "openAIAgents",
|
|
23777
|
+
"openai-agents-core": "openAIAgents",
|
|
23778
|
+
openaiagentscore: "openAIAgents",
|
|
23779
|
+
google: "google",
|
|
23780
|
+
"google-genai": "googleGenAI",
|
|
23781
|
+
googlegenai: "googleGenAI",
|
|
23782
|
+
huggingface: "huggingface",
|
|
23783
|
+
openrouter: "openrouter",
|
|
23784
|
+
openrouteragent: "openrouterAgent",
|
|
23785
|
+
"openrouter-agent": "openrouterAgent",
|
|
23786
|
+
mistral: "mistral",
|
|
23787
|
+
googleadk: "googleADK",
|
|
23788
|
+
"google-adk": "googleADK",
|
|
23789
|
+
cohere: "cohere",
|
|
23790
|
+
groq: "groq",
|
|
23791
|
+
"groq-sdk": "groq",
|
|
23792
|
+
genkit: "genkit",
|
|
23793
|
+
"firebase-genkit": "genkit",
|
|
23794
|
+
githubcopilot: "gitHubCopilot",
|
|
23795
|
+
"github-copilot": "gitHubCopilot",
|
|
23796
|
+
"copilot-sdk": "gitHubCopilot",
|
|
23797
|
+
langchain: "langchain",
|
|
23798
|
+
"langchain-js": "langchain",
|
|
23799
|
+
"@langchain": "langchain",
|
|
23800
|
+
langgraph: "langgraph"
|
|
23801
|
+
};
|
|
23802
|
+
function getDefaultInstrumentationIntegrations() {
|
|
23803
|
+
return {
|
|
23804
|
+
openai: true,
|
|
23805
|
+
openaiCodexSDK: true,
|
|
23806
|
+
anthropic: true,
|
|
23807
|
+
vercel: true,
|
|
23808
|
+
aisdk: true,
|
|
23809
|
+
google: true,
|
|
23810
|
+
googleGenAI: true,
|
|
23811
|
+
googleADK: true,
|
|
23812
|
+
huggingface: true,
|
|
23813
|
+
claudeAgentSDK: true,
|
|
23814
|
+
cursor: true,
|
|
23815
|
+
cursorSDK: true,
|
|
23816
|
+
flue: true,
|
|
23817
|
+
openAIAgents: true,
|
|
23818
|
+
openrouter: true,
|
|
23819
|
+
openrouterAgent: true,
|
|
23820
|
+
mistral: true,
|
|
23821
|
+
cohere: true,
|
|
23822
|
+
groq: true,
|
|
23823
|
+
genkit: true,
|
|
23824
|
+
gitHubCopilot: true,
|
|
23825
|
+
langchain: true,
|
|
23826
|
+
langgraph: true
|
|
23827
|
+
};
|
|
23828
|
+
}
|
|
23829
|
+
function readDisabledInstrumentationEnvConfig(disabledList) {
|
|
23830
|
+
const integrations = {};
|
|
23831
|
+
if (disabledList) {
|
|
23832
|
+
for (const value of disabledList.split(",")) {
|
|
23833
|
+
const sdk = value.trim().toLowerCase();
|
|
23834
|
+
if (sdk.length > 0) {
|
|
23835
|
+
integrations[envIntegrationAliases[sdk] ?? sdk] = false;
|
|
23836
|
+
}
|
|
23837
|
+
}
|
|
23838
|
+
}
|
|
23839
|
+
return { integrations };
|
|
23840
|
+
}
|
|
23841
|
+
|
|
21497
23842
|
// src/instrumentation/registry.ts
|
|
21498
23843
|
var REGISTRY_STATE_KEY = /* @__PURE__ */ Symbol.for("braintrust.registry");
|
|
21499
23844
|
function getSharedState() {
|
|
@@ -21572,50 +23917,16 @@ var PluginRegistry = class {
|
|
|
21572
23917
|
* Get default configuration (all integrations enabled).
|
|
21573
23918
|
*/
|
|
21574
23919
|
getDefaultConfig() {
|
|
21575
|
-
return
|
|
21576
|
-
openai: true,
|
|
21577
|
-
openaiCodexSDK: true,
|
|
21578
|
-
anthropic: true,
|
|
21579
|
-
vercel: true,
|
|
21580
|
-
aisdk: true,
|
|
21581
|
-
google: true,
|
|
21582
|
-
googleGenAI: true,
|
|
21583
|
-
googleADK: true,
|
|
21584
|
-
huggingface: true,
|
|
21585
|
-
claudeAgentSDK: true,
|
|
21586
|
-
cursor: true,
|
|
21587
|
-
cursorSDK: true,
|
|
21588
|
-
openrouter: true,
|
|
21589
|
-
openrouterAgent: true,
|
|
21590
|
-
mistral: true,
|
|
21591
|
-
cohere: true,
|
|
21592
|
-
groq: true,
|
|
21593
|
-
genkit: true,
|
|
21594
|
-
gitHubCopilot: true
|
|
21595
|
-
};
|
|
23920
|
+
return getDefaultInstrumentationIntegrations();
|
|
21596
23921
|
}
|
|
21597
23922
|
/**
|
|
21598
23923
|
* Read configuration from environment variables.
|
|
21599
23924
|
* Supports: BRAINTRUST_DISABLE_INSTRUMENTATION=openai,anthropic,...
|
|
21600
23925
|
*/
|
|
21601
23926
|
readEnvConfig() {
|
|
21602
|
-
|
|
21603
|
-
|
|
21604
|
-
|
|
21605
|
-
const disabled = disabledList.split(",").map((s) => s.trim().toLowerCase()).filter((s) => s.length > 0);
|
|
21606
|
-
for (const sdk of disabled) {
|
|
21607
|
-
if (sdk === "cursor-sdk") {
|
|
21608
|
-
integrations.cursorSDK = false;
|
|
21609
|
-
} else if (sdk === "githubcopilot" || sdk === "github-copilot" || sdk === "copilot-sdk") {
|
|
21610
|
-
integrations.gitHubCopilot = false;
|
|
21611
|
-
} else if (sdk === "openai-codex-sdk") {
|
|
21612
|
-
integrations.openaiCodexSDK = false;
|
|
21613
|
-
} else {
|
|
21614
|
-
integrations[sdk] = false;
|
|
21615
|
-
}
|
|
21616
|
-
}
|
|
21617
|
-
}
|
|
21618
|
-
return { integrations };
|
|
23927
|
+
return readDisabledInstrumentationEnvConfig(
|
|
23928
|
+
isomorph_default.getEnv("BRAINTRUST_DISABLE_INSTRUMENTATION")
|
|
23929
|
+
);
|
|
21619
23930
|
}
|
|
21620
23931
|
};
|
|
21621
23932
|
var registry = new PluginRegistry();
|
|
@@ -21625,6 +23936,7 @@ function configureInstrumentation(config) {
|
|
|
21625
23936
|
export {
|
|
21626
23937
|
BasePlugin,
|
|
21627
23938
|
BraintrustPlugin,
|
|
23939
|
+
OpenAIAgentsTraceProcessor,
|
|
21628
23940
|
configureInstrumentation,
|
|
21629
23941
|
createChannelName,
|
|
21630
23942
|
isValidChannelName,
|