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/cli.js
CHANGED
|
@@ -1232,7 +1232,7 @@ var require_package = __commonJS({
|
|
|
1232
1232
|
"package.json"(exports2, module2) {
|
|
1233
1233
|
module2.exports = {
|
|
1234
1234
|
name: "braintrust",
|
|
1235
|
-
version: "3.
|
|
1235
|
+
version: "3.13.0",
|
|
1236
1236
|
description: "SDK for integrating Braintrust",
|
|
1237
1237
|
repository: {
|
|
1238
1238
|
type: "git",
|
|
@@ -1243,6 +1243,7 @@ var require_package = __commonJS({
|
|
|
1243
1243
|
main: "./dist/index.js",
|
|
1244
1244
|
module: "./dist/index.mjs",
|
|
1245
1245
|
types: "./dist/index.d.ts",
|
|
1246
|
+
sideEffects: true,
|
|
1246
1247
|
browser: {
|
|
1247
1248
|
"./dist/index.js": "./dist/browser.js",
|
|
1248
1249
|
"./dist/index.d.ts": "./dist/browser.d.ts",
|
|
@@ -1282,6 +1283,19 @@ var require_package = __commonJS({
|
|
|
1282
1283
|
require: "./dist/browser.js",
|
|
1283
1284
|
default: "./dist/browser.mjs"
|
|
1284
1285
|
},
|
|
1286
|
+
"./apply-auto-instrumentation": {
|
|
1287
|
+
types: "./dist/apply-auto-instrumentation.d.ts",
|
|
1288
|
+
"edge-light": "./dist/apply-auto-instrumentation.browser.mjs",
|
|
1289
|
+
workerd: "./dist/apply-auto-instrumentation.browser.mjs",
|
|
1290
|
+
node: {
|
|
1291
|
+
import: "./dist/apply-auto-instrumentation.mjs",
|
|
1292
|
+
require: "./dist/apply-auto-instrumentation.js"
|
|
1293
|
+
},
|
|
1294
|
+
browser: "./dist/apply-auto-instrumentation.browser.mjs",
|
|
1295
|
+
import: "./dist/apply-auto-instrumentation.mjs",
|
|
1296
|
+
require: "./dist/apply-auto-instrumentation.js",
|
|
1297
|
+
default: "./dist/apply-auto-instrumentation.mjs"
|
|
1298
|
+
},
|
|
1285
1299
|
"./node": {
|
|
1286
1300
|
types: "./dist/index.d.ts",
|
|
1287
1301
|
import: "./dist/index.mjs",
|
|
@@ -1319,6 +1333,12 @@ var require_package = __commonJS({
|
|
|
1319
1333
|
module: "./dist/auto-instrumentations/bundler/webpack.mjs",
|
|
1320
1334
|
require: "./dist/auto-instrumentations/bundler/webpack.cjs"
|
|
1321
1335
|
},
|
|
1336
|
+
"./next": {
|
|
1337
|
+
types: "./dist/auto-instrumentations/bundler/next.d.ts",
|
|
1338
|
+
import: "./dist/auto-instrumentations/bundler/next.mjs",
|
|
1339
|
+
module: "./dist/auto-instrumentations/bundler/next.mjs",
|
|
1340
|
+
require: "./dist/auto-instrumentations/bundler/next.cjs"
|
|
1341
|
+
},
|
|
1322
1342
|
"./webpack-loader": {
|
|
1323
1343
|
types: "./dist/auto-instrumentations/bundler/webpack-loader.d.ts",
|
|
1324
1344
|
require: "./dist/auto-instrumentations/bundler/webpack-loader.cjs"
|
|
@@ -1350,28 +1370,16 @@ var require_package = __commonJS({
|
|
|
1350
1370
|
test: 'vitest run --exclude "src/wrappers/**/*.test.ts" --exclude "src/otel/**/*.test.ts" --exclude "smoke/**/*.test.ts" --exclude "src/zod/**/*.test.ts" --exclude "tests/api-compatibility/**"',
|
|
1351
1371
|
"test:core": "pnpm prune && pnpm test",
|
|
1352
1372
|
"test:checks": "pnpm run test:core && pnpm run test:vitest",
|
|
1353
|
-
"test:
|
|
1354
|
-
"test:external:openai": "bash scripts/test-provider.sh test:openai openai",
|
|
1355
|
-
"test:external:anthropic": "bash scripts/test-provider.sh test:anthropic @anthropic-ai/sdk",
|
|
1356
|
-
"test:external:google-genai": "bash scripts/test-provider.sh test:google-genai @google/genai",
|
|
1357
|
-
"test:external:ai-sdk": "pnpm run test:external:ai-sdk-v5 && pnpm run test:external:ai-sdk-v6",
|
|
1358
|
-
"test:external:ai-sdk-v5": "cd src/wrappers/ai-sdk/tests/v5 && pnpm install --ignore-workspace && pnpm test",
|
|
1359
|
-
"test:external:ai-sdk-v6": "cd src/wrappers/ai-sdk/tests/v6 && pnpm install --ignore-workspace && pnpm test",
|
|
1360
|
-
"test:external:claude-agent-sdk": "cd src/wrappers/claude-agent-sdk && pnpm install && pnpm test",
|
|
1361
|
-
"test:all": "pnpm run test:checks && pnpm run test:external",
|
|
1373
|
+
"test:all": "pnpm run test:checks",
|
|
1362
1374
|
"test:api-compat": "vitest run tests/api-compatibility/api-compatibility.test.ts",
|
|
1363
|
-
"test:anthropic": "vitest run src/wrappers/anthropic.test.ts",
|
|
1364
|
-
"test:openai": "vitest run src/wrappers/oai.test.ts",
|
|
1365
1375
|
"test:otel": "vitest run --dir src/otel",
|
|
1366
1376
|
"test:otel-no-deps": "vitest run src/otel/otel-no-deps.test.ts --reporter=verbose",
|
|
1367
|
-
"test:google-genai": "vitest run src/wrappers/google-genai.test.ts",
|
|
1368
1377
|
"test:ai-sdk-v1": "vitest run src/wrappers/ai-sdk-v1.test.ts",
|
|
1369
1378
|
"test:ai-sdk-v2": "vitest run src/wrappers/ai-sdk-v2.test.ts src/wrappers/ai-sdk-v1.test.ts",
|
|
1370
1379
|
"test:ai-sdk-v3": "vitest run src/wrappers/ai-sdk-v3.test.ts",
|
|
1371
1380
|
"test:zod-v3": "vitest run src/zod/zod-v3-serialization.test.ts",
|
|
1372
1381
|
"test:zod-v4": "vitest run src/zod/zod-v4-serialization.test.ts",
|
|
1373
1382
|
"test:mastra": "vitest run src/wrappers/mastra.test.ts",
|
|
1374
|
-
"test:claude-agent-sdk": "pnpm --filter @braintrust/claude-agent-sdk-tests test",
|
|
1375
1383
|
"test:vitest": "pnpm --filter @braintrust/vitest-wrapper-tests test",
|
|
1376
1384
|
"test:output": "tsx scripts/test-output.ts --with-comparison --with-metrics --with-progress",
|
|
1377
1385
|
bench: "tsx src/queue.bench.ts",
|
|
@@ -1402,7 +1410,6 @@ var require_package = __commonJS({
|
|
|
1402
1410
|
"@types/node": "^20.10.5",
|
|
1403
1411
|
"@types/pluralize": "^0.0.30",
|
|
1404
1412
|
"@types/tar": "^6.1.13",
|
|
1405
|
-
"@types/uuid": "^9.0.7",
|
|
1406
1413
|
"@typescript-eslint/eslint-plugin": "^8.49.0",
|
|
1407
1414
|
"@typescript-eslint/parser": "^8.49.0",
|
|
1408
1415
|
ai: "^6.0.0",
|
|
@@ -1411,7 +1418,6 @@ var require_package = __commonJS({
|
|
|
1411
1418
|
"cross-env": "^7.0.3",
|
|
1412
1419
|
"eslint-plugin-node-import": "^1.0.5",
|
|
1413
1420
|
openai: "6.25.0",
|
|
1414
|
-
"openapi-zod-client": "^1.18.3",
|
|
1415
1421
|
rollup: "^4.60.3",
|
|
1416
1422
|
tar: "^7.5.2",
|
|
1417
1423
|
tinybench: "^4.0.1",
|
|
@@ -1450,7 +1456,7 @@ var require_package = __commonJS({
|
|
|
1450
1456
|
"source-map": "^0.7.4",
|
|
1451
1457
|
"termi-link": "^1.0.1",
|
|
1452
1458
|
unplugin: "^2.3.5",
|
|
1453
|
-
uuid: "^
|
|
1459
|
+
uuid: "^11.1.1",
|
|
1454
1460
|
"zod-to-json-schema": "^3.25.0"
|
|
1455
1461
|
},
|
|
1456
1462
|
peerDependencies: {
|
|
@@ -1474,7 +1480,7 @@ __export(cli_exports, {
|
|
|
1474
1480
|
});
|
|
1475
1481
|
module.exports = __toCommonJS(cli_exports);
|
|
1476
1482
|
var esbuild = __toESM(require("esbuild"));
|
|
1477
|
-
var
|
|
1483
|
+
var dotenv3 = __toESM(require("dotenv"));
|
|
1478
1484
|
var import_node_fs2 = __toESM(require("node:fs"));
|
|
1479
1485
|
var import_node_os = __toESM(require("node:os"));
|
|
1480
1486
|
var import_node_path5 = __toESM(require("node:path"));
|
|
@@ -1573,6 +1579,7 @@ var iso = {
|
|
|
1573
1579
|
getRepoInfo: async (_settings) => void 0,
|
|
1574
1580
|
getPastNAncestors: async () => [],
|
|
1575
1581
|
getEnv: (_name) => void 0,
|
|
1582
|
+
getBraintrustApiKey: async () => void 0,
|
|
1576
1583
|
getCallerLocation: () => void 0,
|
|
1577
1584
|
newAsyncLocalStorage: () => new DefaultAsyncLocalStorage(),
|
|
1578
1585
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -2405,6 +2412,11 @@ function isPromiseLike(value) {
|
|
|
2405
2412
|
|
|
2406
2413
|
// util/object_util.ts
|
|
2407
2414
|
var SET_UNION_FIELDS = /* @__PURE__ */ new Set(["tags"]);
|
|
2415
|
+
var FORBIDDEN_MERGE_KEYS = /* @__PURE__ */ new Set([
|
|
2416
|
+
"__proto__",
|
|
2417
|
+
"constructor",
|
|
2418
|
+
"prototype"
|
|
2419
|
+
]);
|
|
2408
2420
|
function mergeDictsWithPaths({
|
|
2409
2421
|
mergeInto,
|
|
2410
2422
|
mergeFrom,
|
|
@@ -2427,6 +2439,7 @@ function mergeDictsWithPathsHelper({
|
|
|
2427
2439
|
mergePaths
|
|
2428
2440
|
}) {
|
|
2429
2441
|
Object.entries(mergeFrom).forEach(([k, mergeFromV]) => {
|
|
2442
|
+
if (FORBIDDEN_MERGE_KEYS.has(k)) return;
|
|
2430
2443
|
const fullPath = path8.concat([k]);
|
|
2431
2444
|
const fullPathSerialized = JSON.stringify(fullPath);
|
|
2432
2445
|
const mergeIntoV = recordFind(mergeInto, k);
|
|
@@ -6490,6 +6503,13 @@ var HTTPConnection = class _HTTPConnection {
|
|
|
6490
6503
|
debugLogger.debug(
|
|
6491
6504
|
`Retrying API request ${object_type} ${JSON.stringify(args)} ${e.status} ${e.text}`
|
|
6492
6505
|
);
|
|
6506
|
+
const sleepTimeS = HTTP_RETRY_BASE_SLEEP_TIME_S * 2 ** i;
|
|
6507
|
+
debugLogger.info(
|
|
6508
|
+
`Sleeping for ${sleepTimeS}s before retrying API request`
|
|
6509
|
+
);
|
|
6510
|
+
await new Promise(
|
|
6511
|
+
(resolve2) => setTimeout(resolve2, sleepTimeS * 1e3)
|
|
6512
|
+
);
|
|
6493
6513
|
continue;
|
|
6494
6514
|
}
|
|
6495
6515
|
throw e;
|
|
@@ -7012,20 +7032,7 @@ function startSpanParentArgs(args) {
|
|
|
7012
7032
|
`Mismatch between expected span parent object type ${args.parentObjectType} and provided type ${parentComponents.data.object_type}`
|
|
7013
7033
|
);
|
|
7014
7034
|
}
|
|
7015
|
-
|
|
7016
|
-
args.state,
|
|
7017
|
-
parentComponents
|
|
7018
|
-
);
|
|
7019
|
-
const computeParentObjectId = async () => {
|
|
7020
|
-
const parentComponentsObjectId = await parentComponentsObjectIdLambda();
|
|
7021
|
-
if (await args.parentObjectId.get() !== parentComponentsObjectId) {
|
|
7022
|
-
throw new Error(
|
|
7023
|
-
`Mismatch between expected span parent object id ${await args.parentObjectId.get()} and provided id ${parentComponentsObjectId}`
|
|
7024
|
-
);
|
|
7025
|
-
}
|
|
7026
|
-
return await args.parentObjectId.get();
|
|
7027
|
-
};
|
|
7028
|
-
argParentObjectId = new LazyValue(computeParentObjectId);
|
|
7035
|
+
argParentObjectId = args.parentObjectId;
|
|
7029
7036
|
if (parentComponents.data.row_id) {
|
|
7030
7037
|
argParentSpanIds = {
|
|
7031
7038
|
spanId: parentComponents.data.span_id,
|
|
@@ -7354,6 +7361,7 @@ function now() {
|
|
|
7354
7361
|
}
|
|
7355
7362
|
var DEFAULT_FLUSH_BACKPRESSURE_BYTES = 10 * 1024 * 1024;
|
|
7356
7363
|
var BACKGROUND_LOGGER_BASE_SLEEP_TIME_S = 1;
|
|
7364
|
+
var HTTP_RETRY_BASE_SLEEP_TIME_S = 1;
|
|
7357
7365
|
var HTTPBackgroundLogger = class _HTTPBackgroundLogger {
|
|
7358
7366
|
apiConn;
|
|
7359
7367
|
queue;
|
|
@@ -7984,17 +7992,10 @@ function init(projectOrOptions, optionalOptions) {
|
|
|
7984
7992
|
if (repoInfo2) {
|
|
7985
7993
|
return repoInfo2;
|
|
7986
7994
|
}
|
|
7987
|
-
|
|
7988
|
-
|
|
7989
|
-
|
|
7990
|
-
|
|
7991
|
-
};
|
|
7992
|
-
if (gitMetadataSettings) {
|
|
7993
|
-
mergedGitMetadataSettings = mergeGitMetadataSettings(
|
|
7994
|
-
mergedGitMetadataSettings,
|
|
7995
|
-
gitMetadataSettings
|
|
7996
|
-
);
|
|
7997
|
-
}
|
|
7995
|
+
const mergedGitMetadataSettings = state.gitMetadataSettings == null ? gitMetadataSettings ?? { collect: "none" } : mergeGitMetadataSettings(
|
|
7996
|
+
state.gitMetadataSettings,
|
|
7997
|
+
gitMetadataSettings ?? { collect: "all" }
|
|
7998
|
+
);
|
|
7998
7999
|
return await isomorph_default.getRepoInfo(mergedGitMetadataSettings);
|
|
7999
8000
|
})();
|
|
8000
8001
|
if (repoInfoArg) {
|
|
@@ -8376,6 +8377,55 @@ async function computeLoggerMetadata(state, {
|
|
|
8376
8377
|
};
|
|
8377
8378
|
}
|
|
8378
8379
|
}
|
|
8380
|
+
function initLogger(options = {}) {
|
|
8381
|
+
const {
|
|
8382
|
+
projectName,
|
|
8383
|
+
projectId,
|
|
8384
|
+
asyncFlush: asyncFlushArg,
|
|
8385
|
+
appUrl,
|
|
8386
|
+
apiKey,
|
|
8387
|
+
orgName,
|
|
8388
|
+
forceLogin,
|
|
8389
|
+
debugLogLevel,
|
|
8390
|
+
fetch: fetch2,
|
|
8391
|
+
state: stateArg
|
|
8392
|
+
} = options || {};
|
|
8393
|
+
const asyncFlush = asyncFlushArg === void 0 ? true : asyncFlushArg;
|
|
8394
|
+
const computeMetadataArgs = {
|
|
8395
|
+
project_name: projectName,
|
|
8396
|
+
project_id: projectId
|
|
8397
|
+
};
|
|
8398
|
+
const linkArgs = {
|
|
8399
|
+
org_name: orgName,
|
|
8400
|
+
app_url: appUrl,
|
|
8401
|
+
project_name: projectName,
|
|
8402
|
+
project_id: projectId
|
|
8403
|
+
};
|
|
8404
|
+
const state = stateArg ?? _globalState;
|
|
8405
|
+
state.setDebugLogLevel(debugLogLevel);
|
|
8406
|
+
state.enforceQueueSizeLimit(true);
|
|
8407
|
+
const lazyMetadata = new LazyValue(
|
|
8408
|
+
async () => {
|
|
8409
|
+
await state.login({
|
|
8410
|
+
orgName,
|
|
8411
|
+
apiKey,
|
|
8412
|
+
appUrl,
|
|
8413
|
+
forceLogin,
|
|
8414
|
+
fetch: fetch2
|
|
8415
|
+
});
|
|
8416
|
+
return computeLoggerMetadata(state, computeMetadataArgs);
|
|
8417
|
+
}
|
|
8418
|
+
);
|
|
8419
|
+
const ret = new Logger(state, lazyMetadata, {
|
|
8420
|
+
asyncFlush,
|
|
8421
|
+
computeMetadataArgs,
|
|
8422
|
+
linkArgs
|
|
8423
|
+
});
|
|
8424
|
+
if (options.setCurrent ?? true) {
|
|
8425
|
+
state.currentLogger = ret;
|
|
8426
|
+
}
|
|
8427
|
+
return ret;
|
|
8428
|
+
}
|
|
8379
8429
|
async function login(options = {}) {
|
|
8380
8430
|
const { forceLogin = false } = options || {};
|
|
8381
8431
|
if (!_internalGetGlobalState()) {
|
|
@@ -8407,10 +8457,11 @@ async function login(options = {}) {
|
|
|
8407
8457
|
async function loginToState(options = {}) {
|
|
8408
8458
|
const {
|
|
8409
8459
|
appUrl = isomorph_default.getEnv("BRAINTRUST_APP_URL") || "https://www.braintrust.dev",
|
|
8410
|
-
apiKey
|
|
8460
|
+
apiKey: apiKeyArg,
|
|
8411
8461
|
orgName = isomorph_default.getEnv("BRAINTRUST_ORG_NAME"),
|
|
8412
8462
|
fetch: fetch2 = globalThis.fetch
|
|
8413
8463
|
} = options || {};
|
|
8464
|
+
const apiKey = apiKeyArg !== void 0 ? apiKeyArg : await isomorph_default.getBraintrustApiKey();
|
|
8414
8465
|
const appPublicUrl = isomorph_default.getEnv("BRAINTRUST_APP_PUBLIC_URL") || appUrl;
|
|
8415
8466
|
const state = new BraintrustState(options);
|
|
8416
8467
|
state.resetLoginInfo();
|
|
@@ -9429,9 +9480,15 @@ var SpanImpl = class _SpanImpl {
|
|
|
9429
9480
|
const cachedSpan = {
|
|
9430
9481
|
input: partialRecord.input,
|
|
9431
9482
|
output: partialRecord.output,
|
|
9483
|
+
expected: partialRecord.expected,
|
|
9484
|
+
error: partialRecord.error,
|
|
9485
|
+
scores: partialRecord.scores,
|
|
9486
|
+
metrics: partialRecord.metrics,
|
|
9432
9487
|
metadata: partialRecord.metadata,
|
|
9488
|
+
tags: partialRecord.tags,
|
|
9433
9489
|
span_id: this._spanId,
|
|
9434
9490
|
span_parents: this._spanParents,
|
|
9491
|
+
is_root: this._spanId === this._rootSpanId,
|
|
9435
9492
|
span_attributes: partialRecord.span_attributes
|
|
9436
9493
|
};
|
|
9437
9494
|
this._state.spanCache.queueWrite(
|
|
@@ -9767,6 +9824,7 @@ var Dataset2 = class extends ObjectFetcher {
|
|
|
9767
9824
|
metadata,
|
|
9768
9825
|
tags,
|
|
9769
9826
|
output,
|
|
9827
|
+
origin,
|
|
9770
9828
|
isMerge
|
|
9771
9829
|
}) {
|
|
9772
9830
|
return new LazyValue(async () => {
|
|
@@ -9781,6 +9839,7 @@ var Dataset2 = class extends ObjectFetcher {
|
|
|
9781
9839
|
created: !isMerge ? (/* @__PURE__ */ new Date()).toISOString() : void 0,
|
|
9782
9840
|
//if we're merging/updating an event we will not add this ts
|
|
9783
9841
|
metadata,
|
|
9842
|
+
origin,
|
|
9784
9843
|
...!!isMerge ? {
|
|
9785
9844
|
[IS_MERGE_FIELD]: true
|
|
9786
9845
|
} : {}
|
|
@@ -9800,6 +9859,7 @@ var Dataset2 = class extends ObjectFetcher {
|
|
|
9800
9859
|
* about anything else that's relevant, that you can use to help find and analyze examples later. For example, you could log the
|
|
9801
9860
|
* `prompt`, example's `id`, or anything else that would be useful to slice/dice later. The values in `metadata` can be any
|
|
9802
9861
|
* JSON-serializable type, but its keys must be strings.
|
|
9862
|
+
* @param event.origin (Optional) a reference to the source object this dataset record was derived from.
|
|
9803
9863
|
* @param event.id (Optional) a unique identifier for the event. If you don't provide one, Braintrust will generate one for you.
|
|
9804
9864
|
* @param event.output: (Deprecated) The output of your application. Use `expected` instead.
|
|
9805
9865
|
* @returns The `id` of the logged record.
|
|
@@ -9810,7 +9870,8 @@ var Dataset2 = class extends ObjectFetcher {
|
|
|
9810
9870
|
metadata,
|
|
9811
9871
|
tags,
|
|
9812
9872
|
id,
|
|
9813
|
-
output
|
|
9873
|
+
output,
|
|
9874
|
+
origin
|
|
9814
9875
|
}) {
|
|
9815
9876
|
this.validateEvent({ metadata, expected, output, tags });
|
|
9816
9877
|
const rowId = id || (0, import_uuid2.v4)();
|
|
@@ -9822,6 +9883,7 @@ var Dataset2 = class extends ObjectFetcher {
|
|
|
9822
9883
|
metadata,
|
|
9823
9884
|
tags,
|
|
9824
9885
|
output,
|
|
9886
|
+
origin,
|
|
9825
9887
|
isMerge: false
|
|
9826
9888
|
})
|
|
9827
9889
|
);
|
|
@@ -11643,8 +11705,12 @@ async function invoke(args) {
|
|
|
11643
11705
|
|
|
11644
11706
|
// src/trace.ts
|
|
11645
11707
|
var SpanFetcher = class _SpanFetcher extends ObjectFetcher {
|
|
11646
|
-
constructor(objectType, _objectId, rootSpanId, _state, spanTypeFilter) {
|
|
11647
|
-
const filterExpr = _SpanFetcher.buildFilter(
|
|
11708
|
+
constructor(objectType, _objectId, rootSpanId, _state, spanTypeFilter, includeScorers = false) {
|
|
11709
|
+
const filterExpr = _SpanFetcher.buildFilter(
|
|
11710
|
+
rootSpanId,
|
|
11711
|
+
spanTypeFilter,
|
|
11712
|
+
includeScorers
|
|
11713
|
+
);
|
|
11648
11714
|
super(objectType, void 0, void 0, {
|
|
11649
11715
|
filter: filterExpr
|
|
11650
11716
|
});
|
|
@@ -11653,16 +11719,17 @@ var SpanFetcher = class _SpanFetcher extends ObjectFetcher {
|
|
|
11653
11719
|
this._state = _state;
|
|
11654
11720
|
this.spanTypeFilter = spanTypeFilter;
|
|
11655
11721
|
}
|
|
11656
|
-
static buildFilter(rootSpanId, spanTypeFilter) {
|
|
11722
|
+
static buildFilter(rootSpanId, spanTypeFilter, includeScorers = false) {
|
|
11657
11723
|
const children = [
|
|
11658
11724
|
// Base filter: root_span_id = 'value'
|
|
11659
11725
|
{
|
|
11660
11726
|
op: "eq",
|
|
11661
11727
|
left: { op: "ident", name: ["root_span_id"] },
|
|
11662
11728
|
right: { op: "literal", value: rootSpanId }
|
|
11663
|
-
}
|
|
11664
|
-
|
|
11665
|
-
|
|
11729
|
+
}
|
|
11730
|
+
];
|
|
11731
|
+
if (!includeScorers) {
|
|
11732
|
+
children.push({
|
|
11666
11733
|
op: "or",
|
|
11667
11734
|
children: [
|
|
11668
11735
|
{
|
|
@@ -11675,8 +11742,8 @@ var SpanFetcher = class _SpanFetcher extends ObjectFetcher {
|
|
|
11675
11742
|
right: { op: "literal", value: "scorer" }
|
|
11676
11743
|
}
|
|
11677
11744
|
]
|
|
11678
|
-
}
|
|
11679
|
-
|
|
11745
|
+
});
|
|
11746
|
+
}
|
|
11680
11747
|
if (spanTypeFilter && spanTypeFilter.length > 0) {
|
|
11681
11748
|
children.push({
|
|
11682
11749
|
op: "in",
|
|
@@ -11702,35 +11769,49 @@ var CachedSpanFetcher = class {
|
|
|
11702
11769
|
fetchFn;
|
|
11703
11770
|
constructor(objectTypeOrFetchFn, objectId, rootSpanId, getState) {
|
|
11704
11771
|
if (typeof objectTypeOrFetchFn === "function") {
|
|
11705
|
-
this.fetchFn = objectTypeOrFetchFn;
|
|
11772
|
+
this.fetchFn = (spanType) => objectTypeOrFetchFn(spanType);
|
|
11706
11773
|
} else {
|
|
11707
11774
|
const objectType = objectTypeOrFetchFn;
|
|
11708
|
-
this.fetchFn = async (spanType) => {
|
|
11775
|
+
this.fetchFn = async (spanType, includeScorers) => {
|
|
11709
11776
|
const state = await getState();
|
|
11710
11777
|
const fetcher = new SpanFetcher(
|
|
11711
11778
|
objectType,
|
|
11712
11779
|
objectId,
|
|
11713
11780
|
rootSpanId,
|
|
11714
11781
|
state,
|
|
11715
|
-
spanType
|
|
11782
|
+
spanType,
|
|
11783
|
+
includeScorers
|
|
11716
11784
|
);
|
|
11717
11785
|
const rows = await fetcher.fetchedData();
|
|
11718
|
-
return rows.
|
|
11786
|
+
return rows.map((row) => ({
|
|
11719
11787
|
input: row.input,
|
|
11720
11788
|
output: row.output,
|
|
11789
|
+
expected: row.expected,
|
|
11790
|
+
error: row.error,
|
|
11791
|
+
scores: row.scores,
|
|
11792
|
+
metrics: row.metrics,
|
|
11721
11793
|
metadata: row.metadata,
|
|
11722
11794
|
span_id: row.span_id,
|
|
11723
11795
|
span_parents: row.span_parents,
|
|
11796
|
+
is_root: row.is_root,
|
|
11724
11797
|
span_attributes: row.span_attributes,
|
|
11725
11798
|
id: row.id,
|
|
11726
11799
|
_xact_id: row._xact_id,
|
|
11727
11800
|
_pagination_key: row._pagination_key,
|
|
11728
|
-
root_span_id: row.root_span_id
|
|
11801
|
+
root_span_id: row.root_span_id,
|
|
11802
|
+
created: row.created,
|
|
11803
|
+
tags: row.tags
|
|
11729
11804
|
}));
|
|
11730
11805
|
};
|
|
11731
11806
|
}
|
|
11732
11807
|
}
|
|
11733
|
-
async getSpans({
|
|
11808
|
+
async getSpans({
|
|
11809
|
+
spanType,
|
|
11810
|
+
includeScorers = false
|
|
11811
|
+
} = {}) {
|
|
11812
|
+
if (includeScorers) {
|
|
11813
|
+
return this.fetchFn(spanType, true);
|
|
11814
|
+
}
|
|
11734
11815
|
if (this.allFetched) {
|
|
11735
11816
|
return this.getFromCache(spanType);
|
|
11736
11817
|
}
|
|
@@ -11747,7 +11828,7 @@ var CachedSpanFetcher = class {
|
|
|
11747
11828
|
return this.getFromCache(spanType);
|
|
11748
11829
|
}
|
|
11749
11830
|
async fetchSpans(spanType) {
|
|
11750
|
-
const spans = await this.fetchFn(spanType);
|
|
11831
|
+
const spans = await this.fetchFn(spanType, false);
|
|
11751
11832
|
for (const span of spans) {
|
|
11752
11833
|
const type = span.span_attributes?.type ?? "";
|
|
11753
11834
|
const existing = this.spanCache.get(type) ?? [];
|
|
@@ -11825,10 +11906,13 @@ var LocalTrace = class {
|
|
|
11825
11906
|
* First checks the local span cache for recently logged spans, then falls
|
|
11826
11907
|
* back to CachedSpanFetcher which handles BTQL fetching and caching.
|
|
11827
11908
|
*/
|
|
11828
|
-
async getSpans({
|
|
11909
|
+
async getSpans({
|
|
11910
|
+
spanType,
|
|
11911
|
+
includeScorers = false
|
|
11912
|
+
} = {}) {
|
|
11829
11913
|
const cachedSpans = this.state.spanCache.getByRootSpanId(this.rootSpanId);
|
|
11830
11914
|
if (cachedSpans && cachedSpans.length > 0) {
|
|
11831
|
-
let spans = cachedSpans.filter(
|
|
11915
|
+
let spans = includeScorers ? cachedSpans : cachedSpans.filter(
|
|
11832
11916
|
(span) => span.span_attributes?.purpose !== "scorer"
|
|
11833
11917
|
);
|
|
11834
11918
|
if (spanType && spanType.length > 0) {
|
|
@@ -11839,13 +11923,19 @@ var LocalTrace = class {
|
|
|
11839
11923
|
return spans.map((span) => ({
|
|
11840
11924
|
input: span.input,
|
|
11841
11925
|
output: span.output,
|
|
11926
|
+
expected: span.expected,
|
|
11927
|
+
error: span.error,
|
|
11928
|
+
scores: span.scores,
|
|
11929
|
+
metrics: span.metrics,
|
|
11842
11930
|
metadata: span.metadata,
|
|
11843
11931
|
span_id: span.span_id,
|
|
11844
11932
|
span_parents: span.span_parents,
|
|
11845
|
-
|
|
11933
|
+
is_root: span.is_root,
|
|
11934
|
+
span_attributes: span.span_attributes,
|
|
11935
|
+
tags: span.tags
|
|
11846
11936
|
}));
|
|
11847
11937
|
}
|
|
11848
|
-
return this.cachedFetcher.getSpans({ spanType });
|
|
11938
|
+
return this.cachedFetcher.getSpans({ spanType, includeScorers });
|
|
11849
11939
|
}
|
|
11850
11940
|
/**
|
|
11851
11941
|
* Get the thread (preprocessed messages) for this trace.
|
|
@@ -13290,6 +13380,7 @@ var fsSync = __toESM(require("node:fs"));
|
|
|
13290
13380
|
var crypto = __toESM(require("node:crypto"));
|
|
13291
13381
|
var import_node_util3 = require("node:util");
|
|
13292
13382
|
var zlib = __toESM(require("node:zlib"));
|
|
13383
|
+
var dotenv = __toESM(require("dotenv"));
|
|
13293
13384
|
|
|
13294
13385
|
// src/gitutil.ts
|
|
13295
13386
|
var import_simple_git = require("simple-git");
|
|
@@ -13398,11 +13489,11 @@ function truncateToByteLimit(s, byteLimit = 65536) {
|
|
|
13398
13489
|
return new TextDecoder().decode(truncated);
|
|
13399
13490
|
}
|
|
13400
13491
|
async function getRepoInfo(settings) {
|
|
13401
|
-
if (settings
|
|
13492
|
+
if (!settings || settings.collect === "none") {
|
|
13402
13493
|
return void 0;
|
|
13403
13494
|
}
|
|
13404
13495
|
const repo = await repoInfo();
|
|
13405
|
-
if (!repo ||
|
|
13496
|
+
if (!repo || settings.collect === "all") {
|
|
13406
13497
|
return repo;
|
|
13407
13498
|
}
|
|
13408
13499
|
let sanitized = {};
|
|
@@ -17099,11 +17190,11 @@ function resolveDenyOutputPaths(event, defaultDenyOutputPaths) {
|
|
|
17099
17190
|
if (Array.isArray(event?.denyOutputPaths)) {
|
|
17100
17191
|
return event.denyOutputPaths;
|
|
17101
17192
|
}
|
|
17102
|
-
const
|
|
17103
|
-
if (!
|
|
17193
|
+
const firstArgument2 = event?.arguments && event.arguments.length > 0 ? event.arguments[0] : void 0;
|
|
17194
|
+
if (!firstArgument2 || typeof firstArgument2 !== "object") {
|
|
17104
17195
|
return defaultDenyOutputPaths;
|
|
17105
17196
|
}
|
|
17106
|
-
const runtimeDenyOutputPaths =
|
|
17197
|
+
const runtimeDenyOutputPaths = firstArgument2[RUNTIME_DENY_OUTPUT_PATHS];
|
|
17107
17198
|
if (Array.isArray(runtimeDenyOutputPaths) && runtimeDenyOutputPaths.every((path8) => typeof path8 === "string")) {
|
|
17108
17199
|
return runtimeDenyOutputPaths;
|
|
17109
17200
|
}
|
|
@@ -20762,6 +20853,467 @@ function cleanMetrics2(metrics) {
|
|
|
20762
20853
|
return cleaned;
|
|
20763
20854
|
}
|
|
20764
20855
|
|
|
20856
|
+
// src/instrumentation/plugins/openai-agents-channels.ts
|
|
20857
|
+
var openAIAgentsCoreChannels = defineChannels("@openai/agents-core", {
|
|
20858
|
+
onTraceStart: channel({
|
|
20859
|
+
channelName: "tracing.processor.onTraceStart",
|
|
20860
|
+
kind: "async"
|
|
20861
|
+
}),
|
|
20862
|
+
onTraceEnd: channel({
|
|
20863
|
+
channelName: "tracing.processor.onTraceEnd",
|
|
20864
|
+
kind: "async"
|
|
20865
|
+
}),
|
|
20866
|
+
onSpanStart: channel({
|
|
20867
|
+
channelName: "tracing.processor.onSpanStart",
|
|
20868
|
+
kind: "async"
|
|
20869
|
+
}),
|
|
20870
|
+
onSpanEnd: channel({
|
|
20871
|
+
channelName: "tracing.processor.onSpanEnd",
|
|
20872
|
+
kind: "async"
|
|
20873
|
+
})
|
|
20874
|
+
});
|
|
20875
|
+
|
|
20876
|
+
// src/instrumentation/plugins/openai-agents-trace-processor.ts
|
|
20877
|
+
function isSpanData(spanData, type) {
|
|
20878
|
+
return spanData.type === type;
|
|
20879
|
+
}
|
|
20880
|
+
function spanTypeFromAgents(span) {
|
|
20881
|
+
const spanType = span.spanData.type;
|
|
20882
|
+
if (spanType === "function" || spanType === "guardrail" || spanType === "mcp_tools") {
|
|
20883
|
+
return "tool" /* TOOL */;
|
|
20884
|
+
}
|
|
20885
|
+
if (spanType === "generation" || spanType === "response" || spanType === "transcription" || spanType === "speech") {
|
|
20886
|
+
return "llm" /* LLM */;
|
|
20887
|
+
}
|
|
20888
|
+
return "task" /* TASK */;
|
|
20889
|
+
}
|
|
20890
|
+
function spanNameFromAgents(span) {
|
|
20891
|
+
const spanData = span.spanData;
|
|
20892
|
+
if ("name" in spanData && spanData.name) {
|
|
20893
|
+
return spanData.name;
|
|
20894
|
+
}
|
|
20895
|
+
switch (spanData.type) {
|
|
20896
|
+
case "generation":
|
|
20897
|
+
return "Generation";
|
|
20898
|
+
case "response":
|
|
20899
|
+
return "Response";
|
|
20900
|
+
case "handoff":
|
|
20901
|
+
return "Handoff";
|
|
20902
|
+
case "mcp_tools":
|
|
20903
|
+
return isSpanData(spanData, "mcp_tools") && spanData.server ? `List Tools (${spanData.server})` : "MCP List Tools";
|
|
20904
|
+
case "transcription":
|
|
20905
|
+
return "Transcription";
|
|
20906
|
+
case "speech":
|
|
20907
|
+
return "Speech";
|
|
20908
|
+
case "speech_group":
|
|
20909
|
+
return "Speech Group";
|
|
20910
|
+
default:
|
|
20911
|
+
return "Unknown";
|
|
20912
|
+
}
|
|
20913
|
+
}
|
|
20914
|
+
function getTimeElapsed(end, start) {
|
|
20915
|
+
if (!start || !end) {
|
|
20916
|
+
return void 0;
|
|
20917
|
+
}
|
|
20918
|
+
const startTime = new Date(start).getTime();
|
|
20919
|
+
const endTime = new Date(end).getTime();
|
|
20920
|
+
if (Number.isNaN(startTime) || Number.isNaN(endTime)) {
|
|
20921
|
+
return void 0;
|
|
20922
|
+
}
|
|
20923
|
+
return (endTime - startTime) / 1e3;
|
|
20924
|
+
}
|
|
20925
|
+
function getNumberProperty2(obj, key) {
|
|
20926
|
+
if (!isObject(obj) || !(key in obj)) {
|
|
20927
|
+
return void 0;
|
|
20928
|
+
}
|
|
20929
|
+
const value = obj[key];
|
|
20930
|
+
return typeof value === "number" ? value : void 0;
|
|
20931
|
+
}
|
|
20932
|
+
function parseUsageMetrics(usage) {
|
|
20933
|
+
const metrics = {};
|
|
20934
|
+
if (!isObject(usage)) {
|
|
20935
|
+
return metrics;
|
|
20936
|
+
}
|
|
20937
|
+
const promptTokens = getNumberProperty2(usage, "prompt_tokens") ?? getNumberProperty2(usage, "input_tokens") ?? getNumberProperty2(usage, "promptTokens") ?? getNumberProperty2(usage, "inputTokens");
|
|
20938
|
+
const completionTokens = getNumberProperty2(usage, "completion_tokens") ?? getNumberProperty2(usage, "output_tokens") ?? getNumberProperty2(usage, "completionTokens") ?? getNumberProperty2(usage, "outputTokens");
|
|
20939
|
+
const totalTokens = getNumberProperty2(usage, "total_tokens") ?? getNumberProperty2(usage, "totalTokens");
|
|
20940
|
+
if (promptTokens !== void 0) {
|
|
20941
|
+
metrics.prompt_tokens = promptTokens;
|
|
20942
|
+
}
|
|
20943
|
+
if (completionTokens !== void 0) {
|
|
20944
|
+
metrics.completion_tokens = completionTokens;
|
|
20945
|
+
}
|
|
20946
|
+
if (totalTokens !== void 0) {
|
|
20947
|
+
metrics.tokens = totalTokens;
|
|
20948
|
+
} else if (promptTokens !== void 0 && completionTokens !== void 0) {
|
|
20949
|
+
metrics.tokens = promptTokens + completionTokens;
|
|
20950
|
+
}
|
|
20951
|
+
const inputDetails = usage.input_tokens_details;
|
|
20952
|
+
const cachedTokens = getNumberProperty2(inputDetails, "cached_tokens");
|
|
20953
|
+
const cacheWriteTokens = getNumberProperty2(
|
|
20954
|
+
inputDetails,
|
|
20955
|
+
"cache_write_tokens"
|
|
20956
|
+
);
|
|
20957
|
+
if (cachedTokens !== void 0) {
|
|
20958
|
+
metrics.prompt_cached_tokens = cachedTokens;
|
|
20959
|
+
}
|
|
20960
|
+
if (cacheWriteTokens !== void 0) {
|
|
20961
|
+
metrics.prompt_cache_creation_tokens = cacheWriteTokens;
|
|
20962
|
+
}
|
|
20963
|
+
return metrics;
|
|
20964
|
+
}
|
|
20965
|
+
var OpenAIAgentsTraceProcessor = class _OpenAIAgentsTraceProcessor {
|
|
20966
|
+
static DEFAULT_MAX_TRACES = 1e4;
|
|
20967
|
+
logger;
|
|
20968
|
+
maxTraces;
|
|
20969
|
+
traceSpans = /* @__PURE__ */ new Map();
|
|
20970
|
+
traceOrder = [];
|
|
20971
|
+
_traceSpans = this.traceSpans;
|
|
20972
|
+
constructor(options = {}) {
|
|
20973
|
+
this.logger = options.logger;
|
|
20974
|
+
this.maxTraces = options.maxTraces ?? _OpenAIAgentsTraceProcessor.DEFAULT_MAX_TRACES;
|
|
20975
|
+
}
|
|
20976
|
+
evictOldestTrace() {
|
|
20977
|
+
const oldestTraceId = this.traceOrder.shift();
|
|
20978
|
+
if (oldestTraceId) {
|
|
20979
|
+
this.traceSpans.delete(oldestTraceId);
|
|
20980
|
+
}
|
|
20981
|
+
}
|
|
20982
|
+
onTraceStart(trace) {
|
|
20983
|
+
if (!trace?.traceId) {
|
|
20984
|
+
return Promise.resolve();
|
|
20985
|
+
}
|
|
20986
|
+
if (this.traceOrder.length >= this.maxTraces) {
|
|
20987
|
+
this.evictOldestTrace();
|
|
20988
|
+
}
|
|
20989
|
+
const current = currentSpan();
|
|
20990
|
+
const span = current && current !== NOOP_SPAN ? current.startSpan({
|
|
20991
|
+
name: trace.name,
|
|
20992
|
+
type: "task" /* TASK */
|
|
20993
|
+
}) : this.logger ? this.logger.startSpan({
|
|
20994
|
+
name: trace.name,
|
|
20995
|
+
type: "task" /* TASK */
|
|
20996
|
+
}) : startSpan({
|
|
20997
|
+
name: trace.name,
|
|
20998
|
+
type: "task" /* TASK */
|
|
20999
|
+
});
|
|
21000
|
+
span.log({
|
|
21001
|
+
input: "Agent workflow started",
|
|
21002
|
+
metadata: {
|
|
21003
|
+
group_id: trace.groupId,
|
|
21004
|
+
...trace.metadata || {}
|
|
21005
|
+
}
|
|
21006
|
+
});
|
|
21007
|
+
this.traceSpans.set(trace.traceId, {
|
|
21008
|
+
rootSpan: span,
|
|
21009
|
+
childSpans: /* @__PURE__ */ new Map(),
|
|
21010
|
+
metadata: {
|
|
21011
|
+
firstInput: null,
|
|
21012
|
+
lastOutput: null
|
|
21013
|
+
}
|
|
21014
|
+
});
|
|
21015
|
+
this.traceOrder.push(trace.traceId);
|
|
21016
|
+
return Promise.resolve();
|
|
21017
|
+
}
|
|
21018
|
+
async onTraceEnd(trace) {
|
|
21019
|
+
const traceData = this.traceSpans.get(trace?.traceId);
|
|
21020
|
+
if (!traceData) {
|
|
21021
|
+
return;
|
|
21022
|
+
}
|
|
21023
|
+
try {
|
|
21024
|
+
traceData.rootSpan.log({
|
|
21025
|
+
input: traceData.metadata.firstInput,
|
|
21026
|
+
output: traceData.metadata.lastOutput
|
|
21027
|
+
});
|
|
21028
|
+
traceData.rootSpan.end();
|
|
21029
|
+
await traceData.rootSpan.flush();
|
|
21030
|
+
} finally {
|
|
21031
|
+
this.traceSpans.delete(trace.traceId);
|
|
21032
|
+
const orderIndex = this.traceOrder.indexOf(trace.traceId);
|
|
21033
|
+
if (orderIndex > -1) {
|
|
21034
|
+
this.traceOrder.splice(orderIndex, 1);
|
|
21035
|
+
}
|
|
21036
|
+
}
|
|
21037
|
+
}
|
|
21038
|
+
onSpanStart(span) {
|
|
21039
|
+
if (!span?.spanId || !span.traceId) {
|
|
21040
|
+
return Promise.resolve();
|
|
21041
|
+
}
|
|
21042
|
+
const traceData = this.traceSpans.get(span.traceId);
|
|
21043
|
+
if (!traceData) {
|
|
21044
|
+
return Promise.resolve();
|
|
21045
|
+
}
|
|
21046
|
+
const parentSpan = span.parentId ? traceData.childSpans.get(span.parentId) : traceData.rootSpan;
|
|
21047
|
+
if (!parentSpan) {
|
|
21048
|
+
return Promise.resolve();
|
|
21049
|
+
}
|
|
21050
|
+
const childSpan = parentSpan.startSpan({
|
|
21051
|
+
name: spanNameFromAgents(span),
|
|
21052
|
+
type: spanTypeFromAgents(span)
|
|
21053
|
+
});
|
|
21054
|
+
traceData.childSpans.set(span.spanId, childSpan);
|
|
21055
|
+
return Promise.resolve();
|
|
21056
|
+
}
|
|
21057
|
+
onSpanEnd(span) {
|
|
21058
|
+
if (!span?.spanId || !span.traceId) {
|
|
21059
|
+
return Promise.resolve();
|
|
21060
|
+
}
|
|
21061
|
+
const traceData = this.traceSpans.get(span.traceId);
|
|
21062
|
+
if (!traceData) {
|
|
21063
|
+
return Promise.resolve();
|
|
21064
|
+
}
|
|
21065
|
+
const braintrustSpan = traceData.childSpans.get(span.spanId);
|
|
21066
|
+
if (!braintrustSpan) {
|
|
21067
|
+
return Promise.resolve();
|
|
21068
|
+
}
|
|
21069
|
+
const logData = this.extractLogData(span);
|
|
21070
|
+
braintrustSpan.log({
|
|
21071
|
+
error: span.error,
|
|
21072
|
+
...logData
|
|
21073
|
+
});
|
|
21074
|
+
braintrustSpan.end();
|
|
21075
|
+
traceData.childSpans.delete(span.spanId);
|
|
21076
|
+
const input = logData.input;
|
|
21077
|
+
const output = logData.output;
|
|
21078
|
+
if (traceData.metadata.firstInput === null && input != null) {
|
|
21079
|
+
traceData.metadata.firstInput = input;
|
|
21080
|
+
}
|
|
21081
|
+
if (output != null) {
|
|
21082
|
+
traceData.metadata.lastOutput = output;
|
|
21083
|
+
}
|
|
21084
|
+
return Promise.resolve();
|
|
21085
|
+
}
|
|
21086
|
+
async shutdown() {
|
|
21087
|
+
if (this.logger && typeof this.logger.flush === "function") {
|
|
21088
|
+
await this.logger.flush();
|
|
21089
|
+
}
|
|
21090
|
+
}
|
|
21091
|
+
async forceFlush() {
|
|
21092
|
+
if (this.logger && typeof this.logger.flush === "function") {
|
|
21093
|
+
await this.logger.flush();
|
|
21094
|
+
}
|
|
21095
|
+
}
|
|
21096
|
+
extractLogData(span) {
|
|
21097
|
+
const spanData = span.spanData;
|
|
21098
|
+
switch (spanData.type) {
|
|
21099
|
+
case "agent":
|
|
21100
|
+
return this.extractAgentLogData(spanData);
|
|
21101
|
+
case "response":
|
|
21102
|
+
return this.extractResponseLogData(spanData, span);
|
|
21103
|
+
case "function":
|
|
21104
|
+
return this.extractFunctionLogData(spanData);
|
|
21105
|
+
case "handoff":
|
|
21106
|
+
return this.extractHandoffLogData(spanData);
|
|
21107
|
+
case "guardrail":
|
|
21108
|
+
return this.extractGuardrailLogData(spanData);
|
|
21109
|
+
case "generation":
|
|
21110
|
+
return this.extractGenerationLogData(spanData, span);
|
|
21111
|
+
case "custom":
|
|
21112
|
+
return this.extractCustomLogData(spanData);
|
|
21113
|
+
case "mcp_tools":
|
|
21114
|
+
return this.extractMCPListToolsLogData(spanData);
|
|
21115
|
+
case "transcription":
|
|
21116
|
+
return this.extractTranscriptionLogData(spanData);
|
|
21117
|
+
case "speech":
|
|
21118
|
+
return this.extractSpeechLogData(spanData);
|
|
21119
|
+
case "speech_group":
|
|
21120
|
+
return this.extractSpeechGroupLogData(spanData);
|
|
21121
|
+
default:
|
|
21122
|
+
return {};
|
|
21123
|
+
}
|
|
21124
|
+
}
|
|
21125
|
+
extractAgentLogData(spanData) {
|
|
21126
|
+
return {
|
|
21127
|
+
metadata: {
|
|
21128
|
+
tools: spanData.tools,
|
|
21129
|
+
handoffs: spanData.handoffs,
|
|
21130
|
+
output_type: spanData.output_type
|
|
21131
|
+
}
|
|
21132
|
+
};
|
|
21133
|
+
}
|
|
21134
|
+
extractResponseLogData(spanData, span) {
|
|
21135
|
+
const response = spanData._response;
|
|
21136
|
+
const output = isObject(response) ? response.output : void 0;
|
|
21137
|
+
const usage = isObject(response) ? response.usage : void 0;
|
|
21138
|
+
const metrics = {
|
|
21139
|
+
...this.extractTimingMetrics(span),
|
|
21140
|
+
...parseUsageMetrics(usage)
|
|
21141
|
+
};
|
|
21142
|
+
return {
|
|
21143
|
+
input: spanData._input,
|
|
21144
|
+
output,
|
|
21145
|
+
metadata: isObject(response) ? this.omitKeys(response, ["output", "usage"]) : {},
|
|
21146
|
+
metrics
|
|
21147
|
+
};
|
|
21148
|
+
}
|
|
21149
|
+
extractFunctionLogData(spanData) {
|
|
21150
|
+
return {
|
|
21151
|
+
input: spanData.input,
|
|
21152
|
+
output: spanData.output
|
|
21153
|
+
};
|
|
21154
|
+
}
|
|
21155
|
+
extractHandoffLogData(spanData) {
|
|
21156
|
+
return {
|
|
21157
|
+
metadata: {
|
|
21158
|
+
from_agent: spanData.from_agent,
|
|
21159
|
+
to_agent: spanData.to_agent
|
|
21160
|
+
}
|
|
21161
|
+
};
|
|
21162
|
+
}
|
|
21163
|
+
extractGuardrailLogData(spanData) {
|
|
21164
|
+
return {
|
|
21165
|
+
metadata: {
|
|
21166
|
+
triggered: spanData.triggered
|
|
21167
|
+
}
|
|
21168
|
+
};
|
|
21169
|
+
}
|
|
21170
|
+
extractGenerationLogData(spanData, span) {
|
|
21171
|
+
return {
|
|
21172
|
+
input: spanData.input,
|
|
21173
|
+
output: spanData.output,
|
|
21174
|
+
metadata: {
|
|
21175
|
+
model: spanData.model,
|
|
21176
|
+
model_config: spanData.model_config
|
|
21177
|
+
},
|
|
21178
|
+
metrics: {
|
|
21179
|
+
...this.extractTimingMetrics(span),
|
|
21180
|
+
...parseUsageMetrics(spanData.usage)
|
|
21181
|
+
}
|
|
21182
|
+
};
|
|
21183
|
+
}
|
|
21184
|
+
extractCustomLogData(spanData) {
|
|
21185
|
+
return spanData.data || {};
|
|
21186
|
+
}
|
|
21187
|
+
extractMCPListToolsLogData(spanData) {
|
|
21188
|
+
return {
|
|
21189
|
+
output: spanData.result,
|
|
21190
|
+
metadata: {
|
|
21191
|
+
server: spanData.server
|
|
21192
|
+
}
|
|
21193
|
+
};
|
|
21194
|
+
}
|
|
21195
|
+
extractTranscriptionLogData(spanData) {
|
|
21196
|
+
return {
|
|
21197
|
+
input: spanData.input,
|
|
21198
|
+
output: spanData.output,
|
|
21199
|
+
metadata: {
|
|
21200
|
+
model: spanData.model,
|
|
21201
|
+
model_config: spanData.model_config
|
|
21202
|
+
}
|
|
21203
|
+
};
|
|
21204
|
+
}
|
|
21205
|
+
extractSpeechLogData(spanData) {
|
|
21206
|
+
return {
|
|
21207
|
+
input: spanData.input,
|
|
21208
|
+
output: spanData.output,
|
|
21209
|
+
metadata: {
|
|
21210
|
+
model: spanData.model,
|
|
21211
|
+
model_config: spanData.model_config
|
|
21212
|
+
}
|
|
21213
|
+
};
|
|
21214
|
+
}
|
|
21215
|
+
extractSpeechGroupLogData(spanData) {
|
|
21216
|
+
return {
|
|
21217
|
+
input: spanData.input
|
|
21218
|
+
};
|
|
21219
|
+
}
|
|
21220
|
+
extractTimingMetrics(span) {
|
|
21221
|
+
const timeToFirstToken = getTimeElapsed(
|
|
21222
|
+
span.endedAt ?? void 0,
|
|
21223
|
+
span.startedAt ?? void 0
|
|
21224
|
+
);
|
|
21225
|
+
return timeToFirstToken === void 0 ? {} : { time_to_first_token: timeToFirstToken };
|
|
21226
|
+
}
|
|
21227
|
+
omitKeys(value, keys) {
|
|
21228
|
+
const result = {};
|
|
21229
|
+
for (const [key, fieldValue] of Object.entries(value)) {
|
|
21230
|
+
if (!keys.includes(key)) {
|
|
21231
|
+
result[key] = fieldValue;
|
|
21232
|
+
}
|
|
21233
|
+
}
|
|
21234
|
+
return result;
|
|
21235
|
+
}
|
|
21236
|
+
};
|
|
21237
|
+
|
|
21238
|
+
// src/instrumentation/plugins/openai-agents-plugin.ts
|
|
21239
|
+
function firstArgument(args) {
|
|
21240
|
+
if (Array.isArray(args)) {
|
|
21241
|
+
return args[0];
|
|
21242
|
+
}
|
|
21243
|
+
if (isObject(args) && "length" in args && typeof args.length === "number" && Number.isInteger(args.length) && args.length >= 0) {
|
|
21244
|
+
return Array.from(args)[0];
|
|
21245
|
+
}
|
|
21246
|
+
return void 0;
|
|
21247
|
+
}
|
|
21248
|
+
function isOpenAIAgentsTrace(value) {
|
|
21249
|
+
return isObject(value) && value.type === "trace" && typeof value.traceId === "string";
|
|
21250
|
+
}
|
|
21251
|
+
function isOpenAIAgentsSpan(value) {
|
|
21252
|
+
return isObject(value) && value.type === "trace.span" && typeof value.traceId === "string" && typeof value.spanId === "string";
|
|
21253
|
+
}
|
|
21254
|
+
var OpenAIAgentsPlugin = class extends BasePlugin {
|
|
21255
|
+
processor = new OpenAIAgentsTraceProcessor();
|
|
21256
|
+
onEnable() {
|
|
21257
|
+
this.subscribeToTraceLifecycle();
|
|
21258
|
+
}
|
|
21259
|
+
onDisable() {
|
|
21260
|
+
this.unsubscribers = unsubscribeAll(this.unsubscribers);
|
|
21261
|
+
void this.processor.shutdown();
|
|
21262
|
+
}
|
|
21263
|
+
subscribeToTraceLifecycle() {
|
|
21264
|
+
const traceStartChannel = openAIAgentsCoreChannels.onTraceStart.tracingChannel();
|
|
21265
|
+
const traceStartHandlers = {
|
|
21266
|
+
start: (event) => {
|
|
21267
|
+
const trace = firstArgument(event.arguments);
|
|
21268
|
+
if (isOpenAIAgentsTrace(trace)) {
|
|
21269
|
+
void this.processor.onTraceStart(trace);
|
|
21270
|
+
}
|
|
21271
|
+
}
|
|
21272
|
+
};
|
|
21273
|
+
traceStartChannel.subscribe(traceStartHandlers);
|
|
21274
|
+
this.unsubscribers.push(
|
|
21275
|
+
() => traceStartChannel.unsubscribe(traceStartHandlers)
|
|
21276
|
+
);
|
|
21277
|
+
const traceEndChannel = openAIAgentsCoreChannels.onTraceEnd.tracingChannel();
|
|
21278
|
+
const traceEndHandlers = {
|
|
21279
|
+
start: (event) => {
|
|
21280
|
+
const trace = firstArgument(event.arguments);
|
|
21281
|
+
if (isOpenAIAgentsTrace(trace)) {
|
|
21282
|
+
void this.processor.onTraceEnd(trace);
|
|
21283
|
+
}
|
|
21284
|
+
}
|
|
21285
|
+
};
|
|
21286
|
+
traceEndChannel.subscribe(traceEndHandlers);
|
|
21287
|
+
this.unsubscribers.push(
|
|
21288
|
+
() => traceEndChannel.unsubscribe(traceEndHandlers)
|
|
21289
|
+
);
|
|
21290
|
+
const spanStartChannel = openAIAgentsCoreChannels.onSpanStart.tracingChannel();
|
|
21291
|
+
const spanStartHandlers = {
|
|
21292
|
+
start: (event) => {
|
|
21293
|
+
const span = firstArgument(event.arguments);
|
|
21294
|
+
if (isOpenAIAgentsSpan(span)) {
|
|
21295
|
+
void this.processor.onSpanStart(span);
|
|
21296
|
+
}
|
|
21297
|
+
}
|
|
21298
|
+
};
|
|
21299
|
+
spanStartChannel.subscribe(spanStartHandlers);
|
|
21300
|
+
this.unsubscribers.push(
|
|
21301
|
+
() => spanStartChannel.unsubscribe(spanStartHandlers)
|
|
21302
|
+
);
|
|
21303
|
+
const spanEndChannel = openAIAgentsCoreChannels.onSpanEnd.tracingChannel();
|
|
21304
|
+
const spanEndHandlers = {
|
|
21305
|
+
start: (event) => {
|
|
21306
|
+
const span = firstArgument(event.arguments);
|
|
21307
|
+
if (isOpenAIAgentsSpan(span)) {
|
|
21308
|
+
void this.processor.onSpanEnd(span);
|
|
21309
|
+
}
|
|
21310
|
+
}
|
|
21311
|
+
};
|
|
21312
|
+
spanEndChannel.subscribe(spanEndHandlers);
|
|
21313
|
+
this.unsubscribers.push(() => spanEndChannel.unsubscribe(spanEndHandlers));
|
|
21314
|
+
}
|
|
21315
|
+
};
|
|
21316
|
+
|
|
20765
21317
|
// src/instrumentation/plugins/google-genai-channels.ts
|
|
20766
21318
|
var googleGenAIChannels = defineChannels("@google/genai", {
|
|
20767
21319
|
generateContent: channel({
|
|
@@ -27054,18 +27606,1726 @@ var GitHubCopilotPlugin = class extends BasePlugin {
|
|
|
27054
27606
|
}
|
|
27055
27607
|
};
|
|
27056
27608
|
|
|
27057
|
-
// src/instrumentation/
|
|
27058
|
-
|
|
27059
|
-
|
|
27609
|
+
// src/instrumentation/plugins/flue-channels.ts
|
|
27610
|
+
var flueChannels = defineChannels("@flue/runtime", {
|
|
27611
|
+
createContext: channel({
|
|
27612
|
+
channelName: "createFlueContext",
|
|
27613
|
+
kind: "sync-stream"
|
|
27614
|
+
}),
|
|
27615
|
+
openSession: channel({
|
|
27616
|
+
channelName: "Harness.openSession",
|
|
27617
|
+
kind: "async"
|
|
27618
|
+
}),
|
|
27619
|
+
contextEvent: channel({
|
|
27620
|
+
channelName: "context.event",
|
|
27621
|
+
kind: "sync-stream"
|
|
27622
|
+
}),
|
|
27623
|
+
prompt: channel({
|
|
27624
|
+
channelName: "session.prompt",
|
|
27625
|
+
kind: "async"
|
|
27626
|
+
}),
|
|
27627
|
+
skill: channel({
|
|
27628
|
+
channelName: "session.skill",
|
|
27629
|
+
kind: "async"
|
|
27630
|
+
}),
|
|
27631
|
+
task: channel({
|
|
27632
|
+
channelName: "session.task",
|
|
27633
|
+
kind: "async"
|
|
27634
|
+
}),
|
|
27635
|
+
compact: channel({
|
|
27636
|
+
channelName: "session.compact",
|
|
27637
|
+
kind: "async"
|
|
27638
|
+
})
|
|
27639
|
+
});
|
|
27640
|
+
|
|
27641
|
+
// src/wrappers/flue.ts
|
|
27642
|
+
var WRAPPED_FLUE_CONTEXT = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-context");
|
|
27643
|
+
var WRAPPED_FLUE_HARNESS = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-harness");
|
|
27644
|
+
var WRAPPED_FLUE_SESSION = /* @__PURE__ */ Symbol.for("braintrust.flue.wrapped-session");
|
|
27645
|
+
var SUBSCRIBED_FLUE_CONTEXT_EVENTS = /* @__PURE__ */ Symbol.for(
|
|
27646
|
+
"braintrust.flue.subscribed-context-events"
|
|
27647
|
+
);
|
|
27648
|
+
function patchFlueContextInPlace(ctx) {
|
|
27649
|
+
const context2 = ctx;
|
|
27650
|
+
if (context2[WRAPPED_FLUE_CONTEXT]) {
|
|
27651
|
+
return ctx;
|
|
27652
|
+
}
|
|
27653
|
+
const originalInit = context2.init.bind(context2);
|
|
27654
|
+
try {
|
|
27655
|
+
Object.defineProperty(context2, WRAPPED_FLUE_CONTEXT, {
|
|
27656
|
+
configurable: false,
|
|
27657
|
+
enumerable: false,
|
|
27658
|
+
value: true
|
|
27659
|
+
});
|
|
27660
|
+
Object.defineProperty(context2, "init", {
|
|
27661
|
+
configurable: true,
|
|
27662
|
+
value: async function wrappedFlueInit(options) {
|
|
27663
|
+
const harness = await originalInit(options);
|
|
27664
|
+
return wrapFlueHarness(harness);
|
|
27665
|
+
},
|
|
27666
|
+
writable: true
|
|
27667
|
+
});
|
|
27668
|
+
} catch {
|
|
27669
|
+
}
|
|
27670
|
+
return ctx;
|
|
27060
27671
|
}
|
|
27061
|
-
|
|
27062
|
-
|
|
27063
|
-
|
|
27064
|
-
|
|
27065
|
-
|
|
27066
|
-
|
|
27067
|
-
|
|
27672
|
+
function subscribeFlueContextEvents(ctx, options = {}) {
|
|
27673
|
+
if (!ctx || typeof ctx !== "object" || typeof ctx.subscribeEvent !== "function") {
|
|
27674
|
+
return void 0;
|
|
27675
|
+
}
|
|
27676
|
+
const context2 = ctx;
|
|
27677
|
+
const captureTurnSpans = options.captureTurnSpans ?? true;
|
|
27678
|
+
const existingSubscription = context2[SUBSCRIBED_FLUE_CONTEXT_EVENTS];
|
|
27679
|
+
if (existingSubscription) {
|
|
27680
|
+
if (existingSubscription.captureTurnSpans || !captureTurnSpans) {
|
|
27681
|
+
return void 0;
|
|
27682
|
+
}
|
|
27683
|
+
try {
|
|
27684
|
+
existingSubscription.unsubscribe();
|
|
27685
|
+
} catch {
|
|
27686
|
+
}
|
|
27687
|
+
}
|
|
27688
|
+
try {
|
|
27689
|
+
const unsubscribe = ctx.subscribeEvent((event) => {
|
|
27690
|
+
flueChannels.contextEvent.traceSync(() => void 0, {
|
|
27691
|
+
arguments: [event],
|
|
27692
|
+
captureTurnSpans,
|
|
27693
|
+
context: ctx
|
|
27694
|
+
});
|
|
27695
|
+
});
|
|
27696
|
+
if (existingSubscription) {
|
|
27697
|
+
existingSubscription.captureTurnSpans = captureTurnSpans;
|
|
27698
|
+
existingSubscription.unsubscribe = unsubscribe;
|
|
27699
|
+
} else {
|
|
27700
|
+
Object.defineProperty(context2, SUBSCRIBED_FLUE_CONTEXT_EVENTS, {
|
|
27701
|
+
configurable: false,
|
|
27702
|
+
enumerable: false,
|
|
27703
|
+
value: {
|
|
27704
|
+
captureTurnSpans,
|
|
27705
|
+
unsubscribe
|
|
27706
|
+
}
|
|
27707
|
+
});
|
|
27708
|
+
}
|
|
27709
|
+
return unsubscribe;
|
|
27710
|
+
} catch {
|
|
27711
|
+
return void 0;
|
|
27712
|
+
}
|
|
27713
|
+
}
|
|
27714
|
+
function wrapFlueHarness(harness) {
|
|
27715
|
+
if (!isPlausibleFlueHarness(harness)) {
|
|
27716
|
+
return harness;
|
|
27717
|
+
}
|
|
27718
|
+
const target = harness;
|
|
27719
|
+
if (target[WRAPPED_FLUE_HARNESS]) {
|
|
27720
|
+
return harness;
|
|
27721
|
+
}
|
|
27722
|
+
const originalSession = target.session.bind(target);
|
|
27723
|
+
try {
|
|
27724
|
+
Object.defineProperty(target, WRAPPED_FLUE_HARNESS, {
|
|
27725
|
+
configurable: false,
|
|
27726
|
+
enumerable: false,
|
|
27727
|
+
value: true
|
|
27728
|
+
});
|
|
27729
|
+
Object.defineProperty(target, "session", {
|
|
27730
|
+
configurable: true,
|
|
27731
|
+
value: async function wrappedFlueHarnessSession(name, options) {
|
|
27732
|
+
const session = await originalSession(name, options);
|
|
27733
|
+
return patchFlueSessionInPlace(session);
|
|
27734
|
+
},
|
|
27735
|
+
writable: true
|
|
27736
|
+
});
|
|
27737
|
+
const sessions = target.sessions;
|
|
27738
|
+
if (sessions && typeof sessions === "object") {
|
|
27739
|
+
patchFlueSessionFactory(sessions, "get");
|
|
27740
|
+
patchFlueSessionFactory(sessions, "create");
|
|
27741
|
+
}
|
|
27742
|
+
} catch {
|
|
27743
|
+
}
|
|
27744
|
+
return harness;
|
|
27745
|
+
}
|
|
27746
|
+
function patchFlueSessionInPlace(session) {
|
|
27747
|
+
if (session[WRAPPED_FLUE_SESSION]) {
|
|
27748
|
+
return session;
|
|
27749
|
+
}
|
|
27750
|
+
try {
|
|
27751
|
+
Object.defineProperty(session, WRAPPED_FLUE_SESSION, {
|
|
27752
|
+
configurable: false,
|
|
27753
|
+
enumerable: false,
|
|
27754
|
+
value: true
|
|
27755
|
+
});
|
|
27756
|
+
patchCallHandleMethod(session, "prompt", flueChannels.prompt);
|
|
27757
|
+
patchCallHandleMethod(session, "skill", flueChannels.skill);
|
|
27758
|
+
patchCallHandleMethod(session, "task", flueChannels.task);
|
|
27759
|
+
patchCompact(session);
|
|
27760
|
+
} catch {
|
|
27761
|
+
}
|
|
27762
|
+
return session;
|
|
27763
|
+
}
|
|
27764
|
+
function patchFlueSessionFactory(sessions, method) {
|
|
27765
|
+
const original = sessions[method];
|
|
27766
|
+
if (typeof original !== "function") {
|
|
27767
|
+
return;
|
|
27768
|
+
}
|
|
27769
|
+
const bound = original.bind(sessions);
|
|
27770
|
+
Object.defineProperty(sessions, method, {
|
|
27771
|
+
configurable: true,
|
|
27772
|
+
value: async function wrappedFlueSessionFactory(name, options) {
|
|
27773
|
+
const session = await bound(name, options);
|
|
27774
|
+
return patchFlueSessionInPlace(session);
|
|
27775
|
+
},
|
|
27776
|
+
writable: true
|
|
27777
|
+
});
|
|
27778
|
+
}
|
|
27779
|
+
function patchCallHandleMethod(session, method, channel2) {
|
|
27780
|
+
const original = session[method];
|
|
27781
|
+
if (typeof original !== "function") {
|
|
27782
|
+
return;
|
|
27783
|
+
}
|
|
27784
|
+
const bound = original.bind(session);
|
|
27785
|
+
Object.defineProperty(session, method, {
|
|
27786
|
+
configurable: true,
|
|
27787
|
+
value(input, options) {
|
|
27788
|
+
const args = [input, options];
|
|
27789
|
+
const { originalResult, traced: traced2 } = traceFlueOperation(channel2, {
|
|
27790
|
+
context: {
|
|
27791
|
+
arguments: args,
|
|
27792
|
+
operation: method,
|
|
27793
|
+
session
|
|
27794
|
+
},
|
|
27795
|
+
run: () => bound(input, options)
|
|
27796
|
+
});
|
|
27797
|
+
return preserveCallHandle(originalResult, traced2);
|
|
27798
|
+
},
|
|
27799
|
+
writable: true
|
|
27800
|
+
});
|
|
27801
|
+
}
|
|
27802
|
+
function patchCompact(session) {
|
|
27803
|
+
const original = session.compact;
|
|
27804
|
+
if (typeof original !== "function") {
|
|
27805
|
+
return;
|
|
27806
|
+
}
|
|
27807
|
+
const bound = original.bind(session);
|
|
27808
|
+
Object.defineProperty(session, "compact", {
|
|
27809
|
+
configurable: true,
|
|
27810
|
+
value() {
|
|
27811
|
+
const context2 = {
|
|
27812
|
+
arguments: [],
|
|
27813
|
+
operation: "compact",
|
|
27814
|
+
session
|
|
27815
|
+
};
|
|
27816
|
+
return flueChannels.compact.tracePromise(() => bound(), context2);
|
|
27817
|
+
},
|
|
27818
|
+
writable: true
|
|
27819
|
+
});
|
|
27820
|
+
}
|
|
27821
|
+
function traceFlueOperation(channel2, args) {
|
|
27822
|
+
const tracingChannel2 = channel2.tracingChannel();
|
|
27823
|
+
const context2 = args.context;
|
|
27824
|
+
let originalResult;
|
|
27825
|
+
let traced2;
|
|
27826
|
+
const run2 = () => {
|
|
27827
|
+
try {
|
|
27828
|
+
originalResult = args.run();
|
|
27829
|
+
tracingChannel2.end?.publish(context2);
|
|
27830
|
+
} catch (error2) {
|
|
27831
|
+
context2.error = normalizeError3(error2);
|
|
27832
|
+
tracingChannel2.error?.publish(context2);
|
|
27833
|
+
tracingChannel2.end?.publish(context2);
|
|
27834
|
+
throw error2;
|
|
27835
|
+
}
|
|
27836
|
+
traced2 = Promise.resolve(originalResult).then(
|
|
27837
|
+
(result) => {
|
|
27838
|
+
context2.result = result;
|
|
27839
|
+
tracingChannel2.asyncStart?.publish(context2);
|
|
27840
|
+
tracingChannel2.asyncEnd?.publish(context2);
|
|
27841
|
+
return result;
|
|
27842
|
+
},
|
|
27843
|
+
(error2) => {
|
|
27844
|
+
context2.error = normalizeError3(error2);
|
|
27845
|
+
tracingChannel2.error?.publish(context2);
|
|
27846
|
+
tracingChannel2.asyncStart?.publish(context2);
|
|
27847
|
+
tracingChannel2.asyncEnd?.publish(context2);
|
|
27848
|
+
throw error2;
|
|
27849
|
+
}
|
|
27850
|
+
);
|
|
27851
|
+
};
|
|
27852
|
+
if (tracingChannel2.start?.runStores) {
|
|
27853
|
+
tracingChannel2.start.runStores(context2, run2);
|
|
27854
|
+
} else {
|
|
27855
|
+
tracingChannel2.start?.publish(context2);
|
|
27856
|
+
run2();
|
|
27857
|
+
}
|
|
27858
|
+
return { originalResult, traced: traced2 };
|
|
27859
|
+
}
|
|
27860
|
+
function normalizeError3(error2) {
|
|
27861
|
+
return error2 instanceof Error ? error2 : new Error(String(error2));
|
|
27862
|
+
}
|
|
27863
|
+
function preserveCallHandle(originalHandle, traced2) {
|
|
27864
|
+
if (!isFlueCallHandle(originalHandle)) {
|
|
27865
|
+
return traced2;
|
|
27866
|
+
}
|
|
27867
|
+
const handle = originalHandle;
|
|
27868
|
+
const wrapped = {
|
|
27869
|
+
get signal() {
|
|
27870
|
+
return handle.signal;
|
|
27871
|
+
},
|
|
27872
|
+
abort(reason) {
|
|
27873
|
+
return handle.abort(reason);
|
|
27874
|
+
},
|
|
27875
|
+
then(onfulfilled, onrejected) {
|
|
27876
|
+
return traced2.then(onfulfilled, onrejected);
|
|
27877
|
+
}
|
|
27878
|
+
};
|
|
27879
|
+
return wrapped;
|
|
27880
|
+
}
|
|
27881
|
+
function isPlausibleFlueHarness(value) {
|
|
27882
|
+
return !!value && typeof value === "object" && typeof value.session === "function";
|
|
27883
|
+
}
|
|
27884
|
+
function isFlueCallHandle(value) {
|
|
27885
|
+
return !!value && typeof value === "object" && typeof value.then === "function" && typeof value.abort === "function" && "signal" in value;
|
|
27886
|
+
}
|
|
27887
|
+
|
|
27888
|
+
// src/instrumentation/plugins/flue-plugin.ts
|
|
27889
|
+
var FluePlugin = class extends BasePlugin {
|
|
27890
|
+
activeOperationsById = /* @__PURE__ */ new Map();
|
|
27891
|
+
activeOperationsByScope = /* @__PURE__ */ new Map();
|
|
27892
|
+
compactionsByScope = /* @__PURE__ */ new Map();
|
|
27893
|
+
pendingOperationsByKey = /* @__PURE__ */ new Map();
|
|
27894
|
+
tasksById = /* @__PURE__ */ new Map();
|
|
27895
|
+
toolsById = /* @__PURE__ */ new Map();
|
|
27896
|
+
turnsByScope = /* @__PURE__ */ new Map();
|
|
27897
|
+
onEnable() {
|
|
27898
|
+
this.subscribeToContextCreation();
|
|
27899
|
+
this.subscribeToSessionCreation();
|
|
27900
|
+
this.subscribeToContextEvents();
|
|
27901
|
+
this.subscribeToSessionOperations();
|
|
27902
|
+
}
|
|
27903
|
+
onDisable() {
|
|
27904
|
+
for (const unsubscribe of this.unsubscribers) {
|
|
27905
|
+
unsubscribe();
|
|
27906
|
+
}
|
|
27907
|
+
this.unsubscribers = [];
|
|
27908
|
+
this.activeOperationsById.clear();
|
|
27909
|
+
this.activeOperationsByScope.clear();
|
|
27910
|
+
this.compactionsByScope.clear();
|
|
27911
|
+
this.pendingOperationsByKey.clear();
|
|
27912
|
+
this.tasksById.clear();
|
|
27913
|
+
this.toolsById.clear();
|
|
27914
|
+
this.turnsByScope.clear();
|
|
27915
|
+
}
|
|
27916
|
+
subscribeToContextCreation() {
|
|
27917
|
+
const channel2 = flueChannels.createContext.tracingChannel();
|
|
27918
|
+
const handlers = {
|
|
27919
|
+
end: (event) => {
|
|
27920
|
+
const ctx = event.result;
|
|
27921
|
+
if (!ctx) {
|
|
27922
|
+
return;
|
|
27923
|
+
}
|
|
27924
|
+
subscribeFlueContextEvents(ctx, { captureTurnSpans: false });
|
|
27925
|
+
patchFlueContextInPlace(ctx);
|
|
27926
|
+
},
|
|
27927
|
+
error: () => {
|
|
27928
|
+
}
|
|
27929
|
+
};
|
|
27930
|
+
channel2.subscribe(handlers);
|
|
27931
|
+
this.unsubscribers.push(() => {
|
|
27932
|
+
channel2.unsubscribe(handlers);
|
|
27933
|
+
});
|
|
27934
|
+
}
|
|
27935
|
+
subscribeToSessionCreation() {
|
|
27936
|
+
const channel2 = flueChannels.openSession.tracingChannel();
|
|
27937
|
+
const handlers = {
|
|
27938
|
+
asyncEnd: (event) => {
|
|
27939
|
+
if (event.result) {
|
|
27940
|
+
patchFlueSessionInPlace(
|
|
27941
|
+
event.result
|
|
27942
|
+
);
|
|
27943
|
+
}
|
|
27944
|
+
if (event.harness) {
|
|
27945
|
+
wrapFlueHarness(event.harness);
|
|
27946
|
+
}
|
|
27947
|
+
},
|
|
27948
|
+
error: () => {
|
|
27949
|
+
}
|
|
27950
|
+
};
|
|
27951
|
+
channel2.subscribe(handlers);
|
|
27952
|
+
this.unsubscribers.push(() => {
|
|
27953
|
+
channel2.unsubscribe(handlers);
|
|
27954
|
+
});
|
|
27955
|
+
}
|
|
27956
|
+
subscribeToSessionOperations() {
|
|
27957
|
+
this.subscribeToSessionOperation(flueChannels.prompt);
|
|
27958
|
+
this.subscribeToSessionOperation(flueChannels.skill);
|
|
27959
|
+
this.subscribeToSessionOperation(flueChannels.task);
|
|
27960
|
+
this.subscribeToCompact();
|
|
27961
|
+
}
|
|
27962
|
+
subscribeToSessionOperation(channel2) {
|
|
27963
|
+
const tracingChannel2 = channel2.tracingChannel();
|
|
27964
|
+
const states = /* @__PURE__ */ new WeakMap();
|
|
27965
|
+
const ensureState2 = (event) => {
|
|
27966
|
+
const existing = states.get(event);
|
|
27967
|
+
if (existing) {
|
|
27968
|
+
return existing;
|
|
27969
|
+
}
|
|
27970
|
+
const state = this.startOperationState({
|
|
27971
|
+
args: event.arguments,
|
|
27972
|
+
moduleVersion: typeof event.moduleVersion === "string" ? event.moduleVersion : void 0,
|
|
27973
|
+
operation: event.operation,
|
|
27974
|
+
session: event.session
|
|
27975
|
+
});
|
|
27976
|
+
states.set(event, state);
|
|
27977
|
+
return state;
|
|
27978
|
+
};
|
|
27979
|
+
const unbindCurrentSpanStore = this.bindCurrentSpanStoreToOperationStart(
|
|
27980
|
+
tracingChannel2,
|
|
27981
|
+
ensureState2
|
|
27982
|
+
);
|
|
27983
|
+
const handlers = {
|
|
27984
|
+
start: (event) => {
|
|
27985
|
+
ensureState2(event);
|
|
27986
|
+
},
|
|
27987
|
+
asyncEnd: (event) => {
|
|
27988
|
+
this.endOperationState(states.get(event), event.result);
|
|
27989
|
+
states.delete(event);
|
|
27990
|
+
},
|
|
27991
|
+
error: (event) => {
|
|
27992
|
+
const state = states.get(event);
|
|
27993
|
+
if (state && event.error) {
|
|
27994
|
+
safeLog3(state.span, { error: errorToString(event.error) });
|
|
27995
|
+
this.finishOperationState(state);
|
|
27996
|
+
}
|
|
27997
|
+
states.delete(event);
|
|
27998
|
+
}
|
|
27999
|
+
};
|
|
28000
|
+
tracingChannel2.subscribe(handlers);
|
|
28001
|
+
this.unsubscribers.push(() => {
|
|
28002
|
+
unbindCurrentSpanStore?.();
|
|
28003
|
+
tracingChannel2.unsubscribe(handlers);
|
|
28004
|
+
});
|
|
28005
|
+
}
|
|
28006
|
+
subscribeToCompact() {
|
|
28007
|
+
const tracingChannel2 = flueChannels.compact.tracingChannel();
|
|
28008
|
+
const states = /* @__PURE__ */ new WeakMap();
|
|
28009
|
+
const ensureState2 = (event) => {
|
|
28010
|
+
const existing = states.get(event);
|
|
28011
|
+
if (existing) {
|
|
28012
|
+
return existing;
|
|
28013
|
+
}
|
|
28014
|
+
const state = this.startOperationState({
|
|
28015
|
+
args: [],
|
|
28016
|
+
moduleVersion: typeof event.moduleVersion === "string" ? event.moduleVersion : void 0,
|
|
28017
|
+
operation: event.operation,
|
|
28018
|
+
session: event.session
|
|
28019
|
+
});
|
|
28020
|
+
states.set(event, state);
|
|
28021
|
+
return state;
|
|
28022
|
+
};
|
|
28023
|
+
const unbindCurrentSpanStore = this.bindCurrentSpanStoreToOperationStart(
|
|
28024
|
+
tracingChannel2,
|
|
28025
|
+
ensureState2
|
|
28026
|
+
);
|
|
28027
|
+
const handlers = {
|
|
28028
|
+
start: (event) => {
|
|
28029
|
+
ensureState2(event);
|
|
28030
|
+
},
|
|
28031
|
+
asyncEnd: (event) => {
|
|
28032
|
+
this.endOperationState(states.get(event), void 0);
|
|
28033
|
+
states.delete(event);
|
|
28034
|
+
},
|
|
28035
|
+
error: (event) => {
|
|
28036
|
+
const state = states.get(event);
|
|
28037
|
+
if (state && event.error) {
|
|
28038
|
+
safeLog3(state.span, { error: errorToString(event.error) });
|
|
28039
|
+
this.finishOperationState(state);
|
|
28040
|
+
}
|
|
28041
|
+
states.delete(event);
|
|
28042
|
+
}
|
|
28043
|
+
};
|
|
28044
|
+
tracingChannel2.subscribe(handlers);
|
|
28045
|
+
this.unsubscribers.push(() => {
|
|
28046
|
+
unbindCurrentSpanStore?.();
|
|
28047
|
+
tracingChannel2.unsubscribe(handlers);
|
|
28048
|
+
});
|
|
28049
|
+
}
|
|
28050
|
+
subscribeToContextEvents() {
|
|
28051
|
+
const channel2 = flueChannels.contextEvent.tracingChannel();
|
|
28052
|
+
const handlers = {
|
|
28053
|
+
start: (event) => {
|
|
28054
|
+
const flueEvent = event.arguments[0];
|
|
28055
|
+
if (!flueEvent) {
|
|
28056
|
+
return;
|
|
28057
|
+
}
|
|
28058
|
+
try {
|
|
28059
|
+
this.handleFlueEvent(flueEvent, {
|
|
28060
|
+
captureTurnSpans: event.captureTurnSpans !== false
|
|
28061
|
+
});
|
|
28062
|
+
} catch (error2) {
|
|
28063
|
+
logInstrumentationError3("Flue event", error2);
|
|
28064
|
+
}
|
|
28065
|
+
},
|
|
28066
|
+
error: () => {
|
|
28067
|
+
}
|
|
28068
|
+
};
|
|
28069
|
+
channel2.subscribe(handlers);
|
|
28070
|
+
this.unsubscribers.push(() => {
|
|
28071
|
+
channel2.unsubscribe(handlers);
|
|
28072
|
+
});
|
|
28073
|
+
}
|
|
28074
|
+
bindCurrentSpanStoreToOperationStart(tracingChannel2, ensureState2) {
|
|
28075
|
+
const state = _internalGetGlobalState();
|
|
28076
|
+
const startChannel = tracingChannel2.start;
|
|
28077
|
+
const contextManager = state?.contextManager;
|
|
28078
|
+
const currentSpanStore = contextManager ? contextManager[BRAINTRUST_CURRENT_SPAN_STORE] : void 0;
|
|
28079
|
+
if (!currentSpanStore || !startChannel) {
|
|
28080
|
+
return void 0;
|
|
28081
|
+
}
|
|
28082
|
+
startChannel.bindStore(currentSpanStore, (event) => {
|
|
28083
|
+
const operationState = ensureState2(event);
|
|
28084
|
+
return contextManager.wrapSpanForStore(operationState.span);
|
|
28085
|
+
});
|
|
28086
|
+
return () => {
|
|
28087
|
+
startChannel.unbindStore(currentSpanStore);
|
|
28088
|
+
};
|
|
28089
|
+
}
|
|
28090
|
+
startOperationState(args) {
|
|
28091
|
+
const sessionName = getSessionName(args.session);
|
|
28092
|
+
const metadata = {
|
|
28093
|
+
...extractOperationInputMetadata(args.operation, args.args),
|
|
28094
|
+
...extractSessionMetadata(args.session),
|
|
28095
|
+
"flue.operation": args.operation,
|
|
28096
|
+
provider: "flue",
|
|
28097
|
+
...args.moduleVersion ? { "flue.version": args.moduleVersion } : {}
|
|
28098
|
+
};
|
|
28099
|
+
const span = startSpan({
|
|
28100
|
+
name: `flue.session.${args.operation}`,
|
|
28101
|
+
spanAttributes: { type: "task" /* TASK */ }
|
|
28102
|
+
});
|
|
28103
|
+
const state = {
|
|
28104
|
+
metadata,
|
|
28105
|
+
operation: args.operation,
|
|
28106
|
+
sessionName,
|
|
28107
|
+
span,
|
|
28108
|
+
startTime: getCurrentUnixTimestamp()
|
|
28109
|
+
};
|
|
28110
|
+
safeLog3(span, {
|
|
28111
|
+
input: extractOperationInput(args.operation, args.args),
|
|
28112
|
+
metadata
|
|
28113
|
+
});
|
|
28114
|
+
this.pendingOperationQueue(operationKey(sessionName, args.operation)).push(
|
|
28115
|
+
state
|
|
28116
|
+
);
|
|
28117
|
+
addOperationToScope(
|
|
28118
|
+
this.activeOperationsByScope,
|
|
28119
|
+
sessionName ?? "unknown",
|
|
28120
|
+
state
|
|
28121
|
+
);
|
|
28122
|
+
return state;
|
|
28123
|
+
}
|
|
28124
|
+
endOperationState(state, result) {
|
|
28125
|
+
if (!state) {
|
|
28126
|
+
return;
|
|
28127
|
+
}
|
|
28128
|
+
const metadata = {
|
|
28129
|
+
...state.metadata,
|
|
28130
|
+
...extractPromptResponseMetadata(result)
|
|
28131
|
+
};
|
|
28132
|
+
const metrics = {
|
|
28133
|
+
...buildDurationMetrics3(state.startTime),
|
|
28134
|
+
...metricsFromUsage(result?.usage)
|
|
28135
|
+
};
|
|
28136
|
+
safeLog3(state.span, {
|
|
28137
|
+
metadata,
|
|
28138
|
+
metrics,
|
|
28139
|
+
output: extractOperationOutput(result)
|
|
28140
|
+
});
|
|
28141
|
+
this.finishCompactionsForOperation(state);
|
|
28142
|
+
this.finishOperationState(state);
|
|
28143
|
+
}
|
|
28144
|
+
finishOperationState(state) {
|
|
28145
|
+
removePendingOperation(this.pendingOperationsByKey, state);
|
|
28146
|
+
if (state.operationId) {
|
|
28147
|
+
this.activeOperationsById.delete(state.operationId);
|
|
28148
|
+
}
|
|
28149
|
+
removeScopedOperation(this.activeOperationsByScope, state);
|
|
28150
|
+
state.span.end();
|
|
28151
|
+
}
|
|
28152
|
+
handleFlueEvent(event, options) {
|
|
28153
|
+
switch (event.type) {
|
|
28154
|
+
case "operation_start":
|
|
28155
|
+
this.handleOperationStart(event);
|
|
28156
|
+
return;
|
|
28157
|
+
case "operation":
|
|
28158
|
+
this.handleOperation(event);
|
|
28159
|
+
return;
|
|
28160
|
+
case "text_delta":
|
|
28161
|
+
if (!options.captureTurnSpans) {
|
|
28162
|
+
return;
|
|
28163
|
+
}
|
|
28164
|
+
this.ensureTurnState(event).text.push(
|
|
28165
|
+
typeof event.text === "string" ? event.text : ""
|
|
28166
|
+
);
|
|
28167
|
+
return;
|
|
28168
|
+
case "thinking_start":
|
|
28169
|
+
if (!options.captureTurnSpans) {
|
|
28170
|
+
return;
|
|
28171
|
+
}
|
|
28172
|
+
this.handleThinkingStart(event);
|
|
28173
|
+
return;
|
|
28174
|
+
case "thinking_delta":
|
|
28175
|
+
if (!options.captureTurnSpans) {
|
|
28176
|
+
return;
|
|
28177
|
+
}
|
|
28178
|
+
this.handleThinkingDelta(event);
|
|
28179
|
+
return;
|
|
28180
|
+
case "thinking_end":
|
|
28181
|
+
if (!options.captureTurnSpans) {
|
|
28182
|
+
return;
|
|
28183
|
+
}
|
|
28184
|
+
this.handleThinkingEnd(event);
|
|
28185
|
+
return;
|
|
28186
|
+
case "turn":
|
|
28187
|
+
if (!options.captureTurnSpans) {
|
|
28188
|
+
return;
|
|
28189
|
+
}
|
|
28190
|
+
this.handleTurn(event);
|
|
28191
|
+
return;
|
|
28192
|
+
case "tool_start":
|
|
28193
|
+
this.handleToolStart(event, options);
|
|
28194
|
+
return;
|
|
28195
|
+
case "tool_call":
|
|
28196
|
+
this.handleToolCall(event);
|
|
28197
|
+
return;
|
|
28198
|
+
case "task_start":
|
|
28199
|
+
this.handleTaskStart(event);
|
|
28200
|
+
return;
|
|
28201
|
+
case "task":
|
|
28202
|
+
this.handleTask(event);
|
|
28203
|
+
return;
|
|
28204
|
+
case "compaction_start":
|
|
28205
|
+
this.handleCompactionStart(event);
|
|
28206
|
+
return;
|
|
28207
|
+
case "compaction":
|
|
28208
|
+
this.handleCompaction(event);
|
|
28209
|
+
return;
|
|
28210
|
+
default:
|
|
28211
|
+
return;
|
|
28212
|
+
}
|
|
28213
|
+
}
|
|
28214
|
+
handleOperationStart(event) {
|
|
28215
|
+
if (!isInstrumentedOperation(event.operationKind)) {
|
|
28216
|
+
return;
|
|
28217
|
+
}
|
|
28218
|
+
const state = this.takePendingOperationForEvent(event);
|
|
28219
|
+
if (!state) {
|
|
28220
|
+
return;
|
|
28221
|
+
}
|
|
28222
|
+
state.operationId = event.operationId;
|
|
28223
|
+
this.activeOperationsById.set(event.operationId, state);
|
|
28224
|
+
addScopedOperation(this.activeOperationsByScope, event, state);
|
|
28225
|
+
state.metadata = {
|
|
28226
|
+
...state.metadata,
|
|
28227
|
+
...extractEventMetadata(event),
|
|
28228
|
+
"flue.operation_id": event.operationId
|
|
28229
|
+
};
|
|
28230
|
+
safeLog3(state.span, { metadata: state.metadata });
|
|
28231
|
+
}
|
|
28232
|
+
handleOperation(event) {
|
|
28233
|
+
const state = event.operationId ? this.activeOperationsById.get(event.operationId) : void 0;
|
|
28234
|
+
if (!state) {
|
|
28235
|
+
return;
|
|
28236
|
+
}
|
|
28237
|
+
const metadata = {
|
|
28238
|
+
...state.metadata,
|
|
28239
|
+
...extractEventMetadata(event),
|
|
28240
|
+
...typeof event.durationMs === "number" ? { "flue.duration_ms": event.durationMs } : {},
|
|
28241
|
+
...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
|
|
28242
|
+
};
|
|
28243
|
+
const metrics = metricsFromUsage(event.usage);
|
|
28244
|
+
safeLog3(state.span, {
|
|
28245
|
+
...event.error ? { error: errorToString(event.error) } : {},
|
|
28246
|
+
metadata,
|
|
28247
|
+
...Object.keys(metrics).length ? { metrics } : {}
|
|
28248
|
+
});
|
|
28249
|
+
}
|
|
28250
|
+
ensureTurnState(event) {
|
|
28251
|
+
const scope = scopeKey(event);
|
|
28252
|
+
const existing = this.turnsByScope.get(scope);
|
|
28253
|
+
if (existing) {
|
|
28254
|
+
return existing;
|
|
28255
|
+
}
|
|
28256
|
+
const parent = this.parentSpanForEvent(event);
|
|
28257
|
+
const metadata = {
|
|
28258
|
+
...extractEventMetadata(event),
|
|
28259
|
+
provider: "flue"
|
|
28260
|
+
};
|
|
28261
|
+
const span = startFlueSpan(parent, {
|
|
28262
|
+
name: "flue.turn",
|
|
28263
|
+
spanAttributes: { type: "llm" /* LLM */ }
|
|
28264
|
+
});
|
|
28265
|
+
const state = {
|
|
28266
|
+
metadata,
|
|
28267
|
+
span,
|
|
28268
|
+
hasThinking: false,
|
|
28269
|
+
startTime: getCurrentUnixTimestamp(),
|
|
28270
|
+
text: [],
|
|
28271
|
+
thinking: [],
|
|
28272
|
+
toolCalls: []
|
|
28273
|
+
};
|
|
28274
|
+
safeLog3(span, { metadata });
|
|
28275
|
+
this.turnsByScope.set(scope, state);
|
|
28276
|
+
return state;
|
|
28277
|
+
}
|
|
28278
|
+
handleTurn(event) {
|
|
28279
|
+
const scope = scopeKey(event);
|
|
28280
|
+
const state = this.ensureTurnState(event);
|
|
28281
|
+
const text = state.text.join("");
|
|
28282
|
+
const reasoning = state.finalThinking ?? state.thinking.join("");
|
|
28283
|
+
const outputReasoning = reasoning || (state.hasThinking ? "[reasoning stream present; content unavailable]" : void 0);
|
|
28284
|
+
const metadata = {
|
|
28285
|
+
...state.metadata,
|
|
28286
|
+
...extractEventMetadata(event),
|
|
28287
|
+
...event.model ? { model: event.model, "flue.model": event.model } : {},
|
|
28288
|
+
...event.stopReason ? { "flue.stop_reason": event.stopReason } : {},
|
|
28289
|
+
...event.isError !== void 0 ? { "flue.is_error": event.isError } : {},
|
|
28290
|
+
provider: "flue"
|
|
28291
|
+
};
|
|
28292
|
+
safeLog3(state.span, {
|
|
28293
|
+
...event.error ? { error: errorToString(event.error) } : {},
|
|
28294
|
+
metadata,
|
|
28295
|
+
metrics: {
|
|
28296
|
+
...durationMsMetrics(event.durationMs),
|
|
28297
|
+
...metricsFromUsage(event.usage)
|
|
28298
|
+
},
|
|
28299
|
+
output: toAssistantOutput(
|
|
28300
|
+
text,
|
|
28301
|
+
event.stopReason,
|
|
28302
|
+
outputReasoning,
|
|
28303
|
+
state.toolCalls
|
|
28304
|
+
)
|
|
28305
|
+
});
|
|
28306
|
+
state.span.end();
|
|
28307
|
+
this.turnsByScope.delete(scope);
|
|
28308
|
+
}
|
|
28309
|
+
handleThinkingDelta(event) {
|
|
28310
|
+
const delta = event.delta;
|
|
28311
|
+
if (typeof delta !== "string" || !delta) {
|
|
28312
|
+
return;
|
|
28313
|
+
}
|
|
28314
|
+
const state = this.ensureTurnState(event);
|
|
28315
|
+
state.hasThinking = true;
|
|
28316
|
+
state.metadata["flue.thinking"] = true;
|
|
28317
|
+
state.thinking.push(delta);
|
|
28318
|
+
}
|
|
28319
|
+
handleThinkingStart(event) {
|
|
28320
|
+
const state = this.ensureTurnState(event);
|
|
28321
|
+
state.hasThinking = true;
|
|
28322
|
+
state.metadata["flue.thinking"] = true;
|
|
28323
|
+
}
|
|
28324
|
+
handleThinkingEnd(event) {
|
|
28325
|
+
const state = this.ensureTurnState(event);
|
|
28326
|
+
state.hasThinking = true;
|
|
28327
|
+
state.metadata["flue.thinking"] = true;
|
|
28328
|
+
if (typeof event.content === "string" && event.content) {
|
|
28329
|
+
state.finalThinking = event.content;
|
|
28330
|
+
}
|
|
28331
|
+
}
|
|
28332
|
+
handleToolStart(event, options) {
|
|
28333
|
+
const toolCallId = event.toolCallId;
|
|
28334
|
+
if (!toolCallId) {
|
|
28335
|
+
return;
|
|
28336
|
+
}
|
|
28337
|
+
const parent = this.parentSpanForEvent(event);
|
|
28338
|
+
const scope = scopeKey(event);
|
|
28339
|
+
let turnState = this.turnsByScope.get(scope);
|
|
28340
|
+
if (!turnState && parent && options.captureTurnSpans) {
|
|
28341
|
+
turnState = this.ensureTurnState(event);
|
|
28342
|
+
}
|
|
28343
|
+
const metadata = {
|
|
28344
|
+
...extractEventMetadata(event),
|
|
28345
|
+
...event.toolName ? { "flue.tool_name": event.toolName } : {},
|
|
28346
|
+
"flue.tool_call_id": toolCallId,
|
|
28347
|
+
provider: "flue"
|
|
28348
|
+
};
|
|
28349
|
+
const span = startFlueSpan(parent, {
|
|
28350
|
+
name: `tool: ${event.toolName ?? "unknown"}`,
|
|
28351
|
+
spanAttributes: { type: "tool" /* TOOL */ }
|
|
28352
|
+
});
|
|
28353
|
+
if (turnState) {
|
|
28354
|
+
turnState.toolCalls.push({
|
|
28355
|
+
args: event.args,
|
|
28356
|
+
toolCallId,
|
|
28357
|
+
toolName: event.toolName
|
|
28358
|
+
});
|
|
28359
|
+
}
|
|
28360
|
+
safeLog3(span, {
|
|
28361
|
+
input: event.args,
|
|
28362
|
+
metadata
|
|
28363
|
+
});
|
|
28364
|
+
this.toolsById.set(toolKey(event), {
|
|
28365
|
+
metadata,
|
|
28366
|
+
span,
|
|
28367
|
+
startTime: getCurrentUnixTimestamp()
|
|
28368
|
+
});
|
|
28369
|
+
}
|
|
28370
|
+
handleToolCall(event) {
|
|
28371
|
+
const key = toolKey(event);
|
|
28372
|
+
const state = this.toolsById.get(key) ?? this.startSyntheticToolState(event, event.toolName ?? "unknown");
|
|
28373
|
+
const metadata = {
|
|
28374
|
+
...state.metadata,
|
|
28375
|
+
...extractEventMetadata(event),
|
|
28376
|
+
...event.toolName ? { "flue.tool_name": event.toolName } : {},
|
|
28377
|
+
...event.toolCallId ? { "flue.tool_call_id": event.toolCallId } : {},
|
|
28378
|
+
...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
|
|
28379
|
+
};
|
|
28380
|
+
safeLog3(state.span, {
|
|
28381
|
+
...event.isError ? { error: errorToString(event.result) } : {},
|
|
28382
|
+
metadata,
|
|
28383
|
+
metrics: durationMsMetrics(event.durationMs),
|
|
28384
|
+
output: event.result
|
|
28385
|
+
});
|
|
28386
|
+
state.span.end();
|
|
28387
|
+
this.toolsById.delete(key);
|
|
28388
|
+
}
|
|
28389
|
+
handleTaskStart(event) {
|
|
28390
|
+
const parent = this.parentSpanForEvent(event);
|
|
28391
|
+
const metadata = {
|
|
28392
|
+
...extractEventMetadata(event),
|
|
28393
|
+
...event.role ? { "flue.role": event.role } : {},
|
|
28394
|
+
...event.cwd ? { "flue.cwd": event.cwd } : {},
|
|
28395
|
+
"flue.task_id": event.taskId,
|
|
28396
|
+
provider: "flue"
|
|
28397
|
+
};
|
|
28398
|
+
const span = startFlueSpan(parent, {
|
|
28399
|
+
name: "flue.task",
|
|
28400
|
+
spanAttributes: { type: "task" /* TASK */ }
|
|
28401
|
+
});
|
|
28402
|
+
safeLog3(span, {
|
|
28403
|
+
input: event.prompt,
|
|
28404
|
+
metadata
|
|
28405
|
+
});
|
|
28406
|
+
this.tasksById.set(event.taskId, {
|
|
28407
|
+
metadata,
|
|
28408
|
+
span,
|
|
28409
|
+
startTime: getCurrentUnixTimestamp()
|
|
28410
|
+
});
|
|
28411
|
+
}
|
|
28412
|
+
handleTask(event) {
|
|
28413
|
+
const state = this.tasksById.get(event.taskId);
|
|
28414
|
+
if (!state) {
|
|
28415
|
+
return;
|
|
28416
|
+
}
|
|
28417
|
+
safeLog3(state.span, {
|
|
28418
|
+
...event.isError ? { error: errorToString(event.result) } : {},
|
|
28419
|
+
metadata: {
|
|
28420
|
+
...state.metadata,
|
|
28421
|
+
...extractEventMetadata(event),
|
|
28422
|
+
...event.isError !== void 0 ? { "flue.is_error": event.isError } : {}
|
|
28423
|
+
},
|
|
28424
|
+
metrics: durationMsMetrics(event.durationMs),
|
|
28425
|
+
output: event.result
|
|
28426
|
+
});
|
|
28427
|
+
state.span.end();
|
|
28428
|
+
this.tasksById.delete(event.taskId);
|
|
28429
|
+
}
|
|
28430
|
+
handleCompactionStart(event) {
|
|
28431
|
+
const operationState = this.operationStateForEvent(event);
|
|
28432
|
+
const parent = operationState?.span ?? this.parentSpanForEvent(event);
|
|
28433
|
+
const metadata = {
|
|
28434
|
+
...extractEventMetadata(event),
|
|
28435
|
+
...event.reason ? { "flue.compaction_reason": event.reason } : {},
|
|
28436
|
+
provider: "flue"
|
|
28437
|
+
};
|
|
28438
|
+
const input = {
|
|
28439
|
+
...typeof event.estimatedTokens === "number" ? { estimatedTokens: event.estimatedTokens } : {},
|
|
28440
|
+
...event.reason ? { reason: event.reason } : {}
|
|
28441
|
+
};
|
|
28442
|
+
const span = startFlueSpan(parent, {
|
|
28443
|
+
name: "flue.compaction",
|
|
28444
|
+
spanAttributes: { type: "task" /* TASK */ }
|
|
28445
|
+
});
|
|
28446
|
+
safeLog3(span, {
|
|
28447
|
+
input,
|
|
28448
|
+
metadata
|
|
28449
|
+
});
|
|
28450
|
+
this.compactionsByScope.set(scopeKey(event), {
|
|
28451
|
+
input,
|
|
28452
|
+
metadata,
|
|
28453
|
+
operationState,
|
|
28454
|
+
span,
|
|
28455
|
+
startTime: getCurrentUnixTimestamp()
|
|
28456
|
+
});
|
|
28457
|
+
}
|
|
28458
|
+
handleCompaction(event) {
|
|
28459
|
+
const key = scopeKey(event);
|
|
28460
|
+
const state = this.compactionsByScope.get(key) ?? this.findCompactionState(event);
|
|
28461
|
+
if (!state) {
|
|
28462
|
+
return;
|
|
28463
|
+
}
|
|
28464
|
+
safeLog3(state.span, {
|
|
28465
|
+
metadata: {
|
|
28466
|
+
...state.metadata,
|
|
28467
|
+
...extractEventMetadata(event),
|
|
28468
|
+
...typeof event.messagesBefore === "number" ? { "flue.messages_before": event.messagesBefore } : {},
|
|
28469
|
+
...typeof event.messagesAfter === "number" ? { "flue.messages_after": event.messagesAfter } : {}
|
|
28470
|
+
},
|
|
28471
|
+
metrics: {
|
|
28472
|
+
...durationMsMetrics(event.durationMs),
|
|
28473
|
+
...metricsFromUsage(event.usage)
|
|
28474
|
+
},
|
|
28475
|
+
output: {
|
|
28476
|
+
messagesAfter: event.messagesAfter,
|
|
28477
|
+
messagesBefore: event.messagesBefore
|
|
28478
|
+
}
|
|
28479
|
+
});
|
|
28480
|
+
state.span.end();
|
|
28481
|
+
this.deleteCompactionState(state);
|
|
28482
|
+
}
|
|
28483
|
+
findCompactionState(event) {
|
|
28484
|
+
const operationState = this.operationStateForEvent(event);
|
|
28485
|
+
for (const state of this.compactionsByScope.values()) {
|
|
28486
|
+
if (operationState && state.operationState === operationState) {
|
|
28487
|
+
return state;
|
|
28488
|
+
}
|
|
28489
|
+
}
|
|
28490
|
+
return void 0;
|
|
28491
|
+
}
|
|
28492
|
+
finishCompactionsForOperation(operationState) {
|
|
28493
|
+
for (const state of [...this.compactionsByScope.values()]) {
|
|
28494
|
+
if (state.operationState !== operationState) {
|
|
28495
|
+
continue;
|
|
28496
|
+
}
|
|
28497
|
+
safeLog3(state.span, {
|
|
28498
|
+
input: state.input,
|
|
28499
|
+
metadata: state.metadata,
|
|
28500
|
+
metrics: {
|
|
28501
|
+
...buildDurationMetrics3(state.startTime)
|
|
28502
|
+
},
|
|
28503
|
+
output: { completed: true }
|
|
28504
|
+
});
|
|
28505
|
+
state.span.end();
|
|
28506
|
+
this.deleteCompactionState(state);
|
|
28507
|
+
}
|
|
28508
|
+
}
|
|
28509
|
+
deleteCompactionState(state) {
|
|
28510
|
+
for (const [key, candidate] of this.compactionsByScope) {
|
|
28511
|
+
if (candidate !== state) {
|
|
28512
|
+
continue;
|
|
28513
|
+
}
|
|
28514
|
+
this.compactionsByScope.delete(key);
|
|
28515
|
+
return;
|
|
28516
|
+
}
|
|
28517
|
+
}
|
|
28518
|
+
startSyntheticToolState(event, toolName) {
|
|
28519
|
+
const parent = this.parentSpanForEvent(event);
|
|
28520
|
+
const metadata = {
|
|
28521
|
+
...extractEventMetadata(event),
|
|
28522
|
+
...event.toolCallId ? { "flue.tool_call_id": event.toolCallId } : {},
|
|
28523
|
+
"flue.tool_name": toolName,
|
|
28524
|
+
provider: "flue"
|
|
28525
|
+
};
|
|
28526
|
+
const span = startFlueSpan(parent, {
|
|
28527
|
+
name: `tool: ${toolName}`,
|
|
28528
|
+
spanAttributes: { type: "tool" /* TOOL */ }
|
|
28529
|
+
});
|
|
28530
|
+
safeLog3(span, { metadata });
|
|
28531
|
+
return { metadata, span, startTime: getCurrentUnixTimestamp() };
|
|
28532
|
+
}
|
|
28533
|
+
operationStateForEvent(event) {
|
|
28534
|
+
if (event.operationId) {
|
|
28535
|
+
const operation = this.activeOperationsById.get(event.operationId) ?? this.promotePendingOperationForEvent(event);
|
|
28536
|
+
if (operation) {
|
|
28537
|
+
return operation;
|
|
28538
|
+
}
|
|
28539
|
+
}
|
|
28540
|
+
return this.activeOperationForEventScope(event) ?? this.pendingOperationForEventScope(event);
|
|
28541
|
+
}
|
|
28542
|
+
parentSpanForEvent(event) {
|
|
28543
|
+
if (event.operationId) {
|
|
28544
|
+
const operation = this.operationStateForEvent(event);
|
|
28545
|
+
if (operation) {
|
|
28546
|
+
return operation.span;
|
|
28547
|
+
}
|
|
28548
|
+
}
|
|
28549
|
+
if (event.taskId) {
|
|
28550
|
+
return this.tasksById.get(event.taskId)?.span;
|
|
28551
|
+
}
|
|
28552
|
+
return this.operationStateForEvent(event)?.span;
|
|
28553
|
+
}
|
|
28554
|
+
promotePendingOperationForEvent(event) {
|
|
28555
|
+
if (!event.operationId) {
|
|
28556
|
+
return void 0;
|
|
28557
|
+
}
|
|
28558
|
+
const scopePrefixes = operationScopePrefixes(event);
|
|
28559
|
+
for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
|
|
28560
|
+
if (!candidateQueue.length || !operationKeyMatchesScopes(candidateKey, scopePrefixes)) {
|
|
28561
|
+
continue;
|
|
28562
|
+
}
|
|
28563
|
+
const state = candidateQueue.shift();
|
|
28564
|
+
if (!state) {
|
|
28565
|
+
return void 0;
|
|
28566
|
+
}
|
|
28567
|
+
state.operationId = event.operationId;
|
|
28568
|
+
this.activeOperationsById.set(event.operationId, state);
|
|
28569
|
+
addScopedOperation(this.activeOperationsByScope, event, state);
|
|
28570
|
+
state.metadata = {
|
|
28571
|
+
...state.metadata,
|
|
28572
|
+
...extractEventMetadata(event),
|
|
28573
|
+
"flue.operation_id": event.operationId
|
|
28574
|
+
};
|
|
28575
|
+
safeLog3(state.span, { metadata: state.metadata });
|
|
28576
|
+
return state;
|
|
28577
|
+
}
|
|
28578
|
+
return void 0;
|
|
28579
|
+
}
|
|
28580
|
+
activeOperationForEventScope(event) {
|
|
28581
|
+
for (const scope of operationScopeNames(event)) {
|
|
28582
|
+
const operations = this.activeOperationsByScope.get(scope);
|
|
28583
|
+
if (operations?.length) {
|
|
28584
|
+
return operations[operations.length - 1];
|
|
28585
|
+
}
|
|
28586
|
+
}
|
|
28587
|
+
return void 0;
|
|
28588
|
+
}
|
|
28589
|
+
pendingOperationForEventScope(event) {
|
|
28590
|
+
const scopePrefixes = operationScopePrefixes(event);
|
|
28591
|
+
for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
|
|
28592
|
+
if (!candidateQueue.length || !operationKeyMatchesScopes(candidateKey, scopePrefixes)) {
|
|
28593
|
+
continue;
|
|
28594
|
+
}
|
|
28595
|
+
return candidateQueue[0];
|
|
28596
|
+
}
|
|
28597
|
+
return void 0;
|
|
28598
|
+
}
|
|
28599
|
+
takePendingOperationForEvent(event) {
|
|
28600
|
+
const key = operationKey(event.session, event.operationKind);
|
|
28601
|
+
const queue2 = this.pendingOperationsByKey.get(key);
|
|
28602
|
+
if (queue2?.length) {
|
|
28603
|
+
return queue2.shift();
|
|
28604
|
+
}
|
|
28605
|
+
for (const [candidateKey, candidateQueue] of this.pendingOperationsByKey) {
|
|
28606
|
+
if (candidateKey.endsWith(`::${event.operationKind}`) && candidateQueue.length) {
|
|
28607
|
+
return candidateQueue.shift();
|
|
28608
|
+
}
|
|
28609
|
+
}
|
|
28610
|
+
return void 0;
|
|
28611
|
+
}
|
|
28612
|
+
pendingOperationQueue(key) {
|
|
28613
|
+
const existing = this.pendingOperationsByKey.get(key);
|
|
28614
|
+
if (existing) {
|
|
28615
|
+
return existing;
|
|
28616
|
+
}
|
|
28617
|
+
const queue2 = [];
|
|
28618
|
+
this.pendingOperationsByKey.set(key, queue2);
|
|
28619
|
+
return queue2;
|
|
28620
|
+
}
|
|
28621
|
+
};
|
|
28622
|
+
function isInstrumentedOperation(operation) {
|
|
28623
|
+
return operation === "prompt" || operation === "skill" || operation === "task" || operation === "compact";
|
|
28624
|
+
}
|
|
28625
|
+
function getSessionName(session) {
|
|
28626
|
+
return typeof session?.name === "string" ? session.name : void 0;
|
|
28627
|
+
}
|
|
28628
|
+
function operationKey(sessionName, operation) {
|
|
28629
|
+
return `${sessionName ?? "unknown"}::${operation}`;
|
|
28630
|
+
}
|
|
28631
|
+
function operationScopePrefixes(event) {
|
|
28632
|
+
const scopes = /* @__PURE__ */ new Set();
|
|
28633
|
+
for (const scope of operationScopeNames(event)) {
|
|
28634
|
+
scopes.add(`${scope}::`);
|
|
28635
|
+
}
|
|
28636
|
+
return scopes;
|
|
28637
|
+
}
|
|
28638
|
+
function operationKeyMatchesScopes(key, scopes) {
|
|
28639
|
+
for (const scope of scopes) {
|
|
28640
|
+
if (key.startsWith(scope)) {
|
|
28641
|
+
return true;
|
|
28642
|
+
}
|
|
28643
|
+
}
|
|
28644
|
+
return false;
|
|
28645
|
+
}
|
|
28646
|
+
function operationScopeNames(event) {
|
|
28647
|
+
const scopes = /* @__PURE__ */ new Set();
|
|
28648
|
+
if (event.session) {
|
|
28649
|
+
scopes.add(event.session);
|
|
28650
|
+
}
|
|
28651
|
+
if (event.parentSession) {
|
|
28652
|
+
scopes.add(event.parentSession);
|
|
28653
|
+
}
|
|
28654
|
+
if (!scopes.size) {
|
|
28655
|
+
scopes.add("unknown");
|
|
28656
|
+
}
|
|
28657
|
+
return scopes;
|
|
28658
|
+
}
|
|
28659
|
+
function addScopedOperation(operationsByScope, event, state) {
|
|
28660
|
+
for (const scope of operationScopeNames(event)) {
|
|
28661
|
+
addOperationToScope(operationsByScope, scope, state);
|
|
28662
|
+
}
|
|
28663
|
+
}
|
|
28664
|
+
function addOperationToScope(operationsByScope, scope, state) {
|
|
28665
|
+
const operations = operationsByScope.get(scope);
|
|
28666
|
+
if (operations) {
|
|
28667
|
+
if (!operations.includes(state)) {
|
|
28668
|
+
operations.push(state);
|
|
28669
|
+
}
|
|
28670
|
+
} else {
|
|
28671
|
+
operationsByScope.set(scope, [state]);
|
|
28672
|
+
}
|
|
28673
|
+
}
|
|
28674
|
+
function removeScopedOperation(operationsByScope, state) {
|
|
28675
|
+
for (const [scope, operations] of operationsByScope) {
|
|
28676
|
+
const index = operations.indexOf(state);
|
|
28677
|
+
if (index === -1) {
|
|
28678
|
+
continue;
|
|
28679
|
+
}
|
|
28680
|
+
operations.splice(index, 1);
|
|
28681
|
+
if (operations.length === 0) {
|
|
28682
|
+
operationsByScope.delete(scope);
|
|
28683
|
+
}
|
|
28684
|
+
}
|
|
28685
|
+
}
|
|
28686
|
+
function removePendingOperation(pendingOperationsByKey, state) {
|
|
28687
|
+
for (const [key, queue2] of pendingOperationsByKey) {
|
|
28688
|
+
const index = queue2.indexOf(state);
|
|
28689
|
+
if (index === -1) {
|
|
28690
|
+
continue;
|
|
28691
|
+
}
|
|
28692
|
+
queue2.splice(index, 1);
|
|
28693
|
+
if (queue2.length === 0) {
|
|
28694
|
+
pendingOperationsByKey.delete(key);
|
|
28695
|
+
}
|
|
28696
|
+
return;
|
|
28697
|
+
}
|
|
28698
|
+
}
|
|
28699
|
+
function extractSessionMetadata(session) {
|
|
28700
|
+
const sessionName = getSessionName(session);
|
|
28701
|
+
return sessionName ? { "flue.session": sessionName } : {};
|
|
28702
|
+
}
|
|
28703
|
+
function extractEventMetadata(event) {
|
|
28704
|
+
return {
|
|
28705
|
+
...event.runId ? { "flue.run_id": event.runId } : {},
|
|
28706
|
+
...typeof event.eventIndex === "number" ? { "flue.event_index": event.eventIndex } : {},
|
|
28707
|
+
...event.session ? { "flue.session": event.session } : {},
|
|
28708
|
+
...event.parentSession ? { "flue.parent_session": event.parentSession } : {},
|
|
28709
|
+
...event.harness ? { "flue.harness": event.harness } : {},
|
|
28710
|
+
...event.taskId ? { "flue.task_id": event.taskId } : {},
|
|
28711
|
+
...event.operationId ? { "flue.operation_id": event.operationId } : {}
|
|
28712
|
+
};
|
|
28713
|
+
}
|
|
28714
|
+
function extractOperationInput(operation, args) {
|
|
28715
|
+
switch (operation) {
|
|
28716
|
+
case "prompt":
|
|
28717
|
+
case "task":
|
|
28718
|
+
return args[0];
|
|
28719
|
+
case "skill":
|
|
28720
|
+
return {
|
|
28721
|
+
args: getOptionObject(args[1])?.args,
|
|
28722
|
+
name: args[0]
|
|
28723
|
+
};
|
|
28724
|
+
case "compact":
|
|
28725
|
+
return void 0;
|
|
28726
|
+
}
|
|
28727
|
+
}
|
|
28728
|
+
function extractOperationInputMetadata(operation, args) {
|
|
28729
|
+
const options = getOptionObject(args[1]);
|
|
28730
|
+
return {
|
|
28731
|
+
...operation === "skill" && typeof args[0] === "string" ? { "flue.skill_name": args[0] } : {},
|
|
28732
|
+
...options?.model ? { model: options.model, "flue.model": options.model } : {},
|
|
28733
|
+
...options?.role ? { "flue.role": options.role } : {},
|
|
28734
|
+
...options?.thinkingLevel ? { "flue.thinking_level": options.thinkingLevel } : {},
|
|
28735
|
+
...typeof options?.cwd === "string" ? { "flue.cwd": options.cwd } : {},
|
|
28736
|
+
...Array.isArray(options?.tools) ? {
|
|
28737
|
+
"flue.tools_count": options.tools.length,
|
|
28738
|
+
tools: summarizeTools(options.tools)
|
|
28739
|
+
} : {},
|
|
28740
|
+
...Array.isArray(options?.images) ? { "flue.images_count": options.images.length } : {},
|
|
28741
|
+
...options?.result || options?.schema ? { "flue.result_schema": true } : {}
|
|
28742
|
+
};
|
|
28743
|
+
}
|
|
28744
|
+
function getOptionObject(value) {
|
|
28745
|
+
return isObject(value) ? value : void 0;
|
|
28746
|
+
}
|
|
28747
|
+
function summarizeTools(tools) {
|
|
28748
|
+
return tools.flatMap((tool) => {
|
|
28749
|
+
if (!isObject(tool)) {
|
|
28750
|
+
return [];
|
|
28751
|
+
}
|
|
28752
|
+
const name = typeof tool.name === "string" ? tool.name : void 0;
|
|
28753
|
+
if (!name) {
|
|
28754
|
+
return [];
|
|
28755
|
+
}
|
|
28756
|
+
return [
|
|
28757
|
+
{
|
|
28758
|
+
function: {
|
|
28759
|
+
description: typeof tool.description === "string" ? tool.description : void 0,
|
|
28760
|
+
name,
|
|
28761
|
+
parameters: tool.parameters
|
|
28762
|
+
},
|
|
28763
|
+
type: "function"
|
|
28764
|
+
}
|
|
28765
|
+
];
|
|
28766
|
+
});
|
|
28767
|
+
}
|
|
28768
|
+
function extractPromptResponseMetadata(result) {
|
|
28769
|
+
const modelId = result?.model && typeof result.model.id === "string" ? result.model.id : void 0;
|
|
28770
|
+
return modelId ? {
|
|
28771
|
+
model: modelId,
|
|
28772
|
+
"flue.model": modelId
|
|
28773
|
+
} : {};
|
|
28774
|
+
}
|
|
28775
|
+
function extractOperationOutput(result) {
|
|
28776
|
+
if (!result) {
|
|
28777
|
+
return void 0;
|
|
28778
|
+
}
|
|
28779
|
+
if ("data" in result) {
|
|
28780
|
+
return result.data;
|
|
28781
|
+
}
|
|
28782
|
+
if ("text" in result) {
|
|
28783
|
+
return result.text;
|
|
28784
|
+
}
|
|
28785
|
+
return result;
|
|
28786
|
+
}
|
|
28787
|
+
function metricsFromUsage(usage) {
|
|
28788
|
+
return {
|
|
28789
|
+
...typeof usage?.input === "number" ? { prompt_tokens: usage.input } : {},
|
|
28790
|
+
...typeof usage?.output === "number" ? { completion_tokens: usage.output } : {},
|
|
28791
|
+
...typeof usage?.cacheRead === "number" ? { prompt_cached_tokens: usage.cacheRead } : {},
|
|
28792
|
+
...typeof usage?.cacheWrite === "number" ? { prompt_cache_creation_tokens: usage.cacheWrite } : {},
|
|
28793
|
+
...typeof usage?.totalTokens === "number" ? { tokens: usage.totalTokens } : {},
|
|
28794
|
+
...typeof usage?.cost?.total === "number" ? { estimated_cost: usage.cost.total } : {}
|
|
28795
|
+
};
|
|
28796
|
+
}
|
|
28797
|
+
function buildDurationMetrics3(startTime) {
|
|
28798
|
+
return {
|
|
28799
|
+
duration_ms: Math.max(0, (getCurrentUnixTimestamp() - startTime) * 1e3)
|
|
28800
|
+
};
|
|
28801
|
+
}
|
|
28802
|
+
function durationMsMetrics(durationMs) {
|
|
28803
|
+
return typeof durationMs === "number" ? { duration_ms: durationMs } : {};
|
|
28804
|
+
}
|
|
28805
|
+
function scopeKey(event) {
|
|
28806
|
+
if (event.operationId) {
|
|
28807
|
+
return `operation:${event.operationId}`;
|
|
28808
|
+
}
|
|
28809
|
+
if (event.taskId) {
|
|
28810
|
+
return `task:${event.taskId}`;
|
|
28811
|
+
}
|
|
28812
|
+
if (event.session) {
|
|
28813
|
+
return `session:${event.session}`;
|
|
28814
|
+
}
|
|
28815
|
+
return "flue:unknown";
|
|
28816
|
+
}
|
|
28817
|
+
function toolKey(event) {
|
|
28818
|
+
return `${scopeKey(event)}::tool:${event.toolCallId ?? "unknown"}`;
|
|
28819
|
+
}
|
|
28820
|
+
function toAssistantOutput(text, finishReason, reasoning, toolCalls) {
|
|
28821
|
+
return [
|
|
28822
|
+
{
|
|
28823
|
+
finish_reason: finishReason ?? "stop",
|
|
28824
|
+
index: 0,
|
|
28825
|
+
message: {
|
|
28826
|
+
content: text,
|
|
28827
|
+
...reasoning ? { reasoning } : {},
|
|
28828
|
+
role: "assistant",
|
|
28829
|
+
...toolCalls?.length ? {
|
|
28830
|
+
tool_calls: toolCalls.map((toolCall) => ({
|
|
28831
|
+
function: {
|
|
28832
|
+
arguments: toolCall.args === void 0 ? "{}" : JSON.stringify(toolCall.args),
|
|
28833
|
+
name: toolCall.toolName ?? "unknown"
|
|
28834
|
+
},
|
|
28835
|
+
...toolCall.toolCallId ? { id: toolCall.toolCallId } : {},
|
|
28836
|
+
type: "function"
|
|
28837
|
+
}))
|
|
28838
|
+
} : {}
|
|
28839
|
+
}
|
|
28840
|
+
}
|
|
28841
|
+
];
|
|
28842
|
+
}
|
|
28843
|
+
function startFlueSpan(parent, args) {
|
|
28844
|
+
return parent ? withCurrent(parent, () => startSpan(args)) : startSpan(args);
|
|
28845
|
+
}
|
|
28846
|
+
function safeLog3(span, event) {
|
|
28847
|
+
try {
|
|
28848
|
+
span.log(event);
|
|
28849
|
+
} catch (error2) {
|
|
28850
|
+
logInstrumentationError3("Flue span log", error2);
|
|
28851
|
+
}
|
|
28852
|
+
}
|
|
28853
|
+
function errorToString(error2) {
|
|
28854
|
+
if (error2 instanceof Error) {
|
|
28855
|
+
return error2.message;
|
|
28856
|
+
}
|
|
28857
|
+
if (typeof error2 === "string") {
|
|
28858
|
+
return error2;
|
|
28859
|
+
}
|
|
28860
|
+
try {
|
|
28861
|
+
return JSON.stringify(error2);
|
|
28862
|
+
} catch {
|
|
28863
|
+
return String(error2);
|
|
28864
|
+
}
|
|
28865
|
+
}
|
|
28866
|
+
function logInstrumentationError3(label, error2) {
|
|
28867
|
+
console.error(`Error in ${label} instrumentation:`, error2);
|
|
28868
|
+
}
|
|
28869
|
+
|
|
28870
|
+
// src/wrappers/langchain/callback-handler.ts
|
|
28871
|
+
var BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME = "BraintrustCallbackHandler";
|
|
28872
|
+
var BraintrustLangChainCallbackHandler = class {
|
|
28873
|
+
name = BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
|
|
28874
|
+
spans = /* @__PURE__ */ new Map();
|
|
28875
|
+
skippedRuns = /* @__PURE__ */ new Set();
|
|
28876
|
+
parent;
|
|
28877
|
+
rootRunId;
|
|
28878
|
+
options;
|
|
28879
|
+
startTimes = /* @__PURE__ */ new Map();
|
|
28880
|
+
firstTokenTimes = /* @__PURE__ */ new Map();
|
|
28881
|
+
ttftMs = /* @__PURE__ */ new Map();
|
|
28882
|
+
constructor(options) {
|
|
28883
|
+
this.parent = options?.parent;
|
|
28884
|
+
this.options = {
|
|
28885
|
+
debug: options?.debug ?? false,
|
|
28886
|
+
excludeMetadataProps: options?.excludeMetadataProps ?? /^(l[sc]_|langgraph_|__pregel_|checkpoint_ns)/,
|
|
28887
|
+
logger: options?.logger
|
|
28888
|
+
};
|
|
28889
|
+
}
|
|
28890
|
+
startSpan({
|
|
28891
|
+
runId,
|
|
28892
|
+
parentRunId,
|
|
28893
|
+
...args
|
|
28894
|
+
}) {
|
|
28895
|
+
if (this.spans.has(runId)) {
|
|
28896
|
+
return;
|
|
28897
|
+
}
|
|
28898
|
+
if (!parentRunId) {
|
|
28899
|
+
this.rootRunId = runId;
|
|
28900
|
+
}
|
|
28901
|
+
const tags = args.event?.tags;
|
|
28902
|
+
const spanAttributes = args.spanAttributes || {};
|
|
28903
|
+
spanAttributes.type = args.type || spanAttributes.type || "task";
|
|
28904
|
+
args.type = spanAttributes.type;
|
|
28905
|
+
const currentParent = (typeof this.parent === "function" ? this.parent() : this.parent) ?? currentSpan();
|
|
28906
|
+
let parentSpan;
|
|
28907
|
+
if (parentRunId && this.spans.has(parentRunId)) {
|
|
28908
|
+
parentSpan = this.spans.get(parentRunId);
|
|
28909
|
+
} else if (!Object.is(currentParent, NOOP_SPAN)) {
|
|
28910
|
+
parentSpan = currentParent;
|
|
28911
|
+
} else if (this.options.logger) {
|
|
28912
|
+
parentSpan = this.options.logger;
|
|
28913
|
+
} else {
|
|
28914
|
+
parentSpan = { startSpan };
|
|
28915
|
+
}
|
|
28916
|
+
args.event = {
|
|
28917
|
+
...args.event,
|
|
28918
|
+
tags: void 0,
|
|
28919
|
+
metadata: {
|
|
28920
|
+
...tags ? { tags } : {},
|
|
28921
|
+
...args.event?.metadata,
|
|
28922
|
+
braintrust: {
|
|
28923
|
+
integration_name: "langchain-js",
|
|
28924
|
+
sdk_language: "javascript"
|
|
28925
|
+
},
|
|
28926
|
+
run_id: runId,
|
|
28927
|
+
parent_run_id: parentRunId,
|
|
28928
|
+
...this.options.debug ? { runId, parentRunId } : {}
|
|
28929
|
+
}
|
|
28930
|
+
};
|
|
28931
|
+
let span = parentSpan.startSpan(args);
|
|
28932
|
+
if (!Object.is(this.options.logger, NOOP_SPAN) && Object.is(span, NOOP_SPAN)) {
|
|
28933
|
+
span = initLogger().startSpan(args);
|
|
28934
|
+
}
|
|
28935
|
+
this.spans.set(runId, span);
|
|
28936
|
+
}
|
|
28937
|
+
endSpan({
|
|
28938
|
+
runId,
|
|
28939
|
+
parentRunId,
|
|
28940
|
+
tags,
|
|
28941
|
+
metadata,
|
|
28942
|
+
...args
|
|
28943
|
+
}) {
|
|
28944
|
+
if (!this.spans.has(runId)) {
|
|
28945
|
+
return;
|
|
28946
|
+
}
|
|
28947
|
+
if (this.skippedRuns.has(runId)) {
|
|
28948
|
+
this.skippedRuns.delete(runId);
|
|
28949
|
+
return;
|
|
28950
|
+
}
|
|
28951
|
+
const span = this.spans.get(runId);
|
|
28952
|
+
this.spans.delete(runId);
|
|
28953
|
+
if (runId === this.rootRunId) {
|
|
28954
|
+
this.rootRunId = void 0;
|
|
28955
|
+
}
|
|
28956
|
+
span.log({ ...args, metadata: { tags, ...metadata } });
|
|
28957
|
+
span.end();
|
|
28958
|
+
}
|
|
28959
|
+
async handleLLMStart(llm, prompts, runId, parentRunId, extraParams, tags, metadata, runName) {
|
|
28960
|
+
this.startSpan({
|
|
28961
|
+
runId,
|
|
28962
|
+
parentRunId,
|
|
28963
|
+
name: runName ?? getSerializedName(llm) ?? "LLM",
|
|
28964
|
+
type: "llm",
|
|
28965
|
+
event: {
|
|
28966
|
+
input: prompts,
|
|
28967
|
+
tags,
|
|
28968
|
+
metadata: {
|
|
28969
|
+
serialized: llm,
|
|
28970
|
+
name: runName,
|
|
28971
|
+
metadata,
|
|
28972
|
+
...extraParams
|
|
28973
|
+
}
|
|
28974
|
+
}
|
|
28975
|
+
});
|
|
28976
|
+
}
|
|
28977
|
+
async handleLLMError(err, runId, parentRunId, tags) {
|
|
28978
|
+
this.endSpan({ runId, parentRunId, error: err, tags });
|
|
28979
|
+
}
|
|
28980
|
+
async handleLLMEnd(output, runId, parentRunId, tags) {
|
|
28981
|
+
const metrics = getMetricsFromResponse(output);
|
|
28982
|
+
const modelName2 = getModelNameFromResponse(output);
|
|
28983
|
+
const ttft = this.ttftMs.get(runId);
|
|
28984
|
+
if (ttft !== void 0) {
|
|
28985
|
+
metrics.time_to_first_token = ttft;
|
|
28986
|
+
}
|
|
28987
|
+
this.startTimes.delete(runId);
|
|
28988
|
+
this.firstTokenTimes.delete(runId);
|
|
28989
|
+
this.ttftMs.delete(runId);
|
|
28990
|
+
this.endSpan({
|
|
28991
|
+
runId,
|
|
28992
|
+
parentRunId,
|
|
28993
|
+
output,
|
|
28994
|
+
metrics,
|
|
28995
|
+
tags,
|
|
28996
|
+
metadata: {
|
|
28997
|
+
model: modelName2
|
|
28998
|
+
}
|
|
28999
|
+
});
|
|
29000
|
+
}
|
|
29001
|
+
async handleChatModelStart(llm, messages, runId, parentRunId, extraParams, tags, metadata, runName) {
|
|
29002
|
+
this.startTimes.set(runId, Date.now());
|
|
29003
|
+
this.firstTokenTimes.delete(runId);
|
|
29004
|
+
this.ttftMs.delete(runId);
|
|
29005
|
+
this.startSpan({
|
|
29006
|
+
runId,
|
|
29007
|
+
parentRunId,
|
|
29008
|
+
name: runName ?? getSerializedName(llm) ?? "Chat Model",
|
|
29009
|
+
type: "llm",
|
|
29010
|
+
event: {
|
|
29011
|
+
input: messages,
|
|
29012
|
+
tags,
|
|
29013
|
+
metadata: {
|
|
29014
|
+
serialized: llm,
|
|
29015
|
+
name: runName,
|
|
29016
|
+
metadata,
|
|
29017
|
+
...extraParams
|
|
29018
|
+
}
|
|
29019
|
+
}
|
|
29020
|
+
});
|
|
29021
|
+
}
|
|
29022
|
+
async handleChainStart(chain, inputs, runId, parentRunId, tags, metadata, runType, runName) {
|
|
29023
|
+
if (tags?.includes("langsmith:hidden")) {
|
|
29024
|
+
this.skippedRuns.add(runId);
|
|
29025
|
+
return;
|
|
29026
|
+
}
|
|
29027
|
+
this.startSpan({
|
|
29028
|
+
runId,
|
|
29029
|
+
parentRunId,
|
|
29030
|
+
name: runName ?? getSerializedName(chain) ?? "Chain",
|
|
29031
|
+
event: {
|
|
29032
|
+
input: inputs,
|
|
29033
|
+
tags,
|
|
29034
|
+
metadata: {
|
|
29035
|
+
serialized: chain,
|
|
29036
|
+
name: runName,
|
|
29037
|
+
metadata,
|
|
29038
|
+
run_type: runType
|
|
29039
|
+
}
|
|
29040
|
+
}
|
|
29041
|
+
});
|
|
29042
|
+
}
|
|
29043
|
+
async handleChainError(err, runId, parentRunId, tags, kwargs) {
|
|
29044
|
+
this.endSpan({ runId, parentRunId, error: err, tags, metadata: kwargs });
|
|
29045
|
+
}
|
|
29046
|
+
async handleChainEnd(outputs, runId, parentRunId, tags, kwargs) {
|
|
29047
|
+
this.endSpan({
|
|
29048
|
+
runId,
|
|
29049
|
+
parentRunId,
|
|
29050
|
+
tags,
|
|
29051
|
+
output: outputs,
|
|
29052
|
+
metadata: { ...kwargs }
|
|
29053
|
+
});
|
|
29054
|
+
}
|
|
29055
|
+
async handleToolStart(tool, input, runId, parentRunId, tags, metadata, runName) {
|
|
29056
|
+
this.startSpan({
|
|
29057
|
+
runId,
|
|
29058
|
+
parentRunId,
|
|
29059
|
+
name: runName ?? getSerializedName(tool) ?? "Tool",
|
|
29060
|
+
type: "llm",
|
|
29061
|
+
event: {
|
|
29062
|
+
input: safeJsonParse(input),
|
|
29063
|
+
tags,
|
|
29064
|
+
metadata: {
|
|
29065
|
+
metadata,
|
|
29066
|
+
serialized: tool,
|
|
29067
|
+
input_str: input,
|
|
29068
|
+
input: safeJsonParse(input),
|
|
29069
|
+
name: runName
|
|
29070
|
+
}
|
|
29071
|
+
}
|
|
29072
|
+
});
|
|
29073
|
+
}
|
|
29074
|
+
async handleToolError(err, runId, parentRunId, tags) {
|
|
29075
|
+
this.endSpan({ runId, parentRunId, error: err, tags });
|
|
29076
|
+
}
|
|
29077
|
+
async handleToolEnd(output, runId, parentRunId, tags) {
|
|
29078
|
+
this.endSpan({ runId, parentRunId, output, tags });
|
|
29079
|
+
}
|
|
29080
|
+
async handleAgentAction(action, runId, parentRunId, tags) {
|
|
29081
|
+
this.startSpan({
|
|
29082
|
+
runId,
|
|
29083
|
+
parentRunId,
|
|
29084
|
+
type: "llm",
|
|
29085
|
+
name: typeof action.tool === "string" ? action.tool : "Agent",
|
|
29086
|
+
event: {
|
|
29087
|
+
input: action,
|
|
29088
|
+
tags
|
|
29089
|
+
}
|
|
29090
|
+
});
|
|
29091
|
+
}
|
|
29092
|
+
async handleAgentEnd(action, runId, parentRunId, tags) {
|
|
29093
|
+
this.endSpan({ runId, parentRunId, output: action, tags });
|
|
29094
|
+
}
|
|
29095
|
+
async handleRetrieverStart(retriever, query, runId, parentRunId, tags, metadata, name) {
|
|
29096
|
+
this.startSpan({
|
|
29097
|
+
runId,
|
|
29098
|
+
parentRunId,
|
|
29099
|
+
name: name ?? getSerializedName(retriever) ?? "Retriever",
|
|
29100
|
+
type: "function",
|
|
29101
|
+
event: {
|
|
29102
|
+
input: query,
|
|
29103
|
+
tags,
|
|
29104
|
+
metadata: {
|
|
29105
|
+
serialized: retriever,
|
|
29106
|
+
metadata,
|
|
29107
|
+
name
|
|
29108
|
+
}
|
|
29109
|
+
}
|
|
29110
|
+
});
|
|
29111
|
+
}
|
|
29112
|
+
async handleRetrieverEnd(documents, runId, parentRunId, tags) {
|
|
29113
|
+
this.endSpan({ runId, parentRunId, output: documents, tags });
|
|
29114
|
+
}
|
|
29115
|
+
async handleRetrieverError(err, runId, parentRunId, tags) {
|
|
29116
|
+
this.endSpan({ runId, parentRunId, error: err, tags });
|
|
29117
|
+
}
|
|
29118
|
+
async handleLLMNewToken(_token, _idx, runId, _parentRunId, _tags) {
|
|
29119
|
+
if (!this.firstTokenTimes.has(runId)) {
|
|
29120
|
+
const now2 = Date.now();
|
|
29121
|
+
this.firstTokenTimes.set(runId, now2);
|
|
29122
|
+
const start = this.startTimes.get(runId);
|
|
29123
|
+
if (start !== void 0) {
|
|
29124
|
+
this.ttftMs.set(runId, (now2 - start) / 1e3);
|
|
29125
|
+
}
|
|
29126
|
+
}
|
|
29127
|
+
}
|
|
29128
|
+
};
|
|
29129
|
+
function getSerializedName(serialized) {
|
|
29130
|
+
if (typeof serialized.name === "string") {
|
|
29131
|
+
return serialized.name;
|
|
29132
|
+
}
|
|
29133
|
+
const lastIdPart = serialized.id?.at(-1);
|
|
29134
|
+
return typeof lastIdPart === "string" ? lastIdPart : void 0;
|
|
29135
|
+
}
|
|
29136
|
+
function cleanObject(obj) {
|
|
29137
|
+
return Object.fromEntries(
|
|
29138
|
+
Object.entries(obj).filter(([, value]) => {
|
|
29139
|
+
if (typeof value !== "number") {
|
|
29140
|
+
return false;
|
|
29141
|
+
}
|
|
29142
|
+
return Number.isFinite(value);
|
|
29143
|
+
})
|
|
29144
|
+
);
|
|
29145
|
+
}
|
|
29146
|
+
function walkGenerations(response) {
|
|
29147
|
+
const result = [];
|
|
29148
|
+
const generations = response.generations || [];
|
|
29149
|
+
for (const batch of generations) {
|
|
29150
|
+
if (Array.isArray(batch)) {
|
|
29151
|
+
for (const generation of batch) {
|
|
29152
|
+
if (isRecord(generation)) {
|
|
29153
|
+
result.push(generation);
|
|
29154
|
+
}
|
|
29155
|
+
}
|
|
29156
|
+
} else if (isRecord(batch)) {
|
|
29157
|
+
result.push(batch);
|
|
29158
|
+
}
|
|
29159
|
+
}
|
|
29160
|
+
return result;
|
|
29161
|
+
}
|
|
29162
|
+
function getModelNameFromResponse(response) {
|
|
29163
|
+
for (const generation of walkGenerations(response)) {
|
|
29164
|
+
const message = generation.message;
|
|
29165
|
+
if (!isRecord(message)) {
|
|
29166
|
+
continue;
|
|
29167
|
+
}
|
|
29168
|
+
const responseMetadata = message.response_metadata;
|
|
29169
|
+
if (!isRecord(responseMetadata)) {
|
|
29170
|
+
continue;
|
|
29171
|
+
}
|
|
29172
|
+
const modelName3 = responseMetadata.model_name ?? responseMetadata.model;
|
|
29173
|
+
if (typeof modelName3 === "string") {
|
|
29174
|
+
return modelName3;
|
|
29175
|
+
}
|
|
29176
|
+
}
|
|
29177
|
+
const llmOutput = response.llmOutput || {};
|
|
29178
|
+
const modelName2 = llmOutput.model_name ?? llmOutput.model;
|
|
29179
|
+
return typeof modelName2 === "string" ? modelName2 : void 0;
|
|
29180
|
+
}
|
|
29181
|
+
function getMetricsFromResponse(response) {
|
|
29182
|
+
for (const generation of walkGenerations(response)) {
|
|
29183
|
+
const message = generation.message;
|
|
29184
|
+
if (!isRecord(message)) {
|
|
29185
|
+
continue;
|
|
29186
|
+
}
|
|
29187
|
+
const usageMetadata = message.usage_metadata;
|
|
29188
|
+
if (!isRecord(usageMetadata)) {
|
|
29189
|
+
continue;
|
|
29190
|
+
}
|
|
29191
|
+
const inputTokenDetails = usageMetadata.input_token_details;
|
|
29192
|
+
return cleanObject({
|
|
29193
|
+
total_tokens: usageMetadata.total_tokens,
|
|
29194
|
+
prompt_tokens: usageMetadata.input_tokens,
|
|
29195
|
+
completion_tokens: usageMetadata.output_tokens,
|
|
29196
|
+
prompt_cache_creation_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_creation : void 0,
|
|
29197
|
+
prompt_cached_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_read : void 0
|
|
29198
|
+
});
|
|
29199
|
+
}
|
|
29200
|
+
const llmOutput = response.llmOutput || {};
|
|
29201
|
+
const tokenUsage = isRecord(llmOutput.tokenUsage) ? llmOutput.tokenUsage : isRecord(llmOutput.estimatedTokens) ? llmOutput.estimatedTokens : {};
|
|
29202
|
+
return cleanObject({
|
|
29203
|
+
total_tokens: tokenUsage.totalTokens,
|
|
29204
|
+
prompt_tokens: tokenUsage.promptTokens,
|
|
29205
|
+
completion_tokens: tokenUsage.completionTokens
|
|
29206
|
+
});
|
|
29207
|
+
}
|
|
29208
|
+
function safeJsonParse(input) {
|
|
29209
|
+
try {
|
|
29210
|
+
return JSON.parse(input);
|
|
29211
|
+
} catch {
|
|
29212
|
+
return input;
|
|
29213
|
+
}
|
|
29214
|
+
}
|
|
29215
|
+
function isRecord(value) {
|
|
29216
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
29217
|
+
}
|
|
29218
|
+
|
|
29219
|
+
// src/instrumentation/plugins/langchain-channels.ts
|
|
29220
|
+
var langChainChannels = defineChannels("@langchain/core", {
|
|
29221
|
+
configure: channel({
|
|
29222
|
+
channelName: "CallbackManager.configure",
|
|
29223
|
+
kind: "sync-stream"
|
|
29224
|
+
}),
|
|
29225
|
+
configureSync: channel({
|
|
29226
|
+
channelName: "CallbackManager._configureSync",
|
|
29227
|
+
kind: "sync-stream"
|
|
29228
|
+
})
|
|
29229
|
+
});
|
|
29230
|
+
|
|
29231
|
+
// src/instrumentation/plugins/langchain-plugin.ts
|
|
29232
|
+
var LangChainPlugin = class extends BasePlugin {
|
|
29233
|
+
injectedManagers = /* @__PURE__ */ new WeakSet();
|
|
29234
|
+
onEnable() {
|
|
29235
|
+
this.subscribeToConfigure(langChainChannels.configure);
|
|
29236
|
+
this.subscribeToConfigure(langChainChannels.configureSync);
|
|
29237
|
+
}
|
|
29238
|
+
onDisable() {
|
|
29239
|
+
for (const unsubscribe of this.unsubscribers) {
|
|
29240
|
+
unsubscribe();
|
|
29241
|
+
}
|
|
29242
|
+
this.unsubscribers = [];
|
|
29243
|
+
this.injectedManagers = /* @__PURE__ */ new WeakSet();
|
|
29244
|
+
}
|
|
29245
|
+
subscribeToConfigure(channel2) {
|
|
29246
|
+
const tracingChannel2 = channel2.tracingChannel();
|
|
29247
|
+
const handlers = {
|
|
29248
|
+
start: (event) => {
|
|
29249
|
+
injectHandlerIntoArguments(event.arguments);
|
|
29250
|
+
},
|
|
29251
|
+
end: (event) => {
|
|
29252
|
+
this.injectHandler(event.result);
|
|
29253
|
+
}
|
|
29254
|
+
};
|
|
29255
|
+
tracingChannel2.subscribe(handlers);
|
|
29256
|
+
this.unsubscribers.push(() => {
|
|
29257
|
+
tracingChannel2.unsubscribe(handlers);
|
|
29258
|
+
});
|
|
29259
|
+
}
|
|
29260
|
+
injectHandler(result) {
|
|
29261
|
+
if (!isCallbackManager(result)) {
|
|
29262
|
+
return;
|
|
29263
|
+
}
|
|
29264
|
+
if (this.injectedManagers.has(result) || hasBraintrustHandler(result)) {
|
|
29265
|
+
return;
|
|
29266
|
+
}
|
|
29267
|
+
try {
|
|
29268
|
+
result.addHandler(new BraintrustLangChainCallbackHandler(), true);
|
|
29269
|
+
this.injectedManagers.add(result);
|
|
29270
|
+
} catch {
|
|
29271
|
+
}
|
|
29272
|
+
}
|
|
29273
|
+
};
|
|
29274
|
+
function isCallbackManager(value) {
|
|
29275
|
+
if (typeof value !== "object" || value === null) {
|
|
29276
|
+
return false;
|
|
29277
|
+
}
|
|
29278
|
+
const maybeManager = value;
|
|
29279
|
+
return typeof maybeManager.addHandler === "function";
|
|
29280
|
+
}
|
|
29281
|
+
function hasBraintrustHandler(manager) {
|
|
29282
|
+
return manager.handlers?.some((handler) => {
|
|
29283
|
+
if (typeof handler !== "object" || handler === null) {
|
|
29284
|
+
return false;
|
|
29285
|
+
}
|
|
29286
|
+
const name = Reflect.get(handler, "name");
|
|
29287
|
+
return name === BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
|
|
29288
|
+
}) ?? false;
|
|
29289
|
+
}
|
|
29290
|
+
function injectHandlerIntoArguments(args) {
|
|
29291
|
+
if (!isWritableArgumentsObject(args)) {
|
|
29292
|
+
return;
|
|
29293
|
+
}
|
|
29294
|
+
const inheritedHandlers = Reflect.get(args, "0");
|
|
29295
|
+
const handler = new BraintrustLangChainCallbackHandler();
|
|
29296
|
+
if (inheritedHandlers === void 0 || inheritedHandlers === null) {
|
|
29297
|
+
Reflect.set(args, "0", [handler]);
|
|
29298
|
+
return;
|
|
29299
|
+
}
|
|
29300
|
+
if (Array.isArray(inheritedHandlers)) {
|
|
29301
|
+
if (!inheritedHandlers.some(isBraintrustHandler)) {
|
|
29302
|
+
inheritedHandlers.push(handler);
|
|
29303
|
+
}
|
|
29304
|
+
}
|
|
29305
|
+
}
|
|
29306
|
+
function isWritableArgumentsObject(args) {
|
|
29307
|
+
return typeof args === "object" && args !== null;
|
|
29308
|
+
}
|
|
29309
|
+
function isBraintrustHandler(handler) {
|
|
29310
|
+
if (typeof handler !== "object" || handler === null) {
|
|
29311
|
+
return false;
|
|
29312
|
+
}
|
|
29313
|
+
return Reflect.get(handler, "name") === BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
|
|
29314
|
+
}
|
|
29315
|
+
|
|
29316
|
+
// src/instrumentation/braintrust-plugin.ts
|
|
29317
|
+
function getIntegrationConfig(integrations, key) {
|
|
29318
|
+
return integrations[key];
|
|
29319
|
+
}
|
|
29320
|
+
var BraintrustPlugin = class extends BasePlugin {
|
|
29321
|
+
config;
|
|
29322
|
+
openaiPlugin = null;
|
|
29323
|
+
openAICodexPlugin = null;
|
|
29324
|
+
anthropicPlugin = null;
|
|
29325
|
+
aiSDKPlugin = null;
|
|
29326
|
+
claudeAgentSDKPlugin = null;
|
|
27068
29327
|
cursorSDKPlugin = null;
|
|
29328
|
+
openAIAgentsPlugin = null;
|
|
27069
29329
|
googleGenAIPlugin = null;
|
|
27070
29330
|
huggingFacePlugin = null;
|
|
27071
29331
|
openRouterPlugin = null;
|
|
@@ -27076,6 +29336,8 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
27076
29336
|
groqPlugin = null;
|
|
27077
29337
|
genkitPlugin = null;
|
|
27078
29338
|
gitHubCopilotPlugin = null;
|
|
29339
|
+
fluePlugin = null;
|
|
29340
|
+
langChainPlugin = null;
|
|
27079
29341
|
constructor(config3 = {}) {
|
|
27080
29342
|
super();
|
|
27081
29343
|
this.config = config3;
|
|
@@ -27106,6 +29368,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
27106
29368
|
this.cursorSDKPlugin = new CursorSDKPlugin();
|
|
27107
29369
|
this.cursorSDKPlugin.enable();
|
|
27108
29370
|
}
|
|
29371
|
+
if (integrations.openAIAgents !== false) {
|
|
29372
|
+
this.openAIAgentsPlugin = new OpenAIAgentsPlugin();
|
|
29373
|
+
this.openAIAgentsPlugin.enable();
|
|
29374
|
+
}
|
|
27109
29375
|
if (integrations.googleGenAI !== false && integrations.google !== false) {
|
|
27110
29376
|
this.googleGenAIPlugin = new GoogleGenAIPlugin();
|
|
27111
29377
|
this.googleGenAIPlugin.enable();
|
|
@@ -27146,6 +29412,14 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
27146
29412
|
this.gitHubCopilotPlugin = new GitHubCopilotPlugin();
|
|
27147
29413
|
this.gitHubCopilotPlugin.enable();
|
|
27148
29414
|
}
|
|
29415
|
+
if (getIntegrationConfig(integrations, "flue") !== false) {
|
|
29416
|
+
this.fluePlugin = new FluePlugin();
|
|
29417
|
+
this.fluePlugin.enable();
|
|
29418
|
+
}
|
|
29419
|
+
if (integrations.langchain !== false && integrations.langgraph !== false) {
|
|
29420
|
+
this.langChainPlugin = new LangChainPlugin();
|
|
29421
|
+
this.langChainPlugin.enable();
|
|
29422
|
+
}
|
|
27149
29423
|
}
|
|
27150
29424
|
onDisable() {
|
|
27151
29425
|
if (this.openaiPlugin) {
|
|
@@ -27172,6 +29446,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
27172
29446
|
this.cursorSDKPlugin.disable();
|
|
27173
29447
|
this.cursorSDKPlugin = null;
|
|
27174
29448
|
}
|
|
29449
|
+
if (this.openAIAgentsPlugin) {
|
|
29450
|
+
this.openAIAgentsPlugin.disable();
|
|
29451
|
+
this.openAIAgentsPlugin = null;
|
|
29452
|
+
}
|
|
27175
29453
|
if (this.googleGenAIPlugin) {
|
|
27176
29454
|
this.googleGenAIPlugin.disable();
|
|
27177
29455
|
this.googleGenAIPlugin = null;
|
|
@@ -27212,9 +29490,104 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
27212
29490
|
this.gitHubCopilotPlugin.disable();
|
|
27213
29491
|
this.gitHubCopilotPlugin = null;
|
|
27214
29492
|
}
|
|
29493
|
+
if (this.fluePlugin) {
|
|
29494
|
+
this.fluePlugin.disable();
|
|
29495
|
+
this.fluePlugin = null;
|
|
29496
|
+
}
|
|
29497
|
+
if (this.langChainPlugin) {
|
|
29498
|
+
this.langChainPlugin.disable();
|
|
29499
|
+
this.langChainPlugin = null;
|
|
29500
|
+
}
|
|
27215
29501
|
}
|
|
27216
29502
|
};
|
|
27217
29503
|
|
|
29504
|
+
// src/instrumentation/config.ts
|
|
29505
|
+
var envIntegrationAliases = {
|
|
29506
|
+
openai: "openai",
|
|
29507
|
+
"openai-codex": "openaiCodexSDK",
|
|
29508
|
+
"openai-codex-sdk": "openaiCodexSDK",
|
|
29509
|
+
openaicodexsdk: "openaiCodexSDK",
|
|
29510
|
+
codex: "openaiCodexSDK",
|
|
29511
|
+
"codex-sdk": "openaiCodexSDK",
|
|
29512
|
+
anthropic: "anthropic",
|
|
29513
|
+
aisdk: "aisdk",
|
|
29514
|
+
"ai-sdk": "aisdk",
|
|
29515
|
+
"vercel-ai": "aisdk",
|
|
29516
|
+
vercel: "vercel",
|
|
29517
|
+
claudeagentsdk: "claudeAgentSDK",
|
|
29518
|
+
"claude-agent-sdk": "claudeAgentSDK",
|
|
29519
|
+
cursor: "cursor",
|
|
29520
|
+
"cursor-sdk": "cursorSDK",
|
|
29521
|
+
cursorsdk: "cursorSDK",
|
|
29522
|
+
flue: "flue",
|
|
29523
|
+
"flue-runtime": "flue",
|
|
29524
|
+
"openai-agents": "openAIAgents",
|
|
29525
|
+
openaiagents: "openAIAgents",
|
|
29526
|
+
"openai-agents-core": "openAIAgents",
|
|
29527
|
+
openaiagentscore: "openAIAgents",
|
|
29528
|
+
google: "google",
|
|
29529
|
+
"google-genai": "googleGenAI",
|
|
29530
|
+
googlegenai: "googleGenAI",
|
|
29531
|
+
huggingface: "huggingface",
|
|
29532
|
+
openrouter: "openrouter",
|
|
29533
|
+
openrouteragent: "openrouterAgent",
|
|
29534
|
+
"openrouter-agent": "openrouterAgent",
|
|
29535
|
+
mistral: "mistral",
|
|
29536
|
+
googleadk: "googleADK",
|
|
29537
|
+
"google-adk": "googleADK",
|
|
29538
|
+
cohere: "cohere",
|
|
29539
|
+
groq: "groq",
|
|
29540
|
+
"groq-sdk": "groq",
|
|
29541
|
+
genkit: "genkit",
|
|
29542
|
+
"firebase-genkit": "genkit",
|
|
29543
|
+
githubcopilot: "gitHubCopilot",
|
|
29544
|
+
"github-copilot": "gitHubCopilot",
|
|
29545
|
+
"copilot-sdk": "gitHubCopilot",
|
|
29546
|
+
langchain: "langchain",
|
|
29547
|
+
"langchain-js": "langchain",
|
|
29548
|
+
"@langchain": "langchain",
|
|
29549
|
+
langgraph: "langgraph"
|
|
29550
|
+
};
|
|
29551
|
+
function getDefaultInstrumentationIntegrations() {
|
|
29552
|
+
return {
|
|
29553
|
+
openai: true,
|
|
29554
|
+
openaiCodexSDK: true,
|
|
29555
|
+
anthropic: true,
|
|
29556
|
+
vercel: true,
|
|
29557
|
+
aisdk: true,
|
|
29558
|
+
google: true,
|
|
29559
|
+
googleGenAI: true,
|
|
29560
|
+
googleADK: true,
|
|
29561
|
+
huggingface: true,
|
|
29562
|
+
claudeAgentSDK: true,
|
|
29563
|
+
cursor: true,
|
|
29564
|
+
cursorSDK: true,
|
|
29565
|
+
flue: true,
|
|
29566
|
+
openAIAgents: true,
|
|
29567
|
+
openrouter: true,
|
|
29568
|
+
openrouterAgent: true,
|
|
29569
|
+
mistral: true,
|
|
29570
|
+
cohere: true,
|
|
29571
|
+
groq: true,
|
|
29572
|
+
genkit: true,
|
|
29573
|
+
gitHubCopilot: true,
|
|
29574
|
+
langchain: true,
|
|
29575
|
+
langgraph: true
|
|
29576
|
+
};
|
|
29577
|
+
}
|
|
29578
|
+
function readDisabledInstrumentationEnvConfig(disabledList) {
|
|
29579
|
+
const integrations = {};
|
|
29580
|
+
if (disabledList) {
|
|
29581
|
+
for (const value of disabledList.split(",")) {
|
|
29582
|
+
const sdk = value.trim().toLowerCase();
|
|
29583
|
+
if (sdk.length > 0) {
|
|
29584
|
+
integrations[envIntegrationAliases[sdk] ?? sdk] = false;
|
|
29585
|
+
}
|
|
29586
|
+
}
|
|
29587
|
+
}
|
|
29588
|
+
return { integrations };
|
|
29589
|
+
}
|
|
29590
|
+
|
|
27218
29591
|
// src/instrumentation/registry.ts
|
|
27219
29592
|
var REGISTRY_STATE_KEY = /* @__PURE__ */ Symbol.for("braintrust.registry");
|
|
27220
29593
|
function getSharedState() {
|
|
@@ -27293,60 +29666,75 @@ var PluginRegistry = class {
|
|
|
27293
29666
|
* Get default configuration (all integrations enabled).
|
|
27294
29667
|
*/
|
|
27295
29668
|
getDefaultConfig() {
|
|
27296
|
-
return
|
|
27297
|
-
openai: true,
|
|
27298
|
-
openaiCodexSDK: true,
|
|
27299
|
-
anthropic: true,
|
|
27300
|
-
vercel: true,
|
|
27301
|
-
aisdk: true,
|
|
27302
|
-
google: true,
|
|
27303
|
-
googleGenAI: true,
|
|
27304
|
-
googleADK: true,
|
|
27305
|
-
huggingface: true,
|
|
27306
|
-
claudeAgentSDK: true,
|
|
27307
|
-
cursor: true,
|
|
27308
|
-
cursorSDK: true,
|
|
27309
|
-
openrouter: true,
|
|
27310
|
-
openrouterAgent: true,
|
|
27311
|
-
mistral: true,
|
|
27312
|
-
cohere: true,
|
|
27313
|
-
groq: true,
|
|
27314
|
-
genkit: true,
|
|
27315
|
-
gitHubCopilot: true
|
|
27316
|
-
};
|
|
29669
|
+
return getDefaultInstrumentationIntegrations();
|
|
27317
29670
|
}
|
|
27318
29671
|
/**
|
|
27319
29672
|
* Read configuration from environment variables.
|
|
27320
29673
|
* Supports: BRAINTRUST_DISABLE_INSTRUMENTATION=openai,anthropic,...
|
|
27321
29674
|
*/
|
|
27322
29675
|
readEnvConfig() {
|
|
27323
|
-
|
|
27324
|
-
|
|
27325
|
-
|
|
27326
|
-
const disabled = disabledList.split(",").map((s) => s.trim().toLowerCase()).filter((s) => s.length > 0);
|
|
27327
|
-
for (const sdk of disabled) {
|
|
27328
|
-
if (sdk === "cursor-sdk") {
|
|
27329
|
-
integrations.cursorSDK = false;
|
|
27330
|
-
} else if (sdk === "githubcopilot" || sdk === "github-copilot" || sdk === "copilot-sdk") {
|
|
27331
|
-
integrations.gitHubCopilot = false;
|
|
27332
|
-
} else if (sdk === "openai-codex-sdk") {
|
|
27333
|
-
integrations.openaiCodexSDK = false;
|
|
27334
|
-
} else {
|
|
27335
|
-
integrations[sdk] = false;
|
|
27336
|
-
}
|
|
27337
|
-
}
|
|
27338
|
-
}
|
|
27339
|
-
return { integrations };
|
|
29676
|
+
return readDisabledInstrumentationEnvConfig(
|
|
29677
|
+
isomorph_default.getEnv("BRAINTRUST_DISABLE_INSTRUMENTATION")
|
|
29678
|
+
);
|
|
27340
29679
|
}
|
|
27341
29680
|
};
|
|
27342
29681
|
var registry = new PluginRegistry();
|
|
27343
29682
|
|
|
27344
29683
|
// src/node/config.ts
|
|
29684
|
+
var BRAINTRUST_ENV_SEARCH_PARENT_LIMIT = 64;
|
|
27345
29685
|
function configureNode() {
|
|
27346
29686
|
isomorph_default.buildType = "node";
|
|
27347
29687
|
isomorph_default.getRepoInfo = getRepoInfo;
|
|
27348
29688
|
isomorph_default.getPastNAncestors = getPastNAncestors;
|
|
27349
|
-
isomorph_default.getEnv = (name) =>
|
|
29689
|
+
isomorph_default.getEnv = (name) => {
|
|
29690
|
+
const value = process.env[name];
|
|
29691
|
+
return name === "BRAINTRUST_API_KEY" && !value?.trim() ? void 0 : value;
|
|
29692
|
+
};
|
|
29693
|
+
isomorph_default.getBraintrustApiKey = async () => {
|
|
29694
|
+
const value = process.env.BRAINTRUST_API_KEY;
|
|
29695
|
+
if (value?.trim()) {
|
|
29696
|
+
return value;
|
|
29697
|
+
}
|
|
29698
|
+
const envPaths = [];
|
|
29699
|
+
for (let dir2 = process.cwd(), depth = 0; depth <= BRAINTRUST_ENV_SEARCH_PARENT_LIMIT; dir2 = path.dirname(dir2), depth++) {
|
|
29700
|
+
envPaths.push(path.join(dir2, ".env.braintrust"));
|
|
29701
|
+
if (path.dirname(dir2) === dir2) {
|
|
29702
|
+
break;
|
|
29703
|
+
}
|
|
29704
|
+
}
|
|
29705
|
+
const pending = /* @__PURE__ */ new Map();
|
|
29706
|
+
envPaths.forEach((envPath, index) => {
|
|
29707
|
+
pending.set(
|
|
29708
|
+
index,
|
|
29709
|
+
fs.readFile(envPath, "utf8").then(
|
|
29710
|
+
(contents) => ({ contents, envPath, index }),
|
|
29711
|
+
(error2) => ({ error: error2, envPath, index })
|
|
29712
|
+
)
|
|
29713
|
+
);
|
|
29714
|
+
});
|
|
29715
|
+
const results = [];
|
|
29716
|
+
let nearestUnresolvedIndex = 0;
|
|
29717
|
+
while (pending.size > 0) {
|
|
29718
|
+
const result = await Promise.race(pending.values());
|
|
29719
|
+
pending.delete(result.index);
|
|
29720
|
+
results[result.index] = result;
|
|
29721
|
+
while (results[nearestUnresolvedIndex]) {
|
|
29722
|
+
const nearestResult = results[nearestUnresolvedIndex];
|
|
29723
|
+
if ("contents" in nearestResult) {
|
|
29724
|
+
const parsed = dotenv.parse(nearestResult.contents);
|
|
29725
|
+
const apiKey = parsed.BRAINTRUST_API_KEY;
|
|
29726
|
+
return apiKey?.trim() ? apiKey : void 0;
|
|
29727
|
+
}
|
|
29728
|
+
const e = nearestResult.error;
|
|
29729
|
+
if (typeof e === "object" && e !== null && "code" in e && e.code === "ENOENT") {
|
|
29730
|
+
nearestUnresolvedIndex++;
|
|
29731
|
+
continue;
|
|
29732
|
+
}
|
|
29733
|
+
return void 0;
|
|
29734
|
+
}
|
|
29735
|
+
}
|
|
29736
|
+
return void 0;
|
|
29737
|
+
};
|
|
27350
29738
|
isomorph_default.getCallerLocation = getCallerLocation;
|
|
27351
29739
|
isomorph_default.newAsyncLocalStorage = () => new import_node_async_hooks.AsyncLocalStorage();
|
|
27352
29740
|
isomorph_default.newTracingChannel = (nameOrChannels) => diagnostics_channel.tracingChannel(nameOrChannels);
|
|
@@ -28506,7 +30894,7 @@ async function buildBundledFunctionEntry({
|
|
|
28506
30894
|
|
|
28507
30895
|
// src/cli/util/bundle.ts
|
|
28508
30896
|
var import_env = require("@next/env");
|
|
28509
|
-
var
|
|
30897
|
+
var dotenv2 = __toESM(require("dotenv"));
|
|
28510
30898
|
|
|
28511
30899
|
// src/cli/util/debug-logging.ts
|
|
28512
30900
|
var VERBOSE_DEPRECATION_MESSAGE = "--verbose is deprecated and will be removed in a future version of braintrust. Use --debug-logging debug to see full stack traces and troubleshooting details.";
|
|
@@ -28533,7 +30921,7 @@ async function loadCLIEnv(args) {
|
|
|
28533
30921
|
normalizeDebugLoggingArgs(args);
|
|
28534
30922
|
(0, import_env.loadEnvConfig)(process.cwd(), true);
|
|
28535
30923
|
if (args.env_file) {
|
|
28536
|
-
const loaded =
|
|
30924
|
+
const loaded = dotenv2.config({ path: args.env_file });
|
|
28537
30925
|
if (loaded.error) {
|
|
28538
30926
|
console.error(error(`Error loading ${args.env_file}: ${loaded.error}`));
|
|
28539
30927
|
process.exit(1);
|
|
@@ -30084,7 +32472,7 @@ async function run(args) {
|
|
|
30084
32472
|
normalizeDebugLoggingArgs(args);
|
|
30085
32473
|
(0, import_env2.loadEnvConfig)(process.cwd(), true);
|
|
30086
32474
|
if (args.env_file) {
|
|
30087
|
-
const loaded =
|
|
32475
|
+
const loaded = dotenv3.config({ path: args.env_file });
|
|
30088
32476
|
if (loaded.error) {
|
|
30089
32477
|
console.error(error(`Error loading ${args.env_file}: ${loaded.error}`));
|
|
30090
32478
|
process.exit(1);
|
|
@@ -30162,7 +32550,7 @@ async function run(args) {
|
|
|
30162
32550
|
}
|
|
30163
32551
|
function addAuthArgs(parser) {
|
|
30164
32552
|
parser.add_argument("--api-key", {
|
|
30165
|
-
help: "Specify a braintrust api key. If the parameter is not specified, the
|
|
32553
|
+
help: "Specify a braintrust api key. If the parameter is not specified, BRAINTRUST_API_KEY or the nearest .env.braintrust file will be used."
|
|
30166
32554
|
});
|
|
30167
32555
|
parser.add_argument("--org-name", {
|
|
30168
32556
|
help: "The name of a specific organization to connect to. This is useful if you belong to multiple."
|