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/edge-light.js
CHANGED
|
@@ -33,8 +33,10 @@ __export(edge_light_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(edge_light_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(edge_light_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,
|
|
@@ -263,6 +268,7 @@ var iso = {
|
|
|
263
268
|
getRepoInfo: async (_settings) => void 0,
|
|
264
269
|
getPastNAncestors: async () => [],
|
|
265
270
|
getEnv: (_name) => void 0,
|
|
271
|
+
getBraintrustApiKey: async () => void 0,
|
|
266
272
|
getCallerLocation: () => void 0,
|
|
267
273
|
newAsyncLocalStorage: () => new DefaultAsyncLocalStorage(),
|
|
268
274
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -1095,6 +1101,11 @@ function isPromiseLike(value) {
|
|
|
1095
1101
|
|
|
1096
1102
|
// util/object_util.ts
|
|
1097
1103
|
var SET_UNION_FIELDS = /* @__PURE__ */ new Set(["tags"]);
|
|
1104
|
+
var FORBIDDEN_MERGE_KEYS = /* @__PURE__ */ new Set([
|
|
1105
|
+
"__proto__",
|
|
1106
|
+
"constructor",
|
|
1107
|
+
"prototype"
|
|
1108
|
+
]);
|
|
1098
1109
|
function mergeDictsWithPaths({
|
|
1099
1110
|
mergeInto,
|
|
1100
1111
|
mergeFrom,
|
|
@@ -1117,6 +1128,7 @@ function mergeDictsWithPathsHelper({
|
|
|
1117
1128
|
mergePaths
|
|
1118
1129
|
}) {
|
|
1119
1130
|
Object.entries(mergeFrom).forEach(([k, mergeFromV]) => {
|
|
1131
|
+
if (FORBIDDEN_MERGE_KEYS.has(k)) return;
|
|
1120
1132
|
const fullPath = path.concat([k]);
|
|
1121
1133
|
const fullPathSerialized = JSON.stringify(fullPath);
|
|
1122
1134
|
const mergeIntoV = recordFind(mergeInto, k);
|
|
@@ -5188,6 +5200,13 @@ var HTTPConnection = class _HTTPConnection {
|
|
|
5188
5200
|
debugLogger.debug(
|
|
5189
5201
|
`Retrying API request ${object_type} ${JSON.stringify(args)} ${e.status} ${e.text}`
|
|
5190
5202
|
);
|
|
5203
|
+
const sleepTimeS = HTTP_RETRY_BASE_SLEEP_TIME_S * 2 ** i;
|
|
5204
|
+
debugLogger.info(
|
|
5205
|
+
`Sleeping for ${sleepTimeS}s before retrying API request`
|
|
5206
|
+
);
|
|
5207
|
+
await new Promise(
|
|
5208
|
+
(resolve) => setTimeout(resolve, sleepTimeS * 1e3)
|
|
5209
|
+
);
|
|
5191
5210
|
continue;
|
|
5192
5211
|
}
|
|
5193
5212
|
throw e;
|
|
@@ -5589,6 +5608,19 @@ var JSONAttachment = class extends Attachment {
|
|
|
5589
5608
|
*/
|
|
5590
5609
|
constructor(data, options) {
|
|
5591
5610
|
const { filename = "data.json", pretty = false, state } = options ?? {};
|
|
5611
|
+
const deferredJsonAttachment = globalThis.__BT_DATASET_PIPELINE_DEFER_JSON_ATTACHMENT__;
|
|
5612
|
+
if (deferredJsonAttachment) {
|
|
5613
|
+
super({
|
|
5614
|
+
data: new Blob([]),
|
|
5615
|
+
filename,
|
|
5616
|
+
contentType: "application/json",
|
|
5617
|
+
state
|
|
5618
|
+
});
|
|
5619
|
+
return deferredJsonAttachment(data, {
|
|
5620
|
+
filename,
|
|
5621
|
+
pretty
|
|
5622
|
+
});
|
|
5623
|
+
}
|
|
5592
5624
|
const jsonString = pretty ? JSON.stringify(data, null, 2) : JSON.stringify(data);
|
|
5593
5625
|
const blob = new Blob([jsonString], { type: "application/json" });
|
|
5594
5626
|
super({
|
|
@@ -5837,20 +5869,7 @@ function startSpanParentArgs(args) {
|
|
|
5837
5869
|
`Mismatch between expected span parent object type ${args.parentObjectType} and provided type ${parentComponents.data.object_type}`
|
|
5838
5870
|
);
|
|
5839
5871
|
}
|
|
5840
|
-
|
|
5841
|
-
args.state,
|
|
5842
|
-
parentComponents
|
|
5843
|
-
);
|
|
5844
|
-
const computeParentObjectId = async () => {
|
|
5845
|
-
const parentComponentsObjectId = await parentComponentsObjectIdLambda();
|
|
5846
|
-
if (await args.parentObjectId.get() !== parentComponentsObjectId) {
|
|
5847
|
-
throw new Error(
|
|
5848
|
-
`Mismatch between expected span parent object id ${await args.parentObjectId.get()} and provided id ${parentComponentsObjectId}`
|
|
5849
|
-
);
|
|
5850
|
-
}
|
|
5851
|
-
return await args.parentObjectId.get();
|
|
5852
|
-
};
|
|
5853
|
-
argParentObjectId = new LazyValue(computeParentObjectId);
|
|
5872
|
+
argParentObjectId = args.parentObjectId;
|
|
5854
5873
|
if (parentComponents.data.row_id) {
|
|
5855
5874
|
argParentSpanIds = {
|
|
5856
5875
|
spanId: parentComponents.data.span_id,
|
|
@@ -6236,6 +6255,7 @@ var TestBackgroundLogger = class {
|
|
|
6236
6255
|
}
|
|
6237
6256
|
};
|
|
6238
6257
|
var BACKGROUND_LOGGER_BASE_SLEEP_TIME_S = 1;
|
|
6258
|
+
var HTTP_RETRY_BASE_SLEEP_TIME_S = 1;
|
|
6239
6259
|
var HTTPBackgroundLogger = class _HTTPBackgroundLogger {
|
|
6240
6260
|
apiConn;
|
|
6241
6261
|
queue;
|
|
@@ -6866,17 +6886,10 @@ function init(projectOrOptions, optionalOptions) {
|
|
|
6866
6886
|
if (repoInfo) {
|
|
6867
6887
|
return repoInfo;
|
|
6868
6888
|
}
|
|
6869
|
-
|
|
6870
|
-
|
|
6871
|
-
|
|
6872
|
-
|
|
6873
|
-
};
|
|
6874
|
-
if (gitMetadataSettings) {
|
|
6875
|
-
mergedGitMetadataSettings = mergeGitMetadataSettings(
|
|
6876
|
-
mergedGitMetadataSettings,
|
|
6877
|
-
gitMetadataSettings
|
|
6878
|
-
);
|
|
6879
|
-
}
|
|
6889
|
+
const mergedGitMetadataSettings = state.gitMetadataSettings == null ? gitMetadataSettings ?? { collect: "none" } : mergeGitMetadataSettings(
|
|
6890
|
+
state.gitMetadataSettings,
|
|
6891
|
+
gitMetadataSettings ?? { collect: "all" }
|
|
6892
|
+
);
|
|
6880
6893
|
return await isomorph_default.getRepoInfo(mergedGitMetadataSettings);
|
|
6881
6894
|
})();
|
|
6882
6895
|
if (repoInfoArg) {
|
|
@@ -7600,10 +7613,11 @@ async function login(options = {}) {
|
|
|
7600
7613
|
async function loginToState(options = {}) {
|
|
7601
7614
|
const {
|
|
7602
7615
|
appUrl = isomorph_default.getEnv("BRAINTRUST_APP_URL") || "https://www.braintrust.dev",
|
|
7603
|
-
apiKey
|
|
7616
|
+
apiKey: apiKeyArg,
|
|
7604
7617
|
orgName = isomorph_default.getEnv("BRAINTRUST_ORG_NAME"),
|
|
7605
7618
|
fetch: fetch2 = globalThis.fetch
|
|
7606
7619
|
} = options || {};
|
|
7620
|
+
const apiKey = apiKeyArg !== void 0 ? apiKeyArg : await isomorph_default.getBraintrustApiKey();
|
|
7607
7621
|
const appPublicUrl = isomorph_default.getEnv("BRAINTRUST_APP_PUBLIC_URL") || appUrl;
|
|
7608
7622
|
const state = new BraintrustState(options);
|
|
7609
7623
|
state.resetLoginInfo();
|
|
@@ -8844,9 +8858,15 @@ var SpanImpl = class _SpanImpl {
|
|
|
8844
8858
|
const cachedSpan = {
|
|
8845
8859
|
input: partialRecord.input,
|
|
8846
8860
|
output: partialRecord.output,
|
|
8861
|
+
expected: partialRecord.expected,
|
|
8862
|
+
error: partialRecord.error,
|
|
8863
|
+
scores: partialRecord.scores,
|
|
8864
|
+
metrics: partialRecord.metrics,
|
|
8847
8865
|
metadata: partialRecord.metadata,
|
|
8866
|
+
tags: partialRecord.tags,
|
|
8848
8867
|
span_id: this._spanId,
|
|
8849
8868
|
span_parents: this._spanParents,
|
|
8869
|
+
is_root: this._spanId === this._rootSpanId,
|
|
8850
8870
|
span_attributes: partialRecord.span_attributes
|
|
8851
8871
|
};
|
|
8852
8872
|
this._state.spanCache.queueWrite(
|
|
@@ -9182,6 +9202,7 @@ var Dataset2 = class extends ObjectFetcher {
|
|
|
9182
9202
|
metadata,
|
|
9183
9203
|
tags,
|
|
9184
9204
|
output,
|
|
9205
|
+
origin,
|
|
9185
9206
|
isMerge
|
|
9186
9207
|
}) {
|
|
9187
9208
|
return new LazyValue(async () => {
|
|
@@ -9196,6 +9217,7 @@ var Dataset2 = class extends ObjectFetcher {
|
|
|
9196
9217
|
created: !isMerge ? (/* @__PURE__ */ new Date()).toISOString() : void 0,
|
|
9197
9218
|
//if we're merging/updating an event we will not add this ts
|
|
9198
9219
|
metadata,
|
|
9220
|
+
origin,
|
|
9199
9221
|
...!!isMerge ? {
|
|
9200
9222
|
[IS_MERGE_FIELD]: true
|
|
9201
9223
|
} : {}
|
|
@@ -9215,6 +9237,7 @@ var Dataset2 = class extends ObjectFetcher {
|
|
|
9215
9237
|
* about anything else that's relevant, that you can use to help find and analyze examples later. For example, you could log the
|
|
9216
9238
|
* `prompt`, example's `id`, or anything else that would be useful to slice/dice later. The values in `metadata` can be any
|
|
9217
9239
|
* JSON-serializable type, but its keys must be strings.
|
|
9240
|
+
* @param event.origin (Optional) a reference to the source object this dataset record was derived from.
|
|
9218
9241
|
* @param event.id (Optional) a unique identifier for the event. If you don't provide one, Braintrust will generate one for you.
|
|
9219
9242
|
* @param event.output: (Deprecated) The output of your application. Use `expected` instead.
|
|
9220
9243
|
* @returns The `id` of the logged record.
|
|
@@ -9225,7 +9248,8 @@ var Dataset2 = class extends ObjectFetcher {
|
|
|
9225
9248
|
metadata,
|
|
9226
9249
|
tags,
|
|
9227
9250
|
id,
|
|
9228
|
-
output
|
|
9251
|
+
output,
|
|
9252
|
+
origin
|
|
9229
9253
|
}) {
|
|
9230
9254
|
this.validateEvent({ metadata, expected, output, tags });
|
|
9231
9255
|
const rowId = id || (0, import_uuid2.v4)();
|
|
@@ -9237,6 +9261,7 @@ var Dataset2 = class extends ObjectFetcher {
|
|
|
9237
9261
|
metadata,
|
|
9238
9262
|
tags,
|
|
9239
9263
|
output,
|
|
9264
|
+
origin,
|
|
9240
9265
|
isMerge: false
|
|
9241
9266
|
})
|
|
9242
9267
|
);
|
|
@@ -13695,11 +13720,11 @@ function resolveDenyOutputPaths(event, defaultDenyOutputPaths) {
|
|
|
13695
13720
|
if (Array.isArray(event?.denyOutputPaths)) {
|
|
13696
13721
|
return event.denyOutputPaths;
|
|
13697
13722
|
}
|
|
13698
|
-
const
|
|
13699
|
-
if (!
|
|
13723
|
+
const firstArgument2 = event?.arguments && event.arguments.length > 0 ? event.arguments[0] : void 0;
|
|
13724
|
+
if (!firstArgument2 || typeof firstArgument2 !== "object") {
|
|
13700
13725
|
return defaultDenyOutputPaths;
|
|
13701
13726
|
}
|
|
13702
|
-
const runtimeDenyOutputPaths =
|
|
13727
|
+
const runtimeDenyOutputPaths = firstArgument2[RUNTIME_DENY_OUTPUT_PATHS];
|
|
13703
13728
|
if (Array.isArray(runtimeDenyOutputPaths) && runtimeDenyOutputPaths.every((path) => typeof path === "string")) {
|
|
13704
13729
|
return runtimeDenyOutputPaths;
|
|
13705
13730
|
}
|
|
@@ -17358,6 +17383,467 @@ function cleanMetrics2(metrics) {
|
|
|
17358
17383
|
return cleaned;
|
|
17359
17384
|
}
|
|
17360
17385
|
|
|
17386
|
+
// src/instrumentation/plugins/openai-agents-channels.ts
|
|
17387
|
+
var openAIAgentsCoreChannels = defineChannels("@openai/agents-core", {
|
|
17388
|
+
onTraceStart: channel({
|
|
17389
|
+
channelName: "tracing.processor.onTraceStart",
|
|
17390
|
+
kind: "async"
|
|
17391
|
+
}),
|
|
17392
|
+
onTraceEnd: channel({
|
|
17393
|
+
channelName: "tracing.processor.onTraceEnd",
|
|
17394
|
+
kind: "async"
|
|
17395
|
+
}),
|
|
17396
|
+
onSpanStart: channel({
|
|
17397
|
+
channelName: "tracing.processor.onSpanStart",
|
|
17398
|
+
kind: "async"
|
|
17399
|
+
}),
|
|
17400
|
+
onSpanEnd: channel({
|
|
17401
|
+
channelName: "tracing.processor.onSpanEnd",
|
|
17402
|
+
kind: "async"
|
|
17403
|
+
})
|
|
17404
|
+
});
|
|
17405
|
+
|
|
17406
|
+
// src/instrumentation/plugins/openai-agents-trace-processor.ts
|
|
17407
|
+
function isSpanData(spanData, type) {
|
|
17408
|
+
return spanData.type === type;
|
|
17409
|
+
}
|
|
17410
|
+
function spanTypeFromAgents(span) {
|
|
17411
|
+
const spanType = span.spanData.type;
|
|
17412
|
+
if (spanType === "function" || spanType === "guardrail" || spanType === "mcp_tools") {
|
|
17413
|
+
return "tool" /* TOOL */;
|
|
17414
|
+
}
|
|
17415
|
+
if (spanType === "generation" || spanType === "response" || spanType === "transcription" || spanType === "speech") {
|
|
17416
|
+
return "llm" /* LLM */;
|
|
17417
|
+
}
|
|
17418
|
+
return "task" /* TASK */;
|
|
17419
|
+
}
|
|
17420
|
+
function spanNameFromAgents(span) {
|
|
17421
|
+
const spanData = span.spanData;
|
|
17422
|
+
if ("name" in spanData && spanData.name) {
|
|
17423
|
+
return spanData.name;
|
|
17424
|
+
}
|
|
17425
|
+
switch (spanData.type) {
|
|
17426
|
+
case "generation":
|
|
17427
|
+
return "Generation";
|
|
17428
|
+
case "response":
|
|
17429
|
+
return "Response";
|
|
17430
|
+
case "handoff":
|
|
17431
|
+
return "Handoff";
|
|
17432
|
+
case "mcp_tools":
|
|
17433
|
+
return isSpanData(spanData, "mcp_tools") && spanData.server ? `List Tools (${spanData.server})` : "MCP List Tools";
|
|
17434
|
+
case "transcription":
|
|
17435
|
+
return "Transcription";
|
|
17436
|
+
case "speech":
|
|
17437
|
+
return "Speech";
|
|
17438
|
+
case "speech_group":
|
|
17439
|
+
return "Speech Group";
|
|
17440
|
+
default:
|
|
17441
|
+
return "Unknown";
|
|
17442
|
+
}
|
|
17443
|
+
}
|
|
17444
|
+
function getTimeElapsed(end, start) {
|
|
17445
|
+
if (!start || !end) {
|
|
17446
|
+
return void 0;
|
|
17447
|
+
}
|
|
17448
|
+
const startTime = new Date(start).getTime();
|
|
17449
|
+
const endTime = new Date(end).getTime();
|
|
17450
|
+
if (Number.isNaN(startTime) || Number.isNaN(endTime)) {
|
|
17451
|
+
return void 0;
|
|
17452
|
+
}
|
|
17453
|
+
return (endTime - startTime) / 1e3;
|
|
17454
|
+
}
|
|
17455
|
+
function getNumberProperty2(obj, key) {
|
|
17456
|
+
if (!isObject(obj) || !(key in obj)) {
|
|
17457
|
+
return void 0;
|
|
17458
|
+
}
|
|
17459
|
+
const value = obj[key];
|
|
17460
|
+
return typeof value === "number" ? value : void 0;
|
|
17461
|
+
}
|
|
17462
|
+
function parseUsageMetrics(usage) {
|
|
17463
|
+
const metrics = {};
|
|
17464
|
+
if (!isObject(usage)) {
|
|
17465
|
+
return metrics;
|
|
17466
|
+
}
|
|
17467
|
+
const promptTokens = getNumberProperty2(usage, "prompt_tokens") ?? getNumberProperty2(usage, "input_tokens") ?? getNumberProperty2(usage, "promptTokens") ?? getNumberProperty2(usage, "inputTokens");
|
|
17468
|
+
const completionTokens = getNumberProperty2(usage, "completion_tokens") ?? getNumberProperty2(usage, "output_tokens") ?? getNumberProperty2(usage, "completionTokens") ?? getNumberProperty2(usage, "outputTokens");
|
|
17469
|
+
const totalTokens = getNumberProperty2(usage, "total_tokens") ?? getNumberProperty2(usage, "totalTokens");
|
|
17470
|
+
if (promptTokens !== void 0) {
|
|
17471
|
+
metrics.prompt_tokens = promptTokens;
|
|
17472
|
+
}
|
|
17473
|
+
if (completionTokens !== void 0) {
|
|
17474
|
+
metrics.completion_tokens = completionTokens;
|
|
17475
|
+
}
|
|
17476
|
+
if (totalTokens !== void 0) {
|
|
17477
|
+
metrics.tokens = totalTokens;
|
|
17478
|
+
} else if (promptTokens !== void 0 && completionTokens !== void 0) {
|
|
17479
|
+
metrics.tokens = promptTokens + completionTokens;
|
|
17480
|
+
}
|
|
17481
|
+
const inputDetails = usage.input_tokens_details;
|
|
17482
|
+
const cachedTokens = getNumberProperty2(inputDetails, "cached_tokens");
|
|
17483
|
+
const cacheWriteTokens = getNumberProperty2(
|
|
17484
|
+
inputDetails,
|
|
17485
|
+
"cache_write_tokens"
|
|
17486
|
+
);
|
|
17487
|
+
if (cachedTokens !== void 0) {
|
|
17488
|
+
metrics.prompt_cached_tokens = cachedTokens;
|
|
17489
|
+
}
|
|
17490
|
+
if (cacheWriteTokens !== void 0) {
|
|
17491
|
+
metrics.prompt_cache_creation_tokens = cacheWriteTokens;
|
|
17492
|
+
}
|
|
17493
|
+
return metrics;
|
|
17494
|
+
}
|
|
17495
|
+
var OpenAIAgentsTraceProcessor = class _OpenAIAgentsTraceProcessor {
|
|
17496
|
+
static DEFAULT_MAX_TRACES = 1e4;
|
|
17497
|
+
logger;
|
|
17498
|
+
maxTraces;
|
|
17499
|
+
traceSpans = /* @__PURE__ */ new Map();
|
|
17500
|
+
traceOrder = [];
|
|
17501
|
+
_traceSpans = this.traceSpans;
|
|
17502
|
+
constructor(options = {}) {
|
|
17503
|
+
this.logger = options.logger;
|
|
17504
|
+
this.maxTraces = options.maxTraces ?? _OpenAIAgentsTraceProcessor.DEFAULT_MAX_TRACES;
|
|
17505
|
+
}
|
|
17506
|
+
evictOldestTrace() {
|
|
17507
|
+
const oldestTraceId = this.traceOrder.shift();
|
|
17508
|
+
if (oldestTraceId) {
|
|
17509
|
+
this.traceSpans.delete(oldestTraceId);
|
|
17510
|
+
}
|
|
17511
|
+
}
|
|
17512
|
+
onTraceStart(trace) {
|
|
17513
|
+
if (!trace?.traceId) {
|
|
17514
|
+
return Promise.resolve();
|
|
17515
|
+
}
|
|
17516
|
+
if (this.traceOrder.length >= this.maxTraces) {
|
|
17517
|
+
this.evictOldestTrace();
|
|
17518
|
+
}
|
|
17519
|
+
const current = currentSpan();
|
|
17520
|
+
const span = current && current !== NOOP_SPAN ? current.startSpan({
|
|
17521
|
+
name: trace.name,
|
|
17522
|
+
type: "task" /* TASK */
|
|
17523
|
+
}) : this.logger ? this.logger.startSpan({
|
|
17524
|
+
name: trace.name,
|
|
17525
|
+
type: "task" /* TASK */
|
|
17526
|
+
}) : startSpan({
|
|
17527
|
+
name: trace.name,
|
|
17528
|
+
type: "task" /* TASK */
|
|
17529
|
+
});
|
|
17530
|
+
span.log({
|
|
17531
|
+
input: "Agent workflow started",
|
|
17532
|
+
metadata: {
|
|
17533
|
+
group_id: trace.groupId,
|
|
17534
|
+
...trace.metadata || {}
|
|
17535
|
+
}
|
|
17536
|
+
});
|
|
17537
|
+
this.traceSpans.set(trace.traceId, {
|
|
17538
|
+
rootSpan: span,
|
|
17539
|
+
childSpans: /* @__PURE__ */ new Map(),
|
|
17540
|
+
metadata: {
|
|
17541
|
+
firstInput: null,
|
|
17542
|
+
lastOutput: null
|
|
17543
|
+
}
|
|
17544
|
+
});
|
|
17545
|
+
this.traceOrder.push(trace.traceId);
|
|
17546
|
+
return Promise.resolve();
|
|
17547
|
+
}
|
|
17548
|
+
async onTraceEnd(trace) {
|
|
17549
|
+
const traceData = this.traceSpans.get(trace?.traceId);
|
|
17550
|
+
if (!traceData) {
|
|
17551
|
+
return;
|
|
17552
|
+
}
|
|
17553
|
+
try {
|
|
17554
|
+
traceData.rootSpan.log({
|
|
17555
|
+
input: traceData.metadata.firstInput,
|
|
17556
|
+
output: traceData.metadata.lastOutput
|
|
17557
|
+
});
|
|
17558
|
+
traceData.rootSpan.end();
|
|
17559
|
+
await traceData.rootSpan.flush();
|
|
17560
|
+
} finally {
|
|
17561
|
+
this.traceSpans.delete(trace.traceId);
|
|
17562
|
+
const orderIndex = this.traceOrder.indexOf(trace.traceId);
|
|
17563
|
+
if (orderIndex > -1) {
|
|
17564
|
+
this.traceOrder.splice(orderIndex, 1);
|
|
17565
|
+
}
|
|
17566
|
+
}
|
|
17567
|
+
}
|
|
17568
|
+
onSpanStart(span) {
|
|
17569
|
+
if (!span?.spanId || !span.traceId) {
|
|
17570
|
+
return Promise.resolve();
|
|
17571
|
+
}
|
|
17572
|
+
const traceData = this.traceSpans.get(span.traceId);
|
|
17573
|
+
if (!traceData) {
|
|
17574
|
+
return Promise.resolve();
|
|
17575
|
+
}
|
|
17576
|
+
const parentSpan = span.parentId ? traceData.childSpans.get(span.parentId) : traceData.rootSpan;
|
|
17577
|
+
if (!parentSpan) {
|
|
17578
|
+
return Promise.resolve();
|
|
17579
|
+
}
|
|
17580
|
+
const childSpan = parentSpan.startSpan({
|
|
17581
|
+
name: spanNameFromAgents(span),
|
|
17582
|
+
type: spanTypeFromAgents(span)
|
|
17583
|
+
});
|
|
17584
|
+
traceData.childSpans.set(span.spanId, childSpan);
|
|
17585
|
+
return Promise.resolve();
|
|
17586
|
+
}
|
|
17587
|
+
onSpanEnd(span) {
|
|
17588
|
+
if (!span?.spanId || !span.traceId) {
|
|
17589
|
+
return Promise.resolve();
|
|
17590
|
+
}
|
|
17591
|
+
const traceData = this.traceSpans.get(span.traceId);
|
|
17592
|
+
if (!traceData) {
|
|
17593
|
+
return Promise.resolve();
|
|
17594
|
+
}
|
|
17595
|
+
const braintrustSpan = traceData.childSpans.get(span.spanId);
|
|
17596
|
+
if (!braintrustSpan) {
|
|
17597
|
+
return Promise.resolve();
|
|
17598
|
+
}
|
|
17599
|
+
const logData = this.extractLogData(span);
|
|
17600
|
+
braintrustSpan.log({
|
|
17601
|
+
error: span.error,
|
|
17602
|
+
...logData
|
|
17603
|
+
});
|
|
17604
|
+
braintrustSpan.end();
|
|
17605
|
+
traceData.childSpans.delete(span.spanId);
|
|
17606
|
+
const input = logData.input;
|
|
17607
|
+
const output = logData.output;
|
|
17608
|
+
if (traceData.metadata.firstInput === null && input != null) {
|
|
17609
|
+
traceData.metadata.firstInput = input;
|
|
17610
|
+
}
|
|
17611
|
+
if (output != null) {
|
|
17612
|
+
traceData.metadata.lastOutput = output;
|
|
17613
|
+
}
|
|
17614
|
+
return Promise.resolve();
|
|
17615
|
+
}
|
|
17616
|
+
async shutdown() {
|
|
17617
|
+
if (this.logger && typeof this.logger.flush === "function") {
|
|
17618
|
+
await this.logger.flush();
|
|
17619
|
+
}
|
|
17620
|
+
}
|
|
17621
|
+
async forceFlush() {
|
|
17622
|
+
if (this.logger && typeof this.logger.flush === "function") {
|
|
17623
|
+
await this.logger.flush();
|
|
17624
|
+
}
|
|
17625
|
+
}
|
|
17626
|
+
extractLogData(span) {
|
|
17627
|
+
const spanData = span.spanData;
|
|
17628
|
+
switch (spanData.type) {
|
|
17629
|
+
case "agent":
|
|
17630
|
+
return this.extractAgentLogData(spanData);
|
|
17631
|
+
case "response":
|
|
17632
|
+
return this.extractResponseLogData(spanData, span);
|
|
17633
|
+
case "function":
|
|
17634
|
+
return this.extractFunctionLogData(spanData);
|
|
17635
|
+
case "handoff":
|
|
17636
|
+
return this.extractHandoffLogData(spanData);
|
|
17637
|
+
case "guardrail":
|
|
17638
|
+
return this.extractGuardrailLogData(spanData);
|
|
17639
|
+
case "generation":
|
|
17640
|
+
return this.extractGenerationLogData(spanData, span);
|
|
17641
|
+
case "custom":
|
|
17642
|
+
return this.extractCustomLogData(spanData);
|
|
17643
|
+
case "mcp_tools":
|
|
17644
|
+
return this.extractMCPListToolsLogData(spanData);
|
|
17645
|
+
case "transcription":
|
|
17646
|
+
return this.extractTranscriptionLogData(spanData);
|
|
17647
|
+
case "speech":
|
|
17648
|
+
return this.extractSpeechLogData(spanData);
|
|
17649
|
+
case "speech_group":
|
|
17650
|
+
return this.extractSpeechGroupLogData(spanData);
|
|
17651
|
+
default:
|
|
17652
|
+
return {};
|
|
17653
|
+
}
|
|
17654
|
+
}
|
|
17655
|
+
extractAgentLogData(spanData) {
|
|
17656
|
+
return {
|
|
17657
|
+
metadata: {
|
|
17658
|
+
tools: spanData.tools,
|
|
17659
|
+
handoffs: spanData.handoffs,
|
|
17660
|
+
output_type: spanData.output_type
|
|
17661
|
+
}
|
|
17662
|
+
};
|
|
17663
|
+
}
|
|
17664
|
+
extractResponseLogData(spanData, span) {
|
|
17665
|
+
const response = spanData._response;
|
|
17666
|
+
const output = isObject(response) ? response.output : void 0;
|
|
17667
|
+
const usage = isObject(response) ? response.usage : void 0;
|
|
17668
|
+
const metrics = {
|
|
17669
|
+
...this.extractTimingMetrics(span),
|
|
17670
|
+
...parseUsageMetrics(usage)
|
|
17671
|
+
};
|
|
17672
|
+
return {
|
|
17673
|
+
input: spanData._input,
|
|
17674
|
+
output,
|
|
17675
|
+
metadata: isObject(response) ? this.omitKeys(response, ["output", "usage"]) : {},
|
|
17676
|
+
metrics
|
|
17677
|
+
};
|
|
17678
|
+
}
|
|
17679
|
+
extractFunctionLogData(spanData) {
|
|
17680
|
+
return {
|
|
17681
|
+
input: spanData.input,
|
|
17682
|
+
output: spanData.output
|
|
17683
|
+
};
|
|
17684
|
+
}
|
|
17685
|
+
extractHandoffLogData(spanData) {
|
|
17686
|
+
return {
|
|
17687
|
+
metadata: {
|
|
17688
|
+
from_agent: spanData.from_agent,
|
|
17689
|
+
to_agent: spanData.to_agent
|
|
17690
|
+
}
|
|
17691
|
+
};
|
|
17692
|
+
}
|
|
17693
|
+
extractGuardrailLogData(spanData) {
|
|
17694
|
+
return {
|
|
17695
|
+
metadata: {
|
|
17696
|
+
triggered: spanData.triggered
|
|
17697
|
+
}
|
|
17698
|
+
};
|
|
17699
|
+
}
|
|
17700
|
+
extractGenerationLogData(spanData, span) {
|
|
17701
|
+
return {
|
|
17702
|
+
input: spanData.input,
|
|
17703
|
+
output: spanData.output,
|
|
17704
|
+
metadata: {
|
|
17705
|
+
model: spanData.model,
|
|
17706
|
+
model_config: spanData.model_config
|
|
17707
|
+
},
|
|
17708
|
+
metrics: {
|
|
17709
|
+
...this.extractTimingMetrics(span),
|
|
17710
|
+
...parseUsageMetrics(spanData.usage)
|
|
17711
|
+
}
|
|
17712
|
+
};
|
|
17713
|
+
}
|
|
17714
|
+
extractCustomLogData(spanData) {
|
|
17715
|
+
return spanData.data || {};
|
|
17716
|
+
}
|
|
17717
|
+
extractMCPListToolsLogData(spanData) {
|
|
17718
|
+
return {
|
|
17719
|
+
output: spanData.result,
|
|
17720
|
+
metadata: {
|
|
17721
|
+
server: spanData.server
|
|
17722
|
+
}
|
|
17723
|
+
};
|
|
17724
|
+
}
|
|
17725
|
+
extractTranscriptionLogData(spanData) {
|
|
17726
|
+
return {
|
|
17727
|
+
input: spanData.input,
|
|
17728
|
+
output: spanData.output,
|
|
17729
|
+
metadata: {
|
|
17730
|
+
model: spanData.model,
|
|
17731
|
+
model_config: spanData.model_config
|
|
17732
|
+
}
|
|
17733
|
+
};
|
|
17734
|
+
}
|
|
17735
|
+
extractSpeechLogData(spanData) {
|
|
17736
|
+
return {
|
|
17737
|
+
input: spanData.input,
|
|
17738
|
+
output: spanData.output,
|
|
17739
|
+
metadata: {
|
|
17740
|
+
model: spanData.model,
|
|
17741
|
+
model_config: spanData.model_config
|
|
17742
|
+
}
|
|
17743
|
+
};
|
|
17744
|
+
}
|
|
17745
|
+
extractSpeechGroupLogData(spanData) {
|
|
17746
|
+
return {
|
|
17747
|
+
input: spanData.input
|
|
17748
|
+
};
|
|
17749
|
+
}
|
|
17750
|
+
extractTimingMetrics(span) {
|
|
17751
|
+
const timeToFirstToken = getTimeElapsed(
|
|
17752
|
+
span.endedAt ?? void 0,
|
|
17753
|
+
span.startedAt ?? void 0
|
|
17754
|
+
);
|
|
17755
|
+
return timeToFirstToken === void 0 ? {} : { time_to_first_token: timeToFirstToken };
|
|
17756
|
+
}
|
|
17757
|
+
omitKeys(value, keys) {
|
|
17758
|
+
const result = {};
|
|
17759
|
+
for (const [key, fieldValue] of Object.entries(value)) {
|
|
17760
|
+
if (!keys.includes(key)) {
|
|
17761
|
+
result[key] = fieldValue;
|
|
17762
|
+
}
|
|
17763
|
+
}
|
|
17764
|
+
return result;
|
|
17765
|
+
}
|
|
17766
|
+
};
|
|
17767
|
+
|
|
17768
|
+
// src/instrumentation/plugins/openai-agents-plugin.ts
|
|
17769
|
+
function firstArgument(args) {
|
|
17770
|
+
if (Array.isArray(args)) {
|
|
17771
|
+
return args[0];
|
|
17772
|
+
}
|
|
17773
|
+
if (isObject(args) && "length" in args && typeof args.length === "number" && Number.isInteger(args.length) && args.length >= 0) {
|
|
17774
|
+
return Array.from(args)[0];
|
|
17775
|
+
}
|
|
17776
|
+
return void 0;
|
|
17777
|
+
}
|
|
17778
|
+
function isOpenAIAgentsTrace(value) {
|
|
17779
|
+
return isObject(value) && value.type === "trace" && typeof value.traceId === "string";
|
|
17780
|
+
}
|
|
17781
|
+
function isOpenAIAgentsSpan(value) {
|
|
17782
|
+
return isObject(value) && value.type === "trace.span" && typeof value.traceId === "string" && typeof value.spanId === "string";
|
|
17783
|
+
}
|
|
17784
|
+
var OpenAIAgentsPlugin = class extends BasePlugin {
|
|
17785
|
+
processor = new OpenAIAgentsTraceProcessor();
|
|
17786
|
+
onEnable() {
|
|
17787
|
+
this.subscribeToTraceLifecycle();
|
|
17788
|
+
}
|
|
17789
|
+
onDisable() {
|
|
17790
|
+
this.unsubscribers = unsubscribeAll(this.unsubscribers);
|
|
17791
|
+
void this.processor.shutdown();
|
|
17792
|
+
}
|
|
17793
|
+
subscribeToTraceLifecycle() {
|
|
17794
|
+
const traceStartChannel = openAIAgentsCoreChannels.onTraceStart.tracingChannel();
|
|
17795
|
+
const traceStartHandlers = {
|
|
17796
|
+
start: (event) => {
|
|
17797
|
+
const trace = firstArgument(event.arguments);
|
|
17798
|
+
if (isOpenAIAgentsTrace(trace)) {
|
|
17799
|
+
void this.processor.onTraceStart(trace);
|
|
17800
|
+
}
|
|
17801
|
+
}
|
|
17802
|
+
};
|
|
17803
|
+
traceStartChannel.subscribe(traceStartHandlers);
|
|
17804
|
+
this.unsubscribers.push(
|
|
17805
|
+
() => traceStartChannel.unsubscribe(traceStartHandlers)
|
|
17806
|
+
);
|
|
17807
|
+
const traceEndChannel = openAIAgentsCoreChannels.onTraceEnd.tracingChannel();
|
|
17808
|
+
const traceEndHandlers = {
|
|
17809
|
+
start: (event) => {
|
|
17810
|
+
const trace = firstArgument(event.arguments);
|
|
17811
|
+
if (isOpenAIAgentsTrace(trace)) {
|
|
17812
|
+
void this.processor.onTraceEnd(trace);
|
|
17813
|
+
}
|
|
17814
|
+
}
|
|
17815
|
+
};
|
|
17816
|
+
traceEndChannel.subscribe(traceEndHandlers);
|
|
17817
|
+
this.unsubscribers.push(
|
|
17818
|
+
() => traceEndChannel.unsubscribe(traceEndHandlers)
|
|
17819
|
+
);
|
|
17820
|
+
const spanStartChannel = openAIAgentsCoreChannels.onSpanStart.tracingChannel();
|
|
17821
|
+
const spanStartHandlers = {
|
|
17822
|
+
start: (event) => {
|
|
17823
|
+
const span = firstArgument(event.arguments);
|
|
17824
|
+
if (isOpenAIAgentsSpan(span)) {
|
|
17825
|
+
void this.processor.onSpanStart(span);
|
|
17826
|
+
}
|
|
17827
|
+
}
|
|
17828
|
+
};
|
|
17829
|
+
spanStartChannel.subscribe(spanStartHandlers);
|
|
17830
|
+
this.unsubscribers.push(
|
|
17831
|
+
() => spanStartChannel.unsubscribe(spanStartHandlers)
|
|
17832
|
+
);
|
|
17833
|
+
const spanEndChannel = openAIAgentsCoreChannels.onSpanEnd.tracingChannel();
|
|
17834
|
+
const spanEndHandlers = {
|
|
17835
|
+
start: (event) => {
|
|
17836
|
+
const span = firstArgument(event.arguments);
|
|
17837
|
+
if (isOpenAIAgentsSpan(span)) {
|
|
17838
|
+
void this.processor.onSpanEnd(span);
|
|
17839
|
+
}
|
|
17840
|
+
}
|
|
17841
|
+
};
|
|
17842
|
+
spanEndChannel.subscribe(spanEndHandlers);
|
|
17843
|
+
this.unsubscribers.push(() => spanEndChannel.unsubscribe(spanEndHandlers));
|
|
17844
|
+
}
|
|
17845
|
+
};
|
|
17846
|
+
|
|
17361
17847
|
// src/instrumentation/plugins/google-genai-channels.ts
|
|
17362
17848
|
var googleGenAIChannels = defineChannels("@google/genai", {
|
|
17363
17849
|
generateContent: channel({
|
|
@@ -23650,58 +24136,1794 @@ var GitHubCopilotPlugin = class extends BasePlugin {
|
|
|
23650
24136
|
}
|
|
23651
24137
|
};
|
|
23652
24138
|
|
|
23653
|
-
// src/instrumentation/
|
|
23654
|
-
|
|
23655
|
-
|
|
24139
|
+
// src/instrumentation/plugins/flue-channels.ts
|
|
24140
|
+
var flueChannels = defineChannels("@flue/runtime", {
|
|
24141
|
+
createContext: channel({
|
|
24142
|
+
channelName: "createFlueContext",
|
|
24143
|
+
kind: "sync-stream"
|
|
24144
|
+
}),
|
|
24145
|
+
openSession: channel({
|
|
24146
|
+
channelName: "Harness.openSession",
|
|
24147
|
+
kind: "async"
|
|
24148
|
+
}),
|
|
24149
|
+
contextEvent: channel({
|
|
24150
|
+
channelName: "context.event",
|
|
24151
|
+
kind: "sync-stream"
|
|
24152
|
+
}),
|
|
24153
|
+
prompt: channel({
|
|
24154
|
+
channelName: "session.prompt",
|
|
24155
|
+
kind: "async"
|
|
24156
|
+
}),
|
|
24157
|
+
skill: channel({
|
|
24158
|
+
channelName: "session.skill",
|
|
24159
|
+
kind: "async"
|
|
24160
|
+
}),
|
|
24161
|
+
task: channel({
|
|
24162
|
+
channelName: "session.task",
|
|
24163
|
+
kind: "async"
|
|
24164
|
+
}),
|
|
24165
|
+
compact: channel({
|
|
24166
|
+
channelName: "session.compact",
|
|
24167
|
+
kind: "async"
|
|
24168
|
+
})
|
|
24169
|
+
});
|
|
24170
|
+
|
|
24171
|
+
// src/wrappers/flue.ts
|
|
24172
|
+
var WRAPPED_FLUE_CONTEXT = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-context");
|
|
24173
|
+
var WRAPPED_FLUE_HARNESS = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-harness");
|
|
24174
|
+
var WRAPPED_FLUE_SESSION = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-session");
|
|
24175
|
+
var SUBSCRIBED_FLUE_CONTEXT_EVENTS = /* @__PURE__ */ Symbol.for(
|
|
24176
|
+
"braintrust.flue.subscribed-context-events"
|
|
24177
|
+
);
|
|
24178
|
+
function wrapFlueContext(ctx) {
|
|
24179
|
+
if (!isPlausibleFlueContext(ctx)) {
|
|
24180
|
+
console.warn("Unsupported Flue context. Not wrapping.");
|
|
24181
|
+
return ctx;
|
|
24182
|
+
}
|
|
24183
|
+
const context = ctx;
|
|
24184
|
+
subscribeFlueContextEvents(context, { captureTurnSpans: true });
|
|
24185
|
+
return patchFlueContextInPlace(context);
|
|
23656
24186
|
}
|
|
23657
|
-
|
|
23658
|
-
|
|
23659
|
-
|
|
23660
|
-
|
|
23661
|
-
anthropicPlugin = null;
|
|
23662
|
-
aiSDKPlugin = null;
|
|
23663
|
-
claudeAgentSDKPlugin = null;
|
|
23664
|
-
cursorSDKPlugin = null;
|
|
23665
|
-
googleGenAIPlugin = null;
|
|
23666
|
-
huggingFacePlugin = null;
|
|
23667
|
-
openRouterPlugin = null;
|
|
23668
|
-
openRouterAgentPlugin = null;
|
|
23669
|
-
mistralPlugin = null;
|
|
23670
|
-
googleADKPlugin = null;
|
|
23671
|
-
coherePlugin = null;
|
|
23672
|
-
groqPlugin = null;
|
|
23673
|
-
genkitPlugin = null;
|
|
23674
|
-
gitHubCopilotPlugin = null;
|
|
23675
|
-
constructor(config = {}) {
|
|
23676
|
-
super();
|
|
23677
|
-
this.config = config;
|
|
24187
|
+
function patchFlueContextInPlace(ctx) {
|
|
24188
|
+
const context = ctx;
|
|
24189
|
+
if (context[WRAPPED_FLUE_CONTEXT]) {
|
|
24190
|
+
return ctx;
|
|
23678
24191
|
}
|
|
23679
|
-
|
|
23680
|
-
|
|
23681
|
-
|
|
23682
|
-
|
|
23683
|
-
|
|
23684
|
-
|
|
23685
|
-
|
|
23686
|
-
|
|
23687
|
-
|
|
23688
|
-
|
|
23689
|
-
|
|
23690
|
-
|
|
23691
|
-
|
|
23692
|
-
|
|
23693
|
-
|
|
23694
|
-
|
|
23695
|
-
|
|
23696
|
-
|
|
23697
|
-
|
|
23698
|
-
|
|
24192
|
+
const originalInit = context.init.bind(context);
|
|
24193
|
+
try {
|
|
24194
|
+
Object.defineProperty(context, WRAPPED_FLUE_CONTEXT, {
|
|
24195
|
+
configurable: false,
|
|
24196
|
+
enumerable: false,
|
|
24197
|
+
value: true
|
|
24198
|
+
});
|
|
24199
|
+
Object.defineProperty(context, "init", {
|
|
24200
|
+
configurable: true,
|
|
24201
|
+
value: async function wrappedFlueInit(options) {
|
|
24202
|
+
const harness = await originalInit(options);
|
|
24203
|
+
return wrapFlueHarness(harness);
|
|
24204
|
+
},
|
|
24205
|
+
writable: true
|
|
24206
|
+
});
|
|
24207
|
+
} catch {
|
|
24208
|
+
}
|
|
24209
|
+
return ctx;
|
|
24210
|
+
}
|
|
24211
|
+
function wrapFlueSession(session) {
|
|
24212
|
+
if (!isPlausibleFlueSession(session)) {
|
|
24213
|
+
console.warn("Unsupported Flue session. Not wrapping.");
|
|
24214
|
+
return session;
|
|
24215
|
+
}
|
|
24216
|
+
return patchFlueSessionInPlace(session);
|
|
24217
|
+
}
|
|
24218
|
+
function subscribeFlueContextEvents(ctx, options = {}) {
|
|
24219
|
+
if (!ctx || typeof ctx !== "object" || typeof ctx.subscribeEvent !== "function") {
|
|
24220
|
+
return void 0;
|
|
24221
|
+
}
|
|
24222
|
+
const context = ctx;
|
|
24223
|
+
const captureTurnSpans = options.captureTurnSpans ?? true;
|
|
24224
|
+
const existingSubscription = context[SUBSCRIBED_FLUE_CONTEXT_EVENTS];
|
|
24225
|
+
if (existingSubscription) {
|
|
24226
|
+
if (existingSubscription.captureTurnSpans || !captureTurnSpans) {
|
|
24227
|
+
return void 0;
|
|
24228
|
+
}
|
|
24229
|
+
try {
|
|
24230
|
+
existingSubscription.unsubscribe();
|
|
24231
|
+
} catch {
|
|
24232
|
+
}
|
|
24233
|
+
}
|
|
24234
|
+
try {
|
|
24235
|
+
const unsubscribe = ctx.subscribeEvent((event) => {
|
|
24236
|
+
flueChannels.contextEvent.traceSync(() => void 0, {
|
|
24237
|
+
arguments: [event],
|
|
24238
|
+
captureTurnSpans,
|
|
24239
|
+
context: ctx
|
|
24240
|
+
});
|
|
24241
|
+
});
|
|
24242
|
+
if (existingSubscription) {
|
|
24243
|
+
existingSubscription.captureTurnSpans = captureTurnSpans;
|
|
24244
|
+
existingSubscription.unsubscribe = unsubscribe;
|
|
24245
|
+
} else {
|
|
24246
|
+
Object.defineProperty(context, SUBSCRIBED_FLUE_CONTEXT_EVENTS, {
|
|
24247
|
+
configurable: false,
|
|
24248
|
+
enumerable: false,
|
|
24249
|
+
value: {
|
|
24250
|
+
captureTurnSpans,
|
|
24251
|
+
unsubscribe
|
|
24252
|
+
}
|
|
24253
|
+
});
|
|
24254
|
+
}
|
|
24255
|
+
return unsubscribe;
|
|
24256
|
+
} catch {
|
|
24257
|
+
return void 0;
|
|
24258
|
+
}
|
|
24259
|
+
}
|
|
24260
|
+
function wrapFlueHarness(harness) {
|
|
24261
|
+
if (!isPlausibleFlueHarness(harness)) {
|
|
24262
|
+
return harness;
|
|
24263
|
+
}
|
|
24264
|
+
const target = harness;
|
|
24265
|
+
if (target[WRAPPED_FLUE_HARNESS]) {
|
|
24266
|
+
return harness;
|
|
24267
|
+
}
|
|
24268
|
+
const originalSession = target.session.bind(target);
|
|
24269
|
+
try {
|
|
24270
|
+
Object.defineProperty(target, WRAPPED_FLUE_HARNESS, {
|
|
24271
|
+
configurable: false,
|
|
24272
|
+
enumerable: false,
|
|
24273
|
+
value: true
|
|
24274
|
+
});
|
|
24275
|
+
Object.defineProperty(target, "session", {
|
|
24276
|
+
configurable: true,
|
|
24277
|
+
value: async function wrappedFlueHarnessSession(name, options) {
|
|
24278
|
+
const session = await originalSession(name, options);
|
|
24279
|
+
return patchFlueSessionInPlace(session);
|
|
24280
|
+
},
|
|
24281
|
+
writable: true
|
|
24282
|
+
});
|
|
24283
|
+
const sessions = target.sessions;
|
|
24284
|
+
if (sessions && typeof sessions === "object") {
|
|
24285
|
+
patchFlueSessionFactory(sessions, "get");
|
|
24286
|
+
patchFlueSessionFactory(sessions, "create");
|
|
24287
|
+
}
|
|
24288
|
+
} catch {
|
|
24289
|
+
}
|
|
24290
|
+
return harness;
|
|
24291
|
+
}
|
|
24292
|
+
function patchFlueSessionInPlace(session) {
|
|
24293
|
+
if (session[WRAPPED_FLUE_SESSION]) {
|
|
24294
|
+
return session;
|
|
24295
|
+
}
|
|
24296
|
+
try {
|
|
24297
|
+
Object.defineProperty(session, WRAPPED_FLUE_SESSION, {
|
|
24298
|
+
configurable: false,
|
|
24299
|
+
enumerable: false,
|
|
24300
|
+
value: true
|
|
24301
|
+
});
|
|
24302
|
+
patchCallHandleMethod(session, "prompt", flueChannels.prompt);
|
|
24303
|
+
patchCallHandleMethod(session, "skill", flueChannels.skill);
|
|
24304
|
+
patchCallHandleMethod(session, "task", flueChannels.task);
|
|
24305
|
+
patchCompact(session);
|
|
24306
|
+
} catch {
|
|
24307
|
+
}
|
|
24308
|
+
return session;
|
|
24309
|
+
}
|
|
24310
|
+
function patchFlueSessionFactory(sessions, method) {
|
|
24311
|
+
const original = sessions[method];
|
|
24312
|
+
if (typeof original !== "function") {
|
|
24313
|
+
return;
|
|
24314
|
+
}
|
|
24315
|
+
const bound = original.bind(sessions);
|
|
24316
|
+
Object.defineProperty(sessions, method, {
|
|
24317
|
+
configurable: true,
|
|
24318
|
+
value: async function wrappedFlueSessionFactory(name, options) {
|
|
24319
|
+
const session = await bound(name, options);
|
|
24320
|
+
return patchFlueSessionInPlace(session);
|
|
24321
|
+
},
|
|
24322
|
+
writable: true
|
|
24323
|
+
});
|
|
24324
|
+
}
|
|
24325
|
+
function patchCallHandleMethod(session, method, channel2) {
|
|
24326
|
+
const original = session[method];
|
|
24327
|
+
if (typeof original !== "function") {
|
|
24328
|
+
return;
|
|
24329
|
+
}
|
|
24330
|
+
const bound = original.bind(session);
|
|
24331
|
+
Object.defineProperty(session, method, {
|
|
24332
|
+
configurable: true,
|
|
24333
|
+
value(input, options) {
|
|
24334
|
+
const args = [input, options];
|
|
24335
|
+
const { originalResult, traced: traced2 } = traceFlueOperation(channel2, {
|
|
24336
|
+
context: {
|
|
24337
|
+
arguments: args,
|
|
24338
|
+
operation: method,
|
|
24339
|
+
session
|
|
24340
|
+
},
|
|
24341
|
+
run: () => bound(input, options)
|
|
24342
|
+
});
|
|
24343
|
+
return preserveCallHandle(originalResult, traced2);
|
|
24344
|
+
},
|
|
24345
|
+
writable: true
|
|
24346
|
+
});
|
|
24347
|
+
}
|
|
24348
|
+
function patchCompact(session) {
|
|
24349
|
+
const original = session.compact;
|
|
24350
|
+
if (typeof original !== "function") {
|
|
24351
|
+
return;
|
|
24352
|
+
}
|
|
24353
|
+
const bound = original.bind(session);
|
|
24354
|
+
Object.defineProperty(session, "compact", {
|
|
24355
|
+
configurable: true,
|
|
24356
|
+
value() {
|
|
24357
|
+
const context = {
|
|
24358
|
+
arguments: [],
|
|
24359
|
+
operation: "compact",
|
|
24360
|
+
session
|
|
24361
|
+
};
|
|
24362
|
+
return flueChannels.compact.tracePromise(() => bound(), context);
|
|
24363
|
+
},
|
|
24364
|
+
writable: true
|
|
24365
|
+
});
|
|
24366
|
+
}
|
|
24367
|
+
function traceFlueOperation(channel2, args) {
|
|
24368
|
+
const tracingChannel2 = channel2.tracingChannel();
|
|
24369
|
+
const context = args.context;
|
|
24370
|
+
let originalResult;
|
|
24371
|
+
let traced2;
|
|
24372
|
+
const run = () => {
|
|
24373
|
+
try {
|
|
24374
|
+
originalResult = args.run();
|
|
24375
|
+
tracingChannel2.end?.publish(context);
|
|
24376
|
+
} catch (error) {
|
|
24377
|
+
context.error = normalizeError3(error);
|
|
24378
|
+
tracingChannel2.error?.publish(context);
|
|
24379
|
+
tracingChannel2.end?.publish(context);
|
|
24380
|
+
throw error;
|
|
24381
|
+
}
|
|
24382
|
+
traced2 = Promise.resolve(originalResult).then(
|
|
24383
|
+
(result) => {
|
|
24384
|
+
context.result = result;
|
|
24385
|
+
tracingChannel2.asyncStart?.publish(context);
|
|
24386
|
+
tracingChannel2.asyncEnd?.publish(context);
|
|
24387
|
+
return result;
|
|
24388
|
+
},
|
|
24389
|
+
(error) => {
|
|
24390
|
+
context.error = normalizeError3(error);
|
|
24391
|
+
tracingChannel2.error?.publish(context);
|
|
24392
|
+
tracingChannel2.asyncStart?.publish(context);
|
|
24393
|
+
tracingChannel2.asyncEnd?.publish(context);
|
|
24394
|
+
throw error;
|
|
24395
|
+
}
|
|
24396
|
+
);
|
|
24397
|
+
};
|
|
24398
|
+
if (tracingChannel2.start?.runStores) {
|
|
24399
|
+
tracingChannel2.start.runStores(context, run);
|
|
24400
|
+
} else {
|
|
24401
|
+
tracingChannel2.start?.publish(context);
|
|
24402
|
+
run();
|
|
24403
|
+
}
|
|
24404
|
+
return { originalResult, traced: traced2 };
|
|
24405
|
+
}
|
|
24406
|
+
function normalizeError3(error) {
|
|
24407
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
24408
|
+
}
|
|
24409
|
+
function preserveCallHandle(originalHandle, traced2) {
|
|
24410
|
+
if (!isFlueCallHandle(originalHandle)) {
|
|
24411
|
+
return traced2;
|
|
24412
|
+
}
|
|
24413
|
+
const handle = originalHandle;
|
|
24414
|
+
const wrapped = {
|
|
24415
|
+
get signal() {
|
|
24416
|
+
return handle.signal;
|
|
24417
|
+
},
|
|
24418
|
+
abort(reason) {
|
|
24419
|
+
return handle.abort(reason);
|
|
24420
|
+
},
|
|
24421
|
+
then(onfulfilled, onrejected) {
|
|
24422
|
+
return traced2.then(onfulfilled, onrejected);
|
|
24423
|
+
}
|
|
24424
|
+
};
|
|
24425
|
+
return wrapped;
|
|
24426
|
+
}
|
|
24427
|
+
function isPlausibleFlueContext(value) {
|
|
24428
|
+
return !!value && typeof value === "object" && typeof value.init === "function";
|
|
24429
|
+
}
|
|
24430
|
+
function isPlausibleFlueHarness(value) {
|
|
24431
|
+
return !!value && typeof value === "object" && typeof value.session === "function";
|
|
24432
|
+
}
|
|
24433
|
+
function isPlausibleFlueSession(value) {
|
|
24434
|
+
return !!value && typeof value === "object" && typeof value.prompt === "function" && typeof value.skill === "function" && typeof value.task === "function" && typeof value.compact === "function";
|
|
24435
|
+
}
|
|
24436
|
+
function isFlueCallHandle(value) {
|
|
24437
|
+
return !!value && typeof value === "object" && typeof value.then === "function" && typeof value.abort === "function" && "signal" in value;
|
|
24438
|
+
}
|
|
24439
|
+
|
|
24440
|
+
// src/instrumentation/plugins/flue-plugin.ts
|
|
24441
|
+
var FluePlugin = class extends BasePlugin {
|
|
24442
|
+
activeOperationsById = /* @__PURE__ */ new Map();
|
|
24443
|
+
activeOperationsByScope = /* @__PURE__ */ new Map();
|
|
24444
|
+
compactionsByScope = /* @__PURE__ */ new Map();
|
|
24445
|
+
pendingOperationsByKey = /* @__PURE__ */ new Map();
|
|
24446
|
+
tasksById = /* @__PURE__ */ new Map();
|
|
24447
|
+
toolsById = /* @__PURE__ */ new Map();
|
|
24448
|
+
turnsByScope = /* @__PURE__ */ new Map();
|
|
24449
|
+
onEnable() {
|
|
24450
|
+
this.subscribeToContextCreation();
|
|
24451
|
+
this.subscribeToSessionCreation();
|
|
24452
|
+
this.subscribeToContextEvents();
|
|
24453
|
+
this.subscribeToSessionOperations();
|
|
24454
|
+
}
|
|
24455
|
+
onDisable() {
|
|
24456
|
+
for (const unsubscribe of this.unsubscribers) {
|
|
24457
|
+
unsubscribe();
|
|
24458
|
+
}
|
|
24459
|
+
this.unsubscribers = [];
|
|
24460
|
+
this.activeOperationsById.clear();
|
|
24461
|
+
this.activeOperationsByScope.clear();
|
|
24462
|
+
this.compactionsByScope.clear();
|
|
24463
|
+
this.pendingOperationsByKey.clear();
|
|
24464
|
+
this.tasksById.clear();
|
|
24465
|
+
this.toolsById.clear();
|
|
24466
|
+
this.turnsByScope.clear();
|
|
24467
|
+
}
|
|
24468
|
+
subscribeToContextCreation() {
|
|
24469
|
+
const channel2 = flueChannels.createContext.tracingChannel();
|
|
24470
|
+
const handlers = {
|
|
24471
|
+
end: (event) => {
|
|
24472
|
+
const ctx = event.result;
|
|
24473
|
+
if (!ctx) {
|
|
24474
|
+
return;
|
|
24475
|
+
}
|
|
24476
|
+
subscribeFlueContextEvents(ctx, { captureTurnSpans: false });
|
|
24477
|
+
patchFlueContextInPlace(ctx);
|
|
24478
|
+
},
|
|
24479
|
+
error: () => {
|
|
24480
|
+
}
|
|
24481
|
+
};
|
|
24482
|
+
channel2.subscribe(handlers);
|
|
24483
|
+
this.unsubscribers.push(() => {
|
|
24484
|
+
channel2.unsubscribe(handlers);
|
|
24485
|
+
});
|
|
24486
|
+
}
|
|
24487
|
+
subscribeToSessionCreation() {
|
|
24488
|
+
const channel2 = flueChannels.openSession.tracingChannel();
|
|
24489
|
+
const handlers = {
|
|
24490
|
+
asyncEnd: (event) => {
|
|
24491
|
+
if (event.result) {
|
|
24492
|
+
patchFlueSessionInPlace(
|
|
24493
|
+
event.result
|
|
24494
|
+
);
|
|
24495
|
+
}
|
|
24496
|
+
if (event.harness) {
|
|
24497
|
+
wrapFlueHarness(event.harness);
|
|
24498
|
+
}
|
|
24499
|
+
},
|
|
24500
|
+
error: () => {
|
|
24501
|
+
}
|
|
24502
|
+
};
|
|
24503
|
+
channel2.subscribe(handlers);
|
|
24504
|
+
this.unsubscribers.push(() => {
|
|
24505
|
+
channel2.unsubscribe(handlers);
|
|
24506
|
+
});
|
|
24507
|
+
}
|
|
24508
|
+
subscribeToSessionOperations() {
|
|
24509
|
+
this.subscribeToSessionOperation(flueChannels.prompt);
|
|
24510
|
+
this.subscribeToSessionOperation(flueChannels.skill);
|
|
24511
|
+
this.subscribeToSessionOperation(flueChannels.task);
|
|
24512
|
+
this.subscribeToCompact();
|
|
24513
|
+
}
|
|
24514
|
+
subscribeToSessionOperation(channel2) {
|
|
24515
|
+
const tracingChannel2 = channel2.tracingChannel();
|
|
24516
|
+
const states = /* @__PURE__ */ new WeakMap();
|
|
24517
|
+
const ensureState2 = (event) => {
|
|
24518
|
+
const existing = states.get(event);
|
|
24519
|
+
if (existing) {
|
|
24520
|
+
return existing;
|
|
24521
|
+
}
|
|
24522
|
+
const state = this.startOperationState({
|
|
24523
|
+
args: event.arguments,
|
|
24524
|
+
moduleVersion: typeof event.moduleVersion === "string" ? event.moduleVersion : void 0,
|
|
24525
|
+
operation: event.operation,
|
|
24526
|
+
session: event.session
|
|
24527
|
+
});
|
|
24528
|
+
states.set(event, state);
|
|
24529
|
+
return state;
|
|
24530
|
+
};
|
|
24531
|
+
const unbindCurrentSpanStore = this.bindCurrentSpanStoreToOperationStart(
|
|
24532
|
+
tracingChannel2,
|
|
24533
|
+
ensureState2
|
|
24534
|
+
);
|
|
24535
|
+
const handlers = {
|
|
24536
|
+
start: (event) => {
|
|
24537
|
+
ensureState2(event);
|
|
24538
|
+
},
|
|
24539
|
+
asyncEnd: (event) => {
|
|
24540
|
+
this.endOperationState(states.get(event), event.result);
|
|
24541
|
+
states.delete(event);
|
|
24542
|
+
},
|
|
24543
|
+
error: (event) => {
|
|
24544
|
+
const state = states.get(event);
|
|
24545
|
+
if (state && event.error) {
|
|
24546
|
+
safeLog3(state.span, { error: errorToString(event.error) });
|
|
24547
|
+
this.finishOperationState(state);
|
|
24548
|
+
}
|
|
24549
|
+
states.delete(event);
|
|
24550
|
+
}
|
|
24551
|
+
};
|
|
24552
|
+
tracingChannel2.subscribe(handlers);
|
|
24553
|
+
this.unsubscribers.push(() => {
|
|
24554
|
+
unbindCurrentSpanStore?.();
|
|
24555
|
+
tracingChannel2.unsubscribe(handlers);
|
|
24556
|
+
});
|
|
24557
|
+
}
|
|
24558
|
+
subscribeToCompact() {
|
|
24559
|
+
const tracingChannel2 = flueChannels.compact.tracingChannel();
|
|
24560
|
+
const states = /* @__PURE__ */ new WeakMap();
|
|
24561
|
+
const ensureState2 = (event) => {
|
|
24562
|
+
const existing = states.get(event);
|
|
24563
|
+
if (existing) {
|
|
24564
|
+
return existing;
|
|
24565
|
+
}
|
|
24566
|
+
const state = this.startOperationState({
|
|
24567
|
+
args: [],
|
|
24568
|
+
moduleVersion: typeof event.moduleVersion === "string" ? event.moduleVersion : void 0,
|
|
24569
|
+
operation: event.operation,
|
|
24570
|
+
session: event.session
|
|
24571
|
+
});
|
|
24572
|
+
states.set(event, state);
|
|
24573
|
+
return state;
|
|
24574
|
+
};
|
|
24575
|
+
const unbindCurrentSpanStore = this.bindCurrentSpanStoreToOperationStart(
|
|
24576
|
+
tracingChannel2,
|
|
24577
|
+
ensureState2
|
|
24578
|
+
);
|
|
24579
|
+
const handlers = {
|
|
24580
|
+
start: (event) => {
|
|
24581
|
+
ensureState2(event);
|
|
24582
|
+
},
|
|
24583
|
+
asyncEnd: (event) => {
|
|
24584
|
+
this.endOperationState(states.get(event), void 0);
|
|
24585
|
+
states.delete(event);
|
|
24586
|
+
},
|
|
24587
|
+
error: (event) => {
|
|
24588
|
+
const state = states.get(event);
|
|
24589
|
+
if (state && event.error) {
|
|
24590
|
+
safeLog3(state.span, { error: errorToString(event.error) });
|
|
24591
|
+
this.finishOperationState(state);
|
|
24592
|
+
}
|
|
24593
|
+
states.delete(event);
|
|
24594
|
+
}
|
|
24595
|
+
};
|
|
24596
|
+
tracingChannel2.subscribe(handlers);
|
|
24597
|
+
this.unsubscribers.push(() => {
|
|
24598
|
+
unbindCurrentSpanStore?.();
|
|
24599
|
+
tracingChannel2.unsubscribe(handlers);
|
|
24600
|
+
});
|
|
24601
|
+
}
|
|
24602
|
+
subscribeToContextEvents() {
|
|
24603
|
+
const channel2 = flueChannels.contextEvent.tracingChannel();
|
|
24604
|
+
const handlers = {
|
|
24605
|
+
start: (event) => {
|
|
24606
|
+
const flueEvent = event.arguments[0];
|
|
24607
|
+
if (!flueEvent) {
|
|
24608
|
+
return;
|
|
24609
|
+
}
|
|
24610
|
+
try {
|
|
24611
|
+
this.handleFlueEvent(flueEvent, {
|
|
24612
|
+
captureTurnSpans: event.captureTurnSpans !== false
|
|
24613
|
+
});
|
|
24614
|
+
} catch (error) {
|
|
24615
|
+
logInstrumentationError3("Flue event", error);
|
|
24616
|
+
}
|
|
24617
|
+
},
|
|
24618
|
+
error: () => {
|
|
24619
|
+
}
|
|
24620
|
+
};
|
|
24621
|
+
channel2.subscribe(handlers);
|
|
24622
|
+
this.unsubscribers.push(() => {
|
|
24623
|
+
channel2.unsubscribe(handlers);
|
|
24624
|
+
});
|
|
24625
|
+
}
|
|
24626
|
+
bindCurrentSpanStoreToOperationStart(tracingChannel2, ensureState2) {
|
|
24627
|
+
const state = _internalGetGlobalState();
|
|
24628
|
+
const startChannel = tracingChannel2.start;
|
|
24629
|
+
const contextManager = state?.contextManager;
|
|
24630
|
+
const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
|
|
24631
|
+
if (!currentSpanStore || !startChannel) {
|
|
24632
|
+
return void 0;
|
|
24633
|
+
}
|
|
24634
|
+
startChannel.bindStore(currentSpanStore, (event) => {
|
|
24635
|
+
const operationState = ensureState2(event);
|
|
24636
|
+
return contextManager.wrapSpanForStore(operationState.span);
|
|
24637
|
+
});
|
|
24638
|
+
return () => {
|
|
24639
|
+
startChannel.unbindStore(currentSpanStore);
|
|
24640
|
+
};
|
|
24641
|
+
}
|
|
24642
|
+
startOperationState(args) {
|
|
24643
|
+
const sessionName = getSessionName(args.session);
|
|
24644
|
+
const metadata = {
|
|
24645
|
+
...extractOperationInputMetadata(args.operation, args.args),
|
|
24646
|
+
...extractSessionMetadata(args.session),
|
|
24647
|
+
"flue.operation": args.operation,
|
|
24648
|
+
provider: "flue",
|
|
24649
|
+
...args.moduleVersion ? { "flue.version": args.moduleVersion } : {}
|
|
24650
|
+
};
|
|
24651
|
+
const span = startSpan({
|
|
24652
|
+
name: `flue.session.${args.operation}`,
|
|
24653
|
+
spanAttributes: { type: "task" /* TASK */ }
|
|
24654
|
+
});
|
|
24655
|
+
const state = {
|
|
24656
|
+
metadata,
|
|
24657
|
+
operation: args.operation,
|
|
24658
|
+
sessionName,
|
|
24659
|
+
span,
|
|
24660
|
+
startTime: getCurrentUnixTimestamp()
|
|
24661
|
+
};
|
|
24662
|
+
safeLog3(span, {
|
|
24663
|
+
input: extractOperationInput(args.operation, args.args),
|
|
24664
|
+
metadata
|
|
24665
|
+
});
|
|
24666
|
+
this.pendingOperationQueue(operationKey(sessionName, args.operation)).push(
|
|
24667
|
+
state
|
|
24668
|
+
);
|
|
24669
|
+
addOperationToScope(
|
|
24670
|
+
this.activeOperationsByScope,
|
|
24671
|
+
sessionName ?? "unknown",
|
|
24672
|
+
state
|
|
24673
|
+
);
|
|
24674
|
+
return state;
|
|
24675
|
+
}
|
|
24676
|
+
endOperationState(state, result) {
|
|
24677
|
+
if (!state) {
|
|
24678
|
+
return;
|
|
24679
|
+
}
|
|
24680
|
+
const metadata = {
|
|
24681
|
+
...state.metadata,
|
|
24682
|
+
...extractPromptResponseMetadata(result)
|
|
24683
|
+
};
|
|
24684
|
+
const metrics = {
|
|
24685
|
+
...buildDurationMetrics3(state.startTime),
|
|
24686
|
+
...metricsFromUsage(result?.usage)
|
|
24687
|
+
};
|
|
24688
|
+
safeLog3(state.span, {
|
|
24689
|
+
metadata,
|
|
24690
|
+
metrics,
|
|
24691
|
+
output: extractOperationOutput(result)
|
|
24692
|
+
});
|
|
24693
|
+
this.finishCompactionsForOperation(state);
|
|
24694
|
+
this.finishOperationState(state);
|
|
24695
|
+
}
|
|
24696
|
+
finishOperationState(state) {
|
|
24697
|
+
removePendingOperation(this.pendingOperationsByKey, state);
|
|
24698
|
+
if (state.operationId) {
|
|
24699
|
+
this.activeOperationsById.delete(state.operationId);
|
|
24700
|
+
}
|
|
24701
|
+
removeScopedOperation(this.activeOperationsByScope, state);
|
|
24702
|
+
state.span.end();
|
|
24703
|
+
}
|
|
24704
|
+
handleFlueEvent(event, options) {
|
|
24705
|
+
switch (event.type) {
|
|
24706
|
+
case "operation_start":
|
|
24707
|
+
this.handleOperationStart(event);
|
|
24708
|
+
return;
|
|
24709
|
+
case "operation":
|
|
24710
|
+
this.handleOperation(event);
|
|
24711
|
+
return;
|
|
24712
|
+
case "text_delta":
|
|
24713
|
+
if (!options.captureTurnSpans) {
|
|
24714
|
+
return;
|
|
24715
|
+
}
|
|
24716
|
+
this.ensureTurnState(event).text.push(
|
|
24717
|
+
typeof event.text === "string" ? event.text : ""
|
|
24718
|
+
);
|
|
24719
|
+
return;
|
|
24720
|
+
case "thinking_start":
|
|
24721
|
+
if (!options.captureTurnSpans) {
|
|
24722
|
+
return;
|
|
24723
|
+
}
|
|
24724
|
+
this.handleThinkingStart(event);
|
|
24725
|
+
return;
|
|
24726
|
+
case "thinking_delta":
|
|
24727
|
+
if (!options.captureTurnSpans) {
|
|
24728
|
+
return;
|
|
24729
|
+
}
|
|
24730
|
+
this.handleThinkingDelta(event);
|
|
24731
|
+
return;
|
|
24732
|
+
case "thinking_end":
|
|
24733
|
+
if (!options.captureTurnSpans) {
|
|
24734
|
+
return;
|
|
24735
|
+
}
|
|
24736
|
+
this.handleThinkingEnd(event);
|
|
24737
|
+
return;
|
|
24738
|
+
case "turn":
|
|
24739
|
+
if (!options.captureTurnSpans) {
|
|
24740
|
+
return;
|
|
24741
|
+
}
|
|
24742
|
+
this.handleTurn(event);
|
|
24743
|
+
return;
|
|
24744
|
+
case "tool_start":
|
|
24745
|
+
this.handleToolStart(event, options);
|
|
24746
|
+
return;
|
|
24747
|
+
case "tool_call":
|
|
24748
|
+
this.handleToolCall(event);
|
|
24749
|
+
return;
|
|
24750
|
+
case "task_start":
|
|
24751
|
+
this.handleTaskStart(event);
|
|
24752
|
+
return;
|
|
24753
|
+
case "task":
|
|
24754
|
+
this.handleTask(event);
|
|
24755
|
+
return;
|
|
24756
|
+
case "compaction_start":
|
|
24757
|
+
this.handleCompactionStart(event);
|
|
24758
|
+
return;
|
|
24759
|
+
case "compaction":
|
|
24760
|
+
this.handleCompaction(event);
|
|
24761
|
+
return;
|
|
24762
|
+
default:
|
|
24763
|
+
return;
|
|
24764
|
+
}
|
|
24765
|
+
}
|
|
24766
|
+
handleOperationStart(event) {
|
|
24767
|
+
if (!isInstrumentedOperation(event.operationKind)) {
|
|
24768
|
+
return;
|
|
24769
|
+
}
|
|
24770
|
+
const state = this.takePendingOperationForEvent(event);
|
|
24771
|
+
if (!state) {
|
|
24772
|
+
return;
|
|
24773
|
+
}
|
|
24774
|
+
state.operationId = event.operationId;
|
|
24775
|
+
this.activeOperationsById.set(event.operationId, state);
|
|
24776
|
+
addScopedOperation(this.activeOperationsByScope, event, state);
|
|
24777
|
+
state.metadata = {
|
|
24778
|
+
...state.metadata,
|
|
24779
|
+
...extractEventMetadata(event),
|
|
24780
|
+
"flue.operation_id": event.operationId
|
|
24781
|
+
};
|
|
24782
|
+
safeLog3(state.span, { metadata: state.metadata });
|
|
24783
|
+
}
|
|
24784
|
+
handleOperation(event) {
|
|
24785
|
+
const state = event.operationId ? this.activeOperationsById.get(event.operationId) : void 0;
|
|
24786
|
+
if (!state) {
|
|
24787
|
+
return;
|
|
24788
|
+
}
|
|
24789
|
+
const metadata = {
|
|
24790
|
+
...state.metadata,
|
|
24791
|
+
...extractEventMetadata(event),
|
|
24792
|
+
...typeof event.durationMs === "number" ? { "flue.duration_ms": event.durationMs } : {},
|
|
24793
|
+
...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
|
|
24794
|
+
};
|
|
24795
|
+
const metrics = metricsFromUsage(event.usage);
|
|
24796
|
+
safeLog3(state.span, {
|
|
24797
|
+
...event.error ? { error: errorToString(event.error) } : {},
|
|
24798
|
+
metadata,
|
|
24799
|
+
...Object.keys(metrics).length ? { metrics } : {}
|
|
24800
|
+
});
|
|
24801
|
+
}
|
|
24802
|
+
ensureTurnState(event) {
|
|
24803
|
+
const scope = scopeKey(event);
|
|
24804
|
+
const existing = this.turnsByScope.get(scope);
|
|
24805
|
+
if (existing) {
|
|
24806
|
+
return existing;
|
|
24807
|
+
}
|
|
24808
|
+
const parent = this.parentSpanForEvent(event);
|
|
24809
|
+
const metadata = {
|
|
24810
|
+
...extractEventMetadata(event),
|
|
24811
|
+
provider: "flue"
|
|
24812
|
+
};
|
|
24813
|
+
const span = startFlueSpan(parent, {
|
|
24814
|
+
name: "flue.turn",
|
|
24815
|
+
spanAttributes: { type: "llm" /* LLM */ }
|
|
24816
|
+
});
|
|
24817
|
+
const state = {
|
|
24818
|
+
metadata,
|
|
24819
|
+
span,
|
|
24820
|
+
hasThinking: false,
|
|
24821
|
+
startTime: getCurrentUnixTimestamp(),
|
|
24822
|
+
text: [],
|
|
24823
|
+
thinking: [],
|
|
24824
|
+
toolCalls: []
|
|
24825
|
+
};
|
|
24826
|
+
safeLog3(span, { metadata });
|
|
24827
|
+
this.turnsByScope.set(scope, state);
|
|
24828
|
+
return state;
|
|
24829
|
+
}
|
|
24830
|
+
handleTurn(event) {
|
|
24831
|
+
const scope = scopeKey(event);
|
|
24832
|
+
const state = this.ensureTurnState(event);
|
|
24833
|
+
const text = state.text.join("");
|
|
24834
|
+
const reasoning = state.finalThinking ?? state.thinking.join("");
|
|
24835
|
+
const outputReasoning = reasoning || (state.hasThinking ? "[reasoning stream present; content unavailable]" : void 0);
|
|
24836
|
+
const metadata = {
|
|
24837
|
+
...state.metadata,
|
|
24838
|
+
...extractEventMetadata(event),
|
|
24839
|
+
...event.model ? { model: event.model, "flue.model": event.model } : {},
|
|
24840
|
+
...event.stopReason ? { "flue.stop_reason": event.stopReason } : {},
|
|
24841
|
+
...event.isError !== void 0 ? { "flue.is_error": event.isError } : {},
|
|
24842
|
+
provider: "flue"
|
|
24843
|
+
};
|
|
24844
|
+
safeLog3(state.span, {
|
|
24845
|
+
...event.error ? { error: errorToString(event.error) } : {},
|
|
24846
|
+
metadata,
|
|
24847
|
+
metrics: {
|
|
24848
|
+
...durationMsMetrics(event.durationMs),
|
|
24849
|
+
...metricsFromUsage(event.usage)
|
|
24850
|
+
},
|
|
24851
|
+
output: toAssistantOutput(
|
|
24852
|
+
text,
|
|
24853
|
+
event.stopReason,
|
|
24854
|
+
outputReasoning,
|
|
24855
|
+
state.toolCalls
|
|
24856
|
+
)
|
|
24857
|
+
});
|
|
24858
|
+
state.span.end();
|
|
24859
|
+
this.turnsByScope.delete(scope);
|
|
24860
|
+
}
|
|
24861
|
+
handleThinkingDelta(event) {
|
|
24862
|
+
const delta = event.delta;
|
|
24863
|
+
if (typeof delta !== "string" || !delta) {
|
|
24864
|
+
return;
|
|
24865
|
+
}
|
|
24866
|
+
const state = this.ensureTurnState(event);
|
|
24867
|
+
state.hasThinking = true;
|
|
24868
|
+
state.metadata["flue.thinking"] = true;
|
|
24869
|
+
state.thinking.push(delta);
|
|
24870
|
+
}
|
|
24871
|
+
handleThinkingStart(event) {
|
|
24872
|
+
const state = this.ensureTurnState(event);
|
|
24873
|
+
state.hasThinking = true;
|
|
24874
|
+
state.metadata["flue.thinking"] = true;
|
|
24875
|
+
}
|
|
24876
|
+
handleThinkingEnd(event) {
|
|
24877
|
+
const state = this.ensureTurnState(event);
|
|
24878
|
+
state.hasThinking = true;
|
|
24879
|
+
state.metadata["flue.thinking"] = true;
|
|
24880
|
+
if (typeof event.content === "string" && event.content) {
|
|
24881
|
+
state.finalThinking = event.content;
|
|
24882
|
+
}
|
|
24883
|
+
}
|
|
24884
|
+
handleToolStart(event, options) {
|
|
24885
|
+
const toolCallId = event.toolCallId;
|
|
24886
|
+
if (!toolCallId) {
|
|
24887
|
+
return;
|
|
24888
|
+
}
|
|
24889
|
+
const parent = this.parentSpanForEvent(event);
|
|
24890
|
+
const scope = scopeKey(event);
|
|
24891
|
+
let turnState = this.turnsByScope.get(scope);
|
|
24892
|
+
if (!turnState && parent && options.captureTurnSpans) {
|
|
24893
|
+
turnState = this.ensureTurnState(event);
|
|
24894
|
+
}
|
|
24895
|
+
const metadata = {
|
|
24896
|
+
...extractEventMetadata(event),
|
|
24897
|
+
...event.toolName ? { "flue.tool_name": event.toolName } : {},
|
|
24898
|
+
"flue.tool_call_id": toolCallId,
|
|
24899
|
+
provider: "flue"
|
|
24900
|
+
};
|
|
24901
|
+
const span = startFlueSpan(parent, {
|
|
24902
|
+
name: `tool: ${event.toolName ?? "unknown"}`,
|
|
24903
|
+
spanAttributes: { type: "tool" /* TOOL */ }
|
|
24904
|
+
});
|
|
24905
|
+
if (turnState) {
|
|
24906
|
+
turnState.toolCalls.push({
|
|
24907
|
+
args: event.args,
|
|
24908
|
+
toolCallId,
|
|
24909
|
+
toolName: event.toolName
|
|
24910
|
+
});
|
|
24911
|
+
}
|
|
24912
|
+
safeLog3(span, {
|
|
24913
|
+
input: event.args,
|
|
24914
|
+
metadata
|
|
24915
|
+
});
|
|
24916
|
+
this.toolsById.set(toolKey(event), {
|
|
24917
|
+
metadata,
|
|
24918
|
+
span,
|
|
24919
|
+
startTime: getCurrentUnixTimestamp()
|
|
24920
|
+
});
|
|
24921
|
+
}
|
|
24922
|
+
handleToolCall(event) {
|
|
24923
|
+
const key = toolKey(event);
|
|
24924
|
+
const state = this.toolsById.get(key) ?? this.startSyntheticToolState(event, event.toolName ?? "unknown");
|
|
24925
|
+
const metadata = {
|
|
24926
|
+
...state.metadata,
|
|
24927
|
+
...extractEventMetadata(event),
|
|
24928
|
+
...event.toolName ? { "flue.tool_name": event.toolName } : {},
|
|
24929
|
+
...event.toolCallId ? { "flue.tool_call_id": event.toolCallId } : {},
|
|
24930
|
+
...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
|
|
24931
|
+
};
|
|
24932
|
+
safeLog3(state.span, {
|
|
24933
|
+
...event.isError ? { error: errorToString(event.result) } : {},
|
|
24934
|
+
metadata,
|
|
24935
|
+
metrics: durationMsMetrics(event.durationMs),
|
|
24936
|
+
output: event.result
|
|
24937
|
+
});
|
|
24938
|
+
state.span.end();
|
|
24939
|
+
this.toolsById.delete(key);
|
|
24940
|
+
}
|
|
24941
|
+
handleTaskStart(event) {
|
|
24942
|
+
const parent = this.parentSpanForEvent(event);
|
|
24943
|
+
const metadata = {
|
|
24944
|
+
...extractEventMetadata(event),
|
|
24945
|
+
...event.role ? { "flue.role": event.role } : {},
|
|
24946
|
+
...event.cwd ? { "flue.cwd": event.cwd } : {},
|
|
24947
|
+
"flue.task_id": event.taskId,
|
|
24948
|
+
provider: "flue"
|
|
24949
|
+
};
|
|
24950
|
+
const span = startFlueSpan(parent, {
|
|
24951
|
+
name: "flue.task",
|
|
24952
|
+
spanAttributes: { type: "task" /* TASK */ }
|
|
24953
|
+
});
|
|
24954
|
+
safeLog3(span, {
|
|
24955
|
+
input: event.prompt,
|
|
24956
|
+
metadata
|
|
24957
|
+
});
|
|
24958
|
+
this.tasksById.set(event.taskId, {
|
|
24959
|
+
metadata,
|
|
24960
|
+
span,
|
|
24961
|
+
startTime: getCurrentUnixTimestamp()
|
|
24962
|
+
});
|
|
24963
|
+
}
|
|
24964
|
+
handleTask(event) {
|
|
24965
|
+
const state = this.tasksById.get(event.taskId);
|
|
24966
|
+
if (!state) {
|
|
24967
|
+
return;
|
|
24968
|
+
}
|
|
24969
|
+
safeLog3(state.span, {
|
|
24970
|
+
...event.isError ? { error: errorToString(event.result) } : {},
|
|
24971
|
+
metadata: {
|
|
24972
|
+
...state.metadata,
|
|
24973
|
+
...extractEventMetadata(event),
|
|
24974
|
+
...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
|
|
24975
|
+
},
|
|
24976
|
+
metrics: durationMsMetrics(event.durationMs),
|
|
24977
|
+
output: event.result
|
|
24978
|
+
});
|
|
24979
|
+
state.span.end();
|
|
24980
|
+
this.tasksById.delete(event.taskId);
|
|
24981
|
+
}
|
|
24982
|
+
handleCompactionStart(event) {
|
|
24983
|
+
const operationState = this.operationStateForEvent(event);
|
|
24984
|
+
const parent = operationState?.span ?? this.parentSpanForEvent(event);
|
|
24985
|
+
const metadata = {
|
|
24986
|
+
...extractEventMetadata(event),
|
|
24987
|
+
...event.reason ? { "flue.compaction_reason": event.reason } : {},
|
|
24988
|
+
provider: "flue"
|
|
24989
|
+
};
|
|
24990
|
+
const input = {
|
|
24991
|
+
...typeof event.estimatedTokens === "number" ? { estimatedTokens: event.estimatedTokens } : {},
|
|
24992
|
+
...event.reason ? { reason: event.reason } : {}
|
|
24993
|
+
};
|
|
24994
|
+
const span = startFlueSpan(parent, {
|
|
24995
|
+
name: "flue.compaction",
|
|
24996
|
+
spanAttributes: { type: "task" /* TASK */ }
|
|
24997
|
+
});
|
|
24998
|
+
safeLog3(span, {
|
|
24999
|
+
input,
|
|
25000
|
+
metadata
|
|
25001
|
+
});
|
|
25002
|
+
this.compactionsByScope.set(scopeKey(event), {
|
|
25003
|
+
input,
|
|
25004
|
+
metadata,
|
|
25005
|
+
operationState,
|
|
25006
|
+
span,
|
|
25007
|
+
startTime: getCurrentUnixTimestamp()
|
|
25008
|
+
});
|
|
25009
|
+
}
|
|
25010
|
+
handleCompaction(event) {
|
|
25011
|
+
const key = scopeKey(event);
|
|
25012
|
+
const state = this.compactionsByScope.get(key) ?? this.findCompactionState(event);
|
|
25013
|
+
if (!state) {
|
|
25014
|
+
return;
|
|
25015
|
+
}
|
|
25016
|
+
safeLog3(state.span, {
|
|
25017
|
+
metadata: {
|
|
25018
|
+
...state.metadata,
|
|
25019
|
+
...extractEventMetadata(event),
|
|
25020
|
+
...typeof event.messagesBefore === "number" ? { "flue.messages_before": event.messagesBefore } : {},
|
|
25021
|
+
...typeof event.messagesAfter === "number" ? { "flue.messages_after": event.messagesAfter } : {}
|
|
25022
|
+
},
|
|
25023
|
+
metrics: {
|
|
25024
|
+
...durationMsMetrics(event.durationMs),
|
|
25025
|
+
...metricsFromUsage(event.usage)
|
|
25026
|
+
},
|
|
25027
|
+
output: {
|
|
25028
|
+
messagesAfter: event.messagesAfter,
|
|
25029
|
+
messagesBefore: event.messagesBefore
|
|
25030
|
+
}
|
|
25031
|
+
});
|
|
25032
|
+
state.span.end();
|
|
25033
|
+
this.deleteCompactionState(state);
|
|
25034
|
+
}
|
|
25035
|
+
findCompactionState(event) {
|
|
25036
|
+
const operationState = this.operationStateForEvent(event);
|
|
25037
|
+
for (const state of this.compactionsByScope.values()) {
|
|
25038
|
+
if (operationState && state.operationState === operationState) {
|
|
25039
|
+
return state;
|
|
25040
|
+
}
|
|
25041
|
+
}
|
|
25042
|
+
return void 0;
|
|
25043
|
+
}
|
|
25044
|
+
finishCompactionsForOperation(operationState) {
|
|
25045
|
+
for (const state of [...this.compactionsByScope.values()]) {
|
|
25046
|
+
if (state.operationState !== operationState) {
|
|
25047
|
+
continue;
|
|
25048
|
+
}
|
|
25049
|
+
safeLog3(state.span, {
|
|
25050
|
+
input: state.input,
|
|
25051
|
+
metadata: state.metadata,
|
|
25052
|
+
metrics: {
|
|
25053
|
+
...buildDurationMetrics3(state.startTime)
|
|
25054
|
+
},
|
|
25055
|
+
output: { completed: true }
|
|
25056
|
+
});
|
|
25057
|
+
state.span.end();
|
|
25058
|
+
this.deleteCompactionState(state);
|
|
25059
|
+
}
|
|
25060
|
+
}
|
|
25061
|
+
deleteCompactionState(state) {
|
|
25062
|
+
for (const [key, candidate] of this.compactionsByScope) {
|
|
25063
|
+
if (candidate !== state) {
|
|
25064
|
+
continue;
|
|
25065
|
+
}
|
|
25066
|
+
this.compactionsByScope.delete(key);
|
|
25067
|
+
return;
|
|
25068
|
+
}
|
|
25069
|
+
}
|
|
25070
|
+
startSyntheticToolState(event, toolName) {
|
|
25071
|
+
const parent = this.parentSpanForEvent(event);
|
|
25072
|
+
const metadata = {
|
|
25073
|
+
...extractEventMetadata(event),
|
|
25074
|
+
...event.toolCallId ? { "flue.tool_call_id": event.toolCallId } : {},
|
|
25075
|
+
"flue.tool_name": toolName,
|
|
25076
|
+
provider: "flue"
|
|
25077
|
+
};
|
|
25078
|
+
const span = startFlueSpan(parent, {
|
|
25079
|
+
name: `tool: ${toolName}`,
|
|
25080
|
+
spanAttributes: { type: "tool" /* TOOL */ }
|
|
25081
|
+
});
|
|
25082
|
+
safeLog3(span, { metadata });
|
|
25083
|
+
return { metadata, span, startTime: getCurrentUnixTimestamp() };
|
|
25084
|
+
}
|
|
25085
|
+
operationStateForEvent(event) {
|
|
25086
|
+
if (event.operationId) {
|
|
25087
|
+
const operation = this.activeOperationsById.get(event.operationId) ?? this.promotePendingOperationForEvent(event);
|
|
25088
|
+
if (operation) {
|
|
25089
|
+
return operation;
|
|
25090
|
+
}
|
|
25091
|
+
}
|
|
25092
|
+
return this.activeOperationForEventScope(event) ?? this.pendingOperationForEventScope(event);
|
|
25093
|
+
}
|
|
25094
|
+
parentSpanForEvent(event) {
|
|
25095
|
+
if (event.operationId) {
|
|
25096
|
+
const operation = this.operationStateForEvent(event);
|
|
25097
|
+
if (operation) {
|
|
25098
|
+
return operation.span;
|
|
25099
|
+
}
|
|
25100
|
+
}
|
|
25101
|
+
if (event.taskId) {
|
|
25102
|
+
return this.tasksById.get(event.taskId)?.span;
|
|
25103
|
+
}
|
|
25104
|
+
return this.operationStateForEvent(event)?.span;
|
|
25105
|
+
}
|
|
25106
|
+
promotePendingOperationForEvent(event) {
|
|
25107
|
+
if (!event.operationId) {
|
|
25108
|
+
return void 0;
|
|
25109
|
+
}
|
|
25110
|
+
const scopePrefixes = operationScopePrefixes(event);
|
|
25111
|
+
for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
|
|
25112
|
+
if (!candidateQueue.length || !operationKeyMatchesScopes(candidateKey, scopePrefixes)) {
|
|
25113
|
+
continue;
|
|
25114
|
+
}
|
|
25115
|
+
const state = candidateQueue.shift();
|
|
25116
|
+
if (!state) {
|
|
25117
|
+
return void 0;
|
|
25118
|
+
}
|
|
25119
|
+
state.operationId = event.operationId;
|
|
25120
|
+
this.activeOperationsById.set(event.operationId, state);
|
|
25121
|
+
addScopedOperation(this.activeOperationsByScope, event, state);
|
|
25122
|
+
state.metadata = {
|
|
25123
|
+
...state.metadata,
|
|
25124
|
+
...extractEventMetadata(event),
|
|
25125
|
+
"flue.operation_id": event.operationId
|
|
25126
|
+
};
|
|
25127
|
+
safeLog3(state.span, { metadata: state.metadata });
|
|
25128
|
+
return state;
|
|
25129
|
+
}
|
|
25130
|
+
return void 0;
|
|
25131
|
+
}
|
|
25132
|
+
activeOperationForEventScope(event) {
|
|
25133
|
+
for (const scope of operationScopeNames(event)) {
|
|
25134
|
+
const operations = this.activeOperationsByScope.get(scope);
|
|
25135
|
+
if (operations?.length) {
|
|
25136
|
+
return operations[operations.length - 1];
|
|
25137
|
+
}
|
|
25138
|
+
}
|
|
25139
|
+
return void 0;
|
|
25140
|
+
}
|
|
25141
|
+
pendingOperationForEventScope(event) {
|
|
25142
|
+
const scopePrefixes = operationScopePrefixes(event);
|
|
25143
|
+
for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
|
|
25144
|
+
if (!candidateQueue.length || !operationKeyMatchesScopes(candidateKey, scopePrefixes)) {
|
|
25145
|
+
continue;
|
|
25146
|
+
}
|
|
25147
|
+
return candidateQueue[0];
|
|
25148
|
+
}
|
|
25149
|
+
return void 0;
|
|
25150
|
+
}
|
|
25151
|
+
takePendingOperationForEvent(event) {
|
|
25152
|
+
const key = operationKey(event.session, event.operationKind);
|
|
25153
|
+
const queue2 = this.pendingOperationsByKey.get(key);
|
|
25154
|
+
if (queue2?.length) {
|
|
25155
|
+
return queue2.shift();
|
|
25156
|
+
}
|
|
25157
|
+
for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
|
|
25158
|
+
if (candidateKey.endsWith(`::${event.operationKind}`) && candidateQueue.length) {
|
|
25159
|
+
return candidateQueue.shift();
|
|
25160
|
+
}
|
|
25161
|
+
}
|
|
25162
|
+
return void 0;
|
|
25163
|
+
}
|
|
25164
|
+
pendingOperationQueue(key) {
|
|
25165
|
+
const existing = this.pendingOperationsByKey.get(key);
|
|
25166
|
+
if (existing) {
|
|
25167
|
+
return existing;
|
|
25168
|
+
}
|
|
25169
|
+
const queue2 = [];
|
|
25170
|
+
this.pendingOperationsByKey.set(key, queue2);
|
|
25171
|
+
return queue2;
|
|
25172
|
+
}
|
|
25173
|
+
};
|
|
25174
|
+
function isInstrumentedOperation(operation) {
|
|
25175
|
+
return operation === "prompt" || operation === "skill" || operation === "task" || operation === "compact";
|
|
25176
|
+
}
|
|
25177
|
+
function getSessionName(session) {
|
|
25178
|
+
return typeof session?.name === "string" ? session.name : void 0;
|
|
25179
|
+
}
|
|
25180
|
+
function operationKey(sessionName, operation) {
|
|
25181
|
+
return `${sessionName ?? "unknown"}::${operation}`;
|
|
25182
|
+
}
|
|
25183
|
+
function operationScopePrefixes(event) {
|
|
25184
|
+
const scopes = /* @__PURE__ */ new Set();
|
|
25185
|
+
for (const scope of operationScopeNames(event)) {
|
|
25186
|
+
scopes.add(`${scope}::`);
|
|
25187
|
+
}
|
|
25188
|
+
return scopes;
|
|
25189
|
+
}
|
|
25190
|
+
function operationKeyMatchesScopes(key, scopes) {
|
|
25191
|
+
for (const scope of scopes) {
|
|
25192
|
+
if (key.startsWith(scope)) {
|
|
25193
|
+
return true;
|
|
25194
|
+
}
|
|
25195
|
+
}
|
|
25196
|
+
return false;
|
|
25197
|
+
}
|
|
25198
|
+
function operationScopeNames(event) {
|
|
25199
|
+
const scopes = /* @__PURE__ */ new Set();
|
|
25200
|
+
if (event.session) {
|
|
25201
|
+
scopes.add(event.session);
|
|
25202
|
+
}
|
|
25203
|
+
if (event.parentSession) {
|
|
25204
|
+
scopes.add(event.parentSession);
|
|
25205
|
+
}
|
|
25206
|
+
if (!scopes.size) {
|
|
25207
|
+
scopes.add("unknown");
|
|
25208
|
+
}
|
|
25209
|
+
return scopes;
|
|
25210
|
+
}
|
|
25211
|
+
function addScopedOperation(operationsByScope, event, state) {
|
|
25212
|
+
for (const scope of operationScopeNames(event)) {
|
|
25213
|
+
addOperationToScope(operationsByScope, scope, state);
|
|
25214
|
+
}
|
|
25215
|
+
}
|
|
25216
|
+
function addOperationToScope(operationsByScope, scope, state) {
|
|
25217
|
+
const operations = operationsByScope.get(scope);
|
|
25218
|
+
if (operations) {
|
|
25219
|
+
if (!operations.includes(state)) {
|
|
25220
|
+
operations.push(state);
|
|
25221
|
+
}
|
|
25222
|
+
} else {
|
|
25223
|
+
operationsByScope.set(scope, [state]);
|
|
25224
|
+
}
|
|
25225
|
+
}
|
|
25226
|
+
function removeScopedOperation(operationsByScope, state) {
|
|
25227
|
+
for (const [scope, operations] of operationsByScope) {
|
|
25228
|
+
const index = operations.indexOf(state);
|
|
25229
|
+
if (index === -1) {
|
|
25230
|
+
continue;
|
|
25231
|
+
}
|
|
25232
|
+
operations.splice(index, 1);
|
|
25233
|
+
if (operations.length === 0) {
|
|
25234
|
+
operationsByScope.delete(scope);
|
|
25235
|
+
}
|
|
25236
|
+
}
|
|
25237
|
+
}
|
|
25238
|
+
function removePendingOperation(pendingOperationsByKey, state) {
|
|
25239
|
+
for (const [key, queue2] of pendingOperationsByKey) {
|
|
25240
|
+
const index = queue2.indexOf(state);
|
|
25241
|
+
if (index === -1) {
|
|
25242
|
+
continue;
|
|
25243
|
+
}
|
|
25244
|
+
queue2.splice(index, 1);
|
|
25245
|
+
if (queue2.length === 0) {
|
|
25246
|
+
pendingOperationsByKey.delete(key);
|
|
25247
|
+
}
|
|
25248
|
+
return;
|
|
25249
|
+
}
|
|
25250
|
+
}
|
|
25251
|
+
function extractSessionMetadata(session) {
|
|
25252
|
+
const sessionName = getSessionName(session);
|
|
25253
|
+
return sessionName ? { "flue.session": sessionName } : {};
|
|
25254
|
+
}
|
|
25255
|
+
function extractEventMetadata(event) {
|
|
25256
|
+
return {
|
|
25257
|
+
...event.runId ? { "flue.run_id": event.runId } : {},
|
|
25258
|
+
...typeof event.eventIndex === "number" ? { "flue.event_index": event.eventIndex } : {},
|
|
25259
|
+
...event.session ? { "flue.session": event.session } : {},
|
|
25260
|
+
...event.parentSession ? { "flue.parent_session": event.parentSession } : {},
|
|
25261
|
+
...event.harness ? { "flue.harness": event.harness } : {},
|
|
25262
|
+
...event.taskId ? { "flue.task_id": event.taskId } : {},
|
|
25263
|
+
...event.operationId ? { "flue.operation_id": event.operationId } : {}
|
|
25264
|
+
};
|
|
25265
|
+
}
|
|
25266
|
+
function extractOperationInput(operation, args) {
|
|
25267
|
+
switch (operation) {
|
|
25268
|
+
case "prompt":
|
|
25269
|
+
case "task":
|
|
25270
|
+
return args[0];
|
|
25271
|
+
case "skill":
|
|
25272
|
+
return {
|
|
25273
|
+
args: getOptionObject(args[1])?.args,
|
|
25274
|
+
name: args[0]
|
|
25275
|
+
};
|
|
25276
|
+
case "compact":
|
|
25277
|
+
return void 0;
|
|
25278
|
+
}
|
|
25279
|
+
}
|
|
25280
|
+
function extractOperationInputMetadata(operation, args) {
|
|
25281
|
+
const options = getOptionObject(args[1]);
|
|
25282
|
+
return {
|
|
25283
|
+
...operation === "skill" && typeof args[0] === "string" ? { "flue.skill_name": args[0] } : {},
|
|
25284
|
+
...options?.model ? { model: options.model, "flue.model": options.model } : {},
|
|
25285
|
+
...options?.role ? { "flue.role": options.role } : {},
|
|
25286
|
+
...options?.thinkingLevel ? { "flue.thinking_level": options.thinkingLevel } : {},
|
|
25287
|
+
...typeof options?.cwd === "string" ? { "flue.cwd": options.cwd } : {},
|
|
25288
|
+
...Array.isArray(options?.tools) ? {
|
|
25289
|
+
"flue.tools_count": options.tools.length,
|
|
25290
|
+
tools: summarizeTools(options.tools)
|
|
25291
|
+
} : {},
|
|
25292
|
+
...Array.isArray(options?.images) ? { "flue.images_count": options.images.length } : {},
|
|
25293
|
+
...options?.result || options?.schema ? { "flue.result_schema": true } : {}
|
|
25294
|
+
};
|
|
25295
|
+
}
|
|
25296
|
+
function getOptionObject(value) {
|
|
25297
|
+
return isObject(value) ? value : void 0;
|
|
25298
|
+
}
|
|
25299
|
+
function summarizeTools(tools) {
|
|
25300
|
+
return tools.flatMap((tool) => {
|
|
25301
|
+
if (!isObject(tool)) {
|
|
25302
|
+
return [];
|
|
25303
|
+
}
|
|
25304
|
+
const name = typeof tool.name === "string" ? tool.name : void 0;
|
|
25305
|
+
if (!name) {
|
|
25306
|
+
return [];
|
|
25307
|
+
}
|
|
25308
|
+
return [
|
|
25309
|
+
{
|
|
25310
|
+
function: {
|
|
25311
|
+
description: typeof tool.description === "string" ? tool.description : void 0,
|
|
25312
|
+
name,
|
|
25313
|
+
parameters: tool.parameters
|
|
25314
|
+
},
|
|
25315
|
+
type: "function"
|
|
25316
|
+
}
|
|
25317
|
+
];
|
|
25318
|
+
});
|
|
25319
|
+
}
|
|
25320
|
+
function extractPromptResponseMetadata(result) {
|
|
25321
|
+
const modelId = result?.model && typeof result.model.id === "string" ? result.model.id : void 0;
|
|
25322
|
+
return modelId ? {
|
|
25323
|
+
model: modelId,
|
|
25324
|
+
"flue.model": modelId
|
|
25325
|
+
} : {};
|
|
25326
|
+
}
|
|
25327
|
+
function extractOperationOutput(result) {
|
|
25328
|
+
if (!result) {
|
|
25329
|
+
return void 0;
|
|
25330
|
+
}
|
|
25331
|
+
if ("data" in result) {
|
|
25332
|
+
return result.data;
|
|
25333
|
+
}
|
|
25334
|
+
if ("text" in result) {
|
|
25335
|
+
return result.text;
|
|
25336
|
+
}
|
|
25337
|
+
return result;
|
|
25338
|
+
}
|
|
25339
|
+
function metricsFromUsage(usage) {
|
|
25340
|
+
return {
|
|
25341
|
+
...typeof usage?.input === "number" ? { prompt_tokens: usage.input } : {},
|
|
25342
|
+
...typeof usage?.output === "number" ? { completion_tokens: usage.output } : {},
|
|
25343
|
+
...typeof usage?.cacheRead === "number" ? { prompt_cached_tokens: usage.cacheRead } : {},
|
|
25344
|
+
...typeof usage?.cacheWrite === "number" ? { prompt_cache_creation_tokens: usage.cacheWrite } : {},
|
|
25345
|
+
...typeof usage?.totalTokens === "number" ? { tokens: usage.totalTokens } : {},
|
|
25346
|
+
...typeof usage?.cost?.total === "number" ? { estimated_cost: usage.cost.total } : {}
|
|
25347
|
+
};
|
|
25348
|
+
}
|
|
25349
|
+
function buildDurationMetrics3(startTime) {
|
|
25350
|
+
return {
|
|
25351
|
+
duration_ms: Math.max(0, (getCurrentUnixTimestamp() - startTime) * 1e3)
|
|
25352
|
+
};
|
|
25353
|
+
}
|
|
25354
|
+
function durationMsMetrics(durationMs) {
|
|
25355
|
+
return typeof durationMs === "number" ? { duration_ms: durationMs } : {};
|
|
25356
|
+
}
|
|
25357
|
+
function scopeKey(event) {
|
|
25358
|
+
if (event.operationId) {
|
|
25359
|
+
return `operation:${event.operationId}`;
|
|
25360
|
+
}
|
|
25361
|
+
if (event.taskId) {
|
|
25362
|
+
return `task:${event.taskId}`;
|
|
25363
|
+
}
|
|
25364
|
+
if (event.session) {
|
|
25365
|
+
return `session:${event.session}`;
|
|
25366
|
+
}
|
|
25367
|
+
return "flue:unknown";
|
|
25368
|
+
}
|
|
25369
|
+
function toolKey(event) {
|
|
25370
|
+
return `${scopeKey(event)}::tool:${event.toolCallId ?? "unknown"}`;
|
|
25371
|
+
}
|
|
25372
|
+
function toAssistantOutput(text, finishReason, reasoning, toolCalls) {
|
|
25373
|
+
return [
|
|
25374
|
+
{
|
|
25375
|
+
finish_reason: finishReason ?? "stop",
|
|
25376
|
+
index: 0,
|
|
25377
|
+
message: {
|
|
25378
|
+
content: text,
|
|
25379
|
+
...reasoning ? { reasoning } : {},
|
|
25380
|
+
role: "assistant",
|
|
25381
|
+
...toolCalls?.length ? {
|
|
25382
|
+
tool_calls: toolCalls.map((toolCall) => ({
|
|
25383
|
+
function: {
|
|
25384
|
+
arguments: toolCall.args === void 0 ? "{}" : JSON.stringify(toolCall.args),
|
|
25385
|
+
name: toolCall.toolName ?? "unknown"
|
|
25386
|
+
},
|
|
25387
|
+
...toolCall.toolCallId ? { id: toolCall.toolCallId } : {},
|
|
25388
|
+
type: "function"
|
|
25389
|
+
}))
|
|
25390
|
+
} : {}
|
|
25391
|
+
}
|
|
25392
|
+
}
|
|
25393
|
+
];
|
|
25394
|
+
}
|
|
25395
|
+
function startFlueSpan(parent, args) {
|
|
25396
|
+
return parent ? withCurrent(parent, () => startSpan(args)) : startSpan(args);
|
|
25397
|
+
}
|
|
25398
|
+
function safeLog3(span, event) {
|
|
25399
|
+
try {
|
|
25400
|
+
span.log(event);
|
|
25401
|
+
} catch (error) {
|
|
25402
|
+
logInstrumentationError3("Flue span log", error);
|
|
25403
|
+
}
|
|
25404
|
+
}
|
|
25405
|
+
function errorToString(error) {
|
|
25406
|
+
if (error instanceof Error) {
|
|
25407
|
+
return error.message;
|
|
25408
|
+
}
|
|
25409
|
+
if (typeof error === "string") {
|
|
25410
|
+
return error;
|
|
25411
|
+
}
|
|
25412
|
+
try {
|
|
25413
|
+
return JSON.stringify(error);
|
|
25414
|
+
} catch {
|
|
25415
|
+
return String(error);
|
|
25416
|
+
}
|
|
25417
|
+
}
|
|
25418
|
+
function logInstrumentationError3(label, error) {
|
|
25419
|
+
console.error(`Error in ${label} instrumentation:`, error);
|
|
25420
|
+
}
|
|
25421
|
+
|
|
25422
|
+
// src/wrappers/langchain/callback-handler.ts
|
|
25423
|
+
var BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME = "BraintrustCallbackHandler";
|
|
25424
|
+
var BraintrustLangChainCallbackHandler = class {
|
|
25425
|
+
name = BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
|
|
25426
|
+
spans = /* @__PURE__ */ new Map();
|
|
25427
|
+
skippedRuns = /* @__PURE__ */ new Set();
|
|
25428
|
+
parent;
|
|
25429
|
+
rootRunId;
|
|
25430
|
+
options;
|
|
25431
|
+
startTimes = /* @__PURE__ */ new Map();
|
|
25432
|
+
firstTokenTimes = /* @__PURE__ */ new Map();
|
|
25433
|
+
ttftMs = /* @__PURE__ */ new Map();
|
|
25434
|
+
constructor(options) {
|
|
25435
|
+
this.parent = options?.parent;
|
|
25436
|
+
this.options = {
|
|
25437
|
+
debug: options?.debug ?? false,
|
|
25438
|
+
excludeMetadataProps: options?.excludeMetadataProps ?? /^(l[sc]_|langgraph_|__pregel_|checkpoint_ns)/,
|
|
25439
|
+
logger: options?.logger
|
|
25440
|
+
};
|
|
25441
|
+
}
|
|
25442
|
+
startSpan({
|
|
25443
|
+
runId,
|
|
25444
|
+
parentRunId,
|
|
25445
|
+
...args
|
|
25446
|
+
}) {
|
|
25447
|
+
if (this.spans.has(runId)) {
|
|
25448
|
+
return;
|
|
25449
|
+
}
|
|
25450
|
+
if (!parentRunId) {
|
|
25451
|
+
this.rootRunId = runId;
|
|
25452
|
+
}
|
|
25453
|
+
const tags = args.event?.tags;
|
|
25454
|
+
const spanAttributes = args.spanAttributes || {};
|
|
25455
|
+
spanAttributes.type = args.type || spanAttributes.type || "task";
|
|
25456
|
+
args.type = spanAttributes.type;
|
|
25457
|
+
const currentParent = (typeof this.parent === "function" ? this.parent() : this.parent) ?? currentSpan();
|
|
25458
|
+
let parentSpan;
|
|
25459
|
+
if (parentRunId && this.spans.has(parentRunId)) {
|
|
25460
|
+
parentSpan = this.spans.get(parentRunId);
|
|
25461
|
+
} else if (!Object.is(currentParent, NOOP_SPAN)) {
|
|
25462
|
+
parentSpan = currentParent;
|
|
25463
|
+
} else if (this.options.logger) {
|
|
25464
|
+
parentSpan = this.options.logger;
|
|
25465
|
+
} else {
|
|
25466
|
+
parentSpan = { startSpan };
|
|
25467
|
+
}
|
|
25468
|
+
args.event = {
|
|
25469
|
+
...args.event,
|
|
25470
|
+
tags: void 0,
|
|
25471
|
+
metadata: {
|
|
25472
|
+
...tags ? { tags } : {},
|
|
25473
|
+
...args.event?.metadata,
|
|
25474
|
+
braintrust: {
|
|
25475
|
+
integration_name: "langchain-js",
|
|
25476
|
+
sdk_language: "javascript"
|
|
25477
|
+
},
|
|
25478
|
+
run_id: runId,
|
|
25479
|
+
parent_run_id: parentRunId,
|
|
25480
|
+
...this.options.debug ? { runId, parentRunId } : {}
|
|
25481
|
+
}
|
|
25482
|
+
};
|
|
25483
|
+
let span = parentSpan.startSpan(args);
|
|
25484
|
+
if (!Object.is(this.options.logger, NOOP_SPAN) && Object.is(span, NOOP_SPAN)) {
|
|
25485
|
+
span = initLogger().startSpan(args);
|
|
25486
|
+
}
|
|
25487
|
+
this.spans.set(runId, span);
|
|
25488
|
+
}
|
|
25489
|
+
endSpan({
|
|
25490
|
+
runId,
|
|
25491
|
+
parentRunId,
|
|
25492
|
+
tags,
|
|
25493
|
+
metadata,
|
|
25494
|
+
...args
|
|
25495
|
+
}) {
|
|
25496
|
+
if (!this.spans.has(runId)) {
|
|
25497
|
+
return;
|
|
25498
|
+
}
|
|
25499
|
+
if (this.skippedRuns.has(runId)) {
|
|
25500
|
+
this.skippedRuns.delete(runId);
|
|
25501
|
+
return;
|
|
25502
|
+
}
|
|
25503
|
+
const span = this.spans.get(runId);
|
|
25504
|
+
this.spans.delete(runId);
|
|
25505
|
+
if (runId === this.rootRunId) {
|
|
25506
|
+
this.rootRunId = void 0;
|
|
25507
|
+
}
|
|
25508
|
+
span.log({ ...args, metadata: { tags, ...metadata } });
|
|
25509
|
+
span.end();
|
|
25510
|
+
}
|
|
25511
|
+
async handleLLMStart(llm, prompts, runId, parentRunId, extraParams, tags, metadata, runName) {
|
|
25512
|
+
this.startSpan({
|
|
25513
|
+
runId,
|
|
25514
|
+
parentRunId,
|
|
25515
|
+
name: runName ?? getSerializedName(llm) ?? "LLM",
|
|
25516
|
+
type: "llm",
|
|
25517
|
+
event: {
|
|
25518
|
+
input: prompts,
|
|
25519
|
+
tags,
|
|
25520
|
+
metadata: {
|
|
25521
|
+
serialized: llm,
|
|
25522
|
+
name: runName,
|
|
25523
|
+
metadata,
|
|
25524
|
+
...extraParams
|
|
25525
|
+
}
|
|
25526
|
+
}
|
|
25527
|
+
});
|
|
25528
|
+
}
|
|
25529
|
+
async handleLLMError(err, runId, parentRunId, tags) {
|
|
25530
|
+
this.endSpan({ runId, parentRunId, error: err, tags });
|
|
25531
|
+
}
|
|
25532
|
+
async handleLLMEnd(output, runId, parentRunId, tags) {
|
|
25533
|
+
const metrics = getMetricsFromResponse(output);
|
|
25534
|
+
const modelName2 = getModelNameFromResponse(output);
|
|
25535
|
+
const ttft = this.ttftMs.get(runId);
|
|
25536
|
+
if (ttft !== void 0) {
|
|
25537
|
+
metrics.time_to_first_token = ttft;
|
|
25538
|
+
}
|
|
25539
|
+
this.startTimes.delete(runId);
|
|
25540
|
+
this.firstTokenTimes.delete(runId);
|
|
25541
|
+
this.ttftMs.delete(runId);
|
|
25542
|
+
this.endSpan({
|
|
25543
|
+
runId,
|
|
25544
|
+
parentRunId,
|
|
25545
|
+
output,
|
|
25546
|
+
metrics,
|
|
25547
|
+
tags,
|
|
25548
|
+
metadata: {
|
|
25549
|
+
model: modelName2
|
|
25550
|
+
}
|
|
25551
|
+
});
|
|
25552
|
+
}
|
|
25553
|
+
async handleChatModelStart(llm, messages, runId, parentRunId, extraParams, tags, metadata, runName) {
|
|
25554
|
+
this.startTimes.set(runId, Date.now());
|
|
25555
|
+
this.firstTokenTimes.delete(runId);
|
|
25556
|
+
this.ttftMs.delete(runId);
|
|
25557
|
+
this.startSpan({
|
|
25558
|
+
runId,
|
|
25559
|
+
parentRunId,
|
|
25560
|
+
name: runName ?? getSerializedName(llm) ?? "Chat Model",
|
|
25561
|
+
type: "llm",
|
|
25562
|
+
event: {
|
|
25563
|
+
input: messages,
|
|
25564
|
+
tags,
|
|
25565
|
+
metadata: {
|
|
25566
|
+
serialized: llm,
|
|
25567
|
+
name: runName,
|
|
25568
|
+
metadata,
|
|
25569
|
+
...extraParams
|
|
25570
|
+
}
|
|
25571
|
+
}
|
|
25572
|
+
});
|
|
25573
|
+
}
|
|
25574
|
+
async handleChainStart(chain, inputs, runId, parentRunId, tags, metadata, runType, runName) {
|
|
25575
|
+
if (tags?.includes("langsmith:hidden")) {
|
|
25576
|
+
this.skippedRuns.add(runId);
|
|
25577
|
+
return;
|
|
25578
|
+
}
|
|
25579
|
+
this.startSpan({
|
|
25580
|
+
runId,
|
|
25581
|
+
parentRunId,
|
|
25582
|
+
name: runName ?? getSerializedName(chain) ?? "Chain",
|
|
25583
|
+
event: {
|
|
25584
|
+
input: inputs,
|
|
25585
|
+
tags,
|
|
25586
|
+
metadata: {
|
|
25587
|
+
serialized: chain,
|
|
25588
|
+
name: runName,
|
|
25589
|
+
metadata,
|
|
25590
|
+
run_type: runType
|
|
25591
|
+
}
|
|
25592
|
+
}
|
|
25593
|
+
});
|
|
25594
|
+
}
|
|
25595
|
+
async handleChainError(err, runId, parentRunId, tags, kwargs) {
|
|
25596
|
+
this.endSpan({ runId, parentRunId, error: err, tags, metadata: kwargs });
|
|
25597
|
+
}
|
|
25598
|
+
async handleChainEnd(outputs, runId, parentRunId, tags, kwargs) {
|
|
25599
|
+
this.endSpan({
|
|
25600
|
+
runId,
|
|
25601
|
+
parentRunId,
|
|
25602
|
+
tags,
|
|
25603
|
+
output: outputs,
|
|
25604
|
+
metadata: { ...kwargs }
|
|
25605
|
+
});
|
|
25606
|
+
}
|
|
25607
|
+
async handleToolStart(tool, input, runId, parentRunId, tags, metadata, runName) {
|
|
25608
|
+
this.startSpan({
|
|
25609
|
+
runId,
|
|
25610
|
+
parentRunId,
|
|
25611
|
+
name: runName ?? getSerializedName(tool) ?? "Tool",
|
|
25612
|
+
type: "llm",
|
|
25613
|
+
event: {
|
|
25614
|
+
input: safeJsonParse(input),
|
|
25615
|
+
tags,
|
|
25616
|
+
metadata: {
|
|
25617
|
+
metadata,
|
|
25618
|
+
serialized: tool,
|
|
25619
|
+
input_str: input,
|
|
25620
|
+
input: safeJsonParse(input),
|
|
25621
|
+
name: runName
|
|
25622
|
+
}
|
|
25623
|
+
}
|
|
25624
|
+
});
|
|
25625
|
+
}
|
|
25626
|
+
async handleToolError(err, runId, parentRunId, tags) {
|
|
25627
|
+
this.endSpan({ runId, parentRunId, error: err, tags });
|
|
25628
|
+
}
|
|
25629
|
+
async handleToolEnd(output, runId, parentRunId, tags) {
|
|
25630
|
+
this.endSpan({ runId, parentRunId, output, tags });
|
|
25631
|
+
}
|
|
25632
|
+
async handleAgentAction(action, runId, parentRunId, tags) {
|
|
25633
|
+
this.startSpan({
|
|
25634
|
+
runId,
|
|
25635
|
+
parentRunId,
|
|
25636
|
+
type: "llm",
|
|
25637
|
+
name: typeof action.tool === "string" ? action.tool : "Agent",
|
|
25638
|
+
event: {
|
|
25639
|
+
input: action,
|
|
25640
|
+
tags
|
|
25641
|
+
}
|
|
25642
|
+
});
|
|
25643
|
+
}
|
|
25644
|
+
async handleAgentEnd(action, runId, parentRunId, tags) {
|
|
25645
|
+
this.endSpan({ runId, parentRunId, output: action, tags });
|
|
25646
|
+
}
|
|
25647
|
+
async handleRetrieverStart(retriever, query, runId, parentRunId, tags, metadata, name) {
|
|
25648
|
+
this.startSpan({
|
|
25649
|
+
runId,
|
|
25650
|
+
parentRunId,
|
|
25651
|
+
name: name ?? getSerializedName(retriever) ?? "Retriever",
|
|
25652
|
+
type: "function",
|
|
25653
|
+
event: {
|
|
25654
|
+
input: query,
|
|
25655
|
+
tags,
|
|
25656
|
+
metadata: {
|
|
25657
|
+
serialized: retriever,
|
|
25658
|
+
metadata,
|
|
25659
|
+
name
|
|
25660
|
+
}
|
|
25661
|
+
}
|
|
25662
|
+
});
|
|
25663
|
+
}
|
|
25664
|
+
async handleRetrieverEnd(documents, runId, parentRunId, tags) {
|
|
25665
|
+
this.endSpan({ runId, parentRunId, output: documents, tags });
|
|
25666
|
+
}
|
|
25667
|
+
async handleRetrieverError(err, runId, parentRunId, tags) {
|
|
25668
|
+
this.endSpan({ runId, parentRunId, error: err, tags });
|
|
25669
|
+
}
|
|
25670
|
+
async handleLLMNewToken(_token, _idx, runId, _parentRunId, _tags) {
|
|
25671
|
+
if (!this.firstTokenTimes.has(runId)) {
|
|
25672
|
+
const now2 = Date.now();
|
|
25673
|
+
this.firstTokenTimes.set(runId, now2);
|
|
25674
|
+
const start = this.startTimes.get(runId);
|
|
25675
|
+
if (start !== void 0) {
|
|
25676
|
+
this.ttftMs.set(runId, (now2 - start) / 1e3);
|
|
25677
|
+
}
|
|
25678
|
+
}
|
|
25679
|
+
}
|
|
25680
|
+
};
|
|
25681
|
+
function getSerializedName(serialized) {
|
|
25682
|
+
if (typeof serialized.name === "string") {
|
|
25683
|
+
return serialized.name;
|
|
25684
|
+
}
|
|
25685
|
+
const lastIdPart = serialized.id?.at(-1);
|
|
25686
|
+
return typeof lastIdPart === "string" ? lastIdPart : void 0;
|
|
25687
|
+
}
|
|
25688
|
+
function cleanObject(obj) {
|
|
25689
|
+
return Object.fromEntries(
|
|
25690
|
+
Object.entries(obj).filter(([, value]) => {
|
|
25691
|
+
if (typeof value !== "number") {
|
|
25692
|
+
return false;
|
|
25693
|
+
}
|
|
25694
|
+
return Number.isFinite(value);
|
|
25695
|
+
})
|
|
25696
|
+
);
|
|
25697
|
+
}
|
|
25698
|
+
function walkGenerations(response) {
|
|
25699
|
+
const result = [];
|
|
25700
|
+
const generations = response.generations || [];
|
|
25701
|
+
for (const batch of generations) {
|
|
25702
|
+
if (Array.isArray(batch)) {
|
|
25703
|
+
for (const generation of batch) {
|
|
25704
|
+
if (isRecord(generation)) {
|
|
25705
|
+
result.push(generation);
|
|
25706
|
+
}
|
|
25707
|
+
}
|
|
25708
|
+
} else if (isRecord(batch)) {
|
|
25709
|
+
result.push(batch);
|
|
25710
|
+
}
|
|
25711
|
+
}
|
|
25712
|
+
return result;
|
|
25713
|
+
}
|
|
25714
|
+
function getModelNameFromResponse(response) {
|
|
25715
|
+
for (const generation of walkGenerations(response)) {
|
|
25716
|
+
const message = generation.message;
|
|
25717
|
+
if (!isRecord(message)) {
|
|
25718
|
+
continue;
|
|
25719
|
+
}
|
|
25720
|
+
const responseMetadata = message.response_metadata;
|
|
25721
|
+
if (!isRecord(responseMetadata)) {
|
|
25722
|
+
continue;
|
|
25723
|
+
}
|
|
25724
|
+
const modelName3 = responseMetadata.model_name ?? responseMetadata.model;
|
|
25725
|
+
if (typeof modelName3 === "string") {
|
|
25726
|
+
return modelName3;
|
|
25727
|
+
}
|
|
25728
|
+
}
|
|
25729
|
+
const llmOutput = response.llmOutput || {};
|
|
25730
|
+
const modelName2 = llmOutput.model_name ?? llmOutput.model;
|
|
25731
|
+
return typeof modelName2 === "string" ? modelName2 : void 0;
|
|
25732
|
+
}
|
|
25733
|
+
function getMetricsFromResponse(response) {
|
|
25734
|
+
for (const generation of walkGenerations(response)) {
|
|
25735
|
+
const message = generation.message;
|
|
25736
|
+
if (!isRecord(message)) {
|
|
25737
|
+
continue;
|
|
25738
|
+
}
|
|
25739
|
+
const usageMetadata = message.usage_metadata;
|
|
25740
|
+
if (!isRecord(usageMetadata)) {
|
|
25741
|
+
continue;
|
|
25742
|
+
}
|
|
25743
|
+
const inputTokenDetails = usageMetadata.input_token_details;
|
|
25744
|
+
return cleanObject({
|
|
25745
|
+
total_tokens: usageMetadata.total_tokens,
|
|
25746
|
+
prompt_tokens: usageMetadata.input_tokens,
|
|
25747
|
+
completion_tokens: usageMetadata.output_tokens,
|
|
25748
|
+
prompt_cache_creation_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_creation : void 0,
|
|
25749
|
+
prompt_cached_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_read : void 0
|
|
25750
|
+
});
|
|
25751
|
+
}
|
|
25752
|
+
const llmOutput = response.llmOutput || {};
|
|
25753
|
+
const tokenUsage = isRecord(llmOutput.tokenUsage) ? llmOutput.tokenUsage : isRecord(llmOutput.estimatedTokens) ? llmOutput.estimatedTokens : {};
|
|
25754
|
+
return cleanObject({
|
|
25755
|
+
total_tokens: tokenUsage.totalTokens,
|
|
25756
|
+
prompt_tokens: tokenUsage.promptTokens,
|
|
25757
|
+
completion_tokens: tokenUsage.completionTokens
|
|
25758
|
+
});
|
|
25759
|
+
}
|
|
25760
|
+
function safeJsonParse(input) {
|
|
25761
|
+
try {
|
|
25762
|
+
return JSON.parse(input);
|
|
25763
|
+
} catch {
|
|
25764
|
+
return input;
|
|
25765
|
+
}
|
|
25766
|
+
}
|
|
25767
|
+
function isRecord(value) {
|
|
25768
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
25769
|
+
}
|
|
25770
|
+
|
|
25771
|
+
// src/instrumentation/plugins/langchain-channels.ts
|
|
25772
|
+
var langChainChannels = defineChannels("@langchain/core", {
|
|
25773
|
+
configure: channel({
|
|
25774
|
+
channelName: "CallbackManager.configure",
|
|
25775
|
+
kind: "sync-stream"
|
|
25776
|
+
}),
|
|
25777
|
+
configureSync: channel({
|
|
25778
|
+
channelName: "CallbackManager._configureSync",
|
|
25779
|
+
kind: "sync-stream"
|
|
25780
|
+
})
|
|
25781
|
+
});
|
|
25782
|
+
|
|
25783
|
+
// src/instrumentation/plugins/langchain-plugin.ts
|
|
25784
|
+
var LangChainPlugin = class extends BasePlugin {
|
|
25785
|
+
injectedManagers = /* @__PURE__ */ new WeakSet();
|
|
25786
|
+
onEnable() {
|
|
25787
|
+
this.subscribeToConfigure(langChainChannels.configure);
|
|
25788
|
+
this.subscribeToConfigure(langChainChannels.configureSync);
|
|
25789
|
+
}
|
|
25790
|
+
onDisable() {
|
|
25791
|
+
for (const unsubscribe of this.unsubscribers) {
|
|
25792
|
+
unsubscribe();
|
|
25793
|
+
}
|
|
25794
|
+
this.unsubscribers = [];
|
|
25795
|
+
this.injectedManagers = /* @__PURE__ */ new WeakSet();
|
|
25796
|
+
}
|
|
25797
|
+
subscribeToConfigure(channel2) {
|
|
25798
|
+
const tracingChannel2 = channel2.tracingChannel();
|
|
25799
|
+
const handlers = {
|
|
25800
|
+
start: (event) => {
|
|
25801
|
+
injectHandlerIntoArguments(event.arguments);
|
|
25802
|
+
},
|
|
25803
|
+
end: (event) => {
|
|
25804
|
+
this.injectHandler(event.result);
|
|
25805
|
+
}
|
|
25806
|
+
};
|
|
25807
|
+
tracingChannel2.subscribe(handlers);
|
|
25808
|
+
this.unsubscribers.push(() => {
|
|
25809
|
+
tracingChannel2.unsubscribe(handlers);
|
|
25810
|
+
});
|
|
25811
|
+
}
|
|
25812
|
+
injectHandler(result) {
|
|
25813
|
+
if (!isCallbackManager(result)) {
|
|
25814
|
+
return;
|
|
25815
|
+
}
|
|
25816
|
+
if (this.injectedManagers.has(result) || hasBraintrustHandler(result)) {
|
|
25817
|
+
return;
|
|
25818
|
+
}
|
|
25819
|
+
try {
|
|
25820
|
+
result.addHandler(new BraintrustLangChainCallbackHandler(), true);
|
|
25821
|
+
this.injectedManagers.add(result);
|
|
25822
|
+
} catch {
|
|
25823
|
+
}
|
|
25824
|
+
}
|
|
25825
|
+
};
|
|
25826
|
+
function isCallbackManager(value) {
|
|
25827
|
+
if (typeof value !== "object" || value === null) {
|
|
25828
|
+
return false;
|
|
25829
|
+
}
|
|
25830
|
+
const maybeManager = value;
|
|
25831
|
+
return typeof maybeManager.addHandler === "function";
|
|
25832
|
+
}
|
|
25833
|
+
function hasBraintrustHandler(manager) {
|
|
25834
|
+
return manager.handlers?.some((handler) => {
|
|
25835
|
+
if (typeof handler !== "object" || handler === null) {
|
|
25836
|
+
return false;
|
|
25837
|
+
}
|
|
25838
|
+
const name = Reflect.get(handler, "name");
|
|
25839
|
+
return name === BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
|
|
25840
|
+
}) ?? false;
|
|
25841
|
+
}
|
|
25842
|
+
function injectHandlerIntoArguments(args) {
|
|
25843
|
+
if (!isWritableArgumentsObject(args)) {
|
|
25844
|
+
return;
|
|
25845
|
+
}
|
|
25846
|
+
const inheritedHandlers = Reflect.get(args, "0");
|
|
25847
|
+
const handler = new BraintrustLangChainCallbackHandler();
|
|
25848
|
+
if (inheritedHandlers === void 0 || inheritedHandlers === null) {
|
|
25849
|
+
Reflect.set(args, "0", [handler]);
|
|
25850
|
+
return;
|
|
25851
|
+
}
|
|
25852
|
+
if (Array.isArray(inheritedHandlers)) {
|
|
25853
|
+
if (!inheritedHandlers.some(isBraintrustHandler)) {
|
|
25854
|
+
inheritedHandlers.push(handler);
|
|
25855
|
+
}
|
|
25856
|
+
}
|
|
25857
|
+
}
|
|
25858
|
+
function isWritableArgumentsObject(args) {
|
|
25859
|
+
return typeof args === "object" && args !== null;
|
|
25860
|
+
}
|
|
25861
|
+
function isBraintrustHandler(handler) {
|
|
25862
|
+
if (typeof handler !== "object" || handler === null) {
|
|
25863
|
+
return false;
|
|
25864
|
+
}
|
|
25865
|
+
return Reflect.get(handler, "name") === BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
|
|
25866
|
+
}
|
|
25867
|
+
|
|
25868
|
+
// src/instrumentation/braintrust-plugin.ts
|
|
25869
|
+
function getIntegrationConfig(integrations, key) {
|
|
25870
|
+
return integrations[key];
|
|
25871
|
+
}
|
|
25872
|
+
var BraintrustPlugin = class extends BasePlugin {
|
|
25873
|
+
config;
|
|
25874
|
+
openaiPlugin = null;
|
|
25875
|
+
openAICodexPlugin = null;
|
|
25876
|
+
anthropicPlugin = null;
|
|
25877
|
+
aiSDKPlugin = null;
|
|
25878
|
+
claudeAgentSDKPlugin = null;
|
|
25879
|
+
cursorSDKPlugin = null;
|
|
25880
|
+
openAIAgentsPlugin = null;
|
|
25881
|
+
googleGenAIPlugin = null;
|
|
25882
|
+
huggingFacePlugin = null;
|
|
25883
|
+
openRouterPlugin = null;
|
|
25884
|
+
openRouterAgentPlugin = null;
|
|
25885
|
+
mistralPlugin = null;
|
|
25886
|
+
googleADKPlugin = null;
|
|
25887
|
+
coherePlugin = null;
|
|
25888
|
+
groqPlugin = null;
|
|
25889
|
+
genkitPlugin = null;
|
|
25890
|
+
gitHubCopilotPlugin = null;
|
|
25891
|
+
fluePlugin = null;
|
|
25892
|
+
langChainPlugin = null;
|
|
25893
|
+
constructor(config = {}) {
|
|
25894
|
+
super();
|
|
25895
|
+
this.config = config;
|
|
25896
|
+
}
|
|
25897
|
+
onEnable() {
|
|
25898
|
+
const integrations = this.config.integrations || {};
|
|
25899
|
+
if (integrations.openai !== false) {
|
|
25900
|
+
this.openaiPlugin = new OpenAIPlugin();
|
|
25901
|
+
this.openaiPlugin.enable();
|
|
25902
|
+
}
|
|
25903
|
+
if (integrations.openaiCodexSDK !== false) {
|
|
25904
|
+
this.openAICodexPlugin = new OpenAICodexPlugin();
|
|
25905
|
+
this.openAICodexPlugin.enable();
|
|
25906
|
+
}
|
|
25907
|
+
if (integrations.anthropic !== false) {
|
|
25908
|
+
this.anthropicPlugin = new AnthropicPlugin();
|
|
25909
|
+
this.anthropicPlugin.enable();
|
|
25910
|
+
}
|
|
25911
|
+
if (integrations.aisdk !== false && integrations.vercel !== false) {
|
|
25912
|
+
this.aiSDKPlugin = new AISDKPlugin();
|
|
25913
|
+
this.aiSDKPlugin.enable();
|
|
25914
|
+
}
|
|
25915
|
+
if (integrations.claudeAgentSDK !== false) {
|
|
25916
|
+
this.claudeAgentSDKPlugin = new ClaudeAgentSDKPlugin();
|
|
23699
25917
|
this.claudeAgentSDKPlugin.enable();
|
|
23700
25918
|
}
|
|
23701
25919
|
if (integrations.cursorSDK !== false && integrations.cursor !== false) {
|
|
23702
25920
|
this.cursorSDKPlugin = new CursorSDKPlugin();
|
|
23703
25921
|
this.cursorSDKPlugin.enable();
|
|
23704
25922
|
}
|
|
25923
|
+
if (integrations.openAIAgents !== false) {
|
|
25924
|
+
this.openAIAgentsPlugin = new OpenAIAgentsPlugin();
|
|
25925
|
+
this.openAIAgentsPlugin.enable();
|
|
25926
|
+
}
|
|
23705
25927
|
if (integrations.googleGenAI !== false && integrations.google !== false) {
|
|
23706
25928
|
this.googleGenAIPlugin = new GoogleGenAIPlugin();
|
|
23707
25929
|
this.googleGenAIPlugin.enable();
|
|
@@ -23742,6 +25964,14 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
23742
25964
|
this.gitHubCopilotPlugin = new GitHubCopilotPlugin();
|
|
23743
25965
|
this.gitHubCopilotPlugin.enable();
|
|
23744
25966
|
}
|
|
25967
|
+
if (getIntegrationConfig(integrations, "flue") !== false) {
|
|
25968
|
+
this.fluePlugin = new FluePlugin();
|
|
25969
|
+
this.fluePlugin.enable();
|
|
25970
|
+
}
|
|
25971
|
+
if (integrations.langchain !== false && integrations.langgraph !== false) {
|
|
25972
|
+
this.langChainPlugin = new LangChainPlugin();
|
|
25973
|
+
this.langChainPlugin.enable();
|
|
25974
|
+
}
|
|
23745
25975
|
}
|
|
23746
25976
|
onDisable() {
|
|
23747
25977
|
if (this.openaiPlugin) {
|
|
@@ -23768,6 +25998,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
23768
25998
|
this.cursorSDKPlugin.disable();
|
|
23769
25999
|
this.cursorSDKPlugin = null;
|
|
23770
26000
|
}
|
|
26001
|
+
if (this.openAIAgentsPlugin) {
|
|
26002
|
+
this.openAIAgentsPlugin.disable();
|
|
26003
|
+
this.openAIAgentsPlugin = null;
|
|
26004
|
+
}
|
|
23771
26005
|
if (this.googleGenAIPlugin) {
|
|
23772
26006
|
this.googleGenAIPlugin.disable();
|
|
23773
26007
|
this.googleGenAIPlugin = null;
|
|
@@ -23808,9 +26042,104 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
23808
26042
|
this.gitHubCopilotPlugin.disable();
|
|
23809
26043
|
this.gitHubCopilotPlugin = null;
|
|
23810
26044
|
}
|
|
26045
|
+
if (this.fluePlugin) {
|
|
26046
|
+
this.fluePlugin.disable();
|
|
26047
|
+
this.fluePlugin = null;
|
|
26048
|
+
}
|
|
26049
|
+
if (this.langChainPlugin) {
|
|
26050
|
+
this.langChainPlugin.disable();
|
|
26051
|
+
this.langChainPlugin = null;
|
|
26052
|
+
}
|
|
23811
26053
|
}
|
|
23812
26054
|
};
|
|
23813
26055
|
|
|
26056
|
+
// src/instrumentation/config.ts
|
|
26057
|
+
var envIntegrationAliases = {
|
|
26058
|
+
openai: "openai",
|
|
26059
|
+
"openai-codex": "openaiCodexSDK",
|
|
26060
|
+
"openai-codex-sdk": "openaiCodexSDK",
|
|
26061
|
+
openaicodexsdk: "openaiCodexSDK",
|
|
26062
|
+
codex: "openaiCodexSDK",
|
|
26063
|
+
"codex-sdk": "openaiCodexSDK",
|
|
26064
|
+
anthropic: "anthropic",
|
|
26065
|
+
aisdk: "aisdk",
|
|
26066
|
+
"ai-sdk": "aisdk",
|
|
26067
|
+
"vercel-ai": "aisdk",
|
|
26068
|
+
vercel: "vercel",
|
|
26069
|
+
claudeagentsdk: "claudeAgentSDK",
|
|
26070
|
+
"claude-agent-sdk": "claudeAgentSDK",
|
|
26071
|
+
cursor: "cursor",
|
|
26072
|
+
"cursor-sdk": "cursorSDK",
|
|
26073
|
+
cursorsdk: "cursorSDK",
|
|
26074
|
+
flue: "flue",
|
|
26075
|
+
"flue-runtime": "flue",
|
|
26076
|
+
"openai-agents": "openAIAgents",
|
|
26077
|
+
openaiagents: "openAIAgents",
|
|
26078
|
+
"openai-agents-core": "openAIAgents",
|
|
26079
|
+
openaiagentscore: "openAIAgents",
|
|
26080
|
+
google: "google",
|
|
26081
|
+
"google-genai": "googleGenAI",
|
|
26082
|
+
googlegenai: "googleGenAI",
|
|
26083
|
+
huggingface: "huggingface",
|
|
26084
|
+
openrouter: "openrouter",
|
|
26085
|
+
openrouteragent: "openrouterAgent",
|
|
26086
|
+
"openrouter-agent": "openrouterAgent",
|
|
26087
|
+
mistral: "mistral",
|
|
26088
|
+
googleadk: "googleADK",
|
|
26089
|
+
"google-adk": "googleADK",
|
|
26090
|
+
cohere: "cohere",
|
|
26091
|
+
groq: "groq",
|
|
26092
|
+
"groq-sdk": "groq",
|
|
26093
|
+
genkit: "genkit",
|
|
26094
|
+
"firebase-genkit": "genkit",
|
|
26095
|
+
githubcopilot: "gitHubCopilot",
|
|
26096
|
+
"github-copilot": "gitHubCopilot",
|
|
26097
|
+
"copilot-sdk": "gitHubCopilot",
|
|
26098
|
+
langchain: "langchain",
|
|
26099
|
+
"langchain-js": "langchain",
|
|
26100
|
+
"@langchain": "langchain",
|
|
26101
|
+
langgraph: "langgraph"
|
|
26102
|
+
};
|
|
26103
|
+
function getDefaultInstrumentationIntegrations() {
|
|
26104
|
+
return {
|
|
26105
|
+
openai: true,
|
|
26106
|
+
openaiCodexSDK: true,
|
|
26107
|
+
anthropic: true,
|
|
26108
|
+
vercel: true,
|
|
26109
|
+
aisdk: true,
|
|
26110
|
+
google: true,
|
|
26111
|
+
googleGenAI: true,
|
|
26112
|
+
googleADK: true,
|
|
26113
|
+
huggingface: true,
|
|
26114
|
+
claudeAgentSDK: true,
|
|
26115
|
+
cursor: true,
|
|
26116
|
+
cursorSDK: true,
|
|
26117
|
+
flue: true,
|
|
26118
|
+
openAIAgents: true,
|
|
26119
|
+
openrouter: true,
|
|
26120
|
+
openrouterAgent: true,
|
|
26121
|
+
mistral: true,
|
|
26122
|
+
cohere: true,
|
|
26123
|
+
groq: true,
|
|
26124
|
+
genkit: true,
|
|
26125
|
+
gitHubCopilot: true,
|
|
26126
|
+
langchain: true,
|
|
26127
|
+
langgraph: true
|
|
26128
|
+
};
|
|
26129
|
+
}
|
|
26130
|
+
function readDisabledInstrumentationEnvConfig(disabledList) {
|
|
26131
|
+
const integrations = {};
|
|
26132
|
+
if (disabledList) {
|
|
26133
|
+
for (const value of disabledList.split(",")) {
|
|
26134
|
+
const sdk = value.trim().toLowerCase();
|
|
26135
|
+
if (sdk.length > 0) {
|
|
26136
|
+
integrations[envIntegrationAliases[sdk] ?? sdk] = false;
|
|
26137
|
+
}
|
|
26138
|
+
}
|
|
26139
|
+
}
|
|
26140
|
+
return { integrations };
|
|
26141
|
+
}
|
|
26142
|
+
|
|
23814
26143
|
// src/instrumentation/registry.ts
|
|
23815
26144
|
var REGISTRY_STATE_KEY = /* @__PURE__ */ Symbol.for("braintrust.registry");
|
|
23816
26145
|
function getSharedState() {
|
|
@@ -23889,50 +26218,16 @@ var PluginRegistry = class {
|
|
|
23889
26218
|
* Get default configuration (all integrations enabled).
|
|
23890
26219
|
*/
|
|
23891
26220
|
getDefaultConfig() {
|
|
23892
|
-
return
|
|
23893
|
-
openai: true,
|
|
23894
|
-
openaiCodexSDK: true,
|
|
23895
|
-
anthropic: true,
|
|
23896
|
-
vercel: true,
|
|
23897
|
-
aisdk: true,
|
|
23898
|
-
google: true,
|
|
23899
|
-
googleGenAI: true,
|
|
23900
|
-
googleADK: true,
|
|
23901
|
-
huggingface: true,
|
|
23902
|
-
claudeAgentSDK: true,
|
|
23903
|
-
cursor: true,
|
|
23904
|
-
cursorSDK: true,
|
|
23905
|
-
openrouter: true,
|
|
23906
|
-
openrouterAgent: true,
|
|
23907
|
-
mistral: true,
|
|
23908
|
-
cohere: true,
|
|
23909
|
-
groq: true,
|
|
23910
|
-
genkit: true,
|
|
23911
|
-
gitHubCopilot: true
|
|
23912
|
-
};
|
|
26221
|
+
return getDefaultInstrumentationIntegrations();
|
|
23913
26222
|
}
|
|
23914
26223
|
/**
|
|
23915
26224
|
* Read configuration from environment variables.
|
|
23916
26225
|
* Supports: BRAINTRUST_DISABLE_INSTRUMENTATION=openai,anthropic,...
|
|
23917
26226
|
*/
|
|
23918
26227
|
readEnvConfig() {
|
|
23919
|
-
|
|
23920
|
-
|
|
23921
|
-
|
|
23922
|
-
const disabled = disabledList.split(",").map((s) => s.trim().toLowerCase()).filter((s) => s.length > 0);
|
|
23923
|
-
for (const sdk of disabled) {
|
|
23924
|
-
if (sdk === "cursor-sdk") {
|
|
23925
|
-
integrations.cursorSDK = false;
|
|
23926
|
-
} else if (sdk === "githubcopilot" || sdk === "github-copilot" || sdk === "copilot-sdk") {
|
|
23927
|
-
integrations.gitHubCopilot = false;
|
|
23928
|
-
} else if (sdk === "openai-codex-sdk") {
|
|
23929
|
-
integrations.openaiCodexSDK = false;
|
|
23930
|
-
} else {
|
|
23931
|
-
integrations[sdk] = false;
|
|
23932
|
-
}
|
|
23933
|
-
}
|
|
23934
|
-
}
|
|
23935
|
-
return { integrations };
|
|
26228
|
+
return readDisabledInstrumentationEnvConfig(
|
|
26229
|
+
isomorph_default.getEnv("BRAINTRUST_DISABLE_INSTRUMENTATION")
|
|
26230
|
+
);
|
|
23936
26231
|
}
|
|
23937
26232
|
};
|
|
23938
26233
|
var registry = new PluginRegistry();
|
|
@@ -23962,6 +26257,10 @@ function configureEdgeLight() {
|
|
|
23962
26257
|
}
|
|
23963
26258
|
return process.env[name];
|
|
23964
26259
|
};
|
|
26260
|
+
isomorph_default.getBraintrustApiKey = async () => {
|
|
26261
|
+
const value = isomorph_default.getEnv("BRAINTRUST_API_KEY");
|
|
26262
|
+
return value?.trim() ? value : void 0;
|
|
26263
|
+
};
|
|
23965
26264
|
isomorph_default.hash = (data) => {
|
|
23966
26265
|
let hash = 0;
|
|
23967
26266
|
for (let i = 0; i < data.length; i++) {
|
|
@@ -23983,8 +26282,10 @@ __export(exports_exports, {
|
|
|
23983
26282
|
Attachment: () => Attachment,
|
|
23984
26283
|
AttachmentReference: () => AttachmentReference,
|
|
23985
26284
|
BRAINTRUST_CURRENT_SPAN_STORE: () => BRAINTRUST_CURRENT_SPAN_STORE,
|
|
26285
|
+
BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME: () => BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME,
|
|
23986
26286
|
BaseAttachment: () => BaseAttachment,
|
|
23987
26287
|
BaseExperiment: () => BaseExperiment,
|
|
26288
|
+
BraintrustLangChainCallbackHandler: () => BraintrustLangChainCallbackHandler,
|
|
23988
26289
|
BraintrustMiddleware: () => BraintrustMiddleware,
|
|
23989
26290
|
BraintrustState: () => BraintrustState,
|
|
23990
26291
|
BraintrustStream: () => BraintrustStream,
|
|
@@ -23995,6 +26296,7 @@ __export(exports_exports, {
|
|
|
23995
26296
|
DEFAULT_FETCH_BATCH_SIZE: () => DEFAULT_FETCH_BATCH_SIZE,
|
|
23996
26297
|
DEFAULT_MAX_REQUEST_SIZE: () => DEFAULT_MAX_REQUEST_SIZE,
|
|
23997
26298
|
Dataset: () => Dataset2,
|
|
26299
|
+
DatasetPipeline: () => DatasetPipeline,
|
|
23998
26300
|
ERR_PERMALINK: () => ERR_PERMALINK,
|
|
23999
26301
|
Eval: () => Eval,
|
|
24000
26302
|
EvalResultWithSummary: () => EvalResultWithSummary,
|
|
@@ -24110,6 +26412,8 @@ __export(exports_exports, {
|
|
|
24110
26412
|
wrapCohere: () => wrapCohere,
|
|
24111
26413
|
wrapCopilotClient: () => wrapCopilotClient,
|
|
24112
26414
|
wrapCursorSDK: () => wrapCursorSDK,
|
|
26415
|
+
wrapFlueContext: () => wrapFlueContext,
|
|
26416
|
+
wrapFlueSession: () => wrapFlueSession,
|
|
24113
26417
|
wrapGenkit: () => wrapGenkit,
|
|
24114
26418
|
wrapGoogleADK: () => wrapGoogleADK,
|
|
24115
26419
|
wrapGoogleGenAI: () => wrapGoogleGenAI,
|
|
@@ -25209,7 +27513,7 @@ function extractModelParameters(params, excludeKeys) {
|
|
|
25209
27513
|
}
|
|
25210
27514
|
return modelParams;
|
|
25211
27515
|
}
|
|
25212
|
-
function
|
|
27516
|
+
function getNumberProperty3(obj, key) {
|
|
25213
27517
|
if (!obj || typeof obj !== "object" || !(key in obj)) {
|
|
25214
27518
|
return void 0;
|
|
25215
27519
|
}
|
|
@@ -25218,31 +27522,31 @@ function getNumberProperty2(obj, key) {
|
|
|
25218
27522
|
}
|
|
25219
27523
|
function normalizeUsageMetrics(usage, provider, providerMetadata) {
|
|
25220
27524
|
const metrics = {};
|
|
25221
|
-
const inputTokens =
|
|
27525
|
+
const inputTokens = getNumberProperty3(usage, "inputTokens");
|
|
25222
27526
|
if (inputTokens !== void 0) {
|
|
25223
27527
|
metrics.prompt_tokens = inputTokens;
|
|
25224
27528
|
}
|
|
25225
|
-
const outputTokens =
|
|
27529
|
+
const outputTokens = getNumberProperty3(usage, "outputTokens");
|
|
25226
27530
|
if (outputTokens !== void 0) {
|
|
25227
27531
|
metrics.completion_tokens = outputTokens;
|
|
25228
27532
|
}
|
|
25229
|
-
const totalTokens =
|
|
27533
|
+
const totalTokens = getNumberProperty3(usage, "totalTokens");
|
|
25230
27534
|
if (totalTokens !== void 0) {
|
|
25231
27535
|
metrics.tokens = totalTokens;
|
|
25232
27536
|
}
|
|
25233
|
-
const reasoningTokens =
|
|
27537
|
+
const reasoningTokens = getNumberProperty3(usage, "reasoningTokens");
|
|
25234
27538
|
if (reasoningTokens !== void 0) {
|
|
25235
27539
|
metrics.completion_reasoning_tokens = reasoningTokens;
|
|
25236
27540
|
}
|
|
25237
|
-
const cachedInputTokens =
|
|
27541
|
+
const cachedInputTokens = getNumberProperty3(usage, "cachedInputTokens");
|
|
25238
27542
|
if (cachedInputTokens !== void 0) {
|
|
25239
27543
|
metrics.prompt_cached_tokens = cachedInputTokens;
|
|
25240
27544
|
}
|
|
25241
27545
|
if (provider === "anthropic") {
|
|
25242
27546
|
const anthropicMetadata = providerMetadata?.anthropic;
|
|
25243
27547
|
if (anthropicMetadata) {
|
|
25244
|
-
const cacheReadTokens =
|
|
25245
|
-
const cacheCreationTokens =
|
|
27548
|
+
const cacheReadTokens = getNumberProperty3(anthropicMetadata.usage, "cache_read_input_tokens") || 0;
|
|
27549
|
+
const cacheCreationTokens = getNumberProperty3(
|
|
25246
27550
|
anthropicMetadata.usage,
|
|
25247
27551
|
"cache_creation_input_tokens"
|
|
25248
27552
|
) || 0;
|
|
@@ -26217,17 +28521,17 @@ function wrapGenkit(genkit) {
|
|
|
26217
28521
|
console.warn("Unsupported Genkit object. Not wrapping.");
|
|
26218
28522
|
return genkit;
|
|
26219
28523
|
}
|
|
26220
|
-
function
|
|
28524
|
+
function isRecord2(value) {
|
|
26221
28525
|
return typeof value === "object" && value !== null;
|
|
26222
28526
|
}
|
|
26223
28527
|
function isPropertyBag(value) {
|
|
26224
|
-
return
|
|
28528
|
+
return isRecord2(value) || typeof value === "function";
|
|
26225
28529
|
}
|
|
26226
28530
|
function hasFunction(value, methodName) {
|
|
26227
28531
|
return isPropertyBag(value) && methodName in value && typeof value[methodName] === "function";
|
|
26228
28532
|
}
|
|
26229
28533
|
function isGenkitInstance(value) {
|
|
26230
|
-
return
|
|
28534
|
+
return isRecord2(value) && (hasFunction(value, "generate") || hasFunction(value, "generateStream") || hasFunction(value, "defineFlow") || hasFunction(value, "defineTool"));
|
|
26231
28535
|
}
|
|
26232
28536
|
function isGenkitModule(value) {
|
|
26233
28537
|
return hasFunction(value, "genkit");
|
|
@@ -26281,7 +28585,7 @@ function patchGenkitRegistry(instance) {
|
|
|
26281
28585
|
patchGenkitRegistryConstructor(registry2);
|
|
26282
28586
|
}
|
|
26283
28587
|
function patchGenkitRegistryLookup(registry2) {
|
|
26284
|
-
if (!
|
|
28588
|
+
if (!isRecord2(registry2) || hasRegistryPatchedFlag(registry2) || !hasFunction(registry2, "lookupAction")) {
|
|
26285
28589
|
return;
|
|
26286
28590
|
}
|
|
26287
28591
|
const originalLookupAction = registry2.lookupAction;
|
|
@@ -26307,7 +28611,7 @@ function patchGenkitRegistryLookup(registry2) {
|
|
|
26307
28611
|
}
|
|
26308
28612
|
}
|
|
26309
28613
|
function patchGenkitRegistryConstructor(registry2) {
|
|
26310
|
-
if (!
|
|
28614
|
+
if (!isRecord2(registry2)) {
|
|
26311
28615
|
return;
|
|
26312
28616
|
}
|
|
26313
28617
|
const constructor = registry2.constructor;
|
|
@@ -26323,7 +28627,7 @@ function patchGenkitRegistryConstructor(registry2) {
|
|
|
26323
28627
|
configurable: true,
|
|
26324
28628
|
value: (...args) => {
|
|
26325
28629
|
const childRegistry = originalWithParent.apply(constructor, args);
|
|
26326
|
-
if (args.some((arg) =>
|
|
28630
|
+
if (args.some((arg) => isRecord2(arg) && hasRegistryPatchedFlag(arg))) {
|
|
26327
28631
|
patchGenkitRegistryLookup(childRegistry);
|
|
26328
28632
|
patchGenkitRegistryConstructor(childRegistry);
|
|
26329
28633
|
}
|
|
@@ -26422,7 +28726,7 @@ function hasRegistryConstructorPatchedFlag(value) {
|
|
|
26422
28726
|
);
|
|
26423
28727
|
}
|
|
26424
28728
|
function isPromiseLike2(value) {
|
|
26425
|
-
return
|
|
28729
|
+
return isRecord2(value) && "then" in value && typeof value.then === "function";
|
|
26426
28730
|
}
|
|
26427
28731
|
|
|
26428
28732
|
// src/wrappers/huggingface.ts
|
|
@@ -26785,14 +29089,14 @@ function wrapMistral(mistral) {
|
|
|
26785
29089
|
console.warn("Unsupported Mistral library. Not wrapping.");
|
|
26786
29090
|
return mistral;
|
|
26787
29091
|
}
|
|
26788
|
-
function
|
|
29092
|
+
function isRecord3(value) {
|
|
26789
29093
|
return typeof value === "object" && value !== null;
|
|
26790
29094
|
}
|
|
26791
29095
|
function hasFunction3(value, methodName) {
|
|
26792
|
-
return
|
|
29096
|
+
return isRecord3(value) && methodName in value && typeof value[methodName] === "function";
|
|
26793
29097
|
}
|
|
26794
29098
|
function isSupportedMistralClient(value) {
|
|
26795
|
-
if (!
|
|
29099
|
+
if (!isRecord3(value)) {
|
|
26796
29100
|
return false;
|
|
26797
29101
|
}
|
|
26798
29102
|
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);
|
|
@@ -26976,14 +29280,14 @@ function wrapCohere(cohere) {
|
|
|
26976
29280
|
return cohere;
|
|
26977
29281
|
}
|
|
26978
29282
|
var cohereProxyCache = /* @__PURE__ */ new WeakMap();
|
|
26979
|
-
function
|
|
29283
|
+
function isRecord4(value) {
|
|
26980
29284
|
return typeof value === "object" && value !== null;
|
|
26981
29285
|
}
|
|
26982
29286
|
function hasFunction4(value, methodName) {
|
|
26983
|
-
return
|
|
29287
|
+
return isRecord4(value) && methodName in value && typeof value[methodName] === "function";
|
|
26984
29288
|
}
|
|
26985
29289
|
function isSupportedCohereClient(value) {
|
|
26986
|
-
if (!
|
|
29290
|
+
if (!isRecord4(value)) {
|
|
26987
29291
|
return false;
|
|
26988
29292
|
}
|
|
26989
29293
|
return hasFunction4(value, "chat") || hasFunction4(value, "chatStream") || hasFunction4(value, "embed") || hasFunction4(value, "rerank");
|
|
@@ -27043,20 +29347,20 @@ function wrapGroq(groq) {
|
|
|
27043
29347
|
console.warn("Unsupported Groq library. Not wrapping.");
|
|
27044
29348
|
return groq;
|
|
27045
29349
|
}
|
|
27046
|
-
function
|
|
29350
|
+
function isRecord5(value) {
|
|
27047
29351
|
return typeof value === "object" && value !== null;
|
|
27048
29352
|
}
|
|
27049
29353
|
function hasFunction5(value, methodName) {
|
|
27050
|
-
return
|
|
29354
|
+
return isRecord5(value) && methodName in value && typeof value[methodName] === "function";
|
|
27051
29355
|
}
|
|
27052
29356
|
function hasChat2(value) {
|
|
27053
|
-
return
|
|
29357
|
+
return isRecord5(value) && isRecord5(value.completions) && hasFunction5(value.completions, "create");
|
|
27054
29358
|
}
|
|
27055
29359
|
function hasEmbeddings2(value) {
|
|
27056
29360
|
return hasFunction5(value, "create");
|
|
27057
29361
|
}
|
|
27058
29362
|
function isSupportedGroqClient(value) {
|
|
27059
|
-
return
|
|
29363
|
+
return isRecord5(value) && (value.chat !== void 0 && hasChat2(value.chat) || value.embeddings !== void 0 && hasEmbeddings2(value.embeddings));
|
|
27060
29364
|
}
|
|
27061
29365
|
function groqProxy(groq) {
|
|
27062
29366
|
const privateMethodWorkaroundCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -27251,10 +29555,12 @@ function formatExperimentSummary(summary) {
|
|
|
27251
29555
|
// src/wrappers/shared/flush.ts
|
|
27252
29556
|
async function summarizeAndFlush(experiment, options) {
|
|
27253
29557
|
const shouldDisplay = options.displaySummary ?? true;
|
|
27254
|
-
|
|
27255
|
-
|
|
27256
|
-
|
|
29558
|
+
if (!shouldDisplay) {
|
|
29559
|
+
await experiment.flush();
|
|
29560
|
+
return;
|
|
27257
29561
|
}
|
|
29562
|
+
const summary = await experiment.summarize();
|
|
29563
|
+
console.log(formatExperimentSummary(summary));
|
|
27258
29564
|
}
|
|
27259
29565
|
|
|
27260
29566
|
// src/wrappers/vitest/flush-manager.ts
|
|
@@ -29118,8 +31424,12 @@ var waterfall$1 = awaitify(waterfall);
|
|
|
29118
31424
|
|
|
29119
31425
|
// src/trace.ts
|
|
29120
31426
|
var SpanFetcher = class _SpanFetcher extends ObjectFetcher {
|
|
29121
|
-
constructor(objectType, _objectId, rootSpanId, _state, spanTypeFilter) {
|
|
29122
|
-
const filterExpr = _SpanFetcher.buildFilter(
|
|
31427
|
+
constructor(objectType, _objectId, rootSpanId, _state, spanTypeFilter, includeScorers = false) {
|
|
31428
|
+
const filterExpr = _SpanFetcher.buildFilter(
|
|
31429
|
+
rootSpanId,
|
|
31430
|
+
spanTypeFilter,
|
|
31431
|
+
includeScorers
|
|
31432
|
+
);
|
|
29123
31433
|
super(objectType, void 0, void 0, {
|
|
29124
31434
|
filter: filterExpr
|
|
29125
31435
|
});
|
|
@@ -29128,16 +31438,17 @@ var SpanFetcher = class _SpanFetcher extends ObjectFetcher {
|
|
|
29128
31438
|
this._state = _state;
|
|
29129
31439
|
this.spanTypeFilter = spanTypeFilter;
|
|
29130
31440
|
}
|
|
29131
|
-
static buildFilter(rootSpanId, spanTypeFilter) {
|
|
31441
|
+
static buildFilter(rootSpanId, spanTypeFilter, includeScorers = false) {
|
|
29132
31442
|
const children = [
|
|
29133
31443
|
// Base filter: root_span_id = 'value'
|
|
29134
31444
|
{
|
|
29135
31445
|
op: "eq",
|
|
29136
31446
|
left: { op: "ident", name: ["root_span_id"] },
|
|
29137
31447
|
right: { op: "literal", value: rootSpanId }
|
|
29138
|
-
}
|
|
29139
|
-
|
|
29140
|
-
|
|
31448
|
+
}
|
|
31449
|
+
];
|
|
31450
|
+
if (!includeScorers) {
|
|
31451
|
+
children.push({
|
|
29141
31452
|
op: "or",
|
|
29142
31453
|
children: [
|
|
29143
31454
|
{
|
|
@@ -29150,8 +31461,8 @@ var SpanFetcher = class _SpanFetcher extends ObjectFetcher {
|
|
|
29150
31461
|
right: { op: "literal", value: "scorer" }
|
|
29151
31462
|
}
|
|
29152
31463
|
]
|
|
29153
|
-
}
|
|
29154
|
-
|
|
31464
|
+
});
|
|
31465
|
+
}
|
|
29155
31466
|
if (spanTypeFilter && spanTypeFilter.length > 0) {
|
|
29156
31467
|
children.push({
|
|
29157
31468
|
op: "in",
|
|
@@ -29177,35 +31488,49 @@ var CachedSpanFetcher = class {
|
|
|
29177
31488
|
fetchFn;
|
|
29178
31489
|
constructor(objectTypeOrFetchFn, objectId, rootSpanId, getState) {
|
|
29179
31490
|
if (typeof objectTypeOrFetchFn === "function") {
|
|
29180
|
-
this.fetchFn = objectTypeOrFetchFn;
|
|
31491
|
+
this.fetchFn = (spanType) => objectTypeOrFetchFn(spanType);
|
|
29181
31492
|
} else {
|
|
29182
31493
|
const objectType = objectTypeOrFetchFn;
|
|
29183
|
-
this.fetchFn = async (spanType) => {
|
|
31494
|
+
this.fetchFn = async (spanType, includeScorers) => {
|
|
29184
31495
|
const state = await getState();
|
|
29185
31496
|
const fetcher = new SpanFetcher(
|
|
29186
31497
|
objectType,
|
|
29187
31498
|
objectId,
|
|
29188
31499
|
rootSpanId,
|
|
29189
31500
|
state,
|
|
29190
|
-
spanType
|
|
31501
|
+
spanType,
|
|
31502
|
+
includeScorers
|
|
29191
31503
|
);
|
|
29192
31504
|
const rows = await fetcher.fetchedData();
|
|
29193
|
-
return rows.
|
|
31505
|
+
return rows.map((row) => ({
|
|
29194
31506
|
input: row.input,
|
|
29195
31507
|
output: row.output,
|
|
31508
|
+
expected: row.expected,
|
|
31509
|
+
error: row.error,
|
|
31510
|
+
scores: row.scores,
|
|
31511
|
+
metrics: row.metrics,
|
|
29196
31512
|
metadata: row.metadata,
|
|
29197
31513
|
span_id: row.span_id,
|
|
29198
31514
|
span_parents: row.span_parents,
|
|
31515
|
+
is_root: row.is_root,
|
|
29199
31516
|
span_attributes: row.span_attributes,
|
|
29200
31517
|
id: row.id,
|
|
29201
31518
|
_xact_id: row._xact_id,
|
|
29202
31519
|
_pagination_key: row._pagination_key,
|
|
29203
|
-
root_span_id: row.root_span_id
|
|
31520
|
+
root_span_id: row.root_span_id,
|
|
31521
|
+
created: row.created,
|
|
31522
|
+
tags: row.tags
|
|
29204
31523
|
}));
|
|
29205
31524
|
};
|
|
29206
31525
|
}
|
|
29207
31526
|
}
|
|
29208
|
-
async getSpans({
|
|
31527
|
+
async getSpans({
|
|
31528
|
+
spanType,
|
|
31529
|
+
includeScorers = false
|
|
31530
|
+
} = {}) {
|
|
31531
|
+
if (includeScorers) {
|
|
31532
|
+
return this.fetchFn(spanType, true);
|
|
31533
|
+
}
|
|
29209
31534
|
if (this.allFetched) {
|
|
29210
31535
|
return this.getFromCache(spanType);
|
|
29211
31536
|
}
|
|
@@ -29222,7 +31547,7 @@ var CachedSpanFetcher = class {
|
|
|
29222
31547
|
return this.getFromCache(spanType);
|
|
29223
31548
|
}
|
|
29224
31549
|
async fetchSpans(spanType) {
|
|
29225
|
-
const spans = await this.fetchFn(spanType);
|
|
31550
|
+
const spans = await this.fetchFn(spanType, false);
|
|
29226
31551
|
for (const span of spans) {
|
|
29227
31552
|
const type = span.span_attributes?.type ?? "";
|
|
29228
31553
|
const existing = this.spanCache.get(type) ?? [];
|
|
@@ -29300,10 +31625,13 @@ var LocalTrace = class {
|
|
|
29300
31625
|
* First checks the local span cache for recently logged spans, then falls
|
|
29301
31626
|
* back to CachedSpanFetcher which handles BTQL fetching and caching.
|
|
29302
31627
|
*/
|
|
29303
|
-
async getSpans({
|
|
31628
|
+
async getSpans({
|
|
31629
|
+
spanType,
|
|
31630
|
+
includeScorers = false
|
|
31631
|
+
} = {}) {
|
|
29304
31632
|
const cachedSpans = this.state.spanCache.getByRootSpanId(this.rootSpanId);
|
|
29305
31633
|
if (cachedSpans && cachedSpans.length > 0) {
|
|
29306
|
-
let spans = cachedSpans.filter(
|
|
31634
|
+
let spans = includeScorers ? cachedSpans : cachedSpans.filter(
|
|
29307
31635
|
(span) => span.span_attributes?.purpose !== "scorer"
|
|
29308
31636
|
);
|
|
29309
31637
|
if (spanType && spanType.length > 0) {
|
|
@@ -29314,13 +31642,19 @@ var LocalTrace = class {
|
|
|
29314
31642
|
return spans.map((span) => ({
|
|
29315
31643
|
input: span.input,
|
|
29316
31644
|
output: span.output,
|
|
31645
|
+
expected: span.expected,
|
|
31646
|
+
error: span.error,
|
|
31647
|
+
scores: span.scores,
|
|
31648
|
+
metrics: span.metrics,
|
|
29317
31649
|
metadata: span.metadata,
|
|
29318
31650
|
span_id: span.span_id,
|
|
29319
31651
|
span_parents: span.span_parents,
|
|
29320
|
-
|
|
31652
|
+
is_root: span.is_root,
|
|
31653
|
+
span_attributes: span.span_attributes,
|
|
31654
|
+
tags: span.tags
|
|
29321
31655
|
}));
|
|
29322
31656
|
}
|
|
29323
|
-
return this.cachedFetcher.getSpans({ spanType });
|
|
31657
|
+
return this.cachedFetcher.getSpans({ spanType, includeScorers });
|
|
29324
31658
|
}
|
|
29325
31659
|
/**
|
|
29326
31660
|
* Get the thread (preprocessed messages) for this trace.
|
|
@@ -30509,6 +32843,34 @@ var defaultReporter = {
|
|
|
30509
32843
|
}
|
|
30510
32844
|
};
|
|
30511
32845
|
|
|
32846
|
+
// src/dataset-pipeline.ts
|
|
32847
|
+
function DatasetPipeline(definition) {
|
|
32848
|
+
if (!globalThis.__braintrust_dataset_pipelines) {
|
|
32849
|
+
globalThis.__braintrust_dataset_pipelines = [];
|
|
32850
|
+
}
|
|
32851
|
+
const storedDefinition = {
|
|
32852
|
+
name: definition.name,
|
|
32853
|
+
source: {
|
|
32854
|
+
projectId: definition.source.projectId,
|
|
32855
|
+
projectName: definition.source.projectName,
|
|
32856
|
+
orgName: definition.source.orgName,
|
|
32857
|
+
filter: definition.source.filter,
|
|
32858
|
+
scope: definition.source.scope ?? "span"
|
|
32859
|
+
},
|
|
32860
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any
|
|
32861
|
+
transform: definition.transform,
|
|
32862
|
+
target: {
|
|
32863
|
+
projectId: definition.target.projectId,
|
|
32864
|
+
projectName: definition.target.projectName,
|
|
32865
|
+
orgName: definition.target.orgName,
|
|
32866
|
+
datasetName: definition.target.datasetName,
|
|
32867
|
+
description: definition.target.description,
|
|
32868
|
+
metadata: definition.target.metadata
|
|
32869
|
+
}
|
|
32870
|
+
};
|
|
32871
|
+
globalThis.__braintrust_dataset_pipelines.push(storedDefinition);
|
|
32872
|
+
}
|
|
32873
|
+
|
|
30512
32874
|
// src/framework2.ts
|
|
30513
32875
|
var import_v312 = require("zod/v3");
|
|
30514
32876
|
var currentFilename = typeof __filename !== "undefined" ? __filename : "unknown";
|