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/dev/dist/index.mjs
CHANGED
|
@@ -2510,19 +2510,30 @@ var CallEvent = z6.union([
|
|
|
2510
2510
|
var ChatCompletionContentPartTextWithTitle = z6.object({
|
|
2511
2511
|
text: z6.string().default(""),
|
|
2512
2512
|
type: z6.literal("text"),
|
|
2513
|
-
cache_control: z6.object({
|
|
2513
|
+
cache_control: z6.object({
|
|
2514
|
+
type: z6.literal("ephemeral"),
|
|
2515
|
+
ttl: z6.enum(["5m", "1h"]).optional()
|
|
2516
|
+
}).optional()
|
|
2514
2517
|
});
|
|
2515
2518
|
var ChatCompletionContentPartImageWithTitle = z6.object({
|
|
2516
2519
|
image_url: z6.object({
|
|
2517
2520
|
url: z6.string(),
|
|
2518
2521
|
detail: z6.union([z6.literal("auto"), z6.literal("low"), z6.literal("high")]).optional()
|
|
2519
2522
|
}),
|
|
2520
|
-
type: z6.literal("image_url")
|
|
2523
|
+
type: z6.literal("image_url"),
|
|
2524
|
+
cache_control: z6.object({
|
|
2525
|
+
type: z6.literal("ephemeral"),
|
|
2526
|
+
ttl: z6.enum(["5m", "1h"]).optional()
|
|
2527
|
+
}).optional()
|
|
2521
2528
|
});
|
|
2522
2529
|
var ChatCompletionContentPartFileFile = z6.object({ file_data: z6.string(), filename: z6.string(), file_id: z6.string() }).partial();
|
|
2523
2530
|
var ChatCompletionContentPartFileWithTitle = z6.object({
|
|
2524
2531
|
file: ChatCompletionContentPartFileFile,
|
|
2525
|
-
type: z6.literal("file")
|
|
2532
|
+
type: z6.literal("file"),
|
|
2533
|
+
cache_control: z6.object({
|
|
2534
|
+
type: z6.literal("ephemeral"),
|
|
2535
|
+
ttl: z6.enum(["5m", "1h"]).optional()
|
|
2536
|
+
}).optional()
|
|
2526
2537
|
});
|
|
2527
2538
|
var ChatCompletionContentPart = z6.union([
|
|
2528
2539
|
ChatCompletionContentPartTextWithTitle,
|
|
@@ -2532,7 +2543,10 @@ var ChatCompletionContentPart = z6.union([
|
|
|
2532
2543
|
var ChatCompletionContentPartText = z6.object({
|
|
2533
2544
|
text: z6.string().default(""),
|
|
2534
2545
|
type: z6.literal("text"),
|
|
2535
|
-
cache_control: z6.object({
|
|
2546
|
+
cache_control: z6.object({
|
|
2547
|
+
type: z6.literal("ephemeral"),
|
|
2548
|
+
ttl: z6.enum(["5m", "1h"]).optional()
|
|
2549
|
+
}).optional()
|
|
2536
2550
|
});
|
|
2537
2551
|
var ChatCompletionMessageToolCall = z6.object({
|
|
2538
2552
|
id: z6.string(),
|
|
@@ -4569,7 +4583,7 @@ var DiskCache = class {
|
|
|
4569
4583
|
}
|
|
4570
4584
|
};
|
|
4571
4585
|
|
|
4572
|
-
// src/
|
|
4586
|
+
// src/lru-cache.ts
|
|
4573
4587
|
var LRUCache = class {
|
|
4574
4588
|
cache;
|
|
4575
4589
|
maxSize;
|
|
@@ -4585,13 +4599,23 @@ var LRUCache = class {
|
|
|
4585
4599
|
* @returns The cached value if found, undefined otherwise.
|
|
4586
4600
|
*/
|
|
4587
4601
|
get(key) {
|
|
4588
|
-
const
|
|
4589
|
-
if (
|
|
4602
|
+
const entry = this.cache.get(key);
|
|
4603
|
+
if (entry === void 0) {
|
|
4590
4604
|
return void 0;
|
|
4591
4605
|
}
|
|
4592
4606
|
this.cache.delete(key);
|
|
4593
|
-
this.cache.set(key,
|
|
4594
|
-
return value;
|
|
4607
|
+
this.cache.set(key, entry);
|
|
4608
|
+
return entry.value;
|
|
4609
|
+
}
|
|
4610
|
+
/**
|
|
4611
|
+
* Checks whether a key exists and marks it as most recently used.
|
|
4612
|
+
*/
|
|
4613
|
+
has(key) {
|
|
4614
|
+
if (!this.cache.has(key)) {
|
|
4615
|
+
return false;
|
|
4616
|
+
}
|
|
4617
|
+
this.get(key);
|
|
4618
|
+
return true;
|
|
4595
4619
|
}
|
|
4596
4620
|
/**
|
|
4597
4621
|
* Stores a value in the cache.
|
|
@@ -4608,7 +4632,38 @@ var LRUCache = class {
|
|
|
4608
4632
|
const first = this.cache.keys().next().value;
|
|
4609
4633
|
this.cache.delete(first);
|
|
4610
4634
|
}
|
|
4611
|
-
this.cache.set(key, value);
|
|
4635
|
+
this.cache.set(key, { value });
|
|
4636
|
+
}
|
|
4637
|
+
/**
|
|
4638
|
+
* Removes an item from the cache.
|
|
4639
|
+
*/
|
|
4640
|
+
delete(key) {
|
|
4641
|
+
return this.cache.delete(key);
|
|
4642
|
+
}
|
|
4643
|
+
/**
|
|
4644
|
+
* Iterates over cache entries from least to most recently used.
|
|
4645
|
+
*/
|
|
4646
|
+
*entries() {
|
|
4647
|
+
for (const [key, entry] of this.cache) {
|
|
4648
|
+
yield [key, entry.value];
|
|
4649
|
+
}
|
|
4650
|
+
}
|
|
4651
|
+
/**
|
|
4652
|
+
* Iterates over cache keys from least to most recently used.
|
|
4653
|
+
*/
|
|
4654
|
+
keys() {
|
|
4655
|
+
return this.cache.keys();
|
|
4656
|
+
}
|
|
4657
|
+
/**
|
|
4658
|
+
* Iterates over cache values from least to most recently used.
|
|
4659
|
+
*/
|
|
4660
|
+
*values() {
|
|
4661
|
+
for (const entry of this.cache.values()) {
|
|
4662
|
+
yield entry.value;
|
|
4663
|
+
}
|
|
4664
|
+
}
|
|
4665
|
+
[Symbol.iterator]() {
|
|
4666
|
+
return this.entries();
|
|
4612
4667
|
}
|
|
4613
4668
|
/**
|
|
4614
4669
|
* Removes all items from the cache.
|
|
@@ -5166,6 +5221,9 @@ function applyMaskingToField(maskingFunction, data, fieldName) {
|
|
|
5166
5221
|
return `ERROR: Failed to mask field '${fieldName}' - ${errorType}`;
|
|
5167
5222
|
}
|
|
5168
5223
|
}
|
|
5224
|
+
var INITIAL_SPAN_WRITE_AS_MERGE = /* @__PURE__ */ Symbol(
|
|
5225
|
+
"braintrust.initial-span-write-as-merge"
|
|
5226
|
+
);
|
|
5169
5227
|
var BRAINTRUST_CURRENT_SPAN_STORE = /* @__PURE__ */ Symbol.for(
|
|
5170
5228
|
"braintrust.currentSpanStore"
|
|
5171
5229
|
);
|
|
@@ -5735,25 +5793,46 @@ var HTTPConnection = class _HTTPConnection {
|
|
|
5735
5793
|
})
|
|
5736
5794
|
);
|
|
5737
5795
|
}
|
|
5738
|
-
async post(path2, params, config) {
|
|
5796
|
+
async post(path2, params, config, retries = 0) {
|
|
5739
5797
|
const { headers, ...rest } = config || {};
|
|
5740
5798
|
const this_fetch = this.fetch;
|
|
5741
5799
|
const this_base_url = this.base_url;
|
|
5742
5800
|
const this_headers = this.headers;
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
|
|
5746
|
-
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
|
|
5755
|
-
|
|
5756
|
-
|
|
5801
|
+
const tries = retries + 1;
|
|
5802
|
+
for (let i = 0; i < tries; i++) {
|
|
5803
|
+
try {
|
|
5804
|
+
return await checkResponse(
|
|
5805
|
+
await this_fetch(_urljoin(this_base_url, path2), {
|
|
5806
|
+
method: "POST",
|
|
5807
|
+
headers: {
|
|
5808
|
+
Accept: "application/json",
|
|
5809
|
+
"Content-Type": "application/json",
|
|
5810
|
+
...this_headers,
|
|
5811
|
+
...headers
|
|
5812
|
+
},
|
|
5813
|
+
body: typeof params === "string" ? params : params ? JSON.stringify(params) : void 0,
|
|
5814
|
+
keepalive: true,
|
|
5815
|
+
...rest
|
|
5816
|
+
})
|
|
5817
|
+
);
|
|
5818
|
+
} catch (error) {
|
|
5819
|
+
if (config?.signal?.aborted) {
|
|
5820
|
+
throw getAbortReason(config.signal);
|
|
5821
|
+
}
|
|
5822
|
+
if (i === tries - 1 || !isRetryableHTTPError(error)) {
|
|
5823
|
+
throw error;
|
|
5824
|
+
}
|
|
5825
|
+
debugLogger.debug(
|
|
5826
|
+
`Retrying API request ${path2} after ${formatHTTPError(error)}`
|
|
5827
|
+
);
|
|
5828
|
+
const sleepTimeMs = HTTP_RETRY_BASE_SLEEP_TIME_S * 1e3 * 2 ** i + Math.random() * HTTP_RETRY_JITTER_MS;
|
|
5829
|
+
debugLogger.info(
|
|
5830
|
+
`Sleeping for ${sleepTimeMs}ms before retrying API request`
|
|
5831
|
+
);
|
|
5832
|
+
await waitForRetry(sleepTimeMs, config?.signal);
|
|
5833
|
+
}
|
|
5834
|
+
}
|
|
5835
|
+
throw new Error("Unexpected retry state");
|
|
5757
5836
|
}
|
|
5758
5837
|
async get_json(object_type, args = void 0, retries = 0) {
|
|
5759
5838
|
const tries = retries + 1;
|
|
@@ -6653,6 +6732,45 @@ function now() {
|
|
|
6653
6732
|
var DEFAULT_FLUSH_BACKPRESSURE_BYTES = 10 * 1024 * 1024;
|
|
6654
6733
|
var BACKGROUND_LOGGER_BASE_SLEEP_TIME_S = 1;
|
|
6655
6734
|
var HTTP_RETRY_BASE_SLEEP_TIME_S = 1;
|
|
6735
|
+
var HTTP_RETRY_JITTER_MS = 200;
|
|
6736
|
+
var BTQL_HTTP_RETRIES = 3;
|
|
6737
|
+
var RETRYABLE_HTTP_STATUS_CODES = /* @__PURE__ */ new Set([500, 502, 503, 504]);
|
|
6738
|
+
function isRetryableHTTPError(error) {
|
|
6739
|
+
return !(error instanceof FailedHTTPResponse) || RETRYABLE_HTTP_STATUS_CODES.has(error.status);
|
|
6740
|
+
}
|
|
6741
|
+
function formatHTTPError(error) {
|
|
6742
|
+
if (error instanceof FailedHTTPResponse) {
|
|
6743
|
+
return `${error.status} ${error.text}`;
|
|
6744
|
+
}
|
|
6745
|
+
return error instanceof Error ? error.message : String(error);
|
|
6746
|
+
}
|
|
6747
|
+
function getAbortReason(signal) {
|
|
6748
|
+
return signal.reason ?? new Error("Request aborted");
|
|
6749
|
+
}
|
|
6750
|
+
async function waitForRetry(delayMs, signal) {
|
|
6751
|
+
if (!signal) {
|
|
6752
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
6753
|
+
return;
|
|
6754
|
+
}
|
|
6755
|
+
if (signal.aborted) {
|
|
6756
|
+
throw getAbortReason(signal);
|
|
6757
|
+
}
|
|
6758
|
+
await new Promise((resolve, reject2) => {
|
|
6759
|
+
const onAbort = () => {
|
|
6760
|
+
clearTimeout(timeout);
|
|
6761
|
+
signal.removeEventListener("abort", onAbort);
|
|
6762
|
+
reject2(getAbortReason(signal));
|
|
6763
|
+
};
|
|
6764
|
+
const timeout = setTimeout(() => {
|
|
6765
|
+
signal.removeEventListener("abort", onAbort);
|
|
6766
|
+
resolve();
|
|
6767
|
+
}, delayMs);
|
|
6768
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
6769
|
+
if (signal.aborted) {
|
|
6770
|
+
onAbort();
|
|
6771
|
+
}
|
|
6772
|
+
});
|
|
6773
|
+
}
|
|
6656
6774
|
var HTTPBackgroundLogger = class _HTTPBackgroundLogger {
|
|
6657
6775
|
apiConn;
|
|
6658
6776
|
queue;
|
|
@@ -8080,15 +8198,15 @@ function parentSpanIdsUsable(spanId, rootSpanId) {
|
|
|
8080
8198
|
return Boolean(spanId) && Boolean(rootSpanId);
|
|
8081
8199
|
}
|
|
8082
8200
|
function logError(span, error) {
|
|
8083
|
-
let
|
|
8201
|
+
let errorMessage2 = "<error>";
|
|
8084
8202
|
let stackTrace = "";
|
|
8085
8203
|
if (error instanceof Error) {
|
|
8086
|
-
|
|
8204
|
+
errorMessage2 = error.message;
|
|
8087
8205
|
stackTrace = error.stack || "";
|
|
8088
8206
|
} else {
|
|
8089
|
-
|
|
8207
|
+
errorMessage2 = String(error);
|
|
8090
8208
|
}
|
|
8091
|
-
span.log({ error: `${
|
|
8209
|
+
span.log({ error: `${errorMessage2}
|
|
8092
8210
|
|
|
8093
8211
|
${stackTrace}` });
|
|
8094
8212
|
}
|
|
@@ -8467,7 +8585,8 @@ var ObjectFetcher = class {
|
|
|
8467
8585
|
version: this.pinnedVersion
|
|
8468
8586
|
} : {}
|
|
8469
8587
|
},
|
|
8470
|
-
{ headers: { "Accept-Encoding": "gzip" } }
|
|
8588
|
+
{ headers: { "Accept-Encoding": "gzip" } },
|
|
8589
|
+
BTQL_HTTP_RETRIES
|
|
8471
8590
|
);
|
|
8472
8591
|
const respJson = await resp.json();
|
|
8473
8592
|
const mutate = this.mutateRecord;
|
|
@@ -8984,7 +9103,7 @@ var SpanImpl = class _SpanImpl {
|
|
|
8984
9103
|
this._spanId = resolvedIds.spanId;
|
|
8985
9104
|
this._rootSpanId = resolvedIds.rootSpanId;
|
|
8986
9105
|
this._spanParents = resolvedIds.spanParents;
|
|
8987
|
-
this.isMerge =
|
|
9106
|
+
this.isMerge = args[INITIAL_SPAN_WRITE_AS_MERGE] === true;
|
|
8988
9107
|
this.logInternal({ event, internalData });
|
|
8989
9108
|
this.isMerge = true;
|
|
8990
9109
|
}
|
|
@@ -28555,6 +28674,446 @@ function isBraintrustHandler(handler) {
|
|
|
28555
28674
|
return Reflect.get(handler, "name") === BRAINTRUST_LANGCHAIN_CALLBACK_HANDLER_NAME;
|
|
28556
28675
|
}
|
|
28557
28676
|
|
|
28677
|
+
// src/instrumentation/plugins/langsmith-channels.ts
|
|
28678
|
+
var langSmithChannels = defineChannels("langsmith", {
|
|
28679
|
+
createRun: channel({
|
|
28680
|
+
channelName: "Client.createRun",
|
|
28681
|
+
kind: "async"
|
|
28682
|
+
}),
|
|
28683
|
+
updateRun: channel({
|
|
28684
|
+
channelName: "Client.updateRun",
|
|
28685
|
+
kind: "async"
|
|
28686
|
+
}),
|
|
28687
|
+
batchIngestRuns: channel({
|
|
28688
|
+
channelName: "Client.batchIngestRuns",
|
|
28689
|
+
kind: "async"
|
|
28690
|
+
})
|
|
28691
|
+
});
|
|
28692
|
+
|
|
28693
|
+
// src/instrumentation/plugins/langsmith-plugin.ts
|
|
28694
|
+
var MAX_COMPLETED_RUNS = 1e4;
|
|
28695
|
+
var BLOCKED_METADATA_KEYS = /* @__PURE__ */ new Set([
|
|
28696
|
+
"__proto__",
|
|
28697
|
+
"constructor",
|
|
28698
|
+
"prototype",
|
|
28699
|
+
"usage_metadata"
|
|
28700
|
+
]);
|
|
28701
|
+
var BLOCKED_METADATA_PREFIXES = ["__pregel_", "langgraph_", "lc_"];
|
|
28702
|
+
var LLM_SETTING_KEYS = [
|
|
28703
|
+
"temperature",
|
|
28704
|
+
"top_p",
|
|
28705
|
+
"max_tokens",
|
|
28706
|
+
"frequency_penalty",
|
|
28707
|
+
"presence_penalty",
|
|
28708
|
+
"stop",
|
|
28709
|
+
"response_format"
|
|
28710
|
+
];
|
|
28711
|
+
var LangSmithPlugin = class extends BasePlugin {
|
|
28712
|
+
activeRuns = /* @__PURE__ */ new Map();
|
|
28713
|
+
completedRuns = new LRUCache({
|
|
28714
|
+
max: MAX_COMPLETED_RUNS
|
|
28715
|
+
});
|
|
28716
|
+
skipLangChainRuns;
|
|
28717
|
+
constructor(options = {}) {
|
|
28718
|
+
super();
|
|
28719
|
+
this.skipLangChainRuns = options.skipLangChainRuns ?? true;
|
|
28720
|
+
}
|
|
28721
|
+
onEnable() {
|
|
28722
|
+
const createChannel = langSmithChannels.createRun.tracingChannel();
|
|
28723
|
+
const createHandlers = {
|
|
28724
|
+
start: (event) => {
|
|
28725
|
+
this.containLifecycleFailure("createRun", () => {
|
|
28726
|
+
this.processCreate(event.arguments[0]);
|
|
28727
|
+
});
|
|
28728
|
+
}
|
|
28729
|
+
};
|
|
28730
|
+
createChannel.subscribe(createHandlers);
|
|
28731
|
+
this.unsubscribers.push(() => createChannel.unsubscribe(createHandlers));
|
|
28732
|
+
const updateChannel = langSmithChannels.updateRun.tracingChannel();
|
|
28733
|
+
const updateHandlers = {
|
|
28734
|
+
start: (event) => {
|
|
28735
|
+
this.containLifecycleFailure("updateRun", () => {
|
|
28736
|
+
this.processUpdate(event.arguments[0], event.arguments[1]);
|
|
28737
|
+
});
|
|
28738
|
+
}
|
|
28739
|
+
};
|
|
28740
|
+
updateChannel.subscribe(updateHandlers);
|
|
28741
|
+
this.unsubscribers.push(() => updateChannel.unsubscribe(updateHandlers));
|
|
28742
|
+
const batchChannel = langSmithChannels.batchIngestRuns.tracingChannel();
|
|
28743
|
+
const batchHandlers = {
|
|
28744
|
+
start: (event) => {
|
|
28745
|
+
this.containLifecycleFailure("batchIngestRuns", () => {
|
|
28746
|
+
this.processBatch(event.arguments[0]);
|
|
28747
|
+
});
|
|
28748
|
+
}
|
|
28749
|
+
};
|
|
28750
|
+
batchChannel.subscribe(batchHandlers);
|
|
28751
|
+
this.unsubscribers.push(() => batchChannel.unsubscribe(batchHandlers));
|
|
28752
|
+
}
|
|
28753
|
+
onDisable() {
|
|
28754
|
+
this.unsubscribers = unsubscribeAll(this.unsubscribers);
|
|
28755
|
+
for (const { span } of this.activeRuns.values()) {
|
|
28756
|
+
span.end();
|
|
28757
|
+
}
|
|
28758
|
+
this.activeRuns.clear();
|
|
28759
|
+
this.completedRuns.clear();
|
|
28760
|
+
}
|
|
28761
|
+
processBatch(batch) {
|
|
28762
|
+
if (!isRecord2(batch)) {
|
|
28763
|
+
return;
|
|
28764
|
+
}
|
|
28765
|
+
const creates = ownValue(batch, "runCreates");
|
|
28766
|
+
if (Array.isArray(creates)) {
|
|
28767
|
+
const parentFirst = [...creates].sort((left, right) => {
|
|
28768
|
+
const leftId = stringValue2(ownValue(left, "id"));
|
|
28769
|
+
const rightId = stringValue2(ownValue(right, "id"));
|
|
28770
|
+
const leftParent = stringValue2(ownValue(left, "parent_run_id"));
|
|
28771
|
+
const rightParent = stringValue2(ownValue(right, "parent_run_id"));
|
|
28772
|
+
if (leftParent && leftParent === rightId) {
|
|
28773
|
+
return 1;
|
|
28774
|
+
}
|
|
28775
|
+
if (rightParent && rightParent === leftId) {
|
|
28776
|
+
return -1;
|
|
28777
|
+
}
|
|
28778
|
+
return dottedOrderDepth(left) - dottedOrderDepth(right);
|
|
28779
|
+
});
|
|
28780
|
+
for (const run of parentFirst) {
|
|
28781
|
+
this.containLifecycleFailure("batchIngestRuns create", () => {
|
|
28782
|
+
this.processCreate(run);
|
|
28783
|
+
});
|
|
28784
|
+
}
|
|
28785
|
+
}
|
|
28786
|
+
const updates = ownValue(batch, "runUpdates");
|
|
28787
|
+
if (Array.isArray(updates)) {
|
|
28788
|
+
for (const run of updates) {
|
|
28789
|
+
this.containLifecycleFailure("batchIngestRuns update", () => {
|
|
28790
|
+
this.processUpdate(stringValue2(ownValue(run, "id")) ?? "", run);
|
|
28791
|
+
});
|
|
28792
|
+
}
|
|
28793
|
+
}
|
|
28794
|
+
}
|
|
28795
|
+
processCreate(run) {
|
|
28796
|
+
const id = stringValue2(ownValue(run, "id"));
|
|
28797
|
+
if (!id || this.completedRuns.get(id)) {
|
|
28798
|
+
return;
|
|
28799
|
+
}
|
|
28800
|
+
if (this.shouldSkipLangChainRun(run)) {
|
|
28801
|
+
this.completedRuns.set(id, true);
|
|
28802
|
+
return;
|
|
28803
|
+
}
|
|
28804
|
+
const active = this.activeRuns.get(id);
|
|
28805
|
+
if (active) {
|
|
28806
|
+
const previous = active.run;
|
|
28807
|
+
active.run = mergeRuns(previous, run);
|
|
28808
|
+
this.logRun(
|
|
28809
|
+
active.span,
|
|
28810
|
+
active.run,
|
|
28811
|
+
previous,
|
|
28812
|
+
timestampSeconds(ownValue(active.run, "end_time")) !== void 0 || errorMessage(ownValue(active.run, "error")) !== void 0
|
|
28813
|
+
);
|
|
28814
|
+
this.endIfComplete(id, active, active.run);
|
|
28815
|
+
return;
|
|
28816
|
+
}
|
|
28817
|
+
const span = this.startRunSpan(id, run);
|
|
28818
|
+
const activeRun = { run, span };
|
|
28819
|
+
this.activeRuns.set(id, activeRun);
|
|
28820
|
+
this.logRun(
|
|
28821
|
+
span,
|
|
28822
|
+
run,
|
|
28823
|
+
void 0,
|
|
28824
|
+
timestampSeconds(ownValue(run, "end_time")) !== void 0 || errorMessage(ownValue(run, "error")) !== void 0
|
|
28825
|
+
);
|
|
28826
|
+
this.endIfComplete(id, activeRun, run);
|
|
28827
|
+
}
|
|
28828
|
+
processUpdate(explicitId, run) {
|
|
28829
|
+
const id = stringValue2(explicitId) ?? stringValue2(ownValue(run, "id"));
|
|
28830
|
+
if (!id || this.completedRuns.get(id)) {
|
|
28831
|
+
return;
|
|
28832
|
+
}
|
|
28833
|
+
if (this.shouldSkipLangChainRun(run)) {
|
|
28834
|
+
const active2 = this.activeRuns.get(id);
|
|
28835
|
+
active2?.span.end();
|
|
28836
|
+
this.activeRuns.delete(id);
|
|
28837
|
+
this.completedRuns.set(id, true);
|
|
28838
|
+
return;
|
|
28839
|
+
}
|
|
28840
|
+
let active = this.activeRuns.get(id);
|
|
28841
|
+
if (!active) {
|
|
28842
|
+
const span = this.startRunSpan(id, run);
|
|
28843
|
+
active = { run, span };
|
|
28844
|
+
this.activeRuns.set(id, active);
|
|
28845
|
+
}
|
|
28846
|
+
const previous = active.run;
|
|
28847
|
+
active.run = mergeRuns(previous, run);
|
|
28848
|
+
this.logRun(active.span, active.run, previous, true);
|
|
28849
|
+
this.endIfComplete(id, active, active.run);
|
|
28850
|
+
}
|
|
28851
|
+
startRunSpan(id, run) {
|
|
28852
|
+
const traceId = stringValue2(ownValue(run, "trace_id")) ?? id;
|
|
28853
|
+
const parentId = stringValue2(ownValue(run, "parent_run_id")) ?? stringValue2(ownValue(ownValue(run, "parent_run"), "id"));
|
|
28854
|
+
const startTime = timestampSeconds(ownValue(run, "start_time"));
|
|
28855
|
+
return startSpan({
|
|
28856
|
+
name: stringValue2(ownValue(run, "name")) ?? "LangSmith run",
|
|
28857
|
+
spanId: id,
|
|
28858
|
+
parentSpanIds: {
|
|
28859
|
+
parentSpanIds: parentId ? [parentId] : [],
|
|
28860
|
+
rootSpanId: traceId
|
|
28861
|
+
},
|
|
28862
|
+
spanAttributes: {
|
|
28863
|
+
type: mapRunType(ownValue(run, "run_type"))
|
|
28864
|
+
},
|
|
28865
|
+
...startTime === void 0 ? {} : { startTime },
|
|
28866
|
+
event: { id }
|
|
28867
|
+
});
|
|
28868
|
+
}
|
|
28869
|
+
logRun(span, run, previous, includeOutput) {
|
|
28870
|
+
const inputs = preferOwnValue(run, previous, "inputs");
|
|
28871
|
+
const outputs = preferOwnValue(run, previous, "outputs");
|
|
28872
|
+
const error = errorMessage(preferOwnValue(run, previous, "error"));
|
|
28873
|
+
const metadata = extractMetadata(run, previous);
|
|
28874
|
+
const tags = extractTags(preferOwnValue(run, previous, "tags"));
|
|
28875
|
+
const metrics = extractMetrics(run, previous);
|
|
28876
|
+
span.log({
|
|
28877
|
+
...inputs === void 0 ? {} : { input: sanitizeLoggedValue(inputs) },
|
|
28878
|
+
...includeOutput && outputs !== void 0 ? { output: sanitizeLoggedValue(outputs) } : {},
|
|
28879
|
+
...error === void 0 ? {} : { error },
|
|
28880
|
+
...metadata === void 0 ? {} : { metadata },
|
|
28881
|
+
...tags === void 0 ? {} : { tags },
|
|
28882
|
+
...Object.keys(metrics).length === 0 ? {} : { metrics }
|
|
28883
|
+
});
|
|
28884
|
+
}
|
|
28885
|
+
endIfComplete(id, active, run) {
|
|
28886
|
+
const endTime = timestampSeconds(ownValue(run, "end_time"));
|
|
28887
|
+
if (endTime === void 0 && errorMessage(ownValue(run, "error")) === void 0) {
|
|
28888
|
+
return;
|
|
28889
|
+
}
|
|
28890
|
+
active.span.end(endTime === void 0 ? void 0 : { endTime });
|
|
28891
|
+
this.activeRuns.delete(id);
|
|
28892
|
+
this.completedRuns.set(id, true);
|
|
28893
|
+
}
|
|
28894
|
+
shouldSkipLangChainRun(run) {
|
|
28895
|
+
if (!this.skipLangChainRuns) {
|
|
28896
|
+
return false;
|
|
28897
|
+
}
|
|
28898
|
+
const serialized = ownValue(run, "serialized");
|
|
28899
|
+
return isRecord2(serialized) && ownValue(serialized, "lc") === 1;
|
|
28900
|
+
}
|
|
28901
|
+
containLifecycleFailure(operation, fn) {
|
|
28902
|
+
try {
|
|
28903
|
+
fn();
|
|
28904
|
+
} catch (error) {
|
|
28905
|
+
debugLogger.error(
|
|
28906
|
+
`Failed to process LangSmith ${operation} instrumentation:`,
|
|
28907
|
+
error
|
|
28908
|
+
);
|
|
28909
|
+
}
|
|
28910
|
+
}
|
|
28911
|
+
};
|
|
28912
|
+
function ownValue(value, key) {
|
|
28913
|
+
if (!isRecord2(value)) {
|
|
28914
|
+
return void 0;
|
|
28915
|
+
}
|
|
28916
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
28917
|
+
return descriptor && "value" in descriptor ? descriptor.value : void 0;
|
|
28918
|
+
}
|
|
28919
|
+
function preferOwnValue(current, previous, key) {
|
|
28920
|
+
const currentDescriptor = isRecord2(current) ? Object.getOwnPropertyDescriptor(current, key) : void 0;
|
|
28921
|
+
if (currentDescriptor && "value" in currentDescriptor) {
|
|
28922
|
+
return currentDescriptor.value;
|
|
28923
|
+
}
|
|
28924
|
+
return ownValue(previous, key);
|
|
28925
|
+
}
|
|
28926
|
+
function mergeRuns(previous, current) {
|
|
28927
|
+
const entries = /* @__PURE__ */ new Map();
|
|
28928
|
+
for (const value of [previous, current]) {
|
|
28929
|
+
if (!isRecord2(value)) {
|
|
28930
|
+
continue;
|
|
28931
|
+
}
|
|
28932
|
+
for (const [key, descriptor] of Object.entries(
|
|
28933
|
+
Object.getOwnPropertyDescriptors(value)
|
|
28934
|
+
)) {
|
|
28935
|
+
if (descriptor.enumerable && "value" in descriptor) {
|
|
28936
|
+
entries.set(key, descriptor.value);
|
|
28937
|
+
}
|
|
28938
|
+
}
|
|
28939
|
+
}
|
|
28940
|
+
return Object.fromEntries(entries);
|
|
28941
|
+
}
|
|
28942
|
+
function isRecord2(value) {
|
|
28943
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
28944
|
+
}
|
|
28945
|
+
function stringValue2(value) {
|
|
28946
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
28947
|
+
}
|
|
28948
|
+
function timestampSeconds(value) {
|
|
28949
|
+
if (value instanceof Date) {
|
|
28950
|
+
const timestamp = value.getTime();
|
|
28951
|
+
return Number.isFinite(timestamp) ? timestamp / 1e3 : void 0;
|
|
28952
|
+
}
|
|
28953
|
+
if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
|
|
28954
|
+
return value > 1e10 ? value / 1e3 : value;
|
|
28955
|
+
}
|
|
28956
|
+
if (typeof value === "string") {
|
|
28957
|
+
const timestamp = Date.parse(value);
|
|
28958
|
+
return Number.isFinite(timestamp) ? timestamp / 1e3 : void 0;
|
|
28959
|
+
}
|
|
28960
|
+
return void 0;
|
|
28961
|
+
}
|
|
28962
|
+
function dottedOrderDepth(run) {
|
|
28963
|
+
const dottedOrder = stringValue2(ownValue(run, "dotted_order"));
|
|
28964
|
+
return dottedOrder ? dottedOrder.split(".").length : Number.MAX_SAFE_INTEGER;
|
|
28965
|
+
}
|
|
28966
|
+
function mapRunType(runType) {
|
|
28967
|
+
switch (runType) {
|
|
28968
|
+
case "llm":
|
|
28969
|
+
case "embedding":
|
|
28970
|
+
return "llm" /* LLM */;
|
|
28971
|
+
case "tool":
|
|
28972
|
+
case "retriever":
|
|
28973
|
+
return "tool" /* TOOL */;
|
|
28974
|
+
default:
|
|
28975
|
+
return "task" /* TASK */;
|
|
28976
|
+
}
|
|
28977
|
+
}
|
|
28978
|
+
function extractMetadata(run, previous) {
|
|
28979
|
+
const extra = preferOwnValue(run, previous, "extra");
|
|
28980
|
+
const rawMetadata = ownValue(extra, "metadata");
|
|
28981
|
+
if (!isRecord2(rawMetadata)) {
|
|
28982
|
+
return void 0;
|
|
28983
|
+
}
|
|
28984
|
+
const metadata = {};
|
|
28985
|
+
for (const [key, descriptor] of Object.entries(
|
|
28986
|
+
Object.getOwnPropertyDescriptors(rawMetadata)
|
|
28987
|
+
)) {
|
|
28988
|
+
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}`)) {
|
|
28989
|
+
continue;
|
|
28990
|
+
}
|
|
28991
|
+
const normalizedKey = key === "ls_provider" ? "provider" : key === "ls_model_name" ? "model" : key.startsWith("ls_") ? key.slice(3) : key;
|
|
28992
|
+
const sanitized = sanitizeLoggedValue(descriptor.value);
|
|
28993
|
+
if (sanitized !== void 0) {
|
|
28994
|
+
metadata[normalizedKey] = sanitized;
|
|
28995
|
+
}
|
|
28996
|
+
}
|
|
28997
|
+
return Object.keys(metadata).length === 0 ? void 0 : metadata;
|
|
28998
|
+
}
|
|
28999
|
+
function extractTags(value) {
|
|
29000
|
+
if (!Array.isArray(value)) {
|
|
29001
|
+
return void 0;
|
|
29002
|
+
}
|
|
29003
|
+
const tags = value.filter(
|
|
29004
|
+
(tag) => typeof tag === "string" && tag.length > 0
|
|
29005
|
+
);
|
|
29006
|
+
return tags.length > 0 ? tags : void 0;
|
|
29007
|
+
}
|
|
29008
|
+
function extractMetrics(run, previous) {
|
|
29009
|
+
const outputs = preferOwnValue(run, previous, "outputs");
|
|
29010
|
+
const extra = preferOwnValue(run, previous, "extra");
|
|
29011
|
+
const metadata = ownValue(extra, "metadata");
|
|
29012
|
+
const usage = ownValue(outputs, "usage_metadata") ?? ownValue(metadata, "usage_metadata");
|
|
29013
|
+
const metrics = {};
|
|
29014
|
+
assignFirstMetric(metrics, "prompt_tokens", usage, [
|
|
29015
|
+
"input_tokens",
|
|
29016
|
+
"prompt_tokens"
|
|
29017
|
+
]);
|
|
29018
|
+
assignFirstMetric(metrics, "completion_tokens", usage, [
|
|
29019
|
+
"output_tokens",
|
|
29020
|
+
"completion_tokens"
|
|
29021
|
+
]);
|
|
29022
|
+
assignFirstMetric(metrics, "tokens", usage, ["total_tokens", "tokens"]);
|
|
29023
|
+
const inputTokenDetails = ownValue(usage, "input_token_details");
|
|
29024
|
+
assignFirstMetric(metrics, "prompt_cached_tokens", inputTokenDetails, [
|
|
29025
|
+
"cache_read",
|
|
29026
|
+
"cached_tokens"
|
|
29027
|
+
]);
|
|
29028
|
+
if (metrics.prompt_cached_tokens === void 0) {
|
|
29029
|
+
assignFirstMetric(metrics, "prompt_cached_tokens", usage, [
|
|
29030
|
+
"cache_read_input_tokens",
|
|
29031
|
+
"prompt_cached_tokens"
|
|
29032
|
+
]);
|
|
29033
|
+
}
|
|
29034
|
+
assignFirstMetric(
|
|
29035
|
+
metrics,
|
|
29036
|
+
"prompt_cache_creation_tokens",
|
|
29037
|
+
inputTokenDetails,
|
|
29038
|
+
["cache_creation"]
|
|
29039
|
+
);
|
|
29040
|
+
if (metrics.prompt_cache_creation_tokens === void 0) {
|
|
29041
|
+
assignFirstMetric(metrics, "prompt_cache_creation_tokens", usage, [
|
|
29042
|
+
"cache_creation_input_tokens",
|
|
29043
|
+
"prompt_cache_creation_tokens"
|
|
29044
|
+
]);
|
|
29045
|
+
}
|
|
29046
|
+
if (metrics.tokens === void 0 && (metrics.prompt_tokens !== void 0 || metrics.completion_tokens !== void 0)) {
|
|
29047
|
+
metrics.tokens = (metrics.prompt_tokens ?? 0) + (metrics.completion_tokens ?? 0);
|
|
29048
|
+
}
|
|
29049
|
+
const startTime = timestampSeconds(
|
|
29050
|
+
preferOwnValue(run, previous, "start_time")
|
|
29051
|
+
);
|
|
29052
|
+
const events = preferOwnValue(run, previous, "events");
|
|
29053
|
+
if (startTime !== void 0 && Array.isArray(events)) {
|
|
29054
|
+
for (const event of events) {
|
|
29055
|
+
if (ownValue(event, "name") !== "new_token") {
|
|
29056
|
+
continue;
|
|
29057
|
+
}
|
|
29058
|
+
const eventTime2 = timestampSeconds(ownValue(event, "time"));
|
|
29059
|
+
if (eventTime2 !== void 0 && eventTime2 >= startTime) {
|
|
29060
|
+
metrics.time_to_first_token = eventTime2 - startTime;
|
|
29061
|
+
}
|
|
29062
|
+
break;
|
|
29063
|
+
}
|
|
29064
|
+
}
|
|
29065
|
+
return metrics;
|
|
29066
|
+
}
|
|
29067
|
+
function assignFirstMetric(metrics, target, source, keys) {
|
|
29068
|
+
for (const key of keys) {
|
|
29069
|
+
const value = ownValue(source, key);
|
|
29070
|
+
if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
|
|
29071
|
+
metrics[target] = value;
|
|
29072
|
+
return;
|
|
29073
|
+
}
|
|
29074
|
+
}
|
|
29075
|
+
}
|
|
29076
|
+
function errorMessage(value) {
|
|
29077
|
+
if (typeof value === "string") {
|
|
29078
|
+
return value;
|
|
29079
|
+
}
|
|
29080
|
+
if (value instanceof Error) {
|
|
29081
|
+
return value.message;
|
|
29082
|
+
}
|
|
29083
|
+
return void 0;
|
|
29084
|
+
}
|
|
29085
|
+
function sanitizeLoggedValue(value, seen = /* @__PURE__ */ new WeakSet(), depth = 0) {
|
|
29086
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") {
|
|
29087
|
+
return value;
|
|
29088
|
+
}
|
|
29089
|
+
if (typeof value === "number") {
|
|
29090
|
+
return Number.isFinite(value) ? value : void 0;
|
|
29091
|
+
}
|
|
29092
|
+
if (value instanceof Date) {
|
|
29093
|
+
return Number.isFinite(value.getTime()) ? value.toISOString() : void 0;
|
|
29094
|
+
}
|
|
29095
|
+
if (typeof value !== "object" || depth >= 20) {
|
|
29096
|
+
return void 0;
|
|
29097
|
+
}
|
|
29098
|
+
if (seen.has(value)) {
|
|
29099
|
+
return "[Circular]";
|
|
29100
|
+
}
|
|
29101
|
+
seen.add(value);
|
|
29102
|
+
if (Array.isArray(value)) {
|
|
29103
|
+
return value.map((item) => sanitizeLoggedValue(item, seen, depth + 1));
|
|
29104
|
+
}
|
|
29105
|
+
const entries = [];
|
|
29106
|
+
for (const [key, descriptor] of Object.entries(
|
|
29107
|
+
Object.getOwnPropertyDescriptors(value)
|
|
29108
|
+
)) {
|
|
29109
|
+
if (!descriptor.enumerable || !("value" in descriptor) || BLOCKED_METADATA_KEYS.has(key)) {
|
|
29110
|
+
continue;
|
|
29111
|
+
}
|
|
29112
|
+
entries.push([key, sanitizeLoggedValue(descriptor.value, seen, depth + 1)]);
|
|
29113
|
+
}
|
|
29114
|
+
return Object.fromEntries(entries);
|
|
29115
|
+
}
|
|
29116
|
+
|
|
28558
29117
|
// src/instrumentation/plugins/pi-coding-agent-channels.ts
|
|
28559
29118
|
var piCodingAgentChannels = defineChannels(
|
|
28560
29119
|
"@earendil-works/pi-coding-agent",
|
|
@@ -28934,11 +29493,11 @@ function patchAssistantMessageStream(stream, promptState, llmState) {
|
|
|
28934
29493
|
function recordPiAssistantMessageEvent(promptState, llmState, event) {
|
|
28935
29494
|
recordFirstTokenMetric(llmState, event);
|
|
28936
29495
|
const message = "message" in event ? event.message : void 0;
|
|
28937
|
-
const
|
|
29496
|
+
const errorMessage2 = "error" in event ? event.error : void 0;
|
|
28938
29497
|
if (event.type === "done" && isPiAssistantMessage(message)) {
|
|
28939
29498
|
finishPiLlmSpan(promptState, llmState, message);
|
|
28940
|
-
} else if (event.type === "error" && isPiAssistantMessage(
|
|
28941
|
-
finishPiLlmSpan(promptState, llmState,
|
|
29499
|
+
} else if (event.type === "error" && isPiAssistantMessage(errorMessage2)) {
|
|
29500
|
+
finishPiLlmSpan(promptState, llmState, errorMessage2);
|
|
28942
29501
|
}
|
|
28943
29502
|
}
|
|
28944
29503
|
function recordFirstTokenMetric(state, event) {
|
|
@@ -29456,6 +30015,7 @@ var strandsAgentSDKChannels = defineChannels("@strands-agents/sdk", {
|
|
|
29456
30015
|
});
|
|
29457
30016
|
|
|
29458
30017
|
// src/instrumentation/plugins/strands-agent-sdk-plugin.ts
|
|
30018
|
+
var MAX_STRANDS_STRING_ATTACHMENT_CACHE_ENTRIES = 32;
|
|
29459
30019
|
var StrandsAgentSDKPlugin = class extends BasePlugin {
|
|
29460
30020
|
activeChildParents = /* @__PURE__ */ new WeakMap();
|
|
29461
30021
|
onEnable() {
|
|
@@ -29600,11 +30160,16 @@ function startAgentStream(event, activeChildParents) {
|
|
|
29600
30160
|
...event.moduleVersion ? { "strands_agent_sdk.version": event.moduleVersion } : {}
|
|
29601
30161
|
};
|
|
29602
30162
|
const parentSpan = agent ? getOnlyChildParent(activeChildParents, agent) : void 0;
|
|
30163
|
+
const attachmentCache = createStrandsAttachmentCache();
|
|
30164
|
+
const input = processStrandsInputAttachments(
|
|
30165
|
+
event.arguments[0],
|
|
30166
|
+
attachmentCache
|
|
30167
|
+
);
|
|
29603
30168
|
const span = parentSpan ? withCurrent(
|
|
29604
30169
|
parentSpan,
|
|
29605
30170
|
() => startSpan({
|
|
29606
30171
|
event: {
|
|
29607
|
-
input
|
|
30172
|
+
input,
|
|
29608
30173
|
metadata
|
|
29609
30174
|
},
|
|
29610
30175
|
name: formatAgentSpanName(agent),
|
|
@@ -29612,7 +30177,7 @@ function startAgentStream(event, activeChildParents) {
|
|
|
29612
30177
|
})
|
|
29613
30178
|
) : startSpan({
|
|
29614
30179
|
event: {
|
|
29615
|
-
input
|
|
30180
|
+
input,
|
|
29616
30181
|
metadata
|
|
29617
30182
|
},
|
|
29618
30183
|
name: formatAgentSpanName(agent),
|
|
@@ -29620,6 +30185,7 @@ function startAgentStream(event, activeChildParents) {
|
|
|
29620
30185
|
});
|
|
29621
30186
|
return {
|
|
29622
30187
|
activeTools: /* @__PURE__ */ new Map(),
|
|
30188
|
+
attachmentCache,
|
|
29623
30189
|
finalized: false,
|
|
29624
30190
|
metadata,
|
|
29625
30191
|
span,
|
|
@@ -29635,11 +30201,12 @@ function startMultiAgentStream(event, operation, activeChildParents) {
|
|
|
29635
30201
|
...event.moduleVersion ? { "strands_agent_sdk.version": event.moduleVersion } : {}
|
|
29636
30202
|
};
|
|
29637
30203
|
const parentSpan = orchestrator ? getOnlyChildParent(activeChildParents, orchestrator) : void 0;
|
|
30204
|
+
const input = processStrandsInputAttachments(event.arguments[0]);
|
|
29638
30205
|
const span = parentSpan ? withCurrent(
|
|
29639
30206
|
parentSpan,
|
|
29640
30207
|
() => startSpan({
|
|
29641
30208
|
event: {
|
|
29642
|
-
input
|
|
30209
|
+
input,
|
|
29643
30210
|
metadata
|
|
29644
30211
|
},
|
|
29645
30212
|
name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
|
|
@@ -29647,7 +30214,7 @@ function startMultiAgentStream(event, operation, activeChildParents) {
|
|
|
29647
30214
|
})
|
|
29648
30215
|
) : startSpan({
|
|
29649
30216
|
event: {
|
|
29650
|
-
input
|
|
30217
|
+
input,
|
|
29651
30218
|
metadata
|
|
29652
30219
|
},
|
|
29653
30220
|
name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
|
|
@@ -29756,7 +30323,10 @@ function startModelSpan(state, event) {
|
|
|
29756
30323
|
state.span,
|
|
29757
30324
|
() => startSpan({
|
|
29758
30325
|
event: {
|
|
29759
|
-
input: Array.isArray(event.agent?.messages) ?
|
|
30326
|
+
input: Array.isArray(event.agent?.messages) ? processStrandsInputAttachments(
|
|
30327
|
+
event.agent.messages,
|
|
30328
|
+
state.attachmentCache
|
|
30329
|
+
) : void 0,
|
|
29760
30330
|
metadata
|
|
29761
30331
|
},
|
|
29762
30332
|
name: formatModelSpanName(model),
|
|
@@ -29970,6 +30540,7 @@ function finalizeAgentStream(state, error, output) {
|
|
|
29970
30540
|
...output !== void 0 ? { output } : {}
|
|
29971
30541
|
});
|
|
29972
30542
|
state.span.end();
|
|
30543
|
+
state.attachmentCache.strings.clear();
|
|
29973
30544
|
}
|
|
29974
30545
|
function finalizeMultiAgentStream(state, activeChildParents, error, output) {
|
|
29975
30546
|
if (state.finalized) {
|
|
@@ -30116,6 +30687,166 @@ function extractNodeResultOutput(result) {
|
|
|
30116
30687
|
}
|
|
30117
30688
|
return result;
|
|
30118
30689
|
}
|
|
30690
|
+
var STRANDS_MEDIA_TYPES = {
|
|
30691
|
+
png: "image/png",
|
|
30692
|
+
jpg: "image/jpeg",
|
|
30693
|
+
jpeg: "image/jpeg",
|
|
30694
|
+
gif: "image/gif",
|
|
30695
|
+
webp: "image/webp",
|
|
30696
|
+
mkv: "video/x-matroska",
|
|
30697
|
+
mov: "video/quicktime",
|
|
30698
|
+
mp4: "video/mp4",
|
|
30699
|
+
webm: "video/webm",
|
|
30700
|
+
flv: "video/x-flv",
|
|
30701
|
+
mpeg: "video/mpeg",
|
|
30702
|
+
mpg: "video/mpeg",
|
|
30703
|
+
wmv: "video/x-ms-wmv",
|
|
30704
|
+
"3gp": "video/3gpp",
|
|
30705
|
+
pdf: "application/pdf",
|
|
30706
|
+
csv: "text/csv",
|
|
30707
|
+
doc: "application/msword",
|
|
30708
|
+
docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
30709
|
+
xls: "application/vnd.ms-excel",
|
|
30710
|
+
xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
30711
|
+
html: "text/html",
|
|
30712
|
+
txt: "text/plain",
|
|
30713
|
+
md: "text/markdown",
|
|
30714
|
+
json: "application/json",
|
|
30715
|
+
xml: "application/xml"
|
|
30716
|
+
};
|
|
30717
|
+
function createStrandsAttachmentCache() {
|
|
30718
|
+
return {
|
|
30719
|
+
objects: /* @__PURE__ */ new WeakMap(),
|
|
30720
|
+
strings: new LRUCache({
|
|
30721
|
+
max: MAX_STRANDS_STRING_ATTACHMENT_CACHE_ENTRIES
|
|
30722
|
+
})
|
|
30723
|
+
};
|
|
30724
|
+
}
|
|
30725
|
+
function processStrandsInputAttachments(input, cache = createStrandsAttachmentCache()) {
|
|
30726
|
+
try {
|
|
30727
|
+
return processStrandsInputNode(input, cache);
|
|
30728
|
+
} catch (error) {
|
|
30729
|
+
logInstrumentationError5("Strands Agent SDK input attachments", error);
|
|
30730
|
+
return input;
|
|
30731
|
+
}
|
|
30732
|
+
}
|
|
30733
|
+
function processStrandsInputNode(value, cache) {
|
|
30734
|
+
if (value instanceof BaseAttachment) {
|
|
30735
|
+
return value;
|
|
30736
|
+
}
|
|
30737
|
+
if (Array.isArray(value)) {
|
|
30738
|
+
return value.map((child) => processStrandsInputNode(child, cache));
|
|
30739
|
+
}
|
|
30740
|
+
if (!isObject(value)) {
|
|
30741
|
+
return value;
|
|
30742
|
+
}
|
|
30743
|
+
const directMedia = processDirectStrandsMediaBlock(value, cache);
|
|
30744
|
+
if (directMedia !== void 0) {
|
|
30745
|
+
return directMedia;
|
|
30746
|
+
}
|
|
30747
|
+
const wrappedMedia = processWrappedStrandsMediaBlock(value, cache);
|
|
30748
|
+
if (wrappedMedia !== void 0) {
|
|
30749
|
+
return wrappedMedia;
|
|
30750
|
+
}
|
|
30751
|
+
if (value.type === "message" && Array.isArray(value.content)) {
|
|
30752
|
+
return {
|
|
30753
|
+
role: value.role,
|
|
30754
|
+
content: value.content.map(
|
|
30755
|
+
(child) => processStrandsInputNode(child, cache)
|
|
30756
|
+
),
|
|
30757
|
+
...value.metadata !== void 0 ? { metadata: value.metadata } : {}
|
|
30758
|
+
};
|
|
30759
|
+
}
|
|
30760
|
+
if (typeof value.toJSON === "function") {
|
|
30761
|
+
return processStrandsInputNode(value.toJSON(), cache);
|
|
30762
|
+
}
|
|
30763
|
+
return Object.fromEntries(
|
|
30764
|
+
Object.entries(value).map(([key, child]) => [
|
|
30765
|
+
key,
|
|
30766
|
+
processStrandsInputNode(child, cache)
|
|
30767
|
+
])
|
|
30768
|
+
);
|
|
30769
|
+
}
|
|
30770
|
+
function processDirectStrandsMediaBlock(block, cache) {
|
|
30771
|
+
if (!isStrandsMediaBlock(block)) {
|
|
30772
|
+
return void 0;
|
|
30773
|
+
}
|
|
30774
|
+
const mediaKey = block.type === "imageBlock" ? "image" : block.type === "videoBlock" ? "video" : "document";
|
|
30775
|
+
return createStrandsMediaAttachment(mediaKey, block, cache);
|
|
30776
|
+
}
|
|
30777
|
+
function isStrandsMediaBlock(block) {
|
|
30778
|
+
return (block.type === "imageBlock" || block.type === "videoBlock" || block.type === "documentBlock") && typeof block.format === "string" && isObject(block.source);
|
|
30779
|
+
}
|
|
30780
|
+
function processWrappedStrandsMediaBlock(block, cache) {
|
|
30781
|
+
for (const mediaKey of ["image", "video", "document"]) {
|
|
30782
|
+
const media = block[mediaKey];
|
|
30783
|
+
if (!Object.hasOwn(block, mediaKey) || !isObject(media)) {
|
|
30784
|
+
continue;
|
|
30785
|
+
}
|
|
30786
|
+
const processed = createStrandsMediaAttachment(mediaKey, media, cache);
|
|
30787
|
+
if (processed !== void 0) {
|
|
30788
|
+
return processed;
|
|
30789
|
+
}
|
|
30790
|
+
}
|
|
30791
|
+
return void 0;
|
|
30792
|
+
}
|
|
30793
|
+
function createStrandsMediaAttachment(mediaKey, media, cache) {
|
|
30794
|
+
const format = media.format;
|
|
30795
|
+
const source = media.source;
|
|
30796
|
+
if (typeof format !== "string" || !isObject(source) || !Object.hasOwn(source, "bytes")) {
|
|
30797
|
+
return void 0;
|
|
30798
|
+
}
|
|
30799
|
+
const contentType = STRANDS_MEDIA_TYPES[format.toLowerCase()];
|
|
30800
|
+
if (!contentType) {
|
|
30801
|
+
return void 0;
|
|
30802
|
+
}
|
|
30803
|
+
const filename = mediaKey === "document" && typeof media.name === "string" && media.name.length > 0 ? media.name : `${mediaKey}.${format.toLowerCase()}`;
|
|
30804
|
+
const attachment = getOrCreateStrandsAttachment(
|
|
30805
|
+
source.bytes,
|
|
30806
|
+
filename,
|
|
30807
|
+
contentType,
|
|
30808
|
+
cache
|
|
30809
|
+
);
|
|
30810
|
+
if (!attachment) {
|
|
30811
|
+
return void 0;
|
|
30812
|
+
}
|
|
30813
|
+
const { type: _type, ...serializedMedia } = media;
|
|
30814
|
+
const { type: _sourceType, ...serializedSource } = source;
|
|
30815
|
+
return {
|
|
30816
|
+
[mediaKey]: {
|
|
30817
|
+
...serializedMedia,
|
|
30818
|
+
source: {
|
|
30819
|
+
...serializedSource,
|
|
30820
|
+
bytes: attachment
|
|
30821
|
+
}
|
|
30822
|
+
}
|
|
30823
|
+
};
|
|
30824
|
+
}
|
|
30825
|
+
function getOrCreateStrandsAttachment(data, filename, contentType, cache) {
|
|
30826
|
+
const key = `${contentType}\0${filename}`;
|
|
30827
|
+
const attachments = typeof data === "string" ? cache.strings.get(data) : isObject(data) ? cache.objects.get(data) : void 0;
|
|
30828
|
+
const cached = attachments?.get(key);
|
|
30829
|
+
if (cached) {
|
|
30830
|
+
return cached;
|
|
30831
|
+
}
|
|
30832
|
+
const blob = convertDataToBlob(data, contentType);
|
|
30833
|
+
if (!blob) {
|
|
30834
|
+
return void 0;
|
|
30835
|
+
}
|
|
30836
|
+
const attachment = new Attachment({
|
|
30837
|
+
data: blob,
|
|
30838
|
+
filename,
|
|
30839
|
+
contentType
|
|
30840
|
+
});
|
|
30841
|
+
const updatedAttachments = attachments ?? /* @__PURE__ */ new Map();
|
|
30842
|
+
updatedAttachments.set(key, attachment);
|
|
30843
|
+
if (typeof data === "string") {
|
|
30844
|
+
cache.strings.set(data, updatedAttachments);
|
|
30845
|
+
} else if (isObject(data)) {
|
|
30846
|
+
cache.objects.set(data, updatedAttachments);
|
|
30847
|
+
}
|
|
30848
|
+
return attachment;
|
|
30849
|
+
}
|
|
30119
30850
|
function normalizeContentBlocks(blocks) {
|
|
30120
30851
|
const text = blocks.map((block) => typeof block.text === "string" ? block.text : void 0).filter((part) => Boolean(part)).join("");
|
|
30121
30852
|
return text.length > 0 ? text : blocks;
|
|
@@ -30245,6 +30976,7 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
30245
30976
|
gitHubCopilotPlugin = null;
|
|
30246
30977
|
fluePlugin = null;
|
|
30247
30978
|
langChainPlugin = null;
|
|
30979
|
+
langSmithPlugin = null;
|
|
30248
30980
|
piCodingAgentPlugin = null;
|
|
30249
30981
|
strandsAgentSDKPlugin = null;
|
|
30250
30982
|
constructor(config = {}) {
|
|
@@ -30341,6 +31073,12 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
30341
31073
|
this.langChainPlugin = new LangChainPlugin();
|
|
30342
31074
|
this.langChainPlugin.enable();
|
|
30343
31075
|
}
|
|
31076
|
+
if (integrations.langsmith !== false) {
|
|
31077
|
+
this.langSmithPlugin = new LangSmithPlugin({
|
|
31078
|
+
skipLangChainRuns: integrations.langchain !== false
|
|
31079
|
+
});
|
|
31080
|
+
this.langSmithPlugin.enable();
|
|
31081
|
+
}
|
|
30344
31082
|
}
|
|
30345
31083
|
onDisable() {
|
|
30346
31084
|
if (this.openaiPlugin) {
|
|
@@ -30431,6 +31169,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
30431
31169
|
this.langChainPlugin.disable();
|
|
30432
31170
|
this.langChainPlugin = null;
|
|
30433
31171
|
}
|
|
31172
|
+
if (this.langSmithPlugin) {
|
|
31173
|
+
this.langSmithPlugin.disable();
|
|
31174
|
+
this.langSmithPlugin = null;
|
|
31175
|
+
}
|
|
30434
31176
|
}
|
|
30435
31177
|
};
|
|
30436
31178
|
|
|
@@ -30495,7 +31237,8 @@ var envIntegrationAliases = {
|
|
|
30495
31237
|
langchain: "langchain",
|
|
30496
31238
|
"langchain-js": "langchain",
|
|
30497
31239
|
"@langchain": "langchain",
|
|
30498
|
-
langgraph: "langgraph"
|
|
31240
|
+
langgraph: "langgraph",
|
|
31241
|
+
langsmith: "langsmith"
|
|
30499
31242
|
};
|
|
30500
31243
|
function getDefaultInstrumentationIntegrations() {
|
|
30501
31244
|
return {
|
|
@@ -30526,6 +31269,7 @@ function getDefaultInstrumentationIntegrations() {
|
|
|
30526
31269
|
gitHubCopilot: true,
|
|
30527
31270
|
langchain: true,
|
|
30528
31271
|
langgraph: true,
|
|
31272
|
+
langsmith: true,
|
|
30529
31273
|
piCodingAgent: true,
|
|
30530
31274
|
strandsAgentSDK: true
|
|
30531
31275
|
};
|
|
@@ -30766,6 +31510,15 @@ function modelMetrics(attributes) {
|
|
|
30766
31510
|
}
|
|
30767
31511
|
return Object.keys(out).length > 0 ? out : void 0;
|
|
30768
31512
|
}
|
|
31513
|
+
function timeToFirstTokenSeconds(attributes, spanStartSeconds) {
|
|
31514
|
+
if (!isObject(attributes)) return void 0;
|
|
31515
|
+
if (spanStartSeconds === void 0) return void 0;
|
|
31516
|
+
const raw = attributes.completionStartTime;
|
|
31517
|
+
const completionStart = raw instanceof Date || typeof raw === "string" || typeof raw === "number" ? epochSeconds(raw) : void 0;
|
|
31518
|
+
if (completionStart === void 0) return void 0;
|
|
31519
|
+
const ttft = completionStart - spanStartSeconds;
|
|
31520
|
+
return Number.isFinite(ttft) && ttft >= 0 ? ttft : void 0;
|
|
31521
|
+
}
|
|
30769
31522
|
function buildMetadata(exported) {
|
|
30770
31523
|
const out = {};
|
|
30771
31524
|
if (exported.entityId !== void 0) out.entity_id = exported.entityId;
|
|
@@ -30835,7 +31588,13 @@ var BraintrustObservabilityExporter = class {
|
|
|
30835
31588
|
const args = {
|
|
30836
31589
|
name: exported.name,
|
|
30837
31590
|
spanAttributes: { type: spanTypeFor(exported.type) },
|
|
30838
|
-
startTime: epochSeconds(exported.startTime)
|
|
31591
|
+
startTime: epochSeconds(exported.startTime),
|
|
31592
|
+
// Use the Mastra span id as the Braintrust row id so that
|
|
31593
|
+
// `logFeedback({ id: <mastra span id> })` (and Mastra's score events)
|
|
31594
|
+
// attach to the right row. Without this, `SpanImpl` auto-generates a
|
|
31595
|
+
// row id (`this._id = eventId ?? idGenerator.getSpanId()`) that no
|
|
31596
|
+
// external caller could know.
|
|
31597
|
+
event: { id: exported.id }
|
|
30839
31598
|
};
|
|
30840
31599
|
const parentRecord = exported.parentSpanId ? this.spans.get(exported.parentSpanId) : void 0;
|
|
30841
31600
|
if (!this.capturedParent) {
|
|
@@ -30884,8 +31643,15 @@ var BraintrustObservabilityExporter = class {
|
|
|
30884
31643
|
event.metadata = metadata;
|
|
30885
31644
|
}
|
|
30886
31645
|
const metrics = modelMetrics(exported.attributes);
|
|
30887
|
-
|
|
30888
|
-
|
|
31646
|
+
const ttft = timeToFirstTokenSeconds(
|
|
31647
|
+
exported.attributes,
|
|
31648
|
+
epochSeconds(exported.startTime)
|
|
31649
|
+
);
|
|
31650
|
+
if (metrics || ttft !== void 0) {
|
|
31651
|
+
event.metrics = {
|
|
31652
|
+
...metrics ?? {},
|
|
31653
|
+
...ttft !== void 0 ? { time_to_first_token: ttft } : {}
|
|
31654
|
+
};
|
|
30889
31655
|
}
|
|
30890
31656
|
if (Object.keys(event).length > 0) {
|
|
30891
31657
|
record.span.log(event);
|
|
@@ -33607,8 +34373,8 @@ function makeCheckAuthorized(allowedOrgName) {
|
|
|
33607
34373
|
return next(createError(400, "Missing x-bt-org-name header"));
|
|
33608
34374
|
}
|
|
33609
34375
|
if (allowedOrgName && allowedOrgName !== orgName) {
|
|
33610
|
-
const
|
|
33611
|
-
return next(createError(403,
|
|
34376
|
+
const errorMessage2 = `Org '${orgName}' is not allowed. Only org '${allowedOrgName}' is allowed.`;
|
|
34377
|
+
return next(createError(403, errorMessage2));
|
|
33612
34378
|
}
|
|
33613
34379
|
const state = await cachedLogin({
|
|
33614
34380
|
apiKey: req.ctx?.token,
|