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
package/dist/browser.js
CHANGED
|
@@ -33,8 +33,10 @@ __export(browser_exports, {
|
|
|
33
33
|
Attachment: () => Attachment,
|
|
34
34
|
AttachmentReference: () => AttachmentReference,
|
|
35
35
|
BRAINTRUST_CURRENT_SPAN_STORE: () => BRAINTRUST_CURRENT_SPAN_STORE,
|
|
36
|
+
BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME: () => BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME,
|
|
36
37
|
BaseAttachment: () => BaseAttachment,
|
|
37
38
|
BaseExperiment: () => BaseExperiment,
|
|
39
|
+
BraintrustLangChainCallbackHandler: () => BraintrustLangChainCallbackHandler,
|
|
38
40
|
BraintrustMiddleware: () => BraintrustMiddleware,
|
|
39
41
|
BraintrustState: () => BraintrustState,
|
|
40
42
|
BraintrustStream: () => BraintrustStream,
|
|
@@ -45,6 +47,7 @@ __export(browser_exports, {
|
|
|
45
47
|
DEFAULT_FETCH_BATCH_SIZE: () => DEFAULT_FETCH_BATCH_SIZE,
|
|
46
48
|
DEFAULT_MAX_REQUEST_SIZE: () => DEFAULT_MAX_REQUEST_SIZE,
|
|
47
49
|
Dataset: () => Dataset2,
|
|
50
|
+
DatasetPipeline: () => DatasetPipeline,
|
|
48
51
|
ERR_PERMALINK: () => ERR_PERMALINK,
|
|
49
52
|
Eval: () => Eval,
|
|
50
53
|
EvalResultWithSummary: () => EvalResultWithSummary,
|
|
@@ -161,6 +164,8 @@ __export(browser_exports, {
|
|
|
161
164
|
wrapCohere: () => wrapCohere,
|
|
162
165
|
wrapCopilotClient: () => wrapCopilotClient,
|
|
163
166
|
wrapCursorSDK: () => wrapCursorSDK,
|
|
167
|
+
wrapFlueContext: () => wrapFlueContext,
|
|
168
|
+
wrapFlueSession: () => wrapFlueSession,
|
|
164
169
|
wrapGenkit: () => wrapGenkit,
|
|
165
170
|
wrapGoogleADK: () => wrapGoogleADK,
|
|
166
171
|
wrapGoogleGenAI: () => wrapGoogleGenAI,
|
|
@@ -266,6 +271,7 @@ var iso = {
|
|
|
266
271
|
getRepoInfo: async (_settings) => void 0,
|
|
267
272
|
getPastNAncestors: async () => [],
|
|
268
273
|
getEnv: (_name) => void 0,
|
|
274
|
+
getBraintrustApiKey: async () => void 0,
|
|
269
275
|
getCallerLocation: () => void 0,
|
|
270
276
|
newAsyncLocalStorage: () => new DefaultAsyncLocalStorage(),
|
|
271
277
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -1098,6 +1104,11 @@ function isPromiseLike(value) {
|
|
|
1098
1104
|
|
|
1099
1105
|
// util/object_util.ts
|
|
1100
1106
|
var SET_UNION_FIELDS = /* @__PURE__ */ new Set(["tags"]);
|
|
1107
|
+
var FORBIDDEN_MERGE_KEYS = /* @__PURE__ */ new Set([
|
|
1108
|
+
"__proto__",
|
|
1109
|
+
"constructor",
|
|
1110
|
+
"prototype"
|
|
1111
|
+
]);
|
|
1101
1112
|
function mergeDictsWithPaths({
|
|
1102
1113
|
mergeInto,
|
|
1103
1114
|
mergeFrom,
|
|
@@ -1120,6 +1131,7 @@ function mergeDictsWithPathsHelper({
|
|
|
1120
1131
|
mergePaths
|
|
1121
1132
|
}) {
|
|
1122
1133
|
Object.entries(mergeFrom).forEach(([k, mergeFromV]) => {
|
|
1134
|
+
if (FORBIDDEN_MERGE_KEYS.has(k)) return;
|
|
1123
1135
|
const fullPath = path.concat([k]);
|
|
1124
1136
|
const fullPathSerialized = JSON.stringify(fullPath);
|
|
1125
1137
|
const mergeIntoV = recordFind(mergeInto, k);
|
|
@@ -5191,6 +5203,13 @@ var HTTPConnection = class _HTTPConnection {
|
|
|
5191
5203
|
debugLogger.debug(
|
|
5192
5204
|
`Retrying API request ${object_type} ${JSON.stringify(args)} ${e.status} ${e.text}`
|
|
5193
5205
|
);
|
|
5206
|
+
const sleepTimeS = HTTP_RETRY_BASE_SLEEP_TIME_S * 2 ** i;
|
|
5207
|
+
debugLogger.info(
|
|
5208
|
+
`Sleeping for ${sleepTimeS}s before retrying API request`
|
|
5209
|
+
);
|
|
5210
|
+
await new Promise(
|
|
5211
|
+
(resolve) => setTimeout(resolve, sleepTimeS * 1e3)
|
|
5212
|
+
);
|
|
5194
5213
|
continue;
|
|
5195
5214
|
}
|
|
5196
5215
|
throw e;
|
|
@@ -5592,6 +5611,19 @@ var JSONAttachment = class extends Attachment {
|
|
|
5592
5611
|
*/
|
|
5593
5612
|
constructor(data, options) {
|
|
5594
5613
|
const { filename = "data.json", pretty = false, state } = options ?? {};
|
|
5614
|
+
const deferredJsonAttachment = globalThis.__BT_DATASET_PIPELINE_DEFER_JSON_ATTACHMENT__;
|
|
5615
|
+
if (deferredJsonAttachment) {
|
|
5616
|
+
super({
|
|
5617
|
+
data: new Blob([]),
|
|
5618
|
+
filename,
|
|
5619
|
+
contentType: "application/json",
|
|
5620
|
+
state
|
|
5621
|
+
});
|
|
5622
|
+
return deferredJsonAttachment(data, {
|
|
5623
|
+
filename,
|
|
5624
|
+
pretty
|
|
5625
|
+
});
|
|
5626
|
+
}
|
|
5595
5627
|
const jsonString = pretty ? JSON.stringify(data, null, 2) : JSON.stringify(data);
|
|
5596
5628
|
const blob = new Blob([jsonString], { type: "application/json" });
|
|
5597
5629
|
super({
|
|
@@ -5840,20 +5872,7 @@ function startSpanParentArgs(args) {
|
|
|
5840
5872
|
`Mismatch between expected span parent object type ${args.parentObjectType} and provided type ${parentComponents.data.object_type}`
|
|
5841
5873
|
);
|
|
5842
5874
|
}
|
|
5843
|
-
|
|
5844
|
-
args.state,
|
|
5845
|
-
parentComponents
|
|
5846
|
-
);
|
|
5847
|
-
const computeParentObjectId = async () => {
|
|
5848
|
-
const parentComponentsObjectId = await parentComponentsObjectIdLambda();
|
|
5849
|
-
if (await args.parentObjectId.get() !== parentComponentsObjectId) {
|
|
5850
|
-
throw new Error(
|
|
5851
|
-
`Mismatch between expected span parent object id ${await args.parentObjectId.get()} and provided id ${parentComponentsObjectId}`
|
|
5852
|
-
);
|
|
5853
|
-
}
|
|
5854
|
-
return await args.parentObjectId.get();
|
|
5855
|
-
};
|
|
5856
|
-
argParentObjectId = new LazyValue(computeParentObjectId);
|
|
5875
|
+
argParentObjectId = args.parentObjectId;
|
|
5857
5876
|
if (parentComponents.data.row_id) {
|
|
5858
5877
|
argParentSpanIds = {
|
|
5859
5878
|
spanId: parentComponents.data.span_id,
|
|
@@ -6239,6 +6258,7 @@ var TestBackgroundLogger = class {
|
|
|
6239
6258
|
}
|
|
6240
6259
|
};
|
|
6241
6260
|
var BACKGROUND_LOGGER_BASE_SLEEP_TIME_S = 1;
|
|
6261
|
+
var HTTP_RETRY_BASE_SLEEP_TIME_S = 1;
|
|
6242
6262
|
var HTTPBackgroundLogger = class _HTTPBackgroundLogger {
|
|
6243
6263
|
apiConn;
|
|
6244
6264
|
queue;
|
|
@@ -6869,17 +6889,10 @@ function init(projectOrOptions, optionalOptions) {
|
|
|
6869
6889
|
if (repoInfo) {
|
|
6870
6890
|
return repoInfo;
|
|
6871
6891
|
}
|
|
6872
|
-
|
|
6873
|
-
|
|
6874
|
-
|
|
6875
|
-
|
|
6876
|
-
};
|
|
6877
|
-
if (gitMetadataSettings) {
|
|
6878
|
-
mergedGitMetadataSettings = mergeGitMetadataSettings(
|
|
6879
|
-
mergedGitMetadataSettings,
|
|
6880
|
-
gitMetadataSettings
|
|
6881
|
-
);
|
|
6882
|
-
}
|
|
6892
|
+
const mergedGitMetadataSettings = state.gitMetadataSettings == null ? gitMetadataSettings ?? { collect: "none" } : mergeGitMetadataSettings(
|
|
6893
|
+
state.gitMetadataSettings,
|
|
6894
|
+
gitMetadataSettings ?? { collect: "all" }
|
|
6895
|
+
);
|
|
6883
6896
|
return await isomorph_default.getRepoInfo(mergedGitMetadataSettings);
|
|
6884
6897
|
})();
|
|
6885
6898
|
if (repoInfoArg) {
|
|
@@ -7603,10 +7616,11 @@ async function login(options = {}) {
|
|
|
7603
7616
|
async function loginToState(options = {}) {
|
|
7604
7617
|
const {
|
|
7605
7618
|
appUrl = isomorph_default.getEnv("BRAINTRUST_APP_URL") || "https://www.braintrust.dev",
|
|
7606
|
-
apiKey
|
|
7619
|
+
apiKey: apiKeyArg,
|
|
7607
7620
|
orgName = isomorph_default.getEnv("BRAINTRUST_ORG_NAME"),
|
|
7608
7621
|
fetch: fetch2 = globalThis.fetch
|
|
7609
7622
|
} = options || {};
|
|
7623
|
+
const apiKey = apiKeyArg !== void 0 ? apiKeyArg : await isomorph_default.getBraintrustApiKey();
|
|
7610
7624
|
const appPublicUrl = isomorph_default.getEnv("BRAINTRUST_APP_PUBLIC_URL") || appUrl;
|
|
7611
7625
|
const state = new BraintrustState(options);
|
|
7612
7626
|
state.resetLoginInfo();
|
|
@@ -8847,9 +8861,15 @@ var SpanImpl = class _SpanImpl {
|
|
|
8847
8861
|
const cachedSpan = {
|
|
8848
8862
|
input: partialRecord.input,
|
|
8849
8863
|
output: partialRecord.output,
|
|
8864
|
+
expected: partialRecord.expected,
|
|
8865
|
+
error: partialRecord.error,
|
|
8866
|
+
scores: partialRecord.scores,
|
|
8867
|
+
metrics: partialRecord.metrics,
|
|
8850
8868
|
metadata: partialRecord.metadata,
|
|
8869
|
+
tags: partialRecord.tags,
|
|
8851
8870
|
span_id: this._spanId,
|
|
8852
8871
|
span_parents: this._spanParents,
|
|
8872
|
+
is_root: this._spanId === this._rootSpanId,
|
|
8853
8873
|
span_attributes: partialRecord.span_attributes
|
|
8854
8874
|
};
|
|
8855
8875
|
this._state.spanCache.queueWrite(
|
|
@@ -9185,6 +9205,7 @@ var Dataset2 = class extends ObjectFetcher {
|
|
|
9185
9205
|
metadata,
|
|
9186
9206
|
tags,
|
|
9187
9207
|
output,
|
|
9208
|
+
origin,
|
|
9188
9209
|
isMerge
|
|
9189
9210
|
}) {
|
|
9190
9211
|
return new LazyValue(async () => {
|
|
@@ -9199,6 +9220,7 @@ var Dataset2 = class extends ObjectFetcher {
|
|
|
9199
9220
|
created: !isMerge ? (/* @__PURE__ */ new Date()).toISOString() : void 0,
|
|
9200
9221
|
//if we're merging/updating an event we will not add this ts
|
|
9201
9222
|
metadata,
|
|
9223
|
+
origin,
|
|
9202
9224
|
...!!isMerge ? {
|
|
9203
9225
|
[IS_MERGE_FIELD]: true
|
|
9204
9226
|
} : {}
|
|
@@ -9218,6 +9240,7 @@ var Dataset2 = class extends ObjectFetcher {
|
|
|
9218
9240
|
* about anything else that's relevant, that you can use to help find and analyze examples later. For example, you could log the
|
|
9219
9241
|
* `prompt`, example's `id`, or anything else that would be useful to slice/dice later. The values in `metadata` can be any
|
|
9220
9242
|
* JSON-serializable type, but its keys must be strings.
|
|
9243
|
+
* @param event.origin (Optional) a reference to the source object this dataset record was derived from.
|
|
9221
9244
|
* @param event.id (Optional) a unique identifier for the event. If you don't provide one, Braintrust will generate one for you.
|
|
9222
9245
|
* @param event.output: (Deprecated) The output of your application. Use `expected` instead.
|
|
9223
9246
|
* @returns The `id` of the logged record.
|
|
@@ -9228,7 +9251,8 @@ var Dataset2 = class extends ObjectFetcher {
|
|
|
9228
9251
|
metadata,
|
|
9229
9252
|
tags,
|
|
9230
9253
|
id,
|
|
9231
|
-
output
|
|
9254
|
+
output,
|
|
9255
|
+
origin
|
|
9232
9256
|
}) {
|
|
9233
9257
|
this.validateEvent({ metadata, expected, output, tags });
|
|
9234
9258
|
const rowId = id || (0, import_uuid2.v4)();
|
|
@@ -9240,6 +9264,7 @@ var Dataset2 = class extends ObjectFetcher {
|
|
|
9240
9264
|
metadata,
|
|
9241
9265
|
tags,
|
|
9242
9266
|
output,
|
|
9267
|
+
origin,
|
|
9243
9268
|
isMerge: false
|
|
9244
9269
|
})
|
|
9245
9270
|
);
|
|
@@ -13575,11 +13600,11 @@ function resolveDenyOutputPaths(event, defaultDenyOutputPaths) {
|
|
|
13575
13600
|
if (Array.isArray(event?.denyOutputPaths)) {
|
|
13576
13601
|
return event.denyOutputPaths;
|
|
13577
13602
|
}
|
|
13578
|
-
const
|
|
13579
|
-
if (!
|
|
13603
|
+
const firstArgument2 = event?.arguments && event.arguments.length > 0 ? event.arguments[0] : void 0;
|
|
13604
|
+
if (!firstArgument2 || typeof firstArgument2 !== "object") {
|
|
13580
13605
|
return defaultDenyOutputPaths;
|
|
13581
13606
|
}
|
|
13582
|
-
const runtimeDenyOutputPaths =
|
|
13607
|
+
const runtimeDenyOutputPaths = firstArgument2[RUNTIME_DENY_OUTPUT_PATHS];
|
|
13583
13608
|
if (Array.isArray(runtimeDenyOutputPaths) && runtimeDenyOutputPaths.every((path) => typeof path === "string")) {
|
|
13584
13609
|
return runtimeDenyOutputPaths;
|
|
13585
13610
|
}
|
|
@@ -17238,6 +17263,467 @@ function cleanMetrics2(metrics) {
|
|
|
17238
17263
|
return cleaned;
|
|
17239
17264
|
}
|
|
17240
17265
|
|
|
17266
|
+
// src/instrumentation/plugins/openai-agents-channels.ts
|
|
17267
|
+
var openAIAgentsCoreChannels = defineChannels("@openai/agents-core", {
|
|
17268
|
+
onTraceStart: channel({
|
|
17269
|
+
channelName: "tracing.processor.onTraceStart",
|
|
17270
|
+
kind: "async"
|
|
17271
|
+
}),
|
|
17272
|
+
onTraceEnd: channel({
|
|
17273
|
+
channelName: "tracing.processor.onTraceEnd",
|
|
17274
|
+
kind: "async"
|
|
17275
|
+
}),
|
|
17276
|
+
onSpanStart: channel({
|
|
17277
|
+
channelName: "tracing.processor.onSpanStart",
|
|
17278
|
+
kind: "async"
|
|
17279
|
+
}),
|
|
17280
|
+
onSpanEnd: channel({
|
|
17281
|
+
channelName: "tracing.processor.onSpanEnd",
|
|
17282
|
+
kind: "async"
|
|
17283
|
+
})
|
|
17284
|
+
});
|
|
17285
|
+
|
|
17286
|
+
// src/instrumentation/plugins/openai-agents-trace-processor.ts
|
|
17287
|
+
function isSpanData(spanData, type) {
|
|
17288
|
+
return spanData.type === type;
|
|
17289
|
+
}
|
|
17290
|
+
function spanTypeFromAgents(span) {
|
|
17291
|
+
const spanType = span.spanData.type;
|
|
17292
|
+
if (spanType === "function" || spanType === "guardrail" || spanType === "mcp_tools") {
|
|
17293
|
+
return "tool" /* TOOL */;
|
|
17294
|
+
}
|
|
17295
|
+
if (spanType === "generation" || spanType === "response" || spanType === "transcription" || spanType === "speech") {
|
|
17296
|
+
return "llm" /* LLM */;
|
|
17297
|
+
}
|
|
17298
|
+
return "task" /* TASK */;
|
|
17299
|
+
}
|
|
17300
|
+
function spanNameFromAgents(span) {
|
|
17301
|
+
const spanData = span.spanData;
|
|
17302
|
+
if ("name" in spanData && spanData.name) {
|
|
17303
|
+
return spanData.name;
|
|
17304
|
+
}
|
|
17305
|
+
switch (spanData.type) {
|
|
17306
|
+
case "generation":
|
|
17307
|
+
return "Generation";
|
|
17308
|
+
case "response":
|
|
17309
|
+
return "Response";
|
|
17310
|
+
case "handoff":
|
|
17311
|
+
return "Handoff";
|
|
17312
|
+
case "mcp_tools":
|
|
17313
|
+
return isSpanData(spanData, "mcp_tools") && spanData.server ? `List Tools (${spanData.server})` : "MCP List Tools";
|
|
17314
|
+
case "transcription":
|
|
17315
|
+
return "Transcription";
|
|
17316
|
+
case "speech":
|
|
17317
|
+
return "Speech";
|
|
17318
|
+
case "speech_group":
|
|
17319
|
+
return "Speech Group";
|
|
17320
|
+
default:
|
|
17321
|
+
return "Unknown";
|
|
17322
|
+
}
|
|
17323
|
+
}
|
|
17324
|
+
function getTimeElapsed(end, start) {
|
|
17325
|
+
if (!start || !end) {
|
|
17326
|
+
return void 0;
|
|
17327
|
+
}
|
|
17328
|
+
const startTime = new Date(start).getTime();
|
|
17329
|
+
const endTime = new Date(end).getTime();
|
|
17330
|
+
if (Number.isNaN(startTime) || Number.isNaN(endTime)) {
|
|
17331
|
+
return void 0;
|
|
17332
|
+
}
|
|
17333
|
+
return (endTime - startTime) / 1e3;
|
|
17334
|
+
}
|
|
17335
|
+
function getNumberProperty2(obj, key) {
|
|
17336
|
+
if (!isObject(obj) || !(key in obj)) {
|
|
17337
|
+
return void 0;
|
|
17338
|
+
}
|
|
17339
|
+
const value = obj[key];
|
|
17340
|
+
return typeof value === "number" ? value : void 0;
|
|
17341
|
+
}
|
|
17342
|
+
function parseUsageMetrics(usage) {
|
|
17343
|
+
const metrics = {};
|
|
17344
|
+
if (!isObject(usage)) {
|
|
17345
|
+
return metrics;
|
|
17346
|
+
}
|
|
17347
|
+
const promptTokens = getNumberProperty2(usage, "prompt_tokens") ?? getNumberProperty2(usage, "input_tokens") ?? getNumberProperty2(usage, "promptTokens") ?? getNumberProperty2(usage, "inputTokens");
|
|
17348
|
+
const completionTokens = getNumberProperty2(usage, "completion_tokens") ?? getNumberProperty2(usage, "output_tokens") ?? getNumberProperty2(usage, "completionTokens") ?? getNumberProperty2(usage, "outputTokens");
|
|
17349
|
+
const totalTokens = getNumberProperty2(usage, "total_tokens") ?? getNumberProperty2(usage, "totalTokens");
|
|
17350
|
+
if (promptTokens !== void 0) {
|
|
17351
|
+
metrics.prompt_tokens = promptTokens;
|
|
17352
|
+
}
|
|
17353
|
+
if (completionTokens !== void 0) {
|
|
17354
|
+
metrics.completion_tokens = completionTokens;
|
|
17355
|
+
}
|
|
17356
|
+
if (totalTokens !== void 0) {
|
|
17357
|
+
metrics.tokens = totalTokens;
|
|
17358
|
+
} else if (promptTokens !== void 0 && completionTokens !== void 0) {
|
|
17359
|
+
metrics.tokens = promptTokens + completionTokens;
|
|
17360
|
+
}
|
|
17361
|
+
const inputDetails = usage.input_tokens_details;
|
|
17362
|
+
const cachedTokens = getNumberProperty2(inputDetails, "cached_tokens");
|
|
17363
|
+
const cacheWriteTokens = getNumberProperty2(
|
|
17364
|
+
inputDetails,
|
|
17365
|
+
"cache_write_tokens"
|
|
17366
|
+
);
|
|
17367
|
+
if (cachedTokens !== void 0) {
|
|
17368
|
+
metrics.prompt_cached_tokens = cachedTokens;
|
|
17369
|
+
}
|
|
17370
|
+
if (cacheWriteTokens !== void 0) {
|
|
17371
|
+
metrics.prompt_cache_creation_tokens = cacheWriteTokens;
|
|
17372
|
+
}
|
|
17373
|
+
return metrics;
|
|
17374
|
+
}
|
|
17375
|
+
var OpenAIAgentsTraceProcessor = class _OpenAIAgentsTraceProcessor {
|
|
17376
|
+
static DEFAULT_MAX_TRACES = 1e4;
|
|
17377
|
+
logger;
|
|
17378
|
+
maxTraces;
|
|
17379
|
+
traceSpans = /* @__PURE__ */ new Map();
|
|
17380
|
+
traceOrder = [];
|
|
17381
|
+
_traceSpans = this.traceSpans;
|
|
17382
|
+
constructor(options = {}) {
|
|
17383
|
+
this.logger = options.logger;
|
|
17384
|
+
this.maxTraces = options.maxTraces ?? _OpenAIAgentsTraceProcessor.DEFAULT_MAX_TRACES;
|
|
17385
|
+
}
|
|
17386
|
+
evictOldestTrace() {
|
|
17387
|
+
const oldestTraceId = this.traceOrder.shift();
|
|
17388
|
+
if (oldestTraceId) {
|
|
17389
|
+
this.traceSpans.delete(oldestTraceId);
|
|
17390
|
+
}
|
|
17391
|
+
}
|
|
17392
|
+
onTraceStart(trace) {
|
|
17393
|
+
if (!trace?.traceId) {
|
|
17394
|
+
return Promise.resolve();
|
|
17395
|
+
}
|
|
17396
|
+
if (this.traceOrder.length >= this.maxTraces) {
|
|
17397
|
+
this.evictOldestTrace();
|
|
17398
|
+
}
|
|
17399
|
+
const current = currentSpan();
|
|
17400
|
+
const span = current && current !== NOOP_SPAN ? current.startSpan({
|
|
17401
|
+
name: trace.name,
|
|
17402
|
+
type: "task" /* TASK */
|
|
17403
|
+
}) : this.logger ? this.logger.startSpan({
|
|
17404
|
+
name: trace.name,
|
|
17405
|
+
type: "task" /* TASK */
|
|
17406
|
+
}) : startSpan({
|
|
17407
|
+
name: trace.name,
|
|
17408
|
+
type: "task" /* TASK */
|
|
17409
|
+
});
|
|
17410
|
+
span.log({
|
|
17411
|
+
input: "Agent workflow started",
|
|
17412
|
+
metadata: {
|
|
17413
|
+
group_id: trace.groupId,
|
|
17414
|
+
...trace.metadata || {}
|
|
17415
|
+
}
|
|
17416
|
+
});
|
|
17417
|
+
this.traceSpans.set(trace.traceId, {
|
|
17418
|
+
rootSpan: span,
|
|
17419
|
+
childSpans: /* @__PURE__ */ new Map(),
|
|
17420
|
+
metadata: {
|
|
17421
|
+
firstInput: null,
|
|
17422
|
+
lastOutput: null
|
|
17423
|
+
}
|
|
17424
|
+
});
|
|
17425
|
+
this.traceOrder.push(trace.traceId);
|
|
17426
|
+
return Promise.resolve();
|
|
17427
|
+
}
|
|
17428
|
+
async onTraceEnd(trace) {
|
|
17429
|
+
const traceData = this.traceSpans.get(trace?.traceId);
|
|
17430
|
+
if (!traceData) {
|
|
17431
|
+
return;
|
|
17432
|
+
}
|
|
17433
|
+
try {
|
|
17434
|
+
traceData.rootSpan.log({
|
|
17435
|
+
input: traceData.metadata.firstInput,
|
|
17436
|
+
output: traceData.metadata.lastOutput
|
|
17437
|
+
});
|
|
17438
|
+
traceData.rootSpan.end();
|
|
17439
|
+
await traceData.rootSpan.flush();
|
|
17440
|
+
} finally {
|
|
17441
|
+
this.traceSpans.delete(trace.traceId);
|
|
17442
|
+
const orderIndex = this.traceOrder.indexOf(trace.traceId);
|
|
17443
|
+
if (orderIndex > -1) {
|
|
17444
|
+
this.traceOrder.splice(orderIndex, 1);
|
|
17445
|
+
}
|
|
17446
|
+
}
|
|
17447
|
+
}
|
|
17448
|
+
onSpanStart(span) {
|
|
17449
|
+
if (!span?.spanId || !span.traceId) {
|
|
17450
|
+
return Promise.resolve();
|
|
17451
|
+
}
|
|
17452
|
+
const traceData = this.traceSpans.get(span.traceId);
|
|
17453
|
+
if (!traceData) {
|
|
17454
|
+
return Promise.resolve();
|
|
17455
|
+
}
|
|
17456
|
+
const parentSpan = span.parentId ? traceData.childSpans.get(span.parentId) : traceData.rootSpan;
|
|
17457
|
+
if (!parentSpan) {
|
|
17458
|
+
return Promise.resolve();
|
|
17459
|
+
}
|
|
17460
|
+
const childSpan = parentSpan.startSpan({
|
|
17461
|
+
name: spanNameFromAgents(span),
|
|
17462
|
+
type: spanTypeFromAgents(span)
|
|
17463
|
+
});
|
|
17464
|
+
traceData.childSpans.set(span.spanId, childSpan);
|
|
17465
|
+
return Promise.resolve();
|
|
17466
|
+
}
|
|
17467
|
+
onSpanEnd(span) {
|
|
17468
|
+
if (!span?.spanId || !span.traceId) {
|
|
17469
|
+
return Promise.resolve();
|
|
17470
|
+
}
|
|
17471
|
+
const traceData = this.traceSpans.get(span.traceId);
|
|
17472
|
+
if (!traceData) {
|
|
17473
|
+
return Promise.resolve();
|
|
17474
|
+
}
|
|
17475
|
+
const braintrustSpan = traceData.childSpans.get(span.spanId);
|
|
17476
|
+
if (!braintrustSpan) {
|
|
17477
|
+
return Promise.resolve();
|
|
17478
|
+
}
|
|
17479
|
+
const logData = this.extractLogData(span);
|
|
17480
|
+
braintrustSpan.log({
|
|
17481
|
+
error: span.error,
|
|
17482
|
+
...logData
|
|
17483
|
+
});
|
|
17484
|
+
braintrustSpan.end();
|
|
17485
|
+
traceData.childSpans.delete(span.spanId);
|
|
17486
|
+
const input = logData.input;
|
|
17487
|
+
const output = logData.output;
|
|
17488
|
+
if (traceData.metadata.firstInput === null && input != null) {
|
|
17489
|
+
traceData.metadata.firstInput = input;
|
|
17490
|
+
}
|
|
17491
|
+
if (output != null) {
|
|
17492
|
+
traceData.metadata.lastOutput = output;
|
|
17493
|
+
}
|
|
17494
|
+
return Promise.resolve();
|
|
17495
|
+
}
|
|
17496
|
+
async shutdown() {
|
|
17497
|
+
if (this.logger && typeof this.logger.flush === "function") {
|
|
17498
|
+
await this.logger.flush();
|
|
17499
|
+
}
|
|
17500
|
+
}
|
|
17501
|
+
async forceFlush() {
|
|
17502
|
+
if (this.logger && typeof this.logger.flush === "function") {
|
|
17503
|
+
await this.logger.flush();
|
|
17504
|
+
}
|
|
17505
|
+
}
|
|
17506
|
+
extractLogData(span) {
|
|
17507
|
+
const spanData = span.spanData;
|
|
17508
|
+
switch (spanData.type) {
|
|
17509
|
+
case "agent":
|
|
17510
|
+
return this.extractAgentLogData(spanData);
|
|
17511
|
+
case "response":
|
|
17512
|
+
return this.extractResponseLogData(spanData, span);
|
|
17513
|
+
case "function":
|
|
17514
|
+
return this.extractFunctionLogData(spanData);
|
|
17515
|
+
case "handoff":
|
|
17516
|
+
return this.extractHandoffLogData(spanData);
|
|
17517
|
+
case "guardrail":
|
|
17518
|
+
return this.extractGuardrailLogData(spanData);
|
|
17519
|
+
case "generation":
|
|
17520
|
+
return this.extractGenerationLogData(spanData, span);
|
|
17521
|
+
case "custom":
|
|
17522
|
+
return this.extractCustomLogData(spanData);
|
|
17523
|
+
case "mcp_tools":
|
|
17524
|
+
return this.extractMCPListToolsLogData(spanData);
|
|
17525
|
+
case "transcription":
|
|
17526
|
+
return this.extractTranscriptionLogData(spanData);
|
|
17527
|
+
case "speech":
|
|
17528
|
+
return this.extractSpeechLogData(spanData);
|
|
17529
|
+
case "speech_group":
|
|
17530
|
+
return this.extractSpeechGroupLogData(spanData);
|
|
17531
|
+
default:
|
|
17532
|
+
return {};
|
|
17533
|
+
}
|
|
17534
|
+
}
|
|
17535
|
+
extractAgentLogData(spanData) {
|
|
17536
|
+
return {
|
|
17537
|
+
metadata: {
|
|
17538
|
+
tools: spanData.tools,
|
|
17539
|
+
handoffs: spanData.handoffs,
|
|
17540
|
+
output_type: spanData.output_type
|
|
17541
|
+
}
|
|
17542
|
+
};
|
|
17543
|
+
}
|
|
17544
|
+
extractResponseLogData(spanData, span) {
|
|
17545
|
+
const response = spanData._response;
|
|
17546
|
+
const output = isObject(response) ? response.output : void 0;
|
|
17547
|
+
const usage = isObject(response) ? response.usage : void 0;
|
|
17548
|
+
const metrics = {
|
|
17549
|
+
...this.extractTimingMetrics(span),
|
|
17550
|
+
...parseUsageMetrics(usage)
|
|
17551
|
+
};
|
|
17552
|
+
return {
|
|
17553
|
+
input: spanData._input,
|
|
17554
|
+
output,
|
|
17555
|
+
metadata: isObject(response) ? this.omitKeys(response, ["output", "usage"]) : {},
|
|
17556
|
+
metrics
|
|
17557
|
+
};
|
|
17558
|
+
}
|
|
17559
|
+
extractFunctionLogData(spanData) {
|
|
17560
|
+
return {
|
|
17561
|
+
input: spanData.input,
|
|
17562
|
+
output: spanData.output
|
|
17563
|
+
};
|
|
17564
|
+
}
|
|
17565
|
+
extractHandoffLogData(spanData) {
|
|
17566
|
+
return {
|
|
17567
|
+
metadata: {
|
|
17568
|
+
from_agent: spanData.from_agent,
|
|
17569
|
+
to_agent: spanData.to_agent
|
|
17570
|
+
}
|
|
17571
|
+
};
|
|
17572
|
+
}
|
|
17573
|
+
extractGuardrailLogData(spanData) {
|
|
17574
|
+
return {
|
|
17575
|
+
metadata: {
|
|
17576
|
+
triggered: spanData.triggered
|
|
17577
|
+
}
|
|
17578
|
+
};
|
|
17579
|
+
}
|
|
17580
|
+
extractGenerationLogData(spanData, span) {
|
|
17581
|
+
return {
|
|
17582
|
+
input: spanData.input,
|
|
17583
|
+
output: spanData.output,
|
|
17584
|
+
metadata: {
|
|
17585
|
+
model: spanData.model,
|
|
17586
|
+
model_config: spanData.model_config
|
|
17587
|
+
},
|
|
17588
|
+
metrics: {
|
|
17589
|
+
...this.extractTimingMetrics(span),
|
|
17590
|
+
...parseUsageMetrics(spanData.usage)
|
|
17591
|
+
}
|
|
17592
|
+
};
|
|
17593
|
+
}
|
|
17594
|
+
extractCustomLogData(spanData) {
|
|
17595
|
+
return spanData.data || {};
|
|
17596
|
+
}
|
|
17597
|
+
extractMCPListToolsLogData(spanData) {
|
|
17598
|
+
return {
|
|
17599
|
+
output: spanData.result,
|
|
17600
|
+
metadata: {
|
|
17601
|
+
server: spanData.server
|
|
17602
|
+
}
|
|
17603
|
+
};
|
|
17604
|
+
}
|
|
17605
|
+
extractTranscriptionLogData(spanData) {
|
|
17606
|
+
return {
|
|
17607
|
+
input: spanData.input,
|
|
17608
|
+
output: spanData.output,
|
|
17609
|
+
metadata: {
|
|
17610
|
+
model: spanData.model,
|
|
17611
|
+
model_config: spanData.model_config
|
|
17612
|
+
}
|
|
17613
|
+
};
|
|
17614
|
+
}
|
|
17615
|
+
extractSpeechLogData(spanData) {
|
|
17616
|
+
return {
|
|
17617
|
+
input: spanData.input,
|
|
17618
|
+
output: spanData.output,
|
|
17619
|
+
metadata: {
|
|
17620
|
+
model: spanData.model,
|
|
17621
|
+
model_config: spanData.model_config
|
|
17622
|
+
}
|
|
17623
|
+
};
|
|
17624
|
+
}
|
|
17625
|
+
extractSpeechGroupLogData(spanData) {
|
|
17626
|
+
return {
|
|
17627
|
+
input: spanData.input
|
|
17628
|
+
};
|
|
17629
|
+
}
|
|
17630
|
+
extractTimingMetrics(span) {
|
|
17631
|
+
const timeToFirstToken = getTimeElapsed(
|
|
17632
|
+
span.endedAt ?? void 0,
|
|
17633
|
+
span.startedAt ?? void 0
|
|
17634
|
+
);
|
|
17635
|
+
return timeToFirstToken === void 0 ? {} : { time_to_first_token: timeToFirstToken };
|
|
17636
|
+
}
|
|
17637
|
+
omitKeys(value, keys) {
|
|
17638
|
+
const result = {};
|
|
17639
|
+
for (const [key, fieldValue] of Object.entries(value)) {
|
|
17640
|
+
if (!keys.includes(key)) {
|
|
17641
|
+
result[key] = fieldValue;
|
|
17642
|
+
}
|
|
17643
|
+
}
|
|
17644
|
+
return result;
|
|
17645
|
+
}
|
|
17646
|
+
};
|
|
17647
|
+
|
|
17648
|
+
// src/instrumentation/plugins/openai-agents-plugin.ts
|
|
17649
|
+
function firstArgument(args) {
|
|
17650
|
+
if (Array.isArray(args)) {
|
|
17651
|
+
return args[0];
|
|
17652
|
+
}
|
|
17653
|
+
if (isObject(args) && "length" in args && typeof args.length === "number" && Number.isInteger(args.length) && args.length >= 0) {
|
|
17654
|
+
return Array.from(args)[0];
|
|
17655
|
+
}
|
|
17656
|
+
return void 0;
|
|
17657
|
+
}
|
|
17658
|
+
function isOpenAIAgentsTrace(value) {
|
|
17659
|
+
return isObject(value) && value.type === "trace" && typeof value.traceId === "string";
|
|
17660
|
+
}
|
|
17661
|
+
function isOpenAIAgentsSpan(value) {
|
|
17662
|
+
return isObject(value) && value.type === "trace.span" && typeof value.traceId === "string" && typeof value.spanId === "string";
|
|
17663
|
+
}
|
|
17664
|
+
var OpenAIAgentsPlugin = class extends BasePlugin {
|
|
17665
|
+
processor = new OpenAIAgentsTraceProcessor();
|
|
17666
|
+
onEnable() {
|
|
17667
|
+
this.subscribeToTraceLifecycle();
|
|
17668
|
+
}
|
|
17669
|
+
onDisable() {
|
|
17670
|
+
this.unsubscribers = unsubscribeAll(this.unsubscribers);
|
|
17671
|
+
void this.processor.shutdown();
|
|
17672
|
+
}
|
|
17673
|
+
subscribeToTraceLifecycle() {
|
|
17674
|
+
const traceStartChannel = openAIAgentsCoreChannels.onTraceStart.tracingChannel();
|
|
17675
|
+
const traceStartHandlers = {
|
|
17676
|
+
start: (event) => {
|
|
17677
|
+
const trace = firstArgument(event.arguments);
|
|
17678
|
+
if (isOpenAIAgentsTrace(trace)) {
|
|
17679
|
+
void this.processor.onTraceStart(trace);
|
|
17680
|
+
}
|
|
17681
|
+
}
|
|
17682
|
+
};
|
|
17683
|
+
traceStartChannel.subscribe(traceStartHandlers);
|
|
17684
|
+
this.unsubscribers.push(
|
|
17685
|
+
() => traceStartChannel.unsubscribe(traceStartHandlers)
|
|
17686
|
+
);
|
|
17687
|
+
const traceEndChannel = openAIAgentsCoreChannels.onTraceEnd.tracingChannel();
|
|
17688
|
+
const traceEndHandlers = {
|
|
17689
|
+
start: (event) => {
|
|
17690
|
+
const trace = firstArgument(event.arguments);
|
|
17691
|
+
if (isOpenAIAgentsTrace(trace)) {
|
|
17692
|
+
void this.processor.onTraceEnd(trace);
|
|
17693
|
+
}
|
|
17694
|
+
}
|
|
17695
|
+
};
|
|
17696
|
+
traceEndChannel.subscribe(traceEndHandlers);
|
|
17697
|
+
this.unsubscribers.push(
|
|
17698
|
+
() => traceEndChannel.unsubscribe(traceEndHandlers)
|
|
17699
|
+
);
|
|
17700
|
+
const spanStartChannel = openAIAgentsCoreChannels.onSpanStart.tracingChannel();
|
|
17701
|
+
const spanStartHandlers = {
|
|
17702
|
+
start: (event) => {
|
|
17703
|
+
const span = firstArgument(event.arguments);
|
|
17704
|
+
if (isOpenAIAgentsSpan(span)) {
|
|
17705
|
+
void this.processor.onSpanStart(span);
|
|
17706
|
+
}
|
|
17707
|
+
}
|
|
17708
|
+
};
|
|
17709
|
+
spanStartChannel.subscribe(spanStartHandlers);
|
|
17710
|
+
this.unsubscribers.push(
|
|
17711
|
+
() => spanStartChannel.unsubscribe(spanStartHandlers)
|
|
17712
|
+
);
|
|
17713
|
+
const spanEndChannel = openAIAgentsCoreChannels.onSpanEnd.tracingChannel();
|
|
17714
|
+
const spanEndHandlers = {
|
|
17715
|
+
start: (event) => {
|
|
17716
|
+
const span = firstArgument(event.arguments);
|
|
17717
|
+
if (isOpenAIAgentsSpan(span)) {
|
|
17718
|
+
void this.processor.onSpanEnd(span);
|
|
17719
|
+
}
|
|
17720
|
+
}
|
|
17721
|
+
};
|
|
17722
|
+
spanEndChannel.subscribe(spanEndHandlers);
|
|
17723
|
+
this.unsubscribers.push(() => spanEndChannel.unsubscribe(spanEndHandlers));
|
|
17724
|
+
}
|
|
17725
|
+
};
|
|
17726
|
+
|
|
17241
17727
|
// src/instrumentation/plugins/google-genai-channels.ts
|
|
17242
17728
|
var googleGenAIChannels = defineChannels("@google/genai", {
|
|
17243
17729
|
generateContent: channel({
|
|
@@ -23530,58 +24016,1794 @@ var GitHubCopilotPlugin = class extends BasePlugin {
|
|
|
23530
24016
|
}
|
|
23531
24017
|
};
|
|
23532
24018
|
|
|
23533
|
-
// src/instrumentation/
|
|
23534
|
-
|
|
23535
|
-
|
|
24019
|
+
// src/instrumentation/plugins/flue-channels.ts
|
|
24020
|
+
var flueChannels = defineChannels("@flue/runtime", {
|
|
24021
|
+
createContext: channel({
|
|
24022
|
+
channelName: "createFlueContext",
|
|
24023
|
+
kind: "sync-stream"
|
|
24024
|
+
}),
|
|
24025
|
+
openSession: channel({
|
|
24026
|
+
channelName: "Harness.openSession",
|
|
24027
|
+
kind: "async"
|
|
24028
|
+
}),
|
|
24029
|
+
contextEvent: channel({
|
|
24030
|
+
channelName: "context.event",
|
|
24031
|
+
kind: "sync-stream"
|
|
24032
|
+
}),
|
|
24033
|
+
prompt: channel({
|
|
24034
|
+
channelName: "session.prompt",
|
|
24035
|
+
kind: "async"
|
|
24036
|
+
}),
|
|
24037
|
+
skill: channel({
|
|
24038
|
+
channelName: "session.skill",
|
|
24039
|
+
kind: "async"
|
|
24040
|
+
}),
|
|
24041
|
+
task: channel({
|
|
24042
|
+
channelName: "session.task",
|
|
24043
|
+
kind: "async"
|
|
24044
|
+
}),
|
|
24045
|
+
compact: channel({
|
|
24046
|
+
channelName: "session.compact",
|
|
24047
|
+
kind: "async"
|
|
24048
|
+
})
|
|
24049
|
+
});
|
|
24050
|
+
|
|
24051
|
+
// src/wrappers/flue.ts
|
|
24052
|
+
var WRAPPED_FLUE_CONTEXT = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-context");
|
|
24053
|
+
var WRAPPED_FLUE_HARNESS = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-harness");
|
|
24054
|
+
var WRAPPED_FLUE_SESSION = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-session");
|
|
24055
|
+
var SUBSCRIBED_FLUE_CONTEXT_EVENTS = /* @__PURE__ */ Symbol.for(
|
|
24056
|
+
"braintrust.flue.subscribed-context-events"
|
|
24057
|
+
);
|
|
24058
|
+
function wrapFlueContext(ctx) {
|
|
24059
|
+
if (!isPlausibleFlueContext(ctx)) {
|
|
24060
|
+
console.warn("Unsupported Flue context. Not wrapping.");
|
|
24061
|
+
return ctx;
|
|
24062
|
+
}
|
|
24063
|
+
const context = ctx;
|
|
24064
|
+
subscribeFlueContextEvents(context, { captureTurnSpans: true });
|
|
24065
|
+
return patchFlueContextInPlace(context);
|
|
23536
24066
|
}
|
|
23537
|
-
|
|
23538
|
-
|
|
23539
|
-
|
|
23540
|
-
|
|
23541
|
-
anthropicPlugin = null;
|
|
23542
|
-
aiSDKPlugin = null;
|
|
23543
|
-
claudeAgentSDKPlugin = null;
|
|
23544
|
-
cursorSDKPlugin = null;
|
|
23545
|
-
googleGenAIPlugin = null;
|
|
23546
|
-
huggingFacePlugin = null;
|
|
23547
|
-
openRouterPlugin = null;
|
|
23548
|
-
openRouterAgentPlugin = null;
|
|
23549
|
-
mistralPlugin = null;
|
|
23550
|
-
googleADKPlugin = null;
|
|
23551
|
-
coherePlugin = null;
|
|
23552
|
-
groqPlugin = null;
|
|
23553
|
-
genkitPlugin = null;
|
|
23554
|
-
gitHubCopilotPlugin = null;
|
|
23555
|
-
constructor(config = {}) {
|
|
23556
|
-
super();
|
|
23557
|
-
this.config = config;
|
|
24067
|
+
function patchFlueContextInPlace(ctx) {
|
|
24068
|
+
const context = ctx;
|
|
24069
|
+
if (context[WRAPPED_FLUE_CONTEXT]) {
|
|
24070
|
+
return ctx;
|
|
23558
24071
|
}
|
|
23559
|
-
|
|
23560
|
-
|
|
23561
|
-
|
|
23562
|
-
|
|
23563
|
-
|
|
23564
|
-
|
|
23565
|
-
|
|
23566
|
-
|
|
23567
|
-
|
|
23568
|
-
|
|
23569
|
-
|
|
23570
|
-
|
|
23571
|
-
|
|
23572
|
-
|
|
23573
|
-
|
|
23574
|
-
|
|
23575
|
-
|
|
23576
|
-
|
|
23577
|
-
|
|
23578
|
-
|
|
24072
|
+
const originalInit = context.init.bind(context);
|
|
24073
|
+
try {
|
|
24074
|
+
Object.defineProperty(context, WRAPPED_FLUE_CONTEXT, {
|
|
24075
|
+
configurable: false,
|
|
24076
|
+
enumerable: false,
|
|
24077
|
+
value: true
|
|
24078
|
+
});
|
|
24079
|
+
Object.defineProperty(context, "init", {
|
|
24080
|
+
configurable: true,
|
|
24081
|
+
value: async function wrappedFlueInit(options) {
|
|
24082
|
+
const harness = await originalInit(options);
|
|
24083
|
+
return wrapFlueHarness(harness);
|
|
24084
|
+
},
|
|
24085
|
+
writable: true
|
|
24086
|
+
});
|
|
24087
|
+
} catch {
|
|
24088
|
+
}
|
|
24089
|
+
return ctx;
|
|
24090
|
+
}
|
|
24091
|
+
function wrapFlueSession(session) {
|
|
24092
|
+
if (!isPlausibleFlueSession(session)) {
|
|
24093
|
+
console.warn("Unsupported Flue session. Not wrapping.");
|
|
24094
|
+
return session;
|
|
24095
|
+
}
|
|
24096
|
+
return patchFlueSessionInPlace(session);
|
|
24097
|
+
}
|
|
24098
|
+
function subscribeFlueContextEvents(ctx, options = {}) {
|
|
24099
|
+
if (!ctx || typeof ctx !== "object" || typeof ctx.subscribeEvent !== "function") {
|
|
24100
|
+
return void 0;
|
|
24101
|
+
}
|
|
24102
|
+
const context = ctx;
|
|
24103
|
+
const captureTurnSpans = options.captureTurnSpans ?? true;
|
|
24104
|
+
const existingSubscription = context[SUBSCRIBED_FLUE_CONTEXT_EVENTS];
|
|
24105
|
+
if (existingSubscription) {
|
|
24106
|
+
if (existingSubscription.captureTurnSpans || !captureTurnSpans) {
|
|
24107
|
+
return void 0;
|
|
24108
|
+
}
|
|
24109
|
+
try {
|
|
24110
|
+
existingSubscription.unsubscribe();
|
|
24111
|
+
} catch {
|
|
24112
|
+
}
|
|
24113
|
+
}
|
|
24114
|
+
try {
|
|
24115
|
+
const unsubscribe = ctx.subscribeEvent((event) => {
|
|
24116
|
+
flueChannels.contextEvent.traceSync(() => void 0, {
|
|
24117
|
+
arguments: [event],
|
|
24118
|
+
captureTurnSpans,
|
|
24119
|
+
context: ctx
|
|
24120
|
+
});
|
|
24121
|
+
});
|
|
24122
|
+
if (existingSubscription) {
|
|
24123
|
+
existingSubscription.captureTurnSpans = captureTurnSpans;
|
|
24124
|
+
existingSubscription.unsubscribe = unsubscribe;
|
|
24125
|
+
} else {
|
|
24126
|
+
Object.defineProperty(context, SUBSCRIBED_FLUE_CONTEXT_EVENTS, {
|
|
24127
|
+
configurable: false,
|
|
24128
|
+
enumerable: false,
|
|
24129
|
+
value: {
|
|
24130
|
+
captureTurnSpans,
|
|
24131
|
+
unsubscribe
|
|
24132
|
+
}
|
|
24133
|
+
});
|
|
24134
|
+
}
|
|
24135
|
+
return unsubscribe;
|
|
24136
|
+
} catch {
|
|
24137
|
+
return void 0;
|
|
24138
|
+
}
|
|
24139
|
+
}
|
|
24140
|
+
function wrapFlueHarness(harness) {
|
|
24141
|
+
if (!isPlausibleFlueHarness(harness)) {
|
|
24142
|
+
return harness;
|
|
24143
|
+
}
|
|
24144
|
+
const target = harness;
|
|
24145
|
+
if (target[WRAPPED_FLUE_HARNESS]) {
|
|
24146
|
+
return harness;
|
|
24147
|
+
}
|
|
24148
|
+
const originalSession = target.session.bind(target);
|
|
24149
|
+
try {
|
|
24150
|
+
Object.defineProperty(target, WRAPPED_FLUE_HARNESS, {
|
|
24151
|
+
configurable: false,
|
|
24152
|
+
enumerable: false,
|
|
24153
|
+
value: true
|
|
24154
|
+
});
|
|
24155
|
+
Object.defineProperty(target, "session", {
|
|
24156
|
+
configurable: true,
|
|
24157
|
+
value: async function wrappedFlueHarnessSession(name, options) {
|
|
24158
|
+
const session = await originalSession(name, options);
|
|
24159
|
+
return patchFlueSessionInPlace(session);
|
|
24160
|
+
},
|
|
24161
|
+
writable: true
|
|
24162
|
+
});
|
|
24163
|
+
const sessions = target.sessions;
|
|
24164
|
+
if (sessions && typeof sessions === "object") {
|
|
24165
|
+
patchFlueSessionFactory(sessions, "get");
|
|
24166
|
+
patchFlueSessionFactory(sessions, "create");
|
|
24167
|
+
}
|
|
24168
|
+
} catch {
|
|
24169
|
+
}
|
|
24170
|
+
return harness;
|
|
24171
|
+
}
|
|
24172
|
+
function patchFlueSessionInPlace(session) {
|
|
24173
|
+
if (session[WRAPPED_FLUE_SESSION]) {
|
|
24174
|
+
return session;
|
|
24175
|
+
}
|
|
24176
|
+
try {
|
|
24177
|
+
Object.defineProperty(session, WRAPPED_FLUE_SESSION, {
|
|
24178
|
+
configurable: false,
|
|
24179
|
+
enumerable: false,
|
|
24180
|
+
value: true
|
|
24181
|
+
});
|
|
24182
|
+
patchCallHandleMethod(session, "prompt", flueChannels.prompt);
|
|
24183
|
+
patchCallHandleMethod(session, "skill", flueChannels.skill);
|
|
24184
|
+
patchCallHandleMethod(session, "task", flueChannels.task);
|
|
24185
|
+
patchCompact(session);
|
|
24186
|
+
} catch {
|
|
24187
|
+
}
|
|
24188
|
+
return session;
|
|
24189
|
+
}
|
|
24190
|
+
function patchFlueSessionFactory(sessions, method) {
|
|
24191
|
+
const original = sessions[method];
|
|
24192
|
+
if (typeof original !== "function") {
|
|
24193
|
+
return;
|
|
24194
|
+
}
|
|
24195
|
+
const bound = original.bind(sessions);
|
|
24196
|
+
Object.defineProperty(sessions, method, {
|
|
24197
|
+
configurable: true,
|
|
24198
|
+
value: async function wrappedFlueSessionFactory(name, options) {
|
|
24199
|
+
const session = await bound(name, options);
|
|
24200
|
+
return patchFlueSessionInPlace(session);
|
|
24201
|
+
},
|
|
24202
|
+
writable: true
|
|
24203
|
+
});
|
|
24204
|
+
}
|
|
24205
|
+
function patchCallHandleMethod(session, method, channel2) {
|
|
24206
|
+
const original = session[method];
|
|
24207
|
+
if (typeof original !== "function") {
|
|
24208
|
+
return;
|
|
24209
|
+
}
|
|
24210
|
+
const bound = original.bind(session);
|
|
24211
|
+
Object.defineProperty(session, method, {
|
|
24212
|
+
configurable: true,
|
|
24213
|
+
value(input, options) {
|
|
24214
|
+
const args = [input, options];
|
|
24215
|
+
const { originalResult, traced: traced2 } = traceFlueOperation(channel2, {
|
|
24216
|
+
context: {
|
|
24217
|
+
arguments: args,
|
|
24218
|
+
operation: method,
|
|
24219
|
+
session
|
|
24220
|
+
},
|
|
24221
|
+
run: () => bound(input, options)
|
|
24222
|
+
});
|
|
24223
|
+
return preserveCallHandle(originalResult, traced2);
|
|
24224
|
+
},
|
|
24225
|
+
writable: true
|
|
24226
|
+
});
|
|
24227
|
+
}
|
|
24228
|
+
function patchCompact(session) {
|
|
24229
|
+
const original = session.compact;
|
|
24230
|
+
if (typeof original !== "function") {
|
|
24231
|
+
return;
|
|
24232
|
+
}
|
|
24233
|
+
const bound = original.bind(session);
|
|
24234
|
+
Object.defineProperty(session, "compact", {
|
|
24235
|
+
configurable: true,
|
|
24236
|
+
value() {
|
|
24237
|
+
const context = {
|
|
24238
|
+
arguments: [],
|
|
24239
|
+
operation: "compact",
|
|
24240
|
+
session
|
|
24241
|
+
};
|
|
24242
|
+
return flueChannels.compact.tracePromise(() => bound(), context);
|
|
24243
|
+
},
|
|
24244
|
+
writable: true
|
|
24245
|
+
});
|
|
24246
|
+
}
|
|
24247
|
+
function traceFlueOperation(channel2, args) {
|
|
24248
|
+
const tracingChannel2 = channel2.tracingChannel();
|
|
24249
|
+
const context = args.context;
|
|
24250
|
+
let originalResult;
|
|
24251
|
+
let traced2;
|
|
24252
|
+
const run = () => {
|
|
24253
|
+
try {
|
|
24254
|
+
originalResult = args.run();
|
|
24255
|
+
tracingChannel2.end?.publish(context);
|
|
24256
|
+
} catch (error) {
|
|
24257
|
+
context.error = normalizeError3(error);
|
|
24258
|
+
tracingChannel2.error?.publish(context);
|
|
24259
|
+
tracingChannel2.end?.publish(context);
|
|
24260
|
+
throw error;
|
|
24261
|
+
}
|
|
24262
|
+
traced2 = Promise.resolve(originalResult).then(
|
|
24263
|
+
(result) => {
|
|
24264
|
+
context.result = result;
|
|
24265
|
+
tracingChannel2.asyncStart?.publish(context);
|
|
24266
|
+
tracingChannel2.asyncEnd?.publish(context);
|
|
24267
|
+
return result;
|
|
24268
|
+
},
|
|
24269
|
+
(error) => {
|
|
24270
|
+
context.error = normalizeError3(error);
|
|
24271
|
+
tracingChannel2.error?.publish(context);
|
|
24272
|
+
tracingChannel2.asyncStart?.publish(context);
|
|
24273
|
+
tracingChannel2.asyncEnd?.publish(context);
|
|
24274
|
+
throw error;
|
|
24275
|
+
}
|
|
24276
|
+
);
|
|
24277
|
+
};
|
|
24278
|
+
if (tracingChannel2.start?.runStores) {
|
|
24279
|
+
tracingChannel2.start.runStores(context, run);
|
|
24280
|
+
} else {
|
|
24281
|
+
tracingChannel2.start?.publish(context);
|
|
24282
|
+
run();
|
|
24283
|
+
}
|
|
24284
|
+
return { originalResult, traced: traced2 };
|
|
24285
|
+
}
|
|
24286
|
+
function normalizeError3(error) {
|
|
24287
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
24288
|
+
}
|
|
24289
|
+
function preserveCallHandle(originalHandle, traced2) {
|
|
24290
|
+
if (!isFlueCallHandle(originalHandle)) {
|
|
24291
|
+
return traced2;
|
|
24292
|
+
}
|
|
24293
|
+
const handle = originalHandle;
|
|
24294
|
+
const wrapped = {
|
|
24295
|
+
get signal() {
|
|
24296
|
+
return handle.signal;
|
|
24297
|
+
},
|
|
24298
|
+
abort(reason) {
|
|
24299
|
+
return handle.abort(reason);
|
|
24300
|
+
},
|
|
24301
|
+
then(onfulfilled, onrejected) {
|
|
24302
|
+
return traced2.then(onfulfilled, onrejected);
|
|
24303
|
+
}
|
|
24304
|
+
};
|
|
24305
|
+
return wrapped;
|
|
24306
|
+
}
|
|
24307
|
+
function isPlausibleFlueContext(value) {
|
|
24308
|
+
return !!value && typeof value === "object" && typeof value.init === "function";
|
|
24309
|
+
}
|
|
24310
|
+
function isPlausibleFlueHarness(value) {
|
|
24311
|
+
return !!value && typeof value === "object" && typeof value.session === "function";
|
|
24312
|
+
}
|
|
24313
|
+
function isPlausibleFlueSession(value) {
|
|
24314
|
+
return !!value && typeof value === "object" && typeof value.prompt === "function" && typeof value.skill === "function" && typeof value.task === "function" && typeof value.compact === "function";
|
|
24315
|
+
}
|
|
24316
|
+
function isFlueCallHandle(value) {
|
|
24317
|
+
return !!value && typeof value === "object" && typeof value.then === "function" && typeof value.abort === "function" && "signal" in value;
|
|
24318
|
+
}
|
|
24319
|
+
|
|
24320
|
+
// src/instrumentation/plugins/flue-plugin.ts
|
|
24321
|
+
var FluePlugin = class extends BasePlugin {
|
|
24322
|
+
activeOperationsById = /* @__PURE__ */ new Map();
|
|
24323
|
+
activeOperationsByScope = /* @__PURE__ */ new Map();
|
|
24324
|
+
compactionsByScope = /* @__PURE__ */ new Map();
|
|
24325
|
+
pendingOperationsByKey = /* @__PURE__ */ new Map();
|
|
24326
|
+
tasksById = /* @__PURE__ */ new Map();
|
|
24327
|
+
toolsById = /* @__PURE__ */ new Map();
|
|
24328
|
+
turnsByScope = /* @__PURE__ */ new Map();
|
|
24329
|
+
onEnable() {
|
|
24330
|
+
this.subscribeToContextCreation();
|
|
24331
|
+
this.subscribeToSessionCreation();
|
|
24332
|
+
this.subscribeToContextEvents();
|
|
24333
|
+
this.subscribeToSessionOperations();
|
|
24334
|
+
}
|
|
24335
|
+
onDisable() {
|
|
24336
|
+
for (const unsubscribe of this.unsubscribers) {
|
|
24337
|
+
unsubscribe();
|
|
24338
|
+
}
|
|
24339
|
+
this.unsubscribers = [];
|
|
24340
|
+
this.activeOperationsById.clear();
|
|
24341
|
+
this.activeOperationsByScope.clear();
|
|
24342
|
+
this.compactionsByScope.clear();
|
|
24343
|
+
this.pendingOperationsByKey.clear();
|
|
24344
|
+
this.tasksById.clear();
|
|
24345
|
+
this.toolsById.clear();
|
|
24346
|
+
this.turnsByScope.clear();
|
|
24347
|
+
}
|
|
24348
|
+
subscribeToContextCreation() {
|
|
24349
|
+
const channel2 = flueChannels.createContext.tracingChannel();
|
|
24350
|
+
const handlers = {
|
|
24351
|
+
end: (event) => {
|
|
24352
|
+
const ctx = event.result;
|
|
24353
|
+
if (!ctx) {
|
|
24354
|
+
return;
|
|
24355
|
+
}
|
|
24356
|
+
subscribeFlueContextEvents(ctx, { captureTurnSpans: false });
|
|
24357
|
+
patchFlueContextInPlace(ctx);
|
|
24358
|
+
},
|
|
24359
|
+
error: () => {
|
|
24360
|
+
}
|
|
24361
|
+
};
|
|
24362
|
+
channel2.subscribe(handlers);
|
|
24363
|
+
this.unsubscribers.push(() => {
|
|
24364
|
+
channel2.unsubscribe(handlers);
|
|
24365
|
+
});
|
|
24366
|
+
}
|
|
24367
|
+
subscribeToSessionCreation() {
|
|
24368
|
+
const channel2 = flueChannels.openSession.tracingChannel();
|
|
24369
|
+
const handlers = {
|
|
24370
|
+
asyncEnd: (event) => {
|
|
24371
|
+
if (event.result) {
|
|
24372
|
+
patchFlueSessionInPlace(
|
|
24373
|
+
event.result
|
|
24374
|
+
);
|
|
24375
|
+
}
|
|
24376
|
+
if (event.harness) {
|
|
24377
|
+
wrapFlueHarness(event.harness);
|
|
24378
|
+
}
|
|
24379
|
+
},
|
|
24380
|
+
error: () => {
|
|
24381
|
+
}
|
|
24382
|
+
};
|
|
24383
|
+
channel2.subscribe(handlers);
|
|
24384
|
+
this.unsubscribers.push(() => {
|
|
24385
|
+
channel2.unsubscribe(handlers);
|
|
24386
|
+
});
|
|
24387
|
+
}
|
|
24388
|
+
subscribeToSessionOperations() {
|
|
24389
|
+
this.subscribeToSessionOperation(flueChannels.prompt);
|
|
24390
|
+
this.subscribeToSessionOperation(flueChannels.skill);
|
|
24391
|
+
this.subscribeToSessionOperation(flueChannels.task);
|
|
24392
|
+
this.subscribeToCompact();
|
|
24393
|
+
}
|
|
24394
|
+
subscribeToSessionOperation(channel2) {
|
|
24395
|
+
const tracingChannel2 = channel2.tracingChannel();
|
|
24396
|
+
const states = /* @__PURE__ */ new WeakMap();
|
|
24397
|
+
const ensureState2 = (event) => {
|
|
24398
|
+
const existing = states.get(event);
|
|
24399
|
+
if (existing) {
|
|
24400
|
+
return existing;
|
|
24401
|
+
}
|
|
24402
|
+
const state = this.startOperationState({
|
|
24403
|
+
args: event.arguments,
|
|
24404
|
+
moduleVersion: typeof event.moduleVersion === "string" ? event.moduleVersion : void 0,
|
|
24405
|
+
operation: event.operation,
|
|
24406
|
+
session: event.session
|
|
24407
|
+
});
|
|
24408
|
+
states.set(event, state);
|
|
24409
|
+
return state;
|
|
24410
|
+
};
|
|
24411
|
+
const unbindCurrentSpanStore = this.bindCurrentSpanStoreToOperationStart(
|
|
24412
|
+
tracingChannel2,
|
|
24413
|
+
ensureState2
|
|
24414
|
+
);
|
|
24415
|
+
const handlers = {
|
|
24416
|
+
start: (event) => {
|
|
24417
|
+
ensureState2(event);
|
|
24418
|
+
},
|
|
24419
|
+
asyncEnd: (event) => {
|
|
24420
|
+
this.endOperationState(states.get(event), event.result);
|
|
24421
|
+
states.delete(event);
|
|
24422
|
+
},
|
|
24423
|
+
error: (event) => {
|
|
24424
|
+
const state = states.get(event);
|
|
24425
|
+
if (state && event.error) {
|
|
24426
|
+
safeLog3(state.span, { error: errorToString(event.error) });
|
|
24427
|
+
this.finishOperationState(state);
|
|
24428
|
+
}
|
|
24429
|
+
states.delete(event);
|
|
24430
|
+
}
|
|
24431
|
+
};
|
|
24432
|
+
tracingChannel2.subscribe(handlers);
|
|
24433
|
+
this.unsubscribers.push(() => {
|
|
24434
|
+
unbindCurrentSpanStore?.();
|
|
24435
|
+
tracingChannel2.unsubscribe(handlers);
|
|
24436
|
+
});
|
|
24437
|
+
}
|
|
24438
|
+
subscribeToCompact() {
|
|
24439
|
+
const tracingChannel2 = flueChannels.compact.tracingChannel();
|
|
24440
|
+
const states = /* @__PURE__ */ new WeakMap();
|
|
24441
|
+
const ensureState2 = (event) => {
|
|
24442
|
+
const existing = states.get(event);
|
|
24443
|
+
if (existing) {
|
|
24444
|
+
return existing;
|
|
24445
|
+
}
|
|
24446
|
+
const state = this.startOperationState({
|
|
24447
|
+
args: [],
|
|
24448
|
+
moduleVersion: typeof event.moduleVersion === "string" ? event.moduleVersion : void 0,
|
|
24449
|
+
operation: event.operation,
|
|
24450
|
+
session: event.session
|
|
24451
|
+
});
|
|
24452
|
+
states.set(event, state);
|
|
24453
|
+
return state;
|
|
24454
|
+
};
|
|
24455
|
+
const unbindCurrentSpanStore = this.bindCurrentSpanStoreToOperationStart(
|
|
24456
|
+
tracingChannel2,
|
|
24457
|
+
ensureState2
|
|
24458
|
+
);
|
|
24459
|
+
const handlers = {
|
|
24460
|
+
start: (event) => {
|
|
24461
|
+
ensureState2(event);
|
|
24462
|
+
},
|
|
24463
|
+
asyncEnd: (event) => {
|
|
24464
|
+
this.endOperationState(states.get(event), void 0);
|
|
24465
|
+
states.delete(event);
|
|
24466
|
+
},
|
|
24467
|
+
error: (event) => {
|
|
24468
|
+
const state = states.get(event);
|
|
24469
|
+
if (state && event.error) {
|
|
24470
|
+
safeLog3(state.span, { error: errorToString(event.error) });
|
|
24471
|
+
this.finishOperationState(state);
|
|
24472
|
+
}
|
|
24473
|
+
states.delete(event);
|
|
24474
|
+
}
|
|
24475
|
+
};
|
|
24476
|
+
tracingChannel2.subscribe(handlers);
|
|
24477
|
+
this.unsubscribers.push(() => {
|
|
24478
|
+
unbindCurrentSpanStore?.();
|
|
24479
|
+
tracingChannel2.unsubscribe(handlers);
|
|
24480
|
+
});
|
|
24481
|
+
}
|
|
24482
|
+
subscribeToContextEvents() {
|
|
24483
|
+
const channel2 = flueChannels.contextEvent.tracingChannel();
|
|
24484
|
+
const handlers = {
|
|
24485
|
+
start: (event) => {
|
|
24486
|
+
const flueEvent = event.arguments[0];
|
|
24487
|
+
if (!flueEvent) {
|
|
24488
|
+
return;
|
|
24489
|
+
}
|
|
24490
|
+
try {
|
|
24491
|
+
this.handleFlueEvent(flueEvent, {
|
|
24492
|
+
captureTurnSpans: event.captureTurnSpans !== false
|
|
24493
|
+
});
|
|
24494
|
+
} catch (error) {
|
|
24495
|
+
logInstrumentationError3("Flue event", error);
|
|
24496
|
+
}
|
|
24497
|
+
},
|
|
24498
|
+
error: () => {
|
|
24499
|
+
}
|
|
24500
|
+
};
|
|
24501
|
+
channel2.subscribe(handlers);
|
|
24502
|
+
this.unsubscribers.push(() => {
|
|
24503
|
+
channel2.unsubscribe(handlers);
|
|
24504
|
+
});
|
|
24505
|
+
}
|
|
24506
|
+
bindCurrentSpanStoreToOperationStart(tracingChannel2, ensureState2) {
|
|
24507
|
+
const state = _internalGetGlobalState();
|
|
24508
|
+
const startChannel = tracingChannel2.start;
|
|
24509
|
+
const contextManager = state?.contextManager;
|
|
24510
|
+
const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
|
|
24511
|
+
if (!currentSpanStore || !startChannel) {
|
|
24512
|
+
return void 0;
|
|
24513
|
+
}
|
|
24514
|
+
startChannel.bindStore(currentSpanStore, (event) => {
|
|
24515
|
+
const operationState = ensureState2(event);
|
|
24516
|
+
return contextManager.wrapSpanForStore(operationState.span);
|
|
24517
|
+
});
|
|
24518
|
+
return () => {
|
|
24519
|
+
startChannel.unbindStore(currentSpanStore);
|
|
24520
|
+
};
|
|
24521
|
+
}
|
|
24522
|
+
startOperationState(args) {
|
|
24523
|
+
const sessionName = getSessionName(args.session);
|
|
24524
|
+
const metadata = {
|
|
24525
|
+
...extractOperationInputMetadata(args.operation, args.args),
|
|
24526
|
+
...extractSessionMetadata(args.session),
|
|
24527
|
+
"flue.operation": args.operation,
|
|
24528
|
+
provider: "flue",
|
|
24529
|
+
...args.moduleVersion ? { "flue.version": args.moduleVersion } : {}
|
|
24530
|
+
};
|
|
24531
|
+
const span = startSpan({
|
|
24532
|
+
name: `flue.session.${args.operation}`,
|
|
24533
|
+
spanAttributes: { type: "task" /* TASK */ }
|
|
24534
|
+
});
|
|
24535
|
+
const state = {
|
|
24536
|
+
metadata,
|
|
24537
|
+
operation: args.operation,
|
|
24538
|
+
sessionName,
|
|
24539
|
+
span,
|
|
24540
|
+
startTime: getCurrentUnixTimestamp()
|
|
24541
|
+
};
|
|
24542
|
+
safeLog3(span, {
|
|
24543
|
+
input: extractOperationInput(args.operation, args.args),
|
|
24544
|
+
metadata
|
|
24545
|
+
});
|
|
24546
|
+
this.pendingOperationQueue(operationKey(sessionName, args.operation)).push(
|
|
24547
|
+
state
|
|
24548
|
+
);
|
|
24549
|
+
addOperationToScope(
|
|
24550
|
+
this.activeOperationsByScope,
|
|
24551
|
+
sessionName ?? "unknown",
|
|
24552
|
+
state
|
|
24553
|
+
);
|
|
24554
|
+
return state;
|
|
24555
|
+
}
|
|
24556
|
+
endOperationState(state, result) {
|
|
24557
|
+
if (!state) {
|
|
24558
|
+
return;
|
|
24559
|
+
}
|
|
24560
|
+
const metadata = {
|
|
24561
|
+
...state.metadata,
|
|
24562
|
+
...extractPromptResponseMetadata(result)
|
|
24563
|
+
};
|
|
24564
|
+
const metrics = {
|
|
24565
|
+
...buildDurationMetrics3(state.startTime),
|
|
24566
|
+
...metricsFromUsage(result?.usage)
|
|
24567
|
+
};
|
|
24568
|
+
safeLog3(state.span, {
|
|
24569
|
+
metadata,
|
|
24570
|
+
metrics,
|
|
24571
|
+
output: extractOperationOutput(result)
|
|
24572
|
+
});
|
|
24573
|
+
this.finishCompactionsForOperation(state);
|
|
24574
|
+
this.finishOperationState(state);
|
|
24575
|
+
}
|
|
24576
|
+
finishOperationState(state) {
|
|
24577
|
+
removePendingOperation(this.pendingOperationsByKey, state);
|
|
24578
|
+
if (state.operationId) {
|
|
24579
|
+
this.activeOperationsById.delete(state.operationId);
|
|
24580
|
+
}
|
|
24581
|
+
removeScopedOperation(this.activeOperationsByScope, state);
|
|
24582
|
+
state.span.end();
|
|
24583
|
+
}
|
|
24584
|
+
handleFlueEvent(event, options) {
|
|
24585
|
+
switch (event.type) {
|
|
24586
|
+
case "operation_start":
|
|
24587
|
+
this.handleOperationStart(event);
|
|
24588
|
+
return;
|
|
24589
|
+
case "operation":
|
|
24590
|
+
this.handleOperation(event);
|
|
24591
|
+
return;
|
|
24592
|
+
case "text_delta":
|
|
24593
|
+
if (!options.captureTurnSpans) {
|
|
24594
|
+
return;
|
|
24595
|
+
}
|
|
24596
|
+
this.ensureTurnState(event).text.push(
|
|
24597
|
+
typeof event.text === "string" ? event.text : ""
|
|
24598
|
+
);
|
|
24599
|
+
return;
|
|
24600
|
+
case "thinking_start":
|
|
24601
|
+
if (!options.captureTurnSpans) {
|
|
24602
|
+
return;
|
|
24603
|
+
}
|
|
24604
|
+
this.handleThinkingStart(event);
|
|
24605
|
+
return;
|
|
24606
|
+
case "thinking_delta":
|
|
24607
|
+
if (!options.captureTurnSpans) {
|
|
24608
|
+
return;
|
|
24609
|
+
}
|
|
24610
|
+
this.handleThinkingDelta(event);
|
|
24611
|
+
return;
|
|
24612
|
+
case "thinking_end":
|
|
24613
|
+
if (!options.captureTurnSpans) {
|
|
24614
|
+
return;
|
|
24615
|
+
}
|
|
24616
|
+
this.handleThinkingEnd(event);
|
|
24617
|
+
return;
|
|
24618
|
+
case "turn":
|
|
24619
|
+
if (!options.captureTurnSpans) {
|
|
24620
|
+
return;
|
|
24621
|
+
}
|
|
24622
|
+
this.handleTurn(event);
|
|
24623
|
+
return;
|
|
24624
|
+
case "tool_start":
|
|
24625
|
+
this.handleToolStart(event, options);
|
|
24626
|
+
return;
|
|
24627
|
+
case "tool_call":
|
|
24628
|
+
this.handleToolCall(event);
|
|
24629
|
+
return;
|
|
24630
|
+
case "task_start":
|
|
24631
|
+
this.handleTaskStart(event);
|
|
24632
|
+
return;
|
|
24633
|
+
case "task":
|
|
24634
|
+
this.handleTask(event);
|
|
24635
|
+
return;
|
|
24636
|
+
case "compaction_start":
|
|
24637
|
+
this.handleCompactionStart(event);
|
|
24638
|
+
return;
|
|
24639
|
+
case "compaction":
|
|
24640
|
+
this.handleCompaction(event);
|
|
24641
|
+
return;
|
|
24642
|
+
default:
|
|
24643
|
+
return;
|
|
24644
|
+
}
|
|
24645
|
+
}
|
|
24646
|
+
handleOperationStart(event) {
|
|
24647
|
+
if (!isInstrumentedOperation(event.operationKind)) {
|
|
24648
|
+
return;
|
|
24649
|
+
}
|
|
24650
|
+
const state = this.takePendingOperationForEvent(event);
|
|
24651
|
+
if (!state) {
|
|
24652
|
+
return;
|
|
24653
|
+
}
|
|
24654
|
+
state.operationId = event.operationId;
|
|
24655
|
+
this.activeOperationsById.set(event.operationId, state);
|
|
24656
|
+
addScopedOperation(this.activeOperationsByScope, event, state);
|
|
24657
|
+
state.metadata = {
|
|
24658
|
+
...state.metadata,
|
|
24659
|
+
...extractEventMetadata(event),
|
|
24660
|
+
"flue.operation_id": event.operationId
|
|
24661
|
+
};
|
|
24662
|
+
safeLog3(state.span, { metadata: state.metadata });
|
|
24663
|
+
}
|
|
24664
|
+
handleOperation(event) {
|
|
24665
|
+
const state = event.operationId ? this.activeOperationsById.get(event.operationId) : void 0;
|
|
24666
|
+
if (!state) {
|
|
24667
|
+
return;
|
|
24668
|
+
}
|
|
24669
|
+
const metadata = {
|
|
24670
|
+
...state.metadata,
|
|
24671
|
+
...extractEventMetadata(event),
|
|
24672
|
+
...typeof event.durationMs === "number" ? { "flue.duration_ms": event.durationMs } : {},
|
|
24673
|
+
...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
|
|
24674
|
+
};
|
|
24675
|
+
const metrics = metricsFromUsage(event.usage);
|
|
24676
|
+
safeLog3(state.span, {
|
|
24677
|
+
...event.error ? { error: errorToString(event.error) } : {},
|
|
24678
|
+
metadata,
|
|
24679
|
+
...Object.keys(metrics).length ? { metrics } : {}
|
|
24680
|
+
});
|
|
24681
|
+
}
|
|
24682
|
+
ensureTurnState(event) {
|
|
24683
|
+
const scope = scopeKey(event);
|
|
24684
|
+
const existing = this.turnsByScope.get(scope);
|
|
24685
|
+
if (existing) {
|
|
24686
|
+
return existing;
|
|
24687
|
+
}
|
|
24688
|
+
const parent = this.parentSpanForEvent(event);
|
|
24689
|
+
const metadata = {
|
|
24690
|
+
...extractEventMetadata(event),
|
|
24691
|
+
provider: "flue"
|
|
24692
|
+
};
|
|
24693
|
+
const span = startFlueSpan(parent, {
|
|
24694
|
+
name: "flue.turn",
|
|
24695
|
+
spanAttributes: { type: "llm" /* LLM */ }
|
|
24696
|
+
});
|
|
24697
|
+
const state = {
|
|
24698
|
+
metadata,
|
|
24699
|
+
span,
|
|
24700
|
+
hasThinking: false,
|
|
24701
|
+
startTime: getCurrentUnixTimestamp(),
|
|
24702
|
+
text: [],
|
|
24703
|
+
thinking: [],
|
|
24704
|
+
toolCalls: []
|
|
24705
|
+
};
|
|
24706
|
+
safeLog3(span, { metadata });
|
|
24707
|
+
this.turnsByScope.set(scope, state);
|
|
24708
|
+
return state;
|
|
24709
|
+
}
|
|
24710
|
+
handleTurn(event) {
|
|
24711
|
+
const scope = scopeKey(event);
|
|
24712
|
+
const state = this.ensureTurnState(event);
|
|
24713
|
+
const text = state.text.join("");
|
|
24714
|
+
const reasoning = state.finalThinking ?? state.thinking.join("");
|
|
24715
|
+
const outputReasoning = reasoning || (state.hasThinking ? "[reasoning stream present; content unavailable]" : void 0);
|
|
24716
|
+
const metadata = {
|
|
24717
|
+
...state.metadata,
|
|
24718
|
+
...extractEventMetadata(event),
|
|
24719
|
+
...event.model ? { model: event.model, "flue.model": event.model } : {},
|
|
24720
|
+
...event.stopReason ? { "flue.stop_reason": event.stopReason } : {},
|
|
24721
|
+
...event.isError !== void 0 ? { "flue.is_error": event.isError } : {},
|
|
24722
|
+
provider: "flue"
|
|
24723
|
+
};
|
|
24724
|
+
safeLog3(state.span, {
|
|
24725
|
+
...event.error ? { error: errorToString(event.error) } : {},
|
|
24726
|
+
metadata,
|
|
24727
|
+
metrics: {
|
|
24728
|
+
...durationMsMetrics(event.durationMs),
|
|
24729
|
+
...metricsFromUsage(event.usage)
|
|
24730
|
+
},
|
|
24731
|
+
output: toAssistantOutput(
|
|
24732
|
+
text,
|
|
24733
|
+
event.stopReason,
|
|
24734
|
+
outputReasoning,
|
|
24735
|
+
state.toolCalls
|
|
24736
|
+
)
|
|
24737
|
+
});
|
|
24738
|
+
state.span.end();
|
|
24739
|
+
this.turnsByScope.delete(scope);
|
|
24740
|
+
}
|
|
24741
|
+
handleThinkingDelta(event) {
|
|
24742
|
+
const delta = event.delta;
|
|
24743
|
+
if (typeof delta !== "string" || !delta) {
|
|
24744
|
+
return;
|
|
24745
|
+
}
|
|
24746
|
+
const state = this.ensureTurnState(event);
|
|
24747
|
+
state.hasThinking = true;
|
|
24748
|
+
state.metadata["flue.thinking"] = true;
|
|
24749
|
+
state.thinking.push(delta);
|
|
24750
|
+
}
|
|
24751
|
+
handleThinkingStart(event) {
|
|
24752
|
+
const state = this.ensureTurnState(event);
|
|
24753
|
+
state.hasThinking = true;
|
|
24754
|
+
state.metadata["flue.thinking"] = true;
|
|
24755
|
+
}
|
|
24756
|
+
handleThinkingEnd(event) {
|
|
24757
|
+
const state = this.ensureTurnState(event);
|
|
24758
|
+
state.hasThinking = true;
|
|
24759
|
+
state.metadata["flue.thinking"] = true;
|
|
24760
|
+
if (typeof event.content === "string" && event.content) {
|
|
24761
|
+
state.finalThinking = event.content;
|
|
24762
|
+
}
|
|
24763
|
+
}
|
|
24764
|
+
handleToolStart(event, options) {
|
|
24765
|
+
const toolCallId = event.toolCallId;
|
|
24766
|
+
if (!toolCallId) {
|
|
24767
|
+
return;
|
|
24768
|
+
}
|
|
24769
|
+
const parent = this.parentSpanForEvent(event);
|
|
24770
|
+
const scope = scopeKey(event);
|
|
24771
|
+
let turnState = this.turnsByScope.get(scope);
|
|
24772
|
+
if (!turnState && parent && options.captureTurnSpans) {
|
|
24773
|
+
turnState = this.ensureTurnState(event);
|
|
24774
|
+
}
|
|
24775
|
+
const metadata = {
|
|
24776
|
+
...extractEventMetadata(event),
|
|
24777
|
+
...event.toolName ? { "flue.tool_name": event.toolName } : {},
|
|
24778
|
+
"flue.tool_call_id": toolCallId,
|
|
24779
|
+
provider: "flue"
|
|
24780
|
+
};
|
|
24781
|
+
const span = startFlueSpan(parent, {
|
|
24782
|
+
name: `tool: ${event.toolName ?? "unknown"}`,
|
|
24783
|
+
spanAttributes: { type: "tool" /* TOOL */ }
|
|
24784
|
+
});
|
|
24785
|
+
if (turnState) {
|
|
24786
|
+
turnState.toolCalls.push({
|
|
24787
|
+
args: event.args,
|
|
24788
|
+
toolCallId,
|
|
24789
|
+
toolName: event.toolName
|
|
24790
|
+
});
|
|
24791
|
+
}
|
|
24792
|
+
safeLog3(span, {
|
|
24793
|
+
input: event.args,
|
|
24794
|
+
metadata
|
|
24795
|
+
});
|
|
24796
|
+
this.toolsById.set(toolKey(event), {
|
|
24797
|
+
metadata,
|
|
24798
|
+
span,
|
|
24799
|
+
startTime: getCurrentUnixTimestamp()
|
|
24800
|
+
});
|
|
24801
|
+
}
|
|
24802
|
+
handleToolCall(event) {
|
|
24803
|
+
const key = toolKey(event);
|
|
24804
|
+
const state = this.toolsById.get(key) ?? this.startSyntheticToolState(event, event.toolName ?? "unknown");
|
|
24805
|
+
const metadata = {
|
|
24806
|
+
...state.metadata,
|
|
24807
|
+
...extractEventMetadata(event),
|
|
24808
|
+
...event.toolName ? { "flue.tool_name": event.toolName } : {},
|
|
24809
|
+
...event.toolCallId ? { "flue.tool_call_id": event.toolCallId } : {},
|
|
24810
|
+
...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
|
|
24811
|
+
};
|
|
24812
|
+
safeLog3(state.span, {
|
|
24813
|
+
...event.isError ? { error: errorToString(event.result) } : {},
|
|
24814
|
+
metadata,
|
|
24815
|
+
metrics: durationMsMetrics(event.durationMs),
|
|
24816
|
+
output: event.result
|
|
24817
|
+
});
|
|
24818
|
+
state.span.end();
|
|
24819
|
+
this.toolsById.delete(key);
|
|
24820
|
+
}
|
|
24821
|
+
handleTaskStart(event) {
|
|
24822
|
+
const parent = this.parentSpanForEvent(event);
|
|
24823
|
+
const metadata = {
|
|
24824
|
+
...extractEventMetadata(event),
|
|
24825
|
+
...event.role ? { "flue.role": event.role } : {},
|
|
24826
|
+
...event.cwd ? { "flue.cwd": event.cwd } : {},
|
|
24827
|
+
"flue.task_id": event.taskId,
|
|
24828
|
+
provider: "flue"
|
|
24829
|
+
};
|
|
24830
|
+
const span = startFlueSpan(parent, {
|
|
24831
|
+
name: "flue.task",
|
|
24832
|
+
spanAttributes: { type: "task" /* TASK */ }
|
|
24833
|
+
});
|
|
24834
|
+
safeLog3(span, {
|
|
24835
|
+
input: event.prompt,
|
|
24836
|
+
metadata
|
|
24837
|
+
});
|
|
24838
|
+
this.tasksById.set(event.taskId, {
|
|
24839
|
+
metadata,
|
|
24840
|
+
span,
|
|
24841
|
+
startTime: getCurrentUnixTimestamp()
|
|
24842
|
+
});
|
|
24843
|
+
}
|
|
24844
|
+
handleTask(event) {
|
|
24845
|
+
const state = this.tasksById.get(event.taskId);
|
|
24846
|
+
if (!state) {
|
|
24847
|
+
return;
|
|
24848
|
+
}
|
|
24849
|
+
safeLog3(state.span, {
|
|
24850
|
+
...event.isError ? { error: errorToString(event.result) } : {},
|
|
24851
|
+
metadata: {
|
|
24852
|
+
...state.metadata,
|
|
24853
|
+
...extractEventMetadata(event),
|
|
24854
|
+
...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
|
|
24855
|
+
},
|
|
24856
|
+
metrics: durationMsMetrics(event.durationMs),
|
|
24857
|
+
output: event.result
|
|
24858
|
+
});
|
|
24859
|
+
state.span.end();
|
|
24860
|
+
this.tasksById.delete(event.taskId);
|
|
24861
|
+
}
|
|
24862
|
+
handleCompactionStart(event) {
|
|
24863
|
+
const operationState = this.operationStateForEvent(event);
|
|
24864
|
+
const parent = operationState?.span ?? this.parentSpanForEvent(event);
|
|
24865
|
+
const metadata = {
|
|
24866
|
+
...extractEventMetadata(event),
|
|
24867
|
+
...event.reason ? { "flue.compaction_reason": event.reason } : {},
|
|
24868
|
+
provider: "flue"
|
|
24869
|
+
};
|
|
24870
|
+
const input = {
|
|
24871
|
+
...typeof event.estimatedTokens === "number" ? { estimatedTokens: event.estimatedTokens } : {},
|
|
24872
|
+
...event.reason ? { reason: event.reason } : {}
|
|
24873
|
+
};
|
|
24874
|
+
const span = startFlueSpan(parent, {
|
|
24875
|
+
name: "flue.compaction",
|
|
24876
|
+
spanAttributes: { type: "task" /* TASK */ }
|
|
24877
|
+
});
|
|
24878
|
+
safeLog3(span, {
|
|
24879
|
+
input,
|
|
24880
|
+
metadata
|
|
24881
|
+
});
|
|
24882
|
+
this.compactionsByScope.set(scopeKey(event), {
|
|
24883
|
+
input,
|
|
24884
|
+
metadata,
|
|
24885
|
+
operationState,
|
|
24886
|
+
span,
|
|
24887
|
+
startTime: getCurrentUnixTimestamp()
|
|
24888
|
+
});
|
|
24889
|
+
}
|
|
24890
|
+
handleCompaction(event) {
|
|
24891
|
+
const key = scopeKey(event);
|
|
24892
|
+
const state = this.compactionsByScope.get(key) ?? this.findCompactionState(event);
|
|
24893
|
+
if (!state) {
|
|
24894
|
+
return;
|
|
24895
|
+
}
|
|
24896
|
+
safeLog3(state.span, {
|
|
24897
|
+
metadata: {
|
|
24898
|
+
...state.metadata,
|
|
24899
|
+
...extractEventMetadata(event),
|
|
24900
|
+
...typeof event.messagesBefore === "number" ? { "flue.messages_before": event.messagesBefore } : {},
|
|
24901
|
+
...typeof event.messagesAfter === "number" ? { "flue.messages_after": event.messagesAfter } : {}
|
|
24902
|
+
},
|
|
24903
|
+
metrics: {
|
|
24904
|
+
...durationMsMetrics(event.durationMs),
|
|
24905
|
+
...metricsFromUsage(event.usage)
|
|
24906
|
+
},
|
|
24907
|
+
output: {
|
|
24908
|
+
messagesAfter: event.messagesAfter,
|
|
24909
|
+
messagesBefore: event.messagesBefore
|
|
24910
|
+
}
|
|
24911
|
+
});
|
|
24912
|
+
state.span.end();
|
|
24913
|
+
this.deleteCompactionState(state);
|
|
24914
|
+
}
|
|
24915
|
+
findCompactionState(event) {
|
|
24916
|
+
const operationState = this.operationStateForEvent(event);
|
|
24917
|
+
for (const state of this.compactionsByScope.values()) {
|
|
24918
|
+
if (operationState && state.operationState === operationState) {
|
|
24919
|
+
return state;
|
|
24920
|
+
}
|
|
24921
|
+
}
|
|
24922
|
+
return void 0;
|
|
24923
|
+
}
|
|
24924
|
+
finishCompactionsForOperation(operationState) {
|
|
24925
|
+
for (const state of [...this.compactionsByScope.values()]) {
|
|
24926
|
+
if (state.operationState !== operationState) {
|
|
24927
|
+
continue;
|
|
24928
|
+
}
|
|
24929
|
+
safeLog3(state.span, {
|
|
24930
|
+
input: state.input,
|
|
24931
|
+
metadata: state.metadata,
|
|
24932
|
+
metrics: {
|
|
24933
|
+
...buildDurationMetrics3(state.startTime)
|
|
24934
|
+
},
|
|
24935
|
+
output: { completed: true }
|
|
24936
|
+
});
|
|
24937
|
+
state.span.end();
|
|
24938
|
+
this.deleteCompactionState(state);
|
|
24939
|
+
}
|
|
24940
|
+
}
|
|
24941
|
+
deleteCompactionState(state) {
|
|
24942
|
+
for (const [key, candidate] of this.compactionsByScope) {
|
|
24943
|
+
if (candidate !== state) {
|
|
24944
|
+
continue;
|
|
24945
|
+
}
|
|
24946
|
+
this.compactionsByScope.delete(key);
|
|
24947
|
+
return;
|
|
24948
|
+
}
|
|
24949
|
+
}
|
|
24950
|
+
startSyntheticToolState(event, toolName) {
|
|
24951
|
+
const parent = this.parentSpanForEvent(event);
|
|
24952
|
+
const metadata = {
|
|
24953
|
+
...extractEventMetadata(event),
|
|
24954
|
+
...event.toolCallId ? { "flue.tool_call_id": event.toolCallId } : {},
|
|
24955
|
+
"flue.tool_name": toolName,
|
|
24956
|
+
provider: "flue"
|
|
24957
|
+
};
|
|
24958
|
+
const span = startFlueSpan(parent, {
|
|
24959
|
+
name: `tool: ${toolName}`,
|
|
24960
|
+
spanAttributes: { type: "tool" /* TOOL */ }
|
|
24961
|
+
});
|
|
24962
|
+
safeLog3(span, { metadata });
|
|
24963
|
+
return { metadata, span, startTime: getCurrentUnixTimestamp() };
|
|
24964
|
+
}
|
|
24965
|
+
operationStateForEvent(event) {
|
|
24966
|
+
if (event.operationId) {
|
|
24967
|
+
const operation = this.activeOperationsById.get(event.operationId) ?? this.promotePendingOperationForEvent(event);
|
|
24968
|
+
if (operation) {
|
|
24969
|
+
return operation;
|
|
24970
|
+
}
|
|
24971
|
+
}
|
|
24972
|
+
return this.activeOperationForEventScope(event) ?? this.pendingOperationForEventScope(event);
|
|
24973
|
+
}
|
|
24974
|
+
parentSpanForEvent(event) {
|
|
24975
|
+
if (event.operationId) {
|
|
24976
|
+
const operation = this.operationStateForEvent(event);
|
|
24977
|
+
if (operation) {
|
|
24978
|
+
return operation.span;
|
|
24979
|
+
}
|
|
24980
|
+
}
|
|
24981
|
+
if (event.taskId) {
|
|
24982
|
+
return this.tasksById.get(event.taskId)?.span;
|
|
24983
|
+
}
|
|
24984
|
+
return this.operationStateForEvent(event)?.span;
|
|
24985
|
+
}
|
|
24986
|
+
promotePendingOperationForEvent(event) {
|
|
24987
|
+
if (!event.operationId) {
|
|
24988
|
+
return void 0;
|
|
24989
|
+
}
|
|
24990
|
+
const scopePrefixes = operationScopePrefixes(event);
|
|
24991
|
+
for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
|
|
24992
|
+
if (!candidateQueue.length || !operationKeyMatchesScopes(candidateKey, scopePrefixes)) {
|
|
24993
|
+
continue;
|
|
24994
|
+
}
|
|
24995
|
+
const state = candidateQueue.shift();
|
|
24996
|
+
if (!state) {
|
|
24997
|
+
return void 0;
|
|
24998
|
+
}
|
|
24999
|
+
state.operationId = event.operationId;
|
|
25000
|
+
this.activeOperationsById.set(event.operationId, state);
|
|
25001
|
+
addScopedOperation(this.activeOperationsByScope, event, state);
|
|
25002
|
+
state.metadata = {
|
|
25003
|
+
...state.metadata,
|
|
25004
|
+
...extractEventMetadata(event),
|
|
25005
|
+
"flue.operation_id": event.operationId
|
|
25006
|
+
};
|
|
25007
|
+
safeLog3(state.span, { metadata: state.metadata });
|
|
25008
|
+
return state;
|
|
25009
|
+
}
|
|
25010
|
+
return void 0;
|
|
25011
|
+
}
|
|
25012
|
+
activeOperationForEventScope(event) {
|
|
25013
|
+
for (const scope of operationScopeNames(event)) {
|
|
25014
|
+
const operations = this.activeOperationsByScope.get(scope);
|
|
25015
|
+
if (operations?.length) {
|
|
25016
|
+
return operations[operations.length - 1];
|
|
25017
|
+
}
|
|
25018
|
+
}
|
|
25019
|
+
return void 0;
|
|
25020
|
+
}
|
|
25021
|
+
pendingOperationForEventScope(event) {
|
|
25022
|
+
const scopePrefixes = operationScopePrefixes(event);
|
|
25023
|
+
for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
|
|
25024
|
+
if (!candidateQueue.length || !operationKeyMatchesScopes(candidateKey, scopePrefixes)) {
|
|
25025
|
+
continue;
|
|
25026
|
+
}
|
|
25027
|
+
return candidateQueue[0];
|
|
25028
|
+
}
|
|
25029
|
+
return void 0;
|
|
25030
|
+
}
|
|
25031
|
+
takePendingOperationForEvent(event) {
|
|
25032
|
+
const key = operationKey(event.session, event.operationKind);
|
|
25033
|
+
const queue2 = this.pendingOperationsByKey.get(key);
|
|
25034
|
+
if (queue2?.length) {
|
|
25035
|
+
return queue2.shift();
|
|
25036
|
+
}
|
|
25037
|
+
for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
|
|
25038
|
+
if (candidateKey.endsWith(`::${event.operationKind}`) && candidateQueue.length) {
|
|
25039
|
+
return candidateQueue.shift();
|
|
25040
|
+
}
|
|
25041
|
+
}
|
|
25042
|
+
return void 0;
|
|
25043
|
+
}
|
|
25044
|
+
pendingOperationQueue(key) {
|
|
25045
|
+
const existing = this.pendingOperationsByKey.get(key);
|
|
25046
|
+
if (existing) {
|
|
25047
|
+
return existing;
|
|
25048
|
+
}
|
|
25049
|
+
const queue2 = [];
|
|
25050
|
+
this.pendingOperationsByKey.set(key, queue2);
|
|
25051
|
+
return queue2;
|
|
25052
|
+
}
|
|
25053
|
+
};
|
|
25054
|
+
function isInstrumentedOperation(operation) {
|
|
25055
|
+
return operation === "prompt" || operation === "skill" || operation === "task" || operation === "compact";
|
|
25056
|
+
}
|
|
25057
|
+
function getSessionName(session) {
|
|
25058
|
+
return typeof session?.name === "string" ? session.name : void 0;
|
|
25059
|
+
}
|
|
25060
|
+
function operationKey(sessionName, operation) {
|
|
25061
|
+
return `${sessionName ?? "unknown"}::${operation}`;
|
|
25062
|
+
}
|
|
25063
|
+
function operationScopePrefixes(event) {
|
|
25064
|
+
const scopes = /* @__PURE__ */ new Set();
|
|
25065
|
+
for (const scope of operationScopeNames(event)) {
|
|
25066
|
+
scopes.add(`${scope}::`);
|
|
25067
|
+
}
|
|
25068
|
+
return scopes;
|
|
25069
|
+
}
|
|
25070
|
+
function operationKeyMatchesScopes(key, scopes) {
|
|
25071
|
+
for (const scope of scopes) {
|
|
25072
|
+
if (key.startsWith(scope)) {
|
|
25073
|
+
return true;
|
|
25074
|
+
}
|
|
25075
|
+
}
|
|
25076
|
+
return false;
|
|
25077
|
+
}
|
|
25078
|
+
function operationScopeNames(event) {
|
|
25079
|
+
const scopes = /* @__PURE__ */ new Set();
|
|
25080
|
+
if (event.session) {
|
|
25081
|
+
scopes.add(event.session);
|
|
25082
|
+
}
|
|
25083
|
+
if (event.parentSession) {
|
|
25084
|
+
scopes.add(event.parentSession);
|
|
25085
|
+
}
|
|
25086
|
+
if (!scopes.size) {
|
|
25087
|
+
scopes.add("unknown");
|
|
25088
|
+
}
|
|
25089
|
+
return scopes;
|
|
25090
|
+
}
|
|
25091
|
+
function addScopedOperation(operationsByScope, event, state) {
|
|
25092
|
+
for (const scope of operationScopeNames(event)) {
|
|
25093
|
+
addOperationToScope(operationsByScope, scope, state);
|
|
25094
|
+
}
|
|
25095
|
+
}
|
|
25096
|
+
function addOperationToScope(operationsByScope, scope, state) {
|
|
25097
|
+
const operations = operationsByScope.get(scope);
|
|
25098
|
+
if (operations) {
|
|
25099
|
+
if (!operations.includes(state)) {
|
|
25100
|
+
operations.push(state);
|
|
25101
|
+
}
|
|
25102
|
+
} else {
|
|
25103
|
+
operationsByScope.set(scope, [state]);
|
|
25104
|
+
}
|
|
25105
|
+
}
|
|
25106
|
+
function removeScopedOperation(operationsByScope, state) {
|
|
25107
|
+
for (const [scope, operations] of operationsByScope) {
|
|
25108
|
+
const index = operations.indexOf(state);
|
|
25109
|
+
if (index === -1) {
|
|
25110
|
+
continue;
|
|
25111
|
+
}
|
|
25112
|
+
operations.splice(index, 1);
|
|
25113
|
+
if (operations.length === 0) {
|
|
25114
|
+
operationsByScope.delete(scope);
|
|
25115
|
+
}
|
|
25116
|
+
}
|
|
25117
|
+
}
|
|
25118
|
+
function removePendingOperation(pendingOperationsByKey, state) {
|
|
25119
|
+
for (const [key, queue2] of pendingOperationsByKey) {
|
|
25120
|
+
const index = queue2.indexOf(state);
|
|
25121
|
+
if (index === -1) {
|
|
25122
|
+
continue;
|
|
25123
|
+
}
|
|
25124
|
+
queue2.splice(index, 1);
|
|
25125
|
+
if (queue2.length === 0) {
|
|
25126
|
+
pendingOperationsByKey.delete(key);
|
|
25127
|
+
}
|
|
25128
|
+
return;
|
|
25129
|
+
}
|
|
25130
|
+
}
|
|
25131
|
+
function extractSessionMetadata(session) {
|
|
25132
|
+
const sessionName = getSessionName(session);
|
|
25133
|
+
return sessionName ? { "flue.session": sessionName } : {};
|
|
25134
|
+
}
|
|
25135
|
+
function extractEventMetadata(event) {
|
|
25136
|
+
return {
|
|
25137
|
+
...event.runId ? { "flue.run_id": event.runId } : {},
|
|
25138
|
+
...typeof event.eventIndex === "number" ? { "flue.event_index": event.eventIndex } : {},
|
|
25139
|
+
...event.session ? { "flue.session": event.session } : {},
|
|
25140
|
+
...event.parentSession ? { "flue.parent_session": event.parentSession } : {},
|
|
25141
|
+
...event.harness ? { "flue.harness": event.harness } : {},
|
|
25142
|
+
...event.taskId ? { "flue.task_id": event.taskId } : {},
|
|
25143
|
+
...event.operationId ? { "flue.operation_id": event.operationId } : {}
|
|
25144
|
+
};
|
|
25145
|
+
}
|
|
25146
|
+
function extractOperationInput(operation, args) {
|
|
25147
|
+
switch (operation) {
|
|
25148
|
+
case "prompt":
|
|
25149
|
+
case "task":
|
|
25150
|
+
return args[0];
|
|
25151
|
+
case "skill":
|
|
25152
|
+
return {
|
|
25153
|
+
args: getOptionObject(args[1])?.args,
|
|
25154
|
+
name: args[0]
|
|
25155
|
+
};
|
|
25156
|
+
case "compact":
|
|
25157
|
+
return void 0;
|
|
25158
|
+
}
|
|
25159
|
+
}
|
|
25160
|
+
function extractOperationInputMetadata(operation, args) {
|
|
25161
|
+
const options = getOptionObject(args[1]);
|
|
25162
|
+
return {
|
|
25163
|
+
...operation === "skill" && typeof args[0] === "string" ? { "flue.skill_name": args[0] } : {},
|
|
25164
|
+
...options?.model ? { model: options.model, "flue.model": options.model } : {},
|
|
25165
|
+
...options?.role ? { "flue.role": options.role } : {},
|
|
25166
|
+
...options?.thinkingLevel ? { "flue.thinking_level": options.thinkingLevel } : {},
|
|
25167
|
+
...typeof options?.cwd === "string" ? { "flue.cwd": options.cwd } : {},
|
|
25168
|
+
...Array.isArray(options?.tools) ? {
|
|
25169
|
+
"flue.tools_count": options.tools.length,
|
|
25170
|
+
tools: summarizeTools(options.tools)
|
|
25171
|
+
} : {},
|
|
25172
|
+
...Array.isArray(options?.images) ? { "flue.images_count": options.images.length } : {},
|
|
25173
|
+
...options?.result || options?.schema ? { "flue.result_schema": true } : {}
|
|
25174
|
+
};
|
|
25175
|
+
}
|
|
25176
|
+
function getOptionObject(value) {
|
|
25177
|
+
return isObject(value) ? value : void 0;
|
|
25178
|
+
}
|
|
25179
|
+
function summarizeTools(tools) {
|
|
25180
|
+
return tools.flatMap((tool) => {
|
|
25181
|
+
if (!isObject(tool)) {
|
|
25182
|
+
return [];
|
|
25183
|
+
}
|
|
25184
|
+
const name = typeof tool.name === "string" ? tool.name : void 0;
|
|
25185
|
+
if (!name) {
|
|
25186
|
+
return [];
|
|
25187
|
+
}
|
|
25188
|
+
return [
|
|
25189
|
+
{
|
|
25190
|
+
function: {
|
|
25191
|
+
description: typeof tool.description === "string" ? tool.description : void 0,
|
|
25192
|
+
name,
|
|
25193
|
+
parameters: tool.parameters
|
|
25194
|
+
},
|
|
25195
|
+
type: "function"
|
|
25196
|
+
}
|
|
25197
|
+
];
|
|
25198
|
+
});
|
|
25199
|
+
}
|
|
25200
|
+
function extractPromptResponseMetadata(result) {
|
|
25201
|
+
const modelId = result?.model && typeof result.model.id === "string" ? result.model.id : void 0;
|
|
25202
|
+
return modelId ? {
|
|
25203
|
+
model: modelId,
|
|
25204
|
+
"flue.model": modelId
|
|
25205
|
+
} : {};
|
|
25206
|
+
}
|
|
25207
|
+
function extractOperationOutput(result) {
|
|
25208
|
+
if (!result) {
|
|
25209
|
+
return void 0;
|
|
25210
|
+
}
|
|
25211
|
+
if ("data" in result) {
|
|
25212
|
+
return result.data;
|
|
25213
|
+
}
|
|
25214
|
+
if ("text" in result) {
|
|
25215
|
+
return result.text;
|
|
25216
|
+
}
|
|
25217
|
+
return result;
|
|
25218
|
+
}
|
|
25219
|
+
function metricsFromUsage(usage) {
|
|
25220
|
+
return {
|
|
25221
|
+
...typeof usage?.input === "number" ? { prompt_tokens: usage.input } : {},
|
|
25222
|
+
...typeof usage?.output === "number" ? { completion_tokens: usage.output } : {},
|
|
25223
|
+
...typeof usage?.cacheRead === "number" ? { prompt_cached_tokens: usage.cacheRead } : {},
|
|
25224
|
+
...typeof usage?.cacheWrite === "number" ? { prompt_cache_creation_tokens: usage.cacheWrite } : {},
|
|
25225
|
+
...typeof usage?.totalTokens === "number" ? { tokens: usage.totalTokens } : {},
|
|
25226
|
+
...typeof usage?.cost?.total === "number" ? { estimated_cost: usage.cost.total } : {}
|
|
25227
|
+
};
|
|
25228
|
+
}
|
|
25229
|
+
function buildDurationMetrics3(startTime) {
|
|
25230
|
+
return {
|
|
25231
|
+
duration_ms: Math.max(0, (getCurrentUnixTimestamp() - startTime) * 1e3)
|
|
25232
|
+
};
|
|
25233
|
+
}
|
|
25234
|
+
function durationMsMetrics(durationMs) {
|
|
25235
|
+
return typeof durationMs === "number" ? { duration_ms: durationMs } : {};
|
|
25236
|
+
}
|
|
25237
|
+
function scopeKey(event) {
|
|
25238
|
+
if (event.operationId) {
|
|
25239
|
+
return `operation:${event.operationId}`;
|
|
25240
|
+
}
|
|
25241
|
+
if (event.taskId) {
|
|
25242
|
+
return `task:${event.taskId}`;
|
|
25243
|
+
}
|
|
25244
|
+
if (event.session) {
|
|
25245
|
+
return `session:${event.session}`;
|
|
25246
|
+
}
|
|
25247
|
+
return "flue:unknown";
|
|
25248
|
+
}
|
|
25249
|
+
function toolKey(event) {
|
|
25250
|
+
return `${scopeKey(event)}::tool:${event.toolCallId ?? "unknown"}`;
|
|
25251
|
+
}
|
|
25252
|
+
function toAssistantOutput(text, finishReason, reasoning, toolCalls) {
|
|
25253
|
+
return [
|
|
25254
|
+
{
|
|
25255
|
+
finish_reason: finishReason ?? "stop",
|
|
25256
|
+
index: 0,
|
|
25257
|
+
message: {
|
|
25258
|
+
content: text,
|
|
25259
|
+
...reasoning ? { reasoning } : {},
|
|
25260
|
+
role: "assistant",
|
|
25261
|
+
...toolCalls?.length ? {
|
|
25262
|
+
tool_calls: toolCalls.map((toolCall) => ({
|
|
25263
|
+
function: {
|
|
25264
|
+
arguments: toolCall.args === void 0 ? "{}" : JSON.stringify(toolCall.args),
|
|
25265
|
+
name: toolCall.toolName ?? "unknown"
|
|
25266
|
+
},
|
|
25267
|
+
...toolCall.toolCallId ? { id: toolCall.toolCallId } : {},
|
|
25268
|
+
type: "function"
|
|
25269
|
+
}))
|
|
25270
|
+
} : {}
|
|
25271
|
+
}
|
|
25272
|
+
}
|
|
25273
|
+
];
|
|
25274
|
+
}
|
|
25275
|
+
function startFlueSpan(parent, args) {
|
|
25276
|
+
return parent ? withCurrent(parent, () => startSpan(args)) : startSpan(args);
|
|
25277
|
+
}
|
|
25278
|
+
function safeLog3(span, event) {
|
|
25279
|
+
try {
|
|
25280
|
+
span.log(event);
|
|
25281
|
+
} catch (error) {
|
|
25282
|
+
logInstrumentationError3("Flue span log", error);
|
|
25283
|
+
}
|
|
25284
|
+
}
|
|
25285
|
+
function errorToString(error) {
|
|
25286
|
+
if (error instanceof Error) {
|
|
25287
|
+
return error.message;
|
|
25288
|
+
}
|
|
25289
|
+
if (typeof error === "string") {
|
|
25290
|
+
return error;
|
|
25291
|
+
}
|
|
25292
|
+
try {
|
|
25293
|
+
return JSON.stringify(error);
|
|
25294
|
+
} catch {
|
|
25295
|
+
return String(error);
|
|
25296
|
+
}
|
|
25297
|
+
}
|
|
25298
|
+
function logInstrumentationError3(label, error) {
|
|
25299
|
+
console.error(`Error in ${label} instrumentation:`, error);
|
|
25300
|
+
}
|
|
25301
|
+
|
|
25302
|
+
// src/wrappers/langchain/callback-handler.ts
|
|
25303
|
+
var BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME = "BraintrustCallbackHandler";
|
|
25304
|
+
var BraintrustLangChainCallbackHandler = class {
|
|
25305
|
+
name = BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
|
|
25306
|
+
spans = /* @__PURE__ */ new Map();
|
|
25307
|
+
skippedRuns = /* @__PURE__ */ new Set();
|
|
25308
|
+
parent;
|
|
25309
|
+
rootRunId;
|
|
25310
|
+
options;
|
|
25311
|
+
startTimes = /* @__PURE__ */ new Map();
|
|
25312
|
+
firstTokenTimes = /* @__PURE__ */ new Map();
|
|
25313
|
+
ttftMs = /* @__PURE__ */ new Map();
|
|
25314
|
+
constructor(options) {
|
|
25315
|
+
this.parent = options?.parent;
|
|
25316
|
+
this.options = {
|
|
25317
|
+
debug: options?.debug ?? false,
|
|
25318
|
+
excludeMetadataProps: options?.excludeMetadataProps ?? /^(l[sc]_|langgraph_|__pregel_|checkpoint_ns)/,
|
|
25319
|
+
logger: options?.logger
|
|
25320
|
+
};
|
|
25321
|
+
}
|
|
25322
|
+
startSpan({
|
|
25323
|
+
runId,
|
|
25324
|
+
parentRunId,
|
|
25325
|
+
...args
|
|
25326
|
+
}) {
|
|
25327
|
+
if (this.spans.has(runId)) {
|
|
25328
|
+
return;
|
|
25329
|
+
}
|
|
25330
|
+
if (!parentRunId) {
|
|
25331
|
+
this.rootRunId = runId;
|
|
25332
|
+
}
|
|
25333
|
+
const tags = args.event?.tags;
|
|
25334
|
+
const spanAttributes = args.spanAttributes || {};
|
|
25335
|
+
spanAttributes.type = args.type || spanAttributes.type || "task";
|
|
25336
|
+
args.type = spanAttributes.type;
|
|
25337
|
+
const currentParent = (typeof this.parent === "function" ? this.parent() : this.parent) ?? currentSpan();
|
|
25338
|
+
let parentSpan;
|
|
25339
|
+
if (parentRunId && this.spans.has(parentRunId)) {
|
|
25340
|
+
parentSpan = this.spans.get(parentRunId);
|
|
25341
|
+
} else if (!Object.is(currentParent, NOOP_SPAN)) {
|
|
25342
|
+
parentSpan = currentParent;
|
|
25343
|
+
} else if (this.options.logger) {
|
|
25344
|
+
parentSpan = this.options.logger;
|
|
25345
|
+
} else {
|
|
25346
|
+
parentSpan = { startSpan };
|
|
25347
|
+
}
|
|
25348
|
+
args.event = {
|
|
25349
|
+
...args.event,
|
|
25350
|
+
tags: void 0,
|
|
25351
|
+
metadata: {
|
|
25352
|
+
...tags ? { tags } : {},
|
|
25353
|
+
...args.event?.metadata,
|
|
25354
|
+
braintrust: {
|
|
25355
|
+
integration_name: "langchain-js",
|
|
25356
|
+
sdk_language: "javascript"
|
|
25357
|
+
},
|
|
25358
|
+
run_id: runId,
|
|
25359
|
+
parent_run_id: parentRunId,
|
|
25360
|
+
...this.options.debug ? { runId, parentRunId } : {}
|
|
25361
|
+
}
|
|
25362
|
+
};
|
|
25363
|
+
let span = parentSpan.startSpan(args);
|
|
25364
|
+
if (!Object.is(this.options.logger, NOOP_SPAN) && Object.is(span, NOOP_SPAN)) {
|
|
25365
|
+
span = initLogger().startSpan(args);
|
|
25366
|
+
}
|
|
25367
|
+
this.spans.set(runId, span);
|
|
25368
|
+
}
|
|
25369
|
+
endSpan({
|
|
25370
|
+
runId,
|
|
25371
|
+
parentRunId,
|
|
25372
|
+
tags,
|
|
25373
|
+
metadata,
|
|
25374
|
+
...args
|
|
25375
|
+
}) {
|
|
25376
|
+
if (!this.spans.has(runId)) {
|
|
25377
|
+
return;
|
|
25378
|
+
}
|
|
25379
|
+
if (this.skippedRuns.has(runId)) {
|
|
25380
|
+
this.skippedRuns.delete(runId);
|
|
25381
|
+
return;
|
|
25382
|
+
}
|
|
25383
|
+
const span = this.spans.get(runId);
|
|
25384
|
+
this.spans.delete(runId);
|
|
25385
|
+
if (runId === this.rootRunId) {
|
|
25386
|
+
this.rootRunId = void 0;
|
|
25387
|
+
}
|
|
25388
|
+
span.log({ ...args, metadata: { tags, ...metadata } });
|
|
25389
|
+
span.end();
|
|
25390
|
+
}
|
|
25391
|
+
async handleLLMStart(llm, prompts, runId, parentRunId, extraParams, tags, metadata, runName) {
|
|
25392
|
+
this.startSpan({
|
|
25393
|
+
runId,
|
|
25394
|
+
parentRunId,
|
|
25395
|
+
name: runName ?? getSerializedName(llm) ?? "LLM",
|
|
25396
|
+
type: "llm",
|
|
25397
|
+
event: {
|
|
25398
|
+
input: prompts,
|
|
25399
|
+
tags,
|
|
25400
|
+
metadata: {
|
|
25401
|
+
serialized: llm,
|
|
25402
|
+
name: runName,
|
|
25403
|
+
metadata,
|
|
25404
|
+
...extraParams
|
|
25405
|
+
}
|
|
25406
|
+
}
|
|
25407
|
+
});
|
|
25408
|
+
}
|
|
25409
|
+
async handleLLMError(err, runId, parentRunId, tags) {
|
|
25410
|
+
this.endSpan({ runId, parentRunId, error: err, tags });
|
|
25411
|
+
}
|
|
25412
|
+
async handleLLMEnd(output, runId, parentRunId, tags) {
|
|
25413
|
+
const metrics = getMetricsFromResponse(output);
|
|
25414
|
+
const modelName2 = getModelNameFromResponse(output);
|
|
25415
|
+
const ttft = this.ttftMs.get(runId);
|
|
25416
|
+
if (ttft !== void 0) {
|
|
25417
|
+
metrics.time_to_first_token = ttft;
|
|
25418
|
+
}
|
|
25419
|
+
this.startTimes.delete(runId);
|
|
25420
|
+
this.firstTokenTimes.delete(runId);
|
|
25421
|
+
this.ttftMs.delete(runId);
|
|
25422
|
+
this.endSpan({
|
|
25423
|
+
runId,
|
|
25424
|
+
parentRunId,
|
|
25425
|
+
output,
|
|
25426
|
+
metrics,
|
|
25427
|
+
tags,
|
|
25428
|
+
metadata: {
|
|
25429
|
+
model: modelName2
|
|
25430
|
+
}
|
|
25431
|
+
});
|
|
25432
|
+
}
|
|
25433
|
+
async handleChatModelStart(llm, messages, runId, parentRunId, extraParams, tags, metadata, runName) {
|
|
25434
|
+
this.startTimes.set(runId, Date.now());
|
|
25435
|
+
this.firstTokenTimes.delete(runId);
|
|
25436
|
+
this.ttftMs.delete(runId);
|
|
25437
|
+
this.startSpan({
|
|
25438
|
+
runId,
|
|
25439
|
+
parentRunId,
|
|
25440
|
+
name: runName ?? getSerializedName(llm) ?? "Chat Model",
|
|
25441
|
+
type: "llm",
|
|
25442
|
+
event: {
|
|
25443
|
+
input: messages,
|
|
25444
|
+
tags,
|
|
25445
|
+
metadata: {
|
|
25446
|
+
serialized: llm,
|
|
25447
|
+
name: runName,
|
|
25448
|
+
metadata,
|
|
25449
|
+
...extraParams
|
|
25450
|
+
}
|
|
25451
|
+
}
|
|
25452
|
+
});
|
|
25453
|
+
}
|
|
25454
|
+
async handleChainStart(chain, inputs, runId, parentRunId, tags, metadata, runType, runName) {
|
|
25455
|
+
if (tags?.includes("langsmith:hidden")) {
|
|
25456
|
+
this.skippedRuns.add(runId);
|
|
25457
|
+
return;
|
|
25458
|
+
}
|
|
25459
|
+
this.startSpan({
|
|
25460
|
+
runId,
|
|
25461
|
+
parentRunId,
|
|
25462
|
+
name: runName ?? getSerializedName(chain) ?? "Chain",
|
|
25463
|
+
event: {
|
|
25464
|
+
input: inputs,
|
|
25465
|
+
tags,
|
|
25466
|
+
metadata: {
|
|
25467
|
+
serialized: chain,
|
|
25468
|
+
name: runName,
|
|
25469
|
+
metadata,
|
|
25470
|
+
run_type: runType
|
|
25471
|
+
}
|
|
25472
|
+
}
|
|
25473
|
+
});
|
|
25474
|
+
}
|
|
25475
|
+
async handleChainError(err, runId, parentRunId, tags, kwargs) {
|
|
25476
|
+
this.endSpan({ runId, parentRunId, error: err, tags, metadata: kwargs });
|
|
25477
|
+
}
|
|
25478
|
+
async handleChainEnd(outputs, runId, parentRunId, tags, kwargs) {
|
|
25479
|
+
this.endSpan({
|
|
25480
|
+
runId,
|
|
25481
|
+
parentRunId,
|
|
25482
|
+
tags,
|
|
25483
|
+
output: outputs,
|
|
25484
|
+
metadata: { ...kwargs }
|
|
25485
|
+
});
|
|
25486
|
+
}
|
|
25487
|
+
async handleToolStart(tool, input, runId, parentRunId, tags, metadata, runName) {
|
|
25488
|
+
this.startSpan({
|
|
25489
|
+
runId,
|
|
25490
|
+
parentRunId,
|
|
25491
|
+
name: runName ?? getSerializedName(tool) ?? "Tool",
|
|
25492
|
+
type: "llm",
|
|
25493
|
+
event: {
|
|
25494
|
+
input: safeJsonParse(input),
|
|
25495
|
+
tags,
|
|
25496
|
+
metadata: {
|
|
25497
|
+
metadata,
|
|
25498
|
+
serialized: tool,
|
|
25499
|
+
input_str: input,
|
|
25500
|
+
input: safeJsonParse(input),
|
|
25501
|
+
name: runName
|
|
25502
|
+
}
|
|
25503
|
+
}
|
|
25504
|
+
});
|
|
25505
|
+
}
|
|
25506
|
+
async handleToolError(err, runId, parentRunId, tags) {
|
|
25507
|
+
this.endSpan({ runId, parentRunId, error: err, tags });
|
|
25508
|
+
}
|
|
25509
|
+
async handleToolEnd(output, runId, parentRunId, tags) {
|
|
25510
|
+
this.endSpan({ runId, parentRunId, output, tags });
|
|
25511
|
+
}
|
|
25512
|
+
async handleAgentAction(action, runId, parentRunId, tags) {
|
|
25513
|
+
this.startSpan({
|
|
25514
|
+
runId,
|
|
25515
|
+
parentRunId,
|
|
25516
|
+
type: "llm",
|
|
25517
|
+
name: typeof action.tool === "string" ? action.tool : "Agent",
|
|
25518
|
+
event: {
|
|
25519
|
+
input: action,
|
|
25520
|
+
tags
|
|
25521
|
+
}
|
|
25522
|
+
});
|
|
25523
|
+
}
|
|
25524
|
+
async handleAgentEnd(action, runId, parentRunId, tags) {
|
|
25525
|
+
this.endSpan({ runId, parentRunId, output: action, tags });
|
|
25526
|
+
}
|
|
25527
|
+
async handleRetrieverStart(retriever, query, runId, parentRunId, tags, metadata, name) {
|
|
25528
|
+
this.startSpan({
|
|
25529
|
+
runId,
|
|
25530
|
+
parentRunId,
|
|
25531
|
+
name: name ?? getSerializedName(retriever) ?? "Retriever",
|
|
25532
|
+
type: "function",
|
|
25533
|
+
event: {
|
|
25534
|
+
input: query,
|
|
25535
|
+
tags,
|
|
25536
|
+
metadata: {
|
|
25537
|
+
serialized: retriever,
|
|
25538
|
+
metadata,
|
|
25539
|
+
name
|
|
25540
|
+
}
|
|
25541
|
+
}
|
|
25542
|
+
});
|
|
25543
|
+
}
|
|
25544
|
+
async handleRetrieverEnd(documents, runId, parentRunId, tags) {
|
|
25545
|
+
this.endSpan({ runId, parentRunId, output: documents, tags });
|
|
25546
|
+
}
|
|
25547
|
+
async handleRetrieverError(err, runId, parentRunId, tags) {
|
|
25548
|
+
this.endSpan({ runId, parentRunId, error: err, tags });
|
|
25549
|
+
}
|
|
25550
|
+
async handleLLMNewToken(_token, _idx, runId, _parentRunId, _tags) {
|
|
25551
|
+
if (!this.firstTokenTimes.has(runId)) {
|
|
25552
|
+
const now2 = Date.now();
|
|
25553
|
+
this.firstTokenTimes.set(runId, now2);
|
|
25554
|
+
const start = this.startTimes.get(runId);
|
|
25555
|
+
if (start !== void 0) {
|
|
25556
|
+
this.ttftMs.set(runId, (now2 - start) / 1e3);
|
|
25557
|
+
}
|
|
25558
|
+
}
|
|
25559
|
+
}
|
|
25560
|
+
};
|
|
25561
|
+
function getSerializedName(serialized) {
|
|
25562
|
+
if (typeof serialized.name === "string") {
|
|
25563
|
+
return serialized.name;
|
|
25564
|
+
}
|
|
25565
|
+
const lastIdPart = serialized.id?.at(-1);
|
|
25566
|
+
return typeof lastIdPart === "string" ? lastIdPart : void 0;
|
|
25567
|
+
}
|
|
25568
|
+
function cleanObject(obj) {
|
|
25569
|
+
return Object.fromEntries(
|
|
25570
|
+
Object.entries(obj).filter(([, value]) => {
|
|
25571
|
+
if (typeof value !== "number") {
|
|
25572
|
+
return false;
|
|
25573
|
+
}
|
|
25574
|
+
return Number.isFinite(value);
|
|
25575
|
+
})
|
|
25576
|
+
);
|
|
25577
|
+
}
|
|
25578
|
+
function walkGenerations(response) {
|
|
25579
|
+
const result = [];
|
|
25580
|
+
const generations = response.generations || [];
|
|
25581
|
+
for (const batch of generations) {
|
|
25582
|
+
if (Array.isArray(batch)) {
|
|
25583
|
+
for (const generation of batch) {
|
|
25584
|
+
if (isRecord(generation)) {
|
|
25585
|
+
result.push(generation);
|
|
25586
|
+
}
|
|
25587
|
+
}
|
|
25588
|
+
} else if (isRecord(batch)) {
|
|
25589
|
+
result.push(batch);
|
|
25590
|
+
}
|
|
25591
|
+
}
|
|
25592
|
+
return result;
|
|
25593
|
+
}
|
|
25594
|
+
function getModelNameFromResponse(response) {
|
|
25595
|
+
for (const generation of walkGenerations(response)) {
|
|
25596
|
+
const message = generation.message;
|
|
25597
|
+
if (!isRecord(message)) {
|
|
25598
|
+
continue;
|
|
25599
|
+
}
|
|
25600
|
+
const responseMetadata = message.response_metadata;
|
|
25601
|
+
if (!isRecord(responseMetadata)) {
|
|
25602
|
+
continue;
|
|
25603
|
+
}
|
|
25604
|
+
const modelName3 = responseMetadata.model_name ?? responseMetadata.model;
|
|
25605
|
+
if (typeof modelName3 === "string") {
|
|
25606
|
+
return modelName3;
|
|
25607
|
+
}
|
|
25608
|
+
}
|
|
25609
|
+
const llmOutput = response.llmOutput || {};
|
|
25610
|
+
const modelName2 = llmOutput.model_name ?? llmOutput.model;
|
|
25611
|
+
return typeof modelName2 === "string" ? modelName2 : void 0;
|
|
25612
|
+
}
|
|
25613
|
+
function getMetricsFromResponse(response) {
|
|
25614
|
+
for (const generation of walkGenerations(response)) {
|
|
25615
|
+
const message = generation.message;
|
|
25616
|
+
if (!isRecord(message)) {
|
|
25617
|
+
continue;
|
|
25618
|
+
}
|
|
25619
|
+
const usageMetadata = message.usage_metadata;
|
|
25620
|
+
if (!isRecord(usageMetadata)) {
|
|
25621
|
+
continue;
|
|
25622
|
+
}
|
|
25623
|
+
const inputTokenDetails = usageMetadata.input_token_details;
|
|
25624
|
+
return cleanObject({
|
|
25625
|
+
total_tokens: usageMetadata.total_tokens,
|
|
25626
|
+
prompt_tokens: usageMetadata.input_tokens,
|
|
25627
|
+
completion_tokens: usageMetadata.output_tokens,
|
|
25628
|
+
prompt_cache_creation_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_creation : void 0,
|
|
25629
|
+
prompt_cached_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_read : void 0
|
|
25630
|
+
});
|
|
25631
|
+
}
|
|
25632
|
+
const llmOutput = response.llmOutput || {};
|
|
25633
|
+
const tokenUsage = isRecord(llmOutput.tokenUsage) ? llmOutput.tokenUsage : isRecord(llmOutput.estimatedTokens) ? llmOutput.estimatedTokens : {};
|
|
25634
|
+
return cleanObject({
|
|
25635
|
+
total_tokens: tokenUsage.totalTokens,
|
|
25636
|
+
prompt_tokens: tokenUsage.promptTokens,
|
|
25637
|
+
completion_tokens: tokenUsage.completionTokens
|
|
25638
|
+
});
|
|
25639
|
+
}
|
|
25640
|
+
function safeJsonParse(input) {
|
|
25641
|
+
try {
|
|
25642
|
+
return JSON.parse(input);
|
|
25643
|
+
} catch {
|
|
25644
|
+
return input;
|
|
25645
|
+
}
|
|
25646
|
+
}
|
|
25647
|
+
function isRecord(value) {
|
|
25648
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
25649
|
+
}
|
|
25650
|
+
|
|
25651
|
+
// src/instrumentation/plugins/langchain-channels.ts
|
|
25652
|
+
var langChainChannels = defineChannels("@langchain/core", {
|
|
25653
|
+
configure: channel({
|
|
25654
|
+
channelName: "CallbackManager.configure",
|
|
25655
|
+
kind: "sync-stream"
|
|
25656
|
+
}),
|
|
25657
|
+
configureSync: channel({
|
|
25658
|
+
channelName: "CallbackManager._configureSync",
|
|
25659
|
+
kind: "sync-stream"
|
|
25660
|
+
})
|
|
25661
|
+
});
|
|
25662
|
+
|
|
25663
|
+
// src/instrumentation/plugins/langchain-plugin.ts
|
|
25664
|
+
var LangChainPlugin = class extends BasePlugin {
|
|
25665
|
+
injectedManagers = /* @__PURE__ */ new WeakSet();
|
|
25666
|
+
onEnable() {
|
|
25667
|
+
this.subscribeToConfigure(langChainChannels.configure);
|
|
25668
|
+
this.subscribeToConfigure(langChainChannels.configureSync);
|
|
25669
|
+
}
|
|
25670
|
+
onDisable() {
|
|
25671
|
+
for (const unsubscribe of this.unsubscribers) {
|
|
25672
|
+
unsubscribe();
|
|
25673
|
+
}
|
|
25674
|
+
this.unsubscribers = [];
|
|
25675
|
+
this.injectedManagers = /* @__PURE__ */ new WeakSet();
|
|
25676
|
+
}
|
|
25677
|
+
subscribeToConfigure(channel2) {
|
|
25678
|
+
const tracingChannel2 = channel2.tracingChannel();
|
|
25679
|
+
const handlers = {
|
|
25680
|
+
start: (event) => {
|
|
25681
|
+
injectHandlerIntoArguments(event.arguments);
|
|
25682
|
+
},
|
|
25683
|
+
end: (event) => {
|
|
25684
|
+
this.injectHandler(event.result);
|
|
25685
|
+
}
|
|
25686
|
+
};
|
|
25687
|
+
tracingChannel2.subscribe(handlers);
|
|
25688
|
+
this.unsubscribers.push(() => {
|
|
25689
|
+
tracingChannel2.unsubscribe(handlers);
|
|
25690
|
+
});
|
|
25691
|
+
}
|
|
25692
|
+
injectHandler(result) {
|
|
25693
|
+
if (!isCallbackManager(result)) {
|
|
25694
|
+
return;
|
|
25695
|
+
}
|
|
25696
|
+
if (this.injectedManagers.has(result) || hasBraintrustHandler(result)) {
|
|
25697
|
+
return;
|
|
25698
|
+
}
|
|
25699
|
+
try {
|
|
25700
|
+
result.addHandler(new BraintrustLangChainCallbackHandler(), true);
|
|
25701
|
+
this.injectedManagers.add(result);
|
|
25702
|
+
} catch {
|
|
25703
|
+
}
|
|
25704
|
+
}
|
|
25705
|
+
};
|
|
25706
|
+
function isCallbackManager(value) {
|
|
25707
|
+
if (typeof value !== "object" || value === null) {
|
|
25708
|
+
return false;
|
|
25709
|
+
}
|
|
25710
|
+
const maybeManager = value;
|
|
25711
|
+
return typeof maybeManager.addHandler === "function";
|
|
25712
|
+
}
|
|
25713
|
+
function hasBraintrustHandler(manager) {
|
|
25714
|
+
return manager.handlers?.some((handler) => {
|
|
25715
|
+
if (typeof handler !== "object" || handler === null) {
|
|
25716
|
+
return false;
|
|
25717
|
+
}
|
|
25718
|
+
const name = Reflect.get(handler, "name");
|
|
25719
|
+
return name === BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
|
|
25720
|
+
}) ?? false;
|
|
25721
|
+
}
|
|
25722
|
+
function injectHandlerIntoArguments(args) {
|
|
25723
|
+
if (!isWritableArgumentsObject(args)) {
|
|
25724
|
+
return;
|
|
25725
|
+
}
|
|
25726
|
+
const inheritedHandlers = Reflect.get(args, "0");
|
|
25727
|
+
const handler = new BraintrustLangChainCallbackHandler();
|
|
25728
|
+
if (inheritedHandlers === void 0 || inheritedHandlers === null) {
|
|
25729
|
+
Reflect.set(args, "0", [handler]);
|
|
25730
|
+
return;
|
|
25731
|
+
}
|
|
25732
|
+
if (Array.isArray(inheritedHandlers)) {
|
|
25733
|
+
if (!inheritedHandlers.some(isBraintrustHandler)) {
|
|
25734
|
+
inheritedHandlers.push(handler);
|
|
25735
|
+
}
|
|
25736
|
+
}
|
|
25737
|
+
}
|
|
25738
|
+
function isWritableArgumentsObject(args) {
|
|
25739
|
+
return typeof args === "object" && args !== null;
|
|
25740
|
+
}
|
|
25741
|
+
function isBraintrustHandler(handler) {
|
|
25742
|
+
if (typeof handler !== "object" || handler === null) {
|
|
25743
|
+
return false;
|
|
25744
|
+
}
|
|
25745
|
+
return Reflect.get(handler, "name") === BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
|
|
25746
|
+
}
|
|
25747
|
+
|
|
25748
|
+
// src/instrumentation/braintrust-plugin.ts
|
|
25749
|
+
function getIntegrationConfig(integrations, key) {
|
|
25750
|
+
return integrations[key];
|
|
25751
|
+
}
|
|
25752
|
+
var BraintrustPlugin = class extends BasePlugin {
|
|
25753
|
+
config;
|
|
25754
|
+
openaiPlugin = null;
|
|
25755
|
+
openAICodexPlugin = null;
|
|
25756
|
+
anthropicPlugin = null;
|
|
25757
|
+
aiSDKPlugin = null;
|
|
25758
|
+
claudeAgentSDKPlugin = null;
|
|
25759
|
+
cursorSDKPlugin = null;
|
|
25760
|
+
openAIAgentsPlugin = null;
|
|
25761
|
+
googleGenAIPlugin = null;
|
|
25762
|
+
huggingFacePlugin = null;
|
|
25763
|
+
openRouterPlugin = null;
|
|
25764
|
+
openRouterAgentPlugin = null;
|
|
25765
|
+
mistralPlugin = null;
|
|
25766
|
+
googleADKPlugin = null;
|
|
25767
|
+
coherePlugin = null;
|
|
25768
|
+
groqPlugin = null;
|
|
25769
|
+
genkitPlugin = null;
|
|
25770
|
+
gitHubCopilotPlugin = null;
|
|
25771
|
+
fluePlugin = null;
|
|
25772
|
+
langChainPlugin = null;
|
|
25773
|
+
constructor(config = {}) {
|
|
25774
|
+
super();
|
|
25775
|
+
this.config = config;
|
|
25776
|
+
}
|
|
25777
|
+
onEnable() {
|
|
25778
|
+
const integrations = this.config.integrations || {};
|
|
25779
|
+
if (integrations.openai !== false) {
|
|
25780
|
+
this.openaiPlugin = new OpenAIPlugin();
|
|
25781
|
+
this.openaiPlugin.enable();
|
|
25782
|
+
}
|
|
25783
|
+
if (integrations.openaiCodexSDK !== false) {
|
|
25784
|
+
this.openAICodexPlugin = new OpenAICodexPlugin();
|
|
25785
|
+
this.openAICodexPlugin.enable();
|
|
25786
|
+
}
|
|
25787
|
+
if (integrations.anthropic !== false) {
|
|
25788
|
+
this.anthropicPlugin = new AnthropicPlugin();
|
|
25789
|
+
this.anthropicPlugin.enable();
|
|
25790
|
+
}
|
|
25791
|
+
if (integrations.aisdk !== false && integrations.vercel !== false) {
|
|
25792
|
+
this.aiSDKPlugin = new AISDKPlugin();
|
|
25793
|
+
this.aiSDKPlugin.enable();
|
|
25794
|
+
}
|
|
25795
|
+
if (integrations.claudeAgentSDK !== false) {
|
|
25796
|
+
this.claudeAgentSDKPlugin = new ClaudeAgentSDKPlugin();
|
|
23579
25797
|
this.claudeAgentSDKPlugin.enable();
|
|
23580
25798
|
}
|
|
23581
25799
|
if (integrations.cursorSDK !== false && integrations.cursor !== false) {
|
|
23582
25800
|
this.cursorSDKPlugin = new CursorSDKPlugin();
|
|
23583
25801
|
this.cursorSDKPlugin.enable();
|
|
23584
25802
|
}
|
|
25803
|
+
if (integrations.openAIAgents !== false) {
|
|
25804
|
+
this.openAIAgentsPlugin = new OpenAIAgentsPlugin();
|
|
25805
|
+
this.openAIAgentsPlugin.enable();
|
|
25806
|
+
}
|
|
23585
25807
|
if (integrations.googleGenAI !== false && integrations.google !== false) {
|
|
23586
25808
|
this.googleGenAIPlugin = new GoogleGenAIPlugin();
|
|
23587
25809
|
this.googleGenAIPlugin.enable();
|
|
@@ -23622,6 +25844,14 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
23622
25844
|
this.gitHubCopilotPlugin = new GitHubCopilotPlugin();
|
|
23623
25845
|
this.gitHubCopilotPlugin.enable();
|
|
23624
25846
|
}
|
|
25847
|
+
if (getIntegrationConfig(integrations, "flue") !== false) {
|
|
25848
|
+
this.fluePlugin = new FluePlugin();
|
|
25849
|
+
this.fluePlugin.enable();
|
|
25850
|
+
}
|
|
25851
|
+
if (integrations.langchain !== false && integrations.langgraph !== false) {
|
|
25852
|
+
this.langChainPlugin = new LangChainPlugin();
|
|
25853
|
+
this.langChainPlugin.enable();
|
|
25854
|
+
}
|
|
23625
25855
|
}
|
|
23626
25856
|
onDisable() {
|
|
23627
25857
|
if (this.openaiPlugin) {
|
|
@@ -23648,6 +25878,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
23648
25878
|
this.cursorSDKPlugin.disable();
|
|
23649
25879
|
this.cursorSDKPlugin = null;
|
|
23650
25880
|
}
|
|
25881
|
+
if (this.openAIAgentsPlugin) {
|
|
25882
|
+
this.openAIAgentsPlugin.disable();
|
|
25883
|
+
this.openAIAgentsPlugin = null;
|
|
25884
|
+
}
|
|
23651
25885
|
if (this.googleGenAIPlugin) {
|
|
23652
25886
|
this.googleGenAIPlugin.disable();
|
|
23653
25887
|
this.googleGenAIPlugin = null;
|
|
@@ -23688,9 +25922,104 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
23688
25922
|
this.gitHubCopilotPlugin.disable();
|
|
23689
25923
|
this.gitHubCopilotPlugin = null;
|
|
23690
25924
|
}
|
|
25925
|
+
if (this.fluePlugin) {
|
|
25926
|
+
this.fluePlugin.disable();
|
|
25927
|
+
this.fluePlugin = null;
|
|
25928
|
+
}
|
|
25929
|
+
if (this.langChainPlugin) {
|
|
25930
|
+
this.langChainPlugin.disable();
|
|
25931
|
+
this.langChainPlugin = null;
|
|
25932
|
+
}
|
|
23691
25933
|
}
|
|
23692
25934
|
};
|
|
23693
25935
|
|
|
25936
|
+
// src/instrumentation/config.ts
|
|
25937
|
+
var envIntegrationAliases = {
|
|
25938
|
+
openai: "openai",
|
|
25939
|
+
"openai-codex": "openaiCodexSDK",
|
|
25940
|
+
"openai-codex-sdk": "openaiCodexSDK",
|
|
25941
|
+
openaicodexsdk: "openaiCodexSDK",
|
|
25942
|
+
codex: "openaiCodexSDK",
|
|
25943
|
+
"codex-sdk": "openaiCodexSDK",
|
|
25944
|
+
anthropic: "anthropic",
|
|
25945
|
+
aisdk: "aisdk",
|
|
25946
|
+
"ai-sdk": "aisdk",
|
|
25947
|
+
"vercel-ai": "aisdk",
|
|
25948
|
+
vercel: "vercel",
|
|
25949
|
+
claudeagentsdk: "claudeAgentSDK",
|
|
25950
|
+
"claude-agent-sdk": "claudeAgentSDK",
|
|
25951
|
+
cursor: "cursor",
|
|
25952
|
+
"cursor-sdk": "cursorSDK",
|
|
25953
|
+
cursorsdk: "cursorSDK",
|
|
25954
|
+
flue: "flue",
|
|
25955
|
+
"flue-runtime": "flue",
|
|
25956
|
+
"openai-agents": "openAIAgents",
|
|
25957
|
+
openaiagents: "openAIAgents",
|
|
25958
|
+
"openai-agents-core": "openAIAgents",
|
|
25959
|
+
openaiagentscore: "openAIAgents",
|
|
25960
|
+
google: "google",
|
|
25961
|
+
"google-genai": "googleGenAI",
|
|
25962
|
+
googlegenai: "googleGenAI",
|
|
25963
|
+
huggingface: "huggingface",
|
|
25964
|
+
openrouter: "openrouter",
|
|
25965
|
+
openrouteragent: "openrouterAgent",
|
|
25966
|
+
"openrouter-agent": "openrouterAgent",
|
|
25967
|
+
mistral: "mistral",
|
|
25968
|
+
googleadk: "googleADK",
|
|
25969
|
+
"google-adk": "googleADK",
|
|
25970
|
+
cohere: "cohere",
|
|
25971
|
+
groq: "groq",
|
|
25972
|
+
"groq-sdk": "groq",
|
|
25973
|
+
genkit: "genkit",
|
|
25974
|
+
"firebase-genkit": "genkit",
|
|
25975
|
+
githubcopilot: "gitHubCopilot",
|
|
25976
|
+
"github-copilot": "gitHubCopilot",
|
|
25977
|
+
"copilot-sdk": "gitHubCopilot",
|
|
25978
|
+
langchain: "langchain",
|
|
25979
|
+
"langchain-js": "langchain",
|
|
25980
|
+
"@langchain": "langchain",
|
|
25981
|
+
langgraph: "langgraph"
|
|
25982
|
+
};
|
|
25983
|
+
function getDefaultInstrumentationIntegrations() {
|
|
25984
|
+
return {
|
|
25985
|
+
openai: true,
|
|
25986
|
+
openaiCodexSDK: true,
|
|
25987
|
+
anthropic: true,
|
|
25988
|
+
vercel: true,
|
|
25989
|
+
aisdk: true,
|
|
25990
|
+
google: true,
|
|
25991
|
+
googleGenAI: true,
|
|
25992
|
+
googleADK: true,
|
|
25993
|
+
huggingface: true,
|
|
25994
|
+
claudeAgentSDK: true,
|
|
25995
|
+
cursor: true,
|
|
25996
|
+
cursorSDK: true,
|
|
25997
|
+
flue: true,
|
|
25998
|
+
openAIAgents: true,
|
|
25999
|
+
openrouter: true,
|
|
26000
|
+
openrouterAgent: true,
|
|
26001
|
+
mistral: true,
|
|
26002
|
+
cohere: true,
|
|
26003
|
+
groq: true,
|
|
26004
|
+
genkit: true,
|
|
26005
|
+
gitHubCopilot: true,
|
|
26006
|
+
langchain: true,
|
|
26007
|
+
langgraph: true
|
|
26008
|
+
};
|
|
26009
|
+
}
|
|
26010
|
+
function readDisabledInstrumentationEnvConfig(disabledList) {
|
|
26011
|
+
const integrations = {};
|
|
26012
|
+
if (disabledList) {
|
|
26013
|
+
for (const value of disabledList.split(",")) {
|
|
26014
|
+
const sdk = value.trim().toLowerCase();
|
|
26015
|
+
if (sdk.length > 0) {
|
|
26016
|
+
integrations[envIntegrationAliases[sdk] ?? sdk] = false;
|
|
26017
|
+
}
|
|
26018
|
+
}
|
|
26019
|
+
}
|
|
26020
|
+
return { integrations };
|
|
26021
|
+
}
|
|
26022
|
+
|
|
23694
26023
|
// src/instrumentation/registry.ts
|
|
23695
26024
|
var REGISTRY_STATE_KEY = /* @__PURE__ */ Symbol.for("braintrust.registry");
|
|
23696
26025
|
function getSharedState() {
|
|
@@ -23769,50 +26098,16 @@ var PluginRegistry = class {
|
|
|
23769
26098
|
* Get default configuration (all integrations enabled).
|
|
23770
26099
|
*/
|
|
23771
26100
|
getDefaultConfig() {
|
|
23772
|
-
return
|
|
23773
|
-
openai: true,
|
|
23774
|
-
openaiCodexSDK: true,
|
|
23775
|
-
anthropic: true,
|
|
23776
|
-
vercel: true,
|
|
23777
|
-
aisdk: true,
|
|
23778
|
-
google: true,
|
|
23779
|
-
googleGenAI: true,
|
|
23780
|
-
googleADK: true,
|
|
23781
|
-
huggingface: true,
|
|
23782
|
-
claudeAgentSDK: true,
|
|
23783
|
-
cursor: true,
|
|
23784
|
-
cursorSDK: true,
|
|
23785
|
-
openrouter: true,
|
|
23786
|
-
openrouterAgent: true,
|
|
23787
|
-
mistral: true,
|
|
23788
|
-
cohere: true,
|
|
23789
|
-
groq: true,
|
|
23790
|
-
genkit: true,
|
|
23791
|
-
gitHubCopilot: true
|
|
23792
|
-
};
|
|
26101
|
+
return getDefaultInstrumentationIntegrations();
|
|
23793
26102
|
}
|
|
23794
26103
|
/**
|
|
23795
26104
|
* Read configuration from environment variables.
|
|
23796
26105
|
* Supports: BRAINTRUST_DISABLE_INSTRUMENTATION=openai,anthropic,...
|
|
23797
26106
|
*/
|
|
23798
26107
|
readEnvConfig() {
|
|
23799
|
-
|
|
23800
|
-
|
|
23801
|
-
|
|
23802
|
-
const disabled = disabledList.split(",").map((s) => s.trim().toLowerCase()).filter((s) => s.length > 0);
|
|
23803
|
-
for (const sdk of disabled) {
|
|
23804
|
-
if (sdk === "cursor-sdk") {
|
|
23805
|
-
integrations.cursorSDK = false;
|
|
23806
|
-
} else if (sdk === "githubcopilot" || sdk === "github-copilot" || sdk === "copilot-sdk") {
|
|
23807
|
-
integrations.gitHubCopilot = false;
|
|
23808
|
-
} else if (sdk === "openai-codex-sdk") {
|
|
23809
|
-
integrations.openaiCodexSDK = false;
|
|
23810
|
-
} else {
|
|
23811
|
-
integrations[sdk] = false;
|
|
23812
|
-
}
|
|
23813
|
-
}
|
|
23814
|
-
}
|
|
23815
|
-
return { integrations };
|
|
26108
|
+
return readDisabledInstrumentationEnvConfig(
|
|
26109
|
+
isomorph_default.getEnv("BRAINTRUST_DISABLE_INSTRUMENTATION")
|
|
26110
|
+
);
|
|
23816
26111
|
}
|
|
23817
26112
|
};
|
|
23818
26113
|
var registry = new PluginRegistry();
|
|
@@ -23927,6 +26222,10 @@ function configureBrowser() {
|
|
|
23927
26222
|
}
|
|
23928
26223
|
return process.env[name];
|
|
23929
26224
|
};
|
|
26225
|
+
isomorph_default.getBraintrustApiKey = async () => {
|
|
26226
|
+
const value = isomorph_default.getEnv("BRAINTRUST_API_KEY");
|
|
26227
|
+
return value?.trim() ? value : void 0;
|
|
26228
|
+
};
|
|
23930
26229
|
isomorph_default.hash = (data) => {
|
|
23931
26230
|
let hash = 0;
|
|
23932
26231
|
for (let i = 0; i < data.length; i++) {
|
|
@@ -23948,8 +26247,10 @@ __export(exports_exports, {
|
|
|
23948
26247
|
Attachment: () => Attachment,
|
|
23949
26248
|
AttachmentReference: () => AttachmentReference,
|
|
23950
26249
|
BRAINTRUST_CURRENT_SPAN_STORE: () => BRAINTRUST_CURRENT_SPAN_STORE,
|
|
26250
|
+
BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME: () => BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME,
|
|
23951
26251
|
BaseAttachment: () => BaseAttachment,
|
|
23952
26252
|
BaseExperiment: () => BaseExperiment,
|
|
26253
|
+
BraintrustLangChainCallbackHandler: () => BraintrustLangChainCallbackHandler,
|
|
23953
26254
|
BraintrustMiddleware: () => BraintrustMiddleware,
|
|
23954
26255
|
BraintrustState: () => BraintrustState,
|
|
23955
26256
|
BraintrustStream: () => BraintrustStream,
|
|
@@ -23960,6 +26261,7 @@ __export(exports_exports, {
|
|
|
23960
26261
|
DEFAULT_FETCH_BATCH_SIZE: () => DEFAULT_FETCH_BATCH_SIZE,
|
|
23961
26262
|
DEFAULT_MAX_REQUEST_SIZE: () => DEFAULT_MAX_REQUEST_SIZE,
|
|
23962
26263
|
Dataset: () => Dataset2,
|
|
26264
|
+
DatasetPipeline: () => DatasetPipeline,
|
|
23963
26265
|
ERR_PERMALINK: () => ERR_PERMALINK,
|
|
23964
26266
|
Eval: () => Eval,
|
|
23965
26267
|
EvalResultWithSummary: () => EvalResultWithSummary,
|
|
@@ -24075,6 +26377,8 @@ __export(exports_exports, {
|
|
|
24075
26377
|
wrapCohere: () => wrapCohere,
|
|
24076
26378
|
wrapCopilotClient: () => wrapCopilotClient,
|
|
24077
26379
|
wrapCursorSDK: () => wrapCursorSDK,
|
|
26380
|
+
wrapFlueContext: () => wrapFlueContext,
|
|
26381
|
+
wrapFlueSession: () => wrapFlueSession,
|
|
24078
26382
|
wrapGenkit: () => wrapGenkit,
|
|
24079
26383
|
wrapGoogleADK: () => wrapGoogleADK,
|
|
24080
26384
|
wrapGoogleGenAI: () => wrapGoogleGenAI,
|
|
@@ -25174,7 +27478,7 @@ function extractModelParameters(params, excludeKeys) {
|
|
|
25174
27478
|
}
|
|
25175
27479
|
return modelParams;
|
|
25176
27480
|
}
|
|
25177
|
-
function
|
|
27481
|
+
function getNumberProperty3(obj, key) {
|
|
25178
27482
|
if (!obj || typeof obj !== "object" || !(key in obj)) {
|
|
25179
27483
|
return void 0;
|
|
25180
27484
|
}
|
|
@@ -25183,31 +27487,31 @@ function getNumberProperty2(obj, key) {
|
|
|
25183
27487
|
}
|
|
25184
27488
|
function normalizeUsageMetrics(usage, provider, providerMetadata) {
|
|
25185
27489
|
const metrics = {};
|
|
25186
|
-
const inputTokens =
|
|
27490
|
+
const inputTokens = getNumberProperty3(usage, "inputTokens");
|
|
25187
27491
|
if (inputTokens !== void 0) {
|
|
25188
27492
|
metrics.prompt_tokens = inputTokens;
|
|
25189
27493
|
}
|
|
25190
|
-
const outputTokens =
|
|
27494
|
+
const outputTokens = getNumberProperty3(usage, "outputTokens");
|
|
25191
27495
|
if (outputTokens !== void 0) {
|
|
25192
27496
|
metrics.completion_tokens = outputTokens;
|
|
25193
27497
|
}
|
|
25194
|
-
const totalTokens =
|
|
27498
|
+
const totalTokens = getNumberProperty3(usage, "totalTokens");
|
|
25195
27499
|
if (totalTokens !== void 0) {
|
|
25196
27500
|
metrics.tokens = totalTokens;
|
|
25197
27501
|
}
|
|
25198
|
-
const reasoningTokens =
|
|
27502
|
+
const reasoningTokens = getNumberProperty3(usage, "reasoningTokens");
|
|
25199
27503
|
if (reasoningTokens !== void 0) {
|
|
25200
27504
|
metrics.completion_reasoning_tokens = reasoningTokens;
|
|
25201
27505
|
}
|
|
25202
|
-
const cachedInputTokens =
|
|
27506
|
+
const cachedInputTokens = getNumberProperty3(usage, "cachedInputTokens");
|
|
25203
27507
|
if (cachedInputTokens !== void 0) {
|
|
25204
27508
|
metrics.prompt_cached_tokens = cachedInputTokens;
|
|
25205
27509
|
}
|
|
25206
27510
|
if (provider === "anthropic") {
|
|
25207
27511
|
const anthropicMetadata = providerMetadata?.anthropic;
|
|
25208
27512
|
if (anthropicMetadata) {
|
|
25209
|
-
const cacheReadTokens =
|
|
25210
|
-
const cacheCreationTokens =
|
|
27513
|
+
const cacheReadTokens = getNumberProperty3(anthropicMetadata.usage, "cache_read_input_tokens") || 0;
|
|
27514
|
+
const cacheCreationTokens = getNumberProperty3(
|
|
25211
27515
|
anthropicMetadata.usage,
|
|
25212
27516
|
"cache_creation_input_tokens"
|
|
25213
27517
|
) || 0;
|
|
@@ -26182,17 +28486,17 @@ function wrapGenkit(genkit) {
|
|
|
26182
28486
|
console.warn("Unsupported Genkit object. Not wrapping.");
|
|
26183
28487
|
return genkit;
|
|
26184
28488
|
}
|
|
26185
|
-
function
|
|
28489
|
+
function isRecord2(value) {
|
|
26186
28490
|
return typeof value === "object" && value !== null;
|
|
26187
28491
|
}
|
|
26188
28492
|
function isPropertyBag(value) {
|
|
26189
|
-
return
|
|
28493
|
+
return isRecord2(value) || typeof value === "function";
|
|
26190
28494
|
}
|
|
26191
28495
|
function hasFunction(value, methodName) {
|
|
26192
28496
|
return isPropertyBag(value) && methodName in value && typeof value[methodName] === "function";
|
|
26193
28497
|
}
|
|
26194
28498
|
function isGenkitInstance(value) {
|
|
26195
|
-
return
|
|
28499
|
+
return isRecord2(value) && (hasFunction(value, "generate") || hasFunction(value, "generateStream") || hasFunction(value, "defineFlow") || hasFunction(value, "defineTool"));
|
|
26196
28500
|
}
|
|
26197
28501
|
function isGenkitModule(value) {
|
|
26198
28502
|
return hasFunction(value, "genkit");
|
|
@@ -26246,7 +28550,7 @@ function patchGenkitRegistry(instance) {
|
|
|
26246
28550
|
patchGenkitRegistryConstructor(registry2);
|
|
26247
28551
|
}
|
|
26248
28552
|
function patchGenkitRegistryLookup(registry2) {
|
|
26249
|
-
if (!
|
|
28553
|
+
if (!isRecord2(registry2) || hasRegistryPatchedFlag(registry2) || !hasFunction(registry2, "lookupAction")) {
|
|
26250
28554
|
return;
|
|
26251
28555
|
}
|
|
26252
28556
|
const originalLookupAction = registry2.lookupAction;
|
|
@@ -26272,7 +28576,7 @@ function patchGenkitRegistryLookup(registry2) {
|
|
|
26272
28576
|
}
|
|
26273
28577
|
}
|
|
26274
28578
|
function patchGenkitRegistryConstructor(registry2) {
|
|
26275
|
-
if (!
|
|
28579
|
+
if (!isRecord2(registry2)) {
|
|
26276
28580
|
return;
|
|
26277
28581
|
}
|
|
26278
28582
|
const constructor = registry2.constructor;
|
|
@@ -26288,7 +28592,7 @@ function patchGenkitRegistryConstructor(registry2) {
|
|
|
26288
28592
|
configurable: true,
|
|
26289
28593
|
value: (...args) => {
|
|
26290
28594
|
const childRegistry = originalWithParent.apply(constructor, args);
|
|
26291
|
-
if (args.some((arg) =>
|
|
28595
|
+
if (args.some((arg) => isRecord2(arg) && hasRegistryPatchedFlag(arg))) {
|
|
26292
28596
|
patchGenkitRegistryLookup(childRegistry);
|
|
26293
28597
|
patchGenkitRegistryConstructor(childRegistry);
|
|
26294
28598
|
}
|
|
@@ -26387,7 +28691,7 @@ function hasRegistryConstructorPatchedFlag(value) {
|
|
|
26387
28691
|
);
|
|
26388
28692
|
}
|
|
26389
28693
|
function isPromiseLike2(value) {
|
|
26390
|
-
return
|
|
28694
|
+
return isRecord2(value) && "then" in value && typeof value.then === "function";
|
|
26391
28695
|
}
|
|
26392
28696
|
|
|
26393
28697
|
// src/wrappers/huggingface.ts
|
|
@@ -26750,14 +29054,14 @@ function wrapMistral(mistral) {
|
|
|
26750
29054
|
console.warn("Unsupported Mistral library. Not wrapping.");
|
|
26751
29055
|
return mistral;
|
|
26752
29056
|
}
|
|
26753
|
-
function
|
|
29057
|
+
function isRecord3(value) {
|
|
26754
29058
|
return typeof value === "object" && value !== null;
|
|
26755
29059
|
}
|
|
26756
29060
|
function hasFunction3(value, methodName) {
|
|
26757
|
-
return
|
|
29061
|
+
return isRecord3(value) && methodName in value && typeof value[methodName] === "function";
|
|
26758
29062
|
}
|
|
26759
29063
|
function isSupportedMistralClient(value) {
|
|
26760
|
-
if (!
|
|
29064
|
+
if (!isRecord3(value)) {
|
|
26761
29065
|
return false;
|
|
26762
29066
|
}
|
|
26763
29067
|
return value.chat !== void 0 && hasChat(value.chat) || value.embeddings !== void 0 && hasEmbeddings(value.embeddings) || value.fim !== void 0 && hasFim(value.fim) || value.agents !== void 0 && hasAgents(value.agents) || value.classifiers !== void 0 && hasClassifiers(value.classifiers);
|
|
@@ -26941,14 +29245,14 @@ function wrapCohere(cohere) {
|
|
|
26941
29245
|
return cohere;
|
|
26942
29246
|
}
|
|
26943
29247
|
var cohereProxyCache = /* @__PURE__ */ new WeakMap();
|
|
26944
|
-
function
|
|
29248
|
+
function isRecord4(value) {
|
|
26945
29249
|
return typeof value === "object" && value !== null;
|
|
26946
29250
|
}
|
|
26947
29251
|
function hasFunction4(value, methodName) {
|
|
26948
|
-
return
|
|
29252
|
+
return isRecord4(value) && methodName in value && typeof value[methodName] === "function";
|
|
26949
29253
|
}
|
|
26950
29254
|
function isSupportedCohereClient(value) {
|
|
26951
|
-
if (!
|
|
29255
|
+
if (!isRecord4(value)) {
|
|
26952
29256
|
return false;
|
|
26953
29257
|
}
|
|
26954
29258
|
return hasFunction4(value, "chat") || hasFunction4(value, "chatStream") || hasFunction4(value, "embed") || hasFunction4(value, "rerank");
|
|
@@ -27008,20 +29312,20 @@ function wrapGroq(groq) {
|
|
|
27008
29312
|
console.warn("Unsupported Groq library. Not wrapping.");
|
|
27009
29313
|
return groq;
|
|
27010
29314
|
}
|
|
27011
|
-
function
|
|
29315
|
+
function isRecord5(value) {
|
|
27012
29316
|
return typeof value === "object" && value !== null;
|
|
27013
29317
|
}
|
|
27014
29318
|
function hasFunction5(value, methodName) {
|
|
27015
|
-
return
|
|
29319
|
+
return isRecord5(value) && methodName in value && typeof value[methodName] === "function";
|
|
27016
29320
|
}
|
|
27017
29321
|
function hasChat2(value) {
|
|
27018
|
-
return
|
|
29322
|
+
return isRecord5(value) && isRecord5(value.completions) && hasFunction5(value.completions, "create");
|
|
27019
29323
|
}
|
|
27020
29324
|
function hasEmbeddings2(value) {
|
|
27021
29325
|
return hasFunction5(value, "create");
|
|
27022
29326
|
}
|
|
27023
29327
|
function isSupportedGroqClient(value) {
|
|
27024
|
-
return
|
|
29328
|
+
return isRecord5(value) && (value.chat !== void 0 && hasChat2(value.chat) || value.embeddings !== void 0 && hasEmbeddings2(value.embeddings));
|
|
27025
29329
|
}
|
|
27026
29330
|
function groqProxy(groq) {
|
|
27027
29331
|
const privateMethodWorkaroundCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -27216,10 +29520,12 @@ function formatExperimentSummary(summary) {
|
|
|
27216
29520
|
// src/wrappers/shared/flush.ts
|
|
27217
29521
|
async function summarizeAndFlush(experiment, options) {
|
|
27218
29522
|
const shouldDisplay = options.displaySummary ?? true;
|
|
27219
|
-
|
|
27220
|
-
|
|
27221
|
-
|
|
29523
|
+
if (!shouldDisplay) {
|
|
29524
|
+
await experiment.flush();
|
|
29525
|
+
return;
|
|
27222
29526
|
}
|
|
29527
|
+
const summary = await experiment.summarize();
|
|
29528
|
+
console.log(formatExperimentSummary(summary));
|
|
27223
29529
|
}
|
|
27224
29530
|
|
|
27225
29531
|
// src/wrappers/vitest/flush-manager.ts
|
|
@@ -29083,8 +31389,12 @@ var waterfall$1 = awaitify(waterfall);
|
|
|
29083
31389
|
|
|
29084
31390
|
// src/trace.ts
|
|
29085
31391
|
var SpanFetcher = class _SpanFetcher extends ObjectFetcher {
|
|
29086
|
-
constructor(objectType, _objectId, rootSpanId, _state, spanTypeFilter) {
|
|
29087
|
-
const filterExpr = _SpanFetcher.buildFilter(
|
|
31392
|
+
constructor(objectType, _objectId, rootSpanId, _state, spanTypeFilter, includeScorers = false) {
|
|
31393
|
+
const filterExpr = _SpanFetcher.buildFilter(
|
|
31394
|
+
rootSpanId,
|
|
31395
|
+
spanTypeFilter,
|
|
31396
|
+
includeScorers
|
|
31397
|
+
);
|
|
29088
31398
|
super(objectType, void 0, void 0, {
|
|
29089
31399
|
filter: filterExpr
|
|
29090
31400
|
});
|
|
@@ -29093,16 +31403,17 @@ var SpanFetcher = class _SpanFetcher extends ObjectFetcher {
|
|
|
29093
31403
|
this._state = _state;
|
|
29094
31404
|
this.spanTypeFilter = spanTypeFilter;
|
|
29095
31405
|
}
|
|
29096
|
-
static buildFilter(rootSpanId, spanTypeFilter) {
|
|
31406
|
+
static buildFilter(rootSpanId, spanTypeFilter, includeScorers = false) {
|
|
29097
31407
|
const children = [
|
|
29098
31408
|
// Base filter: root_span_id = 'value'
|
|
29099
31409
|
{
|
|
29100
31410
|
op: "eq",
|
|
29101
31411
|
left: { op: "ident", name: ["root_span_id"] },
|
|
29102
31412
|
right: { op: "literal", value: rootSpanId }
|
|
29103
|
-
}
|
|
29104
|
-
|
|
29105
|
-
|
|
31413
|
+
}
|
|
31414
|
+
];
|
|
31415
|
+
if (!includeScorers) {
|
|
31416
|
+
children.push({
|
|
29106
31417
|
op: "or",
|
|
29107
31418
|
children: [
|
|
29108
31419
|
{
|
|
@@ -29115,8 +31426,8 @@ var SpanFetcher = class _SpanFetcher extends ObjectFetcher {
|
|
|
29115
31426
|
right: { op: "literal", value: "scorer" }
|
|
29116
31427
|
}
|
|
29117
31428
|
]
|
|
29118
|
-
}
|
|
29119
|
-
|
|
31429
|
+
});
|
|
31430
|
+
}
|
|
29120
31431
|
if (spanTypeFilter && spanTypeFilter.length > 0) {
|
|
29121
31432
|
children.push({
|
|
29122
31433
|
op: "in",
|
|
@@ -29142,35 +31453,49 @@ var CachedSpanFetcher = class {
|
|
|
29142
31453
|
fetchFn;
|
|
29143
31454
|
constructor(objectTypeOrFetchFn, objectId, rootSpanId, getState) {
|
|
29144
31455
|
if (typeof objectTypeOrFetchFn === "function") {
|
|
29145
|
-
this.fetchFn = objectTypeOrFetchFn;
|
|
31456
|
+
this.fetchFn = (spanType) => objectTypeOrFetchFn(spanType);
|
|
29146
31457
|
} else {
|
|
29147
31458
|
const objectType = objectTypeOrFetchFn;
|
|
29148
|
-
this.fetchFn = async (spanType) => {
|
|
31459
|
+
this.fetchFn = async (spanType, includeScorers) => {
|
|
29149
31460
|
const state = await getState();
|
|
29150
31461
|
const fetcher = new SpanFetcher(
|
|
29151
31462
|
objectType,
|
|
29152
31463
|
objectId,
|
|
29153
31464
|
rootSpanId,
|
|
29154
31465
|
state,
|
|
29155
|
-
spanType
|
|
31466
|
+
spanType,
|
|
31467
|
+
includeScorers
|
|
29156
31468
|
);
|
|
29157
31469
|
const rows = await fetcher.fetchedData();
|
|
29158
|
-
return rows.
|
|
31470
|
+
return rows.map((row) => ({
|
|
29159
31471
|
input: row.input,
|
|
29160
31472
|
output: row.output,
|
|
31473
|
+
expected: row.expected,
|
|
31474
|
+
error: row.error,
|
|
31475
|
+
scores: row.scores,
|
|
31476
|
+
metrics: row.metrics,
|
|
29161
31477
|
metadata: row.metadata,
|
|
29162
31478
|
span_id: row.span_id,
|
|
29163
31479
|
span_parents: row.span_parents,
|
|
31480
|
+
is_root: row.is_root,
|
|
29164
31481
|
span_attributes: row.span_attributes,
|
|
29165
31482
|
id: row.id,
|
|
29166
31483
|
_xact_id: row._xact_id,
|
|
29167
31484
|
_pagination_key: row._pagination_key,
|
|
29168
|
-
root_span_id: row.root_span_id
|
|
31485
|
+
root_span_id: row.root_span_id,
|
|
31486
|
+
created: row.created,
|
|
31487
|
+
tags: row.tags
|
|
29169
31488
|
}));
|
|
29170
31489
|
};
|
|
29171
31490
|
}
|
|
29172
31491
|
}
|
|
29173
|
-
async getSpans({
|
|
31492
|
+
async getSpans({
|
|
31493
|
+
spanType,
|
|
31494
|
+
includeScorers = false
|
|
31495
|
+
} = {}) {
|
|
31496
|
+
if (includeScorers) {
|
|
31497
|
+
return this.fetchFn(spanType, true);
|
|
31498
|
+
}
|
|
29174
31499
|
if (this.allFetched) {
|
|
29175
31500
|
return this.getFromCache(spanType);
|
|
29176
31501
|
}
|
|
@@ -29187,7 +31512,7 @@ var CachedSpanFetcher = class {
|
|
|
29187
31512
|
return this.getFromCache(spanType);
|
|
29188
31513
|
}
|
|
29189
31514
|
async fetchSpans(spanType) {
|
|
29190
|
-
const spans = await this.fetchFn(spanType);
|
|
31515
|
+
const spans = await this.fetchFn(spanType, false);
|
|
29191
31516
|
for (const span of spans) {
|
|
29192
31517
|
const type = span.span_attributes?.type ?? "";
|
|
29193
31518
|
const existing = this.spanCache.get(type) ?? [];
|
|
@@ -29265,10 +31590,13 @@ var LocalTrace = class {
|
|
|
29265
31590
|
* First checks the local span cache for recently logged spans, then falls
|
|
29266
31591
|
* back to CachedSpanFetcher which handles BTQL fetching and caching.
|
|
29267
31592
|
*/
|
|
29268
|
-
async getSpans({
|
|
31593
|
+
async getSpans({
|
|
31594
|
+
spanType,
|
|
31595
|
+
includeScorers = false
|
|
31596
|
+
} = {}) {
|
|
29269
31597
|
const cachedSpans = this.state.spanCache.getByRootSpanId(this.rootSpanId);
|
|
29270
31598
|
if (cachedSpans && cachedSpans.length > 0) {
|
|
29271
|
-
let spans = cachedSpans.filter(
|
|
31599
|
+
let spans = includeScorers ? cachedSpans : cachedSpans.filter(
|
|
29272
31600
|
(span) => span.span_attributes?.purpose !== "scorer"
|
|
29273
31601
|
);
|
|
29274
31602
|
if (spanType && spanType.length > 0) {
|
|
@@ -29279,13 +31607,19 @@ var LocalTrace = class {
|
|
|
29279
31607
|
return spans.map((span) => ({
|
|
29280
31608
|
input: span.input,
|
|
29281
31609
|
output: span.output,
|
|
31610
|
+
expected: span.expected,
|
|
31611
|
+
error: span.error,
|
|
31612
|
+
scores: span.scores,
|
|
31613
|
+
metrics: span.metrics,
|
|
29282
31614
|
metadata: span.metadata,
|
|
29283
31615
|
span_id: span.span_id,
|
|
29284
31616
|
span_parents: span.span_parents,
|
|
29285
|
-
|
|
31617
|
+
is_root: span.is_root,
|
|
31618
|
+
span_attributes: span.span_attributes,
|
|
31619
|
+
tags: span.tags
|
|
29286
31620
|
}));
|
|
29287
31621
|
}
|
|
29288
|
-
return this.cachedFetcher.getSpans({ spanType });
|
|
31622
|
+
return this.cachedFetcher.getSpans({ spanType, includeScorers });
|
|
29289
31623
|
}
|
|
29290
31624
|
/**
|
|
29291
31625
|
* Get the thread (preprocessed messages) for this trace.
|
|
@@ -30474,6 +32808,34 @@ var defaultReporter = {
|
|
|
30474
32808
|
}
|
|
30475
32809
|
};
|
|
30476
32810
|
|
|
32811
|
+
// src/dataset-pipeline.ts
|
|
32812
|
+
function DatasetPipeline(definition) {
|
|
32813
|
+
if (!globalThis.__braintrust_dataset_pipelines) {
|
|
32814
|
+
globalThis.__braintrust_dataset_pipelines = [];
|
|
32815
|
+
}
|
|
32816
|
+
const storedDefinition = {
|
|
32817
|
+
name: definition.name,
|
|
32818
|
+
source: {
|
|
32819
|
+
projectId: definition.source.projectId,
|
|
32820
|
+
projectName: definition.source.projectName,
|
|
32821
|
+
orgName: definition.source.orgName,
|
|
32822
|
+
filter: definition.source.filter,
|
|
32823
|
+
scope: definition.source.scope ?? "span"
|
|
32824
|
+
},
|
|
32825
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any
|
|
32826
|
+
transform: definition.transform,
|
|
32827
|
+
target: {
|
|
32828
|
+
projectId: definition.target.projectId,
|
|
32829
|
+
projectName: definition.target.projectName,
|
|
32830
|
+
orgName: definition.target.orgName,
|
|
32831
|
+
datasetName: definition.target.datasetName,
|
|
32832
|
+
description: definition.target.description,
|
|
32833
|
+
metadata: definition.target.metadata
|
|
32834
|
+
}
|
|
32835
|
+
};
|
|
32836
|
+
globalThis.__braintrust_dataset_pipelines.push(storedDefinition);
|
|
32837
|
+
}
|
|
32838
|
+
|
|
30477
32839
|
// src/framework2.ts
|
|
30478
32840
|
var import_v312 = require("zod/v3");
|
|
30479
32841
|
var currentFilename = typeof __filename !== "undefined" ? __filename : "unknown";
|