braintrust 3.11.0 → 3.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -8
- package/dev/dist/index.d.mts +26 -7
- package/dev/dist/index.d.ts +26 -7
- package/dev/dist/index.js +2717 -335
- package/dev/dist/index.mjs +2499 -117
- package/dist/apply-auto-instrumentation.browser.d.mts +2 -0
- package/dist/apply-auto-instrumentation.browser.d.ts +2 -0
- package/dist/apply-auto-instrumentation.browser.js +18 -0
- package/dist/apply-auto-instrumentation.browser.mjs +0 -0
- package/dist/apply-auto-instrumentation.d.mts +2 -0
- package/dist/apply-auto-instrumentation.d.ts +2 -0
- package/dist/apply-auto-instrumentation.js +2534 -0
- package/dist/apply-auto-instrumentation.mjs +2534 -0
- package/dist/auto-instrumentations/bundler/esbuild.cjs +1803 -1283
- package/dist/auto-instrumentations/bundler/esbuild.d.mts +9 -5
- package/dist/auto-instrumentations/bundler/esbuild.d.ts +9 -5
- package/dist/auto-instrumentations/bundler/esbuild.mjs +10 -2
- package/dist/auto-instrumentations/bundler/next.cjs +3269 -0
- package/dist/auto-instrumentations/bundler/next.d.mts +3 -0
- package/dist/auto-instrumentations/bundler/next.d.ts +3 -0
- package/dist/auto-instrumentations/bundler/next.mjs +189 -0
- package/dist/auto-instrumentations/bundler/rollup.cjs +1803 -1283
- package/dist/auto-instrumentations/bundler/rollup.d.mts +9 -5
- package/dist/auto-instrumentations/bundler/rollup.d.ts +9 -5
- package/dist/auto-instrumentations/bundler/rollup.mjs +10 -2
- package/dist/auto-instrumentations/bundler/vite.cjs +1803 -1283
- package/dist/auto-instrumentations/bundler/vite.d.mts +9 -5
- package/dist/auto-instrumentations/bundler/vite.d.ts +9 -5
- package/dist/auto-instrumentations/bundler/vite.mjs +10 -2
- package/dist/auto-instrumentations/bundler/webpack-loader.cjs +1861 -1308
- package/dist/auto-instrumentations/bundler/webpack-loader.d.ts +3 -3
- package/dist/auto-instrumentations/bundler/webpack.cjs +1803 -1283
- package/dist/auto-instrumentations/bundler/webpack.d.mts +9 -5
- package/dist/auto-instrumentations/bundler/webpack.d.ts +9 -5
- package/dist/auto-instrumentations/bundler/webpack.mjs +6 -6
- package/dist/auto-instrumentations/{chunk-DIV5TO4S.mjs → chunk-E5DUYJWK.mjs} +338 -1
- package/dist/auto-instrumentations/chunk-GJOO4ESL.mjs +300 -0
- package/dist/auto-instrumentations/chunk-WFEUJACP.mjs +18 -0
- package/dist/auto-instrumentations/hook.mjs +1713 -1460
- package/dist/auto-instrumentations/index.cjs +94 -0
- package/dist/auto-instrumentations/index.d.mts +5 -1
- package/dist/auto-instrumentations/index.d.ts +5 -1
- package/dist/auto-instrumentations/index.mjs +6 -247
- package/dist/auto-instrumentations/loader/esm-hook.mjs +19 -2
- package/dist/auto-instrumentations/plugin-D7nDswtC.d.mts +44 -0
- package/dist/auto-instrumentations/plugin-D7nDswtC.d.ts +44 -0
- package/dist/browser.d.mts +264 -47
- package/dist/browser.d.ts +264 -47
- package/dist/browser.js +2521 -159
- package/dist/browser.mjs +2521 -159
- package/dist/chunk-26JGOELH.js +817 -0
- package/dist/chunk-75IQCUB2.mjs +817 -0
- package/dist/cli.js +2510 -122
- package/dist/edge-light.d.mts +1 -1
- package/dist/edge-light.d.ts +1 -1
- package/dist/edge-light.js +2521 -159
- package/dist/edge-light.mjs +2521 -159
- package/dist/index.d.mts +264 -47
- package/dist/index.d.ts +264 -47
- package/dist/index.js +3498 -1850
- package/dist/index.mjs +2635 -987
- package/dist/instrumentation/index.d.mts +7897 -48
- package/dist/instrumentation/index.d.ts +7897 -48
- package/dist/instrumentation/index.js +2408 -95
- package/dist/instrumentation/index.mjs +2407 -95
- package/dist/workerd.d.mts +1 -1
- package/dist/workerd.d.ts +1 -1
- package/dist/workerd.js +2521 -159
- package/dist/workerd.mjs +2521 -159
- package/package.json +23 -17
- package/util/dist/index.d.mts +3 -1
- package/util/dist/index.d.ts +3 -1
- package/util/dist/index.js +6 -0
- package/util/dist/index.mjs +6 -0
- package/dist/auto-instrumentations/chunk-G6ZWXGZB.mjs +0 -116
- package/dist/auto-instrumentations/plugin-Df3qKIl2.d.mts +0 -22
- package/dist/auto-instrumentations/plugin-Df3qKIl2.d.ts +0 -22
package/dist/browser.mjs
CHANGED
|
@@ -92,6 +92,7 @@ var iso = {
|
|
|
92
92
|
getRepoInfo: async (_settings) => void 0,
|
|
93
93
|
getPastNAncestors: async () => [],
|
|
94
94
|
getEnv: (_name) => void 0,
|
|
95
|
+
getBraintrustApiKey: async () => void 0,
|
|
95
96
|
getCallerLocation: () => void 0,
|
|
96
97
|
newAsyncLocalStorage: () => new DefaultAsyncLocalStorage(),
|
|
97
98
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -924,6 +925,11 @@ function isPromiseLike(value) {
|
|
|
924
925
|
|
|
925
926
|
// util/object_util.ts
|
|
926
927
|
var SET_UNION_FIELDS = /* @__PURE__ */ new Set(["tags"]);
|
|
928
|
+
var FORBIDDEN_MERGE_KEYS = /* @__PURE__ */ new Set([
|
|
929
|
+
"__proto__",
|
|
930
|
+
"constructor",
|
|
931
|
+
"prototype"
|
|
932
|
+
]);
|
|
927
933
|
function mergeDictsWithPaths({
|
|
928
934
|
mergeInto,
|
|
929
935
|
mergeFrom,
|
|
@@ -946,6 +952,7 @@ function mergeDictsWithPathsHelper({
|
|
|
946
952
|
mergePaths
|
|
947
953
|
}) {
|
|
948
954
|
Object.entries(mergeFrom).forEach(([k, mergeFromV]) => {
|
|
955
|
+
if (FORBIDDEN_MERGE_KEYS.has(k)) return;
|
|
949
956
|
const fullPath = path.concat([k]);
|
|
950
957
|
const fullPathSerialized = JSON.stringify(fullPath);
|
|
951
958
|
const mergeIntoV = recordFind(mergeInto, k);
|
|
@@ -5019,6 +5026,13 @@ var HTTPConnection = class _HTTPConnection {
|
|
|
5019
5026
|
debugLogger.debug(
|
|
5020
5027
|
`Retrying API request ${object_type} ${JSON.stringify(args)} ${e.status} ${e.text}`
|
|
5021
5028
|
);
|
|
5029
|
+
const sleepTimeS = HTTP_RETRY_BASE_SLEEP_TIME_S * 2 ** i;
|
|
5030
|
+
debugLogger.info(
|
|
5031
|
+
`Sleeping for ${sleepTimeS}s before retrying API request`
|
|
5032
|
+
);
|
|
5033
|
+
await new Promise(
|
|
5034
|
+
(resolve) => setTimeout(resolve, sleepTimeS * 1e3)
|
|
5035
|
+
);
|
|
5022
5036
|
continue;
|
|
5023
5037
|
}
|
|
5024
5038
|
throw e;
|
|
@@ -5420,6 +5434,19 @@ var JSONAttachment = class extends Attachment {
|
|
|
5420
5434
|
*/
|
|
5421
5435
|
constructor(data, options) {
|
|
5422
5436
|
const { filename = "data.json", pretty = false, state } = options ?? {};
|
|
5437
|
+
const deferredJsonAttachment = globalThis.__BT_DATASET_PIPELINE_DEFER_JSON_ATTACHMENT__;
|
|
5438
|
+
if (deferredJsonAttachment) {
|
|
5439
|
+
super({
|
|
5440
|
+
data: new Blob([]),
|
|
5441
|
+
filename,
|
|
5442
|
+
contentType: "application/json",
|
|
5443
|
+
state
|
|
5444
|
+
});
|
|
5445
|
+
return deferredJsonAttachment(data, {
|
|
5446
|
+
filename,
|
|
5447
|
+
pretty
|
|
5448
|
+
});
|
|
5449
|
+
}
|
|
5423
5450
|
const jsonString = pretty ? JSON.stringify(data, null, 2) : JSON.stringify(data);
|
|
5424
5451
|
const blob = new Blob([jsonString], { type: "application/json" });
|
|
5425
5452
|
super({
|
|
@@ -5668,20 +5695,7 @@ function startSpanParentArgs(args) {
|
|
|
5668
5695
|
`Mismatch between expected span parent object type ${args.parentObjectType} and provided type ${parentComponents.data.object_type}`
|
|
5669
5696
|
);
|
|
5670
5697
|
}
|
|
5671
|
-
|
|
5672
|
-
args.state,
|
|
5673
|
-
parentComponents
|
|
5674
|
-
);
|
|
5675
|
-
const computeParentObjectId = async () => {
|
|
5676
|
-
const parentComponentsObjectId = await parentComponentsObjectIdLambda();
|
|
5677
|
-
if (await args.parentObjectId.get() !== parentComponentsObjectId) {
|
|
5678
|
-
throw new Error(
|
|
5679
|
-
`Mismatch between expected span parent object id ${await args.parentObjectId.get()} and provided id ${parentComponentsObjectId}`
|
|
5680
|
-
);
|
|
5681
|
-
}
|
|
5682
|
-
return await args.parentObjectId.get();
|
|
5683
|
-
};
|
|
5684
|
-
argParentObjectId = new LazyValue(computeParentObjectId);
|
|
5698
|
+
argParentObjectId = args.parentObjectId;
|
|
5685
5699
|
if (parentComponents.data.row_id) {
|
|
5686
5700
|
argParentSpanIds = {
|
|
5687
5701
|
spanId: parentComponents.data.span_id,
|
|
@@ -6067,6 +6081,7 @@ var TestBackgroundLogger = class {
|
|
|
6067
6081
|
}
|
|
6068
6082
|
};
|
|
6069
6083
|
var BACKGROUND_LOGGER_BASE_SLEEP_TIME_S = 1;
|
|
6084
|
+
var HTTP_RETRY_BASE_SLEEP_TIME_S = 1;
|
|
6070
6085
|
var HTTPBackgroundLogger = class _HTTPBackgroundLogger {
|
|
6071
6086
|
apiConn;
|
|
6072
6087
|
queue;
|
|
@@ -6697,17 +6712,10 @@ function init(projectOrOptions, optionalOptions) {
|
|
|
6697
6712
|
if (repoInfo) {
|
|
6698
6713
|
return repoInfo;
|
|
6699
6714
|
}
|
|
6700
|
-
|
|
6701
|
-
|
|
6702
|
-
|
|
6703
|
-
|
|
6704
|
-
};
|
|
6705
|
-
if (gitMetadataSettings) {
|
|
6706
|
-
mergedGitMetadataSettings = mergeGitMetadataSettings(
|
|
6707
|
-
mergedGitMetadataSettings,
|
|
6708
|
-
gitMetadataSettings
|
|
6709
|
-
);
|
|
6710
|
-
}
|
|
6715
|
+
const mergedGitMetadataSettings = state.gitMetadataSettings == null ? gitMetadataSettings ?? { collect: "none" } : mergeGitMetadataSettings(
|
|
6716
|
+
state.gitMetadataSettings,
|
|
6717
|
+
gitMetadataSettings ?? { collect: "all" }
|
|
6718
|
+
);
|
|
6711
6719
|
return await isomorph_default.getRepoInfo(mergedGitMetadataSettings);
|
|
6712
6720
|
})();
|
|
6713
6721
|
if (repoInfoArg) {
|
|
@@ -7431,10 +7439,11 @@ async function login(options = {}) {
|
|
|
7431
7439
|
async function loginToState(options = {}) {
|
|
7432
7440
|
const {
|
|
7433
7441
|
appUrl = isomorph_default.getEnv("BRAINTRUST_APP_URL") || "https://www.braintrust.dev",
|
|
7434
|
-
apiKey
|
|
7442
|
+
apiKey: apiKeyArg,
|
|
7435
7443
|
orgName = isomorph_default.getEnv("BRAINTRUST_ORG_NAME"),
|
|
7436
7444
|
fetch: fetch2 = globalThis.fetch
|
|
7437
7445
|
} = options || {};
|
|
7446
|
+
const apiKey = apiKeyArg !== void 0 ? apiKeyArg : await isomorph_default.getBraintrustApiKey();
|
|
7438
7447
|
const appPublicUrl = isomorph_default.getEnv("BRAINTRUST_APP_PUBLIC_URL") || appUrl;
|
|
7439
7448
|
const state = new BraintrustState(options);
|
|
7440
7449
|
state.resetLoginInfo();
|
|
@@ -8675,9 +8684,15 @@ var SpanImpl = class _SpanImpl {
|
|
|
8675
8684
|
const cachedSpan = {
|
|
8676
8685
|
input: partialRecord.input,
|
|
8677
8686
|
output: partialRecord.output,
|
|
8687
|
+
expected: partialRecord.expected,
|
|
8688
|
+
error: partialRecord.error,
|
|
8689
|
+
scores: partialRecord.scores,
|
|
8690
|
+
metrics: partialRecord.metrics,
|
|
8678
8691
|
metadata: partialRecord.metadata,
|
|
8692
|
+
tags: partialRecord.tags,
|
|
8679
8693
|
span_id: this._spanId,
|
|
8680
8694
|
span_parents: this._spanParents,
|
|
8695
|
+
is_root: this._spanId === this._rootSpanId,
|
|
8681
8696
|
span_attributes: partialRecord.span_attributes
|
|
8682
8697
|
};
|
|
8683
8698
|
this._state.spanCache.queueWrite(
|
|
@@ -9013,6 +9028,7 @@ var Dataset2 = class extends ObjectFetcher {
|
|
|
9013
9028
|
metadata,
|
|
9014
9029
|
tags,
|
|
9015
9030
|
output,
|
|
9031
|
+
origin,
|
|
9016
9032
|
isMerge
|
|
9017
9033
|
}) {
|
|
9018
9034
|
return new LazyValue(async () => {
|
|
@@ -9027,6 +9043,7 @@ var Dataset2 = class extends ObjectFetcher {
|
|
|
9027
9043
|
created: !isMerge ? (/* @__PURE__ */ new Date()).toISOString() : void 0,
|
|
9028
9044
|
//if we're merging/updating an event we will not add this ts
|
|
9029
9045
|
metadata,
|
|
9046
|
+
origin,
|
|
9030
9047
|
...!!isMerge ? {
|
|
9031
9048
|
[IS_MERGE_FIELD]: true
|
|
9032
9049
|
} : {}
|
|
@@ -9046,6 +9063,7 @@ var Dataset2 = class extends ObjectFetcher {
|
|
|
9046
9063
|
* about anything else that's relevant, that you can use to help find and analyze examples later. For example, you could log the
|
|
9047
9064
|
* `prompt`, example's `id`, or anything else that would be useful to slice/dice later. The values in `metadata` can be any
|
|
9048
9065
|
* JSON-serializable type, but its keys must be strings.
|
|
9066
|
+
* @param event.origin (Optional) a reference to the source object this dataset record was derived from.
|
|
9049
9067
|
* @param event.id (Optional) a unique identifier for the event. If you don't provide one, Braintrust will generate one for you.
|
|
9050
9068
|
* @param event.output: (Deprecated) The output of your application. Use `expected` instead.
|
|
9051
9069
|
* @returns The `id` of the logged record.
|
|
@@ -9056,7 +9074,8 @@ var Dataset2 = class extends ObjectFetcher {
|
|
|
9056
9074
|
metadata,
|
|
9057
9075
|
tags,
|
|
9058
9076
|
id,
|
|
9059
|
-
output
|
|
9077
|
+
output,
|
|
9078
|
+
origin
|
|
9060
9079
|
}) {
|
|
9061
9080
|
this.validateEvent({ metadata, expected, output, tags });
|
|
9062
9081
|
const rowId = id || uuidv42();
|
|
@@ -9068,6 +9087,7 @@ var Dataset2 = class extends ObjectFetcher {
|
|
|
9068
9087
|
metadata,
|
|
9069
9088
|
tags,
|
|
9070
9089
|
output,
|
|
9090
|
+
origin,
|
|
9071
9091
|
isMerge: false
|
|
9072
9092
|
})
|
|
9073
9093
|
);
|
|
@@ -13403,11 +13423,11 @@ function resolveDenyOutputPaths(event, defaultDenyOutputPaths) {
|
|
|
13403
13423
|
if (Array.isArray(event?.denyOutputPaths)) {
|
|
13404
13424
|
return event.denyOutputPaths;
|
|
13405
13425
|
}
|
|
13406
|
-
const
|
|
13407
|
-
if (!
|
|
13426
|
+
const firstArgument2 = event?.arguments && event.arguments.length > 0 ? event.arguments[0] : void 0;
|
|
13427
|
+
if (!firstArgument2 || typeof firstArgument2 !== "object") {
|
|
13408
13428
|
return defaultDenyOutputPaths;
|
|
13409
13429
|
}
|
|
13410
|
-
const runtimeDenyOutputPaths =
|
|
13430
|
+
const runtimeDenyOutputPaths = firstArgument2[RUNTIME_DENY_OUTPUT_PATHS];
|
|
13411
13431
|
if (Array.isArray(runtimeDenyOutputPaths) && runtimeDenyOutputPaths.every((path) => typeof path === "string")) {
|
|
13412
13432
|
return runtimeDenyOutputPaths;
|
|
13413
13433
|
}
|
|
@@ -17066,6 +17086,467 @@ function cleanMetrics2(metrics) {
|
|
|
17066
17086
|
return cleaned;
|
|
17067
17087
|
}
|
|
17068
17088
|
|
|
17089
|
+
// src/instrumentation/plugins/openai-agents-channels.ts
|
|
17090
|
+
var openAIAgentsCoreChannels = defineChannels("@openai/agents-core", {
|
|
17091
|
+
onTraceStart: channel({
|
|
17092
|
+
channelName: "tracing.processor.onTraceStart",
|
|
17093
|
+
kind: "async"
|
|
17094
|
+
}),
|
|
17095
|
+
onTraceEnd: channel({
|
|
17096
|
+
channelName: "tracing.processor.onTraceEnd",
|
|
17097
|
+
kind: "async"
|
|
17098
|
+
}),
|
|
17099
|
+
onSpanStart: channel({
|
|
17100
|
+
channelName: "tracing.processor.onSpanStart",
|
|
17101
|
+
kind: "async"
|
|
17102
|
+
}),
|
|
17103
|
+
onSpanEnd: channel({
|
|
17104
|
+
channelName: "tracing.processor.onSpanEnd",
|
|
17105
|
+
kind: "async"
|
|
17106
|
+
})
|
|
17107
|
+
});
|
|
17108
|
+
|
|
17109
|
+
// src/instrumentation/plugins/openai-agents-trace-processor.ts
|
|
17110
|
+
function isSpanData(spanData, type) {
|
|
17111
|
+
return spanData.type === type;
|
|
17112
|
+
}
|
|
17113
|
+
function spanTypeFromAgents(span) {
|
|
17114
|
+
const spanType = span.spanData.type;
|
|
17115
|
+
if (spanType === "function" || spanType === "guardrail" || spanType === "mcp_tools") {
|
|
17116
|
+
return "tool" /* TOOL */;
|
|
17117
|
+
}
|
|
17118
|
+
if (spanType === "generation" || spanType === "response" || spanType === "transcription" || spanType === "speech") {
|
|
17119
|
+
return "llm" /* LLM */;
|
|
17120
|
+
}
|
|
17121
|
+
return "task" /* TASK */;
|
|
17122
|
+
}
|
|
17123
|
+
function spanNameFromAgents(span) {
|
|
17124
|
+
const spanData = span.spanData;
|
|
17125
|
+
if ("name" in spanData && spanData.name) {
|
|
17126
|
+
return spanData.name;
|
|
17127
|
+
}
|
|
17128
|
+
switch (spanData.type) {
|
|
17129
|
+
case "generation":
|
|
17130
|
+
return "Generation";
|
|
17131
|
+
case "response":
|
|
17132
|
+
return "Response";
|
|
17133
|
+
case "handoff":
|
|
17134
|
+
return "Handoff";
|
|
17135
|
+
case "mcp_tools":
|
|
17136
|
+
return isSpanData(spanData, "mcp_tools") && spanData.server ? `List Tools (${spanData.server})` : "MCP List Tools";
|
|
17137
|
+
case "transcription":
|
|
17138
|
+
return "Transcription";
|
|
17139
|
+
case "speech":
|
|
17140
|
+
return "Speech";
|
|
17141
|
+
case "speech_group":
|
|
17142
|
+
return "Speech Group";
|
|
17143
|
+
default:
|
|
17144
|
+
return "Unknown";
|
|
17145
|
+
}
|
|
17146
|
+
}
|
|
17147
|
+
function getTimeElapsed(end, start) {
|
|
17148
|
+
if (!start || !end) {
|
|
17149
|
+
return void 0;
|
|
17150
|
+
}
|
|
17151
|
+
const startTime = new Date(start).getTime();
|
|
17152
|
+
const endTime = new Date(end).getTime();
|
|
17153
|
+
if (Number.isNaN(startTime) || Number.isNaN(endTime)) {
|
|
17154
|
+
return void 0;
|
|
17155
|
+
}
|
|
17156
|
+
return (endTime - startTime) / 1e3;
|
|
17157
|
+
}
|
|
17158
|
+
function getNumberProperty2(obj, key) {
|
|
17159
|
+
if (!isObject(obj) || !(key in obj)) {
|
|
17160
|
+
return void 0;
|
|
17161
|
+
}
|
|
17162
|
+
const value = obj[key];
|
|
17163
|
+
return typeof value === "number" ? value : void 0;
|
|
17164
|
+
}
|
|
17165
|
+
function parseUsageMetrics(usage) {
|
|
17166
|
+
const metrics = {};
|
|
17167
|
+
if (!isObject(usage)) {
|
|
17168
|
+
return metrics;
|
|
17169
|
+
}
|
|
17170
|
+
const promptTokens = getNumberProperty2(usage, "prompt_tokens") ?? getNumberProperty2(usage, "input_tokens") ?? getNumberProperty2(usage, "promptTokens") ?? getNumberProperty2(usage, "inputTokens");
|
|
17171
|
+
const completionTokens = getNumberProperty2(usage, "completion_tokens") ?? getNumberProperty2(usage, "output_tokens") ?? getNumberProperty2(usage, "completionTokens") ?? getNumberProperty2(usage, "outputTokens");
|
|
17172
|
+
const totalTokens = getNumberProperty2(usage, "total_tokens") ?? getNumberProperty2(usage, "totalTokens");
|
|
17173
|
+
if (promptTokens !== void 0) {
|
|
17174
|
+
metrics.prompt_tokens = promptTokens;
|
|
17175
|
+
}
|
|
17176
|
+
if (completionTokens !== void 0) {
|
|
17177
|
+
metrics.completion_tokens = completionTokens;
|
|
17178
|
+
}
|
|
17179
|
+
if (totalTokens !== void 0) {
|
|
17180
|
+
metrics.tokens = totalTokens;
|
|
17181
|
+
} else if (promptTokens !== void 0 && completionTokens !== void 0) {
|
|
17182
|
+
metrics.tokens = promptTokens + completionTokens;
|
|
17183
|
+
}
|
|
17184
|
+
const inputDetails = usage.input_tokens_details;
|
|
17185
|
+
const cachedTokens = getNumberProperty2(inputDetails, "cached_tokens");
|
|
17186
|
+
const cacheWriteTokens = getNumberProperty2(
|
|
17187
|
+
inputDetails,
|
|
17188
|
+
"cache_write_tokens"
|
|
17189
|
+
);
|
|
17190
|
+
if (cachedTokens !== void 0) {
|
|
17191
|
+
metrics.prompt_cached_tokens = cachedTokens;
|
|
17192
|
+
}
|
|
17193
|
+
if (cacheWriteTokens !== void 0) {
|
|
17194
|
+
metrics.prompt_cache_creation_tokens = cacheWriteTokens;
|
|
17195
|
+
}
|
|
17196
|
+
return metrics;
|
|
17197
|
+
}
|
|
17198
|
+
var OpenAIAgentsTraceProcessor = class _OpenAIAgentsTraceProcessor {
|
|
17199
|
+
static DEFAULT_MAX_TRACES = 1e4;
|
|
17200
|
+
logger;
|
|
17201
|
+
maxTraces;
|
|
17202
|
+
traceSpans = /* @__PURE__ */ new Map();
|
|
17203
|
+
traceOrder = [];
|
|
17204
|
+
_traceSpans = this.traceSpans;
|
|
17205
|
+
constructor(options = {}) {
|
|
17206
|
+
this.logger = options.logger;
|
|
17207
|
+
this.maxTraces = options.maxTraces ?? _OpenAIAgentsTraceProcessor.DEFAULT_MAX_TRACES;
|
|
17208
|
+
}
|
|
17209
|
+
evictOldestTrace() {
|
|
17210
|
+
const oldestTraceId = this.traceOrder.shift();
|
|
17211
|
+
if (oldestTraceId) {
|
|
17212
|
+
this.traceSpans.delete(oldestTraceId);
|
|
17213
|
+
}
|
|
17214
|
+
}
|
|
17215
|
+
onTraceStart(trace) {
|
|
17216
|
+
if (!trace?.traceId) {
|
|
17217
|
+
return Promise.resolve();
|
|
17218
|
+
}
|
|
17219
|
+
if (this.traceOrder.length >= this.maxTraces) {
|
|
17220
|
+
this.evictOldestTrace();
|
|
17221
|
+
}
|
|
17222
|
+
const current = currentSpan();
|
|
17223
|
+
const span = current && current !== NOOP_SPAN ? current.startSpan({
|
|
17224
|
+
name: trace.name,
|
|
17225
|
+
type: "task" /* TASK */
|
|
17226
|
+
}) : this.logger ? this.logger.startSpan({
|
|
17227
|
+
name: trace.name,
|
|
17228
|
+
type: "task" /* TASK */
|
|
17229
|
+
}) : startSpan({
|
|
17230
|
+
name: trace.name,
|
|
17231
|
+
type: "task" /* TASK */
|
|
17232
|
+
});
|
|
17233
|
+
span.log({
|
|
17234
|
+
input: "Agent workflow started",
|
|
17235
|
+
metadata: {
|
|
17236
|
+
group_id: trace.groupId,
|
|
17237
|
+
...trace.metadata || {}
|
|
17238
|
+
}
|
|
17239
|
+
});
|
|
17240
|
+
this.traceSpans.set(trace.traceId, {
|
|
17241
|
+
rootSpan: span,
|
|
17242
|
+
childSpans: /* @__PURE__ */ new Map(),
|
|
17243
|
+
metadata: {
|
|
17244
|
+
firstInput: null,
|
|
17245
|
+
lastOutput: null
|
|
17246
|
+
}
|
|
17247
|
+
});
|
|
17248
|
+
this.traceOrder.push(trace.traceId);
|
|
17249
|
+
return Promise.resolve();
|
|
17250
|
+
}
|
|
17251
|
+
async onTraceEnd(trace) {
|
|
17252
|
+
const traceData = this.traceSpans.get(trace?.traceId);
|
|
17253
|
+
if (!traceData) {
|
|
17254
|
+
return;
|
|
17255
|
+
}
|
|
17256
|
+
try {
|
|
17257
|
+
traceData.rootSpan.log({
|
|
17258
|
+
input: traceData.metadata.firstInput,
|
|
17259
|
+
output: traceData.metadata.lastOutput
|
|
17260
|
+
});
|
|
17261
|
+
traceData.rootSpan.end();
|
|
17262
|
+
await traceData.rootSpan.flush();
|
|
17263
|
+
} finally {
|
|
17264
|
+
this.traceSpans.delete(trace.traceId);
|
|
17265
|
+
const orderIndex = this.traceOrder.indexOf(trace.traceId);
|
|
17266
|
+
if (orderIndex > -1) {
|
|
17267
|
+
this.traceOrder.splice(orderIndex, 1);
|
|
17268
|
+
}
|
|
17269
|
+
}
|
|
17270
|
+
}
|
|
17271
|
+
onSpanStart(span) {
|
|
17272
|
+
if (!span?.spanId || !span.traceId) {
|
|
17273
|
+
return Promise.resolve();
|
|
17274
|
+
}
|
|
17275
|
+
const traceData = this.traceSpans.get(span.traceId);
|
|
17276
|
+
if (!traceData) {
|
|
17277
|
+
return Promise.resolve();
|
|
17278
|
+
}
|
|
17279
|
+
const parentSpan = span.parentId ? traceData.childSpans.get(span.parentId) : traceData.rootSpan;
|
|
17280
|
+
if (!parentSpan) {
|
|
17281
|
+
return Promise.resolve();
|
|
17282
|
+
}
|
|
17283
|
+
const childSpan = parentSpan.startSpan({
|
|
17284
|
+
name: spanNameFromAgents(span),
|
|
17285
|
+
type: spanTypeFromAgents(span)
|
|
17286
|
+
});
|
|
17287
|
+
traceData.childSpans.set(span.spanId, childSpan);
|
|
17288
|
+
return Promise.resolve();
|
|
17289
|
+
}
|
|
17290
|
+
onSpanEnd(span) {
|
|
17291
|
+
if (!span?.spanId || !span.traceId) {
|
|
17292
|
+
return Promise.resolve();
|
|
17293
|
+
}
|
|
17294
|
+
const traceData = this.traceSpans.get(span.traceId);
|
|
17295
|
+
if (!traceData) {
|
|
17296
|
+
return Promise.resolve();
|
|
17297
|
+
}
|
|
17298
|
+
const braintrustSpan = traceData.childSpans.get(span.spanId);
|
|
17299
|
+
if (!braintrustSpan) {
|
|
17300
|
+
return Promise.resolve();
|
|
17301
|
+
}
|
|
17302
|
+
const logData = this.extractLogData(span);
|
|
17303
|
+
braintrustSpan.log({
|
|
17304
|
+
error: span.error,
|
|
17305
|
+
...logData
|
|
17306
|
+
});
|
|
17307
|
+
braintrustSpan.end();
|
|
17308
|
+
traceData.childSpans.delete(span.spanId);
|
|
17309
|
+
const input = logData.input;
|
|
17310
|
+
const output = logData.output;
|
|
17311
|
+
if (traceData.metadata.firstInput === null && input != null) {
|
|
17312
|
+
traceData.metadata.firstInput = input;
|
|
17313
|
+
}
|
|
17314
|
+
if (output != null) {
|
|
17315
|
+
traceData.metadata.lastOutput = output;
|
|
17316
|
+
}
|
|
17317
|
+
return Promise.resolve();
|
|
17318
|
+
}
|
|
17319
|
+
async shutdown() {
|
|
17320
|
+
if (this.logger && typeof this.logger.flush === "function") {
|
|
17321
|
+
await this.logger.flush();
|
|
17322
|
+
}
|
|
17323
|
+
}
|
|
17324
|
+
async forceFlush() {
|
|
17325
|
+
if (this.logger && typeof this.logger.flush === "function") {
|
|
17326
|
+
await this.logger.flush();
|
|
17327
|
+
}
|
|
17328
|
+
}
|
|
17329
|
+
extractLogData(span) {
|
|
17330
|
+
const spanData = span.spanData;
|
|
17331
|
+
switch (spanData.type) {
|
|
17332
|
+
case "agent":
|
|
17333
|
+
return this.extractAgentLogData(spanData);
|
|
17334
|
+
case "response":
|
|
17335
|
+
return this.extractResponseLogData(spanData, span);
|
|
17336
|
+
case "function":
|
|
17337
|
+
return this.extractFunctionLogData(spanData);
|
|
17338
|
+
case "handoff":
|
|
17339
|
+
return this.extractHandoffLogData(spanData);
|
|
17340
|
+
case "guardrail":
|
|
17341
|
+
return this.extractGuardrailLogData(spanData);
|
|
17342
|
+
case "generation":
|
|
17343
|
+
return this.extractGenerationLogData(spanData, span);
|
|
17344
|
+
case "custom":
|
|
17345
|
+
return this.extractCustomLogData(spanData);
|
|
17346
|
+
case "mcp_tools":
|
|
17347
|
+
return this.extractMCPListToolsLogData(spanData);
|
|
17348
|
+
case "transcription":
|
|
17349
|
+
return this.extractTranscriptionLogData(spanData);
|
|
17350
|
+
case "speech":
|
|
17351
|
+
return this.extractSpeechLogData(spanData);
|
|
17352
|
+
case "speech_group":
|
|
17353
|
+
return this.extractSpeechGroupLogData(spanData);
|
|
17354
|
+
default:
|
|
17355
|
+
return {};
|
|
17356
|
+
}
|
|
17357
|
+
}
|
|
17358
|
+
extractAgentLogData(spanData) {
|
|
17359
|
+
return {
|
|
17360
|
+
metadata: {
|
|
17361
|
+
tools: spanData.tools,
|
|
17362
|
+
handoffs: spanData.handoffs,
|
|
17363
|
+
output_type: spanData.output_type
|
|
17364
|
+
}
|
|
17365
|
+
};
|
|
17366
|
+
}
|
|
17367
|
+
extractResponseLogData(spanData, span) {
|
|
17368
|
+
const response = spanData._response;
|
|
17369
|
+
const output = isObject(response) ? response.output : void 0;
|
|
17370
|
+
const usage = isObject(response) ? response.usage : void 0;
|
|
17371
|
+
const metrics = {
|
|
17372
|
+
...this.extractTimingMetrics(span),
|
|
17373
|
+
...parseUsageMetrics(usage)
|
|
17374
|
+
};
|
|
17375
|
+
return {
|
|
17376
|
+
input: spanData._input,
|
|
17377
|
+
output,
|
|
17378
|
+
metadata: isObject(response) ? this.omitKeys(response, ["output", "usage"]) : {},
|
|
17379
|
+
metrics
|
|
17380
|
+
};
|
|
17381
|
+
}
|
|
17382
|
+
extractFunctionLogData(spanData) {
|
|
17383
|
+
return {
|
|
17384
|
+
input: spanData.input,
|
|
17385
|
+
output: spanData.output
|
|
17386
|
+
};
|
|
17387
|
+
}
|
|
17388
|
+
extractHandoffLogData(spanData) {
|
|
17389
|
+
return {
|
|
17390
|
+
metadata: {
|
|
17391
|
+
from_agent: spanData.from_agent,
|
|
17392
|
+
to_agent: spanData.to_agent
|
|
17393
|
+
}
|
|
17394
|
+
};
|
|
17395
|
+
}
|
|
17396
|
+
extractGuardrailLogData(spanData) {
|
|
17397
|
+
return {
|
|
17398
|
+
metadata: {
|
|
17399
|
+
triggered: spanData.triggered
|
|
17400
|
+
}
|
|
17401
|
+
};
|
|
17402
|
+
}
|
|
17403
|
+
extractGenerationLogData(spanData, span) {
|
|
17404
|
+
return {
|
|
17405
|
+
input: spanData.input,
|
|
17406
|
+
output: spanData.output,
|
|
17407
|
+
metadata: {
|
|
17408
|
+
model: spanData.model,
|
|
17409
|
+
model_config: spanData.model_config
|
|
17410
|
+
},
|
|
17411
|
+
metrics: {
|
|
17412
|
+
...this.extractTimingMetrics(span),
|
|
17413
|
+
...parseUsageMetrics(spanData.usage)
|
|
17414
|
+
}
|
|
17415
|
+
};
|
|
17416
|
+
}
|
|
17417
|
+
extractCustomLogData(spanData) {
|
|
17418
|
+
return spanData.data || {};
|
|
17419
|
+
}
|
|
17420
|
+
extractMCPListToolsLogData(spanData) {
|
|
17421
|
+
return {
|
|
17422
|
+
output: spanData.result,
|
|
17423
|
+
metadata: {
|
|
17424
|
+
server: spanData.server
|
|
17425
|
+
}
|
|
17426
|
+
};
|
|
17427
|
+
}
|
|
17428
|
+
extractTranscriptionLogData(spanData) {
|
|
17429
|
+
return {
|
|
17430
|
+
input: spanData.input,
|
|
17431
|
+
output: spanData.output,
|
|
17432
|
+
metadata: {
|
|
17433
|
+
model: spanData.model,
|
|
17434
|
+
model_config: spanData.model_config
|
|
17435
|
+
}
|
|
17436
|
+
};
|
|
17437
|
+
}
|
|
17438
|
+
extractSpeechLogData(spanData) {
|
|
17439
|
+
return {
|
|
17440
|
+
input: spanData.input,
|
|
17441
|
+
output: spanData.output,
|
|
17442
|
+
metadata: {
|
|
17443
|
+
model: spanData.model,
|
|
17444
|
+
model_config: spanData.model_config
|
|
17445
|
+
}
|
|
17446
|
+
};
|
|
17447
|
+
}
|
|
17448
|
+
extractSpeechGroupLogData(spanData) {
|
|
17449
|
+
return {
|
|
17450
|
+
input: spanData.input
|
|
17451
|
+
};
|
|
17452
|
+
}
|
|
17453
|
+
extractTimingMetrics(span) {
|
|
17454
|
+
const timeToFirstToken = getTimeElapsed(
|
|
17455
|
+
span.endedAt ?? void 0,
|
|
17456
|
+
span.startedAt ?? void 0
|
|
17457
|
+
);
|
|
17458
|
+
return timeToFirstToken === void 0 ? {} : { time_to_first_token: timeToFirstToken };
|
|
17459
|
+
}
|
|
17460
|
+
omitKeys(value, keys) {
|
|
17461
|
+
const result = {};
|
|
17462
|
+
for (const [key, fieldValue] of Object.entries(value)) {
|
|
17463
|
+
if (!keys.includes(key)) {
|
|
17464
|
+
result[key] = fieldValue;
|
|
17465
|
+
}
|
|
17466
|
+
}
|
|
17467
|
+
return result;
|
|
17468
|
+
}
|
|
17469
|
+
};
|
|
17470
|
+
|
|
17471
|
+
// src/instrumentation/plugins/openai-agents-plugin.ts
|
|
17472
|
+
function firstArgument(args) {
|
|
17473
|
+
if (Array.isArray(args)) {
|
|
17474
|
+
return args[0];
|
|
17475
|
+
}
|
|
17476
|
+
if (isObject(args) && "length" in args && typeof args.length === "number" && Number.isInteger(args.length) && args.length >= 0) {
|
|
17477
|
+
return Array.from(args)[0];
|
|
17478
|
+
}
|
|
17479
|
+
return void 0;
|
|
17480
|
+
}
|
|
17481
|
+
function isOpenAIAgentsTrace(value) {
|
|
17482
|
+
return isObject(value) && value.type === "trace" && typeof value.traceId === "string";
|
|
17483
|
+
}
|
|
17484
|
+
function isOpenAIAgentsSpan(value) {
|
|
17485
|
+
return isObject(value) && value.type === "trace.span" && typeof value.traceId === "string" && typeof value.spanId === "string";
|
|
17486
|
+
}
|
|
17487
|
+
var OpenAIAgentsPlugin = class extends BasePlugin {
|
|
17488
|
+
processor = new OpenAIAgentsTraceProcessor();
|
|
17489
|
+
onEnable() {
|
|
17490
|
+
this.subscribeToTraceLifecycle();
|
|
17491
|
+
}
|
|
17492
|
+
onDisable() {
|
|
17493
|
+
this.unsubscribers = unsubscribeAll(this.unsubscribers);
|
|
17494
|
+
void this.processor.shutdown();
|
|
17495
|
+
}
|
|
17496
|
+
subscribeToTraceLifecycle() {
|
|
17497
|
+
const traceStartChannel = openAIAgentsCoreChannels.onTraceStart.tracingChannel();
|
|
17498
|
+
const traceStartHandlers = {
|
|
17499
|
+
start: (event) => {
|
|
17500
|
+
const trace = firstArgument(event.arguments);
|
|
17501
|
+
if (isOpenAIAgentsTrace(trace)) {
|
|
17502
|
+
void this.processor.onTraceStart(trace);
|
|
17503
|
+
}
|
|
17504
|
+
}
|
|
17505
|
+
};
|
|
17506
|
+
traceStartChannel.subscribe(traceStartHandlers);
|
|
17507
|
+
this.unsubscribers.push(
|
|
17508
|
+
() => traceStartChannel.unsubscribe(traceStartHandlers)
|
|
17509
|
+
);
|
|
17510
|
+
const traceEndChannel = openAIAgentsCoreChannels.onTraceEnd.tracingChannel();
|
|
17511
|
+
const traceEndHandlers = {
|
|
17512
|
+
start: (event) => {
|
|
17513
|
+
const trace = firstArgument(event.arguments);
|
|
17514
|
+
if (isOpenAIAgentsTrace(trace)) {
|
|
17515
|
+
void this.processor.onTraceEnd(trace);
|
|
17516
|
+
}
|
|
17517
|
+
}
|
|
17518
|
+
};
|
|
17519
|
+
traceEndChannel.subscribe(traceEndHandlers);
|
|
17520
|
+
this.unsubscribers.push(
|
|
17521
|
+
() => traceEndChannel.unsubscribe(traceEndHandlers)
|
|
17522
|
+
);
|
|
17523
|
+
const spanStartChannel = openAIAgentsCoreChannels.onSpanStart.tracingChannel();
|
|
17524
|
+
const spanStartHandlers = {
|
|
17525
|
+
start: (event) => {
|
|
17526
|
+
const span = firstArgument(event.arguments);
|
|
17527
|
+
if (isOpenAIAgentsSpan(span)) {
|
|
17528
|
+
void this.processor.onSpanStart(span);
|
|
17529
|
+
}
|
|
17530
|
+
}
|
|
17531
|
+
};
|
|
17532
|
+
spanStartChannel.subscribe(spanStartHandlers);
|
|
17533
|
+
this.unsubscribers.push(
|
|
17534
|
+
() => spanStartChannel.unsubscribe(spanStartHandlers)
|
|
17535
|
+
);
|
|
17536
|
+
const spanEndChannel = openAIAgentsCoreChannels.onSpanEnd.tracingChannel();
|
|
17537
|
+
const spanEndHandlers = {
|
|
17538
|
+
start: (event) => {
|
|
17539
|
+
const span = firstArgument(event.arguments);
|
|
17540
|
+
if (isOpenAIAgentsSpan(span)) {
|
|
17541
|
+
void this.processor.onSpanEnd(span);
|
|
17542
|
+
}
|
|
17543
|
+
}
|
|
17544
|
+
};
|
|
17545
|
+
spanEndChannel.subscribe(spanEndHandlers);
|
|
17546
|
+
this.unsubscribers.push(() => spanEndChannel.unsubscribe(spanEndHandlers));
|
|
17547
|
+
}
|
|
17548
|
+
};
|
|
17549
|
+
|
|
17069
17550
|
// src/instrumentation/plugins/google-genai-channels.ts
|
|
17070
17551
|
var googleGenAIChannels = defineChannels("@google/genai", {
|
|
17071
17552
|
generateContent: channel({
|
|
@@ -23358,58 +23839,1794 @@ var GitHubCopilotPlugin = class extends BasePlugin {
|
|
|
23358
23839
|
}
|
|
23359
23840
|
};
|
|
23360
23841
|
|
|
23361
|
-
// src/instrumentation/
|
|
23362
|
-
|
|
23363
|
-
|
|
23842
|
+
// src/instrumentation/plugins/flue-channels.ts
|
|
23843
|
+
var flueChannels = defineChannels("@flue/runtime", {
|
|
23844
|
+
createContext: channel({
|
|
23845
|
+
channelName: "createFlueContext",
|
|
23846
|
+
kind: "sync-stream"
|
|
23847
|
+
}),
|
|
23848
|
+
openSession: channel({
|
|
23849
|
+
channelName: "Harness.openSession",
|
|
23850
|
+
kind: "async"
|
|
23851
|
+
}),
|
|
23852
|
+
contextEvent: channel({
|
|
23853
|
+
channelName: "context.event",
|
|
23854
|
+
kind: "sync-stream"
|
|
23855
|
+
}),
|
|
23856
|
+
prompt: channel({
|
|
23857
|
+
channelName: "session.prompt",
|
|
23858
|
+
kind: "async"
|
|
23859
|
+
}),
|
|
23860
|
+
skill: channel({
|
|
23861
|
+
channelName: "session.skill",
|
|
23862
|
+
kind: "async"
|
|
23863
|
+
}),
|
|
23864
|
+
task: channel({
|
|
23865
|
+
channelName: "session.task",
|
|
23866
|
+
kind: "async"
|
|
23867
|
+
}),
|
|
23868
|
+
compact: channel({
|
|
23869
|
+
channelName: "session.compact",
|
|
23870
|
+
kind: "async"
|
|
23871
|
+
})
|
|
23872
|
+
});
|
|
23873
|
+
|
|
23874
|
+
// src/wrappers/flue.ts
|
|
23875
|
+
var WRAPPED_FLUE_CONTEXT = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-context");
|
|
23876
|
+
var WRAPPED_FLUE_HARNESS = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-harness");
|
|
23877
|
+
var WRAPPED_FLUE_SESSION = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-session");
|
|
23878
|
+
var SUBSCRIBED_FLUE_CONTEXT_EVENTS = /* @__PURE__ */ Symbol.for(
|
|
23879
|
+
"braintrust.flue.subscribed-context-events"
|
|
23880
|
+
);
|
|
23881
|
+
function wrapFlueContext(ctx) {
|
|
23882
|
+
if (!isPlausibleFlueContext(ctx)) {
|
|
23883
|
+
console.warn("Unsupported Flue context. Not wrapping.");
|
|
23884
|
+
return ctx;
|
|
23885
|
+
}
|
|
23886
|
+
const context = ctx;
|
|
23887
|
+
subscribeFlueContextEvents(context, { captureTurnSpans: true });
|
|
23888
|
+
return patchFlueContextInPlace(context);
|
|
23364
23889
|
}
|
|
23365
|
-
|
|
23366
|
-
|
|
23367
|
-
|
|
23368
|
-
|
|
23369
|
-
anthropicPlugin = null;
|
|
23370
|
-
aiSDKPlugin = null;
|
|
23371
|
-
claudeAgentSDKPlugin = null;
|
|
23372
|
-
cursorSDKPlugin = null;
|
|
23373
|
-
googleGenAIPlugin = null;
|
|
23374
|
-
huggingFacePlugin = null;
|
|
23375
|
-
openRouterPlugin = null;
|
|
23376
|
-
openRouterAgentPlugin = null;
|
|
23377
|
-
mistralPlugin = null;
|
|
23378
|
-
googleADKPlugin = null;
|
|
23379
|
-
coherePlugin = null;
|
|
23380
|
-
groqPlugin = null;
|
|
23381
|
-
genkitPlugin = null;
|
|
23382
|
-
gitHubCopilotPlugin = null;
|
|
23383
|
-
constructor(config = {}) {
|
|
23384
|
-
super();
|
|
23385
|
-
this.config = config;
|
|
23890
|
+
function patchFlueContextInPlace(ctx) {
|
|
23891
|
+
const context = ctx;
|
|
23892
|
+
if (context[WRAPPED_FLUE_CONTEXT]) {
|
|
23893
|
+
return ctx;
|
|
23386
23894
|
}
|
|
23387
|
-
|
|
23388
|
-
|
|
23389
|
-
|
|
23390
|
-
|
|
23391
|
-
|
|
23392
|
-
|
|
23393
|
-
|
|
23394
|
-
|
|
23395
|
-
|
|
23396
|
-
|
|
23397
|
-
|
|
23398
|
-
|
|
23399
|
-
|
|
23400
|
-
|
|
23401
|
-
|
|
23402
|
-
|
|
23403
|
-
|
|
23404
|
-
|
|
23405
|
-
|
|
23406
|
-
|
|
23895
|
+
const originalInit = context.init.bind(context);
|
|
23896
|
+
try {
|
|
23897
|
+
Object.defineProperty(context, WRAPPED_FLUE_CONTEXT, {
|
|
23898
|
+
configurable: false,
|
|
23899
|
+
enumerable: false,
|
|
23900
|
+
value: true
|
|
23901
|
+
});
|
|
23902
|
+
Object.defineProperty(context, "init", {
|
|
23903
|
+
configurable: true,
|
|
23904
|
+
value: async function wrappedFlueInit(options) {
|
|
23905
|
+
const harness = await originalInit(options);
|
|
23906
|
+
return wrapFlueHarness(harness);
|
|
23907
|
+
},
|
|
23908
|
+
writable: true
|
|
23909
|
+
});
|
|
23910
|
+
} catch {
|
|
23911
|
+
}
|
|
23912
|
+
return ctx;
|
|
23913
|
+
}
|
|
23914
|
+
function wrapFlueSession(session) {
|
|
23915
|
+
if (!isPlausibleFlueSession(session)) {
|
|
23916
|
+
console.warn("Unsupported Flue session. Not wrapping.");
|
|
23917
|
+
return session;
|
|
23918
|
+
}
|
|
23919
|
+
return patchFlueSessionInPlace(session);
|
|
23920
|
+
}
|
|
23921
|
+
function subscribeFlueContextEvents(ctx, options = {}) {
|
|
23922
|
+
if (!ctx || typeof ctx !== "object" || typeof ctx.subscribeEvent !== "function") {
|
|
23923
|
+
return void 0;
|
|
23924
|
+
}
|
|
23925
|
+
const context = ctx;
|
|
23926
|
+
const captureTurnSpans = options.captureTurnSpans ?? true;
|
|
23927
|
+
const existingSubscription = context[SUBSCRIBED_FLUE_CONTEXT_EVENTS];
|
|
23928
|
+
if (existingSubscription) {
|
|
23929
|
+
if (existingSubscription.captureTurnSpans || !captureTurnSpans) {
|
|
23930
|
+
return void 0;
|
|
23931
|
+
}
|
|
23932
|
+
try {
|
|
23933
|
+
existingSubscription.unsubscribe();
|
|
23934
|
+
} catch {
|
|
23935
|
+
}
|
|
23936
|
+
}
|
|
23937
|
+
try {
|
|
23938
|
+
const unsubscribe = ctx.subscribeEvent((event) => {
|
|
23939
|
+
flueChannels.contextEvent.traceSync(() => void 0, {
|
|
23940
|
+
arguments: [event],
|
|
23941
|
+
captureTurnSpans,
|
|
23942
|
+
context: ctx
|
|
23943
|
+
});
|
|
23944
|
+
});
|
|
23945
|
+
if (existingSubscription) {
|
|
23946
|
+
existingSubscription.captureTurnSpans = captureTurnSpans;
|
|
23947
|
+
existingSubscription.unsubscribe = unsubscribe;
|
|
23948
|
+
} else {
|
|
23949
|
+
Object.defineProperty(context, SUBSCRIBED_FLUE_CONTEXT_EVENTS, {
|
|
23950
|
+
configurable: false,
|
|
23951
|
+
enumerable: false,
|
|
23952
|
+
value: {
|
|
23953
|
+
captureTurnSpans,
|
|
23954
|
+
unsubscribe
|
|
23955
|
+
}
|
|
23956
|
+
});
|
|
23957
|
+
}
|
|
23958
|
+
return unsubscribe;
|
|
23959
|
+
} catch {
|
|
23960
|
+
return void 0;
|
|
23961
|
+
}
|
|
23962
|
+
}
|
|
23963
|
+
function wrapFlueHarness(harness) {
|
|
23964
|
+
if (!isPlausibleFlueHarness(harness)) {
|
|
23965
|
+
return harness;
|
|
23966
|
+
}
|
|
23967
|
+
const target = harness;
|
|
23968
|
+
if (target[WRAPPED_FLUE_HARNESS]) {
|
|
23969
|
+
return harness;
|
|
23970
|
+
}
|
|
23971
|
+
const originalSession = target.session.bind(target);
|
|
23972
|
+
try {
|
|
23973
|
+
Object.defineProperty(target, WRAPPED_FLUE_HARNESS, {
|
|
23974
|
+
configurable: false,
|
|
23975
|
+
enumerable: false,
|
|
23976
|
+
value: true
|
|
23977
|
+
});
|
|
23978
|
+
Object.defineProperty(target, "session", {
|
|
23979
|
+
configurable: true,
|
|
23980
|
+
value: async function wrappedFlueHarnessSession(name, options) {
|
|
23981
|
+
const session = await originalSession(name, options);
|
|
23982
|
+
return patchFlueSessionInPlace(session);
|
|
23983
|
+
},
|
|
23984
|
+
writable: true
|
|
23985
|
+
});
|
|
23986
|
+
const sessions = target.sessions;
|
|
23987
|
+
if (sessions && typeof sessions === "object") {
|
|
23988
|
+
patchFlueSessionFactory(sessions, "get");
|
|
23989
|
+
patchFlueSessionFactory(sessions, "create");
|
|
23990
|
+
}
|
|
23991
|
+
} catch {
|
|
23992
|
+
}
|
|
23993
|
+
return harness;
|
|
23994
|
+
}
|
|
23995
|
+
function patchFlueSessionInPlace(session) {
|
|
23996
|
+
if (session[WRAPPED_FLUE_SESSION]) {
|
|
23997
|
+
return session;
|
|
23998
|
+
}
|
|
23999
|
+
try {
|
|
24000
|
+
Object.defineProperty(session, WRAPPED_FLUE_SESSION, {
|
|
24001
|
+
configurable: false,
|
|
24002
|
+
enumerable: false,
|
|
24003
|
+
value: true
|
|
24004
|
+
});
|
|
24005
|
+
patchCallHandleMethod(session, "prompt", flueChannels.prompt);
|
|
24006
|
+
patchCallHandleMethod(session, "skill", flueChannels.skill);
|
|
24007
|
+
patchCallHandleMethod(session, "task", flueChannels.task);
|
|
24008
|
+
patchCompact(session);
|
|
24009
|
+
} catch {
|
|
24010
|
+
}
|
|
24011
|
+
return session;
|
|
24012
|
+
}
|
|
24013
|
+
function patchFlueSessionFactory(sessions, method) {
|
|
24014
|
+
const original = sessions[method];
|
|
24015
|
+
if (typeof original !== "function") {
|
|
24016
|
+
return;
|
|
24017
|
+
}
|
|
24018
|
+
const bound = original.bind(sessions);
|
|
24019
|
+
Object.defineProperty(sessions, method, {
|
|
24020
|
+
configurable: true,
|
|
24021
|
+
value: async function wrappedFlueSessionFactory(name, options) {
|
|
24022
|
+
const session = await bound(name, options);
|
|
24023
|
+
return patchFlueSessionInPlace(session);
|
|
24024
|
+
},
|
|
24025
|
+
writable: true
|
|
24026
|
+
});
|
|
24027
|
+
}
|
|
24028
|
+
function patchCallHandleMethod(session, method, channel2) {
|
|
24029
|
+
const original = session[method];
|
|
24030
|
+
if (typeof original !== "function") {
|
|
24031
|
+
return;
|
|
24032
|
+
}
|
|
24033
|
+
const bound = original.bind(session);
|
|
24034
|
+
Object.defineProperty(session, method, {
|
|
24035
|
+
configurable: true,
|
|
24036
|
+
value(input, options) {
|
|
24037
|
+
const args = [input, options];
|
|
24038
|
+
const { originalResult, traced: traced2 } = traceFlueOperation(channel2, {
|
|
24039
|
+
context: {
|
|
24040
|
+
arguments: args,
|
|
24041
|
+
operation: method,
|
|
24042
|
+
session
|
|
24043
|
+
},
|
|
24044
|
+
run: () => bound(input, options)
|
|
24045
|
+
});
|
|
24046
|
+
return preserveCallHandle(originalResult, traced2);
|
|
24047
|
+
},
|
|
24048
|
+
writable: true
|
|
24049
|
+
});
|
|
24050
|
+
}
|
|
24051
|
+
function patchCompact(session) {
|
|
24052
|
+
const original = session.compact;
|
|
24053
|
+
if (typeof original !== "function") {
|
|
24054
|
+
return;
|
|
24055
|
+
}
|
|
24056
|
+
const bound = original.bind(session);
|
|
24057
|
+
Object.defineProperty(session, "compact", {
|
|
24058
|
+
configurable: true,
|
|
24059
|
+
value() {
|
|
24060
|
+
const context = {
|
|
24061
|
+
arguments: [],
|
|
24062
|
+
operation: "compact",
|
|
24063
|
+
session
|
|
24064
|
+
};
|
|
24065
|
+
return flueChannels.compact.tracePromise(() => bound(), context);
|
|
24066
|
+
},
|
|
24067
|
+
writable: true
|
|
24068
|
+
});
|
|
24069
|
+
}
|
|
24070
|
+
function traceFlueOperation(channel2, args) {
|
|
24071
|
+
const tracingChannel2 = channel2.tracingChannel();
|
|
24072
|
+
const context = args.context;
|
|
24073
|
+
let originalResult;
|
|
24074
|
+
let traced2;
|
|
24075
|
+
const run = () => {
|
|
24076
|
+
try {
|
|
24077
|
+
originalResult = args.run();
|
|
24078
|
+
tracingChannel2.end?.publish(context);
|
|
24079
|
+
} catch (error) {
|
|
24080
|
+
context.error = normalizeError3(error);
|
|
24081
|
+
tracingChannel2.error?.publish(context);
|
|
24082
|
+
tracingChannel2.end?.publish(context);
|
|
24083
|
+
throw error;
|
|
24084
|
+
}
|
|
24085
|
+
traced2 = Promise.resolve(originalResult).then(
|
|
24086
|
+
(result) => {
|
|
24087
|
+
context.result = result;
|
|
24088
|
+
tracingChannel2.asyncStart?.publish(context);
|
|
24089
|
+
tracingChannel2.asyncEnd?.publish(context);
|
|
24090
|
+
return result;
|
|
24091
|
+
},
|
|
24092
|
+
(error) => {
|
|
24093
|
+
context.error = normalizeError3(error);
|
|
24094
|
+
tracingChannel2.error?.publish(context);
|
|
24095
|
+
tracingChannel2.asyncStart?.publish(context);
|
|
24096
|
+
tracingChannel2.asyncEnd?.publish(context);
|
|
24097
|
+
throw error;
|
|
24098
|
+
}
|
|
24099
|
+
);
|
|
24100
|
+
};
|
|
24101
|
+
if (tracingChannel2.start?.runStores) {
|
|
24102
|
+
tracingChannel2.start.runStores(context, run);
|
|
24103
|
+
} else {
|
|
24104
|
+
tracingChannel2.start?.publish(context);
|
|
24105
|
+
run();
|
|
24106
|
+
}
|
|
24107
|
+
return { originalResult, traced: traced2 };
|
|
24108
|
+
}
|
|
24109
|
+
function normalizeError3(error) {
|
|
24110
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
24111
|
+
}
|
|
24112
|
+
function preserveCallHandle(originalHandle, traced2) {
|
|
24113
|
+
if (!isFlueCallHandle(originalHandle)) {
|
|
24114
|
+
return traced2;
|
|
24115
|
+
}
|
|
24116
|
+
const handle = originalHandle;
|
|
24117
|
+
const wrapped = {
|
|
24118
|
+
get signal() {
|
|
24119
|
+
return handle.signal;
|
|
24120
|
+
},
|
|
24121
|
+
abort(reason) {
|
|
24122
|
+
return handle.abort(reason);
|
|
24123
|
+
},
|
|
24124
|
+
then(onfulfilled, onrejected) {
|
|
24125
|
+
return traced2.then(onfulfilled, onrejected);
|
|
24126
|
+
}
|
|
24127
|
+
};
|
|
24128
|
+
return wrapped;
|
|
24129
|
+
}
|
|
24130
|
+
function isPlausibleFlueContext(value) {
|
|
24131
|
+
return !!value && typeof value === "object" && typeof value.init === "function";
|
|
24132
|
+
}
|
|
24133
|
+
function isPlausibleFlueHarness(value) {
|
|
24134
|
+
return !!value && typeof value === "object" && typeof value.session === "function";
|
|
24135
|
+
}
|
|
24136
|
+
function isPlausibleFlueSession(value) {
|
|
24137
|
+
return !!value && typeof value === "object" && typeof value.prompt === "function" && typeof value.skill === "function" && typeof value.task === "function" && typeof value.compact === "function";
|
|
24138
|
+
}
|
|
24139
|
+
function isFlueCallHandle(value) {
|
|
24140
|
+
return !!value && typeof value === "object" && typeof value.then === "function" && typeof value.abort === "function" && "signal" in value;
|
|
24141
|
+
}
|
|
24142
|
+
|
|
24143
|
+
// src/instrumentation/plugins/flue-plugin.ts
|
|
24144
|
+
var FluePlugin = class extends BasePlugin {
|
|
24145
|
+
activeOperationsById = /* @__PURE__ */ new Map();
|
|
24146
|
+
activeOperationsByScope = /* @__PURE__ */ new Map();
|
|
24147
|
+
compactionsByScope = /* @__PURE__ */ new Map();
|
|
24148
|
+
pendingOperationsByKey = /* @__PURE__ */ new Map();
|
|
24149
|
+
tasksById = /* @__PURE__ */ new Map();
|
|
24150
|
+
toolsById = /* @__PURE__ */ new Map();
|
|
24151
|
+
turnsByScope = /* @__PURE__ */ new Map();
|
|
24152
|
+
onEnable() {
|
|
24153
|
+
this.subscribeToContextCreation();
|
|
24154
|
+
this.subscribeToSessionCreation();
|
|
24155
|
+
this.subscribeToContextEvents();
|
|
24156
|
+
this.subscribeToSessionOperations();
|
|
24157
|
+
}
|
|
24158
|
+
onDisable() {
|
|
24159
|
+
for (const unsubscribe of this.unsubscribers) {
|
|
24160
|
+
unsubscribe();
|
|
24161
|
+
}
|
|
24162
|
+
this.unsubscribers = [];
|
|
24163
|
+
this.activeOperationsById.clear();
|
|
24164
|
+
this.activeOperationsByScope.clear();
|
|
24165
|
+
this.compactionsByScope.clear();
|
|
24166
|
+
this.pendingOperationsByKey.clear();
|
|
24167
|
+
this.tasksById.clear();
|
|
24168
|
+
this.toolsById.clear();
|
|
24169
|
+
this.turnsByScope.clear();
|
|
24170
|
+
}
|
|
24171
|
+
subscribeToContextCreation() {
|
|
24172
|
+
const channel2 = flueChannels.createContext.tracingChannel();
|
|
24173
|
+
const handlers = {
|
|
24174
|
+
end: (event) => {
|
|
24175
|
+
const ctx = event.result;
|
|
24176
|
+
if (!ctx) {
|
|
24177
|
+
return;
|
|
24178
|
+
}
|
|
24179
|
+
subscribeFlueContextEvents(ctx, { captureTurnSpans: false });
|
|
24180
|
+
patchFlueContextInPlace(ctx);
|
|
24181
|
+
},
|
|
24182
|
+
error: () => {
|
|
24183
|
+
}
|
|
24184
|
+
};
|
|
24185
|
+
channel2.subscribe(handlers);
|
|
24186
|
+
this.unsubscribers.push(() => {
|
|
24187
|
+
channel2.unsubscribe(handlers);
|
|
24188
|
+
});
|
|
24189
|
+
}
|
|
24190
|
+
subscribeToSessionCreation() {
|
|
24191
|
+
const channel2 = flueChannels.openSession.tracingChannel();
|
|
24192
|
+
const handlers = {
|
|
24193
|
+
asyncEnd: (event) => {
|
|
24194
|
+
if (event.result) {
|
|
24195
|
+
patchFlueSessionInPlace(
|
|
24196
|
+
event.result
|
|
24197
|
+
);
|
|
24198
|
+
}
|
|
24199
|
+
if (event.harness) {
|
|
24200
|
+
wrapFlueHarness(event.harness);
|
|
24201
|
+
}
|
|
24202
|
+
},
|
|
24203
|
+
error: () => {
|
|
24204
|
+
}
|
|
24205
|
+
};
|
|
24206
|
+
channel2.subscribe(handlers);
|
|
24207
|
+
this.unsubscribers.push(() => {
|
|
24208
|
+
channel2.unsubscribe(handlers);
|
|
24209
|
+
});
|
|
24210
|
+
}
|
|
24211
|
+
subscribeToSessionOperations() {
|
|
24212
|
+
this.subscribeToSessionOperation(flueChannels.prompt);
|
|
24213
|
+
this.subscribeToSessionOperation(flueChannels.skill);
|
|
24214
|
+
this.subscribeToSessionOperation(flueChannels.task);
|
|
24215
|
+
this.subscribeToCompact();
|
|
24216
|
+
}
|
|
24217
|
+
subscribeToSessionOperation(channel2) {
|
|
24218
|
+
const tracingChannel2 = channel2.tracingChannel();
|
|
24219
|
+
const states = /* @__PURE__ */ new WeakMap();
|
|
24220
|
+
const ensureState2 = (event) => {
|
|
24221
|
+
const existing = states.get(event);
|
|
24222
|
+
if (existing) {
|
|
24223
|
+
return existing;
|
|
24224
|
+
}
|
|
24225
|
+
const state = this.startOperationState({
|
|
24226
|
+
args: event.arguments,
|
|
24227
|
+
moduleVersion: typeof event.moduleVersion === "string" ? event.moduleVersion : void 0,
|
|
24228
|
+
operation: event.operation,
|
|
24229
|
+
session: event.session
|
|
24230
|
+
});
|
|
24231
|
+
states.set(event, state);
|
|
24232
|
+
return state;
|
|
24233
|
+
};
|
|
24234
|
+
const unbindCurrentSpanStore = this.bindCurrentSpanStoreToOperationStart(
|
|
24235
|
+
tracingChannel2,
|
|
24236
|
+
ensureState2
|
|
24237
|
+
);
|
|
24238
|
+
const handlers = {
|
|
24239
|
+
start: (event) => {
|
|
24240
|
+
ensureState2(event);
|
|
24241
|
+
},
|
|
24242
|
+
asyncEnd: (event) => {
|
|
24243
|
+
this.endOperationState(states.get(event), event.result);
|
|
24244
|
+
states.delete(event);
|
|
24245
|
+
},
|
|
24246
|
+
error: (event) => {
|
|
24247
|
+
const state = states.get(event);
|
|
24248
|
+
if (state && event.error) {
|
|
24249
|
+
safeLog3(state.span, { error: errorToString(event.error) });
|
|
24250
|
+
this.finishOperationState(state);
|
|
24251
|
+
}
|
|
24252
|
+
states.delete(event);
|
|
24253
|
+
}
|
|
24254
|
+
};
|
|
24255
|
+
tracingChannel2.subscribe(handlers);
|
|
24256
|
+
this.unsubscribers.push(() => {
|
|
24257
|
+
unbindCurrentSpanStore?.();
|
|
24258
|
+
tracingChannel2.unsubscribe(handlers);
|
|
24259
|
+
});
|
|
24260
|
+
}
|
|
24261
|
+
subscribeToCompact() {
|
|
24262
|
+
const tracingChannel2 = flueChannels.compact.tracingChannel();
|
|
24263
|
+
const states = /* @__PURE__ */ new WeakMap();
|
|
24264
|
+
const ensureState2 = (event) => {
|
|
24265
|
+
const existing = states.get(event);
|
|
24266
|
+
if (existing) {
|
|
24267
|
+
return existing;
|
|
24268
|
+
}
|
|
24269
|
+
const state = this.startOperationState({
|
|
24270
|
+
args: [],
|
|
24271
|
+
moduleVersion: typeof event.moduleVersion === "string" ? event.moduleVersion : void 0,
|
|
24272
|
+
operation: event.operation,
|
|
24273
|
+
session: event.session
|
|
24274
|
+
});
|
|
24275
|
+
states.set(event, state);
|
|
24276
|
+
return state;
|
|
24277
|
+
};
|
|
24278
|
+
const unbindCurrentSpanStore = this.bindCurrentSpanStoreToOperationStart(
|
|
24279
|
+
tracingChannel2,
|
|
24280
|
+
ensureState2
|
|
24281
|
+
);
|
|
24282
|
+
const handlers = {
|
|
24283
|
+
start: (event) => {
|
|
24284
|
+
ensureState2(event);
|
|
24285
|
+
},
|
|
24286
|
+
asyncEnd: (event) => {
|
|
24287
|
+
this.endOperationState(states.get(event), void 0);
|
|
24288
|
+
states.delete(event);
|
|
24289
|
+
},
|
|
24290
|
+
error: (event) => {
|
|
24291
|
+
const state = states.get(event);
|
|
24292
|
+
if (state && event.error) {
|
|
24293
|
+
safeLog3(state.span, { error: errorToString(event.error) });
|
|
24294
|
+
this.finishOperationState(state);
|
|
24295
|
+
}
|
|
24296
|
+
states.delete(event);
|
|
24297
|
+
}
|
|
24298
|
+
};
|
|
24299
|
+
tracingChannel2.subscribe(handlers);
|
|
24300
|
+
this.unsubscribers.push(() => {
|
|
24301
|
+
unbindCurrentSpanStore?.();
|
|
24302
|
+
tracingChannel2.unsubscribe(handlers);
|
|
24303
|
+
});
|
|
24304
|
+
}
|
|
24305
|
+
subscribeToContextEvents() {
|
|
24306
|
+
const channel2 = flueChannels.contextEvent.tracingChannel();
|
|
24307
|
+
const handlers = {
|
|
24308
|
+
start: (event) => {
|
|
24309
|
+
const flueEvent = event.arguments[0];
|
|
24310
|
+
if (!flueEvent) {
|
|
24311
|
+
return;
|
|
24312
|
+
}
|
|
24313
|
+
try {
|
|
24314
|
+
this.handleFlueEvent(flueEvent, {
|
|
24315
|
+
captureTurnSpans: event.captureTurnSpans !== false
|
|
24316
|
+
});
|
|
24317
|
+
} catch (error) {
|
|
24318
|
+
logInstrumentationError3("Flue event", error);
|
|
24319
|
+
}
|
|
24320
|
+
},
|
|
24321
|
+
error: () => {
|
|
24322
|
+
}
|
|
24323
|
+
};
|
|
24324
|
+
channel2.subscribe(handlers);
|
|
24325
|
+
this.unsubscribers.push(() => {
|
|
24326
|
+
channel2.unsubscribe(handlers);
|
|
24327
|
+
});
|
|
24328
|
+
}
|
|
24329
|
+
bindCurrentSpanStoreToOperationStart(tracingChannel2, ensureState2) {
|
|
24330
|
+
const state = _internalGetGlobalState();
|
|
24331
|
+
const startChannel = tracingChannel2.start;
|
|
24332
|
+
const contextManager = state?.contextManager;
|
|
24333
|
+
const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
|
|
24334
|
+
if (!currentSpanStore || !startChannel) {
|
|
24335
|
+
return void 0;
|
|
24336
|
+
}
|
|
24337
|
+
startChannel.bindStore(currentSpanStore, (event) => {
|
|
24338
|
+
const operationState = ensureState2(event);
|
|
24339
|
+
return contextManager.wrapSpanForStore(operationState.span);
|
|
24340
|
+
});
|
|
24341
|
+
return () => {
|
|
24342
|
+
startChannel.unbindStore(currentSpanStore);
|
|
24343
|
+
};
|
|
24344
|
+
}
|
|
24345
|
+
startOperationState(args) {
|
|
24346
|
+
const sessionName = getSessionName(args.session);
|
|
24347
|
+
const metadata = {
|
|
24348
|
+
...extractOperationInputMetadata(args.operation, args.args),
|
|
24349
|
+
...extractSessionMetadata(args.session),
|
|
24350
|
+
"flue.operation": args.operation,
|
|
24351
|
+
provider: "flue",
|
|
24352
|
+
...args.moduleVersion ? { "flue.version": args.moduleVersion } : {}
|
|
24353
|
+
};
|
|
24354
|
+
const span = startSpan({
|
|
24355
|
+
name: `flue.session.${args.operation}`,
|
|
24356
|
+
spanAttributes: { type: "task" /* TASK */ }
|
|
24357
|
+
});
|
|
24358
|
+
const state = {
|
|
24359
|
+
metadata,
|
|
24360
|
+
operation: args.operation,
|
|
24361
|
+
sessionName,
|
|
24362
|
+
span,
|
|
24363
|
+
startTime: getCurrentUnixTimestamp()
|
|
24364
|
+
};
|
|
24365
|
+
safeLog3(span, {
|
|
24366
|
+
input: extractOperationInput(args.operation, args.args),
|
|
24367
|
+
metadata
|
|
24368
|
+
});
|
|
24369
|
+
this.pendingOperationQueue(operationKey(sessionName, args.operation)).push(
|
|
24370
|
+
state
|
|
24371
|
+
);
|
|
24372
|
+
addOperationToScope(
|
|
24373
|
+
this.activeOperationsByScope,
|
|
24374
|
+
sessionName ?? "unknown",
|
|
24375
|
+
state
|
|
24376
|
+
);
|
|
24377
|
+
return state;
|
|
24378
|
+
}
|
|
24379
|
+
endOperationState(state, result) {
|
|
24380
|
+
if (!state) {
|
|
24381
|
+
return;
|
|
24382
|
+
}
|
|
24383
|
+
const metadata = {
|
|
24384
|
+
...state.metadata,
|
|
24385
|
+
...extractPromptResponseMetadata(result)
|
|
24386
|
+
};
|
|
24387
|
+
const metrics = {
|
|
24388
|
+
...buildDurationMetrics3(state.startTime),
|
|
24389
|
+
...metricsFromUsage(result?.usage)
|
|
24390
|
+
};
|
|
24391
|
+
safeLog3(state.span, {
|
|
24392
|
+
metadata,
|
|
24393
|
+
metrics,
|
|
24394
|
+
output: extractOperationOutput(result)
|
|
24395
|
+
});
|
|
24396
|
+
this.finishCompactionsForOperation(state);
|
|
24397
|
+
this.finishOperationState(state);
|
|
24398
|
+
}
|
|
24399
|
+
finishOperationState(state) {
|
|
24400
|
+
removePendingOperation(this.pendingOperationsByKey, state);
|
|
24401
|
+
if (state.operationId) {
|
|
24402
|
+
this.activeOperationsById.delete(state.operationId);
|
|
24403
|
+
}
|
|
24404
|
+
removeScopedOperation(this.activeOperationsByScope, state);
|
|
24405
|
+
state.span.end();
|
|
24406
|
+
}
|
|
24407
|
+
handleFlueEvent(event, options) {
|
|
24408
|
+
switch (event.type) {
|
|
24409
|
+
case "operation_start":
|
|
24410
|
+
this.handleOperationStart(event);
|
|
24411
|
+
return;
|
|
24412
|
+
case "operation":
|
|
24413
|
+
this.handleOperation(event);
|
|
24414
|
+
return;
|
|
24415
|
+
case "text_delta":
|
|
24416
|
+
if (!options.captureTurnSpans) {
|
|
24417
|
+
return;
|
|
24418
|
+
}
|
|
24419
|
+
this.ensureTurnState(event).text.push(
|
|
24420
|
+
typeof event.text === "string" ? event.text : ""
|
|
24421
|
+
);
|
|
24422
|
+
return;
|
|
24423
|
+
case "thinking_start":
|
|
24424
|
+
if (!options.captureTurnSpans) {
|
|
24425
|
+
return;
|
|
24426
|
+
}
|
|
24427
|
+
this.handleThinkingStart(event);
|
|
24428
|
+
return;
|
|
24429
|
+
case "thinking_delta":
|
|
24430
|
+
if (!options.captureTurnSpans) {
|
|
24431
|
+
return;
|
|
24432
|
+
}
|
|
24433
|
+
this.handleThinkingDelta(event);
|
|
24434
|
+
return;
|
|
24435
|
+
case "thinking_end":
|
|
24436
|
+
if (!options.captureTurnSpans) {
|
|
24437
|
+
return;
|
|
24438
|
+
}
|
|
24439
|
+
this.handleThinkingEnd(event);
|
|
24440
|
+
return;
|
|
24441
|
+
case "turn":
|
|
24442
|
+
if (!options.captureTurnSpans) {
|
|
24443
|
+
return;
|
|
24444
|
+
}
|
|
24445
|
+
this.handleTurn(event);
|
|
24446
|
+
return;
|
|
24447
|
+
case "tool_start":
|
|
24448
|
+
this.handleToolStart(event, options);
|
|
24449
|
+
return;
|
|
24450
|
+
case "tool_call":
|
|
24451
|
+
this.handleToolCall(event);
|
|
24452
|
+
return;
|
|
24453
|
+
case "task_start":
|
|
24454
|
+
this.handleTaskStart(event);
|
|
24455
|
+
return;
|
|
24456
|
+
case "task":
|
|
24457
|
+
this.handleTask(event);
|
|
24458
|
+
return;
|
|
24459
|
+
case "compaction_start":
|
|
24460
|
+
this.handleCompactionStart(event);
|
|
24461
|
+
return;
|
|
24462
|
+
case "compaction":
|
|
24463
|
+
this.handleCompaction(event);
|
|
24464
|
+
return;
|
|
24465
|
+
default:
|
|
24466
|
+
return;
|
|
24467
|
+
}
|
|
24468
|
+
}
|
|
24469
|
+
handleOperationStart(event) {
|
|
24470
|
+
if (!isInstrumentedOperation(event.operationKind)) {
|
|
24471
|
+
return;
|
|
24472
|
+
}
|
|
24473
|
+
const state = this.takePendingOperationForEvent(event);
|
|
24474
|
+
if (!state) {
|
|
24475
|
+
return;
|
|
24476
|
+
}
|
|
24477
|
+
state.operationId = event.operationId;
|
|
24478
|
+
this.activeOperationsById.set(event.operationId, state);
|
|
24479
|
+
addScopedOperation(this.activeOperationsByScope, event, state);
|
|
24480
|
+
state.metadata = {
|
|
24481
|
+
...state.metadata,
|
|
24482
|
+
...extractEventMetadata(event),
|
|
24483
|
+
"flue.operation_id": event.operationId
|
|
24484
|
+
};
|
|
24485
|
+
safeLog3(state.span, { metadata: state.metadata });
|
|
24486
|
+
}
|
|
24487
|
+
handleOperation(event) {
|
|
24488
|
+
const state = event.operationId ? this.activeOperationsById.get(event.operationId) : void 0;
|
|
24489
|
+
if (!state) {
|
|
24490
|
+
return;
|
|
24491
|
+
}
|
|
24492
|
+
const metadata = {
|
|
24493
|
+
...state.metadata,
|
|
24494
|
+
...extractEventMetadata(event),
|
|
24495
|
+
...typeof event.durationMs === "number" ? { "flue.duration_ms": event.durationMs } : {},
|
|
24496
|
+
...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
|
|
24497
|
+
};
|
|
24498
|
+
const metrics = metricsFromUsage(event.usage);
|
|
24499
|
+
safeLog3(state.span, {
|
|
24500
|
+
...event.error ? { error: errorToString(event.error) } : {},
|
|
24501
|
+
metadata,
|
|
24502
|
+
...Object.keys(metrics).length ? { metrics } : {}
|
|
24503
|
+
});
|
|
24504
|
+
}
|
|
24505
|
+
ensureTurnState(event) {
|
|
24506
|
+
const scope = scopeKey(event);
|
|
24507
|
+
const existing = this.turnsByScope.get(scope);
|
|
24508
|
+
if (existing) {
|
|
24509
|
+
return existing;
|
|
24510
|
+
}
|
|
24511
|
+
const parent = this.parentSpanForEvent(event);
|
|
24512
|
+
const metadata = {
|
|
24513
|
+
...extractEventMetadata(event),
|
|
24514
|
+
provider: "flue"
|
|
24515
|
+
};
|
|
24516
|
+
const span = startFlueSpan(parent, {
|
|
24517
|
+
name: "flue.turn",
|
|
24518
|
+
spanAttributes: { type: "llm" /* LLM */ }
|
|
24519
|
+
});
|
|
24520
|
+
const state = {
|
|
24521
|
+
metadata,
|
|
24522
|
+
span,
|
|
24523
|
+
hasThinking: false,
|
|
24524
|
+
startTime: getCurrentUnixTimestamp(),
|
|
24525
|
+
text: [],
|
|
24526
|
+
thinking: [],
|
|
24527
|
+
toolCalls: []
|
|
24528
|
+
};
|
|
24529
|
+
safeLog3(span, { metadata });
|
|
24530
|
+
this.turnsByScope.set(scope, state);
|
|
24531
|
+
return state;
|
|
24532
|
+
}
|
|
24533
|
+
handleTurn(event) {
|
|
24534
|
+
const scope = scopeKey(event);
|
|
24535
|
+
const state = this.ensureTurnState(event);
|
|
24536
|
+
const text = state.text.join("");
|
|
24537
|
+
const reasoning = state.finalThinking ?? state.thinking.join("");
|
|
24538
|
+
const outputReasoning = reasoning || (state.hasThinking ? "[reasoning stream present; content unavailable]" : void 0);
|
|
24539
|
+
const metadata = {
|
|
24540
|
+
...state.metadata,
|
|
24541
|
+
...extractEventMetadata(event),
|
|
24542
|
+
...event.model ? { model: event.model, "flue.model": event.model } : {},
|
|
24543
|
+
...event.stopReason ? { "flue.stop_reason": event.stopReason } : {},
|
|
24544
|
+
...event.isError !== void 0 ? { "flue.is_error": event.isError } : {},
|
|
24545
|
+
provider: "flue"
|
|
24546
|
+
};
|
|
24547
|
+
safeLog3(state.span, {
|
|
24548
|
+
...event.error ? { error: errorToString(event.error) } : {},
|
|
24549
|
+
metadata,
|
|
24550
|
+
metrics: {
|
|
24551
|
+
...durationMsMetrics(event.durationMs),
|
|
24552
|
+
...metricsFromUsage(event.usage)
|
|
24553
|
+
},
|
|
24554
|
+
output: toAssistantOutput(
|
|
24555
|
+
text,
|
|
24556
|
+
event.stopReason,
|
|
24557
|
+
outputReasoning,
|
|
24558
|
+
state.toolCalls
|
|
24559
|
+
)
|
|
24560
|
+
});
|
|
24561
|
+
state.span.end();
|
|
24562
|
+
this.turnsByScope.delete(scope);
|
|
24563
|
+
}
|
|
24564
|
+
handleThinkingDelta(event) {
|
|
24565
|
+
const delta = event.delta;
|
|
24566
|
+
if (typeof delta !== "string" || !delta) {
|
|
24567
|
+
return;
|
|
24568
|
+
}
|
|
24569
|
+
const state = this.ensureTurnState(event);
|
|
24570
|
+
state.hasThinking = true;
|
|
24571
|
+
state.metadata["flue.thinking"] = true;
|
|
24572
|
+
state.thinking.push(delta);
|
|
24573
|
+
}
|
|
24574
|
+
handleThinkingStart(event) {
|
|
24575
|
+
const state = this.ensureTurnState(event);
|
|
24576
|
+
state.hasThinking = true;
|
|
24577
|
+
state.metadata["flue.thinking"] = true;
|
|
24578
|
+
}
|
|
24579
|
+
handleThinkingEnd(event) {
|
|
24580
|
+
const state = this.ensureTurnState(event);
|
|
24581
|
+
state.hasThinking = true;
|
|
24582
|
+
state.metadata["flue.thinking"] = true;
|
|
24583
|
+
if (typeof event.content === "string" && event.content) {
|
|
24584
|
+
state.finalThinking = event.content;
|
|
24585
|
+
}
|
|
24586
|
+
}
|
|
24587
|
+
handleToolStart(event, options) {
|
|
24588
|
+
const toolCallId = event.toolCallId;
|
|
24589
|
+
if (!toolCallId) {
|
|
24590
|
+
return;
|
|
24591
|
+
}
|
|
24592
|
+
const parent = this.parentSpanForEvent(event);
|
|
24593
|
+
const scope = scopeKey(event);
|
|
24594
|
+
let turnState = this.turnsByScope.get(scope);
|
|
24595
|
+
if (!turnState && parent && options.captureTurnSpans) {
|
|
24596
|
+
turnState = this.ensureTurnState(event);
|
|
24597
|
+
}
|
|
24598
|
+
const metadata = {
|
|
24599
|
+
...extractEventMetadata(event),
|
|
24600
|
+
...event.toolName ? { "flue.tool_name": event.toolName } : {},
|
|
24601
|
+
"flue.tool_call_id": toolCallId,
|
|
24602
|
+
provider: "flue"
|
|
24603
|
+
};
|
|
24604
|
+
const span = startFlueSpan(parent, {
|
|
24605
|
+
name: `tool: ${event.toolName ?? "unknown"}`,
|
|
24606
|
+
spanAttributes: { type: "tool" /* TOOL */ }
|
|
24607
|
+
});
|
|
24608
|
+
if (turnState) {
|
|
24609
|
+
turnState.toolCalls.push({
|
|
24610
|
+
args: event.args,
|
|
24611
|
+
toolCallId,
|
|
24612
|
+
toolName: event.toolName
|
|
24613
|
+
});
|
|
24614
|
+
}
|
|
24615
|
+
safeLog3(span, {
|
|
24616
|
+
input: event.args,
|
|
24617
|
+
metadata
|
|
24618
|
+
});
|
|
24619
|
+
this.toolsById.set(toolKey(event), {
|
|
24620
|
+
metadata,
|
|
24621
|
+
span,
|
|
24622
|
+
startTime: getCurrentUnixTimestamp()
|
|
24623
|
+
});
|
|
24624
|
+
}
|
|
24625
|
+
handleToolCall(event) {
|
|
24626
|
+
const key = toolKey(event);
|
|
24627
|
+
const state = this.toolsById.get(key) ?? this.startSyntheticToolState(event, event.toolName ?? "unknown");
|
|
24628
|
+
const metadata = {
|
|
24629
|
+
...state.metadata,
|
|
24630
|
+
...extractEventMetadata(event),
|
|
24631
|
+
...event.toolName ? { "flue.tool_name": event.toolName } : {},
|
|
24632
|
+
...event.toolCallId ? { "flue.tool_call_id": event.toolCallId } : {},
|
|
24633
|
+
...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
|
|
24634
|
+
};
|
|
24635
|
+
safeLog3(state.span, {
|
|
24636
|
+
...event.isError ? { error: errorToString(event.result) } : {},
|
|
24637
|
+
metadata,
|
|
24638
|
+
metrics: durationMsMetrics(event.durationMs),
|
|
24639
|
+
output: event.result
|
|
24640
|
+
});
|
|
24641
|
+
state.span.end();
|
|
24642
|
+
this.toolsById.delete(key);
|
|
24643
|
+
}
|
|
24644
|
+
handleTaskStart(event) {
|
|
24645
|
+
const parent = this.parentSpanForEvent(event);
|
|
24646
|
+
const metadata = {
|
|
24647
|
+
...extractEventMetadata(event),
|
|
24648
|
+
...event.role ? { "flue.role": event.role } : {},
|
|
24649
|
+
...event.cwd ? { "flue.cwd": event.cwd } : {},
|
|
24650
|
+
"flue.task_id": event.taskId,
|
|
24651
|
+
provider: "flue"
|
|
24652
|
+
};
|
|
24653
|
+
const span = startFlueSpan(parent, {
|
|
24654
|
+
name: "flue.task",
|
|
24655
|
+
spanAttributes: { type: "task" /* TASK */ }
|
|
24656
|
+
});
|
|
24657
|
+
safeLog3(span, {
|
|
24658
|
+
input: event.prompt,
|
|
24659
|
+
metadata
|
|
24660
|
+
});
|
|
24661
|
+
this.tasksById.set(event.taskId, {
|
|
24662
|
+
metadata,
|
|
24663
|
+
span,
|
|
24664
|
+
startTime: getCurrentUnixTimestamp()
|
|
24665
|
+
});
|
|
24666
|
+
}
|
|
24667
|
+
handleTask(event) {
|
|
24668
|
+
const state = this.tasksById.get(event.taskId);
|
|
24669
|
+
if (!state) {
|
|
24670
|
+
return;
|
|
24671
|
+
}
|
|
24672
|
+
safeLog3(state.span, {
|
|
24673
|
+
...event.isError ? { error: errorToString(event.result) } : {},
|
|
24674
|
+
metadata: {
|
|
24675
|
+
...state.metadata,
|
|
24676
|
+
...extractEventMetadata(event),
|
|
24677
|
+
...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
|
|
24678
|
+
},
|
|
24679
|
+
metrics: durationMsMetrics(event.durationMs),
|
|
24680
|
+
output: event.result
|
|
24681
|
+
});
|
|
24682
|
+
state.span.end();
|
|
24683
|
+
this.tasksById.delete(event.taskId);
|
|
24684
|
+
}
|
|
24685
|
+
handleCompactionStart(event) {
|
|
24686
|
+
const operationState = this.operationStateForEvent(event);
|
|
24687
|
+
const parent = operationState?.span ?? this.parentSpanForEvent(event);
|
|
24688
|
+
const metadata = {
|
|
24689
|
+
...extractEventMetadata(event),
|
|
24690
|
+
...event.reason ? { "flue.compaction_reason": event.reason } : {},
|
|
24691
|
+
provider: "flue"
|
|
24692
|
+
};
|
|
24693
|
+
const input = {
|
|
24694
|
+
...typeof event.estimatedTokens === "number" ? { estimatedTokens: event.estimatedTokens } : {},
|
|
24695
|
+
...event.reason ? { reason: event.reason } : {}
|
|
24696
|
+
};
|
|
24697
|
+
const span = startFlueSpan(parent, {
|
|
24698
|
+
name: "flue.compaction",
|
|
24699
|
+
spanAttributes: { type: "task" /* TASK */ }
|
|
24700
|
+
});
|
|
24701
|
+
safeLog3(span, {
|
|
24702
|
+
input,
|
|
24703
|
+
metadata
|
|
24704
|
+
});
|
|
24705
|
+
this.compactionsByScope.set(scopeKey(event), {
|
|
24706
|
+
input,
|
|
24707
|
+
metadata,
|
|
24708
|
+
operationState,
|
|
24709
|
+
span,
|
|
24710
|
+
startTime: getCurrentUnixTimestamp()
|
|
24711
|
+
});
|
|
24712
|
+
}
|
|
24713
|
+
handleCompaction(event) {
|
|
24714
|
+
const key = scopeKey(event);
|
|
24715
|
+
const state = this.compactionsByScope.get(key) ?? this.findCompactionState(event);
|
|
24716
|
+
if (!state) {
|
|
24717
|
+
return;
|
|
24718
|
+
}
|
|
24719
|
+
safeLog3(state.span, {
|
|
24720
|
+
metadata: {
|
|
24721
|
+
...state.metadata,
|
|
24722
|
+
...extractEventMetadata(event),
|
|
24723
|
+
...typeof event.messagesBefore === "number" ? { "flue.messages_before": event.messagesBefore } : {},
|
|
24724
|
+
...typeof event.messagesAfter === "number" ? { "flue.messages_after": event.messagesAfter } : {}
|
|
24725
|
+
},
|
|
24726
|
+
metrics: {
|
|
24727
|
+
...durationMsMetrics(event.durationMs),
|
|
24728
|
+
...metricsFromUsage(event.usage)
|
|
24729
|
+
},
|
|
24730
|
+
output: {
|
|
24731
|
+
messagesAfter: event.messagesAfter,
|
|
24732
|
+
messagesBefore: event.messagesBefore
|
|
24733
|
+
}
|
|
24734
|
+
});
|
|
24735
|
+
state.span.end();
|
|
24736
|
+
this.deleteCompactionState(state);
|
|
24737
|
+
}
|
|
24738
|
+
findCompactionState(event) {
|
|
24739
|
+
const operationState = this.operationStateForEvent(event);
|
|
24740
|
+
for (const state of this.compactionsByScope.values()) {
|
|
24741
|
+
if (operationState && state.operationState === operationState) {
|
|
24742
|
+
return state;
|
|
24743
|
+
}
|
|
24744
|
+
}
|
|
24745
|
+
return void 0;
|
|
24746
|
+
}
|
|
24747
|
+
finishCompactionsForOperation(operationState) {
|
|
24748
|
+
for (const state of [...this.compactionsByScope.values()]) {
|
|
24749
|
+
if (state.operationState !== operationState) {
|
|
24750
|
+
continue;
|
|
24751
|
+
}
|
|
24752
|
+
safeLog3(state.span, {
|
|
24753
|
+
input: state.input,
|
|
24754
|
+
metadata: state.metadata,
|
|
24755
|
+
metrics: {
|
|
24756
|
+
...buildDurationMetrics3(state.startTime)
|
|
24757
|
+
},
|
|
24758
|
+
output: { completed: true }
|
|
24759
|
+
});
|
|
24760
|
+
state.span.end();
|
|
24761
|
+
this.deleteCompactionState(state);
|
|
24762
|
+
}
|
|
24763
|
+
}
|
|
24764
|
+
deleteCompactionState(state) {
|
|
24765
|
+
for (const [key, candidate] of this.compactionsByScope) {
|
|
24766
|
+
if (candidate !== state) {
|
|
24767
|
+
continue;
|
|
24768
|
+
}
|
|
24769
|
+
this.compactionsByScope.delete(key);
|
|
24770
|
+
return;
|
|
24771
|
+
}
|
|
24772
|
+
}
|
|
24773
|
+
startSyntheticToolState(event, toolName) {
|
|
24774
|
+
const parent = this.parentSpanForEvent(event);
|
|
24775
|
+
const metadata = {
|
|
24776
|
+
...extractEventMetadata(event),
|
|
24777
|
+
...event.toolCallId ? { "flue.tool_call_id": event.toolCallId } : {},
|
|
24778
|
+
"flue.tool_name": toolName,
|
|
24779
|
+
provider: "flue"
|
|
24780
|
+
};
|
|
24781
|
+
const span = startFlueSpan(parent, {
|
|
24782
|
+
name: `tool: ${toolName}`,
|
|
24783
|
+
spanAttributes: { type: "tool" /* TOOL */ }
|
|
24784
|
+
});
|
|
24785
|
+
safeLog3(span, { metadata });
|
|
24786
|
+
return { metadata, span, startTime: getCurrentUnixTimestamp() };
|
|
24787
|
+
}
|
|
24788
|
+
operationStateForEvent(event) {
|
|
24789
|
+
if (event.operationId) {
|
|
24790
|
+
const operation = this.activeOperationsById.get(event.operationId) ?? this.promotePendingOperationForEvent(event);
|
|
24791
|
+
if (operation) {
|
|
24792
|
+
return operation;
|
|
24793
|
+
}
|
|
24794
|
+
}
|
|
24795
|
+
return this.activeOperationForEventScope(event) ?? this.pendingOperationForEventScope(event);
|
|
24796
|
+
}
|
|
24797
|
+
parentSpanForEvent(event) {
|
|
24798
|
+
if (event.operationId) {
|
|
24799
|
+
const operation = this.operationStateForEvent(event);
|
|
24800
|
+
if (operation) {
|
|
24801
|
+
return operation.span;
|
|
24802
|
+
}
|
|
24803
|
+
}
|
|
24804
|
+
if (event.taskId) {
|
|
24805
|
+
return this.tasksById.get(event.taskId)?.span;
|
|
24806
|
+
}
|
|
24807
|
+
return this.operationStateForEvent(event)?.span;
|
|
24808
|
+
}
|
|
24809
|
+
promotePendingOperationForEvent(event) {
|
|
24810
|
+
if (!event.operationId) {
|
|
24811
|
+
return void 0;
|
|
24812
|
+
}
|
|
24813
|
+
const scopePrefixes = operationScopePrefixes(event);
|
|
24814
|
+
for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
|
|
24815
|
+
if (!candidateQueue.length || !operationKeyMatchesScopes(candidateKey, scopePrefixes)) {
|
|
24816
|
+
continue;
|
|
24817
|
+
}
|
|
24818
|
+
const state = candidateQueue.shift();
|
|
24819
|
+
if (!state) {
|
|
24820
|
+
return void 0;
|
|
24821
|
+
}
|
|
24822
|
+
state.operationId = event.operationId;
|
|
24823
|
+
this.activeOperationsById.set(event.operationId, state);
|
|
24824
|
+
addScopedOperation(this.activeOperationsByScope, event, state);
|
|
24825
|
+
state.metadata = {
|
|
24826
|
+
...state.metadata,
|
|
24827
|
+
...extractEventMetadata(event),
|
|
24828
|
+
"flue.operation_id": event.operationId
|
|
24829
|
+
};
|
|
24830
|
+
safeLog3(state.span, { metadata: state.metadata });
|
|
24831
|
+
return state;
|
|
24832
|
+
}
|
|
24833
|
+
return void 0;
|
|
24834
|
+
}
|
|
24835
|
+
activeOperationForEventScope(event) {
|
|
24836
|
+
for (const scope of operationScopeNames(event)) {
|
|
24837
|
+
const operations = this.activeOperationsByScope.get(scope);
|
|
24838
|
+
if (operations?.length) {
|
|
24839
|
+
return operations[operations.length - 1];
|
|
24840
|
+
}
|
|
24841
|
+
}
|
|
24842
|
+
return void 0;
|
|
24843
|
+
}
|
|
24844
|
+
pendingOperationForEventScope(event) {
|
|
24845
|
+
const scopePrefixes = operationScopePrefixes(event);
|
|
24846
|
+
for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
|
|
24847
|
+
if (!candidateQueue.length || !operationKeyMatchesScopes(candidateKey, scopePrefixes)) {
|
|
24848
|
+
continue;
|
|
24849
|
+
}
|
|
24850
|
+
return candidateQueue[0];
|
|
24851
|
+
}
|
|
24852
|
+
return void 0;
|
|
24853
|
+
}
|
|
24854
|
+
takePendingOperationForEvent(event) {
|
|
24855
|
+
const key = operationKey(event.session, event.operationKind);
|
|
24856
|
+
const queue2 = this.pendingOperationsByKey.get(key);
|
|
24857
|
+
if (queue2?.length) {
|
|
24858
|
+
return queue2.shift();
|
|
24859
|
+
}
|
|
24860
|
+
for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
|
|
24861
|
+
if (candidateKey.endsWith(`::${event.operationKind}`) && candidateQueue.length) {
|
|
24862
|
+
return candidateQueue.shift();
|
|
24863
|
+
}
|
|
24864
|
+
}
|
|
24865
|
+
return void 0;
|
|
24866
|
+
}
|
|
24867
|
+
pendingOperationQueue(key) {
|
|
24868
|
+
const existing = this.pendingOperationsByKey.get(key);
|
|
24869
|
+
if (existing) {
|
|
24870
|
+
return existing;
|
|
24871
|
+
}
|
|
24872
|
+
const queue2 = [];
|
|
24873
|
+
this.pendingOperationsByKey.set(key, queue2);
|
|
24874
|
+
return queue2;
|
|
24875
|
+
}
|
|
24876
|
+
};
|
|
24877
|
+
function isInstrumentedOperation(operation) {
|
|
24878
|
+
return operation === "prompt" || operation === "skill" || operation === "task" || operation === "compact";
|
|
24879
|
+
}
|
|
24880
|
+
function getSessionName(session) {
|
|
24881
|
+
return typeof session?.name === "string" ? session.name : void 0;
|
|
24882
|
+
}
|
|
24883
|
+
function operationKey(sessionName, operation) {
|
|
24884
|
+
return `${sessionName ?? "unknown"}::${operation}`;
|
|
24885
|
+
}
|
|
24886
|
+
function operationScopePrefixes(event) {
|
|
24887
|
+
const scopes = /* @__PURE__ */ new Set();
|
|
24888
|
+
for (const scope of operationScopeNames(event)) {
|
|
24889
|
+
scopes.add(`${scope}::`);
|
|
24890
|
+
}
|
|
24891
|
+
return scopes;
|
|
24892
|
+
}
|
|
24893
|
+
function operationKeyMatchesScopes(key, scopes) {
|
|
24894
|
+
for (const scope of scopes) {
|
|
24895
|
+
if (key.startsWith(scope)) {
|
|
24896
|
+
return true;
|
|
24897
|
+
}
|
|
24898
|
+
}
|
|
24899
|
+
return false;
|
|
24900
|
+
}
|
|
24901
|
+
function operationScopeNames(event) {
|
|
24902
|
+
const scopes = /* @__PURE__ */ new Set();
|
|
24903
|
+
if (event.session) {
|
|
24904
|
+
scopes.add(event.session);
|
|
24905
|
+
}
|
|
24906
|
+
if (event.parentSession) {
|
|
24907
|
+
scopes.add(event.parentSession);
|
|
24908
|
+
}
|
|
24909
|
+
if (!scopes.size) {
|
|
24910
|
+
scopes.add("unknown");
|
|
24911
|
+
}
|
|
24912
|
+
return scopes;
|
|
24913
|
+
}
|
|
24914
|
+
function addScopedOperation(operationsByScope, event, state) {
|
|
24915
|
+
for (const scope of operationScopeNames(event)) {
|
|
24916
|
+
addOperationToScope(operationsByScope, scope, state);
|
|
24917
|
+
}
|
|
24918
|
+
}
|
|
24919
|
+
function addOperationToScope(operationsByScope, scope, state) {
|
|
24920
|
+
const operations = operationsByScope.get(scope);
|
|
24921
|
+
if (operations) {
|
|
24922
|
+
if (!operations.includes(state)) {
|
|
24923
|
+
operations.push(state);
|
|
24924
|
+
}
|
|
24925
|
+
} else {
|
|
24926
|
+
operationsByScope.set(scope, [state]);
|
|
24927
|
+
}
|
|
24928
|
+
}
|
|
24929
|
+
function removeScopedOperation(operationsByScope, state) {
|
|
24930
|
+
for (const [scope, operations] of operationsByScope) {
|
|
24931
|
+
const index = operations.indexOf(state);
|
|
24932
|
+
if (index === -1) {
|
|
24933
|
+
continue;
|
|
24934
|
+
}
|
|
24935
|
+
operations.splice(index, 1);
|
|
24936
|
+
if (operations.length === 0) {
|
|
24937
|
+
operationsByScope.delete(scope);
|
|
24938
|
+
}
|
|
24939
|
+
}
|
|
24940
|
+
}
|
|
24941
|
+
function removePendingOperation(pendingOperationsByKey, state) {
|
|
24942
|
+
for (const [key, queue2] of pendingOperationsByKey) {
|
|
24943
|
+
const index = queue2.indexOf(state);
|
|
24944
|
+
if (index === -1) {
|
|
24945
|
+
continue;
|
|
24946
|
+
}
|
|
24947
|
+
queue2.splice(index, 1);
|
|
24948
|
+
if (queue2.length === 0) {
|
|
24949
|
+
pendingOperationsByKey.delete(key);
|
|
24950
|
+
}
|
|
24951
|
+
return;
|
|
24952
|
+
}
|
|
24953
|
+
}
|
|
24954
|
+
function extractSessionMetadata(session) {
|
|
24955
|
+
const sessionName = getSessionName(session);
|
|
24956
|
+
return sessionName ? { "flue.session": sessionName } : {};
|
|
24957
|
+
}
|
|
24958
|
+
function extractEventMetadata(event) {
|
|
24959
|
+
return {
|
|
24960
|
+
...event.runId ? { "flue.run_id": event.runId } : {},
|
|
24961
|
+
...typeof event.eventIndex === "number" ? { "flue.event_index": event.eventIndex } : {},
|
|
24962
|
+
...event.session ? { "flue.session": event.session } : {},
|
|
24963
|
+
...event.parentSession ? { "flue.parent_session": event.parentSession } : {},
|
|
24964
|
+
...event.harness ? { "flue.harness": event.harness } : {},
|
|
24965
|
+
...event.taskId ? { "flue.task_id": event.taskId } : {},
|
|
24966
|
+
...event.operationId ? { "flue.operation_id": event.operationId } : {}
|
|
24967
|
+
};
|
|
24968
|
+
}
|
|
24969
|
+
function extractOperationInput(operation, args) {
|
|
24970
|
+
switch (operation) {
|
|
24971
|
+
case "prompt":
|
|
24972
|
+
case "task":
|
|
24973
|
+
return args[0];
|
|
24974
|
+
case "skill":
|
|
24975
|
+
return {
|
|
24976
|
+
args: getOptionObject(args[1])?.args,
|
|
24977
|
+
name: args[0]
|
|
24978
|
+
};
|
|
24979
|
+
case "compact":
|
|
24980
|
+
return void 0;
|
|
24981
|
+
}
|
|
24982
|
+
}
|
|
24983
|
+
function extractOperationInputMetadata(operation, args) {
|
|
24984
|
+
const options = getOptionObject(args[1]);
|
|
24985
|
+
return {
|
|
24986
|
+
...operation === "skill" && typeof args[0] === "string" ? { "flue.skill_name": args[0] } : {},
|
|
24987
|
+
...options?.model ? { model: options.model, "flue.model": options.model } : {},
|
|
24988
|
+
...options?.role ? { "flue.role": options.role } : {},
|
|
24989
|
+
...options?.thinkingLevel ? { "flue.thinking_level": options.thinkingLevel } : {},
|
|
24990
|
+
...typeof options?.cwd === "string" ? { "flue.cwd": options.cwd } : {},
|
|
24991
|
+
...Array.isArray(options?.tools) ? {
|
|
24992
|
+
"flue.tools_count": options.tools.length,
|
|
24993
|
+
tools: summarizeTools(options.tools)
|
|
24994
|
+
} : {},
|
|
24995
|
+
...Array.isArray(options?.images) ? { "flue.images_count": options.images.length } : {},
|
|
24996
|
+
...options?.result || options?.schema ? { "flue.result_schema": true } : {}
|
|
24997
|
+
};
|
|
24998
|
+
}
|
|
24999
|
+
function getOptionObject(value) {
|
|
25000
|
+
return isObject(value) ? value : void 0;
|
|
25001
|
+
}
|
|
25002
|
+
function summarizeTools(tools) {
|
|
25003
|
+
return tools.flatMap((tool) => {
|
|
25004
|
+
if (!isObject(tool)) {
|
|
25005
|
+
return [];
|
|
25006
|
+
}
|
|
25007
|
+
const name = typeof tool.name === "string" ? tool.name : void 0;
|
|
25008
|
+
if (!name) {
|
|
25009
|
+
return [];
|
|
25010
|
+
}
|
|
25011
|
+
return [
|
|
25012
|
+
{
|
|
25013
|
+
function: {
|
|
25014
|
+
description: typeof tool.description === "string" ? tool.description : void 0,
|
|
25015
|
+
name,
|
|
25016
|
+
parameters: tool.parameters
|
|
25017
|
+
},
|
|
25018
|
+
type: "function"
|
|
25019
|
+
}
|
|
25020
|
+
];
|
|
25021
|
+
});
|
|
25022
|
+
}
|
|
25023
|
+
function extractPromptResponseMetadata(result) {
|
|
25024
|
+
const modelId = result?.model && typeof result.model.id === "string" ? result.model.id : void 0;
|
|
25025
|
+
return modelId ? {
|
|
25026
|
+
model: modelId,
|
|
25027
|
+
"flue.model": modelId
|
|
25028
|
+
} : {};
|
|
25029
|
+
}
|
|
25030
|
+
function extractOperationOutput(result) {
|
|
25031
|
+
if (!result) {
|
|
25032
|
+
return void 0;
|
|
25033
|
+
}
|
|
25034
|
+
if ("data" in result) {
|
|
25035
|
+
return result.data;
|
|
25036
|
+
}
|
|
25037
|
+
if ("text" in result) {
|
|
25038
|
+
return result.text;
|
|
25039
|
+
}
|
|
25040
|
+
return result;
|
|
25041
|
+
}
|
|
25042
|
+
function metricsFromUsage(usage) {
|
|
25043
|
+
return {
|
|
25044
|
+
...typeof usage?.input === "number" ? { prompt_tokens: usage.input } : {},
|
|
25045
|
+
...typeof usage?.output === "number" ? { completion_tokens: usage.output } : {},
|
|
25046
|
+
...typeof usage?.cacheRead === "number" ? { prompt_cached_tokens: usage.cacheRead } : {},
|
|
25047
|
+
...typeof usage?.cacheWrite === "number" ? { prompt_cache_creation_tokens: usage.cacheWrite } : {},
|
|
25048
|
+
...typeof usage?.totalTokens === "number" ? { tokens: usage.totalTokens } : {},
|
|
25049
|
+
...typeof usage?.cost?.total === "number" ? { estimated_cost: usage.cost.total } : {}
|
|
25050
|
+
};
|
|
25051
|
+
}
|
|
25052
|
+
function buildDurationMetrics3(startTime) {
|
|
25053
|
+
return {
|
|
25054
|
+
duration_ms: Math.max(0, (getCurrentUnixTimestamp() - startTime) * 1e3)
|
|
25055
|
+
};
|
|
25056
|
+
}
|
|
25057
|
+
function durationMsMetrics(durationMs) {
|
|
25058
|
+
return typeof durationMs === "number" ? { duration_ms: durationMs } : {};
|
|
25059
|
+
}
|
|
25060
|
+
function scopeKey(event) {
|
|
25061
|
+
if (event.operationId) {
|
|
25062
|
+
return `operation:${event.operationId}`;
|
|
25063
|
+
}
|
|
25064
|
+
if (event.taskId) {
|
|
25065
|
+
return `task:${event.taskId}`;
|
|
25066
|
+
}
|
|
25067
|
+
if (event.session) {
|
|
25068
|
+
return `session:${event.session}`;
|
|
25069
|
+
}
|
|
25070
|
+
return "flue:unknown";
|
|
25071
|
+
}
|
|
25072
|
+
function toolKey(event) {
|
|
25073
|
+
return `${scopeKey(event)}::tool:${event.toolCallId ?? "unknown"}`;
|
|
25074
|
+
}
|
|
25075
|
+
function toAssistantOutput(text, finishReason, reasoning, toolCalls) {
|
|
25076
|
+
return [
|
|
25077
|
+
{
|
|
25078
|
+
finish_reason: finishReason ?? "stop",
|
|
25079
|
+
index: 0,
|
|
25080
|
+
message: {
|
|
25081
|
+
content: text,
|
|
25082
|
+
...reasoning ? { reasoning } : {},
|
|
25083
|
+
role: "assistant",
|
|
25084
|
+
...toolCalls?.length ? {
|
|
25085
|
+
tool_calls: toolCalls.map((toolCall) => ({
|
|
25086
|
+
function: {
|
|
25087
|
+
arguments: toolCall.args === void 0 ? "{}" : JSON.stringify(toolCall.args),
|
|
25088
|
+
name: toolCall.toolName ?? "unknown"
|
|
25089
|
+
},
|
|
25090
|
+
...toolCall.toolCallId ? { id: toolCall.toolCallId } : {},
|
|
25091
|
+
type: "function"
|
|
25092
|
+
}))
|
|
25093
|
+
} : {}
|
|
25094
|
+
}
|
|
25095
|
+
}
|
|
25096
|
+
];
|
|
25097
|
+
}
|
|
25098
|
+
function startFlueSpan(parent, args) {
|
|
25099
|
+
return parent ? withCurrent(parent, () => startSpan(args)) : startSpan(args);
|
|
25100
|
+
}
|
|
25101
|
+
function safeLog3(span, event) {
|
|
25102
|
+
try {
|
|
25103
|
+
span.log(event);
|
|
25104
|
+
} catch (error) {
|
|
25105
|
+
logInstrumentationError3("Flue span log", error);
|
|
25106
|
+
}
|
|
25107
|
+
}
|
|
25108
|
+
function errorToString(error) {
|
|
25109
|
+
if (error instanceof Error) {
|
|
25110
|
+
return error.message;
|
|
25111
|
+
}
|
|
25112
|
+
if (typeof error === "string") {
|
|
25113
|
+
return error;
|
|
25114
|
+
}
|
|
25115
|
+
try {
|
|
25116
|
+
return JSON.stringify(error);
|
|
25117
|
+
} catch {
|
|
25118
|
+
return String(error);
|
|
25119
|
+
}
|
|
25120
|
+
}
|
|
25121
|
+
function logInstrumentationError3(label, error) {
|
|
25122
|
+
console.error(`Error in ${label} instrumentation:`, error);
|
|
25123
|
+
}
|
|
25124
|
+
|
|
25125
|
+
// src/wrappers/langchain/callback-handler.ts
|
|
25126
|
+
var BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME = "BraintrustCallbackHandler";
|
|
25127
|
+
var BraintrustLangChainCallbackHandler = class {
|
|
25128
|
+
name = BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
|
|
25129
|
+
spans = /* @__PURE__ */ new Map();
|
|
25130
|
+
skippedRuns = /* @__PURE__ */ new Set();
|
|
25131
|
+
parent;
|
|
25132
|
+
rootRunId;
|
|
25133
|
+
options;
|
|
25134
|
+
startTimes = /* @__PURE__ */ new Map();
|
|
25135
|
+
firstTokenTimes = /* @__PURE__ */ new Map();
|
|
25136
|
+
ttftMs = /* @__PURE__ */ new Map();
|
|
25137
|
+
constructor(options) {
|
|
25138
|
+
this.parent = options?.parent;
|
|
25139
|
+
this.options = {
|
|
25140
|
+
debug: options?.debug ?? false,
|
|
25141
|
+
excludeMetadataProps: options?.excludeMetadataProps ?? /^(l[sc]_|langgraph_|__pregel_|checkpoint_ns)/,
|
|
25142
|
+
logger: options?.logger
|
|
25143
|
+
};
|
|
25144
|
+
}
|
|
25145
|
+
startSpan({
|
|
25146
|
+
runId,
|
|
25147
|
+
parentRunId,
|
|
25148
|
+
...args
|
|
25149
|
+
}) {
|
|
25150
|
+
if (this.spans.has(runId)) {
|
|
25151
|
+
return;
|
|
25152
|
+
}
|
|
25153
|
+
if (!parentRunId) {
|
|
25154
|
+
this.rootRunId = runId;
|
|
25155
|
+
}
|
|
25156
|
+
const tags = args.event?.tags;
|
|
25157
|
+
const spanAttributes = args.spanAttributes || {};
|
|
25158
|
+
spanAttributes.type = args.type || spanAttributes.type || "task";
|
|
25159
|
+
args.type = spanAttributes.type;
|
|
25160
|
+
const currentParent = (typeof this.parent === "function" ? this.parent() : this.parent) ?? currentSpan();
|
|
25161
|
+
let parentSpan;
|
|
25162
|
+
if (parentRunId && this.spans.has(parentRunId)) {
|
|
25163
|
+
parentSpan = this.spans.get(parentRunId);
|
|
25164
|
+
} else if (!Object.is(currentParent, NOOP_SPAN)) {
|
|
25165
|
+
parentSpan = currentParent;
|
|
25166
|
+
} else if (this.options.logger) {
|
|
25167
|
+
parentSpan = this.options.logger;
|
|
25168
|
+
} else {
|
|
25169
|
+
parentSpan = { startSpan };
|
|
25170
|
+
}
|
|
25171
|
+
args.event = {
|
|
25172
|
+
...args.event,
|
|
25173
|
+
tags: void 0,
|
|
25174
|
+
metadata: {
|
|
25175
|
+
...tags ? { tags } : {},
|
|
25176
|
+
...args.event?.metadata,
|
|
25177
|
+
braintrust: {
|
|
25178
|
+
integration_name: "langchain-js",
|
|
25179
|
+
sdk_language: "javascript"
|
|
25180
|
+
},
|
|
25181
|
+
run_id: runId,
|
|
25182
|
+
parent_run_id: parentRunId,
|
|
25183
|
+
...this.options.debug ? { runId, parentRunId } : {}
|
|
25184
|
+
}
|
|
25185
|
+
};
|
|
25186
|
+
let span = parentSpan.startSpan(args);
|
|
25187
|
+
if (!Object.is(this.options.logger, NOOP_SPAN) && Object.is(span, NOOP_SPAN)) {
|
|
25188
|
+
span = initLogger().startSpan(args);
|
|
25189
|
+
}
|
|
25190
|
+
this.spans.set(runId, span);
|
|
25191
|
+
}
|
|
25192
|
+
endSpan({
|
|
25193
|
+
runId,
|
|
25194
|
+
parentRunId,
|
|
25195
|
+
tags,
|
|
25196
|
+
metadata,
|
|
25197
|
+
...args
|
|
25198
|
+
}) {
|
|
25199
|
+
if (!this.spans.has(runId)) {
|
|
25200
|
+
return;
|
|
25201
|
+
}
|
|
25202
|
+
if (this.skippedRuns.has(runId)) {
|
|
25203
|
+
this.skippedRuns.delete(runId);
|
|
25204
|
+
return;
|
|
25205
|
+
}
|
|
25206
|
+
const span = this.spans.get(runId);
|
|
25207
|
+
this.spans.delete(runId);
|
|
25208
|
+
if (runId === this.rootRunId) {
|
|
25209
|
+
this.rootRunId = void 0;
|
|
25210
|
+
}
|
|
25211
|
+
span.log({ ...args, metadata: { tags, ...metadata } });
|
|
25212
|
+
span.end();
|
|
25213
|
+
}
|
|
25214
|
+
async handleLLMStart(llm, prompts, runId, parentRunId, extraParams, tags, metadata, runName) {
|
|
25215
|
+
this.startSpan({
|
|
25216
|
+
runId,
|
|
25217
|
+
parentRunId,
|
|
25218
|
+
name: runName ?? getSerializedName(llm) ?? "LLM",
|
|
25219
|
+
type: "llm",
|
|
25220
|
+
event: {
|
|
25221
|
+
input: prompts,
|
|
25222
|
+
tags,
|
|
25223
|
+
metadata: {
|
|
25224
|
+
serialized: llm,
|
|
25225
|
+
name: runName,
|
|
25226
|
+
metadata,
|
|
25227
|
+
...extraParams
|
|
25228
|
+
}
|
|
25229
|
+
}
|
|
25230
|
+
});
|
|
25231
|
+
}
|
|
25232
|
+
async handleLLMError(err, runId, parentRunId, tags) {
|
|
25233
|
+
this.endSpan({ runId, parentRunId, error: err, tags });
|
|
25234
|
+
}
|
|
25235
|
+
async handleLLMEnd(output, runId, parentRunId, tags) {
|
|
25236
|
+
const metrics = getMetricsFromResponse(output);
|
|
25237
|
+
const modelName2 = getModelNameFromResponse(output);
|
|
25238
|
+
const ttft = this.ttftMs.get(runId);
|
|
25239
|
+
if (ttft !== void 0) {
|
|
25240
|
+
metrics.time_to_first_token = ttft;
|
|
25241
|
+
}
|
|
25242
|
+
this.startTimes.delete(runId);
|
|
25243
|
+
this.firstTokenTimes.delete(runId);
|
|
25244
|
+
this.ttftMs.delete(runId);
|
|
25245
|
+
this.endSpan({
|
|
25246
|
+
runId,
|
|
25247
|
+
parentRunId,
|
|
25248
|
+
output,
|
|
25249
|
+
metrics,
|
|
25250
|
+
tags,
|
|
25251
|
+
metadata: {
|
|
25252
|
+
model: modelName2
|
|
25253
|
+
}
|
|
25254
|
+
});
|
|
25255
|
+
}
|
|
25256
|
+
async handleChatModelStart(llm, messages, runId, parentRunId, extraParams, tags, metadata, runName) {
|
|
25257
|
+
this.startTimes.set(runId, Date.now());
|
|
25258
|
+
this.firstTokenTimes.delete(runId);
|
|
25259
|
+
this.ttftMs.delete(runId);
|
|
25260
|
+
this.startSpan({
|
|
25261
|
+
runId,
|
|
25262
|
+
parentRunId,
|
|
25263
|
+
name: runName ?? getSerializedName(llm) ?? "Chat Model",
|
|
25264
|
+
type: "llm",
|
|
25265
|
+
event: {
|
|
25266
|
+
input: messages,
|
|
25267
|
+
tags,
|
|
25268
|
+
metadata: {
|
|
25269
|
+
serialized: llm,
|
|
25270
|
+
name: runName,
|
|
25271
|
+
metadata,
|
|
25272
|
+
...extraParams
|
|
25273
|
+
}
|
|
25274
|
+
}
|
|
25275
|
+
});
|
|
25276
|
+
}
|
|
25277
|
+
async handleChainStart(chain, inputs, runId, parentRunId, tags, metadata, runType, runName) {
|
|
25278
|
+
if (tags?.includes("langsmith:hidden")) {
|
|
25279
|
+
this.skippedRuns.add(runId);
|
|
25280
|
+
return;
|
|
25281
|
+
}
|
|
25282
|
+
this.startSpan({
|
|
25283
|
+
runId,
|
|
25284
|
+
parentRunId,
|
|
25285
|
+
name: runName ?? getSerializedName(chain) ?? "Chain",
|
|
25286
|
+
event: {
|
|
25287
|
+
input: inputs,
|
|
25288
|
+
tags,
|
|
25289
|
+
metadata: {
|
|
25290
|
+
serialized: chain,
|
|
25291
|
+
name: runName,
|
|
25292
|
+
metadata,
|
|
25293
|
+
run_type: runType
|
|
25294
|
+
}
|
|
25295
|
+
}
|
|
25296
|
+
});
|
|
25297
|
+
}
|
|
25298
|
+
async handleChainError(err, runId, parentRunId, tags, kwargs) {
|
|
25299
|
+
this.endSpan({ runId, parentRunId, error: err, tags, metadata: kwargs });
|
|
25300
|
+
}
|
|
25301
|
+
async handleChainEnd(outputs, runId, parentRunId, tags, kwargs) {
|
|
25302
|
+
this.endSpan({
|
|
25303
|
+
runId,
|
|
25304
|
+
parentRunId,
|
|
25305
|
+
tags,
|
|
25306
|
+
output: outputs,
|
|
25307
|
+
metadata: { ...kwargs }
|
|
25308
|
+
});
|
|
25309
|
+
}
|
|
25310
|
+
async handleToolStart(tool, input, runId, parentRunId, tags, metadata, runName) {
|
|
25311
|
+
this.startSpan({
|
|
25312
|
+
runId,
|
|
25313
|
+
parentRunId,
|
|
25314
|
+
name: runName ?? getSerializedName(tool) ?? "Tool",
|
|
25315
|
+
type: "llm",
|
|
25316
|
+
event: {
|
|
25317
|
+
input: safeJsonParse(input),
|
|
25318
|
+
tags,
|
|
25319
|
+
metadata: {
|
|
25320
|
+
metadata,
|
|
25321
|
+
serialized: tool,
|
|
25322
|
+
input_str: input,
|
|
25323
|
+
input: safeJsonParse(input),
|
|
25324
|
+
name: runName
|
|
25325
|
+
}
|
|
25326
|
+
}
|
|
25327
|
+
});
|
|
25328
|
+
}
|
|
25329
|
+
async handleToolError(err, runId, parentRunId, tags) {
|
|
25330
|
+
this.endSpan({ runId, parentRunId, error: err, tags });
|
|
25331
|
+
}
|
|
25332
|
+
async handleToolEnd(output, runId, parentRunId, tags) {
|
|
25333
|
+
this.endSpan({ runId, parentRunId, output, tags });
|
|
25334
|
+
}
|
|
25335
|
+
async handleAgentAction(action, runId, parentRunId, tags) {
|
|
25336
|
+
this.startSpan({
|
|
25337
|
+
runId,
|
|
25338
|
+
parentRunId,
|
|
25339
|
+
type: "llm",
|
|
25340
|
+
name: typeof action.tool === "string" ? action.tool : "Agent",
|
|
25341
|
+
event: {
|
|
25342
|
+
input: action,
|
|
25343
|
+
tags
|
|
25344
|
+
}
|
|
25345
|
+
});
|
|
25346
|
+
}
|
|
25347
|
+
async handleAgentEnd(action, runId, parentRunId, tags) {
|
|
25348
|
+
this.endSpan({ runId, parentRunId, output: action, tags });
|
|
25349
|
+
}
|
|
25350
|
+
async handleRetrieverStart(retriever, query, runId, parentRunId, tags, metadata, name) {
|
|
25351
|
+
this.startSpan({
|
|
25352
|
+
runId,
|
|
25353
|
+
parentRunId,
|
|
25354
|
+
name: name ?? getSerializedName(retriever) ?? "Retriever",
|
|
25355
|
+
type: "function",
|
|
25356
|
+
event: {
|
|
25357
|
+
input: query,
|
|
25358
|
+
tags,
|
|
25359
|
+
metadata: {
|
|
25360
|
+
serialized: retriever,
|
|
25361
|
+
metadata,
|
|
25362
|
+
name
|
|
25363
|
+
}
|
|
25364
|
+
}
|
|
25365
|
+
});
|
|
25366
|
+
}
|
|
25367
|
+
async handleRetrieverEnd(documents, runId, parentRunId, tags) {
|
|
25368
|
+
this.endSpan({ runId, parentRunId, output: documents, tags });
|
|
25369
|
+
}
|
|
25370
|
+
async handleRetrieverError(err, runId, parentRunId, tags) {
|
|
25371
|
+
this.endSpan({ runId, parentRunId, error: err, tags });
|
|
25372
|
+
}
|
|
25373
|
+
async handleLLMNewToken(_token, _idx, runId, _parentRunId, _tags) {
|
|
25374
|
+
if (!this.firstTokenTimes.has(runId)) {
|
|
25375
|
+
const now2 = Date.now();
|
|
25376
|
+
this.firstTokenTimes.set(runId, now2);
|
|
25377
|
+
const start = this.startTimes.get(runId);
|
|
25378
|
+
if (start !== void 0) {
|
|
25379
|
+
this.ttftMs.set(runId, (now2 - start) / 1e3);
|
|
25380
|
+
}
|
|
25381
|
+
}
|
|
25382
|
+
}
|
|
25383
|
+
};
|
|
25384
|
+
function getSerializedName(serialized) {
|
|
25385
|
+
if (typeof serialized.name === "string") {
|
|
25386
|
+
return serialized.name;
|
|
25387
|
+
}
|
|
25388
|
+
const lastIdPart = serialized.id?.at(-1);
|
|
25389
|
+
return typeof lastIdPart === "string" ? lastIdPart : void 0;
|
|
25390
|
+
}
|
|
25391
|
+
function cleanObject(obj) {
|
|
25392
|
+
return Object.fromEntries(
|
|
25393
|
+
Object.entries(obj).filter(([, value]) => {
|
|
25394
|
+
if (typeof value !== "number") {
|
|
25395
|
+
return false;
|
|
25396
|
+
}
|
|
25397
|
+
return Number.isFinite(value);
|
|
25398
|
+
})
|
|
25399
|
+
);
|
|
25400
|
+
}
|
|
25401
|
+
function walkGenerations(response) {
|
|
25402
|
+
const result = [];
|
|
25403
|
+
const generations = response.generations || [];
|
|
25404
|
+
for (const batch of generations) {
|
|
25405
|
+
if (Array.isArray(batch)) {
|
|
25406
|
+
for (const generation of batch) {
|
|
25407
|
+
if (isRecord(generation)) {
|
|
25408
|
+
result.push(generation);
|
|
25409
|
+
}
|
|
25410
|
+
}
|
|
25411
|
+
} else if (isRecord(batch)) {
|
|
25412
|
+
result.push(batch);
|
|
25413
|
+
}
|
|
25414
|
+
}
|
|
25415
|
+
return result;
|
|
25416
|
+
}
|
|
25417
|
+
function getModelNameFromResponse(response) {
|
|
25418
|
+
for (const generation of walkGenerations(response)) {
|
|
25419
|
+
const message = generation.message;
|
|
25420
|
+
if (!isRecord(message)) {
|
|
25421
|
+
continue;
|
|
25422
|
+
}
|
|
25423
|
+
const responseMetadata = message.response_metadata;
|
|
25424
|
+
if (!isRecord(responseMetadata)) {
|
|
25425
|
+
continue;
|
|
25426
|
+
}
|
|
25427
|
+
const modelName3 = responseMetadata.model_name ?? responseMetadata.model;
|
|
25428
|
+
if (typeof modelName3 === "string") {
|
|
25429
|
+
return modelName3;
|
|
25430
|
+
}
|
|
25431
|
+
}
|
|
25432
|
+
const llmOutput = response.llmOutput || {};
|
|
25433
|
+
const modelName2 = llmOutput.model_name ?? llmOutput.model;
|
|
25434
|
+
return typeof modelName2 === "string" ? modelName2 : void 0;
|
|
25435
|
+
}
|
|
25436
|
+
function getMetricsFromResponse(response) {
|
|
25437
|
+
for (const generation of walkGenerations(response)) {
|
|
25438
|
+
const message = generation.message;
|
|
25439
|
+
if (!isRecord(message)) {
|
|
25440
|
+
continue;
|
|
25441
|
+
}
|
|
25442
|
+
const usageMetadata = message.usage_metadata;
|
|
25443
|
+
if (!isRecord(usageMetadata)) {
|
|
25444
|
+
continue;
|
|
25445
|
+
}
|
|
25446
|
+
const inputTokenDetails = usageMetadata.input_token_details;
|
|
25447
|
+
return cleanObject({
|
|
25448
|
+
total_tokens: usageMetadata.total_tokens,
|
|
25449
|
+
prompt_tokens: usageMetadata.input_tokens,
|
|
25450
|
+
completion_tokens: usageMetadata.output_tokens,
|
|
25451
|
+
prompt_cache_creation_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_creation : void 0,
|
|
25452
|
+
prompt_cached_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_read : void 0
|
|
25453
|
+
});
|
|
25454
|
+
}
|
|
25455
|
+
const llmOutput = response.llmOutput || {};
|
|
25456
|
+
const tokenUsage = isRecord(llmOutput.tokenUsage) ? llmOutput.tokenUsage : isRecord(llmOutput.estimatedTokens) ? llmOutput.estimatedTokens : {};
|
|
25457
|
+
return cleanObject({
|
|
25458
|
+
total_tokens: tokenUsage.totalTokens,
|
|
25459
|
+
prompt_tokens: tokenUsage.promptTokens,
|
|
25460
|
+
completion_tokens: tokenUsage.completionTokens
|
|
25461
|
+
});
|
|
25462
|
+
}
|
|
25463
|
+
function safeJsonParse(input) {
|
|
25464
|
+
try {
|
|
25465
|
+
return JSON.parse(input);
|
|
25466
|
+
} catch {
|
|
25467
|
+
return input;
|
|
25468
|
+
}
|
|
25469
|
+
}
|
|
25470
|
+
function isRecord(value) {
|
|
25471
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
25472
|
+
}
|
|
25473
|
+
|
|
25474
|
+
// src/instrumentation/plugins/langchain-channels.ts
|
|
25475
|
+
var langChainChannels = defineChannels("@langchain/core", {
|
|
25476
|
+
configure: channel({
|
|
25477
|
+
channelName: "CallbackManager.configure",
|
|
25478
|
+
kind: "sync-stream"
|
|
25479
|
+
}),
|
|
25480
|
+
configureSync: channel({
|
|
25481
|
+
channelName: "CallbackManager._configureSync",
|
|
25482
|
+
kind: "sync-stream"
|
|
25483
|
+
})
|
|
25484
|
+
});
|
|
25485
|
+
|
|
25486
|
+
// src/instrumentation/plugins/langchain-plugin.ts
|
|
25487
|
+
var LangChainPlugin = class extends BasePlugin {
|
|
25488
|
+
injectedManagers = /* @__PURE__ */ new WeakSet();
|
|
25489
|
+
onEnable() {
|
|
25490
|
+
this.subscribeToConfigure(langChainChannels.configure);
|
|
25491
|
+
this.subscribeToConfigure(langChainChannels.configureSync);
|
|
25492
|
+
}
|
|
25493
|
+
onDisable() {
|
|
25494
|
+
for (const unsubscribe of this.unsubscribers) {
|
|
25495
|
+
unsubscribe();
|
|
25496
|
+
}
|
|
25497
|
+
this.unsubscribers = [];
|
|
25498
|
+
this.injectedManagers = /* @__PURE__ */ new WeakSet();
|
|
25499
|
+
}
|
|
25500
|
+
subscribeToConfigure(channel2) {
|
|
25501
|
+
const tracingChannel2 = channel2.tracingChannel();
|
|
25502
|
+
const handlers = {
|
|
25503
|
+
start: (event) => {
|
|
25504
|
+
injectHandlerIntoArguments(event.arguments);
|
|
25505
|
+
},
|
|
25506
|
+
end: (event) => {
|
|
25507
|
+
this.injectHandler(event.result);
|
|
25508
|
+
}
|
|
25509
|
+
};
|
|
25510
|
+
tracingChannel2.subscribe(handlers);
|
|
25511
|
+
this.unsubscribers.push(() => {
|
|
25512
|
+
tracingChannel2.unsubscribe(handlers);
|
|
25513
|
+
});
|
|
25514
|
+
}
|
|
25515
|
+
injectHandler(result) {
|
|
25516
|
+
if (!isCallbackManager(result)) {
|
|
25517
|
+
return;
|
|
25518
|
+
}
|
|
25519
|
+
if (this.injectedManagers.has(result) || hasBraintrustHandler(result)) {
|
|
25520
|
+
return;
|
|
25521
|
+
}
|
|
25522
|
+
try {
|
|
25523
|
+
result.addHandler(new BraintrustLangChainCallbackHandler(), true);
|
|
25524
|
+
this.injectedManagers.add(result);
|
|
25525
|
+
} catch {
|
|
25526
|
+
}
|
|
25527
|
+
}
|
|
25528
|
+
};
|
|
25529
|
+
function isCallbackManager(value) {
|
|
25530
|
+
if (typeof value !== "object" || value === null) {
|
|
25531
|
+
return false;
|
|
25532
|
+
}
|
|
25533
|
+
const maybeManager = value;
|
|
25534
|
+
return typeof maybeManager.addHandler === "function";
|
|
25535
|
+
}
|
|
25536
|
+
function hasBraintrustHandler(manager) {
|
|
25537
|
+
return manager.handlers?.some((handler) => {
|
|
25538
|
+
if (typeof handler !== "object" || handler === null) {
|
|
25539
|
+
return false;
|
|
25540
|
+
}
|
|
25541
|
+
const name = Reflect.get(handler, "name");
|
|
25542
|
+
return name === BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
|
|
25543
|
+
}) ?? false;
|
|
25544
|
+
}
|
|
25545
|
+
function injectHandlerIntoArguments(args) {
|
|
25546
|
+
if (!isWritableArgumentsObject(args)) {
|
|
25547
|
+
return;
|
|
25548
|
+
}
|
|
25549
|
+
const inheritedHandlers = Reflect.get(args, "0");
|
|
25550
|
+
const handler = new BraintrustLangChainCallbackHandler();
|
|
25551
|
+
if (inheritedHandlers === void 0 || inheritedHandlers === null) {
|
|
25552
|
+
Reflect.set(args, "0", [handler]);
|
|
25553
|
+
return;
|
|
25554
|
+
}
|
|
25555
|
+
if (Array.isArray(inheritedHandlers)) {
|
|
25556
|
+
if (!inheritedHandlers.some(isBraintrustHandler)) {
|
|
25557
|
+
inheritedHandlers.push(handler);
|
|
25558
|
+
}
|
|
25559
|
+
}
|
|
25560
|
+
}
|
|
25561
|
+
function isWritableArgumentsObject(args) {
|
|
25562
|
+
return typeof args === "object" && args !== null;
|
|
25563
|
+
}
|
|
25564
|
+
function isBraintrustHandler(handler) {
|
|
25565
|
+
if (typeof handler !== "object" || handler === null) {
|
|
25566
|
+
return false;
|
|
25567
|
+
}
|
|
25568
|
+
return Reflect.get(handler, "name") === BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
|
|
25569
|
+
}
|
|
25570
|
+
|
|
25571
|
+
// src/instrumentation/braintrust-plugin.ts
|
|
25572
|
+
function getIntegrationConfig(integrations, key) {
|
|
25573
|
+
return integrations[key];
|
|
25574
|
+
}
|
|
25575
|
+
var BraintrustPlugin = class extends BasePlugin {
|
|
25576
|
+
config;
|
|
25577
|
+
openaiPlugin = null;
|
|
25578
|
+
openAICodexPlugin = null;
|
|
25579
|
+
anthropicPlugin = null;
|
|
25580
|
+
aiSDKPlugin = null;
|
|
25581
|
+
claudeAgentSDKPlugin = null;
|
|
25582
|
+
cursorSDKPlugin = null;
|
|
25583
|
+
openAIAgentsPlugin = null;
|
|
25584
|
+
googleGenAIPlugin = null;
|
|
25585
|
+
huggingFacePlugin = null;
|
|
25586
|
+
openRouterPlugin = null;
|
|
25587
|
+
openRouterAgentPlugin = null;
|
|
25588
|
+
mistralPlugin = null;
|
|
25589
|
+
googleADKPlugin = null;
|
|
25590
|
+
coherePlugin = null;
|
|
25591
|
+
groqPlugin = null;
|
|
25592
|
+
genkitPlugin = null;
|
|
25593
|
+
gitHubCopilotPlugin = null;
|
|
25594
|
+
fluePlugin = null;
|
|
25595
|
+
langChainPlugin = null;
|
|
25596
|
+
constructor(config = {}) {
|
|
25597
|
+
super();
|
|
25598
|
+
this.config = config;
|
|
25599
|
+
}
|
|
25600
|
+
onEnable() {
|
|
25601
|
+
const integrations = this.config.integrations || {};
|
|
25602
|
+
if (integrations.openai !== false) {
|
|
25603
|
+
this.openaiPlugin = new OpenAIPlugin();
|
|
25604
|
+
this.openaiPlugin.enable();
|
|
25605
|
+
}
|
|
25606
|
+
if (integrations.openaiCodexSDK !== false) {
|
|
25607
|
+
this.openAICodexPlugin = new OpenAICodexPlugin();
|
|
25608
|
+
this.openAICodexPlugin.enable();
|
|
25609
|
+
}
|
|
25610
|
+
if (integrations.anthropic !== false) {
|
|
25611
|
+
this.anthropicPlugin = new AnthropicPlugin();
|
|
25612
|
+
this.anthropicPlugin.enable();
|
|
25613
|
+
}
|
|
25614
|
+
if (integrations.aisdk !== false && integrations.vercel !== false) {
|
|
25615
|
+
this.aiSDKPlugin = new AISDKPlugin();
|
|
25616
|
+
this.aiSDKPlugin.enable();
|
|
25617
|
+
}
|
|
25618
|
+
if (integrations.claudeAgentSDK !== false) {
|
|
25619
|
+
this.claudeAgentSDKPlugin = new ClaudeAgentSDKPlugin();
|
|
23407
25620
|
this.claudeAgentSDKPlugin.enable();
|
|
23408
25621
|
}
|
|
23409
25622
|
if (integrations.cursorSDK !== false && integrations.cursor !== false) {
|
|
23410
25623
|
this.cursorSDKPlugin = new CursorSDKPlugin();
|
|
23411
25624
|
this.cursorSDKPlugin.enable();
|
|
23412
25625
|
}
|
|
25626
|
+
if (integrations.openAIAgents !== false) {
|
|
25627
|
+
this.openAIAgentsPlugin = new OpenAIAgentsPlugin();
|
|
25628
|
+
this.openAIAgentsPlugin.enable();
|
|
25629
|
+
}
|
|
23413
25630
|
if (integrations.googleGenAI !== false && integrations.google !== false) {
|
|
23414
25631
|
this.googleGenAIPlugin = new GoogleGenAIPlugin();
|
|
23415
25632
|
this.googleGenAIPlugin.enable();
|
|
@@ -23450,6 +25667,14 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
23450
25667
|
this.gitHubCopilotPlugin = new GitHubCopilotPlugin();
|
|
23451
25668
|
this.gitHubCopilotPlugin.enable();
|
|
23452
25669
|
}
|
|
25670
|
+
if (getIntegrationConfig(integrations, "flue") !== false) {
|
|
25671
|
+
this.fluePlugin = new FluePlugin();
|
|
25672
|
+
this.fluePlugin.enable();
|
|
25673
|
+
}
|
|
25674
|
+
if (integrations.langchain !== false && integrations.langgraph !== false) {
|
|
25675
|
+
this.langChainPlugin = new LangChainPlugin();
|
|
25676
|
+
this.langChainPlugin.enable();
|
|
25677
|
+
}
|
|
23453
25678
|
}
|
|
23454
25679
|
onDisable() {
|
|
23455
25680
|
if (this.openaiPlugin) {
|
|
@@ -23476,6 +25701,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
23476
25701
|
this.cursorSDKPlugin.disable();
|
|
23477
25702
|
this.cursorSDKPlugin = null;
|
|
23478
25703
|
}
|
|
25704
|
+
if (this.openAIAgentsPlugin) {
|
|
25705
|
+
this.openAIAgentsPlugin.disable();
|
|
25706
|
+
this.openAIAgentsPlugin = null;
|
|
25707
|
+
}
|
|
23479
25708
|
if (this.googleGenAIPlugin) {
|
|
23480
25709
|
this.googleGenAIPlugin.disable();
|
|
23481
25710
|
this.googleGenAIPlugin = null;
|
|
@@ -23516,9 +25745,104 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
23516
25745
|
this.gitHubCopilotPlugin.disable();
|
|
23517
25746
|
this.gitHubCopilotPlugin = null;
|
|
23518
25747
|
}
|
|
25748
|
+
if (this.fluePlugin) {
|
|
25749
|
+
this.fluePlugin.disable();
|
|
25750
|
+
this.fluePlugin = null;
|
|
25751
|
+
}
|
|
25752
|
+
if (this.langChainPlugin) {
|
|
25753
|
+
this.langChainPlugin.disable();
|
|
25754
|
+
this.langChainPlugin = null;
|
|
25755
|
+
}
|
|
23519
25756
|
}
|
|
23520
25757
|
};
|
|
23521
25758
|
|
|
25759
|
+
// src/instrumentation/config.ts
|
|
25760
|
+
var envIntegrationAliases = {
|
|
25761
|
+
openai: "openai",
|
|
25762
|
+
"openai-codex": "openaiCodexSDK",
|
|
25763
|
+
"openai-codex-sdk": "openaiCodexSDK",
|
|
25764
|
+
openaicodexsdk: "openaiCodexSDK",
|
|
25765
|
+
codex: "openaiCodexSDK",
|
|
25766
|
+
"codex-sdk": "openaiCodexSDK",
|
|
25767
|
+
anthropic: "anthropic",
|
|
25768
|
+
aisdk: "aisdk",
|
|
25769
|
+
"ai-sdk": "aisdk",
|
|
25770
|
+
"vercel-ai": "aisdk",
|
|
25771
|
+
vercel: "vercel",
|
|
25772
|
+
claudeagentsdk: "claudeAgentSDK",
|
|
25773
|
+
"claude-agent-sdk": "claudeAgentSDK",
|
|
25774
|
+
cursor: "cursor",
|
|
25775
|
+
"cursor-sdk": "cursorSDK",
|
|
25776
|
+
cursorsdk: "cursorSDK",
|
|
25777
|
+
flue: "flue",
|
|
25778
|
+
"flue-runtime": "flue",
|
|
25779
|
+
"openai-agents": "openAIAgents",
|
|
25780
|
+
openaiagents: "openAIAgents",
|
|
25781
|
+
"openai-agents-core": "openAIAgents",
|
|
25782
|
+
openaiagentscore: "openAIAgents",
|
|
25783
|
+
google: "google",
|
|
25784
|
+
"google-genai": "googleGenAI",
|
|
25785
|
+
googlegenai: "googleGenAI",
|
|
25786
|
+
huggingface: "huggingface",
|
|
25787
|
+
openrouter: "openrouter",
|
|
25788
|
+
openrouteragent: "openrouterAgent",
|
|
25789
|
+
"openrouter-agent": "openrouterAgent",
|
|
25790
|
+
mistral: "mistral",
|
|
25791
|
+
googleadk: "googleADK",
|
|
25792
|
+
"google-adk": "googleADK",
|
|
25793
|
+
cohere: "cohere",
|
|
25794
|
+
groq: "groq",
|
|
25795
|
+
"groq-sdk": "groq",
|
|
25796
|
+
genkit: "genkit",
|
|
25797
|
+
"firebase-genkit": "genkit",
|
|
25798
|
+
githubcopilot: "gitHubCopilot",
|
|
25799
|
+
"github-copilot": "gitHubCopilot",
|
|
25800
|
+
"copilot-sdk": "gitHubCopilot",
|
|
25801
|
+
langchain: "langchain",
|
|
25802
|
+
"langchain-js": "langchain",
|
|
25803
|
+
"@langchain": "langchain",
|
|
25804
|
+
langgraph: "langgraph"
|
|
25805
|
+
};
|
|
25806
|
+
function getDefaultInstrumentationIntegrations() {
|
|
25807
|
+
return {
|
|
25808
|
+
openai: true,
|
|
25809
|
+
openaiCodexSDK: true,
|
|
25810
|
+
anthropic: true,
|
|
25811
|
+
vercel: true,
|
|
25812
|
+
aisdk: true,
|
|
25813
|
+
google: true,
|
|
25814
|
+
googleGenAI: true,
|
|
25815
|
+
googleADK: true,
|
|
25816
|
+
huggingface: true,
|
|
25817
|
+
claudeAgentSDK: true,
|
|
25818
|
+
cursor: true,
|
|
25819
|
+
cursorSDK: true,
|
|
25820
|
+
flue: true,
|
|
25821
|
+
openAIAgents: true,
|
|
25822
|
+
openrouter: true,
|
|
25823
|
+
openrouterAgent: true,
|
|
25824
|
+
mistral: true,
|
|
25825
|
+
cohere: true,
|
|
25826
|
+
groq: true,
|
|
25827
|
+
genkit: true,
|
|
25828
|
+
gitHubCopilot: true,
|
|
25829
|
+
langchain: true,
|
|
25830
|
+
langgraph: true
|
|
25831
|
+
};
|
|
25832
|
+
}
|
|
25833
|
+
function readDisabledInstrumentationEnvConfig(disabledList) {
|
|
25834
|
+
const integrations = {};
|
|
25835
|
+
if (disabledList) {
|
|
25836
|
+
for (const value of disabledList.split(",")) {
|
|
25837
|
+
const sdk = value.trim().toLowerCase();
|
|
25838
|
+
if (sdk.length > 0) {
|
|
25839
|
+
integrations[envIntegrationAliases[sdk] ?? sdk] = false;
|
|
25840
|
+
}
|
|
25841
|
+
}
|
|
25842
|
+
}
|
|
25843
|
+
return { integrations };
|
|
25844
|
+
}
|
|
25845
|
+
|
|
23522
25846
|
// src/instrumentation/registry.ts
|
|
23523
25847
|
var REGISTRY_STATE_KEY = /* @__PURE__ */ Symbol.for("braintrust.registry");
|
|
23524
25848
|
function getSharedState() {
|
|
@@ -23597,50 +25921,16 @@ var PluginRegistry = class {
|
|
|
23597
25921
|
* Get default configuration (all integrations enabled).
|
|
23598
25922
|
*/
|
|
23599
25923
|
getDefaultConfig() {
|
|
23600
|
-
return
|
|
23601
|
-
openai: true,
|
|
23602
|
-
openaiCodexSDK: true,
|
|
23603
|
-
anthropic: true,
|
|
23604
|
-
vercel: true,
|
|
23605
|
-
aisdk: true,
|
|
23606
|
-
google: true,
|
|
23607
|
-
googleGenAI: true,
|
|
23608
|
-
googleADK: true,
|
|
23609
|
-
huggingface: true,
|
|
23610
|
-
claudeAgentSDK: true,
|
|
23611
|
-
cursor: true,
|
|
23612
|
-
cursorSDK: true,
|
|
23613
|
-
openrouter: true,
|
|
23614
|
-
openrouterAgent: true,
|
|
23615
|
-
mistral: true,
|
|
23616
|
-
cohere: true,
|
|
23617
|
-
groq: true,
|
|
23618
|
-
genkit: true,
|
|
23619
|
-
gitHubCopilot: true
|
|
23620
|
-
};
|
|
25924
|
+
return getDefaultInstrumentationIntegrations();
|
|
23621
25925
|
}
|
|
23622
25926
|
/**
|
|
23623
25927
|
* Read configuration from environment variables.
|
|
23624
25928
|
* Supports: BRAINTRUST_DISABLE_INSTRUMENTATION=openai,anthropic,...
|
|
23625
25929
|
*/
|
|
23626
25930
|
readEnvConfig() {
|
|
23627
|
-
|
|
23628
|
-
|
|
23629
|
-
|
|
23630
|
-
const disabled = disabledList.split(",").map((s) => s.trim().toLowerCase()).filter((s) => s.length > 0);
|
|
23631
|
-
for (const sdk of disabled) {
|
|
23632
|
-
if (sdk === "cursor-sdk") {
|
|
23633
|
-
integrations.cursorSDK = false;
|
|
23634
|
-
} else if (sdk === "githubcopilot" || sdk === "github-copilot" || sdk === "copilot-sdk") {
|
|
23635
|
-
integrations.gitHubCopilot = false;
|
|
23636
|
-
} else if (sdk === "openai-codex-sdk") {
|
|
23637
|
-
integrations.openaiCodexSDK = false;
|
|
23638
|
-
} else {
|
|
23639
|
-
integrations[sdk] = false;
|
|
23640
|
-
}
|
|
23641
|
-
}
|
|
23642
|
-
}
|
|
23643
|
-
return { integrations };
|
|
25931
|
+
return readDisabledInstrumentationEnvConfig(
|
|
25932
|
+
isomorph_default.getEnv("BRAINTRUST_DISABLE_INSTRUMENTATION")
|
|
25933
|
+
);
|
|
23644
25934
|
}
|
|
23645
25935
|
};
|
|
23646
25936
|
var registry = new PluginRegistry();
|
|
@@ -23755,6 +26045,10 @@ function configureBrowser() {
|
|
|
23755
26045
|
}
|
|
23756
26046
|
return process.env[name];
|
|
23757
26047
|
};
|
|
26048
|
+
isomorph_default.getBraintrustApiKey = async () => {
|
|
26049
|
+
const value = isomorph_default.getEnv("BRAINTRUST_API_KEY");
|
|
26050
|
+
return value?.trim() ? value : void 0;
|
|
26051
|
+
};
|
|
23758
26052
|
isomorph_default.hash = (data) => {
|
|
23759
26053
|
let hash = 0;
|
|
23760
26054
|
for (let i = 0; i < data.length; i++) {
|
|
@@ -23776,8 +26070,10 @@ __export(exports_exports, {
|
|
|
23776
26070
|
Attachment: () => Attachment,
|
|
23777
26071
|
AttachmentReference: () => AttachmentReference,
|
|
23778
26072
|
BRAINTRUST_CURRENT_SPAN_STORE: () => BRAINTRUST_CURRENT_SPAN_STORE,
|
|
26073
|
+
BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME: () => BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME,
|
|
23779
26074
|
BaseAttachment: () => BaseAttachment,
|
|
23780
26075
|
BaseExperiment: () => BaseExperiment,
|
|
26076
|
+
BraintrustLangChainCallbackHandler: () => BraintrustLangChainCallbackHandler,
|
|
23781
26077
|
BraintrustMiddleware: () => BraintrustMiddleware,
|
|
23782
26078
|
BraintrustState: () => BraintrustState,
|
|
23783
26079
|
BraintrustStream: () => BraintrustStream,
|
|
@@ -23788,6 +26084,7 @@ __export(exports_exports, {
|
|
|
23788
26084
|
DEFAULT_FETCH_BATCH_SIZE: () => DEFAULT_FETCH_BATCH_SIZE,
|
|
23789
26085
|
DEFAULT_MAX_REQUEST_SIZE: () => DEFAULT_MAX_REQUEST_SIZE,
|
|
23790
26086
|
Dataset: () => Dataset2,
|
|
26087
|
+
DatasetPipeline: () => DatasetPipeline,
|
|
23791
26088
|
ERR_PERMALINK: () => ERR_PERMALINK,
|
|
23792
26089
|
Eval: () => Eval,
|
|
23793
26090
|
EvalResultWithSummary: () => EvalResultWithSummary,
|
|
@@ -23903,6 +26200,8 @@ __export(exports_exports, {
|
|
|
23903
26200
|
wrapCohere: () => wrapCohere,
|
|
23904
26201
|
wrapCopilotClient: () => wrapCopilotClient,
|
|
23905
26202
|
wrapCursorSDK: () => wrapCursorSDK,
|
|
26203
|
+
wrapFlueContext: () => wrapFlueContext,
|
|
26204
|
+
wrapFlueSession: () => wrapFlueSession,
|
|
23906
26205
|
wrapGenkit: () => wrapGenkit,
|
|
23907
26206
|
wrapGoogleADK: () => wrapGoogleADK,
|
|
23908
26207
|
wrapGoogleGenAI: () => wrapGoogleGenAI,
|
|
@@ -25002,7 +27301,7 @@ function extractModelParameters(params, excludeKeys) {
|
|
|
25002
27301
|
}
|
|
25003
27302
|
return modelParams;
|
|
25004
27303
|
}
|
|
25005
|
-
function
|
|
27304
|
+
function getNumberProperty3(obj, key) {
|
|
25006
27305
|
if (!obj || typeof obj !== "object" || !(key in obj)) {
|
|
25007
27306
|
return void 0;
|
|
25008
27307
|
}
|
|
@@ -25011,31 +27310,31 @@ function getNumberProperty2(obj, key) {
|
|
|
25011
27310
|
}
|
|
25012
27311
|
function normalizeUsageMetrics(usage, provider, providerMetadata) {
|
|
25013
27312
|
const metrics = {};
|
|
25014
|
-
const inputTokens =
|
|
27313
|
+
const inputTokens = getNumberProperty3(usage, "inputTokens");
|
|
25015
27314
|
if (inputTokens !== void 0) {
|
|
25016
27315
|
metrics.prompt_tokens = inputTokens;
|
|
25017
27316
|
}
|
|
25018
|
-
const outputTokens =
|
|
27317
|
+
const outputTokens = getNumberProperty3(usage, "outputTokens");
|
|
25019
27318
|
if (outputTokens !== void 0) {
|
|
25020
27319
|
metrics.completion_tokens = outputTokens;
|
|
25021
27320
|
}
|
|
25022
|
-
const totalTokens =
|
|
27321
|
+
const totalTokens = getNumberProperty3(usage, "totalTokens");
|
|
25023
27322
|
if (totalTokens !== void 0) {
|
|
25024
27323
|
metrics.tokens = totalTokens;
|
|
25025
27324
|
}
|
|
25026
|
-
const reasoningTokens =
|
|
27325
|
+
const reasoningTokens = getNumberProperty3(usage, "reasoningTokens");
|
|
25027
27326
|
if (reasoningTokens !== void 0) {
|
|
25028
27327
|
metrics.completion_reasoning_tokens = reasoningTokens;
|
|
25029
27328
|
}
|
|
25030
|
-
const cachedInputTokens =
|
|
27329
|
+
const cachedInputTokens = getNumberProperty3(usage, "cachedInputTokens");
|
|
25031
27330
|
if (cachedInputTokens !== void 0) {
|
|
25032
27331
|
metrics.prompt_cached_tokens = cachedInputTokens;
|
|
25033
27332
|
}
|
|
25034
27333
|
if (provider === "anthropic") {
|
|
25035
27334
|
const anthropicMetadata = providerMetadata?.anthropic;
|
|
25036
27335
|
if (anthropicMetadata) {
|
|
25037
|
-
const cacheReadTokens =
|
|
25038
|
-
const cacheCreationTokens =
|
|
27336
|
+
const cacheReadTokens = getNumberProperty3(anthropicMetadata.usage, "cache_read_input_tokens") || 0;
|
|
27337
|
+
const cacheCreationTokens = getNumberProperty3(
|
|
25039
27338
|
anthropicMetadata.usage,
|
|
25040
27339
|
"cache_creation_input_tokens"
|
|
25041
27340
|
) || 0;
|
|
@@ -26010,17 +28309,17 @@ function wrapGenkit(genkit) {
|
|
|
26010
28309
|
console.warn("Unsupported Genkit object. Not wrapping.");
|
|
26011
28310
|
return genkit;
|
|
26012
28311
|
}
|
|
26013
|
-
function
|
|
28312
|
+
function isRecord2(value) {
|
|
26014
28313
|
return typeof value === "object" && value !== null;
|
|
26015
28314
|
}
|
|
26016
28315
|
function isPropertyBag(value) {
|
|
26017
|
-
return
|
|
28316
|
+
return isRecord2(value) || typeof value === "function";
|
|
26018
28317
|
}
|
|
26019
28318
|
function hasFunction(value, methodName) {
|
|
26020
28319
|
return isPropertyBag(value) && methodName in value && typeof value[methodName] === "function";
|
|
26021
28320
|
}
|
|
26022
28321
|
function isGenkitInstance(value) {
|
|
26023
|
-
return
|
|
28322
|
+
return isRecord2(value) && (hasFunction(value, "generate") || hasFunction(value, "generateStream") || hasFunction(value, "defineFlow") || hasFunction(value, "defineTool"));
|
|
26024
28323
|
}
|
|
26025
28324
|
function isGenkitModule(value) {
|
|
26026
28325
|
return hasFunction(value, "genkit");
|
|
@@ -26074,7 +28373,7 @@ function patchGenkitRegistry(instance) {
|
|
|
26074
28373
|
patchGenkitRegistryConstructor(registry2);
|
|
26075
28374
|
}
|
|
26076
28375
|
function patchGenkitRegistryLookup(registry2) {
|
|
26077
|
-
if (!
|
|
28376
|
+
if (!isRecord2(registry2) || hasRegistryPatchedFlag(registry2) || !hasFunction(registry2, "lookupAction")) {
|
|
26078
28377
|
return;
|
|
26079
28378
|
}
|
|
26080
28379
|
const originalLookupAction = registry2.lookupAction;
|
|
@@ -26100,7 +28399,7 @@ function patchGenkitRegistryLookup(registry2) {
|
|
|
26100
28399
|
}
|
|
26101
28400
|
}
|
|
26102
28401
|
function patchGenkitRegistryConstructor(registry2) {
|
|
26103
|
-
if (!
|
|
28402
|
+
if (!isRecord2(registry2)) {
|
|
26104
28403
|
return;
|
|
26105
28404
|
}
|
|
26106
28405
|
const constructor = registry2.constructor;
|
|
@@ -26116,7 +28415,7 @@ function patchGenkitRegistryConstructor(registry2) {
|
|
|
26116
28415
|
configurable: true,
|
|
26117
28416
|
value: (...args) => {
|
|
26118
28417
|
const childRegistry = originalWithParent.apply(constructor, args);
|
|
26119
|
-
if (args.some((arg) =>
|
|
28418
|
+
if (args.some((arg) => isRecord2(arg) && hasRegistryPatchedFlag(arg))) {
|
|
26120
28419
|
patchGenkitRegistryLookup(childRegistry);
|
|
26121
28420
|
patchGenkitRegistryConstructor(childRegistry);
|
|
26122
28421
|
}
|
|
@@ -26215,7 +28514,7 @@ function hasRegistryConstructorPatchedFlag(value) {
|
|
|
26215
28514
|
);
|
|
26216
28515
|
}
|
|
26217
28516
|
function isPromiseLike2(value) {
|
|
26218
|
-
return
|
|
28517
|
+
return isRecord2(value) && "then" in value && typeof value.then === "function";
|
|
26219
28518
|
}
|
|
26220
28519
|
|
|
26221
28520
|
// src/wrappers/huggingface.ts
|
|
@@ -26578,14 +28877,14 @@ function wrapMistral(mistral) {
|
|
|
26578
28877
|
console.warn("Unsupported Mistral library. Not wrapping.");
|
|
26579
28878
|
return mistral;
|
|
26580
28879
|
}
|
|
26581
|
-
function
|
|
28880
|
+
function isRecord3(value) {
|
|
26582
28881
|
return typeof value === "object" && value !== null;
|
|
26583
28882
|
}
|
|
26584
28883
|
function hasFunction3(value, methodName) {
|
|
26585
|
-
return
|
|
28884
|
+
return isRecord3(value) && methodName in value && typeof value[methodName] === "function";
|
|
26586
28885
|
}
|
|
26587
28886
|
function isSupportedMistralClient(value) {
|
|
26588
|
-
if (!
|
|
28887
|
+
if (!isRecord3(value)) {
|
|
26589
28888
|
return false;
|
|
26590
28889
|
}
|
|
26591
28890
|
return value.chat !== void 0 && hasChat(value.chat) || value.embeddings !== void 0 && hasEmbeddings(value.embeddings) || value.fim !== void 0 && hasFim(value.fim) || value.agents !== void 0 && hasAgents(value.agents) || value.classifiers !== void 0 && hasClassifiers(value.classifiers);
|
|
@@ -26769,14 +29068,14 @@ function wrapCohere(cohere) {
|
|
|
26769
29068
|
return cohere;
|
|
26770
29069
|
}
|
|
26771
29070
|
var cohereProxyCache = /* @__PURE__ */ new WeakMap();
|
|
26772
|
-
function
|
|
29071
|
+
function isRecord4(value) {
|
|
26773
29072
|
return typeof value === "object" && value !== null;
|
|
26774
29073
|
}
|
|
26775
29074
|
function hasFunction4(value, methodName) {
|
|
26776
|
-
return
|
|
29075
|
+
return isRecord4(value) && methodName in value && typeof value[methodName] === "function";
|
|
26777
29076
|
}
|
|
26778
29077
|
function isSupportedCohereClient(value) {
|
|
26779
|
-
if (!
|
|
29078
|
+
if (!isRecord4(value)) {
|
|
26780
29079
|
return false;
|
|
26781
29080
|
}
|
|
26782
29081
|
return hasFunction4(value, "chat") || hasFunction4(value, "chatStream") || hasFunction4(value, "embed") || hasFunction4(value, "rerank");
|
|
@@ -26836,20 +29135,20 @@ function wrapGroq(groq) {
|
|
|
26836
29135
|
console.warn("Unsupported Groq library. Not wrapping.");
|
|
26837
29136
|
return groq;
|
|
26838
29137
|
}
|
|
26839
|
-
function
|
|
29138
|
+
function isRecord5(value) {
|
|
26840
29139
|
return typeof value === "object" && value !== null;
|
|
26841
29140
|
}
|
|
26842
29141
|
function hasFunction5(value, methodName) {
|
|
26843
|
-
return
|
|
29142
|
+
return isRecord5(value) && methodName in value && typeof value[methodName] === "function";
|
|
26844
29143
|
}
|
|
26845
29144
|
function hasChat2(value) {
|
|
26846
|
-
return
|
|
29145
|
+
return isRecord5(value) && isRecord5(value.completions) && hasFunction5(value.completions, "create");
|
|
26847
29146
|
}
|
|
26848
29147
|
function hasEmbeddings2(value) {
|
|
26849
29148
|
return hasFunction5(value, "create");
|
|
26850
29149
|
}
|
|
26851
29150
|
function isSupportedGroqClient(value) {
|
|
26852
|
-
return
|
|
29151
|
+
return isRecord5(value) && (value.chat !== void 0 && hasChat2(value.chat) || value.embeddings !== void 0 && hasEmbeddings2(value.embeddings));
|
|
26853
29152
|
}
|
|
26854
29153
|
function groqProxy(groq) {
|
|
26855
29154
|
const privateMethodWorkaroundCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -27044,10 +29343,12 @@ function formatExperimentSummary(summary) {
|
|
|
27044
29343
|
// src/wrappers/shared/flush.ts
|
|
27045
29344
|
async function summarizeAndFlush(experiment, options) {
|
|
27046
29345
|
const shouldDisplay = options.displaySummary ?? true;
|
|
27047
|
-
|
|
27048
|
-
|
|
27049
|
-
|
|
29346
|
+
if (!shouldDisplay) {
|
|
29347
|
+
await experiment.flush();
|
|
29348
|
+
return;
|
|
27050
29349
|
}
|
|
29350
|
+
const summary = await experiment.summarize();
|
|
29351
|
+
console.log(formatExperimentSummary(summary));
|
|
27051
29352
|
}
|
|
27052
29353
|
|
|
27053
29354
|
// src/wrappers/vitest/flush-manager.ts
|
|
@@ -28911,8 +31212,12 @@ var waterfall$1 = awaitify(waterfall);
|
|
|
28911
31212
|
|
|
28912
31213
|
// src/trace.ts
|
|
28913
31214
|
var SpanFetcher = class _SpanFetcher extends ObjectFetcher {
|
|
28914
|
-
constructor(objectType, _objectId, rootSpanId, _state, spanTypeFilter) {
|
|
28915
|
-
const filterExpr = _SpanFetcher.buildFilter(
|
|
31215
|
+
constructor(objectType, _objectId, rootSpanId, _state, spanTypeFilter, includeScorers = false) {
|
|
31216
|
+
const filterExpr = _SpanFetcher.buildFilter(
|
|
31217
|
+
rootSpanId,
|
|
31218
|
+
spanTypeFilter,
|
|
31219
|
+
includeScorers
|
|
31220
|
+
);
|
|
28916
31221
|
super(objectType, void 0, void 0, {
|
|
28917
31222
|
filter: filterExpr
|
|
28918
31223
|
});
|
|
@@ -28921,16 +31226,17 @@ var SpanFetcher = class _SpanFetcher extends ObjectFetcher {
|
|
|
28921
31226
|
this._state = _state;
|
|
28922
31227
|
this.spanTypeFilter = spanTypeFilter;
|
|
28923
31228
|
}
|
|
28924
|
-
static buildFilter(rootSpanId, spanTypeFilter) {
|
|
31229
|
+
static buildFilter(rootSpanId, spanTypeFilter, includeScorers = false) {
|
|
28925
31230
|
const children = [
|
|
28926
31231
|
// Base filter: root_span_id = 'value'
|
|
28927
31232
|
{
|
|
28928
31233
|
op: "eq",
|
|
28929
31234
|
left: { op: "ident", name: ["root_span_id"] },
|
|
28930
31235
|
right: { op: "literal", value: rootSpanId }
|
|
28931
|
-
}
|
|
28932
|
-
|
|
28933
|
-
|
|
31236
|
+
}
|
|
31237
|
+
];
|
|
31238
|
+
if (!includeScorers) {
|
|
31239
|
+
children.push({
|
|
28934
31240
|
op: "or",
|
|
28935
31241
|
children: [
|
|
28936
31242
|
{
|
|
@@ -28943,8 +31249,8 @@ var SpanFetcher = class _SpanFetcher extends ObjectFetcher {
|
|
|
28943
31249
|
right: { op: "literal", value: "scorer" }
|
|
28944
31250
|
}
|
|
28945
31251
|
]
|
|
28946
|
-
}
|
|
28947
|
-
|
|
31252
|
+
});
|
|
31253
|
+
}
|
|
28948
31254
|
if (spanTypeFilter && spanTypeFilter.length > 0) {
|
|
28949
31255
|
children.push({
|
|
28950
31256
|
op: "in",
|
|
@@ -28970,35 +31276,49 @@ var CachedSpanFetcher = class {
|
|
|
28970
31276
|
fetchFn;
|
|
28971
31277
|
constructor(objectTypeOrFetchFn, objectId, rootSpanId, getState) {
|
|
28972
31278
|
if (typeof objectTypeOrFetchFn === "function") {
|
|
28973
|
-
this.fetchFn = objectTypeOrFetchFn;
|
|
31279
|
+
this.fetchFn = (spanType) => objectTypeOrFetchFn(spanType);
|
|
28974
31280
|
} else {
|
|
28975
31281
|
const objectType = objectTypeOrFetchFn;
|
|
28976
|
-
this.fetchFn = async (spanType) => {
|
|
31282
|
+
this.fetchFn = async (spanType, includeScorers) => {
|
|
28977
31283
|
const state = await getState();
|
|
28978
31284
|
const fetcher = new SpanFetcher(
|
|
28979
31285
|
objectType,
|
|
28980
31286
|
objectId,
|
|
28981
31287
|
rootSpanId,
|
|
28982
31288
|
state,
|
|
28983
|
-
spanType
|
|
31289
|
+
spanType,
|
|
31290
|
+
includeScorers
|
|
28984
31291
|
);
|
|
28985
31292
|
const rows = await fetcher.fetchedData();
|
|
28986
|
-
return rows.
|
|
31293
|
+
return rows.map((row) => ({
|
|
28987
31294
|
input: row.input,
|
|
28988
31295
|
output: row.output,
|
|
31296
|
+
expected: row.expected,
|
|
31297
|
+
error: row.error,
|
|
31298
|
+
scores: row.scores,
|
|
31299
|
+
metrics: row.metrics,
|
|
28989
31300
|
metadata: row.metadata,
|
|
28990
31301
|
span_id: row.span_id,
|
|
28991
31302
|
span_parents: row.span_parents,
|
|
31303
|
+
is_root: row.is_root,
|
|
28992
31304
|
span_attributes: row.span_attributes,
|
|
28993
31305
|
id: row.id,
|
|
28994
31306
|
_xact_id: row._xact_id,
|
|
28995
31307
|
_pagination_key: row._pagination_key,
|
|
28996
|
-
root_span_id: row.root_span_id
|
|
31308
|
+
root_span_id: row.root_span_id,
|
|
31309
|
+
created: row.created,
|
|
31310
|
+
tags: row.tags
|
|
28997
31311
|
}));
|
|
28998
31312
|
};
|
|
28999
31313
|
}
|
|
29000
31314
|
}
|
|
29001
|
-
async getSpans({
|
|
31315
|
+
async getSpans({
|
|
31316
|
+
spanType,
|
|
31317
|
+
includeScorers = false
|
|
31318
|
+
} = {}) {
|
|
31319
|
+
if (includeScorers) {
|
|
31320
|
+
return this.fetchFn(spanType, true);
|
|
31321
|
+
}
|
|
29002
31322
|
if (this.allFetched) {
|
|
29003
31323
|
return this.getFromCache(spanType);
|
|
29004
31324
|
}
|
|
@@ -29015,7 +31335,7 @@ var CachedSpanFetcher = class {
|
|
|
29015
31335
|
return this.getFromCache(spanType);
|
|
29016
31336
|
}
|
|
29017
31337
|
async fetchSpans(spanType) {
|
|
29018
|
-
const spans = await this.fetchFn(spanType);
|
|
31338
|
+
const spans = await this.fetchFn(spanType, false);
|
|
29019
31339
|
for (const span of spans) {
|
|
29020
31340
|
const type = span.span_attributes?.type ?? "";
|
|
29021
31341
|
const existing = this.spanCache.get(type) ?? [];
|
|
@@ -29093,10 +31413,13 @@ var LocalTrace = class {
|
|
|
29093
31413
|
* First checks the local span cache for recently logged spans, then falls
|
|
29094
31414
|
* back to CachedSpanFetcher which handles BTQL fetching and caching.
|
|
29095
31415
|
*/
|
|
29096
|
-
async getSpans({
|
|
31416
|
+
async getSpans({
|
|
31417
|
+
spanType,
|
|
31418
|
+
includeScorers = false
|
|
31419
|
+
} = {}) {
|
|
29097
31420
|
const cachedSpans = this.state.spanCache.getByRootSpanId(this.rootSpanId);
|
|
29098
31421
|
if (cachedSpans && cachedSpans.length > 0) {
|
|
29099
|
-
let spans = cachedSpans.filter(
|
|
31422
|
+
let spans = includeScorers ? cachedSpans : cachedSpans.filter(
|
|
29100
31423
|
(span) => span.span_attributes?.purpose !== "scorer"
|
|
29101
31424
|
);
|
|
29102
31425
|
if (spanType && spanType.length > 0) {
|
|
@@ -29107,13 +31430,19 @@ var LocalTrace = class {
|
|
|
29107
31430
|
return spans.map((span) => ({
|
|
29108
31431
|
input: span.input,
|
|
29109
31432
|
output: span.output,
|
|
31433
|
+
expected: span.expected,
|
|
31434
|
+
error: span.error,
|
|
31435
|
+
scores: span.scores,
|
|
31436
|
+
metrics: span.metrics,
|
|
29110
31437
|
metadata: span.metadata,
|
|
29111
31438
|
span_id: span.span_id,
|
|
29112
31439
|
span_parents: span.span_parents,
|
|
29113
|
-
|
|
31440
|
+
is_root: span.is_root,
|
|
31441
|
+
span_attributes: span.span_attributes,
|
|
31442
|
+
tags: span.tags
|
|
29114
31443
|
}));
|
|
29115
31444
|
}
|
|
29116
|
-
return this.cachedFetcher.getSpans({ spanType });
|
|
31445
|
+
return this.cachedFetcher.getSpans({ spanType, includeScorers });
|
|
29117
31446
|
}
|
|
29118
31447
|
/**
|
|
29119
31448
|
* Get the thread (preprocessed messages) for this trace.
|
|
@@ -30302,6 +32631,34 @@ var defaultReporter = {
|
|
|
30302
32631
|
}
|
|
30303
32632
|
};
|
|
30304
32633
|
|
|
32634
|
+
// src/dataset-pipeline.ts
|
|
32635
|
+
function DatasetPipeline(definition) {
|
|
32636
|
+
if (!globalThis.__braintrust_dataset_pipelines) {
|
|
32637
|
+
globalThis.__braintrust_dataset_pipelines = [];
|
|
32638
|
+
}
|
|
32639
|
+
const storedDefinition = {
|
|
32640
|
+
name: definition.name,
|
|
32641
|
+
source: {
|
|
32642
|
+
projectId: definition.source.projectId,
|
|
32643
|
+
projectName: definition.source.projectName,
|
|
32644
|
+
orgName: definition.source.orgName,
|
|
32645
|
+
filter: definition.source.filter,
|
|
32646
|
+
scope: definition.source.scope ?? "span"
|
|
32647
|
+
},
|
|
32648
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any
|
|
32649
|
+
transform: definition.transform,
|
|
32650
|
+
target: {
|
|
32651
|
+
projectId: definition.target.projectId,
|
|
32652
|
+
projectName: definition.target.projectName,
|
|
32653
|
+
orgName: definition.target.orgName,
|
|
32654
|
+
datasetName: definition.target.datasetName,
|
|
32655
|
+
description: definition.target.description,
|
|
32656
|
+
metadata: definition.target.metadata
|
|
32657
|
+
}
|
|
32658
|
+
};
|
|
32659
|
+
globalThis.__braintrust_dataset_pipelines.push(storedDefinition);
|
|
32660
|
+
}
|
|
32661
|
+
|
|
30305
32662
|
// src/framework2.ts
|
|
30306
32663
|
import { z as z12 } from "zod/v3";
|
|
30307
32664
|
var currentFilename = typeof __filename !== "undefined" ? __filename : "unknown";
|
|
@@ -30827,8 +33184,10 @@ export {
|
|
|
30827
33184
|
Attachment,
|
|
30828
33185
|
AttachmentReference,
|
|
30829
33186
|
BRAINTRUST_CURRENT_SPAN_STORE,
|
|
33187
|
+
BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME,
|
|
30830
33188
|
BaseAttachment,
|
|
30831
33189
|
BaseExperiment,
|
|
33190
|
+
BraintrustLangChainCallbackHandler,
|
|
30832
33191
|
BraintrustMiddleware,
|
|
30833
33192
|
BraintrustState,
|
|
30834
33193
|
BraintrustStream,
|
|
@@ -30839,6 +33198,7 @@ export {
|
|
|
30839
33198
|
DEFAULT_FETCH_BATCH_SIZE,
|
|
30840
33199
|
DEFAULT_MAX_REQUEST_SIZE,
|
|
30841
33200
|
Dataset2 as Dataset,
|
|
33201
|
+
DatasetPipeline,
|
|
30842
33202
|
ERR_PERMALINK,
|
|
30843
33203
|
Eval,
|
|
30844
33204
|
EvalResultWithSummary,
|
|
@@ -30955,6 +33315,8 @@ export {
|
|
|
30955
33315
|
wrapCohere,
|
|
30956
33316
|
wrapCopilotClient,
|
|
30957
33317
|
wrapCursorSDK,
|
|
33318
|
+
wrapFlueContext,
|
|
33319
|
+
wrapFlueSession,
|
|
30958
33320
|
wrapGenkit,
|
|
30959
33321
|
wrapGoogleADK,
|
|
30960
33322
|
wrapGoogleGenAI,
|