braintrust 3.28.0 → 3.30.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 +1 -1
- package/dev/dist/index.d.mts +356 -7
- package/dev/dist/index.d.ts +356 -7
- package/dev/dist/index.js +2679 -1828
- package/dev/dist/index.mjs +1862 -1011
- package/dist/apply-auto-instrumentation.js +298 -265
- package/dist/apply-auto-instrumentation.mjs +85 -52
- package/dist/auto-instrumentations/bundler/esbuild.cjs +56 -6
- package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
- package/dist/auto-instrumentations/bundler/next.cjs +56 -6
- package/dist/auto-instrumentations/bundler/next.mjs +3 -3
- package/dist/auto-instrumentations/bundler/rollup.cjs +56 -6
- package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
- package/dist/auto-instrumentations/bundler/vite.cjs +56 -6
- package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
- package/dist/auto-instrumentations/bundler/webpack-loader.cjs +56 -6
- package/dist/auto-instrumentations/bundler/webpack.cjs +56 -6
- package/dist/auto-instrumentations/bundler/webpack.mjs +3 -3
- package/dist/auto-instrumentations/{chunk-26PKVUKB.mjs → chunk-LW4HDHXT.mjs} +12 -4
- package/dist/auto-instrumentations/{chunk-HD35AM3M.mjs → chunk-OXINGIEZ.mjs} +1 -1
- package/dist/auto-instrumentations/{chunk-NP7V4XB2.mjs → chunk-U64OYU4Q.mjs} +45 -3
- package/dist/auto-instrumentations/hook.mjs +967 -136
- package/dist/auto-instrumentations/index.cjs +45 -3
- package/dist/auto-instrumentations/index.mjs +1 -1
- package/dist/browser.d.mts +893 -24
- package/dist/browser.d.ts +893 -24
- package/dist/browser.js +2795 -1136
- package/dist/browser.mjs +2795 -1136
- package/dist/{chunk-BBE7SNRV.js → chunk-2XDW3UCG.js} +155 -23
- package/dist/{chunk-UPFNQCGB.mjs → chunk-BU6SM54N.mjs} +1830 -1045
- package/dist/{chunk-ZHUHZWFY.mjs → chunk-N3JKQ3D3.mjs} +152 -20
- package/dist/{chunk-OBBWQW6K.js → chunk-TWCDSYJN.js} +2890 -2105
- package/dist/cli.js +5976 -1348
- package/dist/edge-light.d.mts +1 -1
- package/dist/edge-light.d.ts +1 -1
- package/dist/edge-light.js +2795 -1136
- package/dist/edge-light.mjs +2795 -1136
- package/dist/index.d.mts +893 -24
- package/dist/index.d.ts +893 -24
- package/dist/index.js +1448 -699
- package/dist/index.mjs +848 -99
- package/dist/instrumentation/index.d.mts +563 -9
- package/dist/instrumentation/index.d.ts +563 -9
- package/dist/instrumentation/index.js +2794 -989
- package/dist/instrumentation/index.mjs +2794 -989
- 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 +2795 -1136
- package/dist/workerd.mjs +2795 -1136
- package/package.json +1 -1
- package/util/dist/index.d.mts +42 -0
- package/util/dist/index.d.ts +42 -0
package/dev/dist/index.mjs
CHANGED
|
@@ -664,8 +664,6 @@ function newGlobalTracingChannel(nameOrChannels) {
|
|
|
664
664
|
var DefaultAsyncLocalStorage = class {
|
|
665
665
|
constructor() {
|
|
666
666
|
}
|
|
667
|
-
enterWith(_) {
|
|
668
|
-
}
|
|
669
667
|
run(_, callback) {
|
|
670
668
|
return callback();
|
|
671
669
|
}
|
|
@@ -2777,7 +2775,9 @@ var AclObjectType = z6.union([
|
|
|
2777
2775
|
"project_log",
|
|
2778
2776
|
"org_project",
|
|
2779
2777
|
"org_audit_logs",
|
|
2780
|
-
"project_group"
|
|
2778
|
+
"project_group",
|
|
2779
|
+
"ai_secret",
|
|
2780
|
+
"org_ai_secret"
|
|
2781
2781
|
]),
|
|
2782
2782
|
z6.null()
|
|
2783
2783
|
]);
|
|
@@ -3610,7 +3610,7 @@ var PromptParserNullish = z6.union([
|
|
|
3610
3610
|
}),
|
|
3611
3611
|
z6.null()
|
|
3612
3612
|
]);
|
|
3613
|
-
var
|
|
3613
|
+
var PreprocessorId = z6.union([
|
|
3614
3614
|
z6.object({
|
|
3615
3615
|
type: z6.literal("function"),
|
|
3616
3616
|
id: z6.string(),
|
|
@@ -3621,6 +3621,7 @@ var PreprocessorSavedFunctionId = z6.union([
|
|
|
3621
3621
|
name: z6.string(),
|
|
3622
3622
|
function_type: z6.literal("preprocessor").optional().default("preprocessor")
|
|
3623
3623
|
}),
|
|
3624
|
+
z6.object({ type: z6.literal("inline"), code: z6.string().min(1) }),
|
|
3624
3625
|
z6.null()
|
|
3625
3626
|
]);
|
|
3626
3627
|
var PromptDataNullish = z6.union([
|
|
@@ -3628,7 +3629,7 @@ var PromptDataNullish = z6.union([
|
|
|
3628
3629
|
prompt: PromptBlockDataNullish,
|
|
3629
3630
|
options: PromptOptionsNullish,
|
|
3630
3631
|
parser: PromptParserNullish,
|
|
3631
|
-
preprocessor:
|
|
3632
|
+
preprocessor: PreprocessorId,
|
|
3632
3633
|
tool_functions: z6.union([z6.array(SavedFunctionId), z6.null()]),
|
|
3633
3634
|
template_format: z6.union([
|
|
3634
3635
|
z6.enum(["mustache", "nunjucks", "none"]),
|
|
@@ -3830,7 +3831,7 @@ var PromptData = z6.object({
|
|
|
3830
3831
|
prompt: PromptBlockDataNullish,
|
|
3831
3832
|
options: PromptOptionsNullish,
|
|
3832
3833
|
parser: PromptParserNullish,
|
|
3833
|
-
preprocessor:
|
|
3834
|
+
preprocessor: PreprocessorId,
|
|
3834
3835
|
tool_functions: z6.union([z6.array(SavedFunctionId), z6.null()]),
|
|
3835
3836
|
template_format: z6.union([
|
|
3836
3837
|
z6.enum(["mustache", "nunjucks", "none"]),
|
|
@@ -4774,6 +4775,7 @@ var View = z6.object({
|
|
|
4774
4775
|
]),
|
|
4775
4776
|
name: z6.string(),
|
|
4776
4777
|
description: z6.union([z6.string(), z6.null()]).optional(),
|
|
4778
|
+
starred: z6.boolean().optional(),
|
|
4777
4779
|
created: z6.union([z6.string(), z6.null()]).optional(),
|
|
4778
4780
|
updated_at: z6.union([z6.string(), z6.null()]).optional(),
|
|
4779
4781
|
view_data: ViewData.optional(),
|
|
@@ -5477,44 +5479,72 @@ function createCacheLayers({
|
|
|
5477
5479
|
}
|
|
5478
5480
|
|
|
5479
5481
|
// src/prompt-cache/prompt-cache.ts
|
|
5480
|
-
function createCacheKey(key) {
|
|
5482
|
+
function createCacheKey(key, namespace) {
|
|
5483
|
+
let cacheKey;
|
|
5481
5484
|
if (key.id) {
|
|
5482
|
-
|
|
5483
|
-
}
|
|
5484
|
-
|
|
5485
|
-
|
|
5486
|
-
|
|
5487
|
-
|
|
5488
|
-
|
|
5489
|
-
|
|
5485
|
+
cacheKey = `id:${key.id}`;
|
|
5486
|
+
} else {
|
|
5487
|
+
const prefix = key.projectId ?? key.projectName;
|
|
5488
|
+
if (!prefix) {
|
|
5489
|
+
throw new Error("Either projectId or projectName must be provided");
|
|
5490
|
+
}
|
|
5491
|
+
if (!key.slug) {
|
|
5492
|
+
throw new Error("Slug must be provided when not using ID");
|
|
5493
|
+
}
|
|
5494
|
+
cacheKey = `${prefix}:${key.slug}:${key.version ?? "latest"}`;
|
|
5490
5495
|
}
|
|
5491
|
-
return `${
|
|
5496
|
+
return namespace === void 0 ? cacheKey : `${namespace.length}:${namespace}:${cacheKey}`;
|
|
5492
5497
|
}
|
|
5493
|
-
var PromptCache = class {
|
|
5498
|
+
var PromptCache = class _PromptCache {
|
|
5494
5499
|
memoryCache;
|
|
5495
5500
|
diskCache;
|
|
5501
|
+
namespace;
|
|
5502
|
+
expectedResolvedOrgIdentity;
|
|
5496
5503
|
constructor(options) {
|
|
5497
5504
|
this.memoryCache = options.memoryCache;
|
|
5498
5505
|
this.diskCache = options.diskCache;
|
|
5506
|
+
this.namespace = options.namespace;
|
|
5507
|
+
this.expectedResolvedOrgIdentity = options.expectedResolvedOrgIdentity;
|
|
5508
|
+
}
|
|
5509
|
+
/**
|
|
5510
|
+
* Returns a cache view that shares the same storage layers but isolates all
|
|
5511
|
+
* entries under the provided namespace.
|
|
5512
|
+
*/
|
|
5513
|
+
withNamespace(namespace, expectedResolvedOrgIdentity) {
|
|
5514
|
+
return new _PromptCache({
|
|
5515
|
+
memoryCache: this.memoryCache,
|
|
5516
|
+
diskCache: this.diskCache,
|
|
5517
|
+
namespace,
|
|
5518
|
+
expectedResolvedOrgIdentity
|
|
5519
|
+
});
|
|
5499
5520
|
}
|
|
5500
5521
|
/**
|
|
5501
5522
|
* Retrieves a prompt from the cache.
|
|
5502
5523
|
* First checks the in-memory LRU cache, then falls back to checking the disk cache if available.
|
|
5503
5524
|
*/
|
|
5504
5525
|
async get(key) {
|
|
5505
|
-
const cacheKey = createCacheKey(key);
|
|
5526
|
+
const cacheKey = createCacheKey(key, this.namespace);
|
|
5506
5527
|
if (this.memoryCache) {
|
|
5507
|
-
const
|
|
5508
|
-
if (
|
|
5509
|
-
return
|
|
5528
|
+
const memoryEntry = this.memoryCache.get(cacheKey);
|
|
5529
|
+
if (memoryEntry !== void 0 && (this.expectedResolvedOrgIdentity === void 0 || memoryEntry.resolvedOrgIdentity === this.expectedResolvedOrgIdentity)) {
|
|
5530
|
+
return memoryEntry.value;
|
|
5510
5531
|
}
|
|
5511
5532
|
}
|
|
5512
5533
|
if (this.diskCache) {
|
|
5513
|
-
const
|
|
5514
|
-
if (!
|
|
5534
|
+
const diskEntry = await this.diskCache.get(cacheKey);
|
|
5535
|
+
if (!diskEntry || this.expectedResolvedOrgIdentity !== void 0 && diskEntry.resolvedOrgIdentity !== this.expectedResolvedOrgIdentity) {
|
|
5515
5536
|
return void 0;
|
|
5516
5537
|
}
|
|
5517
|
-
|
|
5538
|
+
const serializedPrompt = diskEntry.value;
|
|
5539
|
+
const diskPrompt = new Prompt2(
|
|
5540
|
+
serializedPrompt.metadata,
|
|
5541
|
+
serializedPrompt.defaults,
|
|
5542
|
+
serializedPrompt.noTrace
|
|
5543
|
+
);
|
|
5544
|
+
this.memoryCache?.set(cacheKey, {
|
|
5545
|
+
value: diskPrompt,
|
|
5546
|
+
resolvedOrgIdentity: diskEntry.resolvedOrgIdentity
|
|
5547
|
+
});
|
|
5518
5548
|
return diskPrompt;
|
|
5519
5549
|
}
|
|
5520
5550
|
return void 0;
|
|
@@ -5528,58 +5558,91 @@ var PromptCache = class {
|
|
|
5528
5558
|
* @throws If there is an error writing to the disk cache.
|
|
5529
5559
|
*/
|
|
5530
5560
|
async set(key, value) {
|
|
5531
|
-
const cacheKey = createCacheKey(key);
|
|
5532
|
-
|
|
5561
|
+
const cacheKey = createCacheKey(key, this.namespace);
|
|
5562
|
+
const memoryEntry = {
|
|
5563
|
+
value,
|
|
5564
|
+
resolvedOrgIdentity: this.expectedResolvedOrgIdentity
|
|
5565
|
+
};
|
|
5566
|
+
this.memoryCache?.set(cacheKey, memoryEntry);
|
|
5533
5567
|
if (this.diskCache) {
|
|
5534
|
-
await this.diskCache.set(cacheKey,
|
|
5568
|
+
await this.diskCache.set(cacheKey, {
|
|
5569
|
+
value: value._internalSerializeForCache(),
|
|
5570
|
+
resolvedOrgIdentity: this.expectedResolvedOrgIdentity
|
|
5571
|
+
});
|
|
5535
5572
|
}
|
|
5536
5573
|
}
|
|
5537
5574
|
};
|
|
5538
5575
|
|
|
5539
5576
|
// src/prompt-cache/parameters-cache.ts
|
|
5540
|
-
function createCacheKey2(key) {
|
|
5577
|
+
function createCacheKey2(key, namespace) {
|
|
5578
|
+
let cacheKey;
|
|
5541
5579
|
if (key.id) {
|
|
5542
|
-
|
|
5543
|
-
}
|
|
5544
|
-
|
|
5545
|
-
|
|
5546
|
-
|
|
5547
|
-
|
|
5548
|
-
|
|
5549
|
-
|
|
5580
|
+
cacheKey = `parameters:id:${key.id}`;
|
|
5581
|
+
} else {
|
|
5582
|
+
const prefix = key.projectId ?? key.projectName;
|
|
5583
|
+
if (!prefix) {
|
|
5584
|
+
throw new Error("Either projectId or projectName must be provided");
|
|
5585
|
+
}
|
|
5586
|
+
if (!key.slug) {
|
|
5587
|
+
throw new Error("Slug must be provided when not using ID");
|
|
5588
|
+
}
|
|
5589
|
+
cacheKey = `parameters:${prefix}:${key.slug}:${key.version ?? "latest"}`;
|
|
5550
5590
|
}
|
|
5551
|
-
return
|
|
5591
|
+
return namespace === void 0 ? cacheKey : `${namespace.length}:${namespace}:${cacheKey}`;
|
|
5552
5592
|
}
|
|
5553
|
-
var ParametersCache = class {
|
|
5593
|
+
var ParametersCache = class _ParametersCache {
|
|
5554
5594
|
memoryCache;
|
|
5555
5595
|
diskCache;
|
|
5596
|
+
namespace;
|
|
5597
|
+
expectedResolvedOrgIdentity;
|
|
5556
5598
|
constructor(options) {
|
|
5557
5599
|
this.memoryCache = options.memoryCache;
|
|
5558
5600
|
this.diskCache = options.diskCache;
|
|
5601
|
+
this.namespace = options.namespace;
|
|
5602
|
+
this.expectedResolvedOrgIdentity = options.expectedResolvedOrgIdentity;
|
|
5603
|
+
}
|
|
5604
|
+
withNamespace(namespace, expectedResolvedOrgIdentity) {
|
|
5605
|
+
return new _ParametersCache({
|
|
5606
|
+
memoryCache: this.memoryCache,
|
|
5607
|
+
diskCache: this.diskCache,
|
|
5608
|
+
namespace,
|
|
5609
|
+
expectedResolvedOrgIdentity
|
|
5610
|
+
});
|
|
5559
5611
|
}
|
|
5560
5612
|
async get(key) {
|
|
5561
|
-
const cacheKey = createCacheKey2(key);
|
|
5613
|
+
const cacheKey = createCacheKey2(key, this.namespace);
|
|
5562
5614
|
if (this.memoryCache) {
|
|
5563
|
-
const
|
|
5564
|
-
if (
|
|
5565
|
-
return
|
|
5615
|
+
const memoryEntry = this.memoryCache.get(cacheKey);
|
|
5616
|
+
if (memoryEntry !== void 0 && (this.expectedResolvedOrgIdentity === void 0 || memoryEntry.resolvedOrgIdentity === this.expectedResolvedOrgIdentity)) {
|
|
5617
|
+
return memoryEntry.value;
|
|
5566
5618
|
}
|
|
5567
5619
|
}
|
|
5568
5620
|
if (this.diskCache) {
|
|
5569
|
-
const
|
|
5570
|
-
if (!
|
|
5621
|
+
const diskEntry = await this.diskCache.get(cacheKey);
|
|
5622
|
+
if (!diskEntry || this.expectedResolvedOrgIdentity !== void 0 && diskEntry.resolvedOrgIdentity !== this.expectedResolvedOrgIdentity) {
|
|
5571
5623
|
return void 0;
|
|
5572
5624
|
}
|
|
5573
|
-
|
|
5574
|
-
|
|
5625
|
+
const diskParameters = new RemoteEvalParameters(diskEntry.value.metadata);
|
|
5626
|
+
this.memoryCache?.set(cacheKey, {
|
|
5627
|
+
value: diskParameters,
|
|
5628
|
+
resolvedOrgIdentity: diskEntry.resolvedOrgIdentity
|
|
5629
|
+
});
|
|
5630
|
+
return diskParameters;
|
|
5575
5631
|
}
|
|
5576
5632
|
return void 0;
|
|
5577
5633
|
}
|
|
5578
5634
|
async set(key, value) {
|
|
5579
|
-
const cacheKey = createCacheKey2(key);
|
|
5580
|
-
|
|
5635
|
+
const cacheKey = createCacheKey2(key, this.namespace);
|
|
5636
|
+
const memoryEntry = {
|
|
5637
|
+
value,
|
|
5638
|
+
resolvedOrgIdentity: this.expectedResolvedOrgIdentity
|
|
5639
|
+
};
|
|
5640
|
+
this.memoryCache?.set(cacheKey, memoryEntry);
|
|
5581
5641
|
if (this.diskCache) {
|
|
5582
|
-
await this.diskCache.set(cacheKey,
|
|
5642
|
+
await this.diskCache.set(cacheKey, {
|
|
5643
|
+
value: value._internalSerializeForCache(),
|
|
5644
|
+
resolvedOrgIdentity: this.expectedResolvedOrgIdentity
|
|
5645
|
+
});
|
|
5583
5646
|
}
|
|
5584
5647
|
}
|
|
5585
5648
|
};
|
|
@@ -5883,6 +5946,7 @@ var INSTRUMENTATION_NAMES = {
|
|
|
5883
5946
|
CLOUDFLARE_THINK: "cloudflare-think",
|
|
5884
5947
|
COHERE: "cohere",
|
|
5885
5948
|
CURSOR_SDK: "cursor-sdk",
|
|
5949
|
+
DEEPSEEK_HARNESS: "deepseek-harness",
|
|
5886
5950
|
EVE: "eve",
|
|
5887
5951
|
FLUE: "flue",
|
|
5888
5952
|
GENKIT: "genkit",
|
|
@@ -5908,7 +5972,7 @@ var INSTRUMENTATION_NAMES = {
|
|
|
5908
5972
|
var INTERNAL_SPAN_INSTRUMENTATION_NAME = /* @__PURE__ */ Symbol.for(
|
|
5909
5973
|
"braintrust.spanInstrumentationName"
|
|
5910
5974
|
);
|
|
5911
|
-
var SDK_VERSION = true ? "3.
|
|
5975
|
+
var SDK_VERSION = true ? "3.30.0" : "0.0.0";
|
|
5912
5976
|
function withSpanInstrumentationName(args, instrumentationName) {
|
|
5913
5977
|
return {
|
|
5914
5978
|
...args,
|
|
@@ -6027,6 +6091,16 @@ var datasetSnapshotRegisterResponseSchema = z8.object({
|
|
|
6027
6091
|
dataset_snapshot: DatasetSnapshot,
|
|
6028
6092
|
found_existing: z8.boolean().optional()
|
|
6029
6093
|
});
|
|
6094
|
+
var datasetObjectInfoSchema = z8.object({
|
|
6095
|
+
object_id: z8.string(),
|
|
6096
|
+
object_name: z8.string(),
|
|
6097
|
+
parent_cols: z8.object({
|
|
6098
|
+
project: z8.object({
|
|
6099
|
+
id: z8.string(),
|
|
6100
|
+
name: z8.string()
|
|
6101
|
+
})
|
|
6102
|
+
})
|
|
6103
|
+
});
|
|
6030
6104
|
var datasetRestorePreviewResultSchema = z8.object({
|
|
6031
6105
|
rows_to_restore: z8.number(),
|
|
6032
6106
|
rows_to_delete: z8.number()
|
|
@@ -6240,12 +6314,53 @@ var loginSchema = z8.strictObject({
|
|
|
6240
6314
|
});
|
|
6241
6315
|
var stateNonce = 0;
|
|
6242
6316
|
var V1_PROXY_SUFFIX = "/v1/proxy";
|
|
6317
|
+
var LOADER_LOGIN_CACHE_MAX = 16;
|
|
6243
6318
|
function normalizeProxyConnUrl(proxyUrl) {
|
|
6244
6319
|
return proxyUrl.endsWith(V1_PROXY_SUFFIX) ? proxyUrl.slice(0, proxyUrl.length - V1_PROXY_SUFFIX.length) : proxyUrl;
|
|
6245
6320
|
}
|
|
6246
6321
|
var BraintrustState = class _BraintrustState {
|
|
6322
|
+
id;
|
|
6323
|
+
currentExperiment;
|
|
6324
|
+
// Note: the value of IsAsyncFlush doesn't really matter here, since we
|
|
6325
|
+
// (safely) dynamically cast it whenever retrieving the logger.
|
|
6326
|
+
currentLogger;
|
|
6327
|
+
currentParent;
|
|
6328
|
+
currentSpan;
|
|
6329
|
+
// Any time we re-log in, we directly update the apiConn inside the logger.
|
|
6330
|
+
// This is preferable to replacing the whole logger, which would create the
|
|
6331
|
+
// possibility of multiple loggers floating around, which may not log in a
|
|
6332
|
+
// deterministic order.
|
|
6333
|
+
_bgLogger;
|
|
6334
|
+
_overrideBgLogger = null;
|
|
6335
|
+
appUrl = null;
|
|
6336
|
+
appPublicUrl = null;
|
|
6337
|
+
loginToken = null;
|
|
6338
|
+
orgId = null;
|
|
6339
|
+
orgName = null;
|
|
6340
|
+
apiUrl = null;
|
|
6341
|
+
proxyUrl = null;
|
|
6342
|
+
loggedIn = false;
|
|
6343
|
+
gitMetadataSettings;
|
|
6344
|
+
debugLogLevel;
|
|
6345
|
+
debugLogLevelConfigured = false;
|
|
6346
|
+
fetch = globalThis.fetch;
|
|
6347
|
+
_appConn = null;
|
|
6348
|
+
_apiConn = null;
|
|
6349
|
+
_proxyConn = null;
|
|
6350
|
+
promptCache;
|
|
6351
|
+
parametersCache;
|
|
6352
|
+
spanCache;
|
|
6353
|
+
_idGenerator = null;
|
|
6354
|
+
_contextManager = null;
|
|
6355
|
+
_otelFlushCallback = null;
|
|
6356
|
+
spanOriginEnvironment;
|
|
6357
|
+
traceContextSigningSecret;
|
|
6358
|
+
loaderLoginCache = /* @__PURE__ */ new WeakMap();
|
|
6359
|
+
loginParams;
|
|
6360
|
+
activeLoginOrgNameSelector;
|
|
6247
6361
|
constructor(loginParams) {
|
|
6248
|
-
this.loginParams = loginParams;
|
|
6362
|
+
this.loginParams = { ...loginParams };
|
|
6363
|
+
this.activeLoginOrgNameSelector = loginParams.orgName ?? isomorph_default.getEnv("BRAINTRUST_ORG_NAME");
|
|
6249
6364
|
this.id = `${(/* @__PURE__ */ new Date()).toLocaleString()}-${stateNonce++}`;
|
|
6250
6365
|
this.currentExperiment = void 0;
|
|
6251
6366
|
this.currentLogger = void 0;
|
|
@@ -6282,12 +6397,14 @@ var BraintrustState = class _BraintrustState {
|
|
|
6282
6397
|
const {
|
|
6283
6398
|
memoryCache: parametersMemoryCache,
|
|
6284
6399
|
diskCache: parametersDiskCache
|
|
6285
|
-
} = createCacheLayers(
|
|
6286
|
-
|
|
6287
|
-
|
|
6288
|
-
|
|
6289
|
-
|
|
6290
|
-
|
|
6400
|
+
} = createCacheLayers(
|
|
6401
|
+
{
|
|
6402
|
+
memoryMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_MEMORY_MAX",
|
|
6403
|
+
diskCacheDirEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DIR",
|
|
6404
|
+
diskMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DISK_MAX",
|
|
6405
|
+
getDefaultDiskCacheDir: () => `${isomorph_default.getEnv("HOME") ?? isomorph_default.homedir()}/.braintrust/parameters_cache`
|
|
6406
|
+
}
|
|
6407
|
+
);
|
|
6291
6408
|
this.parametersCache = new ParametersCache({
|
|
6292
6409
|
memoryCache: parametersMemoryCache,
|
|
6293
6410
|
diskCache: parametersDiskCache
|
|
@@ -6296,43 +6413,6 @@ var BraintrustState = class _BraintrustState {
|
|
|
6296
6413
|
this.spanOriginEnvironment = detectSpanOriginEnvironment();
|
|
6297
6414
|
this._internalSetTraceContextSigningSecret(loginParams.apiKey);
|
|
6298
6415
|
}
|
|
6299
|
-
loginParams;
|
|
6300
|
-
id;
|
|
6301
|
-
currentExperiment;
|
|
6302
|
-
// Note: the value of IsAsyncFlush doesn't really matter here, since we
|
|
6303
|
-
// (safely) dynamically cast it whenever retrieving the logger.
|
|
6304
|
-
currentLogger;
|
|
6305
|
-
currentParent;
|
|
6306
|
-
currentSpan;
|
|
6307
|
-
// Any time we re-log in, we directly update the apiConn inside the logger.
|
|
6308
|
-
// This is preferable to replacing the whole logger, which would create the
|
|
6309
|
-
// possibility of multiple loggers floating around, which may not log in a
|
|
6310
|
-
// deterministic order.
|
|
6311
|
-
_bgLogger;
|
|
6312
|
-
_overrideBgLogger = null;
|
|
6313
|
-
appUrl = null;
|
|
6314
|
-
appPublicUrl = null;
|
|
6315
|
-
loginToken = null;
|
|
6316
|
-
orgId = null;
|
|
6317
|
-
orgName = null;
|
|
6318
|
-
apiUrl = null;
|
|
6319
|
-
proxyUrl = null;
|
|
6320
|
-
loggedIn = false;
|
|
6321
|
-
gitMetadataSettings;
|
|
6322
|
-
debugLogLevel;
|
|
6323
|
-
debugLogLevelConfigured = false;
|
|
6324
|
-
fetch = globalThis.fetch;
|
|
6325
|
-
_appConn = null;
|
|
6326
|
-
_apiConn = null;
|
|
6327
|
-
_proxyConn = null;
|
|
6328
|
-
promptCache;
|
|
6329
|
-
parametersCache;
|
|
6330
|
-
spanCache;
|
|
6331
|
-
_idGenerator = null;
|
|
6332
|
-
_contextManager = null;
|
|
6333
|
-
_otelFlushCallback = null;
|
|
6334
|
-
spanOriginEnvironment;
|
|
6335
|
-
traceContextSigningSecret;
|
|
6336
6416
|
/** @internal */
|
|
6337
6417
|
_internalSetTraceContextSigningSecret(secret) {
|
|
6338
6418
|
const normalizedSecret = secret?.trim();
|
|
@@ -6357,6 +6437,101 @@ var BraintrustState = class _BraintrustState {
|
|
|
6357
6437
|
this._appConn = null;
|
|
6358
6438
|
this._apiConn = null;
|
|
6359
6439
|
this._proxyConn = null;
|
|
6440
|
+
this.loaderLoginCache = /* @__PURE__ */ new WeakMap();
|
|
6441
|
+
}
|
|
6442
|
+
/** @internal */
|
|
6443
|
+
async _internalResolveLoaderLoginOptions({
|
|
6444
|
+
apiKey,
|
|
6445
|
+
appUrl,
|
|
6446
|
+
orgName,
|
|
6447
|
+
fetch: fetch2,
|
|
6448
|
+
forceLogin
|
|
6449
|
+
}) {
|
|
6450
|
+
const resolvedAppUrl = appUrl ?? (this.loggedIn ? this.appUrl ?? void 0 : void 0) ?? this.loginParams.appUrl ?? isomorph_default.getEnv("BRAINTRUST_APP_URL") ?? "https://www.braintrust.dev";
|
|
6451
|
+
const resolvedApiKey = apiKey ?? (this.loggedIn ? this.loginToken ?? void 0 : void 0) ?? this.loginParams.apiKey ?? await isomorph_default.getBraintrustApiKey();
|
|
6452
|
+
if (!resolvedApiKey) {
|
|
6453
|
+
throw new Error(
|
|
6454
|
+
"Please specify an api key (e.g. by setting BRAINTRUST_API_KEY)."
|
|
6455
|
+
);
|
|
6456
|
+
}
|
|
6457
|
+
const normalizedApiKey = HTTPConnection.sanitize_token(resolvedApiKey);
|
|
6458
|
+
const usesActiveCredential = this.loggedIn && normalizedApiKey === this.loginToken;
|
|
6459
|
+
const requestedOrgName = orgName ?? (usesActiveCredential ? this.activeLoginOrgNameSelector : void 0) ?? this.loginParams.orgName ?? isomorph_default.getEnv("BRAINTRUST_ORG_NAME");
|
|
6460
|
+
const resolvedOrgName = orgName ?? (usesActiveCredential ? this.orgName ?? void 0 : void 0) ?? requestedOrgName;
|
|
6461
|
+
const resolvedFetch = fetch2 ?? (this.loggedIn ? this.fetch : void 0) ?? this.loginParams.fetch ?? globalThis.fetch;
|
|
6462
|
+
const credentialCacheNamespace = JSON.stringify([
|
|
6463
|
+
"loader-credential",
|
|
6464
|
+
resolvedAppUrl,
|
|
6465
|
+
requestedOrgName,
|
|
6466
|
+
normalizedApiKey
|
|
6467
|
+
]);
|
|
6468
|
+
return {
|
|
6469
|
+
apiKey: normalizedApiKey,
|
|
6470
|
+
appUrl: resolvedAppUrl,
|
|
6471
|
+
orgName: resolvedOrgName,
|
|
6472
|
+
fetch: resolvedFetch,
|
|
6473
|
+
forceLogin,
|
|
6474
|
+
credentialCacheNamespace,
|
|
6475
|
+
existingState: !forceLogin && usesActiveCredential && resolvedAppUrl === this.appUrl && resolvedOrgName === this.orgName && resolvedFetch === this.fetch ? this : void 0
|
|
6476
|
+
};
|
|
6477
|
+
}
|
|
6478
|
+
/** @internal */
|
|
6479
|
+
_internalGetLoaderCacheViews(loginOptions, requestState) {
|
|
6480
|
+
const expectedResolvedOrgIdentity = requestState?.orgId && requestState.appUrl ? JSON.stringify([
|
|
6481
|
+
"loader-org",
|
|
6482
|
+
requestState.appUrl,
|
|
6483
|
+
requestState.orgId
|
|
6484
|
+
]) : void 0;
|
|
6485
|
+
return {
|
|
6486
|
+
promptCache: this.promptCache.withNamespace(
|
|
6487
|
+
loginOptions.credentialCacheNamespace,
|
|
6488
|
+
expectedResolvedOrgIdentity
|
|
6489
|
+
),
|
|
6490
|
+
parametersCache: this.parametersCache.withNamespace(
|
|
6491
|
+
loginOptions.credentialCacheNamespace,
|
|
6492
|
+
expectedResolvedOrgIdentity
|
|
6493
|
+
)
|
|
6494
|
+
};
|
|
6495
|
+
}
|
|
6496
|
+
/** @internal */
|
|
6497
|
+
async _internalGetLoaderState({
|
|
6498
|
+
apiKey,
|
|
6499
|
+
appUrl,
|
|
6500
|
+
orgName,
|
|
6501
|
+
fetch: fetch2,
|
|
6502
|
+
forceLogin,
|
|
6503
|
+
existingState
|
|
6504
|
+
}) {
|
|
6505
|
+
if (existingState) {
|
|
6506
|
+
return existingState;
|
|
6507
|
+
}
|
|
6508
|
+
let cache = this.loaderLoginCache.get(fetch2);
|
|
6509
|
+
if (!cache) {
|
|
6510
|
+
cache = new LRUCache({ max: LOADER_LOGIN_CACHE_MAX });
|
|
6511
|
+
this.loaderLoginCache.set(fetch2, cache);
|
|
6512
|
+
}
|
|
6513
|
+
const cacheKey = JSON.stringify([appUrl, orgName, apiKey]);
|
|
6514
|
+
if (!forceLogin) {
|
|
6515
|
+
const cachedState = cache.get(cacheKey);
|
|
6516
|
+
if (cachedState) {
|
|
6517
|
+
return cachedState;
|
|
6518
|
+
}
|
|
6519
|
+
}
|
|
6520
|
+
const statePromise = loginToLoaderRequestState({
|
|
6521
|
+
orgName,
|
|
6522
|
+
apiKey,
|
|
6523
|
+
appUrl,
|
|
6524
|
+
fetch: fetch2
|
|
6525
|
+
});
|
|
6526
|
+
cache.set(cacheKey, statePromise);
|
|
6527
|
+
try {
|
|
6528
|
+
return await statePromise;
|
|
6529
|
+
} catch (error) {
|
|
6530
|
+
if (cache.get(cacheKey) === statePromise) {
|
|
6531
|
+
cache.delete(cacheKey);
|
|
6532
|
+
}
|
|
6533
|
+
throw error;
|
|
6534
|
+
}
|
|
6360
6535
|
}
|
|
6361
6536
|
resetIdGenState() {
|
|
6362
6537
|
this._idGenerator = null;
|
|
@@ -6405,6 +6580,8 @@ var BraintrustState = class _BraintrustState {
|
|
|
6405
6580
|
this.debugLogLevel = other.debugLogLevel;
|
|
6406
6581
|
this.debugLogLevelConfigured = other.debugLogLevelConfigured;
|
|
6407
6582
|
this.traceContextSigningSecret = other.traceContextSigningSecret;
|
|
6583
|
+
this.fetch = other.fetch;
|
|
6584
|
+
this.activeLoginOrgNameSelector = other.activeLoginOrgNameSelector;
|
|
6408
6585
|
setGlobalDebugLogLevel(
|
|
6409
6586
|
this.debugLogLevelConfigured ? this.debugLogLevel ?? false : void 0
|
|
6410
6587
|
);
|
|
@@ -6612,36 +6789,76 @@ var FailedHTTPResponse = class extends Error {
|
|
|
6612
6789
|
status;
|
|
6613
6790
|
text;
|
|
6614
6791
|
data;
|
|
6615
|
-
|
|
6792
|
+
cause;
|
|
6793
|
+
constructor(status, text, data, cause) {
|
|
6616
6794
|
super(`${status}: ${text} (${data})`);
|
|
6617
6795
|
this.status = status;
|
|
6618
6796
|
this.text = text;
|
|
6619
6797
|
this.data = data;
|
|
6798
|
+
this.cause = cause;
|
|
6799
|
+
}
|
|
6800
|
+
};
|
|
6801
|
+
var HTTPTransportError = class extends Error {
|
|
6802
|
+
cause;
|
|
6803
|
+
constructor(cause) {
|
|
6804
|
+
super(cause instanceof Error ? cause.message : String(cause));
|
|
6805
|
+
this.name = "HTTPTransportError";
|
|
6806
|
+
this.cause = cause;
|
|
6620
6807
|
}
|
|
6621
6808
|
};
|
|
6809
|
+
var httpTransportErrorCauses = /* @__PURE__ */ new WeakSet();
|
|
6810
|
+
function recordHTTPTransportError(error) {
|
|
6811
|
+
if (typeof error === "object" && error !== null || typeof error === "function") {
|
|
6812
|
+
httpTransportErrorCauses.add(error);
|
|
6813
|
+
}
|
|
6814
|
+
}
|
|
6815
|
+
function rethrowHTTPTransportError(error, classifyTransportErrors) {
|
|
6816
|
+
if (classifyTransportErrors) {
|
|
6817
|
+
throw new HTTPTransportError(error);
|
|
6818
|
+
}
|
|
6819
|
+
recordHTTPTransportError(error);
|
|
6820
|
+
throw error;
|
|
6821
|
+
}
|
|
6822
|
+
async function readJSONResponse(response, classifyTransportErrors = false) {
|
|
6823
|
+
let data;
|
|
6824
|
+
try {
|
|
6825
|
+
data = await response.text();
|
|
6826
|
+
} catch (error) {
|
|
6827
|
+
rethrowHTTPTransportError(error, classifyTransportErrors);
|
|
6828
|
+
}
|
|
6829
|
+
return JSON.parse(data);
|
|
6830
|
+
}
|
|
6622
6831
|
async function checkResponse(resp) {
|
|
6623
6832
|
if (resp.ok) {
|
|
6624
6833
|
return resp;
|
|
6625
|
-
}
|
|
6834
|
+
}
|
|
6835
|
+
let data;
|
|
6836
|
+
try {
|
|
6837
|
+
data = await resp.text();
|
|
6838
|
+
} catch (error) {
|
|
6626
6839
|
throw new FailedHTTPResponse(
|
|
6627
6840
|
resp.status,
|
|
6628
6841
|
resp.statusText,
|
|
6629
|
-
|
|
6842
|
+
"Unable to read response body",
|
|
6843
|
+
error
|
|
6630
6844
|
);
|
|
6631
6845
|
}
|
|
6846
|
+
throw new FailedHTTPResponse(resp.status, resp.statusText, data);
|
|
6632
6847
|
}
|
|
6633
6848
|
var HTTPConnection = class _HTTPConnection {
|
|
6634
|
-
base_url
|
|
6635
|
-
|
|
6636
|
-
headers;
|
|
6637
|
-
fetch;
|
|
6638
|
-
constructor(base_url, fetch2) {
|
|
6849
|
+
constructor(base_url, fetch2, classifyTransportErrors = false) {
|
|
6850
|
+
this.classifyTransportErrors = classifyTransportErrors;
|
|
6639
6851
|
this.base_url = base_url;
|
|
6640
6852
|
this.token = null;
|
|
6641
6853
|
this.headers = {};
|
|
6642
6854
|
this._reset();
|
|
6643
6855
|
this.fetch = fetch2;
|
|
6644
6856
|
}
|
|
6857
|
+
classifyTransportErrors;
|
|
6858
|
+
base_url;
|
|
6859
|
+
token;
|
|
6860
|
+
headers;
|
|
6861
|
+
fetch;
|
|
6645
6862
|
setFetch(fetch2) {
|
|
6646
6863
|
this.fetch = fetch2;
|
|
6647
6864
|
}
|
|
@@ -6681,9 +6898,9 @@ var HTTPConnection = class _HTTPConnection {
|
|
|
6681
6898
|
).toString();
|
|
6682
6899
|
const this_fetch = this.fetch;
|
|
6683
6900
|
const this_headers = this.headers;
|
|
6684
|
-
|
|
6685
|
-
|
|
6686
|
-
await this_fetch(url.toString(), {
|
|
6901
|
+
let response;
|
|
6902
|
+
try {
|
|
6903
|
+
response = await this_fetch(url.toString(), {
|
|
6687
6904
|
headers: {
|
|
6688
6905
|
Accept: "application/json",
|
|
6689
6906
|
...this_headers,
|
|
@@ -6691,8 +6908,14 @@ var HTTPConnection = class _HTTPConnection {
|
|
|
6691
6908
|
},
|
|
6692
6909
|
keepalive: true,
|
|
6693
6910
|
...rest
|
|
6694
|
-
})
|
|
6695
|
-
)
|
|
6911
|
+
});
|
|
6912
|
+
} catch (error) {
|
|
6913
|
+
if (config?.signal?.aborted) {
|
|
6914
|
+
throw getAbortReason(config.signal);
|
|
6915
|
+
}
|
|
6916
|
+
rethrowHTTPTransportError(error, this.classifyTransportErrors);
|
|
6917
|
+
}
|
|
6918
|
+
return await checkResponse(response);
|
|
6696
6919
|
}
|
|
6697
6920
|
async post(path3, params, config, retries = 0) {
|
|
6698
6921
|
const { headers, ...rest } = config || {};
|
|
@@ -6702,8 +6925,9 @@ var HTTPConnection = class _HTTPConnection {
|
|
|
6702
6925
|
const tries = retries + 1;
|
|
6703
6926
|
for (let i = 0; i < tries; i++) {
|
|
6704
6927
|
try {
|
|
6705
|
-
|
|
6706
|
-
|
|
6928
|
+
let response;
|
|
6929
|
+
try {
|
|
6930
|
+
response = await this_fetch(_urljoin(this_base_url, path3), {
|
|
6707
6931
|
method: "POST",
|
|
6708
6932
|
headers: {
|
|
6709
6933
|
Accept: "application/json",
|
|
@@ -6714,8 +6938,14 @@ var HTTPConnection = class _HTTPConnection {
|
|
|
6714
6938
|
body: typeof params === "string" ? params : params ? JSON.stringify(params) : void 0,
|
|
6715
6939
|
keepalive: true,
|
|
6716
6940
|
...rest
|
|
6717
|
-
})
|
|
6718
|
-
)
|
|
6941
|
+
});
|
|
6942
|
+
} catch (error) {
|
|
6943
|
+
if (config?.signal?.aborted) {
|
|
6944
|
+
throw getAbortReason(config.signal);
|
|
6945
|
+
}
|
|
6946
|
+
rethrowHTTPTransportError(error, this.classifyTransportErrors);
|
|
6947
|
+
}
|
|
6948
|
+
return await checkResponse(response);
|
|
6719
6949
|
} catch (error) {
|
|
6720
6950
|
if (config?.signal?.aborted) {
|
|
6721
6951
|
throw getAbortReason(config.signal);
|
|
@@ -6740,7 +6970,7 @@ var HTTPConnection = class _HTTPConnection {
|
|
|
6740
6970
|
for (let i = 0; i < tries; i++) {
|
|
6741
6971
|
try {
|
|
6742
6972
|
const resp = await this.get(`${object_type}`, args);
|
|
6743
|
-
return await resp.
|
|
6973
|
+
return await readJSONResponse(resp, this.classifyTransportErrors);
|
|
6744
6974
|
} catch (e) {
|
|
6745
6975
|
if (i < tries - 1) {
|
|
6746
6976
|
debugLogger.debug(
|
|
@@ -6763,7 +6993,7 @@ var HTTPConnection = class _HTTPConnection {
|
|
|
6763
6993
|
const resp = await this.post(`${object_type}`, args, {
|
|
6764
6994
|
headers: { "Content-Type": "application/json" }
|
|
6765
6995
|
});
|
|
6766
|
-
return await resp.
|
|
6996
|
+
return await readJSONResponse(resp, this.classifyTransportErrors);
|
|
6767
6997
|
}
|
|
6768
6998
|
// Custom inspect for Node.js console.log
|
|
6769
6999
|
[/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")]() {
|
|
@@ -8583,6 +8813,7 @@ function initDataset(projectOrOptions, optionalOptions) {
|
|
|
8583
8813
|
const {
|
|
8584
8814
|
project,
|
|
8585
8815
|
dataset,
|
|
8816
|
+
datasetId,
|
|
8586
8817
|
description,
|
|
8587
8818
|
version,
|
|
8588
8819
|
snapshotName,
|
|
@@ -8598,6 +8829,11 @@ function initDataset(projectOrOptions, optionalOptions) {
|
|
|
8598
8829
|
state: stateArg,
|
|
8599
8830
|
_internal_btql
|
|
8600
8831
|
} = options;
|
|
8832
|
+
if (datasetId !== void 0 && (description !== void 0 || metadata !== void 0)) {
|
|
8833
|
+
throw new Error(
|
|
8834
|
+
"Cannot specify description or metadata when datasetId is provided"
|
|
8835
|
+
);
|
|
8836
|
+
}
|
|
8601
8837
|
const selection = normalizeDatasetSelection({
|
|
8602
8838
|
version,
|
|
8603
8839
|
environment,
|
|
@@ -8618,6 +8854,35 @@ function initDataset(projectOrOptions, optionalOptions) {
|
|
|
8618
8854
|
fetch: fetch2,
|
|
8619
8855
|
forceLogin
|
|
8620
8856
|
});
|
|
8857
|
+
if (datasetId !== void 0) {
|
|
8858
|
+
const objectInfo = datasetObjectInfoSchema.array().parse(
|
|
8859
|
+
await state.appConn().post_json("api/self/get_object_info", {
|
|
8860
|
+
object_type: "dataset",
|
|
8861
|
+
object_ids: [datasetId]
|
|
8862
|
+
})
|
|
8863
|
+
);
|
|
8864
|
+
if (objectInfo.length === 0) {
|
|
8865
|
+
throw new Error(`Dataset with ID ${datasetId} not found`);
|
|
8866
|
+
}
|
|
8867
|
+
if (objectInfo.length !== 1) {
|
|
8868
|
+
throw new Error(
|
|
8869
|
+
`Expected exactly one dataset with ID ${datasetId}, but found ${objectInfo.length}`
|
|
8870
|
+
);
|
|
8871
|
+
}
|
|
8872
|
+
const datasetInfo = objectInfo[0];
|
|
8873
|
+
return {
|
|
8874
|
+
project: {
|
|
8875
|
+
id: datasetInfo.parent_cols.project.id,
|
|
8876
|
+
name: datasetInfo.parent_cols.project.name,
|
|
8877
|
+
fullInfo: datasetInfo.parent_cols.project
|
|
8878
|
+
},
|
|
8879
|
+
dataset: {
|
|
8880
|
+
id: datasetInfo.object_id,
|
|
8881
|
+
name: datasetInfo.object_name,
|
|
8882
|
+
fullInfo: datasetInfo
|
|
8883
|
+
}
|
|
8884
|
+
};
|
|
8885
|
+
}
|
|
8621
8886
|
const args = {
|
|
8622
8887
|
org_id: state.orgId,
|
|
8623
8888
|
project_name: project,
|
|
@@ -8792,6 +9057,52 @@ async function login(options = {}) {
|
|
|
8792
9057
|
await state.login(options);
|
|
8793
9058
|
return state;
|
|
8794
9059
|
}
|
|
9060
|
+
async function loginToLoaderRequestState({
|
|
9061
|
+
appUrl,
|
|
9062
|
+
apiKey,
|
|
9063
|
+
orgName,
|
|
9064
|
+
fetch: fetch2
|
|
9065
|
+
}) {
|
|
9066
|
+
let orgId;
|
|
9067
|
+
let apiUrl;
|
|
9068
|
+
if (apiKey === TEST_API_KEY) {
|
|
9069
|
+
orgId = "test-org-id";
|
|
9070
|
+
apiUrl = "https://braintrust.dev/fake-api-url";
|
|
9071
|
+
} else {
|
|
9072
|
+
let loginResponse;
|
|
9073
|
+
try {
|
|
9074
|
+
loginResponse = await fetch2(_urljoin(appUrl, `/api/apikey/login`), {
|
|
9075
|
+
method: "POST",
|
|
9076
|
+
headers: {
|
|
9077
|
+
"Content-Type": "application/json",
|
|
9078
|
+
Authorization: `Bearer ${apiKey}`
|
|
9079
|
+
}
|
|
9080
|
+
});
|
|
9081
|
+
} catch (error) {
|
|
9082
|
+
throw new HTTPTransportError(error);
|
|
9083
|
+
}
|
|
9084
|
+
const info = await readJSONResponse(
|
|
9085
|
+
await checkResponse(loginResponse),
|
|
9086
|
+
true
|
|
9087
|
+
);
|
|
9088
|
+
const org = selectLoginOrg(info.org_info, orgName);
|
|
9089
|
+
orgId = org.id;
|
|
9090
|
+
apiUrl = isomorph_default.getEnv("BRAINTRUST_API_URL") ?? org.api_url;
|
|
9091
|
+
if (!apiUrl) {
|
|
9092
|
+
throw new Error(
|
|
9093
|
+
orgName ? `Unable to log into organization '${orgName}'. Are you sure this credential is scoped to the organization?` : "Unable to log into any organization with the provided credential."
|
|
9094
|
+
);
|
|
9095
|
+
}
|
|
9096
|
+
}
|
|
9097
|
+
const apiConnection = new HTTPConnection(apiUrl, fetch2, true);
|
|
9098
|
+
apiConnection.set_token(apiKey);
|
|
9099
|
+
apiConnection.make_long_lived();
|
|
9100
|
+
return {
|
|
9101
|
+
appUrl,
|
|
9102
|
+
orgId,
|
|
9103
|
+
apiConn: () => apiConnection
|
|
9104
|
+
};
|
|
9105
|
+
}
|
|
8795
9106
|
async function loginToState(options = {}) {
|
|
8796
9107
|
const {
|
|
8797
9108
|
appUrl = isomorph_default.getEnv("BRAINTRUST_APP_URL") || "https://www.braintrust.dev",
|
|
@@ -8823,16 +9134,18 @@ async function loginToState(options = {}) {
|
|
|
8823
9134
|
_saveOrgInfo(state, testOrgInfo, testOrgInfo[0].name);
|
|
8824
9135
|
return state;
|
|
8825
9136
|
} else {
|
|
8826
|
-
const
|
|
8827
|
-
|
|
9137
|
+
const loginResponse = await fetch2(
|
|
9138
|
+
_urljoin(state.appUrl, `/api/apikey/login`),
|
|
9139
|
+
{
|
|
8828
9140
|
method: "POST",
|
|
8829
9141
|
headers: {
|
|
8830
9142
|
"Content-Type": "application/json",
|
|
8831
9143
|
Authorization: `Bearer ${apiKey}`
|
|
8832
9144
|
}
|
|
8833
|
-
}
|
|
9145
|
+
}
|
|
8834
9146
|
);
|
|
8835
|
-
const
|
|
9147
|
+
const resp = await checkResponse(loginResponse);
|
|
9148
|
+
const info = await readJSONResponse(resp);
|
|
8836
9149
|
_saveOrgInfo(state, info.org_info, orgName);
|
|
8837
9150
|
if (!state.apiUrl) {
|
|
8838
9151
|
if (orgName) {
|
|
@@ -9174,6 +9487,15 @@ function _internalStartSpanWithInitialMerge(args) {
|
|
|
9174
9487
|
[INITIAL_SPAN_WRITE_AS_MERGE]: true
|
|
9175
9488
|
}).span;
|
|
9176
9489
|
}
|
|
9490
|
+
function _internalStartSpanWithInitialMergeAndParentSpanIds(args) {
|
|
9491
|
+
return startSpanAndIsLogger(
|
|
9492
|
+
{
|
|
9493
|
+
...args,
|
|
9494
|
+
[INITIAL_SPAN_WRITE_AS_MERGE]: true
|
|
9495
|
+
},
|
|
9496
|
+
{ useParentSpanIdsForObjectParent: true }
|
|
9497
|
+
).span;
|
|
9498
|
+
}
|
|
9177
9499
|
function _internalStartSpanWithContext(args, context) {
|
|
9178
9500
|
return startSpanAndIsLogger({
|
|
9179
9501
|
...args,
|
|
@@ -9184,7 +9506,7 @@ async function flush(options) {
|
|
|
9184
9506
|
const state = options?.state ?? _globalState;
|
|
9185
9507
|
return await state.bgLogger().flush();
|
|
9186
9508
|
}
|
|
9187
|
-
function startSpanAndIsLogger(args) {
|
|
9509
|
+
function startSpanAndIsLogger(args, internalOptions) {
|
|
9188
9510
|
const state = args?.state ?? _globalState;
|
|
9189
9511
|
const { parentObject, propagatedState } = getSpanParentObjectAndPropagatedState({
|
|
9190
9512
|
asyncFlush: args?.asyncFlush,
|
|
@@ -9198,7 +9520,7 @@ function startSpanAndIsLogger(args) {
|
|
|
9198
9520
|
) ? {
|
|
9199
9521
|
spanId: parentObject.data.span_id,
|
|
9200
9522
|
rootSpanId: parentObject.data.root_span_id
|
|
9201
|
-
} : void 0;
|
|
9523
|
+
} : internalOptions?.useParentSpanIdsForObjectParent ? args?.parentSpanIds : void 0;
|
|
9202
9524
|
const { parent: _ignoredParent, ...spanArgs } = args ?? {};
|
|
9203
9525
|
const span = new SpanImpl({
|
|
9204
9526
|
state,
|
|
@@ -9234,27 +9556,28 @@ function withCurrent(span, callback, state = void 0) {
|
|
|
9234
9556
|
function withParent(parent, callback, state = void 0) {
|
|
9235
9557
|
return (state ?? _globalState).currentParent.run(parent, () => callback());
|
|
9236
9558
|
}
|
|
9237
|
-
function _saveOrgInfo(state,
|
|
9238
|
-
|
|
9559
|
+
function _saveOrgInfo(state, orgInfo, orgName) {
|
|
9560
|
+
const org = selectLoginOrg(orgInfo, orgName);
|
|
9561
|
+
state.orgId = org.id;
|
|
9562
|
+
state.orgName = org.name;
|
|
9563
|
+
state.apiUrl = isomorph_default.getEnv("BRAINTRUST_API_URL") ?? org.api_url;
|
|
9564
|
+
state.proxyUrl = isomorph_default.getEnv("BRAINTRUST_PROXY_URL") ?? org.proxy_url;
|
|
9565
|
+
state.gitMetadataSettings = org.git_metadata || void 0;
|
|
9566
|
+
}
|
|
9567
|
+
function selectLoginOrg(orgInfo, orgName) {
|
|
9568
|
+
if (orgInfo.length === 0) {
|
|
9239
9569
|
throw new LoginInvalidOrgError(
|
|
9240
9570
|
"This user is not part of any organizations."
|
|
9241
9571
|
);
|
|
9242
9572
|
}
|
|
9243
|
-
for (const org of
|
|
9244
|
-
if (
|
|
9245
|
-
|
|
9246
|
-
state.orgName = org.name;
|
|
9247
|
-
state.apiUrl = isomorph_default.getEnv("BRAINTRUST_API_URL") ?? org.api_url;
|
|
9248
|
-
state.proxyUrl = isomorph_default.getEnv("BRAINTRUST_PROXY_URL") ?? org.proxy_url;
|
|
9249
|
-
state.gitMetadataSettings = org.git_metadata || void 0;
|
|
9250
|
-
break;
|
|
9573
|
+
for (const org of orgInfo) {
|
|
9574
|
+
if (orgName === void 0 || org.name === orgName) {
|
|
9575
|
+
return org;
|
|
9251
9576
|
}
|
|
9252
9577
|
}
|
|
9253
|
-
|
|
9254
|
-
|
|
9255
|
-
|
|
9256
|
-
);
|
|
9257
|
-
}
|
|
9578
|
+
throw new LoginInvalidOrgError(
|
|
9579
|
+
`Organization ${orgName} not found. Must be one of ${orgInfo.map((org) => org.name).join(", ")}`
|
|
9580
|
+
);
|
|
9258
9581
|
}
|
|
9259
9582
|
function validateTags(tags) {
|
|
9260
9583
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -11157,6 +11480,14 @@ var Prompt2 = class _Prompt {
|
|
|
11157
11480
|
static isPrompt(data) {
|
|
11158
11481
|
return typeof data === "object" && data !== null && "__braintrust_prompt_marker" in data;
|
|
11159
11482
|
}
|
|
11483
|
+
/** @internal */
|
|
11484
|
+
_internalSerializeForCache() {
|
|
11485
|
+
return {
|
|
11486
|
+
metadata: this.metadata,
|
|
11487
|
+
defaults: this.defaults,
|
|
11488
|
+
noTrace: this.noTrace
|
|
11489
|
+
};
|
|
11490
|
+
}
|
|
11160
11491
|
static fromPromptData(name, promptData) {
|
|
11161
11492
|
return new _Prompt(
|
|
11162
11493
|
{
|
|
@@ -11197,6 +11528,10 @@ var RemoteEvalParameters = class {
|
|
|
11197
11528
|
get data() {
|
|
11198
11529
|
return this.metadata.function_data.data ?? {};
|
|
11199
11530
|
}
|
|
11531
|
+
/** @internal */
|
|
11532
|
+
_internalSerializeForCache() {
|
|
11533
|
+
return { metadata: this.metadata };
|
|
11534
|
+
}
|
|
11200
11535
|
validate(data) {
|
|
11201
11536
|
if (typeof data !== "object" || data === null) {
|
|
11202
11537
|
return false;
|
|
@@ -11888,56 +12223,14 @@ function suppressionStore() {
|
|
|
11888
12223
|
autoInstrumentationSuppressionStore ??= isomorph_default.newAsyncLocalStorage();
|
|
11889
12224
|
return autoInstrumentationSuppressionStore;
|
|
11890
12225
|
}
|
|
11891
|
-
function currentFrames() {
|
|
11892
|
-
return suppressionStore().getStore()?.frames ?? [];
|
|
11893
|
-
}
|
|
11894
12226
|
function isAutoInstrumentationSuppressed() {
|
|
11895
|
-
|
|
11896
|
-
return frames[frames.length - 1]?.mode === "suppress";
|
|
12227
|
+
return suppressionStore().getStore() === true;
|
|
11897
12228
|
}
|
|
11898
12229
|
function runWithAutoInstrumentationSuppressed(callback) {
|
|
11899
|
-
|
|
11900
|
-
id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
|
|
11901
|
-
mode: "suppress"
|
|
11902
|
-
};
|
|
11903
|
-
return suppressionStore().run(
|
|
11904
|
-
{ frames: [...currentFrames(), frame] },
|
|
11905
|
-
callback
|
|
11906
|
-
);
|
|
12230
|
+
return suppressionStore().run(true, callback);
|
|
11907
12231
|
}
|
|
11908
|
-
function
|
|
11909
|
-
|
|
11910
|
-
if (!startChannel) {
|
|
11911
|
-
return void 0;
|
|
11912
|
-
}
|
|
11913
|
-
const store = suppressionStore();
|
|
11914
|
-
startChannel.bindStore(store, () => ({
|
|
11915
|
-
frames: [
|
|
11916
|
-
...currentFrames(),
|
|
11917
|
-
{
|
|
11918
|
-
id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
|
|
11919
|
-
mode: "suppress"
|
|
11920
|
-
}
|
|
11921
|
-
]
|
|
11922
|
-
}));
|
|
11923
|
-
return () => {
|
|
11924
|
-
startChannel.unbindStore(store);
|
|
11925
|
-
};
|
|
11926
|
-
}
|
|
11927
|
-
function enterAutoInstrumentationAllowed() {
|
|
11928
|
-
const frame = {
|
|
11929
|
-
id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-allow"),
|
|
11930
|
-
mode: "allow"
|
|
11931
|
-
};
|
|
11932
|
-
suppressionStore().enterWith({
|
|
11933
|
-
frames: [...currentFrames(), frame]
|
|
11934
|
-
});
|
|
11935
|
-
return () => {
|
|
11936
|
-
const frames = currentFrames().filter(
|
|
11937
|
-
(candidate) => candidate.id !== frame.id
|
|
11938
|
-
);
|
|
11939
|
-
suppressionStore().enterWith(frames.length > 0 ? { frames } : void 0);
|
|
11940
|
-
};
|
|
12232
|
+
function runWithAutoInstrumentationAllowed(callback) {
|
|
12233
|
+
return suppressionStore().run(void 0, callback);
|
|
11941
12234
|
}
|
|
11942
12235
|
|
|
11943
12236
|
// src/instrumentation/core/channel-tracing.ts
|
|
@@ -12527,6 +12820,131 @@ function unsubscribeAll(unsubscribers) {
|
|
|
12527
12820
|
return [];
|
|
12528
12821
|
}
|
|
12529
12822
|
|
|
12823
|
+
// src/instrumentation/core/channel-definitions.ts
|
|
12824
|
+
function channel(spec) {
|
|
12825
|
+
return spec;
|
|
12826
|
+
}
|
|
12827
|
+
function defineChannels(pkg, channels, options) {
|
|
12828
|
+
const { instrumentationName } = options;
|
|
12829
|
+
return Object.fromEntries(
|
|
12830
|
+
Object.entries(channels).map(([key, spec]) => {
|
|
12831
|
+
const fullChannelName = `orchestrion:${pkg}:${spec.channelName}`;
|
|
12832
|
+
if (spec.kind === "async") {
|
|
12833
|
+
const asyncSpec = spec;
|
|
12834
|
+
const tracingChannel2 = () => isomorph_default.newTracingChannel(
|
|
12835
|
+
fullChannelName
|
|
12836
|
+
);
|
|
12837
|
+
const intercept2 = (interceptor) => {
|
|
12838
|
+
const hook = tracingChannel2();
|
|
12839
|
+
return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
|
|
12840
|
+
};
|
|
12841
|
+
};
|
|
12842
|
+
return [
|
|
12843
|
+
key,
|
|
12844
|
+
{
|
|
12845
|
+
...asyncSpec,
|
|
12846
|
+
instrumentationName,
|
|
12847
|
+
intercept: intercept2,
|
|
12848
|
+
invoke: (target, thisArg, args, additional) => {
|
|
12849
|
+
const hook = tracingChannel2();
|
|
12850
|
+
return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
|
|
12851
|
+
},
|
|
12852
|
+
tracingChannel: tracingChannel2,
|
|
12853
|
+
tracePromise: (fn, context) => tracingChannel2().tracePromise(
|
|
12854
|
+
fn,
|
|
12855
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
12856
|
+
context
|
|
12857
|
+
)
|
|
12858
|
+
}
|
|
12859
|
+
];
|
|
12860
|
+
}
|
|
12861
|
+
const syncSpec = spec;
|
|
12862
|
+
const tracingChannel = () => isomorph_default.newTracingChannel(
|
|
12863
|
+
fullChannelName
|
|
12864
|
+
);
|
|
12865
|
+
const intercept = (interceptor) => {
|
|
12866
|
+
const hook = tracingChannel();
|
|
12867
|
+
return typeof hook.intercept === "function" ? hook.intercept(interceptor) : () => {
|
|
12868
|
+
};
|
|
12869
|
+
};
|
|
12870
|
+
return [
|
|
12871
|
+
key,
|
|
12872
|
+
{
|
|
12873
|
+
...syncSpec,
|
|
12874
|
+
instrumentationName,
|
|
12875
|
+
intercept,
|
|
12876
|
+
invoke: (target, thisArg, args, additional) => {
|
|
12877
|
+
const hook = tracingChannel();
|
|
12878
|
+
return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
|
|
12879
|
+
},
|
|
12880
|
+
tracingChannel,
|
|
12881
|
+
traceSync: (fn, context) => tracingChannel().traceSync(
|
|
12882
|
+
fn,
|
|
12883
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
12884
|
+
context
|
|
12885
|
+
)
|
|
12886
|
+
}
|
|
12887
|
+
];
|
|
12888
|
+
})
|
|
12889
|
+
);
|
|
12890
|
+
}
|
|
12891
|
+
|
|
12892
|
+
// src/instrumentation/plugins/openai-channels.ts
|
|
12893
|
+
var openAIChannels = defineChannels(
|
|
12894
|
+
"openai",
|
|
12895
|
+
{
|
|
12896
|
+
filesCreateTraced: channel({
|
|
12897
|
+
channelName: "files.create-traced",
|
|
12898
|
+
kind: "async"
|
|
12899
|
+
}),
|
|
12900
|
+
batchesRetrieveTraced: channel({
|
|
12901
|
+
channelName: "batches.retrieve-traced",
|
|
12902
|
+
kind: "async"
|
|
12903
|
+
}),
|
|
12904
|
+
batchesCompleteTrace: channel({
|
|
12905
|
+
channelName: "batches.complete-trace",
|
|
12906
|
+
kind: "async"
|
|
12907
|
+
}),
|
|
12908
|
+
chatCompletionsCreate: channel({
|
|
12909
|
+
channelName: "chat.completions.create",
|
|
12910
|
+
kind: "async"
|
|
12911
|
+
}),
|
|
12912
|
+
embeddingsCreate: channel({
|
|
12913
|
+
channelName: "embeddings.create",
|
|
12914
|
+
kind: "async"
|
|
12915
|
+
}),
|
|
12916
|
+
betaChatCompletionsParse: channel({
|
|
12917
|
+
channelName: "beta.chat.completions.parse",
|
|
12918
|
+
kind: "async"
|
|
12919
|
+
}),
|
|
12920
|
+
betaChatCompletionsStream: channel({
|
|
12921
|
+
channelName: "beta.chat.completions.stream",
|
|
12922
|
+
kind: "sync-stream"
|
|
12923
|
+
}),
|
|
12924
|
+
moderationsCreate: channel({
|
|
12925
|
+
channelName: "moderations.create",
|
|
12926
|
+
kind: "async"
|
|
12927
|
+
}),
|
|
12928
|
+
responsesCreate: channel({
|
|
12929
|
+
channelName: "responses.create",
|
|
12930
|
+
kind: "async"
|
|
12931
|
+
}),
|
|
12932
|
+
responsesStream: channel({
|
|
12933
|
+
channelName: "responses.stream",
|
|
12934
|
+
kind: "sync-stream"
|
|
12935
|
+
}),
|
|
12936
|
+
responsesParse: channel({
|
|
12937
|
+
channelName: "responses.parse",
|
|
12938
|
+
kind: "async"
|
|
12939
|
+
}),
|
|
12940
|
+
responsesCompact: channel({
|
|
12941
|
+
channelName: "responses.compact",
|
|
12942
|
+
kind: "async"
|
|
12943
|
+
})
|
|
12944
|
+
},
|
|
12945
|
+
{ instrumentationName: INSTRUMENTATION_NAMES.OPENAI }
|
|
12946
|
+
);
|
|
12947
|
+
|
|
12530
12948
|
// src/wrappers/attachment-utils.ts
|
|
12531
12949
|
function getExtensionFromMediaType(mediaType) {
|
|
12532
12950
|
const extensionMap = {
|
|
@@ -12702,118 +13120,91 @@ function processInputAttachments(input) {
|
|
|
12702
13120
|
return processNode(input);
|
|
12703
13121
|
}
|
|
12704
13122
|
|
|
12705
|
-
// src/instrumentation/
|
|
12706
|
-
|
|
12707
|
-
|
|
12708
|
-
|
|
12709
|
-
|
|
12710
|
-
|
|
12711
|
-
|
|
12712
|
-
|
|
12713
|
-
|
|
12714
|
-
|
|
12715
|
-
|
|
12716
|
-
|
|
12717
|
-
|
|
12718
|
-
|
|
12719
|
-
|
|
12720
|
-
|
|
12721
|
-
|
|
12722
|
-
|
|
12723
|
-
|
|
12724
|
-
|
|
12725
|
-
|
|
12726
|
-
|
|
12727
|
-
...asyncSpec,
|
|
12728
|
-
instrumentationName,
|
|
12729
|
-
intercept: intercept2,
|
|
12730
|
-
invoke: (target, thisArg, args, additional) => {
|
|
12731
|
-
const hook = tracingChannel2();
|
|
12732
|
-
return typeof hook.invoke === "function" ? hook.invoke(target, thisArg, args, additional) : Reflect.apply(target, thisArg, args);
|
|
12733
|
-
},
|
|
12734
|
-
tracingChannel: tracingChannel2,
|
|
12735
|
-
tracePromise: (fn, context) => tracingChannel2().tracePromise(
|
|
12736
|
-
fn,
|
|
12737
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
12738
|
-
context
|
|
12739
|
-
)
|
|
12740
|
-
}
|
|
12741
|
-
];
|
|
13123
|
+
// src/instrumentation/plugins/openai-span-data.ts
|
|
13124
|
+
var OPENAI_METADATA_KEYS = [
|
|
13125
|
+
"model",
|
|
13126
|
+
"temperature",
|
|
13127
|
+
"top_p",
|
|
13128
|
+
"max_tokens",
|
|
13129
|
+
"frequency_penalty",
|
|
13130
|
+
"presence_penalty",
|
|
13131
|
+
"stop",
|
|
13132
|
+
"response_format",
|
|
13133
|
+
"tools",
|
|
13134
|
+
"tool_choice",
|
|
13135
|
+
"parallel_tool_calls",
|
|
13136
|
+
"max_tool_calls"
|
|
13137
|
+
];
|
|
13138
|
+
function batchMetadata(params) {
|
|
13139
|
+
const metadata = { provider: "openai" };
|
|
13140
|
+
for (const key of OPENAI_METADATA_KEYS) {
|
|
13141
|
+
try {
|
|
13142
|
+
const value = Reflect.get(params, key);
|
|
13143
|
+
if (value !== void 0) {
|
|
13144
|
+
metadata[key] = value;
|
|
12742
13145
|
}
|
|
12743
|
-
|
|
12744
|
-
|
|
12745
|
-
|
|
12746
|
-
|
|
12747
|
-
|
|
12748
|
-
|
|
12749
|
-
|
|
12750
|
-
|
|
12751
|
-
|
|
12752
|
-
|
|
12753
|
-
|
|
12754
|
-
|
|
12755
|
-
|
|
12756
|
-
|
|
12757
|
-
|
|
12758
|
-
|
|
12759
|
-
|
|
12760
|
-
|
|
12761
|
-
|
|
12762
|
-
|
|
12763
|
-
|
|
12764
|
-
|
|
12765
|
-
|
|
12766
|
-
|
|
12767
|
-
|
|
12768
|
-
|
|
12769
|
-
|
|
12770
|
-
|
|
12771
|
-
|
|
13146
|
+
} catch {
|
|
13147
|
+
}
|
|
13148
|
+
}
|
|
13149
|
+
return metadata;
|
|
13150
|
+
}
|
|
13151
|
+
function extractOpenAIBatchInput(endpoint, params) {
|
|
13152
|
+
const input = endpoint === "/v1/chat/completions" ? params.messages : params.input;
|
|
13153
|
+
return {
|
|
13154
|
+
input: processInputAttachments(input),
|
|
13155
|
+
metadata: batchMetadata(params)
|
|
13156
|
+
};
|
|
13157
|
+
}
|
|
13158
|
+
function extractOpenAIChatInput(params) {
|
|
13159
|
+
const { messages, ...metadata } = params;
|
|
13160
|
+
return {
|
|
13161
|
+
input: processInputAttachments(messages),
|
|
13162
|
+
metadata: { ...metadata, provider: "openai" }
|
|
13163
|
+
};
|
|
13164
|
+
}
|
|
13165
|
+
function extractOpenAIResponsesInput(params) {
|
|
13166
|
+
const { input, ...metadata } = params;
|
|
13167
|
+
return {
|
|
13168
|
+
input: processInputAttachments(input),
|
|
13169
|
+
metadata: { ...metadata, provider: "openai" }
|
|
13170
|
+
};
|
|
13171
|
+
}
|
|
13172
|
+
function extractOpenAIResponsesMetadata(result) {
|
|
13173
|
+
if (!result) {
|
|
13174
|
+
return void 0;
|
|
13175
|
+
}
|
|
13176
|
+
const { output: _output, usage: _usage, ...metadata } = result;
|
|
13177
|
+
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
13178
|
+
}
|
|
13179
|
+
function processImagesInOutput(output) {
|
|
13180
|
+
if (Array.isArray(output)) {
|
|
13181
|
+
return output.map(processImagesInOutput);
|
|
13182
|
+
}
|
|
13183
|
+
if (isObject(output) && output.type === "image_generation_call" && typeof output.result === "string" && output.result) {
|
|
13184
|
+
const fileExtension = output.output_format || "png";
|
|
13185
|
+
const contentType = `image/${fileExtension}`;
|
|
13186
|
+
const baseFilename = typeof output.revised_prompt === "string" ? output.revised_prompt.slice(0, 50).replace(/[^a-zA-Z0-9]/g, "_") : "generated_image";
|
|
13187
|
+
let binaryString;
|
|
13188
|
+
try {
|
|
13189
|
+
binaryString = atob(output.result);
|
|
13190
|
+
} catch {
|
|
13191
|
+
return output;
|
|
13192
|
+
}
|
|
13193
|
+
const bytes = new Uint8Array(binaryString.length);
|
|
13194
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
13195
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
13196
|
+
}
|
|
13197
|
+
return {
|
|
13198
|
+
...output,
|
|
13199
|
+
result: new Attachment({
|
|
13200
|
+
data: new Blob([bytes], { type: contentType }),
|
|
13201
|
+
filename: `${baseFilename}.${fileExtension}`,
|
|
13202
|
+
contentType
|
|
13203
|
+
})
|
|
13204
|
+
};
|
|
13205
|
+
}
|
|
13206
|
+
return output;
|
|
12772
13207
|
}
|
|
12773
|
-
|
|
12774
|
-
// src/instrumentation/plugins/openai-channels.ts
|
|
12775
|
-
var openAIChannels = defineChannels(
|
|
12776
|
-
"openai",
|
|
12777
|
-
{
|
|
12778
|
-
chatCompletionsCreate: channel({
|
|
12779
|
-
channelName: "chat.completions.create",
|
|
12780
|
-
kind: "async"
|
|
12781
|
-
}),
|
|
12782
|
-
embeddingsCreate: channel({
|
|
12783
|
-
channelName: "embeddings.create",
|
|
12784
|
-
kind: "async"
|
|
12785
|
-
}),
|
|
12786
|
-
betaChatCompletionsParse: channel({
|
|
12787
|
-
channelName: "beta.chat.completions.parse",
|
|
12788
|
-
kind: "async"
|
|
12789
|
-
}),
|
|
12790
|
-
betaChatCompletionsStream: channel({
|
|
12791
|
-
channelName: "beta.chat.completions.stream",
|
|
12792
|
-
kind: "sync-stream"
|
|
12793
|
-
}),
|
|
12794
|
-
moderationsCreate: channel({
|
|
12795
|
-
channelName: "moderations.create",
|
|
12796
|
-
kind: "async"
|
|
12797
|
-
}),
|
|
12798
|
-
responsesCreate: channel({
|
|
12799
|
-
channelName: "responses.create",
|
|
12800
|
-
kind: "async"
|
|
12801
|
-
}),
|
|
12802
|
-
responsesStream: channel({
|
|
12803
|
-
channelName: "responses.stream",
|
|
12804
|
-
kind: "sync-stream"
|
|
12805
|
-
}),
|
|
12806
|
-
responsesParse: channel({
|
|
12807
|
-
channelName: "responses.parse",
|
|
12808
|
-
kind: "async"
|
|
12809
|
-
}),
|
|
12810
|
-
responsesCompact: channel({
|
|
12811
|
-
channelName: "responses.compact",
|
|
12812
|
-
kind: "async"
|
|
12813
|
-
})
|
|
12814
|
-
},
|
|
12815
|
-
{ instrumentationName: INSTRUMENTATION_NAMES.OPENAI }
|
|
12816
|
-
);
|
|
12817
13208
|
|
|
12818
13209
|
// src/openai-utils.ts
|
|
12819
13210
|
var BRAINTRUST_CACHED_STREAM_METRIC = "__braintrust_cached_metric";
|
|
@@ -12870,23 +13261,573 @@ function getCachedMetricFromHeaders(headers) {
|
|
|
12870
13261
|
return parseCachedHeader(headers.get(LEGACY_CACHED_HEADER));
|
|
12871
13262
|
}
|
|
12872
13263
|
|
|
13264
|
+
// src/instrumentation/plugins/openai-batch-instrumentation.ts
|
|
13265
|
+
var SUPPORTED_ENDPOINTS = /* @__PURE__ */ new Set(["/v1/chat/completions", "/v1/responses"]);
|
|
13266
|
+
var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
|
|
13267
|
+
"completed",
|
|
13268
|
+
"failed",
|
|
13269
|
+
"expired",
|
|
13270
|
+
"cancelled"
|
|
13271
|
+
]);
|
|
13272
|
+
var pendingBatchTraces = /* @__PURE__ */ new Map();
|
|
13273
|
+
function read(value, key) {
|
|
13274
|
+
if (!isObject(value)) {
|
|
13275
|
+
return void 0;
|
|
13276
|
+
}
|
|
13277
|
+
try {
|
|
13278
|
+
return Reflect.get(value, key);
|
|
13279
|
+
} catch {
|
|
13280
|
+
return void 0;
|
|
13281
|
+
}
|
|
13282
|
+
}
|
|
13283
|
+
function isBatchRecordIterable(value) {
|
|
13284
|
+
if (value === null || typeof value !== "object" && typeof value !== "function") {
|
|
13285
|
+
return false;
|
|
13286
|
+
}
|
|
13287
|
+
return typeof read(value, Symbol.iterator) === "function" || typeof read(value, Symbol.asyncIterator) === "function";
|
|
13288
|
+
}
|
|
13289
|
+
function validCustomId(value) {
|
|
13290
|
+
return typeof value === "string" && value.length > 0 && value.length <= 64;
|
|
13291
|
+
}
|
|
13292
|
+
function logBatchInstrumentationError(context, error) {
|
|
13293
|
+
debugLogger.debug(`OpenAI Batch instrumentation ${context}:`, error);
|
|
13294
|
+
}
|
|
13295
|
+
async function exportParent(parent) {
|
|
13296
|
+
if ("toStr" in parent && typeof parent.toStr === "function") {
|
|
13297
|
+
return parent.toStr();
|
|
13298
|
+
}
|
|
13299
|
+
if ("export" in parent && typeof parent.export === "function") {
|
|
13300
|
+
return await parent.export();
|
|
13301
|
+
}
|
|
13302
|
+
return void 0;
|
|
13303
|
+
}
|
|
13304
|
+
async function deterministicDigest(namespace, ...parts) {
|
|
13305
|
+
const encoded = new TextEncoder().encode(
|
|
13306
|
+
[namespace, ...parts].map((part) => `${part.length}:${part}`).join("\0")
|
|
13307
|
+
);
|
|
13308
|
+
return new Uint8Array(
|
|
13309
|
+
await globalThis.crypto.subtle.digest("SHA-256", encoded)
|
|
13310
|
+
);
|
|
13311
|
+
}
|
|
13312
|
+
function digestHex(bytes, length) {
|
|
13313
|
+
return Array.from(bytes.slice(0, length)).map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
13314
|
+
}
|
|
13315
|
+
function digestUuid(bytes) {
|
|
13316
|
+
const hex = digestHex(bytes, 16);
|
|
13317
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
13318
|
+
}
|
|
13319
|
+
async function batchSpanIds(inputFileId) {
|
|
13320
|
+
const [row, span, root] = await Promise.all([
|
|
13321
|
+
deterministicDigest("openai:batch:row", inputFileId),
|
|
13322
|
+
deterministicDigest("openai:batch:span", inputFileId),
|
|
13323
|
+
deterministicDigest("openai:batch:root", inputFileId)
|
|
13324
|
+
]);
|
|
13325
|
+
return {
|
|
13326
|
+
rowId: digestUuid(row),
|
|
13327
|
+
spanId: digestHex(span, 8),
|
|
13328
|
+
rootSpanId: digestHex(root, 16)
|
|
13329
|
+
};
|
|
13330
|
+
}
|
|
13331
|
+
async function childSpanIds(inputFileId, customId) {
|
|
13332
|
+
const [row, span] = await Promise.all([
|
|
13333
|
+
deterministicDigest("openai:batch:child:row", inputFileId, customId),
|
|
13334
|
+
deterministicDigest("openai:batch:child:span", inputFileId, customId)
|
|
13335
|
+
]);
|
|
13336
|
+
return { rowId: digestUuid(row), spanId: digestHex(span, 8) };
|
|
13337
|
+
}
|
|
13338
|
+
async function startBatchSpan(context) {
|
|
13339
|
+
const ids = await batchSpanIds(context.inputFileId);
|
|
13340
|
+
const parent = SpanComponentsV4.fromStr(context.parent);
|
|
13341
|
+
const hasParentSpan = Boolean(
|
|
13342
|
+
parent.data.row_id && parent.data.span_id && parent.data.root_span_id
|
|
13343
|
+
);
|
|
13344
|
+
return withCurrent(
|
|
13345
|
+
NOOP_SPAN,
|
|
13346
|
+
() => _internalStartSpanWithInitialMergeAndParentSpanIds(
|
|
13347
|
+
withSpanInstrumentationName(
|
|
13348
|
+
{
|
|
13349
|
+
name: "openai.batch",
|
|
13350
|
+
type: "task" /* TASK */,
|
|
13351
|
+
parent: context.parent,
|
|
13352
|
+
...!hasParentSpan ? {
|
|
13353
|
+
parentSpanIds: {
|
|
13354
|
+
parentSpanIds: [],
|
|
13355
|
+
rootSpanId: ids.rootSpanId
|
|
13356
|
+
}
|
|
13357
|
+
} : {},
|
|
13358
|
+
spanId: ids.spanId,
|
|
13359
|
+
startTime: context.taskStartTime,
|
|
13360
|
+
event: {
|
|
13361
|
+
id: ids.rowId,
|
|
13362
|
+
metadata: {
|
|
13363
|
+
endpoint: context.endpoint,
|
|
13364
|
+
input_file_id: context.inputFileId,
|
|
13365
|
+
provider: "openai"
|
|
13366
|
+
}
|
|
13367
|
+
}
|
|
13368
|
+
},
|
|
13369
|
+
INSTRUMENTATION_NAMES.OPENAI
|
|
13370
|
+
)
|
|
13371
|
+
)
|
|
13372
|
+
);
|
|
13373
|
+
}
|
|
13374
|
+
async function startBatchChild(context, taskParent, input) {
|
|
13375
|
+
const ids = await childSpanIds(context.inputFileId, input.customId);
|
|
13376
|
+
return withCurrent(
|
|
13377
|
+
NOOP_SPAN,
|
|
13378
|
+
() => _internalStartSpanWithInitialMerge(
|
|
13379
|
+
withSpanInstrumentationName(
|
|
13380
|
+
{
|
|
13381
|
+
name: context.endpoint === "/v1/chat/completions" ? "Chat Completion" : "openai.responses.create",
|
|
13382
|
+
type: "llm" /* LLM */,
|
|
13383
|
+
parent: taskParent,
|
|
13384
|
+
spanId: ids.spanId,
|
|
13385
|
+
startTime: context.childStartTime,
|
|
13386
|
+
event: {
|
|
13387
|
+
id: ids.rowId,
|
|
13388
|
+
...input.spanData?.input !== void 0 ? { input: input.spanData.input } : {},
|
|
13389
|
+
metadata: {
|
|
13390
|
+
...input.spanData?.metadata,
|
|
13391
|
+
custom_id: input.customId,
|
|
13392
|
+
provider: "openai"
|
|
13393
|
+
}
|
|
13394
|
+
}
|
|
13395
|
+
},
|
|
13396
|
+
INSTRUMENTATION_NAMES.OPENAI
|
|
13397
|
+
)
|
|
13398
|
+
)
|
|
13399
|
+
);
|
|
13400
|
+
}
|
|
13401
|
+
async function* jsonlRecords(file, onIssue = () => {
|
|
13402
|
+
}) {
|
|
13403
|
+
const resolvedFile = await file;
|
|
13404
|
+
if (typeof resolvedFile === "string") {
|
|
13405
|
+
for (const line of resolvedFile.split("\n")) {
|
|
13406
|
+
if (!line.trim()) {
|
|
13407
|
+
continue;
|
|
13408
|
+
}
|
|
13409
|
+
try {
|
|
13410
|
+
yield JSON.parse(line.replace(/\r$/, ""));
|
|
13411
|
+
} catch (error) {
|
|
13412
|
+
logBatchInstrumentationError("skipped malformed JSONL", error);
|
|
13413
|
+
onIssue(new Error("OpenAI Batch file contains malformed JSONL"));
|
|
13414
|
+
}
|
|
13415
|
+
}
|
|
13416
|
+
return;
|
|
13417
|
+
}
|
|
13418
|
+
const body = read(resolvedFile, "body");
|
|
13419
|
+
const getReader = read(body, "getReader");
|
|
13420
|
+
if (isObject(body) && typeof getReader === "function") {
|
|
13421
|
+
let reader;
|
|
13422
|
+
try {
|
|
13423
|
+
reader = Reflect.apply(getReader, body, []);
|
|
13424
|
+
const decoder = new TextDecoder();
|
|
13425
|
+
let pending = "";
|
|
13426
|
+
while (true) {
|
|
13427
|
+
const readChunk = read(reader, "read");
|
|
13428
|
+
if (typeof readChunk !== "function") {
|
|
13429
|
+
throw new Error("Response body stream has no read method");
|
|
13430
|
+
}
|
|
13431
|
+
const chunk = await Reflect.apply(readChunk, reader, []);
|
|
13432
|
+
if (!isObject(chunk)) {
|
|
13433
|
+
throw new Error("Response body stream returned an invalid chunk");
|
|
13434
|
+
}
|
|
13435
|
+
if (chunk.done === true) {
|
|
13436
|
+
pending += decoder.decode();
|
|
13437
|
+
break;
|
|
13438
|
+
}
|
|
13439
|
+
if (!(chunk.value instanceof Uint8Array)) {
|
|
13440
|
+
throw new Error("Response body stream returned a non-byte chunk");
|
|
13441
|
+
}
|
|
13442
|
+
pending += decoder.decode(chunk.value, { stream: true });
|
|
13443
|
+
let newline = pending.indexOf("\n");
|
|
13444
|
+
while (newline !== -1) {
|
|
13445
|
+
const line = pending.slice(0, newline).replace(/\r$/, "");
|
|
13446
|
+
pending = pending.slice(newline + 1);
|
|
13447
|
+
if (line.trim()) {
|
|
13448
|
+
try {
|
|
13449
|
+
yield JSON.parse(line);
|
|
13450
|
+
} catch (error) {
|
|
13451
|
+
logBatchInstrumentationError("skipped malformed JSONL", error);
|
|
13452
|
+
onIssue(new Error("OpenAI Batch file contains malformed JSONL"));
|
|
13453
|
+
}
|
|
13454
|
+
}
|
|
13455
|
+
newline = pending.indexOf("\n");
|
|
13456
|
+
}
|
|
13457
|
+
}
|
|
13458
|
+
if (pending.trim()) {
|
|
13459
|
+
try {
|
|
13460
|
+
yield JSON.parse(pending.replace(/\r$/, ""));
|
|
13461
|
+
} catch (error) {
|
|
13462
|
+
logBatchInstrumentationError("skipped malformed JSONL", error);
|
|
13463
|
+
onIssue(new Error("OpenAI Batch file contains malformed JSONL"));
|
|
13464
|
+
}
|
|
13465
|
+
}
|
|
13466
|
+
} catch (error) {
|
|
13467
|
+
logBatchInstrumentationError("could not read JSONL response body", error);
|
|
13468
|
+
onIssue(new Error("OpenAI Batch response body could not be read"));
|
|
13469
|
+
} finally {
|
|
13470
|
+
const releaseLock = read(reader, "releaseLock");
|
|
13471
|
+
if (typeof releaseLock === "function") {
|
|
13472
|
+
try {
|
|
13473
|
+
Reflect.apply(releaseLock, reader, []);
|
|
13474
|
+
} catch (error) {
|
|
13475
|
+
logBatchInstrumentationError(
|
|
13476
|
+
"could not release stream reader",
|
|
13477
|
+
error
|
|
13478
|
+
);
|
|
13479
|
+
}
|
|
13480
|
+
}
|
|
13481
|
+
}
|
|
13482
|
+
return;
|
|
13483
|
+
}
|
|
13484
|
+
if (isBatchRecordIterable(resolvedFile)) {
|
|
13485
|
+
for await (const record of resolvedFile) {
|
|
13486
|
+
yield record;
|
|
13487
|
+
}
|
|
13488
|
+
return;
|
|
13489
|
+
}
|
|
13490
|
+
logBatchInstrumentationError("skipped invalid JSONL source", resolvedFile);
|
|
13491
|
+
onIssue(new Error("OpenAI Batch file source is invalid"));
|
|
13492
|
+
}
|
|
13493
|
+
async function readBatchInputs(file) {
|
|
13494
|
+
const inputs = /* @__PURE__ */ new Map();
|
|
13495
|
+
const issues = [];
|
|
13496
|
+
let endpoint;
|
|
13497
|
+
try {
|
|
13498
|
+
for await (const value of jsonlRecords(
|
|
13499
|
+
file,
|
|
13500
|
+
(issue) => issues.push(issue)
|
|
13501
|
+
)) {
|
|
13502
|
+
const customId = read(value, "custom_id");
|
|
13503
|
+
const url = read(value, "url");
|
|
13504
|
+
const body = read(value, "body");
|
|
13505
|
+
if (!validCustomId(customId) || inputs.has(customId) || read(value, "method") !== "POST" || typeof url !== "string" || !SUPPORTED_ENDPOINTS.has(url) || endpoint !== void 0 && endpoint !== url || !isObject(body)) {
|
|
13506
|
+
issues.push(new Error("OpenAI Batch input contains an invalid record"));
|
|
13507
|
+
continue;
|
|
13508
|
+
}
|
|
13509
|
+
endpoint = url;
|
|
13510
|
+
let spanData;
|
|
13511
|
+
try {
|
|
13512
|
+
spanData = extractOpenAIBatchInput(url, body);
|
|
13513
|
+
} catch (error) {
|
|
13514
|
+
logBatchInstrumentationError("could not extract batch input", error);
|
|
13515
|
+
}
|
|
13516
|
+
inputs.set(customId, { customId, spanData });
|
|
13517
|
+
}
|
|
13518
|
+
} catch (error) {
|
|
13519
|
+
logBatchInstrumentationError("could not process input file", error);
|
|
13520
|
+
issues.push(new Error("OpenAI Batch input file could not be processed"));
|
|
13521
|
+
}
|
|
13522
|
+
if (!endpoint || inputs.size === 0) {
|
|
13523
|
+
issues.push(new Error("OpenAI Batch input contains no supported records"));
|
|
13524
|
+
}
|
|
13525
|
+
return { endpoint, inputs, issues };
|
|
13526
|
+
}
|
|
13527
|
+
async function writePendingSpans(trace, endTime) {
|
|
13528
|
+
const task = await startBatchSpan(trace.context);
|
|
13529
|
+
const taskParent = await task.export();
|
|
13530
|
+
for (const input of trace.inputs.values()) {
|
|
13531
|
+
try {
|
|
13532
|
+
const child = await startBatchChild(trace.context, taskParent, input);
|
|
13533
|
+
if (endTime !== void 0) {
|
|
13534
|
+
child.end({ endTime });
|
|
13535
|
+
}
|
|
13536
|
+
} catch (error) {
|
|
13537
|
+
logBatchInstrumentationError("could not write batch request span", error);
|
|
13538
|
+
}
|
|
13539
|
+
}
|
|
13540
|
+
if (endTime !== void 0) {
|
|
13541
|
+
if (trace.status && trace.status !== "completed") {
|
|
13542
|
+
task.log({ error: new Error(`OpenAI Batch ${trace.status}`) });
|
|
13543
|
+
}
|
|
13544
|
+
task.end({ endTime });
|
|
13545
|
+
}
|
|
13546
|
+
}
|
|
13547
|
+
var interceptOpenAIFilesCreateTraced = async (target, thisArg, args) => {
|
|
13548
|
+
const startTime = getCurrentUnixTimestamp();
|
|
13549
|
+
const inputPromise = readBatchInputs(args[0].inputFileContent);
|
|
13550
|
+
const parentPromise = exportParent(args[0].parent);
|
|
13551
|
+
const file = await Reflect.apply(target, thisArg, args);
|
|
13552
|
+
try {
|
|
13553
|
+
const inputFileId = read(file, "id");
|
|
13554
|
+
const [inputData, exportedParent2] = await Promise.all([
|
|
13555
|
+
inputPromise,
|
|
13556
|
+
parentPromise
|
|
13557
|
+
]);
|
|
13558
|
+
if (typeof inputFileId !== "string" || !exportedParent2 || !inputData.endpoint || inputData.issues.length > 0) {
|
|
13559
|
+
if (inputData.issues[0]) {
|
|
13560
|
+
logBatchInstrumentationError(
|
|
13561
|
+
"skipped invalid input file",
|
|
13562
|
+
inputData.issues[0]
|
|
13563
|
+
);
|
|
13564
|
+
}
|
|
13565
|
+
return file;
|
|
13566
|
+
}
|
|
13567
|
+
const trace = {
|
|
13568
|
+
context: {
|
|
13569
|
+
inputFileId,
|
|
13570
|
+
endpoint: inputData.endpoint,
|
|
13571
|
+
parent: exportedParent2,
|
|
13572
|
+
taskStartTime: startTime,
|
|
13573
|
+
childStartTime: startTime
|
|
13574
|
+
},
|
|
13575
|
+
inputs: inputData.inputs
|
|
13576
|
+
};
|
|
13577
|
+
pendingBatchTraces.set(inputFileId, trace);
|
|
13578
|
+
await writePendingSpans(trace);
|
|
13579
|
+
} catch (error) {
|
|
13580
|
+
logBatchInstrumentationError("could not start batch spans", error);
|
|
13581
|
+
}
|
|
13582
|
+
return file;
|
|
13583
|
+
};
|
|
13584
|
+
function validTimestamp(value) {
|
|
13585
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0;
|
|
13586
|
+
}
|
|
13587
|
+
function terminalEndTime(batch, startTime) {
|
|
13588
|
+
let timestamp;
|
|
13589
|
+
switch (batch.status) {
|
|
13590
|
+
case "completed":
|
|
13591
|
+
timestamp = batch.completed_at;
|
|
13592
|
+
break;
|
|
13593
|
+
case "failed":
|
|
13594
|
+
timestamp = batch.failed_at;
|
|
13595
|
+
break;
|
|
13596
|
+
case "expired":
|
|
13597
|
+
timestamp = batch.expired_at;
|
|
13598
|
+
break;
|
|
13599
|
+
default:
|
|
13600
|
+
timestamp = batch.cancelled_at;
|
|
13601
|
+
}
|
|
13602
|
+
return validTimestamp(timestamp) ? Math.max(timestamp, startTime) : Math.max(getCurrentUnixTimestamp(), startTime);
|
|
13603
|
+
}
|
|
13604
|
+
async function updateBatchTimestamps(batch) {
|
|
13605
|
+
const trace = pendingBatchTraces.get(batch.input_file_id);
|
|
13606
|
+
if (!trace || trace.context.endpoint !== batch.endpoint) {
|
|
13607
|
+
return;
|
|
13608
|
+
}
|
|
13609
|
+
if (validTimestamp(batch.created_at)) {
|
|
13610
|
+
trace.context.taskStartTime = batch.created_at;
|
|
13611
|
+
}
|
|
13612
|
+
trace.context.childStartTime = validTimestamp(batch.in_progress_at) ? Math.max(batch.in_progress_at, trace.context.taskStartTime) : trace.context.taskStartTime;
|
|
13613
|
+
trace.status = batch.status;
|
|
13614
|
+
if (TERMINAL_STATUSES.has(batch.status)) {
|
|
13615
|
+
trace.endTime = terminalEndTime(batch, trace.context.childStartTime);
|
|
13616
|
+
}
|
|
13617
|
+
await writePendingSpans(trace, trace.endTime);
|
|
13618
|
+
}
|
|
13619
|
+
var interceptOpenAIBatchesRetrieveTraced = (target, thisArg, args) => Promise.resolve(Reflect.apply(target, thisArg, args)).then(async (batch) => {
|
|
13620
|
+
try {
|
|
13621
|
+
await updateBatchTimestamps(batch);
|
|
13622
|
+
} catch (error) {
|
|
13623
|
+
logBatchInstrumentationError("could not update batch timestamps", error);
|
|
13624
|
+
}
|
|
13625
|
+
return batch;
|
|
13626
|
+
});
|
|
13627
|
+
function errorFromResult(result) {
|
|
13628
|
+
const error = read(result.value, "error");
|
|
13629
|
+
if (isObject(error)) {
|
|
13630
|
+
const message = read(error, "message");
|
|
13631
|
+
return new Error(
|
|
13632
|
+
typeof message === "string" ? message : "OpenAI Batch request failed"
|
|
13633
|
+
);
|
|
13634
|
+
}
|
|
13635
|
+
const response = read(result.value, "response");
|
|
13636
|
+
const statusCode = read(response, "status_code");
|
|
13637
|
+
if (result.source === "error" || typeof statusCode === "number" && (statusCode < 200 || statusCode >= 300)) {
|
|
13638
|
+
const message = read(read(read(response, "body"), "error"), "message");
|
|
13639
|
+
return new Error(
|
|
13640
|
+
typeof message === "string" ? message : "OpenAI Batch request failed"
|
|
13641
|
+
);
|
|
13642
|
+
}
|
|
13643
|
+
return void 0;
|
|
13644
|
+
}
|
|
13645
|
+
async function completeBatchResult(context, taskParent, endTime, input, result) {
|
|
13646
|
+
const child = await startBatchChild(context, taskParent, input);
|
|
13647
|
+
try {
|
|
13648
|
+
const resultError = errorFromResult(result);
|
|
13649
|
+
const responseBody = read(read(result.value, "response"), "body");
|
|
13650
|
+
if (resultError) {
|
|
13651
|
+
child.log({ error: resultError });
|
|
13652
|
+
} else if (isObject(responseBody)) {
|
|
13653
|
+
const model = read(responseBody, "model");
|
|
13654
|
+
child.log({
|
|
13655
|
+
output: context.endpoint === "/v1/chat/completions" ? read(responseBody, "choices") : processImagesInOutput(read(responseBody, "output")),
|
|
13656
|
+
...typeof model === "string" ? { metadata: { model } } : {},
|
|
13657
|
+
metrics: parseMetricsFromUsage(read(responseBody, "usage"))
|
|
13658
|
+
});
|
|
13659
|
+
} else {
|
|
13660
|
+
child.log({ error: new Error("OpenAI Batch response body is missing") });
|
|
13661
|
+
}
|
|
13662
|
+
} catch (error) {
|
|
13663
|
+
child.log({ error });
|
|
13664
|
+
} finally {
|
|
13665
|
+
child.end({ endTime });
|
|
13666
|
+
}
|
|
13667
|
+
}
|
|
13668
|
+
async function completeResultFile({
|
|
13669
|
+
context,
|
|
13670
|
+
endTime,
|
|
13671
|
+
file,
|
|
13672
|
+
inputs,
|
|
13673
|
+
issues,
|
|
13674
|
+
seen,
|
|
13675
|
+
source,
|
|
13676
|
+
taskParent
|
|
13677
|
+
}) {
|
|
13678
|
+
if (file === void 0) {
|
|
13679
|
+
return;
|
|
13680
|
+
}
|
|
13681
|
+
for await (const value of jsonlRecords(file, (issue) => issues.push(issue))) {
|
|
13682
|
+
const customId = read(value, "custom_id");
|
|
13683
|
+
if (!validCustomId(customId) || !isObject(value)) {
|
|
13684
|
+
issues.push(
|
|
13685
|
+
new Error("OpenAI Batch result is missing a valid custom_id")
|
|
13686
|
+
);
|
|
13687
|
+
continue;
|
|
13688
|
+
}
|
|
13689
|
+
if (seen.has(customId)) {
|
|
13690
|
+
issues.push(new Error("OpenAI Batch result contains a duplicate"));
|
|
13691
|
+
continue;
|
|
13692
|
+
}
|
|
13693
|
+
const input = inputs.get(customId);
|
|
13694
|
+
if (!input) {
|
|
13695
|
+
issues.push(
|
|
13696
|
+
new Error("OpenAI Batch result does not match an input record")
|
|
13697
|
+
);
|
|
13698
|
+
continue;
|
|
13699
|
+
}
|
|
13700
|
+
seen.add(customId);
|
|
13701
|
+
await completeBatchResult(context, taskParent, endTime, input, {
|
|
13702
|
+
value,
|
|
13703
|
+
source
|
|
13704
|
+
});
|
|
13705
|
+
}
|
|
13706
|
+
}
|
|
13707
|
+
function sameInputs(first, second) {
|
|
13708
|
+
return first.size === second.size && [...first.keys()].every((customId) => second.has(customId));
|
|
13709
|
+
}
|
|
13710
|
+
async function contextForCompletion(inputFileId, inputData) {
|
|
13711
|
+
if (!inputData.endpoint || inputData.issues.length > 0) {
|
|
13712
|
+
return void 0;
|
|
13713
|
+
}
|
|
13714
|
+
const existing = pendingBatchTraces.get(inputFileId);
|
|
13715
|
+
if (existing) {
|
|
13716
|
+
if (existing.context.endpoint !== inputData.endpoint || !sameInputs(existing.inputs, inputData.inputs)) {
|
|
13717
|
+
return void 0;
|
|
13718
|
+
}
|
|
13719
|
+
return { ...existing, inputs: inputData.inputs };
|
|
13720
|
+
}
|
|
13721
|
+
const parent = await exportParent(getSpanParentObject());
|
|
13722
|
+
if (!parent) {
|
|
13723
|
+
return void 0;
|
|
13724
|
+
}
|
|
13725
|
+
const startTime = getCurrentUnixTimestamp();
|
|
13726
|
+
return {
|
|
13727
|
+
context: {
|
|
13728
|
+
inputFileId,
|
|
13729
|
+
endpoint: inputData.endpoint,
|
|
13730
|
+
parent,
|
|
13731
|
+
taskStartTime: startTime,
|
|
13732
|
+
childStartTime: startTime
|
|
13733
|
+
},
|
|
13734
|
+
inputs: inputData.inputs
|
|
13735
|
+
};
|
|
13736
|
+
}
|
|
13737
|
+
async function completeBatch(args) {
|
|
13738
|
+
const inputData = await readBatchInputs(args.inputFileContent);
|
|
13739
|
+
const trace = await contextForCompletion(args.inputFileId, inputData);
|
|
13740
|
+
if (!trace) {
|
|
13741
|
+
logBatchInstrumentationError(
|
|
13742
|
+
"left batch spans pending",
|
|
13743
|
+
inputData.issues[0] ?? new Error("OpenAI Batch input does not match")
|
|
13744
|
+
);
|
|
13745
|
+
return;
|
|
13746
|
+
}
|
|
13747
|
+
const endTime = trace.endTime ?? getCurrentUnixTimestamp();
|
|
13748
|
+
const task = await startBatchSpan(trace.context);
|
|
13749
|
+
const taskParent = await task.export();
|
|
13750
|
+
const issues = [];
|
|
13751
|
+
const seen = /* @__PURE__ */ new Set();
|
|
13752
|
+
await Promise.all([
|
|
13753
|
+
completeResultFile({
|
|
13754
|
+
context: trace.context,
|
|
13755
|
+
endTime,
|
|
13756
|
+
file: args.outputFileContent,
|
|
13757
|
+
inputs: trace.inputs,
|
|
13758
|
+
issues,
|
|
13759
|
+
seen,
|
|
13760
|
+
source: "output",
|
|
13761
|
+
taskParent
|
|
13762
|
+
}),
|
|
13763
|
+
completeResultFile({
|
|
13764
|
+
context: trace.context,
|
|
13765
|
+
endTime,
|
|
13766
|
+
file: args.errorFileContent,
|
|
13767
|
+
inputs: trace.inputs,
|
|
13768
|
+
issues,
|
|
13769
|
+
seen,
|
|
13770
|
+
source: "error",
|
|
13771
|
+
taskParent
|
|
13772
|
+
})
|
|
13773
|
+
]);
|
|
13774
|
+
if (issues.length > 0) {
|
|
13775
|
+
logBatchInstrumentationError("left batch spans pending", issues[0]);
|
|
13776
|
+
return;
|
|
13777
|
+
}
|
|
13778
|
+
const missing = [...trace.inputs.values()].filter(
|
|
13779
|
+
({ customId }) => !seen.has(customId)
|
|
13780
|
+
);
|
|
13781
|
+
if (!trace.status || trace.status === "completed") {
|
|
13782
|
+
if (missing.length > 0) {
|
|
13783
|
+
logBatchInstrumentationError(
|
|
13784
|
+
"left batch spans pending",
|
|
13785
|
+
new Error("OpenAI Batch result files are incomplete")
|
|
13786
|
+
);
|
|
13787
|
+
return;
|
|
13788
|
+
}
|
|
13789
|
+
} else {
|
|
13790
|
+
for (const input of missing) {
|
|
13791
|
+
const child = await startBatchChild(trace.context, taskParent, input);
|
|
13792
|
+
child.log({ error: new Error(`OpenAI Batch ${trace.status}`) });
|
|
13793
|
+
child.end({ endTime });
|
|
13794
|
+
}
|
|
13795
|
+
task.log({ error: new Error(`OpenAI Batch ${trace.status}`) });
|
|
13796
|
+
}
|
|
13797
|
+
task.end({ endTime });
|
|
13798
|
+
pendingBatchTraces.delete(args.inputFileId);
|
|
13799
|
+
}
|
|
13800
|
+
var interceptOpenAIBatchTraceComplete = (target, thisArg, args) => Promise.resolve(Reflect.apply(target, thisArg, args)).then(async (result) => {
|
|
13801
|
+
try {
|
|
13802
|
+
await completeBatch(args[0]);
|
|
13803
|
+
} catch (error) {
|
|
13804
|
+
logBatchInstrumentationError("could not complete batch", error);
|
|
13805
|
+
}
|
|
13806
|
+
return result;
|
|
13807
|
+
});
|
|
13808
|
+
|
|
12873
13809
|
// src/instrumentation/plugins/openai-plugin.ts
|
|
12874
13810
|
var OpenAIPlugin = class extends BasePlugin {
|
|
12875
13811
|
constructor() {
|
|
12876
13812
|
super();
|
|
12877
13813
|
}
|
|
12878
13814
|
onEnable() {
|
|
13815
|
+
this.unsubscribers.push(
|
|
13816
|
+
openAIChannels.filesCreateTraced.intercept(
|
|
13817
|
+
interceptOpenAIFilesCreateTraced
|
|
13818
|
+
),
|
|
13819
|
+
openAIChannels.batchesRetrieveTraced.intercept(
|
|
13820
|
+
interceptOpenAIBatchesRetrieveTraced
|
|
13821
|
+
),
|
|
13822
|
+
openAIChannels.batchesCompleteTrace.intercept(
|
|
13823
|
+
interceptOpenAIBatchTraceComplete
|
|
13824
|
+
)
|
|
13825
|
+
);
|
|
12879
13826
|
this.unsubscribers.push(
|
|
12880
13827
|
traceStreamingChannel(openAIChannels.chatCompletionsCreate, {
|
|
12881
13828
|
name: "Chat Completion",
|
|
12882
13829
|
type: "llm" /* LLM */,
|
|
12883
|
-
extractInput: ([params]) =>
|
|
12884
|
-
const { messages, ...metadata } = params;
|
|
12885
|
-
return {
|
|
12886
|
-
input: processInputAttachments(messages),
|
|
12887
|
-
metadata: { ...metadata, provider: "openai" }
|
|
12888
|
-
};
|
|
12889
|
-
},
|
|
13830
|
+
extractInput: ([params]) => extractOpenAIChatInput(params),
|
|
12890
13831
|
extractOutput: (result) => {
|
|
12891
13832
|
return result?.choices;
|
|
12892
13833
|
},
|
|
@@ -12932,13 +13873,7 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
12932
13873
|
traceStreamingChannel(openAIChannels.betaChatCompletionsParse, {
|
|
12933
13874
|
name: "Chat Completion",
|
|
12934
13875
|
type: "llm" /* LLM */,
|
|
12935
|
-
extractInput: ([params]) =>
|
|
12936
|
-
const { messages, ...metadata } = params;
|
|
12937
|
-
return {
|
|
12938
|
-
input: processInputAttachments(messages),
|
|
12939
|
-
metadata: { ...metadata, provider: "openai" }
|
|
12940
|
-
};
|
|
12941
|
-
},
|
|
13876
|
+
extractInput: ([params]) => extractOpenAIChatInput(params),
|
|
12942
13877
|
extractOutput: (result) => {
|
|
12943
13878
|
return result?.choices;
|
|
12944
13879
|
},
|
|
@@ -12960,13 +13895,7 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
12960
13895
|
traceSyncStreamChannel(openAIChannels.betaChatCompletionsStream, {
|
|
12961
13896
|
name: "Chat Completion",
|
|
12962
13897
|
type: "llm" /* LLM */,
|
|
12963
|
-
extractInput: ([params]) =>
|
|
12964
|
-
const { messages, ...metadata } = params;
|
|
12965
|
-
return {
|
|
12966
|
-
input: processInputAttachments(messages),
|
|
12967
|
-
metadata: { ...metadata, provider: "openai" }
|
|
12968
|
-
};
|
|
12969
|
-
}
|
|
13898
|
+
extractInput: ([params]) => extractOpenAIChatInput(params)
|
|
12970
13899
|
})
|
|
12971
13900
|
);
|
|
12972
13901
|
this.unsubscribers.push(
|
|
@@ -12996,23 +13925,11 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
12996
13925
|
traceStreamingChannel(openAIChannels.responsesCreate, {
|
|
12997
13926
|
name: "openai.responses.create",
|
|
12998
13927
|
type: "llm" /* LLM */,
|
|
12999
|
-
extractInput: ([params]) =>
|
|
13000
|
-
const { input, ...metadata } = params;
|
|
13001
|
-
return {
|
|
13002
|
-
input: processInputAttachments(input),
|
|
13003
|
-
metadata: { ...metadata, provider: "openai" }
|
|
13004
|
-
};
|
|
13005
|
-
},
|
|
13928
|
+
extractInput: ([params]) => extractOpenAIResponsesInput(params),
|
|
13006
13929
|
extractOutput: (result) => {
|
|
13007
13930
|
return processImagesInOutput(result?.output);
|
|
13008
13931
|
},
|
|
13009
|
-
extractMetadata: (result) =>
|
|
13010
|
-
if (!result) {
|
|
13011
|
-
return void 0;
|
|
13012
|
-
}
|
|
13013
|
-
const { output: _output, usage: _usage, ...metadata } = result;
|
|
13014
|
-
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
13015
|
-
},
|
|
13932
|
+
extractMetadata: (result) => extractOpenAIResponsesMetadata(result),
|
|
13016
13933
|
extractMetrics: (result, startTime, endEvent) => {
|
|
13017
13934
|
const metrics = withCachedMetric(
|
|
13018
13935
|
parseMetricsFromUsage(result?.usage),
|
|
@@ -13031,13 +13948,7 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
13031
13948
|
traceSyncStreamChannel(openAIChannels.responsesStream, {
|
|
13032
13949
|
name: "openai.responses.create",
|
|
13033
13950
|
type: "llm" /* LLM */,
|
|
13034
|
-
extractInput: ([params]) =>
|
|
13035
|
-
const { input, ...metadata } = params;
|
|
13036
|
-
return {
|
|
13037
|
-
input: processInputAttachments(input),
|
|
13038
|
-
metadata: { ...metadata, provider: "openai" }
|
|
13039
|
-
};
|
|
13040
|
-
},
|
|
13951
|
+
extractInput: ([params]) => extractOpenAIResponsesInput(params),
|
|
13041
13952
|
extractFromEvent: (event) => {
|
|
13042
13953
|
if (event.type !== "response.completed" || !event.response) {
|
|
13043
13954
|
return {};
|
|
@@ -13060,23 +13971,11 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
13060
13971
|
traceStreamingChannel(openAIChannels.responsesParse, {
|
|
13061
13972
|
name: "openai.responses.parse",
|
|
13062
13973
|
type: "llm" /* LLM */,
|
|
13063
|
-
extractInput: ([params]) =>
|
|
13064
|
-
const { input, ...metadata } = params;
|
|
13065
|
-
return {
|
|
13066
|
-
input: processInputAttachments(input),
|
|
13067
|
-
metadata: { ...metadata, provider: "openai" }
|
|
13068
|
-
};
|
|
13069
|
-
},
|
|
13974
|
+
extractInput: ([params]) => extractOpenAIResponsesInput(params),
|
|
13070
13975
|
extractOutput: (result) => {
|
|
13071
13976
|
return processImagesInOutput(result?.output);
|
|
13072
13977
|
},
|
|
13073
|
-
extractMetadata: (result) =>
|
|
13074
|
-
if (!result) {
|
|
13075
|
-
return void 0;
|
|
13076
|
-
}
|
|
13077
|
-
const { output: _output, usage: _usage, ...metadata } = result;
|
|
13078
|
-
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
13079
|
-
},
|
|
13978
|
+
extractMetadata: (result) => extractOpenAIResponsesMetadata(result),
|
|
13080
13979
|
extractMetrics: (result, startTime, endEvent) => {
|
|
13081
13980
|
const metrics = withCachedMetric(
|
|
13082
13981
|
parseMetricsFromUsage(result?.usage),
|
|
@@ -13095,23 +13994,11 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
13095
13994
|
traceAsyncChannel(openAIChannels.responsesCompact, {
|
|
13096
13995
|
name: "openai.responses.compact",
|
|
13097
13996
|
type: "llm" /* LLM */,
|
|
13098
|
-
extractInput: ([params]) =>
|
|
13099
|
-
const { input, ...metadata } = params;
|
|
13100
|
-
return {
|
|
13101
|
-
input: processInputAttachments(input),
|
|
13102
|
-
metadata: { ...metadata, provider: "openai" }
|
|
13103
|
-
};
|
|
13104
|
-
},
|
|
13997
|
+
extractInput: ([params]) => extractOpenAIResponsesInput(params),
|
|
13105
13998
|
extractOutput: (result) => {
|
|
13106
13999
|
return processImagesInOutput(result?.output);
|
|
13107
14000
|
},
|
|
13108
|
-
extractMetadata: (result) =>
|
|
13109
|
-
if (!result) {
|
|
13110
|
-
return void 0;
|
|
13111
|
-
}
|
|
13112
|
-
const { output: _output, usage: _usage, ...metadata } = result;
|
|
13113
|
-
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
13114
|
-
},
|
|
14001
|
+
extractMetadata: (result) => extractOpenAIResponsesMetadata(result),
|
|
13115
14002
|
extractMetrics: (result, startTime, endEvent) => {
|
|
13116
14003
|
const metrics = withCachedMetric(
|
|
13117
14004
|
parseMetricsFromUsage(result?.usage),
|
|
@@ -13167,35 +14054,6 @@ function withCachedMetric(metrics, result, endEvent) {
|
|
|
13167
14054
|
cached
|
|
13168
14055
|
};
|
|
13169
14056
|
}
|
|
13170
|
-
function processImagesInOutput(output) {
|
|
13171
|
-
if (Array.isArray(output)) {
|
|
13172
|
-
return output.map(processImagesInOutput);
|
|
13173
|
-
}
|
|
13174
|
-
if (isObject(output)) {
|
|
13175
|
-
if (output.type === "image_generation_call" && output.result && typeof output.result === "string") {
|
|
13176
|
-
const fileExtension = output.output_format || "png";
|
|
13177
|
-
const contentType = `image/${fileExtension}`;
|
|
13178
|
-
const baseFilename = output.revised_prompt && typeof output.revised_prompt === "string" ? output.revised_prompt.slice(0, 50).replace(/[^a-zA-Z0-9]/g, "_") : "generated_image";
|
|
13179
|
-
const filename = `${baseFilename}.${fileExtension}`;
|
|
13180
|
-
const binaryString = atob(output.result);
|
|
13181
|
-
const bytes = new Uint8Array(binaryString.length);
|
|
13182
|
-
for (let i = 0; i < binaryString.length; i++) {
|
|
13183
|
-
bytes[i] = binaryString.charCodeAt(i);
|
|
13184
|
-
}
|
|
13185
|
-
const blob = new Blob([bytes], { type: contentType });
|
|
13186
|
-
const attachment = new Attachment({
|
|
13187
|
-
data: blob,
|
|
13188
|
-
filename,
|
|
13189
|
-
contentType
|
|
13190
|
-
});
|
|
13191
|
-
return {
|
|
13192
|
-
...output,
|
|
13193
|
-
result: attachment
|
|
13194
|
-
};
|
|
13195
|
-
}
|
|
13196
|
-
}
|
|
13197
|
-
return output;
|
|
13198
|
-
}
|
|
13199
14057
|
function mergeLogprobTokens(existing, incoming) {
|
|
13200
14058
|
if (incoming === void 0) {
|
|
13201
14059
|
return existing;
|
|
@@ -13226,13 +14084,33 @@ function aggregateChatLogprobs(existing, incoming) {
|
|
|
13226
14084
|
}
|
|
13227
14085
|
return aggregated;
|
|
13228
14086
|
}
|
|
14087
|
+
function createAggregatedChatChoice(index) {
|
|
14088
|
+
return {
|
|
14089
|
+
index,
|
|
14090
|
+
role: void 0,
|
|
14091
|
+
content: void 0,
|
|
14092
|
+
refusal: void 0,
|
|
14093
|
+
toolCallsByIndex: /* @__PURE__ */ new Map(),
|
|
14094
|
+
logprobs: void 0,
|
|
14095
|
+
finish_reason: void 0
|
|
14096
|
+
};
|
|
14097
|
+
}
|
|
14098
|
+
function toChatChoice(choice) {
|
|
14099
|
+
const toolCalls = Array.from(choice.toolCallsByIndex.entries()).sort(([left], [right]) => left - right).map(([, toolCall]) => toolCall);
|
|
14100
|
+
return {
|
|
14101
|
+
index: choice.index,
|
|
14102
|
+
message: {
|
|
14103
|
+
role: choice.role,
|
|
14104
|
+
content: choice.content,
|
|
14105
|
+
...choice.refusal !== void 0 ? { refusal: choice.refusal } : {},
|
|
14106
|
+
tool_calls: toolCalls.length > 0 ? toolCalls : void 0
|
|
14107
|
+
},
|
|
14108
|
+
logprobs: choice.logprobs ?? null,
|
|
14109
|
+
finish_reason: choice.finish_reason
|
|
14110
|
+
};
|
|
14111
|
+
}
|
|
13229
14112
|
function aggregateChatCompletionChunks(chunks, streamResult, endEvent) {
|
|
13230
|
-
|
|
13231
|
-
let content = void 0;
|
|
13232
|
-
let refusal = void 0;
|
|
13233
|
-
let tool_calls = void 0;
|
|
13234
|
-
let logprobs = void 0;
|
|
13235
|
-
let finish_reason = void 0;
|
|
14113
|
+
const choicesByIndex = /* @__PURE__ */ new Map();
|
|
13236
14114
|
let metrics = {};
|
|
13237
14115
|
for (const chunk of chunks) {
|
|
13238
14116
|
if (chunk.usage) {
|
|
@@ -13241,62 +14119,75 @@ function aggregateChatCompletionChunks(chunks, streamResult, endEvent) {
|
|
|
13241
14119
|
...parseMetricsFromUsage(chunk.usage)
|
|
13242
14120
|
};
|
|
13243
14121
|
}
|
|
13244
|
-
const
|
|
13245
|
-
if (!
|
|
13246
|
-
continue;
|
|
13247
|
-
}
|
|
13248
|
-
if (choice.finish_reason) {
|
|
13249
|
-
finish_reason = choice.finish_reason;
|
|
13250
|
-
}
|
|
13251
|
-
logprobs = aggregateChatLogprobs(logprobs, choice.logprobs);
|
|
13252
|
-
const delta = choice.delta;
|
|
13253
|
-
if (!delta) {
|
|
14122
|
+
const choices = chunk.choices;
|
|
14123
|
+
if (!choices?.length) {
|
|
13254
14124
|
continue;
|
|
13255
14125
|
}
|
|
13256
|
-
|
|
13257
|
-
|
|
13258
|
-
|
|
13259
|
-
|
|
13260
|
-
|
|
13261
|
-
|
|
13262
|
-
|
|
13263
|
-
|
|
13264
|
-
|
|
13265
|
-
|
|
13266
|
-
|
|
13267
|
-
|
|
13268
|
-
|
|
13269
|
-
|
|
13270
|
-
|
|
13271
|
-
|
|
13272
|
-
|
|
13273
|
-
|
|
13274
|
-
|
|
13275
|
-
|
|
13276
|
-
|
|
14126
|
+
for (const choice of choices) {
|
|
14127
|
+
const choiceIndex = choice.index;
|
|
14128
|
+
let aggregatedChoice = choicesByIndex.get(choiceIndex);
|
|
14129
|
+
if (!aggregatedChoice) {
|
|
14130
|
+
aggregatedChoice = createAggregatedChatChoice(choiceIndex);
|
|
14131
|
+
choicesByIndex.set(choiceIndex, aggregatedChoice);
|
|
14132
|
+
}
|
|
14133
|
+
if (choice.finish_reason) {
|
|
14134
|
+
aggregatedChoice.finish_reason = choice.finish_reason;
|
|
14135
|
+
}
|
|
14136
|
+
aggregatedChoice.logprobs = aggregateChatLogprobs(
|
|
14137
|
+
aggregatedChoice.logprobs,
|
|
14138
|
+
choice.logprobs
|
|
14139
|
+
);
|
|
14140
|
+
const delta = choice.delta;
|
|
14141
|
+
if (!delta) {
|
|
14142
|
+
continue;
|
|
14143
|
+
}
|
|
14144
|
+
if (delta.finish_reason) {
|
|
14145
|
+
aggregatedChoice.finish_reason = delta.finish_reason;
|
|
14146
|
+
}
|
|
14147
|
+
if (!aggregatedChoice.role && delta.role) {
|
|
14148
|
+
aggregatedChoice.role = delta.role;
|
|
14149
|
+
}
|
|
14150
|
+
if (delta.content) {
|
|
14151
|
+
aggregatedChoice.content = (aggregatedChoice.content || "") + delta.content;
|
|
14152
|
+
}
|
|
14153
|
+
if (delta.refusal) {
|
|
14154
|
+
aggregatedChoice.refusal = (aggregatedChoice.refusal || "") + delta.refusal;
|
|
14155
|
+
}
|
|
14156
|
+
if (delta.tool_calls) {
|
|
14157
|
+
for (const toolDelta of delta.tool_calls) {
|
|
14158
|
+
let aggregatedToolCall = aggregatedChoice.toolCallsByIndex.get(
|
|
14159
|
+
toolDelta.index
|
|
14160
|
+
);
|
|
14161
|
+
if (!aggregatedToolCall) {
|
|
14162
|
+
aggregatedToolCall = {
|
|
14163
|
+
function: { arguments: "" }
|
|
14164
|
+
};
|
|
14165
|
+
aggregatedChoice.toolCallsByIndex.set(
|
|
14166
|
+
toolDelta.index,
|
|
14167
|
+
aggregatedToolCall
|
|
14168
|
+
);
|
|
13277
14169
|
}
|
|
13278
|
-
|
|
13279
|
-
|
|
13280
|
-
|
|
14170
|
+
if (toolDelta.id !== void 0) {
|
|
14171
|
+
aggregatedToolCall.id = toolDelta.id;
|
|
14172
|
+
}
|
|
14173
|
+
if (toolDelta.type !== void 0) {
|
|
14174
|
+
aggregatedToolCall.type = toolDelta.type;
|
|
14175
|
+
}
|
|
14176
|
+
if (toolDelta.function?.name !== void 0) {
|
|
14177
|
+
aggregatedToolCall.function.name = toolDelta.function.name;
|
|
14178
|
+
}
|
|
14179
|
+
if (toolDelta.function?.arguments !== void 0) {
|
|
14180
|
+
aggregatedToolCall.function.arguments += toolDelta.function.arguments;
|
|
14181
|
+
}
|
|
14182
|
+
}
|
|
13281
14183
|
}
|
|
13282
14184
|
}
|
|
13283
14185
|
}
|
|
13284
14186
|
metrics = withCachedMetric(metrics, streamResult, endEvent);
|
|
14187
|
+
const output = Array.from(choicesByIndex.values()).sort((left, right) => left.index - right.index).map(toChatChoice);
|
|
13285
14188
|
return {
|
|
13286
14189
|
metrics,
|
|
13287
|
-
output: [
|
|
13288
|
-
{
|
|
13289
|
-
index: 0,
|
|
13290
|
-
message: {
|
|
13291
|
-
role,
|
|
13292
|
-
content,
|
|
13293
|
-
...refusal !== void 0 ? { refusal } : {},
|
|
13294
|
-
tool_calls
|
|
13295
|
-
},
|
|
13296
|
-
logprobs: logprobs ?? null,
|
|
13297
|
-
finish_reason
|
|
13298
|
-
}
|
|
13299
|
-
]
|
|
14190
|
+
output: output.length > 0 ? output : [toChatChoice(createAggregatedChatChoice(0))]
|
|
13300
14191
|
};
|
|
13301
14192
|
}
|
|
13302
14193
|
function aggregateResponseStreamEvents(chunks, _streamResult, endEvent) {
|
|
@@ -14619,6 +15510,12 @@ function parseMetricsFromUsage2(usage) {
|
|
|
14619
15510
|
}
|
|
14620
15511
|
}
|
|
14621
15512
|
}
|
|
15513
|
+
if (isObject(usage.output_tokens_details)) {
|
|
15514
|
+
const thinkingTokens = usage.output_tokens_details.thinking_tokens;
|
|
15515
|
+
if (typeof thinkingTokens === "number") {
|
|
15516
|
+
metrics.completion_reasoning_tokens = thinkingTokens;
|
|
15517
|
+
}
|
|
15518
|
+
}
|
|
14622
15519
|
if (isObject(usage.server_tool_use)) {
|
|
14623
15520
|
for (const [name, value] of Object.entries(usage.server_tool_use)) {
|
|
14624
15521
|
if (typeof value === "number") {
|
|
@@ -15575,7 +16472,6 @@ function endHarnessTurn(parent) {
|
|
|
15575
16472
|
function braintrustAISDKTelemetry() {
|
|
15576
16473
|
const operations = /* @__PURE__ */ new Map();
|
|
15577
16474
|
const operationKeysByCallId = /* @__PURE__ */ new Map();
|
|
15578
|
-
const workflowOperationKeyStore = isomorph_default.newAsyncLocalStorage();
|
|
15579
16475
|
const modelSpans = /* @__PURE__ */ new Map();
|
|
15580
16476
|
const objectSpans = /* @__PURE__ */ new Map();
|
|
15581
16477
|
const embedSpans = /* @__PURE__ */ new Map();
|
|
@@ -15618,9 +16514,6 @@ function braintrustAISDKTelemetry() {
|
|
|
15618
16514
|
return;
|
|
15619
16515
|
}
|
|
15620
16516
|
operations.delete(operationKey);
|
|
15621
|
-
if (workflowOperationKeyStore.getStore() === operationKey) {
|
|
15622
|
-
workflowOperationKeyStore.enterWith(void 0);
|
|
15623
|
-
}
|
|
15624
16517
|
const keys = operationKeysByCallId.get(state.callId);
|
|
15625
16518
|
if (!keys) {
|
|
15626
16519
|
return;
|
|
@@ -15668,14 +16561,7 @@ function braintrustAISDKTelemetry() {
|
|
|
15668
16561
|
return key;
|
|
15669
16562
|
}
|
|
15670
16563
|
}
|
|
15671
|
-
|
|
15672
|
-
if (workflowOperationKey && keys.includes(workflowOperationKey)) {
|
|
15673
|
-
return workflowOperationKey;
|
|
15674
|
-
}
|
|
15675
|
-
if (callId === "workflow-agent") {
|
|
15676
|
-
return void 0;
|
|
15677
|
-
}
|
|
15678
|
-
return mode === "finish" ? keys[0] : keys[keys.length - 1];
|
|
16564
|
+
return callId === "workflow-agent" || mode === "active" ? keys[keys.length - 1] : keys[0];
|
|
15679
16565
|
};
|
|
15680
16566
|
const operationKeyFromEvent = (event, mode = "active") => {
|
|
15681
16567
|
const explicit = explicitOperationKey(event);
|
|
@@ -15689,17 +16575,13 @@ function braintrustAISDKTelemetry() {
|
|
|
15689
16575
|
if (operationKey) {
|
|
15690
16576
|
return operationKey;
|
|
15691
16577
|
}
|
|
15692
|
-
const
|
|
15693
|
-
if (
|
|
15694
|
-
return
|
|
16578
|
+
const workflowAgentKeys2 = operationKeysByCallId.get("workflow-agent");
|
|
16579
|
+
if (workflowAgentKeys2?.length) {
|
|
16580
|
+
return workflowAgentKeys2[workflowAgentKeys2.length - 1];
|
|
15695
16581
|
}
|
|
15696
16582
|
return callId === "workflow-agent" ? void 0 : callId;
|
|
15697
16583
|
}
|
|
15698
16584
|
}
|
|
15699
|
-
const workflowOperationKey = workflowOperationKeyStore.getStore();
|
|
15700
|
-
if (workflowOperationKey && operations.has(workflowOperationKey)) {
|
|
15701
|
-
return workflowOperationKey;
|
|
15702
|
-
}
|
|
15703
16585
|
const wrapperSpan = currentWorkflowAgentWrapperSpan();
|
|
15704
16586
|
if (wrapperSpan?.spanId) {
|
|
15705
16587
|
for (const [operationKey, state] of operations) {
|
|
@@ -15709,8 +16591,8 @@ function braintrustAISDKTelemetry() {
|
|
|
15709
16591
|
}
|
|
15710
16592
|
}
|
|
15711
16593
|
const workflowAgentKeys = operationKeysByCallId.get("workflow-agent");
|
|
15712
|
-
if (workflowAgentKeys?.length
|
|
15713
|
-
return workflowAgentKeys[
|
|
16594
|
+
if (workflowAgentKeys?.length) {
|
|
16595
|
+
return workflowAgentKeys[workflowAgentKeys.length - 1];
|
|
15714
16596
|
}
|
|
15715
16597
|
if (operations.size === 1) {
|
|
15716
16598
|
return operations.keys().next().value;
|
|
@@ -15913,9 +16795,6 @@ function braintrustAISDKTelemetry() {
|
|
|
15913
16795
|
if (!ownsSpan) {
|
|
15914
16796
|
return;
|
|
15915
16797
|
}
|
|
15916
|
-
if (workflowAgent) {
|
|
15917
|
-
workflowOperationKeyStore.enterWith(operationKey);
|
|
15918
|
-
}
|
|
15919
16798
|
let metadata = metadataFromEvent(event);
|
|
15920
16799
|
const logPayload = { metadata };
|
|
15921
16800
|
const workflowAgentCallInput = workflowAgent ? operationInput(event, operationName) : void 0;
|
|
@@ -16387,6 +17266,10 @@ var aiSDKChannels = defineChannels(
|
|
|
16387
17266
|
channelName: "generateText",
|
|
16388
17267
|
kind: "async"
|
|
16389
17268
|
}),
|
|
17269
|
+
generateImage: channel({
|
|
17270
|
+
channelName: "generateImage",
|
|
17271
|
+
kind: "async"
|
|
17272
|
+
}),
|
|
16390
17273
|
streamText: channel({
|
|
16391
17274
|
channelName: "streamText",
|
|
16392
17275
|
kind: "async"
|
|
@@ -16574,7 +17457,7 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
16574
17457
|
}
|
|
16575
17458
|
subscribeToAISDK() {
|
|
16576
17459
|
const denyOutputPaths = this.config.denyOutputPaths || DEFAULT_DENY_OUTPUT_PATHS;
|
|
16577
|
-
this.unsubscribers.push(
|
|
17460
|
+
this.unsubscribers.push(interceptAISDKV7TelemetryDispatcher());
|
|
16578
17461
|
this.unsubscribers.push(subscribeToHarnessAgentCreateSession());
|
|
16579
17462
|
this.unsubscribers.push(
|
|
16580
17463
|
subscribeToHarnessContinuation(
|
|
@@ -16602,6 +17485,18 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
16602
17485
|
aggregateChunks: aggregateAISDKChunks
|
|
16603
17486
|
})
|
|
16604
17487
|
);
|
|
17488
|
+
this.unsubscribers.push(
|
|
17489
|
+
traceAsyncChannel(aiSDKChannels.generateImage, {
|
|
17490
|
+
name: "generateImage",
|
|
17491
|
+
type: "llm" /* LLM */,
|
|
17492
|
+
extractInput: ([params], event) => prepareAISDKGenerateImageInput(params, event.self),
|
|
17493
|
+
extractOutput: (result, endEvent) => processAISDKGenerateImageOutput(
|
|
17494
|
+
result,
|
|
17495
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
17496
|
+
),
|
|
17497
|
+
extractMetrics: (result) => extractTokenMetrics(result)
|
|
17498
|
+
})
|
|
17499
|
+
);
|
|
16605
17500
|
this.unsubscribers.push(
|
|
16606
17501
|
traceStreamingChannel(aiSDKChannels.streamText, {
|
|
16607
17502
|
name: "streamText",
|
|
@@ -17091,26 +17986,29 @@ function subscribeToHarnessContinuation(continuationChannel, defaultDenyOutputPa
|
|
|
17091
17986
|
channel2.unsubscribe(handlers);
|
|
17092
17987
|
};
|
|
17093
17988
|
}
|
|
17094
|
-
function
|
|
17095
|
-
const channel2 = aiSDKChannels.v7CreateTelemetryDispatcher.tracingChannel();
|
|
17989
|
+
function interceptAISDKV7TelemetryDispatcher() {
|
|
17096
17990
|
const telemetry = braintrustAISDKTelemetry();
|
|
17097
|
-
|
|
17098
|
-
|
|
17099
|
-
const
|
|
17100
|
-
|
|
17101
|
-
|
|
17991
|
+
return aiSDKChannels.v7CreateTelemetryDispatcher.intercept(
|
|
17992
|
+
(target, thisArg, args) => {
|
|
17993
|
+
const dispatcher = Reflect.apply(target, thisArg, args);
|
|
17994
|
+
const telemetryOptions = args[0]?.telemetry;
|
|
17995
|
+
if (telemetryOptions?.isEnabled !== false) {
|
|
17996
|
+
try {
|
|
17997
|
+
patchAISDKV7TelemetryDispatcher(
|
|
17998
|
+
dispatcher,
|
|
17999
|
+
telemetry,
|
|
18000
|
+
telemetryOptions
|
|
18001
|
+
);
|
|
18002
|
+
} catch (error) {
|
|
18003
|
+
debugLogger.error(
|
|
18004
|
+
"Error instrumenting AI SDK v7 telemetry dispatcher:",
|
|
18005
|
+
error
|
|
18006
|
+
);
|
|
18007
|
+
}
|
|
17102
18008
|
}
|
|
17103
|
-
|
|
17104
|
-
event.result,
|
|
17105
|
-
telemetry,
|
|
17106
|
-
telemetryOptions
|
|
17107
|
-
);
|
|
18009
|
+
return dispatcher;
|
|
17108
18010
|
}
|
|
17109
|
-
|
|
17110
|
-
channel2.subscribe(handlers);
|
|
17111
|
-
return () => {
|
|
17112
|
-
channel2.unsubscribe(handlers);
|
|
17113
|
-
};
|
|
18011
|
+
);
|
|
17114
18012
|
}
|
|
17115
18013
|
function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry, telemetryOptions) {
|
|
17116
18014
|
if (!isObject(dispatcher)) {
|
|
@@ -17435,16 +18333,10 @@ var convertImageToAttachment = (image, explicitMimeType) => {
|
|
|
17435
18333
|
}
|
|
17436
18334
|
}
|
|
17437
18335
|
if (explicitMimeType) {
|
|
17438
|
-
|
|
17439
|
-
|
|
17440
|
-
data: new Blob([image], { type: explicitMimeType }),
|
|
17441
|
-
filename: `image.${getExtensionFromMediaType(explicitMimeType)}`,
|
|
17442
|
-
contentType: explicitMimeType
|
|
17443
|
-
});
|
|
17444
|
-
}
|
|
17445
|
-
if (typeof Buffer !== "undefined" && Buffer.isBuffer(image)) {
|
|
18336
|
+
const blob = convertDataToBlob(image, explicitMimeType);
|
|
18337
|
+
if (blob) {
|
|
17446
18338
|
return new Attachment({
|
|
17447
|
-
data:
|
|
18339
|
+
data: blob,
|
|
17448
18340
|
filename: `image.${getExtensionFromMediaType(explicitMimeType)}`,
|
|
17449
18341
|
contentType: explicitMimeType
|
|
17450
18342
|
});
|
|
@@ -17498,6 +18390,25 @@ var convertDataToAttachment = (data, mimeType, filename) => {
|
|
|
17498
18390
|
function processAISDKCallInput(params) {
|
|
17499
18391
|
return processInputAttachmentsSync(params);
|
|
17500
18392
|
}
|
|
18393
|
+
function processAISDKGenerateImageInput(params) {
|
|
18394
|
+
const prompt = params.prompt;
|
|
18395
|
+
if (!isObject(prompt) || Array.isArray(prompt)) {
|
|
18396
|
+
return processAISDKCallInput(params);
|
|
18397
|
+
}
|
|
18398
|
+
const processedPrompt = { ...prompt };
|
|
18399
|
+
if (Array.isArray(prompt.images)) {
|
|
18400
|
+
processedPrompt.images = prompt.images.map(
|
|
18401
|
+
(image) => convertImageToAttachment(image, "image/png") ?? image
|
|
18402
|
+
);
|
|
18403
|
+
}
|
|
18404
|
+
if (prompt.mask !== void 0) {
|
|
18405
|
+
processedPrompt.mask = convertImageToAttachment(prompt.mask, "image/png") ?? prompt.mask;
|
|
18406
|
+
}
|
|
18407
|
+
return processAISDKCallInput({
|
|
18408
|
+
...params,
|
|
18409
|
+
prompt: processedPrompt
|
|
18410
|
+
});
|
|
18411
|
+
}
|
|
17501
18412
|
function processAISDKWorkflowAgentCallInput(params) {
|
|
17502
18413
|
const processed = processAISDKCallInput(params);
|
|
17503
18414
|
return {
|
|
@@ -17636,6 +18547,12 @@ function prepareAISDKEmbedInput(params, self) {
|
|
|
17636
18547
|
metadata: extractMetadataFromEmbedParams(params, self)
|
|
17637
18548
|
};
|
|
17638
18549
|
}
|
|
18550
|
+
function prepareAISDKGenerateImageInput(params, self) {
|
|
18551
|
+
return {
|
|
18552
|
+
input: processAISDKGenerateImageInput(params).input,
|
|
18553
|
+
metadata: extractMetadataFromCallParams(params, self)
|
|
18554
|
+
};
|
|
18555
|
+
}
|
|
17639
18556
|
function prepareAISDKRerankInput(params, self) {
|
|
17640
18557
|
const { documents, query } = params;
|
|
17641
18558
|
return {
|
|
@@ -19011,6 +19928,57 @@ function processAISDKOutput(output, denyOutputPaths) {
|
|
|
19011
19928
|
}
|
|
19012
19929
|
return normalizeAISDKLoggedOutput(sanitized);
|
|
19013
19930
|
}
|
|
19931
|
+
function processAISDKGenerateImageOutput(output, denyOutputPaths) {
|
|
19932
|
+
if (!output || typeof output !== "object") {
|
|
19933
|
+
return output;
|
|
19934
|
+
}
|
|
19935
|
+
const summarized = {};
|
|
19936
|
+
for (const field of [
|
|
19937
|
+
"usage",
|
|
19938
|
+
"warnings",
|
|
19939
|
+
"providerMetadata",
|
|
19940
|
+
"experimental_providerMetadata",
|
|
19941
|
+
"responses"
|
|
19942
|
+
]) {
|
|
19943
|
+
const value = safeSerializableFieldRead(output, field);
|
|
19944
|
+
if (value !== void 0 && isSerializableOutputValue(value)) {
|
|
19945
|
+
summarized[field] = value;
|
|
19946
|
+
}
|
|
19947
|
+
}
|
|
19948
|
+
const images = safeSerializableFieldRead(output, "images");
|
|
19949
|
+
const image = safeSerializableFieldRead(output, "image");
|
|
19950
|
+
const generatedFiles = Array.isArray(images) && images.length > 0 ? images : image !== void 0 ? [image] : [];
|
|
19951
|
+
const loggedOutput = normalizeAISDKLoggedOutput(
|
|
19952
|
+
omit(summarized, denyOutputPaths)
|
|
19953
|
+
);
|
|
19954
|
+
if (generatedFiles.length > 0) {
|
|
19955
|
+
loggedOutput.images = generatedFiles.map(
|
|
19956
|
+
(file, index) => convertAISDKGeneratedFileToAttachment(file, index)
|
|
19957
|
+
);
|
|
19958
|
+
}
|
|
19959
|
+
return loggedOutput;
|
|
19960
|
+
}
|
|
19961
|
+
function convertAISDKGeneratedFileToAttachment(file, index) {
|
|
19962
|
+
if (!file || typeof file !== "object") {
|
|
19963
|
+
return file;
|
|
19964
|
+
}
|
|
19965
|
+
const generatedFile = file;
|
|
19966
|
+
const generatedMediaType = safeSerializableFieldRead(
|
|
19967
|
+
generatedFile,
|
|
19968
|
+
"mediaType"
|
|
19969
|
+
);
|
|
19970
|
+
const mediaType = typeof generatedMediaType === "string" ? generatedMediaType : "application/octet-stream";
|
|
19971
|
+
const data = safeSerializableFieldRead(generatedFile, "base64") ?? safeSerializableFieldRead(generatedFile, "uint8Array");
|
|
19972
|
+
const blob = convertDataToBlob(data, mediaType);
|
|
19973
|
+
if (blob) {
|
|
19974
|
+
return new Attachment({
|
|
19975
|
+
data: blob,
|
|
19976
|
+
filename: `generated_image_${index}.${getExtensionFromMediaType(mediaType)}`,
|
|
19977
|
+
contentType: mediaType
|
|
19978
|
+
});
|
|
19979
|
+
}
|
|
19980
|
+
return file;
|
|
19981
|
+
}
|
|
19014
19982
|
function processAISDKEmbeddingOutput(output, denyOutputPaths) {
|
|
19015
19983
|
if (!output || typeof output !== "object") {
|
|
19016
19984
|
return output;
|
|
@@ -19511,118 +20479,22 @@ var claudeAgentSDKChannels = defineChannels(
|
|
|
19511
20479
|
var CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION = "__braintrust_skip_local_tool_hooks";
|
|
19512
20480
|
|
|
19513
20481
|
// src/instrumentation/plugins/claude-agent-sdk-local-tool-context.ts
|
|
19514
|
-
var
|
|
19515
|
-
|
|
19516
|
-
)
|
|
19517
|
-
|
|
19518
|
-
const maybeIsoWithAsyncLocalStorage = isomorph_default;
|
|
19519
|
-
if (typeof maybeIsoWithAsyncLocalStorage.newAsyncLocalStorage === "function") {
|
|
19520
|
-
return maybeIsoWithAsyncLocalStorage.newAsyncLocalStorage();
|
|
19521
|
-
}
|
|
19522
|
-
let currentStore;
|
|
19523
|
-
return {
|
|
19524
|
-
enterWith(store) {
|
|
19525
|
-
currentStore = store;
|
|
19526
|
-
},
|
|
19527
|
-
getStore() {
|
|
19528
|
-
return currentStore;
|
|
19529
|
-
},
|
|
19530
|
-
run(store, callback) {
|
|
19531
|
-
const previousStore = currentStore;
|
|
19532
|
-
currentStore = store;
|
|
19533
|
-
try {
|
|
19534
|
-
return callback();
|
|
19535
|
-
} finally {
|
|
19536
|
-
currentStore = previousStore;
|
|
19537
|
-
}
|
|
19538
|
-
}
|
|
19539
|
-
};
|
|
19540
|
-
}
|
|
19541
|
-
var localToolContextStore = createLocalToolContextStore();
|
|
19542
|
-
var fallbackLocalToolParentResolver;
|
|
19543
|
-
function createClaudeLocalToolContext() {
|
|
19544
|
-
return {};
|
|
19545
|
-
}
|
|
19546
|
-
function runWithClaudeLocalToolContext(callback, context) {
|
|
19547
|
-
return localToolContextStore.run(
|
|
19548
|
-
context ?? createClaudeLocalToolContext(),
|
|
19549
|
-
callback
|
|
19550
|
-
);
|
|
19551
|
-
}
|
|
19552
|
-
function ensureClaudeLocalToolContext() {
|
|
19553
|
-
const existing = localToolContextStore.getStore();
|
|
19554
|
-
if (existing) {
|
|
19555
|
-
return existing;
|
|
19556
|
-
}
|
|
19557
|
-
const created = {};
|
|
19558
|
-
localToolContextStore.enterWith(created);
|
|
19559
|
-
return created;
|
|
19560
|
-
}
|
|
19561
|
-
function setClaudeLocalToolParentResolver(resolver) {
|
|
19562
|
-
fallbackLocalToolParentResolver = resolver;
|
|
19563
|
-
const context = ensureClaudeLocalToolContext();
|
|
19564
|
-
if (!context) {
|
|
19565
|
-
return;
|
|
19566
|
-
}
|
|
19567
|
-
context.resolveLocalToolParent = resolver;
|
|
19568
|
-
}
|
|
19569
|
-
function getClaudeLocalToolParentResolver() {
|
|
19570
|
-
return localToolContextStore.getStore()?.resolveLocalToolParent ?? fallbackLocalToolParentResolver;
|
|
20482
|
+
var localToolContextStore = isomorph_default.newAsyncLocalStorage();
|
|
20483
|
+
var localToolParentResolversByToolUseId = /* @__PURE__ */ new Map();
|
|
20484
|
+
function runWithClaudeLocalToolContext(callback, resolver) {
|
|
20485
|
+
return localToolContextStore.run(resolver, callback);
|
|
19571
20486
|
}
|
|
19572
|
-
function
|
|
19573
|
-
|
|
20487
|
+
function registerClaudeLocalToolParentResolver(toolUseId, resolver) {
|
|
20488
|
+
localToolParentResolversByToolUseId.set(toolUseId, resolver);
|
|
19574
20489
|
}
|
|
19575
|
-
function
|
|
19576
|
-
|
|
19577
|
-
|
|
19578
|
-
|
|
19579
|
-
const stream = result;
|
|
19580
|
-
const originalAsyncIterator = stream[Symbol.asyncIterator];
|
|
19581
|
-
if (originalAsyncIterator[LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED]) {
|
|
19582
|
-
return result;
|
|
20490
|
+
function getClaudeLocalToolParentResolver(toolUseId) {
|
|
20491
|
+
const currentResolver = localToolContextStore.getStore();
|
|
20492
|
+
if (!toolUseId) {
|
|
20493
|
+
return currentResolver;
|
|
19583
20494
|
}
|
|
19584
|
-
const
|
|
19585
|
-
|
|
19586
|
-
|
|
19587
|
-
if (!iterator || typeof iterator !== "object") {
|
|
19588
|
-
return iterator;
|
|
19589
|
-
}
|
|
19590
|
-
const patchMethod = (methodName) => {
|
|
19591
|
-
const originalMethod = Reflect.get(iterator, methodName);
|
|
19592
|
-
if (typeof originalMethod !== "function") {
|
|
19593
|
-
return;
|
|
19594
|
-
}
|
|
19595
|
-
Reflect.set(
|
|
19596
|
-
iterator,
|
|
19597
|
-
methodName,
|
|
19598
|
-
(...args) => runWithClaudeLocalToolContext(
|
|
19599
|
-
() => Reflect.apply(
|
|
19600
|
-
originalMethod,
|
|
19601
|
-
iterator,
|
|
19602
|
-
args
|
|
19603
|
-
),
|
|
19604
|
-
localToolContext
|
|
19605
|
-
)
|
|
19606
|
-
);
|
|
19607
|
-
};
|
|
19608
|
-
patchMethod("next");
|
|
19609
|
-
patchMethod("return");
|
|
19610
|
-
patchMethod("throw");
|
|
19611
|
-
return iterator;
|
|
19612
|
-
}, localToolContext);
|
|
19613
|
-
};
|
|
19614
|
-
Object.defineProperty(
|
|
19615
|
-
patchedAsyncIterator,
|
|
19616
|
-
LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED,
|
|
19617
|
-
{
|
|
19618
|
-
configurable: false,
|
|
19619
|
-
enumerable: false,
|
|
19620
|
-
value: true,
|
|
19621
|
-
writable: false
|
|
19622
|
-
}
|
|
19623
|
-
);
|
|
19624
|
-
Reflect.set(stream, Symbol.asyncIterator, patchedAsyncIterator);
|
|
19625
|
-
return result;
|
|
20495
|
+
const registeredResolver = localToolParentResolversByToolUseId.get(toolUseId);
|
|
20496
|
+
localToolParentResolversByToolUseId.delete(toolUseId);
|
|
20497
|
+
return currentResolver ?? registeredResolver;
|
|
19626
20498
|
}
|
|
19627
20499
|
|
|
19628
20500
|
// src/instrumentation/plugins/claude-agent-sdk-local-tool-spans.ts
|
|
@@ -19648,7 +20520,7 @@ function wrapLocalClaudeToolHandler(handler, getMetadata) {
|
|
|
19648
20520
|
const metadata = getMetadata();
|
|
19649
20521
|
const rawToolName = metadata.serverName ? `mcp__${metadata.serverName}__${metadata.toolName}` : metadata.toolName;
|
|
19650
20522
|
const toolUseId = getToolUseIdFromExtra(handlerArgs[1]);
|
|
19651
|
-
const localToolParentResolver = getClaudeLocalToolParentResolver();
|
|
20523
|
+
const localToolParentResolver = getClaudeLocalToolParentResolver(toolUseId);
|
|
19652
20524
|
const spanName = metadata.serverName ? `tool: ${metadata.serverName}/${metadata.toolName}` : `tool: ${metadata.toolName}`;
|
|
19653
20525
|
const runWithResolvedParent = async () => {
|
|
19654
20526
|
const parent = toolUseId && localToolParentResolver ? await localToolParentResolver(toolUseId).catch(() => void 0) : void 0;
|
|
@@ -20175,6 +21047,7 @@ function createToolTracingHooks(resolveParentSpan, taskIdToToolUseId, toolUseToP
|
|
|
20175
21047
|
}
|
|
20176
21048
|
}
|
|
20177
21049
|
if (skipLocalToolHooks && (isLocalToolUse(input.tool_name, mcpServers) || localToolHookNames.has(input.tool_name))) {
|
|
21050
|
+
registerClaudeLocalToolParentResolver(toolUseID, resolveParentSpan);
|
|
20178
21051
|
return {};
|
|
20179
21052
|
}
|
|
20180
21053
|
const parsed = parseToolName(input.tool_name);
|
|
@@ -20885,7 +21758,7 @@ async function finalizeQuerySpan(state) {
|
|
|
20885
21758
|
}
|
|
20886
21759
|
var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
20887
21760
|
onEnable() {
|
|
20888
|
-
this.
|
|
21761
|
+
this.interceptQuery();
|
|
20889
21762
|
}
|
|
20890
21763
|
onDisable() {
|
|
20891
21764
|
for (const unsubscribe of this.unsubscribers) {
|
|
@@ -20893,211 +21766,218 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
20893
21766
|
}
|
|
20894
21767
|
this.unsubscribers = [];
|
|
20895
21768
|
}
|
|
20896
|
-
|
|
20897
|
-
const
|
|
20898
|
-
|
|
20899
|
-
|
|
20900
|
-
|
|
20901
|
-
|
|
20902
|
-
|
|
20903
|
-
|
|
20904
|
-
|
|
20905
|
-
|
|
20906
|
-
|
|
20907
|
-
|
|
20908
|
-
|
|
20909
|
-
|
|
20910
|
-
|
|
20911
|
-
|
|
20912
|
-
|
|
20913
|
-
|
|
20914
|
-
|
|
20915
|
-
|
|
20916
|
-
try {
|
|
20917
|
-
for await (const message of promptStream) {
|
|
20918
|
-
capturedPromptMessages.push(message);
|
|
20919
|
-
yield message;
|
|
20920
|
-
}
|
|
20921
|
-
} finally {
|
|
20922
|
-
resolvePromptDone?.();
|
|
21769
|
+
interceptQuery() {
|
|
21770
|
+
const startQuery = (params) => {
|
|
21771
|
+
const originalPrompt = params.prompt;
|
|
21772
|
+
const options = params.options ?? {};
|
|
21773
|
+
const promptIsAsyncIterable = isAsyncIterable(originalPrompt);
|
|
21774
|
+
let promptStarted = false;
|
|
21775
|
+
let capturedPromptMessages;
|
|
21776
|
+
let resolvePromptDone;
|
|
21777
|
+
const promptDone = new Promise((resolve) => {
|
|
21778
|
+
resolvePromptDone = resolve;
|
|
21779
|
+
});
|
|
21780
|
+
if (promptIsAsyncIterable) {
|
|
21781
|
+
capturedPromptMessages = [];
|
|
21782
|
+
const promptStream = originalPrompt;
|
|
21783
|
+
params.prompt = (async function* () {
|
|
21784
|
+
promptStarted = true;
|
|
21785
|
+
try {
|
|
21786
|
+
for await (const message of promptStream) {
|
|
21787
|
+
capturedPromptMessages.push(message);
|
|
21788
|
+
yield message;
|
|
20923
21789
|
}
|
|
20924
|
-
}
|
|
20925
|
-
|
|
20926
|
-
const span = startSpan(
|
|
20927
|
-
withSpanInstrumentationName(
|
|
20928
|
-
{
|
|
20929
|
-
name: "Claude Agent",
|
|
20930
|
-
spanAttributes: {
|
|
20931
|
-
type: "task" /* TASK */
|
|
20932
|
-
}
|
|
20933
|
-
},
|
|
20934
|
-
INSTRUMENTATION_NAMES.CLAUDE_AGENT_SDK
|
|
20935
|
-
)
|
|
20936
|
-
);
|
|
20937
|
-
const startTime = getCurrentUnixTimestamp();
|
|
20938
|
-
try {
|
|
20939
|
-
span.log({
|
|
20940
|
-
input: typeof originalPrompt === "string" ? originalPrompt : promptIsAsyncIterable ? void 0 : originalPrompt !== void 0 ? String(originalPrompt) : void 0,
|
|
20941
|
-
metadata: filterSerializableOptions(options)
|
|
20942
|
-
});
|
|
20943
|
-
} catch (error) {
|
|
20944
|
-
console.error("Error extracting input for Claude Agent SDK:", error);
|
|
20945
|
-
}
|
|
20946
|
-
const activeToolSpans = /* @__PURE__ */ new Map();
|
|
20947
|
-
const activeLlmSpansByParentToolUse = /* @__PURE__ */ new Map();
|
|
20948
|
-
const conversationHistoryByParentKey = /* @__PURE__ */ new Map();
|
|
20949
|
-
const subAgentSpans = /* @__PURE__ */ new Map();
|
|
20950
|
-
const endedSubAgentSpans = /* @__PURE__ */ new Set();
|
|
20951
|
-
const toolUseToParent = /* @__PURE__ */ new Map();
|
|
20952
|
-
const latestLlmParentBySubAgentToolUse = /* @__PURE__ */ new Map();
|
|
20953
|
-
const latestRootLlmParentRef = {
|
|
20954
|
-
value: void 0
|
|
20955
|
-
};
|
|
20956
|
-
const subAgentDetailsByToolUseId = /* @__PURE__ */ new Map();
|
|
20957
|
-
const taskIdToToolUseId = /* @__PURE__ */ new Map();
|
|
20958
|
-
const promptMessagesByParentKey = /* @__PURE__ */ new Map();
|
|
20959
|
-
const promptSourcePriorityByParentKey = /* @__PURE__ */ new Map();
|
|
20960
|
-
const localToolContext = createClaudeLocalToolContext();
|
|
20961
|
-
const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
|
|
20962
|
-
const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
|
|
20963
|
-
const resolveToolUseParentSpan = async (toolUseID, context) => {
|
|
20964
|
-
const trackedParentToolUseId = toolUseToParent.get(toolUseID);
|
|
20965
|
-
const parentToolUseId = trackedParentToolUseId ?? (context?.agentId ? taskIdToToolUseId.get(context.agentId) ?? null : null);
|
|
20966
|
-
const parentKey = llmParentKey(parentToolUseId);
|
|
20967
|
-
const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
|
|
20968
|
-
const latestLlmParent = parentToolUseId ? latestLlmParentBySubAgentToolUse.get(parentToolUseId) : latestRootLlmParentRef.value;
|
|
20969
|
-
if (!activeLlmSpan && !latestLlmParent) {
|
|
20970
|
-
await ensureActiveLlmSpanForParentToolUse(
|
|
20971
|
-
span,
|
|
20972
|
-
activeLlmSpansByParentToolUse,
|
|
20973
|
-
subAgentDetailsByToolUseId,
|
|
20974
|
-
activeToolSpans,
|
|
20975
|
-
subAgentSpans,
|
|
20976
|
-
parentToolUseId,
|
|
20977
|
-
getCurrentUnixTimestamp()
|
|
20978
|
-
);
|
|
20979
|
-
}
|
|
20980
|
-
if (parentToolUseId) {
|
|
20981
|
-
const subAgentSpan = await ensureSubAgentSpan(
|
|
20982
|
-
subAgentDetailsByToolUseId,
|
|
20983
|
-
span,
|
|
20984
|
-
activeToolSpans,
|
|
20985
|
-
subAgentSpans,
|
|
20986
|
-
parentToolUseId
|
|
20987
|
-
);
|
|
20988
|
-
return subAgentSpan.export();
|
|
21790
|
+
} finally {
|
|
21791
|
+
resolvePromptDone?.();
|
|
20989
21792
|
}
|
|
20990
|
-
|
|
20991
|
-
|
|
20992
|
-
|
|
20993
|
-
|
|
20994
|
-
|
|
20995
|
-
|
|
20996
|
-
|
|
20997
|
-
|
|
20998
|
-
|
|
20999
|
-
|
|
21000
|
-
|
|
21001
|
-
|
|
21002
|
-
|
|
21003
|
-
|
|
21004
|
-
|
|
21005
|
-
|
|
21006
|
-
|
|
21007
|
-
|
|
21008
|
-
spans.set(event, {
|
|
21009
|
-
activeLlmSpansByParentToolUse,
|
|
21010
|
-
activePartialMessageIdByParentKey: /* @__PURE__ */ new Map(),
|
|
21011
|
-
activeToolSpans,
|
|
21012
|
-
conversationHistoryByParentKey,
|
|
21013
|
-
capturedPromptMessages,
|
|
21014
|
-
currentMessageId: void 0,
|
|
21015
|
-
currentMessageStartTime: startTime,
|
|
21016
|
-
currentMessages: [],
|
|
21017
|
-
endedSubAgentSpans,
|
|
21018
|
-
finalOutputUsageMessageIds: /* @__PURE__ */ new Set(),
|
|
21019
|
-
finalResults: [],
|
|
21020
|
-
options: optionsWithHooks,
|
|
21021
|
-
originalPrompt,
|
|
21022
|
-
processing: Promise.resolve(),
|
|
21023
|
-
promptDone,
|
|
21024
|
-
promptMessagesByParentKey,
|
|
21025
|
-
promptStarted: () => promptStarted,
|
|
21026
|
-
promptSourcePriorityByParentKey,
|
|
21027
|
-
span,
|
|
21028
|
-
subAgentDetailsByToolUseId,
|
|
21029
|
-
subAgentSpans,
|
|
21030
|
-
taskIdToToolUseId,
|
|
21031
|
-
latestLlmParentBySubAgentToolUse,
|
|
21032
|
-
latestRootLlmParentRef,
|
|
21033
|
-
toolUseToParent,
|
|
21034
|
-
usageByMessageId: /* @__PURE__ */ new Map(),
|
|
21035
|
-
localToolContext
|
|
21793
|
+
})();
|
|
21794
|
+
}
|
|
21795
|
+
const span = startSpan(
|
|
21796
|
+
withSpanInstrumentationName(
|
|
21797
|
+
{
|
|
21798
|
+
name: "Claude Agent",
|
|
21799
|
+
spanAttributes: {
|
|
21800
|
+
type: "task" /* TASK */
|
|
21801
|
+
}
|
|
21802
|
+
},
|
|
21803
|
+
INSTRUMENTATION_NAMES.CLAUDE_AGENT_SDK
|
|
21804
|
+
)
|
|
21805
|
+
);
|
|
21806
|
+
const startTime = getCurrentUnixTimestamp();
|
|
21807
|
+
try {
|
|
21808
|
+
span.log({
|
|
21809
|
+
input: typeof originalPrompt === "string" ? originalPrompt : promptIsAsyncIterable ? void 0 : originalPrompt !== void 0 ? String(originalPrompt) : void 0,
|
|
21810
|
+
metadata: filterSerializableOptions(options)
|
|
21036
21811
|
});
|
|
21037
|
-
}
|
|
21038
|
-
|
|
21039
|
-
|
|
21040
|
-
|
|
21041
|
-
|
|
21042
|
-
|
|
21043
|
-
|
|
21044
|
-
|
|
21045
|
-
|
|
21046
|
-
|
|
21047
|
-
|
|
21048
|
-
|
|
21049
|
-
|
|
21050
|
-
|
|
21051
|
-
|
|
21052
|
-
|
|
21053
|
-
|
|
21054
|
-
|
|
21055
|
-
|
|
21056
|
-
|
|
21057
|
-
|
|
21058
|
-
|
|
21059
|
-
|
|
21060
|
-
|
|
21061
|
-
|
|
21062
|
-
|
|
21063
|
-
|
|
21064
|
-
|
|
21065
|
-
|
|
21066
|
-
|
|
21067
|
-
|
|
21068
|
-
|
|
21069
|
-
|
|
21070
|
-
|
|
21071
|
-
|
|
21072
|
-
})
|
|
21073
|
-
});
|
|
21074
|
-
return;
|
|
21075
|
-
}
|
|
21076
|
-
try {
|
|
21077
|
-
state.span.log({ output: eventResult });
|
|
21078
|
-
} catch (error) {
|
|
21079
|
-
console.error("Error extracting output for Claude Agent SDK:", error);
|
|
21080
|
-
} finally {
|
|
21081
|
-
state.span.end();
|
|
21082
|
-
spans.delete(event);
|
|
21812
|
+
} catch (error) {
|
|
21813
|
+
console.error("Error extracting input for Claude Agent SDK:", error);
|
|
21814
|
+
}
|
|
21815
|
+
const activeToolSpans = /* @__PURE__ */ new Map();
|
|
21816
|
+
const activeLlmSpansByParentToolUse = /* @__PURE__ */ new Map();
|
|
21817
|
+
const conversationHistoryByParentKey = /* @__PURE__ */ new Map();
|
|
21818
|
+
const subAgentSpans = /* @__PURE__ */ new Map();
|
|
21819
|
+
const endedSubAgentSpans = /* @__PURE__ */ new Set();
|
|
21820
|
+
const toolUseToParent = /* @__PURE__ */ new Map();
|
|
21821
|
+
const latestLlmParentBySubAgentToolUse = /* @__PURE__ */ new Map();
|
|
21822
|
+
const latestRootLlmParentRef = {
|
|
21823
|
+
value: void 0
|
|
21824
|
+
};
|
|
21825
|
+
const subAgentDetailsByToolUseId = /* @__PURE__ */ new Map();
|
|
21826
|
+
const taskIdToToolUseId = /* @__PURE__ */ new Map();
|
|
21827
|
+
const promptMessagesByParentKey = /* @__PURE__ */ new Map();
|
|
21828
|
+
const promptSourcePriorityByParentKey = /* @__PURE__ */ new Map();
|
|
21829
|
+
const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
|
|
21830
|
+
const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
|
|
21831
|
+
const resolveToolUseParentSpan = async (toolUseID, context) => {
|
|
21832
|
+
const trackedParentToolUseId = toolUseToParent.get(toolUseID);
|
|
21833
|
+
const parentToolUseId = trackedParentToolUseId ?? (context?.agentId ? taskIdToToolUseId.get(context.agentId) ?? null : null);
|
|
21834
|
+
const parentKey = llmParentKey(parentToolUseId);
|
|
21835
|
+
const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
|
|
21836
|
+
const latestLlmParent = parentToolUseId ? latestLlmParentBySubAgentToolUse.get(parentToolUseId) : latestRootLlmParentRef.value;
|
|
21837
|
+
if (!activeLlmSpan && !latestLlmParent) {
|
|
21838
|
+
await ensureActiveLlmSpanForParentToolUse(
|
|
21839
|
+
span,
|
|
21840
|
+
activeLlmSpansByParentToolUse,
|
|
21841
|
+
subAgentDetailsByToolUseId,
|
|
21842
|
+
activeToolSpans,
|
|
21843
|
+
subAgentSpans,
|
|
21844
|
+
parentToolUseId,
|
|
21845
|
+
getCurrentUnixTimestamp()
|
|
21846
|
+
);
|
|
21083
21847
|
}
|
|
21084
|
-
|
|
21085
|
-
|
|
21086
|
-
|
|
21087
|
-
|
|
21088
|
-
|
|
21848
|
+
if (parentToolUseId) {
|
|
21849
|
+
const subAgentSpan = await ensureSubAgentSpan(
|
|
21850
|
+
subAgentDetailsByToolUseId,
|
|
21851
|
+
span,
|
|
21852
|
+
activeToolSpans,
|
|
21853
|
+
subAgentSpans,
|
|
21854
|
+
parentToolUseId
|
|
21855
|
+
);
|
|
21856
|
+
return subAgentSpan.export();
|
|
21089
21857
|
}
|
|
21090
|
-
|
|
21091
|
-
|
|
21858
|
+
return span.export();
|
|
21859
|
+
};
|
|
21860
|
+
const optionsWithHooks = injectTracingHooks(
|
|
21861
|
+
options,
|
|
21862
|
+
resolveToolUseParentSpan,
|
|
21863
|
+
taskIdToToolUseId,
|
|
21864
|
+
toolUseToParent,
|
|
21865
|
+
activeToolSpans,
|
|
21866
|
+
localToolHookNames,
|
|
21867
|
+
skipLocalToolHooks,
|
|
21868
|
+
subAgentDetailsByToolUseId,
|
|
21869
|
+
subAgentSpans,
|
|
21870
|
+
endedSubAgentSpans
|
|
21871
|
+
);
|
|
21872
|
+
params.options = optionsWithHooks;
|
|
21873
|
+
return {
|
|
21874
|
+
activeLlmSpansByParentToolUse,
|
|
21875
|
+
activePartialMessageIdByParentKey: /* @__PURE__ */ new Map(),
|
|
21876
|
+
activeToolSpans,
|
|
21877
|
+
conversationHistoryByParentKey,
|
|
21878
|
+
capturedPromptMessages,
|
|
21879
|
+
currentMessageId: void 0,
|
|
21880
|
+
currentMessageStartTime: startTime,
|
|
21881
|
+
currentMessages: [],
|
|
21882
|
+
endedSubAgentSpans,
|
|
21883
|
+
finalOutputUsageMessageIds: /* @__PURE__ */ new Set(),
|
|
21884
|
+
finalResults: [],
|
|
21885
|
+
options: optionsWithHooks,
|
|
21886
|
+
originalPrompt,
|
|
21887
|
+
processing: Promise.resolve(),
|
|
21888
|
+
promptDone,
|
|
21889
|
+
promptMessagesByParentKey,
|
|
21890
|
+
promptStarted: () => promptStarted,
|
|
21891
|
+
promptSourcePriorityByParentKey,
|
|
21892
|
+
span,
|
|
21893
|
+
subAgentDetailsByToolUseId,
|
|
21894
|
+
subAgentSpans,
|
|
21895
|
+
taskIdToToolUseId,
|
|
21896
|
+
latestLlmParentBySubAgentToolUse,
|
|
21897
|
+
latestRootLlmParentRef,
|
|
21898
|
+
toolUseToParent,
|
|
21899
|
+
usageByMessageId: /* @__PURE__ */ new Map(),
|
|
21900
|
+
localToolParentResolver: resolveToolUseParentSpan
|
|
21901
|
+
};
|
|
21902
|
+
};
|
|
21903
|
+
const finishQuery = (state, result) => {
|
|
21904
|
+
if (isAsyncIterable(result)) {
|
|
21905
|
+
patchStreamIfNeeded(result, {
|
|
21906
|
+
aroundNext: (callback) => runWithClaudeLocalToolContext(
|
|
21907
|
+
callback,
|
|
21908
|
+
state.localToolParentResolver
|
|
21909
|
+
),
|
|
21910
|
+
onChunk: (message) => {
|
|
21911
|
+
maybeTrackToolUseContext(state, message);
|
|
21912
|
+
state.processing = state.processing.then(() => handleStreamMessage(state, message)).catch((error) => {
|
|
21913
|
+
console.error(
|
|
21914
|
+
"Error processing Claude Agent SDK stream chunk:",
|
|
21915
|
+
error
|
|
21916
|
+
);
|
|
21917
|
+
});
|
|
21918
|
+
},
|
|
21919
|
+
onComplete: () => state.processing.then(() => finalizeQuerySpan(state)),
|
|
21920
|
+
onError: (error) => state.processing.then(() => {
|
|
21921
|
+
state.span.log({ error: error.message });
|
|
21922
|
+
}).then(() => finalizeQuerySpan(state))
|
|
21092
21923
|
});
|
|
21924
|
+
return;
|
|
21925
|
+
}
|
|
21926
|
+
try {
|
|
21927
|
+
state.span.log({ output: result });
|
|
21928
|
+
} catch (error) {
|
|
21929
|
+
console.error("Error extracting output for Claude Agent SDK:", error);
|
|
21930
|
+
} finally {
|
|
21093
21931
|
state.span.end();
|
|
21094
|
-
spans.delete(event);
|
|
21095
21932
|
}
|
|
21096
21933
|
};
|
|
21097
|
-
|
|
21098
|
-
|
|
21099
|
-
|
|
21100
|
-
|
|
21934
|
+
this.unsubscribers.push(
|
|
21935
|
+
claudeAgentSDKChannels.query.intercept((target, thisArg, args) => {
|
|
21936
|
+
let state;
|
|
21937
|
+
try {
|
|
21938
|
+
args[0] ??= {};
|
|
21939
|
+
state = startQuery(args[0]);
|
|
21940
|
+
} catch (error) {
|
|
21941
|
+
debugLogger.error(
|
|
21942
|
+
"Error starting Claude Agent SDK instrumentation:",
|
|
21943
|
+
error
|
|
21944
|
+
);
|
|
21945
|
+
}
|
|
21946
|
+
const invokeTarget = () => Reflect.apply(target, thisArg, args);
|
|
21947
|
+
try {
|
|
21948
|
+
const result = state ? runWithClaudeLocalToolContext(
|
|
21949
|
+
invokeTarget,
|
|
21950
|
+
state.localToolParentResolver
|
|
21951
|
+
) : invokeTarget();
|
|
21952
|
+
if (state) {
|
|
21953
|
+
try {
|
|
21954
|
+
finishQuery(state, result);
|
|
21955
|
+
} catch (error) {
|
|
21956
|
+
debugLogger.error(
|
|
21957
|
+
"Error finalizing Claude Agent SDK instrumentation:",
|
|
21958
|
+
error
|
|
21959
|
+
);
|
|
21960
|
+
}
|
|
21961
|
+
}
|
|
21962
|
+
return result;
|
|
21963
|
+
} catch (error) {
|
|
21964
|
+
if (state) {
|
|
21965
|
+
try {
|
|
21966
|
+
state.span.log({
|
|
21967
|
+
error: error instanceof Error ? error.message : String(error)
|
|
21968
|
+
});
|
|
21969
|
+
state.span.end();
|
|
21970
|
+
} catch (instrumentationError) {
|
|
21971
|
+
debugLogger.error(
|
|
21972
|
+
"Error handling Claude Agent SDK instrumentation failure:",
|
|
21973
|
+
instrumentationError
|
|
21974
|
+
);
|
|
21975
|
+
}
|
|
21976
|
+
}
|
|
21977
|
+
throw error;
|
|
21978
|
+
}
|
|
21979
|
+
})
|
|
21980
|
+
);
|
|
21101
21981
|
}
|
|
21102
21982
|
};
|
|
21103
21983
|
|
|
@@ -25211,7 +26091,7 @@ function patchOpenRouterCallModelResult(args) {
|
|
|
25211
26091
|
span,
|
|
25212
26092
|
() => originalMethod.apply(resultLike, args2)
|
|
25213
26093
|
);
|
|
25214
|
-
if (!
|
|
26094
|
+
if (!isAsyncIterable3(stream)) {
|
|
25215
26095
|
return stream;
|
|
25216
26096
|
}
|
|
25217
26097
|
return wrapAsyncIterableWithSpan({
|
|
@@ -25406,7 +26286,7 @@ function wrapAsyncIterableWithSpan(args) {
|
|
|
25406
26286
|
}
|
|
25407
26287
|
};
|
|
25408
26288
|
}
|
|
25409
|
-
function
|
|
26289
|
+
function isAsyncIterable3(value) {
|
|
25410
26290
|
return !!value && (typeof value === "object" || typeof value === "function") && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
|
|
25411
26291
|
}
|
|
25412
26292
|
function normalizeError(error) {
|
|
@@ -26284,7 +27164,7 @@ function patchOpenRouterCallModelResult2(args) {
|
|
|
26284
27164
|
span,
|
|
26285
27165
|
() => originalMethod.apply(resultLike, args2)
|
|
26286
27166
|
);
|
|
26287
|
-
if (!
|
|
27167
|
+
if (!isAsyncIterable4(stream)) {
|
|
26288
27168
|
return stream;
|
|
26289
27169
|
}
|
|
26290
27170
|
return wrapAsyncIterableWithSpan2({
|
|
@@ -26479,7 +27359,7 @@ function wrapAsyncIterableWithSpan2(args) {
|
|
|
26479
27359
|
}
|
|
26480
27360
|
};
|
|
26481
27361
|
}
|
|
26482
|
-
function
|
|
27362
|
+
function isAsyncIterable4(value) {
|
|
26483
27363
|
return !!value && (typeof value === "object" || typeof value === "function") && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
|
|
26484
27364
|
}
|
|
26485
27365
|
function normalizeError2(error) {
|
|
@@ -32471,12 +33351,14 @@ function getMetricsFromResponse(response) {
|
|
|
32471
33351
|
continue;
|
|
32472
33352
|
}
|
|
32473
33353
|
const inputTokenDetails = usageMetadata.input_token_details;
|
|
33354
|
+
const outputTokenDetails = usageMetadata.output_token_details;
|
|
32474
33355
|
return normalizeTokenMetrics({
|
|
32475
33356
|
total_tokens: usageMetadata.total_tokens,
|
|
32476
33357
|
prompt_tokens: usageMetadata.input_tokens,
|
|
32477
33358
|
completion_tokens: usageMetadata.output_tokens,
|
|
32478
33359
|
prompt_cache_creation_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_creation : void 0,
|
|
32479
|
-
prompt_cached_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_read : void 0
|
|
33360
|
+
prompt_cached_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_read : void 0,
|
|
33361
|
+
completion_reasoning_tokens: isRecord(outputTokenDetails) ? outputTokenDetails.reasoning : void 0
|
|
32480
33362
|
});
|
|
32481
33363
|
}
|
|
32482
33364
|
const llmOutput = response.llmOutput || {};
|
|
@@ -33063,6 +33945,9 @@ var piCodingAgentChannels = defineChannels(
|
|
|
33063
33945
|
// src/instrumentation/plugins/pi-coding-agent-plugin.ts
|
|
33064
33946
|
var piAgentPatchStates = /* @__PURE__ */ new WeakMap();
|
|
33065
33947
|
var piAgentEventSubscriptions = /* @__PURE__ */ new WeakSet();
|
|
33948
|
+
var PI_TOOL_EXECUTE_WRAPPED = /* @__PURE__ */ Symbol.for(
|
|
33949
|
+
"braintrust.pi_coding_agent.tool_execute_wrapped"
|
|
33950
|
+
);
|
|
33066
33951
|
var piPromptContextStore;
|
|
33067
33952
|
var PiCodingAgentPlugin = class extends BasePlugin {
|
|
33068
33953
|
activePromptStates = /* @__PURE__ */ new Set();
|
|
@@ -33143,6 +34028,7 @@ function startPiPromptRun(event, onFinalize) {
|
|
|
33143
34028
|
return void 0;
|
|
33144
34029
|
}
|
|
33145
34030
|
installPiAgentInstrumentation(agent);
|
|
34031
|
+
wrapPiToolExecutors(agent.state?.tools);
|
|
33146
34032
|
const metadata = {
|
|
33147
34033
|
...extractSessionMetadata(session),
|
|
33148
34034
|
...extractPromptOptionsMetadata(event.arguments[1]),
|
|
@@ -33187,7 +34073,7 @@ function extractSession(event) {
|
|
|
33187
34073
|
return isObject(candidate) && typeof candidate.prompt === "function" ? candidate : void 0;
|
|
33188
34074
|
}
|
|
33189
34075
|
function isPiAgent(value) {
|
|
33190
|
-
return isObject(value) && typeof value.streamFn === "function" && typeof value.subscribe === "function";
|
|
34076
|
+
return isObject(value) && (typeof value.streamFunction === "function" || typeof value.streamFn === "function") && typeof value.subscribe === "function";
|
|
33191
34077
|
}
|
|
33192
34078
|
function promptContextStore() {
|
|
33193
34079
|
piPromptContextStore ??= isomorph_default.newAsyncLocalStorage();
|
|
@@ -33197,17 +34083,21 @@ function currentPiPromptState() {
|
|
|
33197
34083
|
return promptContextStore().getStore();
|
|
33198
34084
|
}
|
|
33199
34085
|
function installPiAgentInstrumentation(agent) {
|
|
34086
|
+
const property = typeof agent.streamFunction === "function" ? "streamFunction" : "streamFn";
|
|
34087
|
+
const streamFunction = agent[property];
|
|
33200
34088
|
const existing = piAgentPatchStates.get(agent);
|
|
33201
|
-
if (!existing ||
|
|
34089
|
+
if (streamFunction && (!existing || existing.property !== property || streamFunction !== existing.wrappedStreamFunction)) {
|
|
33202
34090
|
const patchState = {
|
|
33203
|
-
|
|
33204
|
-
|
|
34091
|
+
originalStreamFunction: streamFunction,
|
|
34092
|
+
property,
|
|
34093
|
+
wrappedStreamFunction: streamFunction
|
|
33205
34094
|
};
|
|
33206
|
-
patchState.
|
|
34095
|
+
patchState.wrappedStreamFunction = makeInstrumentedStreamFunction(
|
|
33207
34096
|
agent,
|
|
33208
|
-
patchState.
|
|
34097
|
+
patchState.originalStreamFunction,
|
|
34098
|
+
property
|
|
33209
34099
|
);
|
|
33210
|
-
agent
|
|
34100
|
+
agent[property] = patchState.wrappedStreamFunction;
|
|
33211
34101
|
piAgentPatchStates.set(agent, patchState);
|
|
33212
34102
|
}
|
|
33213
34103
|
if (piAgentEventSubscriptions.has(agent)) {
|
|
@@ -33232,14 +34122,21 @@ function installPiAgentInstrumentation(agent) {
|
|
|
33232
34122
|
logInstrumentationError4("Pi Coding Agent event subscription", error);
|
|
33233
34123
|
}
|
|
33234
34124
|
}
|
|
33235
|
-
function
|
|
33236
|
-
return async function
|
|
33237
|
-
const invokeOriginal = () => Reflect.apply(
|
|
34125
|
+
function makeInstrumentedStreamFunction(agent, originalStreamFunction, property) {
|
|
34126
|
+
return async function instrumentedPiStreamFunction(model, context, options) {
|
|
34127
|
+
const invokeOriginal = () => Reflect.apply(originalStreamFunction, this, [model, context, options]);
|
|
33238
34128
|
const state = currentPiPromptState();
|
|
33239
34129
|
if (!state || state.agent !== agent || state.finalized) {
|
|
33240
34130
|
return invokeOriginal();
|
|
33241
34131
|
}
|
|
33242
|
-
|
|
34132
|
+
wrapPiToolExecutors(context.tools);
|
|
34133
|
+
const llmState = await startPiLlmSpan(
|
|
34134
|
+
state,
|
|
34135
|
+
model,
|
|
34136
|
+
context,
|
|
34137
|
+
property,
|
|
34138
|
+
options
|
|
34139
|
+
);
|
|
33243
34140
|
try {
|
|
33244
34141
|
const stream = await runWithAutoInstrumentationSuppressed(invokeOriginal);
|
|
33245
34142
|
return patchAssistantMessageStream(stream, state, llmState);
|
|
@@ -33249,12 +34146,39 @@ function makeInstrumentedStreamFn(agent, originalStreamFn) {
|
|
|
33249
34146
|
}
|
|
33250
34147
|
};
|
|
33251
34148
|
}
|
|
33252
|
-
|
|
34149
|
+
function wrapPiToolExecutors(tools) {
|
|
34150
|
+
if (!tools) {
|
|
34151
|
+
return;
|
|
34152
|
+
}
|
|
34153
|
+
for (const tool of tools) {
|
|
34154
|
+
try {
|
|
34155
|
+
const execute = tool.execute;
|
|
34156
|
+
if (typeof execute !== "function" || execute[PI_TOOL_EXECUTE_WRAPPED]) {
|
|
34157
|
+
continue;
|
|
34158
|
+
}
|
|
34159
|
+
const wrappedExecute = function(...args) {
|
|
34160
|
+
return runWithAutoInstrumentationAllowed(
|
|
34161
|
+
() => Reflect.apply(execute, this, args)
|
|
34162
|
+
);
|
|
34163
|
+
};
|
|
34164
|
+
Object.defineProperty(wrappedExecute, PI_TOOL_EXECUTE_WRAPPED, {
|
|
34165
|
+
configurable: false,
|
|
34166
|
+
enumerable: false,
|
|
34167
|
+
value: true,
|
|
34168
|
+
writable: false
|
|
34169
|
+
});
|
|
34170
|
+
tool.execute = wrappedExecute;
|
|
34171
|
+
} catch (error) {
|
|
34172
|
+
logInstrumentationError4("Pi Coding Agent tool wrapping", error);
|
|
34173
|
+
}
|
|
34174
|
+
}
|
|
34175
|
+
}
|
|
34176
|
+
async function startPiLlmSpan(state, model, context, property, options) {
|
|
33253
34177
|
const metadata = {
|
|
33254
34178
|
...extractModelMetadata2(model),
|
|
33255
34179
|
...extractStreamOptionsMetadata(options),
|
|
33256
34180
|
...extractToolMetadata(context.tools),
|
|
33257
|
-
"pi_coding_agent.operation":
|
|
34181
|
+
"pi_coding_agent.operation": `agent.${property}`
|
|
33258
34182
|
};
|
|
33259
34183
|
const span = startSpan(
|
|
33260
34184
|
withSpanInstrumentationName(
|
|
@@ -33420,35 +34344,26 @@ async function startPiToolSpan(state, event) {
|
|
|
33420
34344
|
if (!event.toolCallId || state.activeToolSpans.has(event.toolCallId)) {
|
|
33421
34345
|
return;
|
|
33422
34346
|
}
|
|
33423
|
-
const restoreAutoInstrumentation = enterAutoInstrumentationAllowed();
|
|
33424
34347
|
const metadata = {
|
|
33425
34348
|
"gen_ai.tool.call.id": event.toolCallId,
|
|
33426
34349
|
"gen_ai.tool.name": event.toolName,
|
|
33427
34350
|
"pi_coding_agent.tool.name": event.toolName
|
|
33428
34351
|
};
|
|
33429
|
-
|
|
33430
|
-
|
|
33431
|
-
|
|
33432
|
-
{
|
|
33433
|
-
|
|
33434
|
-
|
|
33435
|
-
metadata
|
|
33436
|
-
},
|
|
33437
|
-
name: event.toolName || "tool",
|
|
33438
|
-
parent: await state.span.export(),
|
|
33439
|
-
spanAttributes: { type: "tool" /* TOOL */ }
|
|
34352
|
+
const span = startSpan(
|
|
34353
|
+
withSpanInstrumentationName(
|
|
34354
|
+
{
|
|
34355
|
+
event: {
|
|
34356
|
+
input: event.args,
|
|
34357
|
+
metadata
|
|
33440
34358
|
},
|
|
33441
|
-
|
|
33442
|
-
|
|
33443
|
-
|
|
33444
|
-
|
|
33445
|
-
|
|
33446
|
-
|
|
33447
|
-
|
|
33448
|
-
|
|
33449
|
-
restoreAutoInstrumentation();
|
|
33450
|
-
throw error;
|
|
33451
|
-
}
|
|
34359
|
+
name: event.toolName || "tool",
|
|
34360
|
+
parent: await state.span.export(),
|
|
34361
|
+
spanAttributes: { type: "tool" /* TOOL */ }
|
|
34362
|
+
},
|
|
34363
|
+
INSTRUMENTATION_NAMES.PI_CODING_AGENT
|
|
34364
|
+
)
|
|
34365
|
+
);
|
|
34366
|
+
state.activeToolSpans.set(event.toolCallId, { span });
|
|
33452
34367
|
}
|
|
33453
34368
|
function finishPiToolSpan(state, event) {
|
|
33454
34369
|
const toolState = state.activeToolSpans.get(event.toolCallId);
|
|
@@ -33469,11 +34384,7 @@ function finishPiToolSpan(state, event) {
|
|
|
33469
34384
|
output: event.result
|
|
33470
34385
|
});
|
|
33471
34386
|
} finally {
|
|
33472
|
-
|
|
33473
|
-
toolState.span.end();
|
|
33474
|
-
} finally {
|
|
33475
|
-
toolState.restoreAutoInstrumentation?.();
|
|
33476
|
-
}
|
|
34387
|
+
toolState.span.end();
|
|
33477
34388
|
}
|
|
33478
34389
|
}
|
|
33479
34390
|
function finishPiPromptRun(state, error) {
|
|
@@ -33544,14 +34455,10 @@ function finishPiLlmSpan(promptState, llmState, message, error) {
|
|
|
33544
34455
|
}
|
|
33545
34456
|
function finishOpenToolSpans(state, error) {
|
|
33546
34457
|
for (const [, toolState] of state.activeToolSpans) {
|
|
33547
|
-
|
|
33548
|
-
|
|
33549
|
-
|
|
33550
|
-
|
|
33551
|
-
toolState.span.end();
|
|
33552
|
-
} finally {
|
|
33553
|
-
toolState.restoreAutoInstrumentation?.();
|
|
33554
|
-
}
|
|
34458
|
+
safeLog4(toolState.span, {
|
|
34459
|
+
error: error ? toLoggedError(error) : "Pi tool did not complete"
|
|
34460
|
+
});
|
|
34461
|
+
toolState.span.end();
|
|
33555
34462
|
}
|
|
33556
34463
|
state.activeToolSpans.clear();
|
|
33557
34464
|
}
|
|
@@ -33870,12 +34777,12 @@ var MAX_STRANDS_STRING_ATTACHMENT_CACHE_ENTRIES = 32;
|
|
|
33870
34777
|
var StrandsAgentSDKPlugin = class extends BasePlugin {
|
|
33871
34778
|
activeChildParents = /* @__PURE__ */ new WeakMap();
|
|
33872
34779
|
onEnable() {
|
|
33873
|
-
this.
|
|
33874
|
-
this.
|
|
34780
|
+
this.interceptAgentStream();
|
|
34781
|
+
this.interceptMultiAgentStream(
|
|
33875
34782
|
strandsAgentSDKChannels.graphStream,
|
|
33876
34783
|
"Graph.stream"
|
|
33877
34784
|
);
|
|
33878
|
-
this.
|
|
34785
|
+
this.interceptMultiAgentStream(
|
|
33879
34786
|
strandsAgentSDKChannels.swarmStream,
|
|
33880
34787
|
"Swarm.stream"
|
|
33881
34788
|
);
|
|
@@ -33886,122 +34793,92 @@ var StrandsAgentSDKPlugin = class extends BasePlugin {
|
|
|
33886
34793
|
}
|
|
33887
34794
|
this.unsubscribers = [];
|
|
33888
34795
|
}
|
|
33889
|
-
|
|
33890
|
-
|
|
33891
|
-
|
|
33892
|
-
|
|
33893
|
-
|
|
33894
|
-
|
|
33895
|
-
|
|
33896
|
-
|
|
33897
|
-
|
|
33898
|
-
|
|
33899
|
-
|
|
33900
|
-
|
|
33901
|
-
|
|
33902
|
-
|
|
33903
|
-
|
|
33904
|
-
|
|
33905
|
-
const result = event.result;
|
|
33906
|
-
if (isAsyncIterable(result)) {
|
|
33907
|
-
patchStreamIfNeeded(result, {
|
|
33908
|
-
aroundNext: (callback) => runWithAutoInstrumentationSuppressed(callback),
|
|
33909
|
-
onChunk: (chunk) => handleAgentStreamEvent(state, chunk),
|
|
33910
|
-
onComplete: () => {
|
|
33911
|
-
finalizeAgentStream(state);
|
|
33912
|
-
states.delete(event);
|
|
33913
|
-
},
|
|
33914
|
-
onError: (error) => {
|
|
33915
|
-
finalizeAgentStream(state, error);
|
|
33916
|
-
states.delete(event);
|
|
33917
|
-
}
|
|
33918
|
-
});
|
|
33919
|
-
return;
|
|
33920
|
-
}
|
|
33921
|
-
finalizeAgentStream(state, void 0, result);
|
|
33922
|
-
states.delete(event);
|
|
33923
|
-
},
|
|
33924
|
-
error: (event) => {
|
|
33925
|
-
const state = states.get(event);
|
|
33926
|
-
if (!state || !event.error) {
|
|
33927
|
-
return;
|
|
33928
|
-
}
|
|
33929
|
-
finalizeAgentStream(state, event.error);
|
|
33930
|
-
states.delete(event);
|
|
33931
|
-
}
|
|
33932
|
-
};
|
|
33933
|
-
channel2.subscribe(handlers);
|
|
33934
|
-
this.unsubscribers.push(() => {
|
|
33935
|
-
unbindAutoInstrumentationSuppression?.();
|
|
33936
|
-
channel2.unsubscribe(handlers);
|
|
33937
|
-
});
|
|
34796
|
+
interceptAgentStream() {
|
|
34797
|
+
this.unsubscribers.push(
|
|
34798
|
+
strandsAgentSDKChannels.agentStream.intercept(
|
|
34799
|
+
(target, thisArg, args, additional) => instrumentStrandsStreamInvocation({
|
|
34800
|
+
finalize: finalizeAgentStream,
|
|
34801
|
+
handleChunk: handleAgentStreamEvent,
|
|
34802
|
+
invoke: () => Reflect.apply(target, thisArg, args),
|
|
34803
|
+
name: "Strands Agent SDK",
|
|
34804
|
+
start: () => startAgentStream(
|
|
34805
|
+
args[0],
|
|
34806
|
+
extractAgent(additional.agent, thisArg),
|
|
34807
|
+
this.activeChildParents
|
|
34808
|
+
)
|
|
34809
|
+
})
|
|
34810
|
+
)
|
|
34811
|
+
);
|
|
33938
34812
|
}
|
|
33939
|
-
|
|
33940
|
-
|
|
33941
|
-
|
|
33942
|
-
|
|
33943
|
-
|
|
33944
|
-
|
|
33945
|
-
|
|
33946
|
-
|
|
33947
|
-
|
|
33948
|
-
|
|
33949
|
-
|
|
33950
|
-
|
|
33951
|
-
|
|
33952
|
-
|
|
33953
|
-
|
|
33954
|
-
|
|
33955
|
-
|
|
33956
|
-
|
|
33957
|
-
|
|
33958
|
-
}
|
|
33959
|
-
|
|
33960
|
-
|
|
33961
|
-
|
|
33962
|
-
|
|
33963
|
-
|
|
33964
|
-
|
|
33965
|
-
|
|
33966
|
-
|
|
33967
|
-
|
|
33968
|
-
|
|
33969
|
-
|
|
33970
|
-
|
|
33971
|
-
|
|
33972
|
-
|
|
33973
|
-
|
|
33974
|
-
|
|
33975
|
-
|
|
33976
|
-
|
|
33977
|
-
|
|
33978
|
-
|
|
33979
|
-
|
|
33980
|
-
|
|
33981
|
-
this.activeChildParents,
|
|
33982
|
-
void 0,
|
|
33983
|
-
result
|
|
34813
|
+
interceptMultiAgentStream(channel2, operation) {
|
|
34814
|
+
this.unsubscribers.push(
|
|
34815
|
+
channel2.intercept(
|
|
34816
|
+
(target, thisArg, args, additional) => instrumentStrandsStreamInvocation({
|
|
34817
|
+
finalize: (state, error, output) => finalizeMultiAgentStream(
|
|
34818
|
+
state,
|
|
34819
|
+
this.activeChildParents,
|
|
34820
|
+
error,
|
|
34821
|
+
output
|
|
34822
|
+
),
|
|
34823
|
+
handleChunk: (state, chunk) => handleMultiAgentStreamEvent(state, chunk, this.activeChildParents),
|
|
34824
|
+
invoke: () => Reflect.apply(target, thisArg, args),
|
|
34825
|
+
name: "Strands multi-agent",
|
|
34826
|
+
start: () => startMultiAgentStream(
|
|
34827
|
+
args[0],
|
|
34828
|
+
extractOrchestrator(additional.orchestrator, thisArg),
|
|
34829
|
+
operation,
|
|
34830
|
+
this.activeChildParents
|
|
34831
|
+
)
|
|
34832
|
+
})
|
|
34833
|
+
)
|
|
34834
|
+
);
|
|
34835
|
+
}
|
|
34836
|
+
};
|
|
34837
|
+
function instrumentStrandsStreamInvocation(options) {
|
|
34838
|
+
let state;
|
|
34839
|
+
try {
|
|
34840
|
+
state = options.start();
|
|
34841
|
+
} catch (error) {
|
|
34842
|
+
debugLogger.error(`Error starting ${options.name} instrumentation:`, error);
|
|
34843
|
+
}
|
|
34844
|
+
let result;
|
|
34845
|
+
try {
|
|
34846
|
+
result = runWithAutoInstrumentationSuppressed(options.invoke);
|
|
34847
|
+
} catch (error) {
|
|
34848
|
+
if (state) {
|
|
34849
|
+
try {
|
|
34850
|
+
options.finalize(state, error);
|
|
34851
|
+
} catch (instrumentationError) {
|
|
34852
|
+
debugLogger.error(
|
|
34853
|
+
`Error handling ${options.name} instrumentation failure:`,
|
|
34854
|
+
instrumentationError
|
|
33984
34855
|
);
|
|
33985
|
-
states.delete(event);
|
|
33986
|
-
},
|
|
33987
|
-
error: (event) => {
|
|
33988
|
-
const state = states.get(event);
|
|
33989
|
-
if (!state || !event.error) {
|
|
33990
|
-
return;
|
|
33991
|
-
}
|
|
33992
|
-
finalizeMultiAgentStream(state, this.activeChildParents, event.error);
|
|
33993
|
-
states.delete(event);
|
|
33994
34856
|
}
|
|
33995
|
-
}
|
|
33996
|
-
|
|
33997
|
-
this.unsubscribers.push(() => {
|
|
33998
|
-
unbindAutoInstrumentationSuppression?.();
|
|
33999
|
-
tracingChannel.unsubscribe(handlers);
|
|
34000
|
-
});
|
|
34857
|
+
}
|
|
34858
|
+
throw error;
|
|
34001
34859
|
}
|
|
34002
|
-
|
|
34003
|
-
|
|
34004
|
-
|
|
34860
|
+
if (state) {
|
|
34861
|
+
try {
|
|
34862
|
+
if (isAsyncIterable(result)) {
|
|
34863
|
+
patchStreamIfNeeded(result, {
|
|
34864
|
+
aroundNext: (callback) => runWithAutoInstrumentationSuppressed(callback),
|
|
34865
|
+
onChunk: (chunk) => options.handleChunk(state, chunk),
|
|
34866
|
+
onComplete: () => options.finalize(state),
|
|
34867
|
+
onError: (error) => options.finalize(state, error)
|
|
34868
|
+
});
|
|
34869
|
+
} else {
|
|
34870
|
+
options.finalize(state, void 0, result);
|
|
34871
|
+
}
|
|
34872
|
+
} catch (error) {
|
|
34873
|
+
debugLogger.error(
|
|
34874
|
+
`Error finalizing ${options.name} instrumentation:`,
|
|
34875
|
+
error
|
|
34876
|
+
);
|
|
34877
|
+
}
|
|
34878
|
+
}
|
|
34879
|
+
return result;
|
|
34880
|
+
}
|
|
34881
|
+
function startAgentStream(input, agent, activeChildParents) {
|
|
34005
34882
|
const model = agent?.model;
|
|
34006
34883
|
const metadata = {
|
|
34007
34884
|
...extractAgentMetadata2(agent),
|
|
@@ -34011,17 +34888,14 @@ function startAgentStream(event, activeChildParents) {
|
|
|
34011
34888
|
};
|
|
34012
34889
|
const parentSpan = agent ? getOnlyChildParent(activeChildParents, agent) : void 0;
|
|
34013
34890
|
const attachmentCache = createStrandsAttachmentCache();
|
|
34014
|
-
const
|
|
34015
|
-
event.arguments[0],
|
|
34016
|
-
attachmentCache
|
|
34017
|
-
);
|
|
34891
|
+
const processedInput = processStrandsInputAttachments(input, attachmentCache);
|
|
34018
34892
|
const span = parentSpan ? withCurrent(
|
|
34019
34893
|
parentSpan,
|
|
34020
34894
|
() => startSpan(
|
|
34021
34895
|
withSpanInstrumentationName(
|
|
34022
34896
|
{
|
|
34023
34897
|
event: {
|
|
34024
|
-
input,
|
|
34898
|
+
input: processedInput,
|
|
34025
34899
|
metadata
|
|
34026
34900
|
},
|
|
34027
34901
|
name: formatAgentSpanName(agent),
|
|
@@ -34034,7 +34908,7 @@ function startAgentStream(event, activeChildParents) {
|
|
|
34034
34908
|
withSpanInstrumentationName(
|
|
34035
34909
|
{
|
|
34036
34910
|
event: {
|
|
34037
|
-
input,
|
|
34911
|
+
input: processedInput,
|
|
34038
34912
|
metadata
|
|
34039
34913
|
},
|
|
34040
34914
|
name: formatAgentSpanName(agent),
|
|
@@ -34052,22 +34926,21 @@ function startAgentStream(event, activeChildParents) {
|
|
|
34052
34926
|
startTime: getCurrentUnixTimestamp()
|
|
34053
34927
|
};
|
|
34054
34928
|
}
|
|
34055
|
-
function startMultiAgentStream(
|
|
34056
|
-
const orchestrator = extractOrchestrator(event);
|
|
34929
|
+
function startMultiAgentStream(input, orchestrator, operation, activeChildParents) {
|
|
34057
34930
|
const metadata = {
|
|
34058
34931
|
"strands.operation": operation,
|
|
34059
34932
|
provider: "strands",
|
|
34060
34933
|
...orchestrator?.id ? { "strands.orchestrator.id": orchestrator.id } : {}
|
|
34061
34934
|
};
|
|
34062
34935
|
const parentSpan = orchestrator ? getOnlyChildParent(activeChildParents, orchestrator) : void 0;
|
|
34063
|
-
const
|
|
34936
|
+
const processedInput = processStrandsInputAttachments(input);
|
|
34064
34937
|
const span = parentSpan ? withCurrent(
|
|
34065
34938
|
parentSpan,
|
|
34066
34939
|
() => startSpan(
|
|
34067
34940
|
withSpanInstrumentationName(
|
|
34068
34941
|
{
|
|
34069
34942
|
event: {
|
|
34070
|
-
input,
|
|
34943
|
+
input: processedInput,
|
|
34071
34944
|
metadata
|
|
34072
34945
|
},
|
|
34073
34946
|
name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
|
|
@@ -34080,7 +34953,7 @@ function startMultiAgentStream(event, operation, activeChildParents) {
|
|
|
34080
34953
|
withSpanInstrumentationName(
|
|
34081
34954
|
{
|
|
34082
34955
|
event: {
|
|
34083
|
-
input,
|
|
34956
|
+
input: processedInput,
|
|
34084
34957
|
metadata
|
|
34085
34958
|
},
|
|
34086
34959
|
name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
|
|
@@ -34451,12 +35324,12 @@ function finalizeMultiAgentStream(state, activeChildParents, error, output) {
|
|
|
34451
35324
|
});
|
|
34452
35325
|
state.span.end();
|
|
34453
35326
|
}
|
|
34454
|
-
function extractAgent(
|
|
34455
|
-
const candidate =
|
|
35327
|
+
function extractAgent(agent, self) {
|
|
35328
|
+
const candidate = agent ?? self;
|
|
34456
35329
|
return isObject(candidate) && typeof candidate.stream === "function" ? candidate : void 0;
|
|
34457
35330
|
}
|
|
34458
|
-
function extractOrchestrator(
|
|
34459
|
-
const candidate =
|
|
35331
|
+
function extractOrchestrator(orchestrator, self) {
|
|
35332
|
+
const candidate = orchestrator ?? self;
|
|
34460
35333
|
return isObject(candidate) && typeof candidate.stream === "function" ? candidate : void 0;
|
|
34461
35334
|
}
|
|
34462
35335
|
function extractAgentMetadata2(agent) {
|
|
@@ -36664,7 +37537,7 @@ function isAsync(fn) {
|
|
|
36664
37537
|
function isAsyncGenerator2(fn) {
|
|
36665
37538
|
return fn[Symbol.toStringTag] === "AsyncGenerator";
|
|
36666
37539
|
}
|
|
36667
|
-
function
|
|
37540
|
+
function isAsyncIterable5(obj) {
|
|
36668
37541
|
return typeof obj[Symbol.asyncIterator] === "function";
|
|
36669
37542
|
}
|
|
36670
37543
|
function wrapAsync(asyncFn) {
|
|
@@ -36836,7 +37709,7 @@ var eachOfLimit$2 = (limit) => {
|
|
|
36836
37709
|
if (isAsyncGenerator2(obj)) {
|
|
36837
37710
|
return asyncEachOfLimit(obj, limit, iteratee, callback);
|
|
36838
37711
|
}
|
|
36839
|
-
if (
|
|
37712
|
+
if (isAsyncIterable5(obj)) {
|
|
36840
37713
|
return asyncEachOfLimit(obj[Symbol.asyncIterator](), limit, iteratee, callback);
|
|
36841
37714
|
}
|
|
36842
37715
|
var nextElem = createIterator(obj);
|
|
@@ -38272,7 +39145,7 @@ function callEvaluatorData(data) {
|
|
|
38272
39145
|
baseExperiment
|
|
38273
39146
|
};
|
|
38274
39147
|
}
|
|
38275
|
-
function
|
|
39148
|
+
function isAsyncIterable6(value) {
|
|
38276
39149
|
return typeof value === "object" && value !== null && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
|
|
38277
39150
|
}
|
|
38278
39151
|
function isIterable(value) {
|
|
@@ -38307,7 +39180,7 @@ async function _internalResolveEvaluatorData(evaluator, experiment) {
|
|
|
38307
39180
|
}).asDataset();
|
|
38308
39181
|
}
|
|
38309
39182
|
const resolvedDataResult = dataResult instanceof Promise ? await dataResult : dataResult;
|
|
38310
|
-
if (
|
|
39183
|
+
if (isAsyncIterable6(resolvedDataResult)) {
|
|
38311
39184
|
return resolvedDataResult;
|
|
38312
39185
|
}
|
|
38313
39186
|
if (Array.isArray(resolvedDataResult) || isIterable(resolvedDataResult)) {
|
|
@@ -40207,14 +41080,9 @@ async function getDataset(state, data) {
|
|
|
40207
41080
|
_internal_btql: data._internal_btql ?? void 0
|
|
40208
41081
|
});
|
|
40209
41082
|
} else if ("dataset_id" in data) {
|
|
40210
|
-
const datasetInfo = await getDatasetById({
|
|
40211
|
-
state,
|
|
40212
|
-
datasetId: data.dataset_id
|
|
40213
|
-
});
|
|
40214
41083
|
return initDataset({
|
|
40215
41084
|
state,
|
|
40216
|
-
|
|
40217
|
-
dataset: datasetInfo.dataset,
|
|
41085
|
+
datasetId: data.dataset_id,
|
|
40218
41086
|
version: data.dataset_version ?? void 0,
|
|
40219
41087
|
environment: data.dataset_environment ?? void 0,
|
|
40220
41088
|
_internal_btql: data._internal_btql ?? void 0
|
|
@@ -40225,23 +41093,6 @@ async function getDataset(state, data) {
|
|
|
40225
41093
|
return data.data;
|
|
40226
41094
|
}
|
|
40227
41095
|
}
|
|
40228
|
-
var datasetFetchSchema = z14.object({
|
|
40229
|
-
project_id: z14.string(),
|
|
40230
|
-
name: z14.string()
|
|
40231
|
-
});
|
|
40232
|
-
async function getDatasetById({
|
|
40233
|
-
state,
|
|
40234
|
-
datasetId
|
|
40235
|
-
}) {
|
|
40236
|
-
const dataset = await state.appConn().post_json("api/dataset/get", {
|
|
40237
|
-
id: datasetId
|
|
40238
|
-
});
|
|
40239
|
-
const parsed = z14.array(datasetFetchSchema).parse(dataset);
|
|
40240
|
-
if (parsed.length === 0) {
|
|
40241
|
-
throw new Error(`Dataset '${datasetId}' not found`);
|
|
40242
|
-
}
|
|
40243
|
-
return { projectId: parsed[0].project_id, dataset: parsed[0].name };
|
|
40244
|
-
}
|
|
40245
41096
|
function makeScorer(state, name, score, projectId) {
|
|
40246
41097
|
const ret = async (input) => {
|
|
40247
41098
|
const request = {
|