braintrust 3.21.0 → 3.23.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 +47 -0
- package/dev/dist/index.d.mts +1030 -1
- package/dev/dist/index.d.ts +1030 -1
- package/dev/dist/index.js +1429 -663
- package/dev/dist/index.mjs +811 -45
- package/dist/apply-auto-instrumentation.js +222 -186
- package/dist/apply-auto-instrumentation.mjs +37 -1
- package/dist/auto-instrumentations/bundler/esbuild.cjs +53 -1
- package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
- package/dist/auto-instrumentations/bundler/next.cjs +53 -1
- package/dist/auto-instrumentations/bundler/next.mjs +3 -3
- package/dist/auto-instrumentations/bundler/rollup.cjs +53 -1
- package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
- package/dist/auto-instrumentations/bundler/vite.cjs +53 -1
- package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
- package/dist/auto-instrumentations/bundler/webpack-loader.cjs +53 -1
- package/dist/auto-instrumentations/bundler/webpack.cjs +53 -1
- package/dist/auto-instrumentations/bundler/webpack.mjs +3 -3
- package/dist/auto-instrumentations/{chunk-TKRPRPGD.mjs → chunk-EXY7QCJD.mjs} +5 -2
- package/dist/auto-instrumentations/{chunk-T6J4C7LX.mjs → chunk-KIMLYPRW.mjs} +1 -1
- package/dist/auto-instrumentations/{chunk-BRQX23KL.mjs → chunk-YXLNSAMJ.mjs} +51 -0
- package/dist/auto-instrumentations/hook.mjs +224 -31
- package/dist/auto-instrumentations/index.cjs +52 -0
- package/dist/auto-instrumentations/index.d.mts +3 -1
- package/dist/auto-instrumentations/index.d.ts +3 -1
- package/dist/auto-instrumentations/index.mjs +3 -1
- package/dist/browser.d.mts +3273 -93
- package/dist/browser.d.ts +3273 -93
- package/dist/browser.js +2495 -63
- package/dist/browser.mjs +2495 -63
- package/dist/{chunk-KMGUTPB7.mjs → chunk-36IPYKMG.mjs} +20 -1
- package/dist/{chunk-BFGIH2ZJ.js → chunk-CDIKAHDZ.js} +21 -2
- package/dist/{chunk-FY7DAKA5.js → chunk-FZWPFCVE.js} +1590 -832
- package/dist/{chunk-O2P765XK.mjs → chunk-IXL4PMY4.mjs} +802 -44
- package/dist/cli.js +816 -47
- package/dist/edge-light.d.mts +1 -1
- package/dist/edge-light.d.ts +1 -1
- package/dist/edge-light.js +2495 -63
- package/dist/edge-light.mjs +2495 -63
- package/dist/index.d.mts +3273 -93
- package/dist/index.d.ts +3273 -93
- package/dist/index.js +2078 -416
- package/dist/index.mjs +1664 -2
- package/dist/instrumentation/index.d.mts +912 -2
- package/dist/instrumentation/index.d.ts +912 -2
- package/dist/instrumentation/index.js +2202 -42
- package/dist/instrumentation/index.mjs +2200 -42
- package/dist/vitest-evals-reporter.js +16 -16
- package/dist/vitest-evals-reporter.mjs +2 -2
- package/dist/workerd.d.mts +1 -1
- package/dist/workerd.d.ts +1 -1
- package/dist/workerd.js +2495 -63
- package/dist/workerd.mjs +2495 -63
- package/package.json +5 -2
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.23.0",
|
|
1236
1236
|
description: "SDK for integrating Braintrust",
|
|
1237
1237
|
repository: {
|
|
1238
1238
|
type: "git",
|
|
@@ -1413,6 +1413,7 @@ var require_package = __commonJS({
|
|
|
1413
1413
|
"@types/async": "^3.2.24",
|
|
1414
1414
|
"@types/cli-progress": "^3.11.5",
|
|
1415
1415
|
"@types/cors": "^2.8.17",
|
|
1416
|
+
"@types/esquery": "^1.5.4",
|
|
1416
1417
|
"@types/express": "^5.0.0",
|
|
1417
1418
|
"@types/http-errors": "^2.0.4",
|
|
1418
1419
|
"@types/mustache": "^4.2.5",
|
|
@@ -1424,11 +1425,14 @@ var require_package = __commonJS({
|
|
|
1424
1425
|
ai: "^6.0.0",
|
|
1425
1426
|
async: "^3.2.5",
|
|
1426
1427
|
"cross-env": "^7.0.3",
|
|
1428
|
+
"eslint-plugin-es-x": "9.7.0",
|
|
1429
|
+
"eslint-plugin-n": "^18.2.1",
|
|
1427
1430
|
"eslint-plugin-node-import": "^1.0.5",
|
|
1428
1431
|
openai: "6.25.0",
|
|
1429
1432
|
rollup: "^4.60.3",
|
|
1430
1433
|
tar: "^7.5.16",
|
|
1431
1434
|
tinybench: "^4.0.1",
|
|
1435
|
+
"ts-declaration-location": "^1.0.7",
|
|
1432
1436
|
tsup: "^8.5.1",
|
|
1433
1437
|
tsx: "^4.21.0",
|
|
1434
1438
|
typedoc: "^0.25.13",
|
|
@@ -1442,7 +1446,6 @@ var require_package = __commonJS({
|
|
|
1442
1446
|
},
|
|
1443
1447
|
dependencies: {
|
|
1444
1448
|
"@next/env": "^14.2.3",
|
|
1445
|
-
"@types/estree": "^1.0.8",
|
|
1446
1449
|
"@vercel/functions": "^1.0.2",
|
|
1447
1450
|
acorn: "^8.16.0",
|
|
1448
1451
|
"acorn-import-attributes": "^1.9.5",
|
|
@@ -3724,19 +3727,30 @@ var CallEvent = import_v36.z.union([
|
|
|
3724
3727
|
var ChatCompletionContentPartTextWithTitle = import_v36.z.object({
|
|
3725
3728
|
text: import_v36.z.string().default(""),
|
|
3726
3729
|
type: import_v36.z.literal("text"),
|
|
3727
|
-
cache_control: import_v36.z.object({
|
|
3730
|
+
cache_control: import_v36.z.object({
|
|
3731
|
+
type: import_v36.z.literal("ephemeral"),
|
|
3732
|
+
ttl: import_v36.z.enum(["5m", "1h"]).optional()
|
|
3733
|
+
}).optional()
|
|
3728
3734
|
});
|
|
3729
3735
|
var ChatCompletionContentPartImageWithTitle = import_v36.z.object({
|
|
3730
3736
|
image_url: import_v36.z.object({
|
|
3731
3737
|
url: import_v36.z.string(),
|
|
3732
3738
|
detail: import_v36.z.union([import_v36.z.literal("auto"), import_v36.z.literal("low"), import_v36.z.literal("high")]).optional()
|
|
3733
3739
|
}),
|
|
3734
|
-
type: import_v36.z.literal("image_url")
|
|
3740
|
+
type: import_v36.z.literal("image_url"),
|
|
3741
|
+
cache_control: import_v36.z.object({
|
|
3742
|
+
type: import_v36.z.literal("ephemeral"),
|
|
3743
|
+
ttl: import_v36.z.enum(["5m", "1h"]).optional()
|
|
3744
|
+
}).optional()
|
|
3735
3745
|
});
|
|
3736
3746
|
var ChatCompletionContentPartFileFile = import_v36.z.object({ file_data: import_v36.z.string(), filename: import_v36.z.string(), file_id: import_v36.z.string() }).partial();
|
|
3737
3747
|
var ChatCompletionContentPartFileWithTitle = import_v36.z.object({
|
|
3738
3748
|
file: ChatCompletionContentPartFileFile,
|
|
3739
|
-
type: import_v36.z.literal("file")
|
|
3749
|
+
type: import_v36.z.literal("file"),
|
|
3750
|
+
cache_control: import_v36.z.object({
|
|
3751
|
+
type: import_v36.z.literal("ephemeral"),
|
|
3752
|
+
ttl: import_v36.z.enum(["5m", "1h"]).optional()
|
|
3753
|
+
}).optional()
|
|
3740
3754
|
});
|
|
3741
3755
|
var ChatCompletionContentPart = import_v36.z.union([
|
|
3742
3756
|
ChatCompletionContentPartTextWithTitle,
|
|
@@ -3746,7 +3760,10 @@ var ChatCompletionContentPart = import_v36.z.union([
|
|
|
3746
3760
|
var ChatCompletionContentPartText = import_v36.z.object({
|
|
3747
3761
|
text: import_v36.z.string().default(""),
|
|
3748
3762
|
type: import_v36.z.literal("text"),
|
|
3749
|
-
cache_control: import_v36.z.object({
|
|
3763
|
+
cache_control: import_v36.z.object({
|
|
3764
|
+
type: import_v36.z.literal("ephemeral"),
|
|
3765
|
+
ttl: import_v36.z.enum(["5m", "1h"]).optional()
|
|
3766
|
+
}).optional()
|
|
3750
3767
|
});
|
|
3751
3768
|
var ChatCompletionMessageToolCall = import_v36.z.object({
|
|
3752
3769
|
id: import_v36.z.string(),
|
|
@@ -5781,7 +5798,7 @@ var DiskCache = class {
|
|
|
5781
5798
|
}
|
|
5782
5799
|
};
|
|
5783
5800
|
|
|
5784
|
-
// src/
|
|
5801
|
+
// src/lru-cache.ts
|
|
5785
5802
|
var LRUCache = class {
|
|
5786
5803
|
cache;
|
|
5787
5804
|
maxSize;
|
|
@@ -5797,13 +5814,23 @@ var LRUCache = class {
|
|
|
5797
5814
|
* @returns The cached value if found, undefined otherwise.
|
|
5798
5815
|
*/
|
|
5799
5816
|
get(key) {
|
|
5800
|
-
const
|
|
5801
|
-
if (
|
|
5817
|
+
const entry = this.cache.get(key);
|
|
5818
|
+
if (entry === void 0) {
|
|
5802
5819
|
return void 0;
|
|
5803
5820
|
}
|
|
5804
5821
|
this.cache.delete(key);
|
|
5805
|
-
this.cache.set(key,
|
|
5806
|
-
return value;
|
|
5822
|
+
this.cache.set(key, entry);
|
|
5823
|
+
return entry.value;
|
|
5824
|
+
}
|
|
5825
|
+
/**
|
|
5826
|
+
* Checks whether a key exists and marks it as most recently used.
|
|
5827
|
+
*/
|
|
5828
|
+
has(key) {
|
|
5829
|
+
if (!this.cache.has(key)) {
|
|
5830
|
+
return false;
|
|
5831
|
+
}
|
|
5832
|
+
this.get(key);
|
|
5833
|
+
return true;
|
|
5807
5834
|
}
|
|
5808
5835
|
/**
|
|
5809
5836
|
* Stores a value in the cache.
|
|
@@ -5820,7 +5847,38 @@ var LRUCache = class {
|
|
|
5820
5847
|
const first = this.cache.keys().next().value;
|
|
5821
5848
|
this.cache.delete(first);
|
|
5822
5849
|
}
|
|
5823
|
-
this.cache.set(key, value);
|
|
5850
|
+
this.cache.set(key, { value });
|
|
5851
|
+
}
|
|
5852
|
+
/**
|
|
5853
|
+
* Removes an item from the cache.
|
|
5854
|
+
*/
|
|
5855
|
+
delete(key) {
|
|
5856
|
+
return this.cache.delete(key);
|
|
5857
|
+
}
|
|
5858
|
+
/**
|
|
5859
|
+
* Iterates over cache entries from least to most recently used.
|
|
5860
|
+
*/
|
|
5861
|
+
*entries() {
|
|
5862
|
+
for (const [key, entry] of this.cache) {
|
|
5863
|
+
yield [key, entry.value];
|
|
5864
|
+
}
|
|
5865
|
+
}
|
|
5866
|
+
/**
|
|
5867
|
+
* Iterates over cache keys from least to most recently used.
|
|
5868
|
+
*/
|
|
5869
|
+
keys() {
|
|
5870
|
+
return this.cache.keys();
|
|
5871
|
+
}
|
|
5872
|
+
/**
|
|
5873
|
+
* Iterates over cache values from least to most recently used.
|
|
5874
|
+
*/
|
|
5875
|
+
*values() {
|
|
5876
|
+
for (const entry of this.cache.values()) {
|
|
5877
|
+
yield entry.value;
|
|
5878
|
+
}
|
|
5879
|
+
}
|
|
5880
|
+
[Symbol.iterator]() {
|
|
5881
|
+
return this.entries();
|
|
5824
5882
|
}
|
|
5825
5883
|
/**
|
|
5826
5884
|
* Removes all items from the cache.
|
|
@@ -6378,6 +6436,9 @@ function applyMaskingToField(maskingFunction, data, fieldName) {
|
|
|
6378
6436
|
return `ERROR: Failed to mask field '${fieldName}' - ${errorType}`;
|
|
6379
6437
|
}
|
|
6380
6438
|
}
|
|
6439
|
+
var INITIAL_SPAN_WRITE_AS_MERGE = /* @__PURE__ */ Symbol(
|
|
6440
|
+
"braintrust.initial-span-write-as-merge"
|
|
6441
|
+
);
|
|
6381
6442
|
var BRAINTRUST_CURRENT_SPAN_STORE = /* @__PURE__ */ Symbol.for(
|
|
6382
6443
|
"braintrust.currentSpanStore"
|
|
6383
6444
|
);
|
|
@@ -6947,25 +7008,46 @@ var HTTPConnection = class _HTTPConnection {
|
|
|
6947
7008
|
})
|
|
6948
7009
|
);
|
|
6949
7010
|
}
|
|
6950
|
-
async post(path8, params, config3) {
|
|
7011
|
+
async post(path8, params, config3, retries = 0) {
|
|
6951
7012
|
const { headers, ...rest } = config3 || {};
|
|
6952
7013
|
const this_fetch = this.fetch;
|
|
6953
7014
|
const this_base_url = this.base_url;
|
|
6954
7015
|
const this_headers = this.headers;
|
|
6955
|
-
|
|
6956
|
-
|
|
6957
|
-
|
|
6958
|
-
|
|
6959
|
-
|
|
6960
|
-
|
|
6961
|
-
|
|
6962
|
-
|
|
6963
|
-
|
|
6964
|
-
|
|
6965
|
-
|
|
6966
|
-
|
|
6967
|
-
|
|
6968
|
-
|
|
7016
|
+
const tries = retries + 1;
|
|
7017
|
+
for (let i = 0; i < tries; i++) {
|
|
7018
|
+
try {
|
|
7019
|
+
return await checkResponse(
|
|
7020
|
+
await this_fetch(_urljoin(this_base_url, path8), {
|
|
7021
|
+
method: "POST",
|
|
7022
|
+
headers: {
|
|
7023
|
+
Accept: "application/json",
|
|
7024
|
+
"Content-Type": "application/json",
|
|
7025
|
+
...this_headers,
|
|
7026
|
+
...headers
|
|
7027
|
+
},
|
|
7028
|
+
body: typeof params === "string" ? params : params ? JSON.stringify(params) : void 0,
|
|
7029
|
+
keepalive: true,
|
|
7030
|
+
...rest
|
|
7031
|
+
})
|
|
7032
|
+
);
|
|
7033
|
+
} catch (error2) {
|
|
7034
|
+
if (config3?.signal?.aborted) {
|
|
7035
|
+
throw getAbortReason(config3.signal);
|
|
7036
|
+
}
|
|
7037
|
+
if (i === tries - 1 || !isRetryableHTTPError(error2)) {
|
|
7038
|
+
throw error2;
|
|
7039
|
+
}
|
|
7040
|
+
debugLogger.debug(
|
|
7041
|
+
`Retrying API request ${path8} after ${formatHTTPError(error2)}`
|
|
7042
|
+
);
|
|
7043
|
+
const sleepTimeMs = HTTP_RETRY_BASE_SLEEP_TIME_S * 1e3 * 2 ** i + Math.random() * HTTP_RETRY_JITTER_MS;
|
|
7044
|
+
debugLogger.info(
|
|
7045
|
+
`Sleeping for ${sleepTimeMs}ms before retrying API request`
|
|
7046
|
+
);
|
|
7047
|
+
await waitForRetry(sleepTimeMs, config3?.signal);
|
|
7048
|
+
}
|
|
7049
|
+
}
|
|
7050
|
+
throw new Error("Unexpected retry state");
|
|
6969
7051
|
}
|
|
6970
7052
|
async get_json(object_type, args = void 0, retries = 0) {
|
|
6971
7053
|
const tries = retries + 1;
|
|
@@ -7865,6 +7947,45 @@ function now() {
|
|
|
7865
7947
|
var DEFAULT_FLUSH_BACKPRESSURE_BYTES = 10 * 1024 * 1024;
|
|
7866
7948
|
var BACKGROUND_LOGGER_BASE_SLEEP_TIME_S = 1;
|
|
7867
7949
|
var HTTP_RETRY_BASE_SLEEP_TIME_S = 1;
|
|
7950
|
+
var HTTP_RETRY_JITTER_MS = 200;
|
|
7951
|
+
var BTQL_HTTP_RETRIES = 3;
|
|
7952
|
+
var RETRYABLE_HTTP_STATUS_CODES = /* @__PURE__ */ new Set([500, 502, 503, 504]);
|
|
7953
|
+
function isRetryableHTTPError(error2) {
|
|
7954
|
+
return !(error2 instanceof FailedHTTPResponse) || RETRYABLE_HTTP_STATUS_CODES.has(error2.status);
|
|
7955
|
+
}
|
|
7956
|
+
function formatHTTPError(error2) {
|
|
7957
|
+
if (error2 instanceof FailedHTTPResponse) {
|
|
7958
|
+
return `${error2.status} ${error2.text}`;
|
|
7959
|
+
}
|
|
7960
|
+
return error2 instanceof Error ? error2.message : String(error2);
|
|
7961
|
+
}
|
|
7962
|
+
function getAbortReason(signal) {
|
|
7963
|
+
return signal.reason ?? new Error("Request aborted");
|
|
7964
|
+
}
|
|
7965
|
+
async function waitForRetry(delayMs, signal) {
|
|
7966
|
+
if (!signal) {
|
|
7967
|
+
await new Promise((resolve2) => setTimeout(resolve2, delayMs));
|
|
7968
|
+
return;
|
|
7969
|
+
}
|
|
7970
|
+
if (signal.aborted) {
|
|
7971
|
+
throw getAbortReason(signal);
|
|
7972
|
+
}
|
|
7973
|
+
await new Promise((resolve2, reject2) => {
|
|
7974
|
+
const onAbort = () => {
|
|
7975
|
+
clearTimeout(timeout);
|
|
7976
|
+
signal.removeEventListener("abort", onAbort);
|
|
7977
|
+
reject2(getAbortReason(signal));
|
|
7978
|
+
};
|
|
7979
|
+
const timeout = setTimeout(() => {
|
|
7980
|
+
signal.removeEventListener("abort", onAbort);
|
|
7981
|
+
resolve2();
|
|
7982
|
+
}, delayMs);
|
|
7983
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
7984
|
+
if (signal.aborted) {
|
|
7985
|
+
onAbort();
|
|
7986
|
+
}
|
|
7987
|
+
});
|
|
7988
|
+
}
|
|
7868
7989
|
var HTTPBackgroundLogger = class _HTTPBackgroundLogger {
|
|
7869
7990
|
apiConn;
|
|
7870
7991
|
queue;
|
|
@@ -9292,15 +9413,15 @@ function parentSpanIdsUsable(spanId, rootSpanId) {
|
|
|
9292
9413
|
return Boolean(spanId) && Boolean(rootSpanId);
|
|
9293
9414
|
}
|
|
9294
9415
|
function logError(span, error2) {
|
|
9295
|
-
let
|
|
9416
|
+
let errorMessage2 = "<error>";
|
|
9296
9417
|
let stackTrace = "";
|
|
9297
9418
|
if (error2 instanceof Error) {
|
|
9298
|
-
|
|
9419
|
+
errorMessage2 = error2.message;
|
|
9299
9420
|
stackTrace = error2.stack || "";
|
|
9300
9421
|
} else {
|
|
9301
|
-
|
|
9422
|
+
errorMessage2 = String(error2);
|
|
9302
9423
|
}
|
|
9303
|
-
span.log({ error: `${
|
|
9424
|
+
span.log({ error: `${errorMessage2}
|
|
9304
9425
|
|
|
9305
9426
|
${stackTrace}` });
|
|
9306
9427
|
}
|
|
@@ -9679,7 +9800,8 @@ var ObjectFetcher = class {
|
|
|
9679
9800
|
version: this.pinnedVersion
|
|
9680
9801
|
} : {}
|
|
9681
9802
|
},
|
|
9682
|
-
{ headers: { "Accept-Encoding": "gzip" } }
|
|
9803
|
+
{ headers: { "Accept-Encoding": "gzip" } },
|
|
9804
|
+
BTQL_HTTP_RETRIES
|
|
9683
9805
|
);
|
|
9684
9806
|
const respJson = await resp.json();
|
|
9685
9807
|
const mutate = this.mutateRecord;
|
|
@@ -10196,7 +10318,7 @@ var SpanImpl = class _SpanImpl {
|
|
|
10196
10318
|
this._spanId = resolvedIds.spanId;
|
|
10197
10319
|
this._rootSpanId = resolvedIds.rootSpanId;
|
|
10198
10320
|
this._spanParents = resolvedIds.spanParents;
|
|
10199
|
-
this.isMerge =
|
|
10321
|
+
this.isMerge = args[INITIAL_SPAN_WRITE_AS_MERGE] === true;
|
|
10200
10322
|
this.logInternal({ event, internalData });
|
|
10201
10323
|
this.isMerge = true;
|
|
10202
10324
|
}
|
|
@@ -32855,6 +32977,446 @@ function isBraintrustHandler(handler) {
|
|
|
32855
32977
|
return Reflect.get(handler, "name") === BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
|
|
32856
32978
|
}
|
|
32857
32979
|
|
|
32980
|
+
// src/instrumentation/plugins/langsmith-channels.ts
|
|
32981
|
+
var langSmithChannels = defineChannels("langsmith", {
|
|
32982
|
+
createRun: channel({
|
|
32983
|
+
channelName: "Client.createRun",
|
|
32984
|
+
kind: "async"
|
|
32985
|
+
}),
|
|
32986
|
+
updateRun: channel({
|
|
32987
|
+
channelName: "Client.updateRun",
|
|
32988
|
+
kind: "async"
|
|
32989
|
+
}),
|
|
32990
|
+
batchIngestRuns: channel({
|
|
32991
|
+
channelName: "Client.batchIngestRuns",
|
|
32992
|
+
kind: "async"
|
|
32993
|
+
})
|
|
32994
|
+
});
|
|
32995
|
+
|
|
32996
|
+
// src/instrumentation/plugins/langsmith-plugin.ts
|
|
32997
|
+
var MAX_COMPLETED_RUNS = 1e4;
|
|
32998
|
+
var BLOCKED_METADATA_KEYS = /* @__PURE__ */ new Set([
|
|
32999
|
+
"__proto__",
|
|
33000
|
+
"constructor",
|
|
33001
|
+
"prototype",
|
|
33002
|
+
"usage_metadata"
|
|
33003
|
+
]);
|
|
33004
|
+
var BLOCKED_METADATA_PREFIXES = ["__pregel_", "langgraph_", "lc_"];
|
|
33005
|
+
var LLM_SETTING_KEYS = [
|
|
33006
|
+
"temperature",
|
|
33007
|
+
"top_p",
|
|
33008
|
+
"max_tokens",
|
|
33009
|
+
"frequency_penalty",
|
|
33010
|
+
"presence_penalty",
|
|
33011
|
+
"stop",
|
|
33012
|
+
"response_format"
|
|
33013
|
+
];
|
|
33014
|
+
var LangSmithPlugin = class extends BasePlugin {
|
|
33015
|
+
activeRuns = /* @__PURE__ */ new Map();
|
|
33016
|
+
completedRuns = new LRUCache({
|
|
33017
|
+
max: MAX_COMPLETED_RUNS
|
|
33018
|
+
});
|
|
33019
|
+
skipLangChainRuns;
|
|
33020
|
+
constructor(options = {}) {
|
|
33021
|
+
super();
|
|
33022
|
+
this.skipLangChainRuns = options.skipLangChainRuns ?? true;
|
|
33023
|
+
}
|
|
33024
|
+
onEnable() {
|
|
33025
|
+
const createChannel = langSmithChannels.createRun.tracingChannel();
|
|
33026
|
+
const createHandlers = {
|
|
33027
|
+
start: (event) => {
|
|
33028
|
+
this.containLifecycleFailure("createRun", () => {
|
|
33029
|
+
this.processCreate(event.arguments[0]);
|
|
33030
|
+
});
|
|
33031
|
+
}
|
|
33032
|
+
};
|
|
33033
|
+
createChannel.subscribe(createHandlers);
|
|
33034
|
+
this.unsubscribers.push(() => createChannel.unsubscribe(createHandlers));
|
|
33035
|
+
const updateChannel = langSmithChannels.updateRun.tracingChannel();
|
|
33036
|
+
const updateHandlers = {
|
|
33037
|
+
start: (event) => {
|
|
33038
|
+
this.containLifecycleFailure("updateRun", () => {
|
|
33039
|
+
this.processUpdate(event.arguments[0], event.arguments[1]);
|
|
33040
|
+
});
|
|
33041
|
+
}
|
|
33042
|
+
};
|
|
33043
|
+
updateChannel.subscribe(updateHandlers);
|
|
33044
|
+
this.unsubscribers.push(() => updateChannel.unsubscribe(updateHandlers));
|
|
33045
|
+
const batchChannel = langSmithChannels.batchIngestRuns.tracingChannel();
|
|
33046
|
+
const batchHandlers = {
|
|
33047
|
+
start: (event) => {
|
|
33048
|
+
this.containLifecycleFailure("batchIngestRuns", () => {
|
|
33049
|
+
this.processBatch(event.arguments[0]);
|
|
33050
|
+
});
|
|
33051
|
+
}
|
|
33052
|
+
};
|
|
33053
|
+
batchChannel.subscribe(batchHandlers);
|
|
33054
|
+
this.unsubscribers.push(() => batchChannel.unsubscribe(batchHandlers));
|
|
33055
|
+
}
|
|
33056
|
+
onDisable() {
|
|
33057
|
+
this.unsubscribers = unsubscribeAll(this.unsubscribers);
|
|
33058
|
+
for (const { span } of this.activeRuns.values()) {
|
|
33059
|
+
span.end();
|
|
33060
|
+
}
|
|
33061
|
+
this.activeRuns.clear();
|
|
33062
|
+
this.completedRuns.clear();
|
|
33063
|
+
}
|
|
33064
|
+
processBatch(batch) {
|
|
33065
|
+
if (!isRecord2(batch)) {
|
|
33066
|
+
return;
|
|
33067
|
+
}
|
|
33068
|
+
const creates = ownValue(batch, "runCreates");
|
|
33069
|
+
if (Array.isArray(creates)) {
|
|
33070
|
+
const parentFirst = [...creates].sort((left, right) => {
|
|
33071
|
+
const leftId = stringValue2(ownValue(left, "id"));
|
|
33072
|
+
const rightId = stringValue2(ownValue(right, "id"));
|
|
33073
|
+
const leftParent = stringValue2(ownValue(left, "parent_run_id"));
|
|
33074
|
+
const rightParent = stringValue2(ownValue(right, "parent_run_id"));
|
|
33075
|
+
if (leftParent && leftParent === rightId) {
|
|
33076
|
+
return 1;
|
|
33077
|
+
}
|
|
33078
|
+
if (rightParent && rightParent === leftId) {
|
|
33079
|
+
return -1;
|
|
33080
|
+
}
|
|
33081
|
+
return dottedOrderDepth(left) - dottedOrderDepth(right);
|
|
33082
|
+
});
|
|
33083
|
+
for (const run2 of parentFirst) {
|
|
33084
|
+
this.containLifecycleFailure("batchIngestRuns create", () => {
|
|
33085
|
+
this.processCreate(run2);
|
|
33086
|
+
});
|
|
33087
|
+
}
|
|
33088
|
+
}
|
|
33089
|
+
const updates = ownValue(batch, "runUpdates");
|
|
33090
|
+
if (Array.isArray(updates)) {
|
|
33091
|
+
for (const run2 of updates) {
|
|
33092
|
+
this.containLifecycleFailure("batchIngestRuns update", () => {
|
|
33093
|
+
this.processUpdate(stringValue2(ownValue(run2, "id")) ?? "", run2);
|
|
33094
|
+
});
|
|
33095
|
+
}
|
|
33096
|
+
}
|
|
33097
|
+
}
|
|
33098
|
+
processCreate(run2) {
|
|
33099
|
+
const id = stringValue2(ownValue(run2, "id"));
|
|
33100
|
+
if (!id || this.completedRuns.get(id)) {
|
|
33101
|
+
return;
|
|
33102
|
+
}
|
|
33103
|
+
if (this.shouldSkipLangChainRun(run2)) {
|
|
33104
|
+
this.completedRuns.set(id, true);
|
|
33105
|
+
return;
|
|
33106
|
+
}
|
|
33107
|
+
const active = this.activeRuns.get(id);
|
|
33108
|
+
if (active) {
|
|
33109
|
+
const previous = active.run;
|
|
33110
|
+
active.run = mergeRuns(previous, run2);
|
|
33111
|
+
this.logRun(
|
|
33112
|
+
active.span,
|
|
33113
|
+
active.run,
|
|
33114
|
+
previous,
|
|
33115
|
+
timestampSeconds(ownValue(active.run, "end_time")) !== void 0 || errorMessage(ownValue(active.run, "error")) !== void 0
|
|
33116
|
+
);
|
|
33117
|
+
this.endIfComplete(id, active, active.run);
|
|
33118
|
+
return;
|
|
33119
|
+
}
|
|
33120
|
+
const span = this.startRunSpan(id, run2);
|
|
33121
|
+
const activeRun = { run: run2, span };
|
|
33122
|
+
this.activeRuns.set(id, activeRun);
|
|
33123
|
+
this.logRun(
|
|
33124
|
+
span,
|
|
33125
|
+
run2,
|
|
33126
|
+
void 0,
|
|
33127
|
+
timestampSeconds(ownValue(run2, "end_time")) !== void 0 || errorMessage(ownValue(run2, "error")) !== void 0
|
|
33128
|
+
);
|
|
33129
|
+
this.endIfComplete(id, activeRun, run2);
|
|
33130
|
+
}
|
|
33131
|
+
processUpdate(explicitId, run2) {
|
|
33132
|
+
const id = stringValue2(explicitId) ?? stringValue2(ownValue(run2, "id"));
|
|
33133
|
+
if (!id || this.completedRuns.get(id)) {
|
|
33134
|
+
return;
|
|
33135
|
+
}
|
|
33136
|
+
if (this.shouldSkipLangChainRun(run2)) {
|
|
33137
|
+
const active2 = this.activeRuns.get(id);
|
|
33138
|
+
active2?.span.end();
|
|
33139
|
+
this.activeRuns.delete(id);
|
|
33140
|
+
this.completedRuns.set(id, true);
|
|
33141
|
+
return;
|
|
33142
|
+
}
|
|
33143
|
+
let active = this.activeRuns.get(id);
|
|
33144
|
+
if (!active) {
|
|
33145
|
+
const span = this.startRunSpan(id, run2);
|
|
33146
|
+
active = { run: run2, span };
|
|
33147
|
+
this.activeRuns.set(id, active);
|
|
33148
|
+
}
|
|
33149
|
+
const previous = active.run;
|
|
33150
|
+
active.run = mergeRuns(previous, run2);
|
|
33151
|
+
this.logRun(active.span, active.run, previous, true);
|
|
33152
|
+
this.endIfComplete(id, active, active.run);
|
|
33153
|
+
}
|
|
33154
|
+
startRunSpan(id, run2) {
|
|
33155
|
+
const traceId = stringValue2(ownValue(run2, "trace_id")) ?? id;
|
|
33156
|
+
const parentId = stringValue2(ownValue(run2, "parent_run_id")) ?? stringValue2(ownValue(ownValue(run2, "parent_run"), "id"));
|
|
33157
|
+
const startTime = timestampSeconds(ownValue(run2, "start_time"));
|
|
33158
|
+
return startSpan({
|
|
33159
|
+
name: stringValue2(ownValue(run2, "name")) ?? "LangSmith run",
|
|
33160
|
+
spanId: id,
|
|
33161
|
+
parentSpanIds: {
|
|
33162
|
+
parentSpanIds: parentId ? [parentId] : [],
|
|
33163
|
+
rootSpanId: traceId
|
|
33164
|
+
},
|
|
33165
|
+
spanAttributes: {
|
|
33166
|
+
type: mapRunType(ownValue(run2, "run_type"))
|
|
33167
|
+
},
|
|
33168
|
+
...startTime === void 0 ? {} : { startTime },
|
|
33169
|
+
event: { id }
|
|
33170
|
+
});
|
|
33171
|
+
}
|
|
33172
|
+
logRun(span, run2, previous, includeOutput) {
|
|
33173
|
+
const inputs = preferOwnValue(run2, previous, "inputs");
|
|
33174
|
+
const outputs = preferOwnValue(run2, previous, "outputs");
|
|
33175
|
+
const error2 = errorMessage(preferOwnValue(run2, previous, "error"));
|
|
33176
|
+
const metadata = extractMetadata(run2, previous);
|
|
33177
|
+
const tags = extractTags(preferOwnValue(run2, previous, "tags"));
|
|
33178
|
+
const metrics = extractMetrics(run2, previous);
|
|
33179
|
+
span.log({
|
|
33180
|
+
...inputs === void 0 ? {} : { input: sanitizeLoggedValue(inputs) },
|
|
33181
|
+
...includeOutput && outputs !== void 0 ? { output: sanitizeLoggedValue(outputs) } : {},
|
|
33182
|
+
...error2 === void 0 ? {} : { error: error2 },
|
|
33183
|
+
...metadata === void 0 ? {} : { metadata },
|
|
33184
|
+
...tags === void 0 ? {} : { tags },
|
|
33185
|
+
...Object.keys(metrics).length === 0 ? {} : { metrics }
|
|
33186
|
+
});
|
|
33187
|
+
}
|
|
33188
|
+
endIfComplete(id, active, run2) {
|
|
33189
|
+
const endTime = timestampSeconds(ownValue(run2, "end_time"));
|
|
33190
|
+
if (endTime === void 0 && errorMessage(ownValue(run2, "error")) === void 0) {
|
|
33191
|
+
return;
|
|
33192
|
+
}
|
|
33193
|
+
active.span.end(endTime === void 0 ? void 0 : { endTime });
|
|
33194
|
+
this.activeRuns.delete(id);
|
|
33195
|
+
this.completedRuns.set(id, true);
|
|
33196
|
+
}
|
|
33197
|
+
shouldSkipLangChainRun(run2) {
|
|
33198
|
+
if (!this.skipLangChainRuns) {
|
|
33199
|
+
return false;
|
|
33200
|
+
}
|
|
33201
|
+
const serialized = ownValue(run2, "serialized");
|
|
33202
|
+
return isRecord2(serialized) && ownValue(serialized, "lc") === 1;
|
|
33203
|
+
}
|
|
33204
|
+
containLifecycleFailure(operation, fn) {
|
|
33205
|
+
try {
|
|
33206
|
+
fn();
|
|
33207
|
+
} catch (error2) {
|
|
33208
|
+
debugLogger.error(
|
|
33209
|
+
`Failed to process LangSmith ${operation} instrumentation:`,
|
|
33210
|
+
error2
|
|
33211
|
+
);
|
|
33212
|
+
}
|
|
33213
|
+
}
|
|
33214
|
+
};
|
|
33215
|
+
function ownValue(value, key) {
|
|
33216
|
+
if (!isRecord2(value)) {
|
|
33217
|
+
return void 0;
|
|
33218
|
+
}
|
|
33219
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
33220
|
+
return descriptor && "value" in descriptor ? descriptor.value : void 0;
|
|
33221
|
+
}
|
|
33222
|
+
function preferOwnValue(current, previous, key) {
|
|
33223
|
+
const currentDescriptor = isRecord2(current) ? Object.getOwnPropertyDescriptor(current, key) : void 0;
|
|
33224
|
+
if (currentDescriptor && "value" in currentDescriptor) {
|
|
33225
|
+
return currentDescriptor.value;
|
|
33226
|
+
}
|
|
33227
|
+
return ownValue(previous, key);
|
|
33228
|
+
}
|
|
33229
|
+
function mergeRuns(previous, current) {
|
|
33230
|
+
const entries = /* @__PURE__ */ new Map();
|
|
33231
|
+
for (const value of [previous, current]) {
|
|
33232
|
+
if (!isRecord2(value)) {
|
|
33233
|
+
continue;
|
|
33234
|
+
}
|
|
33235
|
+
for (const [key, descriptor] of Object.entries(
|
|
33236
|
+
Object.getOwnPropertyDescriptors(value)
|
|
33237
|
+
)) {
|
|
33238
|
+
if (descriptor.enumerable && "value" in descriptor) {
|
|
33239
|
+
entries.set(key, descriptor.value);
|
|
33240
|
+
}
|
|
33241
|
+
}
|
|
33242
|
+
}
|
|
33243
|
+
return Object.fromEntries(entries);
|
|
33244
|
+
}
|
|
33245
|
+
function isRecord2(value) {
|
|
33246
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
33247
|
+
}
|
|
33248
|
+
function stringValue2(value) {
|
|
33249
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
33250
|
+
}
|
|
33251
|
+
function timestampSeconds(value) {
|
|
33252
|
+
if (value instanceof Date) {
|
|
33253
|
+
const timestamp = value.getTime();
|
|
33254
|
+
return Number.isFinite(timestamp) ? timestamp / 1e3 : void 0;
|
|
33255
|
+
}
|
|
33256
|
+
if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
|
|
33257
|
+
return value > 1e10 ? value / 1e3 : value;
|
|
33258
|
+
}
|
|
33259
|
+
if (typeof value === "string") {
|
|
33260
|
+
const timestamp = Date.parse(value);
|
|
33261
|
+
return Number.isFinite(timestamp) ? timestamp / 1e3 : void 0;
|
|
33262
|
+
}
|
|
33263
|
+
return void 0;
|
|
33264
|
+
}
|
|
33265
|
+
function dottedOrderDepth(run2) {
|
|
33266
|
+
const dottedOrder = stringValue2(ownValue(run2, "dotted_order"));
|
|
33267
|
+
return dottedOrder ? dottedOrder.split(".").length : Number.MAX_SAFE_INTEGER;
|
|
33268
|
+
}
|
|
33269
|
+
function mapRunType(runType) {
|
|
33270
|
+
switch (runType) {
|
|
33271
|
+
case "llm":
|
|
33272
|
+
case "embedding":
|
|
33273
|
+
return "llm" /* LLM */;
|
|
33274
|
+
case "tool":
|
|
33275
|
+
case "retriever":
|
|
33276
|
+
return "tool" /* TOOL */;
|
|
33277
|
+
default:
|
|
33278
|
+
return "task" /* TASK */;
|
|
33279
|
+
}
|
|
33280
|
+
}
|
|
33281
|
+
function extractMetadata(run2, previous) {
|
|
33282
|
+
const extra = preferOwnValue(run2, previous, "extra");
|
|
33283
|
+
const rawMetadata = ownValue(extra, "metadata");
|
|
33284
|
+
if (!isRecord2(rawMetadata)) {
|
|
33285
|
+
return void 0;
|
|
33286
|
+
}
|
|
33287
|
+
const metadata = {};
|
|
33288
|
+
for (const [key, descriptor] of Object.entries(
|
|
33289
|
+
Object.getOwnPropertyDescriptors(rawMetadata)
|
|
33290
|
+
)) {
|
|
33291
|
+
if (!("value" in descriptor) || !descriptor.enumerable || BLOCKED_METADATA_KEYS.has(key) || BLOCKED_METADATA_PREFIXES.some((prefix) => key.startsWith(prefix)) || key.startsWith("ls_") && key !== "ls_provider" && key !== "ls_model_name" && !LLM_SETTING_KEYS.some((setting) => key === `ls_${setting}`)) {
|
|
33292
|
+
continue;
|
|
33293
|
+
}
|
|
33294
|
+
const normalizedKey = key === "ls_provider" ? "provider" : key === "ls_model_name" ? "model" : key.startsWith("ls_") ? key.slice(3) : key;
|
|
33295
|
+
const sanitized = sanitizeLoggedValue(descriptor.value);
|
|
33296
|
+
if (sanitized !== void 0) {
|
|
33297
|
+
metadata[normalizedKey] = sanitized;
|
|
33298
|
+
}
|
|
33299
|
+
}
|
|
33300
|
+
return Object.keys(metadata).length === 0 ? void 0 : metadata;
|
|
33301
|
+
}
|
|
33302
|
+
function extractTags(value) {
|
|
33303
|
+
if (!Array.isArray(value)) {
|
|
33304
|
+
return void 0;
|
|
33305
|
+
}
|
|
33306
|
+
const tags = value.filter(
|
|
33307
|
+
(tag) => typeof tag === "string" && tag.length > 0
|
|
33308
|
+
);
|
|
33309
|
+
return tags.length > 0 ? tags : void 0;
|
|
33310
|
+
}
|
|
33311
|
+
function extractMetrics(run2, previous) {
|
|
33312
|
+
const outputs = preferOwnValue(run2, previous, "outputs");
|
|
33313
|
+
const extra = preferOwnValue(run2, previous, "extra");
|
|
33314
|
+
const metadata = ownValue(extra, "metadata");
|
|
33315
|
+
const usage = ownValue(outputs, "usage_metadata") ?? ownValue(metadata, "usage_metadata");
|
|
33316
|
+
const metrics = {};
|
|
33317
|
+
assignFirstMetric(metrics, "prompt_tokens", usage, [
|
|
33318
|
+
"input_tokens",
|
|
33319
|
+
"prompt_tokens"
|
|
33320
|
+
]);
|
|
33321
|
+
assignFirstMetric(metrics, "completion_tokens", usage, [
|
|
33322
|
+
"output_tokens",
|
|
33323
|
+
"completion_tokens"
|
|
33324
|
+
]);
|
|
33325
|
+
assignFirstMetric(metrics, "tokens", usage, ["total_tokens", "tokens"]);
|
|
33326
|
+
const inputTokenDetails = ownValue(usage, "input_token_details");
|
|
33327
|
+
assignFirstMetric(metrics, "prompt_cached_tokens", inputTokenDetails, [
|
|
33328
|
+
"cache_read",
|
|
33329
|
+
"cached_tokens"
|
|
33330
|
+
]);
|
|
33331
|
+
if (metrics.prompt_cached_tokens === void 0) {
|
|
33332
|
+
assignFirstMetric(metrics, "prompt_cached_tokens", usage, [
|
|
33333
|
+
"cache_read_input_tokens",
|
|
33334
|
+
"prompt_cached_tokens"
|
|
33335
|
+
]);
|
|
33336
|
+
}
|
|
33337
|
+
assignFirstMetric(
|
|
33338
|
+
metrics,
|
|
33339
|
+
"prompt_cache_creation_tokens",
|
|
33340
|
+
inputTokenDetails,
|
|
33341
|
+
["cache_creation"]
|
|
33342
|
+
);
|
|
33343
|
+
if (metrics.prompt_cache_creation_tokens === void 0) {
|
|
33344
|
+
assignFirstMetric(metrics, "prompt_cache_creation_tokens", usage, [
|
|
33345
|
+
"cache_creation_input_tokens",
|
|
33346
|
+
"prompt_cache_creation_tokens"
|
|
33347
|
+
]);
|
|
33348
|
+
}
|
|
33349
|
+
if (metrics.tokens === void 0 && (metrics.prompt_tokens !== void 0 || metrics.completion_tokens !== void 0)) {
|
|
33350
|
+
metrics.tokens = (metrics.prompt_tokens ?? 0) + (metrics.completion_tokens ?? 0);
|
|
33351
|
+
}
|
|
33352
|
+
const startTime = timestampSeconds(
|
|
33353
|
+
preferOwnValue(run2, previous, "start_time")
|
|
33354
|
+
);
|
|
33355
|
+
const events = preferOwnValue(run2, previous, "events");
|
|
33356
|
+
if (startTime !== void 0 && Array.isArray(events)) {
|
|
33357
|
+
for (const event of events) {
|
|
33358
|
+
if (ownValue(event, "name") !== "new_token") {
|
|
33359
|
+
continue;
|
|
33360
|
+
}
|
|
33361
|
+
const eventTime2 = timestampSeconds(ownValue(event, "time"));
|
|
33362
|
+
if (eventTime2 !== void 0 && eventTime2 >= startTime) {
|
|
33363
|
+
metrics.time_to_first_token = eventTime2 - startTime;
|
|
33364
|
+
}
|
|
33365
|
+
break;
|
|
33366
|
+
}
|
|
33367
|
+
}
|
|
33368
|
+
return metrics;
|
|
33369
|
+
}
|
|
33370
|
+
function assignFirstMetric(metrics, target, source, keys) {
|
|
33371
|
+
for (const key of keys) {
|
|
33372
|
+
const value = ownValue(source, key);
|
|
33373
|
+
if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
|
|
33374
|
+
metrics[target] = value;
|
|
33375
|
+
return;
|
|
33376
|
+
}
|
|
33377
|
+
}
|
|
33378
|
+
}
|
|
33379
|
+
function errorMessage(value) {
|
|
33380
|
+
if (typeof value === "string") {
|
|
33381
|
+
return value;
|
|
33382
|
+
}
|
|
33383
|
+
if (value instanceof Error) {
|
|
33384
|
+
return value.message;
|
|
33385
|
+
}
|
|
33386
|
+
return void 0;
|
|
33387
|
+
}
|
|
33388
|
+
function sanitizeLoggedValue(value, seen = /* @__PURE__ */ new WeakSet(), depth = 0) {
|
|
33389
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") {
|
|
33390
|
+
return value;
|
|
33391
|
+
}
|
|
33392
|
+
if (typeof value === "number") {
|
|
33393
|
+
return Number.isFinite(value) ? value : void 0;
|
|
33394
|
+
}
|
|
33395
|
+
if (value instanceof Date) {
|
|
33396
|
+
return Number.isFinite(value.getTime()) ? value.toISOString() : void 0;
|
|
33397
|
+
}
|
|
33398
|
+
if (typeof value !== "object" || depth >= 20) {
|
|
33399
|
+
return void 0;
|
|
33400
|
+
}
|
|
33401
|
+
if (seen.has(value)) {
|
|
33402
|
+
return "[Circular]";
|
|
33403
|
+
}
|
|
33404
|
+
seen.add(value);
|
|
33405
|
+
if (Array.isArray(value)) {
|
|
33406
|
+
return value.map((item) => sanitizeLoggedValue(item, seen, depth + 1));
|
|
33407
|
+
}
|
|
33408
|
+
const entries = [];
|
|
33409
|
+
for (const [key, descriptor] of Object.entries(
|
|
33410
|
+
Object.getOwnPropertyDescriptors(value)
|
|
33411
|
+
)) {
|
|
33412
|
+
if (!descriptor.enumerable || !("value" in descriptor) || BLOCKED_METADATA_KEYS.has(key)) {
|
|
33413
|
+
continue;
|
|
33414
|
+
}
|
|
33415
|
+
entries.push([key, sanitizeLoggedValue(descriptor.value, seen, depth + 1)]);
|
|
33416
|
+
}
|
|
33417
|
+
return Object.fromEntries(entries);
|
|
33418
|
+
}
|
|
33419
|
+
|
|
32858
33420
|
// src/instrumentation/plugins/pi-coding-agent-channels.ts
|
|
32859
33421
|
var piCodingAgentChannels = defineChannels(
|
|
32860
33422
|
"@earendil-works/pi-coding-agent",
|
|
@@ -33234,11 +33796,11 @@ function patchAssistantMessageStream(stream, promptState, llmState) {
|
|
|
33234
33796
|
function recordPiAssistantMessageEvent(promptState, llmState, event) {
|
|
33235
33797
|
recordFirstTokenMetric(llmState, event);
|
|
33236
33798
|
const message = "message" in event ? event.message : void 0;
|
|
33237
|
-
const
|
|
33799
|
+
const errorMessage2 = "error" in event ? event.error : void 0;
|
|
33238
33800
|
if (event.type === "done" && isPiAssistantMessage(message)) {
|
|
33239
33801
|
finishPiLlmSpan(promptState, llmState, message);
|
|
33240
|
-
} else if (event.type === "error" && isPiAssistantMessage(
|
|
33241
|
-
finishPiLlmSpan(promptState, llmState,
|
|
33802
|
+
} else if (event.type === "error" && isPiAssistantMessage(errorMessage2)) {
|
|
33803
|
+
finishPiLlmSpan(promptState, llmState, errorMessage2);
|
|
33242
33804
|
}
|
|
33243
33805
|
}
|
|
33244
33806
|
function recordFirstTokenMetric(state, event) {
|
|
@@ -33756,6 +34318,7 @@ var strandsAgentSDKChannels = defineChannels("@strands-agents/sdk", {
|
|
|
33756
34318
|
});
|
|
33757
34319
|
|
|
33758
34320
|
// src/instrumentation/plugins/strands-agent-sdk-plugin.ts
|
|
34321
|
+
var MAX_STRANDS_STRING_ATTACHMENT_CACHE_ENTRIES = 32;
|
|
33759
34322
|
var StrandsAgentSDKPlugin = class extends BasePlugin {
|
|
33760
34323
|
activeChildParents = /* @__PURE__ */ new WeakMap();
|
|
33761
34324
|
onEnable() {
|
|
@@ -33900,11 +34463,16 @@ function startAgentStream(event, activeChildParents) {
|
|
|
33900
34463
|
...event.moduleVersion ? { "strands_agent_sdk.version": event.moduleVersion } : {}
|
|
33901
34464
|
};
|
|
33902
34465
|
const parentSpan = agent ? getOnlyChildParent(activeChildParents, agent) : void 0;
|
|
34466
|
+
const attachmentCache = createStrandsAttachmentCache();
|
|
34467
|
+
const input = processStrandsInputAttachments(
|
|
34468
|
+
event.arguments[0],
|
|
34469
|
+
attachmentCache
|
|
34470
|
+
);
|
|
33903
34471
|
const span = parentSpan ? withCurrent(
|
|
33904
34472
|
parentSpan,
|
|
33905
34473
|
() => startSpan({
|
|
33906
34474
|
event: {
|
|
33907
|
-
input
|
|
34475
|
+
input,
|
|
33908
34476
|
metadata
|
|
33909
34477
|
},
|
|
33910
34478
|
name: formatAgentSpanName(agent),
|
|
@@ -33912,7 +34480,7 @@ function startAgentStream(event, activeChildParents) {
|
|
|
33912
34480
|
})
|
|
33913
34481
|
) : startSpan({
|
|
33914
34482
|
event: {
|
|
33915
|
-
input
|
|
34483
|
+
input,
|
|
33916
34484
|
metadata
|
|
33917
34485
|
},
|
|
33918
34486
|
name: formatAgentSpanName(agent),
|
|
@@ -33920,6 +34488,7 @@ function startAgentStream(event, activeChildParents) {
|
|
|
33920
34488
|
});
|
|
33921
34489
|
return {
|
|
33922
34490
|
activeTools: /* @__PURE__ */ new Map(),
|
|
34491
|
+
attachmentCache,
|
|
33923
34492
|
finalized: false,
|
|
33924
34493
|
metadata,
|
|
33925
34494
|
span,
|
|
@@ -33935,11 +34504,12 @@ function startMultiAgentStream(event, operation, activeChildParents) {
|
|
|
33935
34504
|
...event.moduleVersion ? { "strands_agent_sdk.version": event.moduleVersion } : {}
|
|
33936
34505
|
};
|
|
33937
34506
|
const parentSpan = orchestrator ? getOnlyChildParent(activeChildParents, orchestrator) : void 0;
|
|
34507
|
+
const input = processStrandsInputAttachments(event.arguments[0]);
|
|
33938
34508
|
const span = parentSpan ? withCurrent(
|
|
33939
34509
|
parentSpan,
|
|
33940
34510
|
() => startSpan({
|
|
33941
34511
|
event: {
|
|
33942
|
-
input
|
|
34512
|
+
input,
|
|
33943
34513
|
metadata
|
|
33944
34514
|
},
|
|
33945
34515
|
name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
|
|
@@ -33947,7 +34517,7 @@ function startMultiAgentStream(event, operation, activeChildParents) {
|
|
|
33947
34517
|
})
|
|
33948
34518
|
) : startSpan({
|
|
33949
34519
|
event: {
|
|
33950
|
-
input
|
|
34520
|
+
input,
|
|
33951
34521
|
metadata
|
|
33952
34522
|
},
|
|
33953
34523
|
name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
|
|
@@ -34056,7 +34626,10 @@ function startModelSpan(state, event) {
|
|
|
34056
34626
|
state.span,
|
|
34057
34627
|
() => startSpan({
|
|
34058
34628
|
event: {
|
|
34059
|
-
input: Array.isArray(event.agent?.messages) ?
|
|
34629
|
+
input: Array.isArray(event.agent?.messages) ? processStrandsInputAttachments(
|
|
34630
|
+
event.agent.messages,
|
|
34631
|
+
state.attachmentCache
|
|
34632
|
+
) : void 0,
|
|
34060
34633
|
metadata
|
|
34061
34634
|
},
|
|
34062
34635
|
name: formatModelSpanName(model),
|
|
@@ -34270,6 +34843,7 @@ function finalizeAgentStream(state, error2, output) {
|
|
|
34270
34843
|
...output !== void 0 ? { output } : {}
|
|
34271
34844
|
});
|
|
34272
34845
|
state.span.end();
|
|
34846
|
+
state.attachmentCache.strings.clear();
|
|
34273
34847
|
}
|
|
34274
34848
|
function finalizeMultiAgentStream(state, activeChildParents, error2, output) {
|
|
34275
34849
|
if (state.finalized) {
|
|
@@ -34416,6 +34990,166 @@ function extractNodeResultOutput(result) {
|
|
|
34416
34990
|
}
|
|
34417
34991
|
return result;
|
|
34418
34992
|
}
|
|
34993
|
+
var STRANDS_MEDIA_TYPES = {
|
|
34994
|
+
png: "image/png",
|
|
34995
|
+
jpg: "image/jpeg",
|
|
34996
|
+
jpeg: "image/jpeg",
|
|
34997
|
+
gif: "image/gif",
|
|
34998
|
+
webp: "image/webp",
|
|
34999
|
+
mkv: "video/x-matroska",
|
|
35000
|
+
mov: "video/quicktime",
|
|
35001
|
+
mp4: "video/mp4",
|
|
35002
|
+
webm: "video/webm",
|
|
35003
|
+
flv: "video/x-flv",
|
|
35004
|
+
mpeg: "video/mpeg",
|
|
35005
|
+
mpg: "video/mpeg",
|
|
35006
|
+
wmv: "video/x-ms-wmv",
|
|
35007
|
+
"3gp": "video/3gpp",
|
|
35008
|
+
pdf: "application/pdf",
|
|
35009
|
+
csv: "text/csv",
|
|
35010
|
+
doc: "application/msword",
|
|
35011
|
+
docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
35012
|
+
xls: "application/vnd.ms-excel",
|
|
35013
|
+
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
35014
|
+
html: "text/html",
|
|
35015
|
+
txt: "text/plain",
|
|
35016
|
+
md: "text/markdown",
|
|
35017
|
+
json: "application/json",
|
|
35018
|
+
xml: "application/xml"
|
|
35019
|
+
};
|
|
35020
|
+
function createStrandsAttachmentCache() {
|
|
35021
|
+
return {
|
|
35022
|
+
objects: /* @__PURE__ */ new WeakMap(),
|
|
35023
|
+
strings: new LRUCache({
|
|
35024
|
+
max: MAX_STRANDS_STRING_ATTACHMENT_CACHE_ENTRIES
|
|
35025
|
+
})
|
|
35026
|
+
};
|
|
35027
|
+
}
|
|
35028
|
+
function processStrandsInputAttachments(input, cache = createStrandsAttachmentCache()) {
|
|
35029
|
+
try {
|
|
35030
|
+
return processStrandsInputNode(input, cache);
|
|
35031
|
+
} catch (error2) {
|
|
35032
|
+
logInstrumentationError5("Strands Agent SDK input attachments", error2);
|
|
35033
|
+
return input;
|
|
35034
|
+
}
|
|
35035
|
+
}
|
|
35036
|
+
function processStrandsInputNode(value, cache) {
|
|
35037
|
+
if (value instanceof BaseAttachment) {
|
|
35038
|
+
return value;
|
|
35039
|
+
}
|
|
35040
|
+
if (Array.isArray(value)) {
|
|
35041
|
+
return value.map((child) => processStrandsInputNode(child, cache));
|
|
35042
|
+
}
|
|
35043
|
+
if (!isObject(value)) {
|
|
35044
|
+
return value;
|
|
35045
|
+
}
|
|
35046
|
+
const directMedia = processDirectStrandsMediaBlock(value, cache);
|
|
35047
|
+
if (directMedia !== void 0) {
|
|
35048
|
+
return directMedia;
|
|
35049
|
+
}
|
|
35050
|
+
const wrappedMedia = processWrappedStrandsMediaBlock(value, cache);
|
|
35051
|
+
if (wrappedMedia !== void 0) {
|
|
35052
|
+
return wrappedMedia;
|
|
35053
|
+
}
|
|
35054
|
+
if (value.type === "message" && Array.isArray(value.content)) {
|
|
35055
|
+
return {
|
|
35056
|
+
role: value.role,
|
|
35057
|
+
content: value.content.map(
|
|
35058
|
+
(child) => processStrandsInputNode(child, cache)
|
|
35059
|
+
),
|
|
35060
|
+
...value.metadata !== void 0 ? { metadata: value.metadata } : {}
|
|
35061
|
+
};
|
|
35062
|
+
}
|
|
35063
|
+
if (typeof value.toJSON === "function") {
|
|
35064
|
+
return processStrandsInputNode(value.toJSON(), cache);
|
|
35065
|
+
}
|
|
35066
|
+
return Object.fromEntries(
|
|
35067
|
+
Object.entries(value).map(([key, child]) => [
|
|
35068
|
+
key,
|
|
35069
|
+
processStrandsInputNode(child, cache)
|
|
35070
|
+
])
|
|
35071
|
+
);
|
|
35072
|
+
}
|
|
35073
|
+
function processDirectStrandsMediaBlock(block, cache) {
|
|
35074
|
+
if (!isStrandsMediaBlock(block)) {
|
|
35075
|
+
return void 0;
|
|
35076
|
+
}
|
|
35077
|
+
const mediaKey = block.type === "imageBlock" ? "image" : block.type === "videoBlock" ? "video" : "document";
|
|
35078
|
+
return createStrandsMediaAttachment(mediaKey, block, cache);
|
|
35079
|
+
}
|
|
35080
|
+
function isStrandsMediaBlock(block) {
|
|
35081
|
+
return (block.type === "imageBlock" || block.type === "videoBlock" || block.type === "documentBlock") && typeof block.format === "string" && isObject(block.source);
|
|
35082
|
+
}
|
|
35083
|
+
function processWrappedStrandsMediaBlock(block, cache) {
|
|
35084
|
+
for (const mediaKey of ["image", "video", "document"]) {
|
|
35085
|
+
const media = block[mediaKey];
|
|
35086
|
+
if (!Object.hasOwn(block, mediaKey) || !isObject(media)) {
|
|
35087
|
+
continue;
|
|
35088
|
+
}
|
|
35089
|
+
const processed = createStrandsMediaAttachment(mediaKey, media, cache);
|
|
35090
|
+
if (processed !== void 0) {
|
|
35091
|
+
return processed;
|
|
35092
|
+
}
|
|
35093
|
+
}
|
|
35094
|
+
return void 0;
|
|
35095
|
+
}
|
|
35096
|
+
function createStrandsMediaAttachment(mediaKey, media, cache) {
|
|
35097
|
+
const format = media.format;
|
|
35098
|
+
const source = media.source;
|
|
35099
|
+
if (typeof format !== "string" || !isObject(source) || !Object.hasOwn(source, "bytes")) {
|
|
35100
|
+
return void 0;
|
|
35101
|
+
}
|
|
35102
|
+
const contentType = STRANDS_MEDIA_TYPES[format.toLowerCase()];
|
|
35103
|
+
if (!contentType) {
|
|
35104
|
+
return void 0;
|
|
35105
|
+
}
|
|
35106
|
+
const filename = mediaKey === "document" && typeof media.name === "string" && media.name.length > 0 ? media.name : `${mediaKey}.${format.toLowerCase()}`;
|
|
35107
|
+
const attachment = getOrCreateStrandsAttachment(
|
|
35108
|
+
source.bytes,
|
|
35109
|
+
filename,
|
|
35110
|
+
contentType,
|
|
35111
|
+
cache
|
|
35112
|
+
);
|
|
35113
|
+
if (!attachment) {
|
|
35114
|
+
return void 0;
|
|
35115
|
+
}
|
|
35116
|
+
const { type: _type, ...serializedMedia } = media;
|
|
35117
|
+
const { type: _sourceType, ...serializedSource } = source;
|
|
35118
|
+
return {
|
|
35119
|
+
[mediaKey]: {
|
|
35120
|
+
...serializedMedia,
|
|
35121
|
+
source: {
|
|
35122
|
+
...serializedSource,
|
|
35123
|
+
bytes: attachment
|
|
35124
|
+
}
|
|
35125
|
+
}
|
|
35126
|
+
};
|
|
35127
|
+
}
|
|
35128
|
+
function getOrCreateStrandsAttachment(data, filename, contentType, cache) {
|
|
35129
|
+
const key = `${contentType}\0${filename}`;
|
|
35130
|
+
const attachments = typeof data === "string" ? cache.strings.get(data) : isObject(data) ? cache.objects.get(data) : void 0;
|
|
35131
|
+
const cached = attachments?.get(key);
|
|
35132
|
+
if (cached) {
|
|
35133
|
+
return cached;
|
|
35134
|
+
}
|
|
35135
|
+
const blob = convertDataToBlob(data, contentType);
|
|
35136
|
+
if (!blob) {
|
|
35137
|
+
return void 0;
|
|
35138
|
+
}
|
|
35139
|
+
const attachment = new Attachment({
|
|
35140
|
+
data: blob,
|
|
35141
|
+
filename,
|
|
35142
|
+
contentType
|
|
35143
|
+
});
|
|
35144
|
+
const updatedAttachments = attachments ?? /* @__PURE__ */ new Map();
|
|
35145
|
+
updatedAttachments.set(key, attachment);
|
|
35146
|
+
if (typeof data === "string") {
|
|
35147
|
+
cache.strings.set(data, updatedAttachments);
|
|
35148
|
+
} else if (isObject(data)) {
|
|
35149
|
+
cache.objects.set(data, updatedAttachments);
|
|
35150
|
+
}
|
|
35151
|
+
return attachment;
|
|
35152
|
+
}
|
|
34419
35153
|
function normalizeContentBlocks(blocks) {
|
|
34420
35154
|
const text = blocks.map((block) => typeof block.text === "string" ? block.text : void 0).filter((part) => Boolean(part)).join("");
|
|
34421
35155
|
return text.length > 0 ? text : blocks;
|
|
@@ -34545,6 +35279,7 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
34545
35279
|
gitHubCopilotPlugin = null;
|
|
34546
35280
|
fluePlugin = null;
|
|
34547
35281
|
langChainPlugin = null;
|
|
35282
|
+
langSmithPlugin = null;
|
|
34548
35283
|
piCodingAgentPlugin = null;
|
|
34549
35284
|
strandsAgentSDKPlugin = null;
|
|
34550
35285
|
constructor(config3 = {}) {
|
|
@@ -34641,6 +35376,12 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
34641
35376
|
this.langChainPlugin = new LangChainPlugin();
|
|
34642
35377
|
this.langChainPlugin.enable();
|
|
34643
35378
|
}
|
|
35379
|
+
if (integrations.langsmith !== false) {
|
|
35380
|
+
this.langSmithPlugin = new LangSmithPlugin({
|
|
35381
|
+
skipLangChainRuns: integrations.langchain !== false
|
|
35382
|
+
});
|
|
35383
|
+
this.langSmithPlugin.enable();
|
|
35384
|
+
}
|
|
34644
35385
|
}
|
|
34645
35386
|
onDisable() {
|
|
34646
35387
|
if (this.openaiPlugin) {
|
|
@@ -34731,6 +35472,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
34731
35472
|
this.langChainPlugin.disable();
|
|
34732
35473
|
this.langChainPlugin = null;
|
|
34733
35474
|
}
|
|
35475
|
+
if (this.langSmithPlugin) {
|
|
35476
|
+
this.langSmithPlugin.disable();
|
|
35477
|
+
this.langSmithPlugin = null;
|
|
35478
|
+
}
|
|
34734
35479
|
}
|
|
34735
35480
|
};
|
|
34736
35481
|
|
|
@@ -34795,7 +35540,8 @@ var envIntegrationAliases = {
|
|
|
34795
35540
|
langchain: "langchain",
|
|
34796
35541
|
"langchain-js": "langchain",
|
|
34797
35542
|
"@langchain": "langchain",
|
|
34798
|
-
langgraph: "langgraph"
|
|
35543
|
+
langgraph: "langgraph",
|
|
35544
|
+
langsmith: "langsmith"
|
|
34799
35545
|
};
|
|
34800
35546
|
function getDefaultInstrumentationIntegrations() {
|
|
34801
35547
|
return {
|
|
@@ -34826,6 +35572,7 @@ function getDefaultInstrumentationIntegrations() {
|
|
|
34826
35572
|
gitHubCopilot: true,
|
|
34827
35573
|
langchain: true,
|
|
34828
35574
|
langgraph: true,
|
|
35575
|
+
langsmith: true,
|
|
34829
35576
|
piCodingAgent: true,
|
|
34830
35577
|
strandsAgentSDK: true
|
|
34831
35578
|
};
|
|
@@ -35066,6 +35813,15 @@ function modelMetrics(attributes) {
|
|
|
35066
35813
|
}
|
|
35067
35814
|
return Object.keys(out).length > 0 ? out : void 0;
|
|
35068
35815
|
}
|
|
35816
|
+
function timeToFirstTokenSeconds(attributes, spanStartSeconds) {
|
|
35817
|
+
if (!isObject(attributes)) return void 0;
|
|
35818
|
+
if (spanStartSeconds === void 0) return void 0;
|
|
35819
|
+
const raw = attributes.completionStartTime;
|
|
35820
|
+
const completionStart = raw instanceof Date || typeof raw === "string" || typeof raw === "number" ? epochSeconds(raw) : void 0;
|
|
35821
|
+
if (completionStart === void 0) return void 0;
|
|
35822
|
+
const ttft = completionStart - spanStartSeconds;
|
|
35823
|
+
return Number.isFinite(ttft) && ttft >= 0 ? ttft : void 0;
|
|
35824
|
+
}
|
|
35069
35825
|
function buildMetadata(exported) {
|
|
35070
35826
|
const out = {};
|
|
35071
35827
|
if (exported.entityId !== void 0) out.entity_id = exported.entityId;
|
|
@@ -35135,7 +35891,13 @@ var BraintrustObservabilityExporter = class {
|
|
|
35135
35891
|
const args = {
|
|
35136
35892
|
name: exported.name,
|
|
35137
35893
|
spanAttributes: { type: spanTypeFor(exported.type) },
|
|
35138
|
-
startTime: epochSeconds(exported.startTime)
|
|
35894
|
+
startTime: epochSeconds(exported.startTime),
|
|
35895
|
+
// Use the Mastra span id as the Braintrust row id so that
|
|
35896
|
+
// `logFeedback({ id: <mastra span id> })` (and Mastra's score events)
|
|
35897
|
+
// attach to the right row. Without this, `SpanImpl` auto-generates a
|
|
35898
|
+
// row id (`this._id = eventId ?? idGenerator.getSpanId()`) that no
|
|
35899
|
+
// external caller could know.
|
|
35900
|
+
event: { id: exported.id }
|
|
35139
35901
|
};
|
|
35140
35902
|
const parentRecord = exported.parentSpanId ? this.spans.get(exported.parentSpanId) : void 0;
|
|
35141
35903
|
if (!this.capturedParent) {
|
|
@@ -35184,8 +35946,15 @@ var BraintrustObservabilityExporter = class {
|
|
|
35184
35946
|
event.metadata = metadata;
|
|
35185
35947
|
}
|
|
35186
35948
|
const metrics = modelMetrics(exported.attributes);
|
|
35187
|
-
|
|
35188
|
-
|
|
35949
|
+
const ttft = timeToFirstTokenSeconds(
|
|
35950
|
+
exported.attributes,
|
|
35951
|
+
epochSeconds(exported.startTime)
|
|
35952
|
+
);
|
|
35953
|
+
if (metrics || ttft !== void 0) {
|
|
35954
|
+
event.metrics = {
|
|
35955
|
+
...metrics ?? {},
|
|
35956
|
+
...ttft !== void 0 ? { time_to_first_token: ttft } : {}
|
|
35957
|
+
};
|
|
35189
35958
|
}
|
|
35190
35959
|
if (Object.keys(event).length > 0) {
|
|
35191
35960
|
record.span.log(event);
|
|
@@ -36884,8 +37653,8 @@ function makeCheckAuthorized(allowedOrgName) {
|
|
|
36884
37653
|
return next((0, import_http_errors.default)(400, "Missing x-bt-org-name header"));
|
|
36885
37654
|
}
|
|
36886
37655
|
if (allowedOrgName && allowedOrgName !== orgName) {
|
|
36887
|
-
const
|
|
36888
|
-
return next((0, import_http_errors.default)(403,
|
|
37656
|
+
const errorMessage2 = `Org '${orgName}' is not allowed. Only org '${allowedOrgName}' is allowed.`;
|
|
37657
|
+
return next((0, import_http_errors.default)(403, errorMessage2));
|
|
36889
37658
|
}
|
|
36890
37659
|
const state = await cachedLogin({
|
|
36891
37660
|
apiKey: req.ctx?.token,
|