braintrust 3.28.0 → 3.29.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 +1815 -1548
- package/dev/dist/index.mjs +1054 -787
- package/dist/apply-auto-instrumentation.js +297 -264
- package/dist/apply-auto-instrumentation.mjs +84 -51
- package/dist/auto-instrumentations/bundler/esbuild.cjs +43 -5
- package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
- package/dist/auto-instrumentations/bundler/next.cjs +43 -5
- package/dist/auto-instrumentations/bundler/next.mjs +3 -3
- package/dist/auto-instrumentations/bundler/rollup.cjs +43 -5
- package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
- package/dist/auto-instrumentations/bundler/vite.cjs +43 -5
- package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
- package/dist/auto-instrumentations/bundler/webpack-loader.cjs +43 -5
- package/dist/auto-instrumentations/bundler/webpack.cjs +43 -5
- package/dist/auto-instrumentations/bundler/webpack.mjs +3 -3
- package/dist/auto-instrumentations/{chunk-NP7V4XB2.mjs → chunk-AOIYCVEL.mjs} +32 -2
- package/dist/auto-instrumentations/{chunk-26PKVUKB.mjs → chunk-DKTGDNA7.mjs} +12 -4
- package/dist/auto-instrumentations/{chunk-HD35AM3M.mjs → chunk-OMCZ3MV2.mjs} +1 -1
- package/dist/auto-instrumentations/hook.mjs +952 -133
- package/dist/auto-instrumentations/index.cjs +32 -2
- package/dist/auto-instrumentations/index.mjs +1 -1
- package/dist/browser.d.mts +760 -22
- package/dist/browser.d.ts +760 -22
- package/dist/browser.js +1661 -848
- package/dist/browser.mjs +1661 -848
- package/dist/{chunk-BBE7SNRV.js → chunk-6Z5S7VOU.js} +143 -23
- package/dist/{chunk-ZHUHZWFY.mjs → chunk-7FA6VP2S.mjs} +140 -20
- package/dist/{chunk-UPFNQCGB.mjs → chunk-M6XPNJC4.mjs} +1144 -931
- package/dist/{chunk-OBBWQW6K.js → chunk-XLLGRXGR.js} +2335 -2122
- package/dist/cli.js +5134 -1090
- package/dist/edge-light.js +1661 -848
- package/dist/edge-light.mjs +1661 -848
- package/dist/index.d.mts +760 -22
- package/dist/index.d.ts +760 -22
- package/dist/index.js +1054 -567
- package/dist/index.mjs +514 -27
- package/dist/instrumentation/index.d.mts +548 -9
- package/dist/instrumentation/index.d.ts +548 -9
- package/dist/instrumentation/index.js +1975 -765
- package/dist/instrumentation/index.mjs +1975 -765
- package/dist/vitest-evals-reporter.js +16 -16
- package/dist/vitest-evals-reporter.mjs +2 -2
- package/dist/workerd.js +1661 -848
- package/dist/workerd.mjs +1661 -848
- package/package.json +1 -1
- package/util/dist/index.d.mts +42 -0
- package/util/dist/index.d.ts +42 -0
|
@@ -699,8 +699,6 @@ function newGlobalTracingChannel(nameOrChannels) {
|
|
|
699
699
|
var DefaultAsyncLocalStorage = class {
|
|
700
700
|
constructor() {
|
|
701
701
|
}
|
|
702
|
-
enterWith(_) {
|
|
703
|
-
}
|
|
704
702
|
run(_, callback) {
|
|
705
703
|
return callback();
|
|
706
704
|
}
|
|
@@ -2622,7 +2620,9 @@ var AclObjectType = import_v36.z.union([
|
|
|
2622
2620
|
"project_log",
|
|
2623
2621
|
"org_project",
|
|
2624
2622
|
"org_audit_logs",
|
|
2625
|
-
"project_group"
|
|
2623
|
+
"project_group",
|
|
2624
|
+
"ai_secret",
|
|
2625
|
+
"org_ai_secret"
|
|
2626
2626
|
]),
|
|
2627
2627
|
import_v36.z.null()
|
|
2628
2628
|
]);
|
|
@@ -3455,7 +3455,7 @@ var PromptParserNullish = import_v36.z.union([
|
|
|
3455
3455
|
}),
|
|
3456
3456
|
import_v36.z.null()
|
|
3457
3457
|
]);
|
|
3458
|
-
var
|
|
3458
|
+
var PreprocessorId = import_v36.z.union([
|
|
3459
3459
|
import_v36.z.object({
|
|
3460
3460
|
type: import_v36.z.literal("function"),
|
|
3461
3461
|
id: import_v36.z.string(),
|
|
@@ -3466,6 +3466,7 @@ var PreprocessorSavedFunctionId = import_v36.z.union([
|
|
|
3466
3466
|
name: import_v36.z.string(),
|
|
3467
3467
|
function_type: import_v36.z.literal("preprocessor").optional().default("preprocessor")
|
|
3468
3468
|
}),
|
|
3469
|
+
import_v36.z.object({ type: import_v36.z.literal("inline"), code: import_v36.z.string().min(1) }),
|
|
3469
3470
|
import_v36.z.null()
|
|
3470
3471
|
]);
|
|
3471
3472
|
var PromptDataNullish = import_v36.z.union([
|
|
@@ -3473,7 +3474,7 @@ var PromptDataNullish = import_v36.z.union([
|
|
|
3473
3474
|
prompt: PromptBlockDataNullish,
|
|
3474
3475
|
options: PromptOptionsNullish,
|
|
3475
3476
|
parser: PromptParserNullish,
|
|
3476
|
-
preprocessor:
|
|
3477
|
+
preprocessor: PreprocessorId,
|
|
3477
3478
|
tool_functions: import_v36.z.union([import_v36.z.array(SavedFunctionId), import_v36.z.null()]),
|
|
3478
3479
|
template_format: import_v36.z.union([
|
|
3479
3480
|
import_v36.z.enum(["mustache", "nunjucks", "none"]),
|
|
@@ -3675,7 +3676,7 @@ var PromptData = import_v36.z.object({
|
|
|
3675
3676
|
prompt: PromptBlockDataNullish,
|
|
3676
3677
|
options: PromptOptionsNullish,
|
|
3677
3678
|
parser: PromptParserNullish,
|
|
3678
|
-
preprocessor:
|
|
3679
|
+
preprocessor: PreprocessorId,
|
|
3679
3680
|
tool_functions: import_v36.z.union([import_v36.z.array(SavedFunctionId), import_v36.z.null()]),
|
|
3680
3681
|
template_format: import_v36.z.union([
|
|
3681
3682
|
import_v36.z.enum(["mustache", "nunjucks", "none"]),
|
|
@@ -4619,6 +4620,7 @@ var View = import_v36.z.object({
|
|
|
4619
4620
|
]),
|
|
4620
4621
|
name: import_v36.z.string(),
|
|
4621
4622
|
description: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
|
|
4623
|
+
starred: import_v36.z.boolean().optional(),
|
|
4622
4624
|
created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
|
|
4623
4625
|
updated_at: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
|
|
4624
4626
|
view_data: ViewData.optional(),
|
|
@@ -4708,6 +4710,34 @@ var registerTemplatePlugin = templateRegistry.register.bind(templateRegistry);
|
|
|
4708
4710
|
var getTemplateRenderer = templateRegistry.get.bind(templateRegistry);
|
|
4709
4711
|
registerTemplatePlugin(mustachePlugin);
|
|
4710
4712
|
|
|
4713
|
+
// src/template/renderer.ts
|
|
4714
|
+
function isTemplateFormat(v) {
|
|
4715
|
+
return v === "mustache" || v === "nunjucks" || v === "none";
|
|
4716
|
+
}
|
|
4717
|
+
function parseTemplateFormat(value, defaultFormat = "mustache") {
|
|
4718
|
+
return isTemplateFormat(value) ? value : defaultFormat;
|
|
4719
|
+
}
|
|
4720
|
+
function renderTemplateContent(template, variables, escape, options) {
|
|
4721
|
+
const strict = !!options.strict;
|
|
4722
|
+
const templateFormat = parseTemplateFormat(options.templateFormat);
|
|
4723
|
+
if (templateFormat === "none") {
|
|
4724
|
+
return template;
|
|
4725
|
+
}
|
|
4726
|
+
const renderer = getTemplateRenderer(templateFormat);
|
|
4727
|
+
if (!renderer) {
|
|
4728
|
+
if (templateFormat === "nunjucks") {
|
|
4729
|
+
throw new Error(
|
|
4730
|
+
"Nunjucks templating requires @braintrust/template-nunjucks. Install and import it to enable templateFormat: 'nunjucks'."
|
|
4731
|
+
);
|
|
4732
|
+
}
|
|
4733
|
+
throw new Error(`No template renderer registered for ${templateFormat}`);
|
|
4734
|
+
}
|
|
4735
|
+
if (strict && renderer.lint) {
|
|
4736
|
+
renderer.lint(template, variables);
|
|
4737
|
+
}
|
|
4738
|
+
return renderer.render(template, variables, escape, strict);
|
|
4739
|
+
}
|
|
4740
|
+
|
|
4711
4741
|
// src/logger.ts
|
|
4712
4742
|
var import_v38 = require("zod/v3");
|
|
4713
4743
|
|
|
@@ -5292,44 +5322,72 @@ function createCacheLayers({
|
|
|
5292
5322
|
}
|
|
5293
5323
|
|
|
5294
5324
|
// src/prompt-cache/prompt-cache.ts
|
|
5295
|
-
function createCacheKey(key) {
|
|
5325
|
+
function createCacheKey(key, namespace) {
|
|
5326
|
+
let cacheKey;
|
|
5296
5327
|
if (key.id) {
|
|
5297
|
-
|
|
5298
|
-
}
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
|
|
5302
|
-
|
|
5303
|
-
|
|
5304
|
-
|
|
5328
|
+
cacheKey = `id:${key.id}`;
|
|
5329
|
+
} else {
|
|
5330
|
+
const prefix = key.projectId ?? key.projectName;
|
|
5331
|
+
if (!prefix) {
|
|
5332
|
+
throw new Error("Either projectId or projectName must be provided");
|
|
5333
|
+
}
|
|
5334
|
+
if (!key.slug) {
|
|
5335
|
+
throw new Error("Slug must be provided when not using ID");
|
|
5336
|
+
}
|
|
5337
|
+
cacheKey = `${prefix}:${key.slug}:${key.version ?? "latest"}`;
|
|
5305
5338
|
}
|
|
5306
|
-
return `${
|
|
5339
|
+
return namespace === void 0 ? cacheKey : `${namespace.length}:${namespace}:${cacheKey}`;
|
|
5307
5340
|
}
|
|
5308
|
-
var PromptCache = class {
|
|
5341
|
+
var PromptCache = class _PromptCache {
|
|
5309
5342
|
memoryCache;
|
|
5310
5343
|
diskCache;
|
|
5344
|
+
namespace;
|
|
5345
|
+
expectedResolvedOrgIdentity;
|
|
5311
5346
|
constructor(options) {
|
|
5312
5347
|
this.memoryCache = options.memoryCache;
|
|
5313
5348
|
this.diskCache = options.diskCache;
|
|
5349
|
+
this.namespace = options.namespace;
|
|
5350
|
+
this.expectedResolvedOrgIdentity = options.expectedResolvedOrgIdentity;
|
|
5351
|
+
}
|
|
5352
|
+
/**
|
|
5353
|
+
* Returns a cache view that shares the same storage layers but isolates all
|
|
5354
|
+
* entries under the provided namespace.
|
|
5355
|
+
*/
|
|
5356
|
+
withNamespace(namespace, expectedResolvedOrgIdentity) {
|
|
5357
|
+
return new _PromptCache({
|
|
5358
|
+
memoryCache: this.memoryCache,
|
|
5359
|
+
diskCache: this.diskCache,
|
|
5360
|
+
namespace,
|
|
5361
|
+
expectedResolvedOrgIdentity
|
|
5362
|
+
});
|
|
5314
5363
|
}
|
|
5315
5364
|
/**
|
|
5316
5365
|
* Retrieves a prompt from the cache.
|
|
5317
5366
|
* First checks the in-memory LRU cache, then falls back to checking the disk cache if available.
|
|
5318
5367
|
*/
|
|
5319
5368
|
async get(key) {
|
|
5320
|
-
const cacheKey = createCacheKey(key);
|
|
5369
|
+
const cacheKey = createCacheKey(key, this.namespace);
|
|
5321
5370
|
if (this.memoryCache) {
|
|
5322
|
-
const
|
|
5323
|
-
if (
|
|
5324
|
-
return
|
|
5371
|
+
const memoryEntry = this.memoryCache.get(cacheKey);
|
|
5372
|
+
if (memoryEntry !== void 0 && (this.expectedResolvedOrgIdentity === void 0 || memoryEntry.resolvedOrgIdentity === this.expectedResolvedOrgIdentity)) {
|
|
5373
|
+
return memoryEntry.value;
|
|
5325
5374
|
}
|
|
5326
5375
|
}
|
|
5327
5376
|
if (this.diskCache) {
|
|
5328
|
-
const
|
|
5329
|
-
if (!
|
|
5377
|
+
const diskEntry = await this.diskCache.get(cacheKey);
|
|
5378
|
+
if (!diskEntry || this.expectedResolvedOrgIdentity !== void 0 && diskEntry.resolvedOrgIdentity !== this.expectedResolvedOrgIdentity) {
|
|
5330
5379
|
return void 0;
|
|
5331
5380
|
}
|
|
5332
|
-
|
|
5381
|
+
const serializedPrompt = diskEntry.value;
|
|
5382
|
+
const diskPrompt = new Prompt2(
|
|
5383
|
+
serializedPrompt.metadata,
|
|
5384
|
+
serializedPrompt.defaults,
|
|
5385
|
+
serializedPrompt.noTrace
|
|
5386
|
+
);
|
|
5387
|
+
this.memoryCache?.set(cacheKey, {
|
|
5388
|
+
value: diskPrompt,
|
|
5389
|
+
resolvedOrgIdentity: diskEntry.resolvedOrgIdentity
|
|
5390
|
+
});
|
|
5333
5391
|
return diskPrompt;
|
|
5334
5392
|
}
|
|
5335
5393
|
return void 0;
|
|
@@ -5343,58 +5401,91 @@ var PromptCache = class {
|
|
|
5343
5401
|
* @throws If there is an error writing to the disk cache.
|
|
5344
5402
|
*/
|
|
5345
5403
|
async set(key, value) {
|
|
5346
|
-
const cacheKey = createCacheKey(key);
|
|
5347
|
-
|
|
5404
|
+
const cacheKey = createCacheKey(key, this.namespace);
|
|
5405
|
+
const memoryEntry = {
|
|
5406
|
+
value,
|
|
5407
|
+
resolvedOrgIdentity: this.expectedResolvedOrgIdentity
|
|
5408
|
+
};
|
|
5409
|
+
this.memoryCache?.set(cacheKey, memoryEntry);
|
|
5348
5410
|
if (this.diskCache) {
|
|
5349
|
-
await this.diskCache.set(cacheKey,
|
|
5411
|
+
await this.diskCache.set(cacheKey, {
|
|
5412
|
+
value: value._internalSerializeForCache(),
|
|
5413
|
+
resolvedOrgIdentity: this.expectedResolvedOrgIdentity
|
|
5414
|
+
});
|
|
5350
5415
|
}
|
|
5351
5416
|
}
|
|
5352
5417
|
};
|
|
5353
5418
|
|
|
5354
5419
|
// src/prompt-cache/parameters-cache.ts
|
|
5355
|
-
function createCacheKey2(key) {
|
|
5420
|
+
function createCacheKey2(key, namespace) {
|
|
5421
|
+
let cacheKey;
|
|
5356
5422
|
if (key.id) {
|
|
5357
|
-
|
|
5358
|
-
}
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
|
-
|
|
5423
|
+
cacheKey = `parameters:id:${key.id}`;
|
|
5424
|
+
} else {
|
|
5425
|
+
const prefix = key.projectId ?? key.projectName;
|
|
5426
|
+
if (!prefix) {
|
|
5427
|
+
throw new Error("Either projectId or projectName must be provided");
|
|
5428
|
+
}
|
|
5429
|
+
if (!key.slug) {
|
|
5430
|
+
throw new Error("Slug must be provided when not using ID");
|
|
5431
|
+
}
|
|
5432
|
+
cacheKey = `parameters:${prefix}:${key.slug}:${key.version ?? "latest"}`;
|
|
5365
5433
|
}
|
|
5366
|
-
return
|
|
5434
|
+
return namespace === void 0 ? cacheKey : `${namespace.length}:${namespace}:${cacheKey}`;
|
|
5367
5435
|
}
|
|
5368
|
-
var ParametersCache = class {
|
|
5436
|
+
var ParametersCache = class _ParametersCache {
|
|
5369
5437
|
memoryCache;
|
|
5370
5438
|
diskCache;
|
|
5439
|
+
namespace;
|
|
5440
|
+
expectedResolvedOrgIdentity;
|
|
5371
5441
|
constructor(options) {
|
|
5372
5442
|
this.memoryCache = options.memoryCache;
|
|
5373
5443
|
this.diskCache = options.diskCache;
|
|
5444
|
+
this.namespace = options.namespace;
|
|
5445
|
+
this.expectedResolvedOrgIdentity = options.expectedResolvedOrgIdentity;
|
|
5446
|
+
}
|
|
5447
|
+
withNamespace(namespace, expectedResolvedOrgIdentity) {
|
|
5448
|
+
return new _ParametersCache({
|
|
5449
|
+
memoryCache: this.memoryCache,
|
|
5450
|
+
diskCache: this.diskCache,
|
|
5451
|
+
namespace,
|
|
5452
|
+
expectedResolvedOrgIdentity
|
|
5453
|
+
});
|
|
5374
5454
|
}
|
|
5375
5455
|
async get(key) {
|
|
5376
|
-
const cacheKey = createCacheKey2(key);
|
|
5456
|
+
const cacheKey = createCacheKey2(key, this.namespace);
|
|
5377
5457
|
if (this.memoryCache) {
|
|
5378
|
-
const
|
|
5379
|
-
if (
|
|
5380
|
-
return
|
|
5458
|
+
const memoryEntry = this.memoryCache.get(cacheKey);
|
|
5459
|
+
if (memoryEntry !== void 0 && (this.expectedResolvedOrgIdentity === void 0 || memoryEntry.resolvedOrgIdentity === this.expectedResolvedOrgIdentity)) {
|
|
5460
|
+
return memoryEntry.value;
|
|
5381
5461
|
}
|
|
5382
5462
|
}
|
|
5383
5463
|
if (this.diskCache) {
|
|
5384
|
-
const
|
|
5385
|
-
if (!
|
|
5464
|
+
const diskEntry = await this.diskCache.get(cacheKey);
|
|
5465
|
+
if (!diskEntry || this.expectedResolvedOrgIdentity !== void 0 && diskEntry.resolvedOrgIdentity !== this.expectedResolvedOrgIdentity) {
|
|
5386
5466
|
return void 0;
|
|
5387
5467
|
}
|
|
5388
|
-
|
|
5389
|
-
|
|
5468
|
+
const diskParameters = new RemoteEvalParameters(diskEntry.value.metadata);
|
|
5469
|
+
this.memoryCache?.set(cacheKey, {
|
|
5470
|
+
value: diskParameters,
|
|
5471
|
+
resolvedOrgIdentity: diskEntry.resolvedOrgIdentity
|
|
5472
|
+
});
|
|
5473
|
+
return diskParameters;
|
|
5390
5474
|
}
|
|
5391
5475
|
return void 0;
|
|
5392
5476
|
}
|
|
5393
5477
|
async set(key, value) {
|
|
5394
|
-
const cacheKey = createCacheKey2(key);
|
|
5395
|
-
|
|
5478
|
+
const cacheKey = createCacheKey2(key, this.namespace);
|
|
5479
|
+
const memoryEntry = {
|
|
5480
|
+
value,
|
|
5481
|
+
resolvedOrgIdentity: this.expectedResolvedOrgIdentity
|
|
5482
|
+
};
|
|
5483
|
+
this.memoryCache?.set(cacheKey, memoryEntry);
|
|
5396
5484
|
if (this.diskCache) {
|
|
5397
|
-
await this.diskCache.set(cacheKey,
|
|
5485
|
+
await this.diskCache.set(cacheKey, {
|
|
5486
|
+
value: value._internalSerializeForCache(),
|
|
5487
|
+
resolvedOrgIdentity: this.expectedResolvedOrgIdentity
|
|
5488
|
+
});
|
|
5398
5489
|
}
|
|
5399
5490
|
}
|
|
5400
5491
|
};
|
|
@@ -5698,6 +5789,7 @@ var INSTRUMENTATION_NAMES = {
|
|
|
5698
5789
|
CLOUDFLARE_THINK: "cloudflare-think",
|
|
5699
5790
|
COHERE: "cohere",
|
|
5700
5791
|
CURSOR_SDK: "cursor-sdk",
|
|
5792
|
+
DEEPSEEK_HARNESS: "deepseek-harness",
|
|
5701
5793
|
EVE: "eve",
|
|
5702
5794
|
FLUE: "flue",
|
|
5703
5795
|
GENKIT: "genkit",
|
|
@@ -5723,7 +5815,7 @@ var INSTRUMENTATION_NAMES = {
|
|
|
5723
5815
|
var INTERNAL_SPAN_INSTRUMENTATION_NAME = /* @__PURE__ */ Symbol.for(
|
|
5724
5816
|
"braintrust.spanInstrumentationName"
|
|
5725
5817
|
);
|
|
5726
|
-
var SDK_VERSION = true ? "3.
|
|
5818
|
+
var SDK_VERSION = true ? "3.29.0" : "0.0.0";
|
|
5727
5819
|
function withSpanInstrumentationName(args, instrumentationName) {
|
|
5728
5820
|
return {
|
|
5729
5821
|
...args,
|
|
@@ -5842,6 +5934,16 @@ var datasetSnapshotRegisterResponseSchema = import_v38.z.object({
|
|
|
5842
5934
|
dataset_snapshot: DatasetSnapshot,
|
|
5843
5935
|
found_existing: import_v38.z.boolean().optional()
|
|
5844
5936
|
});
|
|
5937
|
+
var datasetObjectInfoSchema = import_v38.z.object({
|
|
5938
|
+
object_id: import_v38.z.string(),
|
|
5939
|
+
object_name: import_v38.z.string(),
|
|
5940
|
+
parent_cols: import_v38.z.object({
|
|
5941
|
+
project: import_v38.z.object({
|
|
5942
|
+
id: import_v38.z.string(),
|
|
5943
|
+
name: import_v38.z.string()
|
|
5944
|
+
})
|
|
5945
|
+
})
|
|
5946
|
+
});
|
|
5845
5947
|
var datasetRestorePreviewResultSchema = import_v38.z.object({
|
|
5846
5948
|
rows_to_restore: import_v38.z.number(),
|
|
5847
5949
|
rows_to_delete: import_v38.z.number()
|
|
@@ -6055,12 +6157,53 @@ var loginSchema = import_v38.z.strictObject({
|
|
|
6055
6157
|
});
|
|
6056
6158
|
var stateNonce = 0;
|
|
6057
6159
|
var V1_PROXY_SUFFIX = "/v1/proxy";
|
|
6160
|
+
var LOADER_LOGIN_CACHE_MAX = 16;
|
|
6058
6161
|
function normalizeProxyConnUrl(proxyUrl) {
|
|
6059
6162
|
return proxyUrl.endsWith(V1_PROXY_SUFFIX) ? proxyUrl.slice(0, proxyUrl.length - V1_PROXY_SUFFIX.length) : proxyUrl;
|
|
6060
6163
|
}
|
|
6061
6164
|
var BraintrustState = class _BraintrustState {
|
|
6165
|
+
id;
|
|
6166
|
+
currentExperiment;
|
|
6167
|
+
// Note: the value of IsAsyncFlush doesn't really matter here, since we
|
|
6168
|
+
// (safely) dynamically cast it whenever retrieving the logger.
|
|
6169
|
+
currentLogger;
|
|
6170
|
+
currentParent;
|
|
6171
|
+
currentSpan;
|
|
6172
|
+
// Any time we re-log in, we directly update the apiConn inside the logger.
|
|
6173
|
+
// This is preferable to replacing the whole logger, which would create the
|
|
6174
|
+
// possibility of multiple loggers floating around, which may not log in a
|
|
6175
|
+
// deterministic order.
|
|
6176
|
+
_bgLogger;
|
|
6177
|
+
_overrideBgLogger = null;
|
|
6178
|
+
appUrl = null;
|
|
6179
|
+
appPublicUrl = null;
|
|
6180
|
+
loginToken = null;
|
|
6181
|
+
orgId = null;
|
|
6182
|
+
orgName = null;
|
|
6183
|
+
apiUrl = null;
|
|
6184
|
+
proxyUrl = null;
|
|
6185
|
+
loggedIn = false;
|
|
6186
|
+
gitMetadataSettings;
|
|
6187
|
+
debugLogLevel;
|
|
6188
|
+
debugLogLevelConfigured = false;
|
|
6189
|
+
fetch = globalThis.fetch;
|
|
6190
|
+
_appConn = null;
|
|
6191
|
+
_apiConn = null;
|
|
6192
|
+
_proxyConn = null;
|
|
6193
|
+
promptCache;
|
|
6194
|
+
parametersCache;
|
|
6195
|
+
spanCache;
|
|
6196
|
+
_idGenerator = null;
|
|
6197
|
+
_contextManager = null;
|
|
6198
|
+
_otelFlushCallback = null;
|
|
6199
|
+
spanOriginEnvironment;
|
|
6200
|
+
traceContextSigningSecret;
|
|
6201
|
+
loaderLoginCache = /* @__PURE__ */ new WeakMap();
|
|
6202
|
+
loginParams;
|
|
6203
|
+
activeLoginOrgNameSelector;
|
|
6062
6204
|
constructor(loginParams) {
|
|
6063
|
-
this.loginParams = loginParams;
|
|
6205
|
+
this.loginParams = { ...loginParams };
|
|
6206
|
+
this.activeLoginOrgNameSelector = loginParams.orgName ?? isomorph_default.getEnv("BRAINTRUST_ORG_NAME");
|
|
6064
6207
|
this.id = `${(/* @__PURE__ */ new Date()).toLocaleString()}-${stateNonce++}`;
|
|
6065
6208
|
this.currentExperiment = void 0;
|
|
6066
6209
|
this.currentLogger = void 0;
|
|
@@ -6097,12 +6240,14 @@ var BraintrustState = class _BraintrustState {
|
|
|
6097
6240
|
const {
|
|
6098
6241
|
memoryCache: parametersMemoryCache,
|
|
6099
6242
|
diskCache: parametersDiskCache
|
|
6100
|
-
} = createCacheLayers(
|
|
6101
|
-
|
|
6102
|
-
|
|
6103
|
-
|
|
6104
|
-
|
|
6105
|
-
|
|
6243
|
+
} = createCacheLayers(
|
|
6244
|
+
{
|
|
6245
|
+
memoryMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_MEMORY_MAX",
|
|
6246
|
+
diskCacheDirEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DIR",
|
|
6247
|
+
diskMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DISK_MAX",
|
|
6248
|
+
getDefaultDiskCacheDir: () => `${isomorph_default.getEnv("HOME") ?? isomorph_default.homedir()}/.braintrust/parameters_cache`
|
|
6249
|
+
}
|
|
6250
|
+
);
|
|
6106
6251
|
this.parametersCache = new ParametersCache({
|
|
6107
6252
|
memoryCache: parametersMemoryCache,
|
|
6108
6253
|
diskCache: parametersDiskCache
|
|
@@ -6111,43 +6256,6 @@ var BraintrustState = class _BraintrustState {
|
|
|
6111
6256
|
this.spanOriginEnvironment = detectSpanOriginEnvironment();
|
|
6112
6257
|
this._internalSetTraceContextSigningSecret(loginParams.apiKey);
|
|
6113
6258
|
}
|
|
6114
|
-
loginParams;
|
|
6115
|
-
id;
|
|
6116
|
-
currentExperiment;
|
|
6117
|
-
// Note: the value of IsAsyncFlush doesn't really matter here, since we
|
|
6118
|
-
// (safely) dynamically cast it whenever retrieving the logger.
|
|
6119
|
-
currentLogger;
|
|
6120
|
-
currentParent;
|
|
6121
|
-
currentSpan;
|
|
6122
|
-
// Any time we re-log in, we directly update the apiConn inside the logger.
|
|
6123
|
-
// This is preferable to replacing the whole logger, which would create the
|
|
6124
|
-
// possibility of multiple loggers floating around, which may not log in a
|
|
6125
|
-
// deterministic order.
|
|
6126
|
-
_bgLogger;
|
|
6127
|
-
_overrideBgLogger = null;
|
|
6128
|
-
appUrl = null;
|
|
6129
|
-
appPublicUrl = null;
|
|
6130
|
-
loginToken = null;
|
|
6131
|
-
orgId = null;
|
|
6132
|
-
orgName = null;
|
|
6133
|
-
apiUrl = null;
|
|
6134
|
-
proxyUrl = null;
|
|
6135
|
-
loggedIn = false;
|
|
6136
|
-
gitMetadataSettings;
|
|
6137
|
-
debugLogLevel;
|
|
6138
|
-
debugLogLevelConfigured = false;
|
|
6139
|
-
fetch = globalThis.fetch;
|
|
6140
|
-
_appConn = null;
|
|
6141
|
-
_apiConn = null;
|
|
6142
|
-
_proxyConn = null;
|
|
6143
|
-
promptCache;
|
|
6144
|
-
parametersCache;
|
|
6145
|
-
spanCache;
|
|
6146
|
-
_idGenerator = null;
|
|
6147
|
-
_contextManager = null;
|
|
6148
|
-
_otelFlushCallback = null;
|
|
6149
|
-
spanOriginEnvironment;
|
|
6150
|
-
traceContextSigningSecret;
|
|
6151
6259
|
/** @internal */
|
|
6152
6260
|
_internalSetTraceContextSigningSecret(secret) {
|
|
6153
6261
|
const normalizedSecret = secret?.trim();
|
|
@@ -6172,6 +6280,101 @@ var BraintrustState = class _BraintrustState {
|
|
|
6172
6280
|
this._appConn = null;
|
|
6173
6281
|
this._apiConn = null;
|
|
6174
6282
|
this._proxyConn = null;
|
|
6283
|
+
this.loaderLoginCache = /* @__PURE__ */ new WeakMap();
|
|
6284
|
+
}
|
|
6285
|
+
/** @internal */
|
|
6286
|
+
async _internalResolveLoaderLoginOptions({
|
|
6287
|
+
apiKey,
|
|
6288
|
+
appUrl,
|
|
6289
|
+
orgName,
|
|
6290
|
+
fetch: fetch2,
|
|
6291
|
+
forceLogin
|
|
6292
|
+
}) {
|
|
6293
|
+
const resolvedAppUrl = appUrl ?? (this.loggedIn ? this.appUrl ?? void 0 : void 0) ?? this.loginParams.appUrl ?? isomorph_default.getEnv("BRAINTRUST_APP_URL") ?? "https://www.braintrust.dev";
|
|
6294
|
+
const resolvedApiKey = apiKey ?? (this.loggedIn ? this.loginToken ?? void 0 : void 0) ?? this.loginParams.apiKey ?? await isomorph_default.getBraintrustApiKey();
|
|
6295
|
+
if (!resolvedApiKey) {
|
|
6296
|
+
throw new Error(
|
|
6297
|
+
"Please specify an api key (e.g. by setting BRAINTRUST_API_KEY)."
|
|
6298
|
+
);
|
|
6299
|
+
}
|
|
6300
|
+
const normalizedApiKey = HTTPConnection.sanitize_token(resolvedApiKey);
|
|
6301
|
+
const usesActiveCredential = this.loggedIn && normalizedApiKey === this.loginToken;
|
|
6302
|
+
const requestedOrgName = orgName ?? (usesActiveCredential ? this.activeLoginOrgNameSelector : void 0) ?? this.loginParams.orgName ?? isomorph_default.getEnv("BRAINTRUST_ORG_NAME");
|
|
6303
|
+
const resolvedOrgName = orgName ?? (usesActiveCredential ? this.orgName ?? void 0 : void 0) ?? requestedOrgName;
|
|
6304
|
+
const resolvedFetch = fetch2 ?? (this.loggedIn ? this.fetch : void 0) ?? this.loginParams.fetch ?? globalThis.fetch;
|
|
6305
|
+
const credentialCacheNamespace = JSON.stringify([
|
|
6306
|
+
"loader-credential",
|
|
6307
|
+
resolvedAppUrl,
|
|
6308
|
+
requestedOrgName,
|
|
6309
|
+
normalizedApiKey
|
|
6310
|
+
]);
|
|
6311
|
+
return {
|
|
6312
|
+
apiKey: normalizedApiKey,
|
|
6313
|
+
appUrl: resolvedAppUrl,
|
|
6314
|
+
orgName: resolvedOrgName,
|
|
6315
|
+
fetch: resolvedFetch,
|
|
6316
|
+
forceLogin,
|
|
6317
|
+
credentialCacheNamespace,
|
|
6318
|
+
existingState: !forceLogin && usesActiveCredential && resolvedAppUrl === this.appUrl && resolvedOrgName === this.orgName && resolvedFetch === this.fetch ? this : void 0
|
|
6319
|
+
};
|
|
6320
|
+
}
|
|
6321
|
+
/** @internal */
|
|
6322
|
+
_internalGetLoaderCacheViews(loginOptions, requestState) {
|
|
6323
|
+
const expectedResolvedOrgIdentity = requestState?.orgId && requestState.appUrl ? JSON.stringify([
|
|
6324
|
+
"loader-org",
|
|
6325
|
+
requestState.appUrl,
|
|
6326
|
+
requestState.orgId
|
|
6327
|
+
]) : void 0;
|
|
6328
|
+
return {
|
|
6329
|
+
promptCache: this.promptCache.withNamespace(
|
|
6330
|
+
loginOptions.credentialCacheNamespace,
|
|
6331
|
+
expectedResolvedOrgIdentity
|
|
6332
|
+
),
|
|
6333
|
+
parametersCache: this.parametersCache.withNamespace(
|
|
6334
|
+
loginOptions.credentialCacheNamespace,
|
|
6335
|
+
expectedResolvedOrgIdentity
|
|
6336
|
+
)
|
|
6337
|
+
};
|
|
6338
|
+
}
|
|
6339
|
+
/** @internal */
|
|
6340
|
+
async _internalGetLoaderState({
|
|
6341
|
+
apiKey,
|
|
6342
|
+
appUrl,
|
|
6343
|
+
orgName,
|
|
6344
|
+
fetch: fetch2,
|
|
6345
|
+
forceLogin,
|
|
6346
|
+
existingState
|
|
6347
|
+
}) {
|
|
6348
|
+
if (existingState) {
|
|
6349
|
+
return existingState;
|
|
6350
|
+
}
|
|
6351
|
+
let cache = this.loaderLoginCache.get(fetch2);
|
|
6352
|
+
if (!cache) {
|
|
6353
|
+
cache = new LRUCache({ max: LOADER_LOGIN_CACHE_MAX });
|
|
6354
|
+
this.loaderLoginCache.set(fetch2, cache);
|
|
6355
|
+
}
|
|
6356
|
+
const cacheKey = JSON.stringify([appUrl, orgName, apiKey]);
|
|
6357
|
+
if (!forceLogin) {
|
|
6358
|
+
const cachedState = cache.get(cacheKey);
|
|
6359
|
+
if (cachedState) {
|
|
6360
|
+
return cachedState;
|
|
6361
|
+
}
|
|
6362
|
+
}
|
|
6363
|
+
const statePromise = loginToLoaderRequestState({
|
|
6364
|
+
orgName,
|
|
6365
|
+
apiKey,
|
|
6366
|
+
appUrl,
|
|
6367
|
+
fetch: fetch2
|
|
6368
|
+
});
|
|
6369
|
+
cache.set(cacheKey, statePromise);
|
|
6370
|
+
try {
|
|
6371
|
+
return await statePromise;
|
|
6372
|
+
} catch (error) {
|
|
6373
|
+
if (cache.get(cacheKey) === statePromise) {
|
|
6374
|
+
cache.delete(cacheKey);
|
|
6375
|
+
}
|
|
6376
|
+
throw error;
|
|
6377
|
+
}
|
|
6175
6378
|
}
|
|
6176
6379
|
resetIdGenState() {
|
|
6177
6380
|
this._idGenerator = null;
|
|
@@ -6220,6 +6423,8 @@ var BraintrustState = class _BraintrustState {
|
|
|
6220
6423
|
this.debugLogLevel = other.debugLogLevel;
|
|
6221
6424
|
this.debugLogLevelConfigured = other.debugLogLevelConfigured;
|
|
6222
6425
|
this.traceContextSigningSecret = other.traceContextSigningSecret;
|
|
6426
|
+
this.fetch = other.fetch;
|
|
6427
|
+
this.activeLoginOrgNameSelector = other.activeLoginOrgNameSelector;
|
|
6223
6428
|
setGlobalDebugLogLevel(
|
|
6224
6429
|
this.debugLogLevelConfigured ? this.debugLogLevel ?? false : void 0
|
|
6225
6430
|
);
|
|
@@ -6414,36 +6619,76 @@ var FailedHTTPResponse = class extends Error {
|
|
|
6414
6619
|
status;
|
|
6415
6620
|
text;
|
|
6416
6621
|
data;
|
|
6417
|
-
|
|
6622
|
+
cause;
|
|
6623
|
+
constructor(status, text, data, cause) {
|
|
6418
6624
|
super(`${status}: ${text} (${data})`);
|
|
6419
6625
|
this.status = status;
|
|
6420
6626
|
this.text = text;
|
|
6421
6627
|
this.data = data;
|
|
6628
|
+
this.cause = cause;
|
|
6629
|
+
}
|
|
6630
|
+
};
|
|
6631
|
+
var HTTPTransportError = class extends Error {
|
|
6632
|
+
cause;
|
|
6633
|
+
constructor(cause) {
|
|
6634
|
+
super(cause instanceof Error ? cause.message : String(cause));
|
|
6635
|
+
this.name = "HTTPTransportError";
|
|
6636
|
+
this.cause = cause;
|
|
6422
6637
|
}
|
|
6423
6638
|
};
|
|
6639
|
+
var httpTransportErrorCauses = /* @__PURE__ */ new WeakSet();
|
|
6640
|
+
function recordHTTPTransportError(error) {
|
|
6641
|
+
if (typeof error === "object" && error !== null || typeof error === "function") {
|
|
6642
|
+
httpTransportErrorCauses.add(error);
|
|
6643
|
+
}
|
|
6644
|
+
}
|
|
6645
|
+
function rethrowHTTPTransportError(error, classifyTransportErrors) {
|
|
6646
|
+
if (classifyTransportErrors) {
|
|
6647
|
+
throw new HTTPTransportError(error);
|
|
6648
|
+
}
|
|
6649
|
+
recordHTTPTransportError(error);
|
|
6650
|
+
throw error;
|
|
6651
|
+
}
|
|
6652
|
+
async function readJSONResponse(response, classifyTransportErrors = false) {
|
|
6653
|
+
let data;
|
|
6654
|
+
try {
|
|
6655
|
+
data = await response.text();
|
|
6656
|
+
} catch (error) {
|
|
6657
|
+
rethrowHTTPTransportError(error, classifyTransportErrors);
|
|
6658
|
+
}
|
|
6659
|
+
return JSON.parse(data);
|
|
6660
|
+
}
|
|
6424
6661
|
async function checkResponse(resp) {
|
|
6425
6662
|
if (resp.ok) {
|
|
6426
6663
|
return resp;
|
|
6427
|
-
}
|
|
6664
|
+
}
|
|
6665
|
+
let data;
|
|
6666
|
+
try {
|
|
6667
|
+
data = await resp.text();
|
|
6668
|
+
} catch (error) {
|
|
6428
6669
|
throw new FailedHTTPResponse(
|
|
6429
6670
|
resp.status,
|
|
6430
6671
|
resp.statusText,
|
|
6431
|
-
|
|
6672
|
+
"Unable to read response body",
|
|
6673
|
+
error
|
|
6432
6674
|
);
|
|
6433
6675
|
}
|
|
6676
|
+
throw new FailedHTTPResponse(resp.status, resp.statusText, data);
|
|
6434
6677
|
}
|
|
6435
6678
|
var HTTPConnection = class _HTTPConnection {
|
|
6436
|
-
base_url
|
|
6437
|
-
|
|
6438
|
-
headers;
|
|
6439
|
-
fetch;
|
|
6440
|
-
constructor(base_url, fetch2) {
|
|
6679
|
+
constructor(base_url, fetch2, classifyTransportErrors = false) {
|
|
6680
|
+
this.classifyTransportErrors = classifyTransportErrors;
|
|
6441
6681
|
this.base_url = base_url;
|
|
6442
6682
|
this.token = null;
|
|
6443
6683
|
this.headers = {};
|
|
6444
6684
|
this._reset();
|
|
6445
6685
|
this.fetch = fetch2;
|
|
6446
6686
|
}
|
|
6687
|
+
classifyTransportErrors;
|
|
6688
|
+
base_url;
|
|
6689
|
+
token;
|
|
6690
|
+
headers;
|
|
6691
|
+
fetch;
|
|
6447
6692
|
setFetch(fetch2) {
|
|
6448
6693
|
this.fetch = fetch2;
|
|
6449
6694
|
}
|
|
@@ -6483,9 +6728,9 @@ var HTTPConnection = class _HTTPConnection {
|
|
|
6483
6728
|
).toString();
|
|
6484
6729
|
const this_fetch = this.fetch;
|
|
6485
6730
|
const this_headers = this.headers;
|
|
6486
|
-
|
|
6487
|
-
|
|
6488
|
-
await this_fetch(url.toString(), {
|
|
6731
|
+
let response;
|
|
6732
|
+
try {
|
|
6733
|
+
response = await this_fetch(url.toString(), {
|
|
6489
6734
|
headers: {
|
|
6490
6735
|
Accept: "application/json",
|
|
6491
6736
|
...this_headers,
|
|
@@ -6493,8 +6738,14 @@ var HTTPConnection = class _HTTPConnection {
|
|
|
6493
6738
|
},
|
|
6494
6739
|
keepalive: true,
|
|
6495
6740
|
...rest
|
|
6496
|
-
})
|
|
6497
|
-
)
|
|
6741
|
+
});
|
|
6742
|
+
} catch (error) {
|
|
6743
|
+
if (config?.signal?.aborted) {
|
|
6744
|
+
throw getAbortReason(config.signal);
|
|
6745
|
+
}
|
|
6746
|
+
rethrowHTTPTransportError(error, this.classifyTransportErrors);
|
|
6747
|
+
}
|
|
6748
|
+
return await checkResponse(response);
|
|
6498
6749
|
}
|
|
6499
6750
|
async post(path, params, config, retries = 0) {
|
|
6500
6751
|
const { headers, ...rest } = config || {};
|
|
@@ -6504,8 +6755,9 @@ var HTTPConnection = class _HTTPConnection {
|
|
|
6504
6755
|
const tries = retries + 1;
|
|
6505
6756
|
for (let i = 0; i < tries; i++) {
|
|
6506
6757
|
try {
|
|
6507
|
-
|
|
6508
|
-
|
|
6758
|
+
let response;
|
|
6759
|
+
try {
|
|
6760
|
+
response = await this_fetch(_urljoin(this_base_url, path), {
|
|
6509
6761
|
method: "POST",
|
|
6510
6762
|
headers: {
|
|
6511
6763
|
Accept: "application/json",
|
|
@@ -6516,8 +6768,14 @@ var HTTPConnection = class _HTTPConnection {
|
|
|
6516
6768
|
body: typeof params === "string" ? params : params ? JSON.stringify(params) : void 0,
|
|
6517
6769
|
keepalive: true,
|
|
6518
6770
|
...rest
|
|
6519
|
-
})
|
|
6520
|
-
)
|
|
6771
|
+
});
|
|
6772
|
+
} catch (error) {
|
|
6773
|
+
if (config?.signal?.aborted) {
|
|
6774
|
+
throw getAbortReason(config.signal);
|
|
6775
|
+
}
|
|
6776
|
+
rethrowHTTPTransportError(error, this.classifyTransportErrors);
|
|
6777
|
+
}
|
|
6778
|
+
return await checkResponse(response);
|
|
6521
6779
|
} catch (error) {
|
|
6522
6780
|
if (config?.signal?.aborted) {
|
|
6523
6781
|
throw getAbortReason(config.signal);
|
|
@@ -6542,7 +6800,7 @@ var HTTPConnection = class _HTTPConnection {
|
|
|
6542
6800
|
for (let i = 0; i < tries; i++) {
|
|
6543
6801
|
try {
|
|
6544
6802
|
const resp = await this.get(`${object_type}`, args);
|
|
6545
|
-
return await resp.
|
|
6803
|
+
return await readJSONResponse(resp, this.classifyTransportErrors);
|
|
6546
6804
|
} catch (e) {
|
|
6547
6805
|
if (i < tries - 1) {
|
|
6548
6806
|
debugLogger.debug(
|
|
@@ -6565,7 +6823,7 @@ var HTTPConnection = class _HTTPConnection {
|
|
|
6565
6823
|
const resp = await this.post(`${object_type}`, args, {
|
|
6566
6824
|
headers: { "Content-Type": "application/json" }
|
|
6567
6825
|
});
|
|
6568
|
-
return await resp.
|
|
6826
|
+
return await readJSONResponse(resp, this.classifyTransportErrors);
|
|
6569
6827
|
}
|
|
6570
6828
|
// Custom inspect for Node.js console.log
|
|
6571
6829
|
[/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")]() {
|
|
@@ -8120,6 +8378,52 @@ function initLogger(options = {}) {
|
|
|
8120
8378
|
}
|
|
8121
8379
|
return ret;
|
|
8122
8380
|
}
|
|
8381
|
+
async function loginToLoaderRequestState({
|
|
8382
|
+
appUrl,
|
|
8383
|
+
apiKey,
|
|
8384
|
+
orgName,
|
|
8385
|
+
fetch: fetch2
|
|
8386
|
+
}) {
|
|
8387
|
+
let orgId;
|
|
8388
|
+
let apiUrl;
|
|
8389
|
+
if (apiKey === TEST_API_KEY) {
|
|
8390
|
+
orgId = "test-org-id";
|
|
8391
|
+
apiUrl = "https://braintrust.dev/fake-api-url";
|
|
8392
|
+
} else {
|
|
8393
|
+
let loginResponse;
|
|
8394
|
+
try {
|
|
8395
|
+
loginResponse = await fetch2(_urljoin(appUrl, `/api/apikey/login`), {
|
|
8396
|
+
method: "POST",
|
|
8397
|
+
headers: {
|
|
8398
|
+
"Content-Type": "application/json",
|
|
8399
|
+
Authorization: `Bearer ${apiKey}`
|
|
8400
|
+
}
|
|
8401
|
+
});
|
|
8402
|
+
} catch (error) {
|
|
8403
|
+
throw new HTTPTransportError(error);
|
|
8404
|
+
}
|
|
8405
|
+
const info = await readJSONResponse(
|
|
8406
|
+
await checkResponse(loginResponse),
|
|
8407
|
+
true
|
|
8408
|
+
);
|
|
8409
|
+
const org = selectLoginOrg(info.org_info, orgName);
|
|
8410
|
+
orgId = org.id;
|
|
8411
|
+
apiUrl = isomorph_default.getEnv("BRAINTRUST_API_URL") ?? org.api_url;
|
|
8412
|
+
if (!apiUrl) {
|
|
8413
|
+
throw new Error(
|
|
8414
|
+
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."
|
|
8415
|
+
);
|
|
8416
|
+
}
|
|
8417
|
+
}
|
|
8418
|
+
const apiConnection = new HTTPConnection(apiUrl, fetch2, true);
|
|
8419
|
+
apiConnection.set_token(apiKey);
|
|
8420
|
+
apiConnection.make_long_lived();
|
|
8421
|
+
return {
|
|
8422
|
+
appUrl,
|
|
8423
|
+
orgId,
|
|
8424
|
+
apiConn: () => apiConnection
|
|
8425
|
+
};
|
|
8426
|
+
}
|
|
8123
8427
|
async function loginToState(options = {}) {
|
|
8124
8428
|
const {
|
|
8125
8429
|
appUrl = isomorph_default.getEnv("BRAINTRUST_APP_URL") || "https://www.braintrust.dev",
|
|
@@ -8151,16 +8455,18 @@ async function loginToState(options = {}) {
|
|
|
8151
8455
|
_saveOrgInfo(state, testOrgInfo, testOrgInfo[0].name);
|
|
8152
8456
|
return state;
|
|
8153
8457
|
} else {
|
|
8154
|
-
const
|
|
8155
|
-
|
|
8458
|
+
const loginResponse = await fetch2(
|
|
8459
|
+
_urljoin(state.appUrl, `/api/apikey/login`),
|
|
8460
|
+
{
|
|
8156
8461
|
method: "POST",
|
|
8157
8462
|
headers: {
|
|
8158
8463
|
"Content-Type": "application/json",
|
|
8159
8464
|
Authorization: `Bearer ${apiKey}`
|
|
8160
8465
|
}
|
|
8161
|
-
}
|
|
8466
|
+
}
|
|
8162
8467
|
);
|
|
8163
|
-
const
|
|
8468
|
+
const resp = await checkResponse(loginResponse);
|
|
8469
|
+
const info = await readJSONResponse(resp);
|
|
8164
8470
|
_saveOrgInfo(state, info.org_info, orgName);
|
|
8165
8471
|
if (!state.apiUrl) {
|
|
8166
8472
|
if (orgName) {
|
|
@@ -8528,27 +8834,28 @@ function withCurrent(span, callback, state = void 0) {
|
|
|
8528
8834
|
const currentState = state ?? _globalState;
|
|
8529
8835
|
return currentState.contextManager.runInContext(span, () => callback(span));
|
|
8530
8836
|
}
|
|
8531
|
-
function _saveOrgInfo(state,
|
|
8532
|
-
|
|
8837
|
+
function _saveOrgInfo(state, orgInfo, orgName) {
|
|
8838
|
+
const org = selectLoginOrg(orgInfo, orgName);
|
|
8839
|
+
state.orgId = org.id;
|
|
8840
|
+
state.orgName = org.name;
|
|
8841
|
+
state.apiUrl = isomorph_default.getEnv("BRAINTRUST_API_URL") ?? org.api_url;
|
|
8842
|
+
state.proxyUrl = isomorph_default.getEnv("BRAINTRUST_PROXY_URL") ?? org.proxy_url;
|
|
8843
|
+
state.gitMetadataSettings = org.git_metadata || void 0;
|
|
8844
|
+
}
|
|
8845
|
+
function selectLoginOrg(orgInfo, orgName) {
|
|
8846
|
+
if (orgInfo.length === 0) {
|
|
8533
8847
|
throw new LoginInvalidOrgError(
|
|
8534
8848
|
"This user is not part of any organizations."
|
|
8535
8849
|
);
|
|
8536
8850
|
}
|
|
8537
|
-
for (const org of
|
|
8538
|
-
if (
|
|
8539
|
-
|
|
8540
|
-
state.orgName = org.name;
|
|
8541
|
-
state.apiUrl = isomorph_default.getEnv("BRAINTRUST_API_URL") ?? org.api_url;
|
|
8542
|
-
state.proxyUrl = isomorph_default.getEnv("BRAINTRUST_PROXY_URL") ?? org.proxy_url;
|
|
8543
|
-
state.gitMetadataSettings = org.git_metadata || void 0;
|
|
8544
|
-
break;
|
|
8851
|
+
for (const org of orgInfo) {
|
|
8852
|
+
if (orgName === void 0 || org.name === orgName) {
|
|
8853
|
+
return org;
|
|
8545
8854
|
}
|
|
8546
8855
|
}
|
|
8547
|
-
|
|
8548
|
-
|
|
8549
|
-
|
|
8550
|
-
);
|
|
8551
|
-
}
|
|
8856
|
+
throw new LoginInvalidOrgError(
|
|
8857
|
+
`Organization ${orgName} not found. Must be one of ${orgInfo.map((org) => org.name).join(", ")}`
|
|
8858
|
+
);
|
|
8552
8859
|
}
|
|
8553
8860
|
function validateTags(tags) {
|
|
8554
8861
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -8713,6 +9020,19 @@ function enrichAttachments(event, state) {
|
|
|
8713
9020
|
}
|
|
8714
9021
|
return event;
|
|
8715
9022
|
}
|
|
9023
|
+
async function resolveAttachmentsToBase64(event, state) {
|
|
9024
|
+
for (const [key, value] of Object.entries(event)) {
|
|
9025
|
+
if (value instanceof ReadonlyAttachment) {
|
|
9026
|
+
event[key] = await value.asBase64Url();
|
|
9027
|
+
continue;
|
|
9028
|
+
}
|
|
9029
|
+
if (!(value instanceof Object)) {
|
|
9030
|
+
continue;
|
|
9031
|
+
}
|
|
9032
|
+
await resolveAttachmentsToBase64(value, state);
|
|
9033
|
+
}
|
|
9034
|
+
return event;
|
|
9035
|
+
}
|
|
8716
9036
|
function validateAndSanitizeExperimentLogFullArgs(event, hasDataset) {
|
|
8717
9037
|
if ("input" in event && !isEmpty2(event.input) && "inputs" in event && !isEmpty2(event.inputs) || !("input" in event) && !("inputs" in event)) {
|
|
8718
9038
|
throw new Error(
|
|
@@ -10002,6 +10322,473 @@ var Dataset2 = class extends ObjectFetcher {
|
|
|
10002
10322
|
return typeof data === "object" && data !== null && "__braintrust_dataset_marker" in data;
|
|
10003
10323
|
}
|
|
10004
10324
|
};
|
|
10325
|
+
function isAttachmentObject(value) {
|
|
10326
|
+
return BraintrustAttachmentReference.safeParse(value).success || InlineAttachmentReferenceSchema.safeParse(value).success || ExternalAttachmentReference.safeParse(value).success;
|
|
10327
|
+
}
|
|
10328
|
+
function isURL(url) {
|
|
10329
|
+
try {
|
|
10330
|
+
const parsedUrl = new URL(url.trim());
|
|
10331
|
+
return parsedUrl.protocol === "http:" || parsedUrl.protocol === "https:";
|
|
10332
|
+
} catch {
|
|
10333
|
+
return false;
|
|
10334
|
+
}
|
|
10335
|
+
}
|
|
10336
|
+
function expandAttachmentArrayPreTemplate(content, variables) {
|
|
10337
|
+
if (typeof content !== "string") return null;
|
|
10338
|
+
const match = content.match(/^\{\{\s*([\w.]+)\s*\}\}$/);
|
|
10339
|
+
if (!match) return null;
|
|
10340
|
+
const varPath = match[1];
|
|
10341
|
+
const value = varPath.includes(".") ? getObjValueByPath(variables, varPath.split(".")) : variables[varPath];
|
|
10342
|
+
if (!Array.isArray(value)) return null;
|
|
10343
|
+
const allValid = value.every(
|
|
10344
|
+
(v) => isAttachmentObject(v) || typeof v === "string" && isURL(v)
|
|
10345
|
+
);
|
|
10346
|
+
if (!allValid) return null;
|
|
10347
|
+
return value.map((item) => ({
|
|
10348
|
+
type: "image_url",
|
|
10349
|
+
image_url: { url: item }
|
|
10350
|
+
}));
|
|
10351
|
+
}
|
|
10352
|
+
function renderMessageImpl(render, message, variables) {
|
|
10353
|
+
return {
|
|
10354
|
+
...message,
|
|
10355
|
+
..."content" in message ? {
|
|
10356
|
+
content: isEmpty2(message.content) ? void 0 : typeof message.content === "string" ? render(message.content) : message.content.flatMap((c) => {
|
|
10357
|
+
switch (c.type) {
|
|
10358
|
+
case "text":
|
|
10359
|
+
return [{ ...c, text: render(c.text) }];
|
|
10360
|
+
case "image_url":
|
|
10361
|
+
if (isObject(c.image_url.url)) {
|
|
10362
|
+
throw new Error(
|
|
10363
|
+
"Attachments must be replaced with URLs before calling `build()`"
|
|
10364
|
+
);
|
|
10365
|
+
}
|
|
10366
|
+
if (variables) {
|
|
10367
|
+
const expanded = expandAttachmentArrayPreTemplate(
|
|
10368
|
+
c.image_url.url,
|
|
10369
|
+
variables
|
|
10370
|
+
);
|
|
10371
|
+
if (expanded) {
|
|
10372
|
+
return expanded;
|
|
10373
|
+
}
|
|
10374
|
+
}
|
|
10375
|
+
return [
|
|
10376
|
+
{
|
|
10377
|
+
...c,
|
|
10378
|
+
image_url: {
|
|
10379
|
+
...c.image_url,
|
|
10380
|
+
url: render(c.image_url.url)
|
|
10381
|
+
}
|
|
10382
|
+
}
|
|
10383
|
+
];
|
|
10384
|
+
case "file":
|
|
10385
|
+
return [
|
|
10386
|
+
{
|
|
10387
|
+
...c,
|
|
10388
|
+
file: {
|
|
10389
|
+
...c.file.file_data && {
|
|
10390
|
+
file_data: render(c.file.file_data)
|
|
10391
|
+
},
|
|
10392
|
+
...c.file.file_id && {
|
|
10393
|
+
file_id: render(c.file.file_id)
|
|
10394
|
+
},
|
|
10395
|
+
...c.file.filename && {
|
|
10396
|
+
filename: render(c.file.filename)
|
|
10397
|
+
}
|
|
10398
|
+
}
|
|
10399
|
+
}
|
|
10400
|
+
];
|
|
10401
|
+
default:
|
|
10402
|
+
const _exhaustiveCheck = c;
|
|
10403
|
+
return _exhaustiveCheck;
|
|
10404
|
+
}
|
|
10405
|
+
})
|
|
10406
|
+
} : {},
|
|
10407
|
+
..."tool_calls" in message ? {
|
|
10408
|
+
tool_calls: isEmpty2(message.tool_calls) ? void 0 : message.tool_calls.map((t) => {
|
|
10409
|
+
return {
|
|
10410
|
+
type: t.type,
|
|
10411
|
+
id: render(t.id),
|
|
10412
|
+
function: {
|
|
10413
|
+
name: render(t.function.name),
|
|
10414
|
+
arguments: render(t.function.arguments)
|
|
10415
|
+
}
|
|
10416
|
+
};
|
|
10417
|
+
})
|
|
10418
|
+
} : {},
|
|
10419
|
+
..."tool_call_id" in message ? {
|
|
10420
|
+
tool_call_id: render(message.tool_call_id)
|
|
10421
|
+
} : {}
|
|
10422
|
+
};
|
|
10423
|
+
}
|
|
10424
|
+
function deserializePlainStringAsJSON(s) {
|
|
10425
|
+
if (s.trim() === "") {
|
|
10426
|
+
return { value: null, error: void 0 };
|
|
10427
|
+
}
|
|
10428
|
+
try {
|
|
10429
|
+
return { value: JSON.parse(s), error: void 0 };
|
|
10430
|
+
} catch (e) {
|
|
10431
|
+
return { value: s, error: e };
|
|
10432
|
+
}
|
|
10433
|
+
}
|
|
10434
|
+
function renderTemplatedObject(obj, args, options) {
|
|
10435
|
+
if (typeof obj === "string") {
|
|
10436
|
+
return renderTemplateContent(
|
|
10437
|
+
obj,
|
|
10438
|
+
args,
|
|
10439
|
+
(value) => typeof value === "string" ? value : JSON.stringify(value),
|
|
10440
|
+
{
|
|
10441
|
+
strict: options.strict,
|
|
10442
|
+
templateFormat: options.templateFormat
|
|
10443
|
+
}
|
|
10444
|
+
);
|
|
10445
|
+
} else if (isArray(obj)) {
|
|
10446
|
+
return obj.map((item) => renderTemplatedObject(item, args, options));
|
|
10447
|
+
} else if (isObject(obj)) {
|
|
10448
|
+
return Object.fromEntries(
|
|
10449
|
+
Object.entries(obj).map(([key, value]) => [
|
|
10450
|
+
key,
|
|
10451
|
+
renderTemplatedObject(value, args, options)
|
|
10452
|
+
])
|
|
10453
|
+
);
|
|
10454
|
+
}
|
|
10455
|
+
return obj;
|
|
10456
|
+
}
|
|
10457
|
+
function renderPromptParams(params, args, options = {}) {
|
|
10458
|
+
const templateFormat = parseTemplateFormat(options.templateFormat);
|
|
10459
|
+
const strict = !!options.strict;
|
|
10460
|
+
const schemaParsed = import_v38.z.object({
|
|
10461
|
+
response_format: import_v38.z.object({
|
|
10462
|
+
type: import_v38.z.literal("json_schema"),
|
|
10463
|
+
json_schema: ResponseFormatJsonSchema.omit({ schema: true }).extend({
|
|
10464
|
+
schema: import_v38.z.unknown()
|
|
10465
|
+
})
|
|
10466
|
+
})
|
|
10467
|
+
}).safeParse(params);
|
|
10468
|
+
if (schemaParsed.success) {
|
|
10469
|
+
const rawSchema = schemaParsed.data.response_format.json_schema.schema;
|
|
10470
|
+
const templatedSchema = renderTemplatedObject(rawSchema, args, {
|
|
10471
|
+
strict,
|
|
10472
|
+
templateFormat
|
|
10473
|
+
});
|
|
10474
|
+
const parsedSchema = typeof templatedSchema === "string" ? deserializePlainStringAsJSON(templatedSchema).value : templatedSchema;
|
|
10475
|
+
return {
|
|
10476
|
+
...params,
|
|
10477
|
+
response_format: {
|
|
10478
|
+
...schemaParsed.data.response_format,
|
|
10479
|
+
json_schema: {
|
|
10480
|
+
...schemaParsed.data.response_format.json_schema,
|
|
10481
|
+
schema: parsedSchema
|
|
10482
|
+
}
|
|
10483
|
+
}
|
|
10484
|
+
};
|
|
10485
|
+
}
|
|
10486
|
+
return params;
|
|
10487
|
+
}
|
|
10488
|
+
var Prompt2 = class _Prompt {
|
|
10489
|
+
constructor(metadata, defaults, noTrace) {
|
|
10490
|
+
this.metadata = metadata;
|
|
10491
|
+
this.defaults = defaults;
|
|
10492
|
+
this.noTrace = noTrace;
|
|
10493
|
+
void this.__braintrust_prompt_marker;
|
|
10494
|
+
}
|
|
10495
|
+
metadata;
|
|
10496
|
+
defaults;
|
|
10497
|
+
noTrace;
|
|
10498
|
+
parsedPromptData;
|
|
10499
|
+
hasParsedPromptData = false;
|
|
10500
|
+
__braintrust_prompt_marker = true;
|
|
10501
|
+
get id() {
|
|
10502
|
+
return this.metadata.id;
|
|
10503
|
+
}
|
|
10504
|
+
get projectId() {
|
|
10505
|
+
return this.metadata.project_id;
|
|
10506
|
+
}
|
|
10507
|
+
get name() {
|
|
10508
|
+
return "name" in this.metadata ? this.metadata.name : `Playground function ${this.metadata.id}`;
|
|
10509
|
+
}
|
|
10510
|
+
get slug() {
|
|
10511
|
+
return "slug" in this.metadata ? this.metadata.slug : this.metadata.id;
|
|
10512
|
+
}
|
|
10513
|
+
get prompt() {
|
|
10514
|
+
return this.getParsedPromptData()?.prompt;
|
|
10515
|
+
}
|
|
10516
|
+
get version() {
|
|
10517
|
+
return this.metadata[TRANSACTION_ID_FIELD];
|
|
10518
|
+
}
|
|
10519
|
+
get options() {
|
|
10520
|
+
return this.getParsedPromptData()?.options || {};
|
|
10521
|
+
}
|
|
10522
|
+
get templateFormat() {
|
|
10523
|
+
return this.getParsedPromptData()?.template_format;
|
|
10524
|
+
}
|
|
10525
|
+
get promptData() {
|
|
10526
|
+
return this.getParsedPromptData();
|
|
10527
|
+
}
|
|
10528
|
+
/**
|
|
10529
|
+
* Build the prompt with the given formatting options. The args you pass in will
|
|
10530
|
+
* be forwarded to the mustache template that defines the prompt and rendered with
|
|
10531
|
+
* the `mustache-js` library.
|
|
10532
|
+
*
|
|
10533
|
+
* @param buildArgs Args to forward along to the prompt template.
|
|
10534
|
+
*/
|
|
10535
|
+
build(buildArgs, options = {}) {
|
|
10536
|
+
return this.runBuild(buildArgs, {
|
|
10537
|
+
flavor: options.flavor ?? "chat",
|
|
10538
|
+
messages: options.messages,
|
|
10539
|
+
strict: options.strict,
|
|
10540
|
+
templateFormat: options.templateFormat
|
|
10541
|
+
});
|
|
10542
|
+
}
|
|
10543
|
+
/**
|
|
10544
|
+
* This is a special build method that first resolves attachment references, and then
|
|
10545
|
+
* calls the regular build method. You should use this if you are building prompts from
|
|
10546
|
+
* dataset rows that contain attachments.
|
|
10547
|
+
*
|
|
10548
|
+
* @param buildArgs Args to forward along to the prompt template.
|
|
10549
|
+
*/
|
|
10550
|
+
async buildWithAttachments(buildArgs, options = {}) {
|
|
10551
|
+
const hydrated = buildArgs instanceof Object ? await resolveAttachmentsToBase64(buildArgs, options.state) : buildArgs;
|
|
10552
|
+
return this.runBuild(hydrated, {
|
|
10553
|
+
flavor: options.flavor ?? "chat",
|
|
10554
|
+
messages: options.messages,
|
|
10555
|
+
strict: options.strict,
|
|
10556
|
+
templateFormat: options.templateFormat
|
|
10557
|
+
});
|
|
10558
|
+
}
|
|
10559
|
+
runBuild(buildArgs, options) {
|
|
10560
|
+
const { flavor } = options;
|
|
10561
|
+
const params = Object.fromEntries(
|
|
10562
|
+
Object.entries({
|
|
10563
|
+
...this.defaults,
|
|
10564
|
+
...Object.fromEntries(
|
|
10565
|
+
Object.entries(this.options.params || {}).filter(
|
|
10566
|
+
([k, _v]) => !BRAINTRUST_PARAMS.includes(k)
|
|
10567
|
+
)
|
|
10568
|
+
),
|
|
10569
|
+
...!isEmpty2(this.options.model) ? {
|
|
10570
|
+
model: this.options.model
|
|
10571
|
+
} : {}
|
|
10572
|
+
}).filter(([key, value]) => key !== "response_format" || value !== null)
|
|
10573
|
+
);
|
|
10574
|
+
if (!("model" in params) || isEmpty2(params.model)) {
|
|
10575
|
+
throw new Error(
|
|
10576
|
+
"No model specified. Either specify it in the prompt or as a default"
|
|
10577
|
+
);
|
|
10578
|
+
}
|
|
10579
|
+
const spanInfo = this.noTrace ? {} : {
|
|
10580
|
+
span_info: {
|
|
10581
|
+
metadata: {
|
|
10582
|
+
prompt: this.id ? {
|
|
10583
|
+
variables: buildArgs,
|
|
10584
|
+
id: this.id,
|
|
10585
|
+
project_id: this.projectId,
|
|
10586
|
+
version: this.version,
|
|
10587
|
+
..."prompt_session_id" in this.metadata ? { prompt_session_id: this.metadata.prompt_session_id } : {}
|
|
10588
|
+
} : void 0
|
|
10589
|
+
}
|
|
10590
|
+
}
|
|
10591
|
+
};
|
|
10592
|
+
const prompt = this.prompt;
|
|
10593
|
+
if (!prompt) {
|
|
10594
|
+
throw new Error("Empty prompt");
|
|
10595
|
+
}
|
|
10596
|
+
const dictArgParsed = import_v38.z.record(import_v38.z.unknown()).safeParse(buildArgs);
|
|
10597
|
+
const variables = {
|
|
10598
|
+
input: buildArgs,
|
|
10599
|
+
...dictArgParsed.success ? dictArgParsed.data : {}
|
|
10600
|
+
};
|
|
10601
|
+
const promptDataTemplateFormat = this.templateFormat;
|
|
10602
|
+
const resolvedTemplateFormat = parseTemplateFormat(
|
|
10603
|
+
options.templateFormat ?? promptDataTemplateFormat
|
|
10604
|
+
);
|
|
10605
|
+
const renderedPrompt = _Prompt.renderPrompt({
|
|
10606
|
+
prompt,
|
|
10607
|
+
buildArgs,
|
|
10608
|
+
options: { ...options, templateFormat: resolvedTemplateFormat }
|
|
10609
|
+
});
|
|
10610
|
+
if (flavor === "chat") {
|
|
10611
|
+
if (renderedPrompt.type !== "chat") {
|
|
10612
|
+
throw new Error(
|
|
10613
|
+
"Prompt is a completion prompt. Use buildCompletion() instead"
|
|
10614
|
+
);
|
|
10615
|
+
}
|
|
10616
|
+
return {
|
|
10617
|
+
...renderPromptParams(params, variables, {
|
|
10618
|
+
strict: options.strict,
|
|
10619
|
+
templateFormat: resolvedTemplateFormat
|
|
10620
|
+
}),
|
|
10621
|
+
...spanInfo,
|
|
10622
|
+
messages: renderedPrompt.messages,
|
|
10623
|
+
...renderedPrompt.tools ? {
|
|
10624
|
+
tools: ChatCompletionTool.array().parse(JSON.parse(renderedPrompt.tools))
|
|
10625
|
+
} : void 0
|
|
10626
|
+
};
|
|
10627
|
+
} else if (flavor === "completion") {
|
|
10628
|
+
if (renderedPrompt.type !== "completion") {
|
|
10629
|
+
throw new Error(`Prompt is a chat prompt. Use flavor: 'chat' instead`);
|
|
10630
|
+
}
|
|
10631
|
+
return {
|
|
10632
|
+
...renderPromptParams(params, variables, {
|
|
10633
|
+
strict: options.strict,
|
|
10634
|
+
templateFormat: resolvedTemplateFormat
|
|
10635
|
+
}),
|
|
10636
|
+
...spanInfo,
|
|
10637
|
+
prompt: renderedPrompt.content
|
|
10638
|
+
};
|
|
10639
|
+
} else {
|
|
10640
|
+
throw new Error("never!");
|
|
10641
|
+
}
|
|
10642
|
+
}
|
|
10643
|
+
static renderPrompt({
|
|
10644
|
+
prompt,
|
|
10645
|
+
buildArgs,
|
|
10646
|
+
options
|
|
10647
|
+
}) {
|
|
10648
|
+
const escape = (v) => {
|
|
10649
|
+
if (v === void 0) {
|
|
10650
|
+
throw new Error("Missing!");
|
|
10651
|
+
} else if (typeof v === "string") {
|
|
10652
|
+
return v;
|
|
10653
|
+
} else if (v instanceof ReadonlyAttachment) {
|
|
10654
|
+
throw new Error(
|
|
10655
|
+
"Use buildWithAttachments() to build prompts with attachments"
|
|
10656
|
+
);
|
|
10657
|
+
} else {
|
|
10658
|
+
return JSON.stringify(v);
|
|
10659
|
+
}
|
|
10660
|
+
};
|
|
10661
|
+
const dictArgParsed = import_v38.z.record(import_v38.z.unknown()).safeParse(buildArgs);
|
|
10662
|
+
const variables = {
|
|
10663
|
+
input: buildArgs,
|
|
10664
|
+
...dictArgParsed.success ? dictArgParsed.data : {}
|
|
10665
|
+
};
|
|
10666
|
+
const templateFormat = parseTemplateFormat(options.templateFormat);
|
|
10667
|
+
if (prompt.type === "chat") {
|
|
10668
|
+
const render = (template) => renderTemplateContent(template, variables, escape, {
|
|
10669
|
+
strict: options.strict,
|
|
10670
|
+
templateFormat
|
|
10671
|
+
});
|
|
10672
|
+
const baseMessages = (prompt.messages || []).map(
|
|
10673
|
+
(m) => renderMessageImpl(render, m, variables)
|
|
10674
|
+
);
|
|
10675
|
+
const hasSystemPrompt = baseMessages.some((m) => m.role === "system");
|
|
10676
|
+
const messages = [
|
|
10677
|
+
...baseMessages,
|
|
10678
|
+
...(options.messages ?? []).filter(
|
|
10679
|
+
(m) => !(hasSystemPrompt && m.role === "system")
|
|
10680
|
+
)
|
|
10681
|
+
];
|
|
10682
|
+
return {
|
|
10683
|
+
type: "chat",
|
|
10684
|
+
messages,
|
|
10685
|
+
...prompt.tools?.trim() ? {
|
|
10686
|
+
tools: render(prompt.tools)
|
|
10687
|
+
} : void 0
|
|
10688
|
+
};
|
|
10689
|
+
} else if (prompt.type === "completion") {
|
|
10690
|
+
if (options.messages) {
|
|
10691
|
+
throw new Error(
|
|
10692
|
+
"extra messages are not supported for completion prompts"
|
|
10693
|
+
);
|
|
10694
|
+
}
|
|
10695
|
+
const content = renderTemplateContent(prompt.content, variables, escape, {
|
|
10696
|
+
strict: options.strict,
|
|
10697
|
+
templateFormat
|
|
10698
|
+
});
|
|
10699
|
+
return {
|
|
10700
|
+
type: "completion",
|
|
10701
|
+
content
|
|
10702
|
+
};
|
|
10703
|
+
} else {
|
|
10704
|
+
const _ = prompt;
|
|
10705
|
+
throw new Error(`Invalid prompt type: ${_}`);
|
|
10706
|
+
}
|
|
10707
|
+
}
|
|
10708
|
+
getParsedPromptData() {
|
|
10709
|
+
if (!this.hasParsedPromptData) {
|
|
10710
|
+
this.parsedPromptData = PromptData.parse(this.metadata.prompt_data);
|
|
10711
|
+
this.hasParsedPromptData = true;
|
|
10712
|
+
}
|
|
10713
|
+
return this.parsedPromptData;
|
|
10714
|
+
}
|
|
10715
|
+
static isPrompt(data) {
|
|
10716
|
+
return typeof data === "object" && data !== null && "__braintrust_prompt_marker" in data;
|
|
10717
|
+
}
|
|
10718
|
+
/** @internal */
|
|
10719
|
+
_internalSerializeForCache() {
|
|
10720
|
+
return {
|
|
10721
|
+
metadata: this.metadata,
|
|
10722
|
+
defaults: this.defaults,
|
|
10723
|
+
noTrace: this.noTrace
|
|
10724
|
+
};
|
|
10725
|
+
}
|
|
10726
|
+
static fromPromptData(name, promptData) {
|
|
10727
|
+
return new _Prompt(
|
|
10728
|
+
{
|
|
10729
|
+
name,
|
|
10730
|
+
slug: name,
|
|
10731
|
+
prompt_data: promptData
|
|
10732
|
+
},
|
|
10733
|
+
{},
|
|
10734
|
+
false
|
|
10735
|
+
);
|
|
10736
|
+
}
|
|
10737
|
+
};
|
|
10738
|
+
var RemoteEvalParameters = class {
|
|
10739
|
+
constructor(metadata) {
|
|
10740
|
+
this.metadata = metadata;
|
|
10741
|
+
void this.__braintrust_parameters_marker;
|
|
10742
|
+
}
|
|
10743
|
+
metadata;
|
|
10744
|
+
__braintrust_parameters_marker = true;
|
|
10745
|
+
get id() {
|
|
10746
|
+
return this.metadata.id;
|
|
10747
|
+
}
|
|
10748
|
+
get projectId() {
|
|
10749
|
+
return this.metadata.project_id;
|
|
10750
|
+
}
|
|
10751
|
+
get name() {
|
|
10752
|
+
return this.metadata.name;
|
|
10753
|
+
}
|
|
10754
|
+
get slug() {
|
|
10755
|
+
return this.metadata.slug;
|
|
10756
|
+
}
|
|
10757
|
+
get version() {
|
|
10758
|
+
return this.metadata[TRANSACTION_ID_FIELD];
|
|
10759
|
+
}
|
|
10760
|
+
get schema() {
|
|
10761
|
+
return this.metadata.function_data.__schema;
|
|
10762
|
+
}
|
|
10763
|
+
get data() {
|
|
10764
|
+
return this.metadata.function_data.data ?? {};
|
|
10765
|
+
}
|
|
10766
|
+
/** @internal */
|
|
10767
|
+
_internalSerializeForCache() {
|
|
10768
|
+
return { metadata: this.metadata };
|
|
10769
|
+
}
|
|
10770
|
+
validate(data) {
|
|
10771
|
+
if (typeof data !== "object" || data === null) {
|
|
10772
|
+
return false;
|
|
10773
|
+
}
|
|
10774
|
+
const schemaProps = this.schema.properties;
|
|
10775
|
+
if (typeof schemaProps !== "object" || schemaProps === null) {
|
|
10776
|
+
return true;
|
|
10777
|
+
}
|
|
10778
|
+
for (const key of Object.keys(schemaProps)) {
|
|
10779
|
+
if (!(key in data)) {
|
|
10780
|
+
const required = Array.isArray(this.schema.required) ? this.schema.required : [];
|
|
10781
|
+
if (required.includes(key)) {
|
|
10782
|
+
return false;
|
|
10783
|
+
}
|
|
10784
|
+
}
|
|
10785
|
+
}
|
|
10786
|
+
return true;
|
|
10787
|
+
}
|
|
10788
|
+
static isParameters(x) {
|
|
10789
|
+
return typeof x === "object" && x !== null && "__braintrust_parameters_marker" in x && x.__braintrust_parameters_marker === true;
|
|
10790
|
+
}
|
|
10791
|
+
};
|
|
10005
10792
|
var TEST_API_KEY = "___TEST_API_KEY__THIS_IS_NOT_REAL___";
|
|
10006
10793
|
|
|
10007
10794
|
// src/instrumentation/core/channel-tracing-utils.ts
|
|
@@ -10447,56 +11234,14 @@ function suppressionStore() {
|
|
|
10447
11234
|
autoInstrumentationSuppressionStore ??= isomorph_default.newAsyncLocalStorage();
|
|
10448
11235
|
return autoInstrumentationSuppressionStore;
|
|
10449
11236
|
}
|
|
10450
|
-
function currentFrames() {
|
|
10451
|
-
return suppressionStore().getStore()?.frames ?? [];
|
|
10452
|
-
}
|
|
10453
11237
|
function isAutoInstrumentationSuppressed() {
|
|
10454
|
-
|
|
10455
|
-
return frames[frames.length - 1]?.mode === "suppress";
|
|
11238
|
+
return suppressionStore().getStore() === true;
|
|
10456
11239
|
}
|
|
10457
11240
|
function runWithAutoInstrumentationSuppressed(callback) {
|
|
10458
|
-
|
|
10459
|
-
id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
|
|
10460
|
-
mode: "suppress"
|
|
10461
|
-
};
|
|
10462
|
-
return suppressionStore().run(
|
|
10463
|
-
{ frames: [...currentFrames(), frame] },
|
|
10464
|
-
callback
|
|
10465
|
-
);
|
|
11241
|
+
return suppressionStore().run(true, callback);
|
|
10466
11242
|
}
|
|
10467
|
-
function
|
|
10468
|
-
|
|
10469
|
-
if (!startChannel) {
|
|
10470
|
-
return void 0;
|
|
10471
|
-
}
|
|
10472
|
-
const store = suppressionStore();
|
|
10473
|
-
startChannel.bindStore(store, () => ({
|
|
10474
|
-
frames: [
|
|
10475
|
-
...currentFrames(),
|
|
10476
|
-
{
|
|
10477
|
-
id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
|
|
10478
|
-
mode: "suppress"
|
|
10479
|
-
}
|
|
10480
|
-
]
|
|
10481
|
-
}));
|
|
10482
|
-
return () => {
|
|
10483
|
-
startChannel.unbindStore(store);
|
|
10484
|
-
};
|
|
10485
|
-
}
|
|
10486
|
-
function enterAutoInstrumentationAllowed() {
|
|
10487
|
-
const frame = {
|
|
10488
|
-
id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-allow"),
|
|
10489
|
-
mode: "allow"
|
|
10490
|
-
};
|
|
10491
|
-
suppressionStore().enterWith({
|
|
10492
|
-
frames: [...currentFrames(), frame]
|
|
10493
|
-
});
|
|
10494
|
-
return () => {
|
|
10495
|
-
const frames = currentFrames().filter(
|
|
10496
|
-
(candidate) => candidate.id !== frame.id
|
|
10497
|
-
);
|
|
10498
|
-
suppressionStore().enterWith(frames.length > 0 ? { frames } : void 0);
|
|
10499
|
-
};
|
|
11243
|
+
function runWithAutoInstrumentationAllowed(callback) {
|
|
11244
|
+
return suppressionStore().run(void 0, callback);
|
|
10500
11245
|
}
|
|
10501
11246
|
|
|
10502
11247
|
// src/instrumentation/core/channel-tracing.ts
|
|
@@ -11785,13 +12530,33 @@ function aggregateChatLogprobs(existing, incoming) {
|
|
|
11785
12530
|
}
|
|
11786
12531
|
return aggregated;
|
|
11787
12532
|
}
|
|
12533
|
+
function createAggregatedChatChoice(index) {
|
|
12534
|
+
return {
|
|
12535
|
+
index,
|
|
12536
|
+
role: void 0,
|
|
12537
|
+
content: void 0,
|
|
12538
|
+
refusal: void 0,
|
|
12539
|
+
toolCallsByIndex: /* @__PURE__ */ new Map(),
|
|
12540
|
+
logprobs: void 0,
|
|
12541
|
+
finish_reason: void 0
|
|
12542
|
+
};
|
|
12543
|
+
}
|
|
12544
|
+
function toChatChoice(choice) {
|
|
12545
|
+
const toolCalls = Array.from(choice.toolCallsByIndex.entries()).sort(([left], [right]) => left - right).map(([, toolCall]) => toolCall);
|
|
12546
|
+
return {
|
|
12547
|
+
index: choice.index,
|
|
12548
|
+
message: {
|
|
12549
|
+
role: choice.role,
|
|
12550
|
+
content: choice.content,
|
|
12551
|
+
...choice.refusal !== void 0 ? { refusal: choice.refusal } : {},
|
|
12552
|
+
tool_calls: toolCalls.length > 0 ? toolCalls : void 0
|
|
12553
|
+
},
|
|
12554
|
+
logprobs: choice.logprobs ?? null,
|
|
12555
|
+
finish_reason: choice.finish_reason
|
|
12556
|
+
};
|
|
12557
|
+
}
|
|
11788
12558
|
function aggregateChatCompletionChunks(chunks, streamResult, endEvent) {
|
|
11789
|
-
|
|
11790
|
-
let content = void 0;
|
|
11791
|
-
let refusal = void 0;
|
|
11792
|
-
let tool_calls = void 0;
|
|
11793
|
-
let logprobs = void 0;
|
|
11794
|
-
let finish_reason = void 0;
|
|
12559
|
+
const choicesByIndex = /* @__PURE__ */ new Map();
|
|
11795
12560
|
let metrics = {};
|
|
11796
12561
|
for (const chunk of chunks) {
|
|
11797
12562
|
if (chunk.usage) {
|
|
@@ -11800,62 +12565,75 @@ function aggregateChatCompletionChunks(chunks, streamResult, endEvent) {
|
|
|
11800
12565
|
...parseMetricsFromUsage(chunk.usage)
|
|
11801
12566
|
};
|
|
11802
12567
|
}
|
|
11803
|
-
const
|
|
11804
|
-
if (!
|
|
11805
|
-
continue;
|
|
11806
|
-
}
|
|
11807
|
-
if (choice.finish_reason) {
|
|
11808
|
-
finish_reason = choice.finish_reason;
|
|
11809
|
-
}
|
|
11810
|
-
logprobs = aggregateChatLogprobs(logprobs, choice.logprobs);
|
|
11811
|
-
const delta = choice.delta;
|
|
11812
|
-
if (!delta) {
|
|
12568
|
+
const choices = chunk.choices;
|
|
12569
|
+
if (!choices?.length) {
|
|
11813
12570
|
continue;
|
|
11814
12571
|
}
|
|
11815
|
-
|
|
11816
|
-
|
|
11817
|
-
|
|
11818
|
-
|
|
11819
|
-
|
|
11820
|
-
|
|
11821
|
-
|
|
11822
|
-
|
|
11823
|
-
|
|
11824
|
-
|
|
11825
|
-
|
|
11826
|
-
|
|
11827
|
-
|
|
11828
|
-
|
|
11829
|
-
|
|
11830
|
-
|
|
11831
|
-
|
|
11832
|
-
|
|
11833
|
-
|
|
11834
|
-
|
|
11835
|
-
|
|
12572
|
+
for (const choice of choices) {
|
|
12573
|
+
const choiceIndex = choice.index;
|
|
12574
|
+
let aggregatedChoice = choicesByIndex.get(choiceIndex);
|
|
12575
|
+
if (!aggregatedChoice) {
|
|
12576
|
+
aggregatedChoice = createAggregatedChatChoice(choiceIndex);
|
|
12577
|
+
choicesByIndex.set(choiceIndex, aggregatedChoice);
|
|
12578
|
+
}
|
|
12579
|
+
if (choice.finish_reason) {
|
|
12580
|
+
aggregatedChoice.finish_reason = choice.finish_reason;
|
|
12581
|
+
}
|
|
12582
|
+
aggregatedChoice.logprobs = aggregateChatLogprobs(
|
|
12583
|
+
aggregatedChoice.logprobs,
|
|
12584
|
+
choice.logprobs
|
|
12585
|
+
);
|
|
12586
|
+
const delta = choice.delta;
|
|
12587
|
+
if (!delta) {
|
|
12588
|
+
continue;
|
|
12589
|
+
}
|
|
12590
|
+
if (delta.finish_reason) {
|
|
12591
|
+
aggregatedChoice.finish_reason = delta.finish_reason;
|
|
12592
|
+
}
|
|
12593
|
+
if (!aggregatedChoice.role && delta.role) {
|
|
12594
|
+
aggregatedChoice.role = delta.role;
|
|
12595
|
+
}
|
|
12596
|
+
if (delta.content) {
|
|
12597
|
+
aggregatedChoice.content = (aggregatedChoice.content || "") + delta.content;
|
|
12598
|
+
}
|
|
12599
|
+
if (delta.refusal) {
|
|
12600
|
+
aggregatedChoice.refusal = (aggregatedChoice.refusal || "") + delta.refusal;
|
|
12601
|
+
}
|
|
12602
|
+
if (delta.tool_calls) {
|
|
12603
|
+
for (const toolDelta of delta.tool_calls) {
|
|
12604
|
+
let aggregatedToolCall = aggregatedChoice.toolCallsByIndex.get(
|
|
12605
|
+
toolDelta.index
|
|
12606
|
+
);
|
|
12607
|
+
if (!aggregatedToolCall) {
|
|
12608
|
+
aggregatedToolCall = {
|
|
12609
|
+
function: { arguments: "" }
|
|
12610
|
+
};
|
|
12611
|
+
aggregatedChoice.toolCallsByIndex.set(
|
|
12612
|
+
toolDelta.index,
|
|
12613
|
+
aggregatedToolCall
|
|
12614
|
+
);
|
|
11836
12615
|
}
|
|
11837
|
-
|
|
11838
|
-
|
|
11839
|
-
|
|
12616
|
+
if (toolDelta.id !== void 0) {
|
|
12617
|
+
aggregatedToolCall.id = toolDelta.id;
|
|
12618
|
+
}
|
|
12619
|
+
if (toolDelta.type !== void 0) {
|
|
12620
|
+
aggregatedToolCall.type = toolDelta.type;
|
|
12621
|
+
}
|
|
12622
|
+
if (toolDelta.function?.name !== void 0) {
|
|
12623
|
+
aggregatedToolCall.function.name = toolDelta.function.name;
|
|
12624
|
+
}
|
|
12625
|
+
if (toolDelta.function?.arguments !== void 0) {
|
|
12626
|
+
aggregatedToolCall.function.arguments += toolDelta.function.arguments;
|
|
12627
|
+
}
|
|
12628
|
+
}
|
|
11840
12629
|
}
|
|
11841
12630
|
}
|
|
11842
12631
|
}
|
|
11843
12632
|
metrics = withCachedMetric(metrics, streamResult, endEvent);
|
|
12633
|
+
const output = Array.from(choicesByIndex.values()).sort((left, right) => left.index - right.index).map(toChatChoice);
|
|
11844
12634
|
return {
|
|
11845
12635
|
metrics,
|
|
11846
|
-
output: [
|
|
11847
|
-
{
|
|
11848
|
-
index: 0,
|
|
11849
|
-
message: {
|
|
11850
|
-
role,
|
|
11851
|
-
content,
|
|
11852
|
-
...refusal !== void 0 ? { refusal } : {},
|
|
11853
|
-
tool_calls
|
|
11854
|
-
},
|
|
11855
|
-
logprobs: logprobs ?? null,
|
|
11856
|
-
finish_reason
|
|
11857
|
-
}
|
|
11858
|
-
]
|
|
12636
|
+
output: output.length > 0 ? output : [toChatChoice(createAggregatedChatChoice(0))]
|
|
11859
12637
|
};
|
|
11860
12638
|
}
|
|
11861
12639
|
function aggregateResponseStreamEvents(chunks, _streamResult, endEvent) {
|
|
@@ -13178,6 +13956,12 @@ function parseMetricsFromUsage2(usage) {
|
|
|
13178
13956
|
}
|
|
13179
13957
|
}
|
|
13180
13958
|
}
|
|
13959
|
+
if (isObject(usage.output_tokens_details)) {
|
|
13960
|
+
const thinkingTokens = usage.output_tokens_details.thinking_tokens;
|
|
13961
|
+
if (typeof thinkingTokens === "number") {
|
|
13962
|
+
metrics.completion_reasoning_tokens = thinkingTokens;
|
|
13963
|
+
}
|
|
13964
|
+
}
|
|
13181
13965
|
if (isObject(usage.server_tool_use)) {
|
|
13182
13966
|
for (const [name, value] of Object.entries(usage.server_tool_use)) {
|
|
13183
13967
|
if (typeof value === "number") {
|
|
@@ -14134,7 +14918,6 @@ function endHarnessTurn(parent) {
|
|
|
14134
14918
|
function braintrustAISDKTelemetry() {
|
|
14135
14919
|
const operations = /* @__PURE__ */ new Map();
|
|
14136
14920
|
const operationKeysByCallId = /* @__PURE__ */ new Map();
|
|
14137
|
-
const workflowOperationKeyStore = isomorph_default.newAsyncLocalStorage();
|
|
14138
14921
|
const modelSpans = /* @__PURE__ */ new Map();
|
|
14139
14922
|
const objectSpans = /* @__PURE__ */ new Map();
|
|
14140
14923
|
const embedSpans = /* @__PURE__ */ new Map();
|
|
@@ -14177,9 +14960,6 @@ function braintrustAISDKTelemetry() {
|
|
|
14177
14960
|
return;
|
|
14178
14961
|
}
|
|
14179
14962
|
operations.delete(operationKey);
|
|
14180
|
-
if (workflowOperationKeyStore.getStore() === operationKey) {
|
|
14181
|
-
workflowOperationKeyStore.enterWith(void 0);
|
|
14182
|
-
}
|
|
14183
14963
|
const keys = operationKeysByCallId.get(state.callId);
|
|
14184
14964
|
if (!keys) {
|
|
14185
14965
|
return;
|
|
@@ -14227,14 +15007,7 @@ function braintrustAISDKTelemetry() {
|
|
|
14227
15007
|
return key;
|
|
14228
15008
|
}
|
|
14229
15009
|
}
|
|
14230
|
-
|
|
14231
|
-
if (workflowOperationKey && keys.includes(workflowOperationKey)) {
|
|
14232
|
-
return workflowOperationKey;
|
|
14233
|
-
}
|
|
14234
|
-
if (callId === "workflow-agent") {
|
|
14235
|
-
return void 0;
|
|
14236
|
-
}
|
|
14237
|
-
return mode === "finish" ? keys[0] : keys[keys.length - 1];
|
|
15010
|
+
return callId === "workflow-agent" || mode === "active" ? keys[keys.length - 1] : keys[0];
|
|
14238
15011
|
};
|
|
14239
15012
|
const operationKeyFromEvent = (event, mode = "active") => {
|
|
14240
15013
|
const explicit = explicitOperationKey(event);
|
|
@@ -14248,17 +15021,13 @@ function braintrustAISDKTelemetry() {
|
|
|
14248
15021
|
if (operationKey) {
|
|
14249
15022
|
return operationKey;
|
|
14250
15023
|
}
|
|
14251
|
-
const
|
|
14252
|
-
if (
|
|
14253
|
-
return
|
|
15024
|
+
const workflowAgentKeys2 = operationKeysByCallId.get("workflow-agent");
|
|
15025
|
+
if (workflowAgentKeys2?.length) {
|
|
15026
|
+
return workflowAgentKeys2[workflowAgentKeys2.length - 1];
|
|
14254
15027
|
}
|
|
14255
15028
|
return callId === "workflow-agent" ? void 0 : callId;
|
|
14256
15029
|
}
|
|
14257
15030
|
}
|
|
14258
|
-
const workflowOperationKey = workflowOperationKeyStore.getStore();
|
|
14259
|
-
if (workflowOperationKey && operations.has(workflowOperationKey)) {
|
|
14260
|
-
return workflowOperationKey;
|
|
14261
|
-
}
|
|
14262
15031
|
const wrapperSpan = currentWorkflowAgentWrapperSpan();
|
|
14263
15032
|
if (wrapperSpan?.spanId) {
|
|
14264
15033
|
for (const [operationKey, state] of operations) {
|
|
@@ -14268,8 +15037,8 @@ function braintrustAISDKTelemetry() {
|
|
|
14268
15037
|
}
|
|
14269
15038
|
}
|
|
14270
15039
|
const workflowAgentKeys = operationKeysByCallId.get("workflow-agent");
|
|
14271
|
-
if (workflowAgentKeys?.length
|
|
14272
|
-
return workflowAgentKeys[
|
|
15040
|
+
if (workflowAgentKeys?.length) {
|
|
15041
|
+
return workflowAgentKeys[workflowAgentKeys.length - 1];
|
|
14273
15042
|
}
|
|
14274
15043
|
if (operations.size === 1) {
|
|
14275
15044
|
return operations.keys().next().value;
|
|
@@ -14472,9 +15241,6 @@ function braintrustAISDKTelemetry() {
|
|
|
14472
15241
|
if (!ownsSpan) {
|
|
14473
15242
|
return;
|
|
14474
15243
|
}
|
|
14475
|
-
if (workflowAgent) {
|
|
14476
|
-
workflowOperationKeyStore.enterWith(operationKey);
|
|
14477
|
-
}
|
|
14478
15244
|
let metadata = metadataFromEvent(event);
|
|
14479
15245
|
const logPayload = { metadata };
|
|
14480
15246
|
const workflowAgentCallInput = workflowAgent ? operationInput(event, operationName) : void 0;
|
|
@@ -14946,6 +15712,10 @@ var aiSDKChannels = defineChannels(
|
|
|
14946
15712
|
channelName: "generateText",
|
|
14947
15713
|
kind: "async"
|
|
14948
15714
|
}),
|
|
15715
|
+
generateImage: channel({
|
|
15716
|
+
channelName: "generateImage",
|
|
15717
|
+
kind: "async"
|
|
15718
|
+
}),
|
|
14949
15719
|
streamText: channel({
|
|
14950
15720
|
channelName: "streamText",
|
|
14951
15721
|
kind: "async"
|
|
@@ -15133,7 +15903,7 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
15133
15903
|
}
|
|
15134
15904
|
subscribeToAISDK() {
|
|
15135
15905
|
const denyOutputPaths = this.config.denyOutputPaths || DEFAULT_DENY_OUTPUT_PATHS;
|
|
15136
|
-
this.unsubscribers.push(
|
|
15906
|
+
this.unsubscribers.push(interceptAISDKV7TelemetryDispatcher());
|
|
15137
15907
|
this.unsubscribers.push(subscribeToHarnessAgentCreateSession());
|
|
15138
15908
|
this.unsubscribers.push(
|
|
15139
15909
|
subscribeToHarnessContinuation(
|
|
@@ -15161,6 +15931,18 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
15161
15931
|
aggregateChunks: aggregateAISDKChunks
|
|
15162
15932
|
})
|
|
15163
15933
|
);
|
|
15934
|
+
this.unsubscribers.push(
|
|
15935
|
+
traceAsyncChannel(aiSDKChannels.generateImage, {
|
|
15936
|
+
name: "generateImage",
|
|
15937
|
+
type: "llm" /* LLM */,
|
|
15938
|
+
extractInput: ([params], event) => prepareAISDKGenerateImageInput(params, event.self),
|
|
15939
|
+
extractOutput: (result, endEvent) => processAISDKGenerateImageOutput(
|
|
15940
|
+
result,
|
|
15941
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
15942
|
+
),
|
|
15943
|
+
extractMetrics: (result) => extractTokenMetrics(result)
|
|
15944
|
+
})
|
|
15945
|
+
);
|
|
15164
15946
|
this.unsubscribers.push(
|
|
15165
15947
|
traceStreamingChannel(aiSDKChannels.streamText, {
|
|
15166
15948
|
name: "streamText",
|
|
@@ -15650,26 +16432,29 @@ function subscribeToHarnessContinuation(continuationChannel, defaultDenyOutputPa
|
|
|
15650
16432
|
channel2.unsubscribe(handlers);
|
|
15651
16433
|
};
|
|
15652
16434
|
}
|
|
15653
|
-
function
|
|
15654
|
-
const channel2 = aiSDKChannels.v7CreateTelemetryDispatcher.tracingChannel();
|
|
16435
|
+
function interceptAISDKV7TelemetryDispatcher() {
|
|
15655
16436
|
const telemetry = braintrustAISDKTelemetry();
|
|
15656
|
-
|
|
15657
|
-
|
|
15658
|
-
const
|
|
15659
|
-
|
|
15660
|
-
|
|
16437
|
+
return aiSDKChannels.v7CreateTelemetryDispatcher.intercept(
|
|
16438
|
+
(target, thisArg, args) => {
|
|
16439
|
+
const dispatcher = Reflect.apply(target, thisArg, args);
|
|
16440
|
+
const telemetryOptions = args[0]?.telemetry;
|
|
16441
|
+
if (telemetryOptions?.isEnabled !== false) {
|
|
16442
|
+
try {
|
|
16443
|
+
patchAISDKV7TelemetryDispatcher(
|
|
16444
|
+
dispatcher,
|
|
16445
|
+
telemetry,
|
|
16446
|
+
telemetryOptions
|
|
16447
|
+
);
|
|
16448
|
+
} catch (error) {
|
|
16449
|
+
debugLogger.error(
|
|
16450
|
+
"Error instrumenting AI SDK v7 telemetry dispatcher:",
|
|
16451
|
+
error
|
|
16452
|
+
);
|
|
16453
|
+
}
|
|
15661
16454
|
}
|
|
15662
|
-
|
|
15663
|
-
event.result,
|
|
15664
|
-
telemetry,
|
|
15665
|
-
telemetryOptions
|
|
15666
|
-
);
|
|
16455
|
+
return dispatcher;
|
|
15667
16456
|
}
|
|
15668
|
-
|
|
15669
|
-
channel2.subscribe(handlers);
|
|
15670
|
-
return () => {
|
|
15671
|
-
channel2.unsubscribe(handlers);
|
|
15672
|
-
};
|
|
16457
|
+
);
|
|
15673
16458
|
}
|
|
15674
16459
|
function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry, telemetryOptions) {
|
|
15675
16460
|
if (!isObject(dispatcher)) {
|
|
@@ -15994,16 +16779,10 @@ var convertImageToAttachment = (image, explicitMimeType) => {
|
|
|
15994
16779
|
}
|
|
15995
16780
|
}
|
|
15996
16781
|
if (explicitMimeType) {
|
|
15997
|
-
|
|
15998
|
-
|
|
15999
|
-
data: new Blob([image], { type: explicitMimeType }),
|
|
16000
|
-
filename: `image.${getExtensionFromMediaType(explicitMimeType)}`,
|
|
16001
|
-
contentType: explicitMimeType
|
|
16002
|
-
});
|
|
16003
|
-
}
|
|
16004
|
-
if (typeof Buffer !== "undefined" && Buffer.isBuffer(image)) {
|
|
16782
|
+
const blob = convertDataToBlob(image, explicitMimeType);
|
|
16783
|
+
if (blob) {
|
|
16005
16784
|
return new Attachment({
|
|
16006
|
-
data:
|
|
16785
|
+
data: blob,
|
|
16007
16786
|
filename: `image.${getExtensionFromMediaType(explicitMimeType)}`,
|
|
16008
16787
|
contentType: explicitMimeType
|
|
16009
16788
|
});
|
|
@@ -16057,6 +16836,25 @@ var convertDataToAttachment = (data, mimeType, filename) => {
|
|
|
16057
16836
|
function processAISDKCallInput(params) {
|
|
16058
16837
|
return processInputAttachmentsSync(params);
|
|
16059
16838
|
}
|
|
16839
|
+
function processAISDKGenerateImageInput(params) {
|
|
16840
|
+
const prompt = params.prompt;
|
|
16841
|
+
if (!isObject(prompt) || Array.isArray(prompt)) {
|
|
16842
|
+
return processAISDKCallInput(params);
|
|
16843
|
+
}
|
|
16844
|
+
const processedPrompt = { ...prompt };
|
|
16845
|
+
if (Array.isArray(prompt.images)) {
|
|
16846
|
+
processedPrompt.images = prompt.images.map(
|
|
16847
|
+
(image) => convertImageToAttachment(image, "image/png") ?? image
|
|
16848
|
+
);
|
|
16849
|
+
}
|
|
16850
|
+
if (prompt.mask !== void 0) {
|
|
16851
|
+
processedPrompt.mask = convertImageToAttachment(prompt.mask, "image/png") ?? prompt.mask;
|
|
16852
|
+
}
|
|
16853
|
+
return processAISDKCallInput({
|
|
16854
|
+
...params,
|
|
16855
|
+
prompt: processedPrompt
|
|
16856
|
+
});
|
|
16857
|
+
}
|
|
16060
16858
|
function processAISDKWorkflowAgentCallInput(params) {
|
|
16061
16859
|
const processed = processAISDKCallInput(params);
|
|
16062
16860
|
return {
|
|
@@ -16195,6 +16993,12 @@ function prepareAISDKEmbedInput(params, self) {
|
|
|
16195
16993
|
metadata: extractMetadataFromEmbedParams(params, self)
|
|
16196
16994
|
};
|
|
16197
16995
|
}
|
|
16996
|
+
function prepareAISDKGenerateImageInput(params, self) {
|
|
16997
|
+
return {
|
|
16998
|
+
input: processAISDKGenerateImageInput(params).input,
|
|
16999
|
+
metadata: extractMetadataFromCallParams(params, self)
|
|
17000
|
+
};
|
|
17001
|
+
}
|
|
16198
17002
|
function prepareAISDKRerankInput(params, self) {
|
|
16199
17003
|
const { documents, query } = params;
|
|
16200
17004
|
return {
|
|
@@ -17570,6 +18374,57 @@ function processAISDKOutput(output, denyOutputPaths) {
|
|
|
17570
18374
|
}
|
|
17571
18375
|
return normalizeAISDKLoggedOutput(sanitized);
|
|
17572
18376
|
}
|
|
18377
|
+
function processAISDKGenerateImageOutput(output, denyOutputPaths) {
|
|
18378
|
+
if (!output || typeof output !== "object") {
|
|
18379
|
+
return output;
|
|
18380
|
+
}
|
|
18381
|
+
const summarized = {};
|
|
18382
|
+
for (const field of [
|
|
18383
|
+
"usage",
|
|
18384
|
+
"warnings",
|
|
18385
|
+
"providerMetadata",
|
|
18386
|
+
"experimental_providerMetadata",
|
|
18387
|
+
"responses"
|
|
18388
|
+
]) {
|
|
18389
|
+
const value = safeSerializableFieldRead(output, field);
|
|
18390
|
+
if (value !== void 0 && isSerializableOutputValue(value)) {
|
|
18391
|
+
summarized[field] = value;
|
|
18392
|
+
}
|
|
18393
|
+
}
|
|
18394
|
+
const images = safeSerializableFieldRead(output, "images");
|
|
18395
|
+
const image = safeSerializableFieldRead(output, "image");
|
|
18396
|
+
const generatedFiles = Array.isArray(images) && images.length > 0 ? images : image !== void 0 ? [image] : [];
|
|
18397
|
+
const loggedOutput = normalizeAISDKLoggedOutput(
|
|
18398
|
+
omit(summarized, denyOutputPaths)
|
|
18399
|
+
);
|
|
18400
|
+
if (generatedFiles.length > 0) {
|
|
18401
|
+
loggedOutput.images = generatedFiles.map(
|
|
18402
|
+
(file, index) => convertAISDKGeneratedFileToAttachment(file, index)
|
|
18403
|
+
);
|
|
18404
|
+
}
|
|
18405
|
+
return loggedOutput;
|
|
18406
|
+
}
|
|
18407
|
+
function convertAISDKGeneratedFileToAttachment(file, index) {
|
|
18408
|
+
if (!file || typeof file !== "object") {
|
|
18409
|
+
return file;
|
|
18410
|
+
}
|
|
18411
|
+
const generatedFile = file;
|
|
18412
|
+
const generatedMediaType = safeSerializableFieldRead(
|
|
18413
|
+
generatedFile,
|
|
18414
|
+
"mediaType"
|
|
18415
|
+
);
|
|
18416
|
+
const mediaType = typeof generatedMediaType === "string" ? generatedMediaType : "application/octet-stream";
|
|
18417
|
+
const data = safeSerializableFieldRead(generatedFile, "base64") ?? safeSerializableFieldRead(generatedFile, "uint8Array");
|
|
18418
|
+
const blob = convertDataToBlob(data, mediaType);
|
|
18419
|
+
if (blob) {
|
|
18420
|
+
return new Attachment({
|
|
18421
|
+
data: blob,
|
|
18422
|
+
filename: `generated_image_${index}.${getExtensionFromMediaType(mediaType)}`,
|
|
18423
|
+
contentType: mediaType
|
|
18424
|
+
});
|
|
18425
|
+
}
|
|
18426
|
+
return file;
|
|
18427
|
+
}
|
|
17573
18428
|
function processAISDKEmbeddingOutput(output, denyOutputPaths) {
|
|
17574
18429
|
if (!output || typeof output !== "object") {
|
|
17575
18430
|
return output;
|
|
@@ -18070,118 +18925,22 @@ var claudeAgentSDKChannels = defineChannels(
|
|
|
18070
18925
|
var CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION = "__braintrust_skip_local_tool_hooks";
|
|
18071
18926
|
|
|
18072
18927
|
// src/instrumentation/plugins/claude-agent-sdk-local-tool-context.ts
|
|
18073
|
-
var
|
|
18074
|
-
|
|
18075
|
-
)
|
|
18076
|
-
|
|
18077
|
-
const maybeIsoWithAsyncLocalStorage = isomorph_default;
|
|
18078
|
-
if (typeof maybeIsoWithAsyncLocalStorage.newAsyncLocalStorage === "function") {
|
|
18079
|
-
return maybeIsoWithAsyncLocalStorage.newAsyncLocalStorage();
|
|
18080
|
-
}
|
|
18081
|
-
let currentStore;
|
|
18082
|
-
return {
|
|
18083
|
-
enterWith(store) {
|
|
18084
|
-
currentStore = store;
|
|
18085
|
-
},
|
|
18086
|
-
getStore() {
|
|
18087
|
-
return currentStore;
|
|
18088
|
-
},
|
|
18089
|
-
run(store, callback) {
|
|
18090
|
-
const previousStore = currentStore;
|
|
18091
|
-
currentStore = store;
|
|
18092
|
-
try {
|
|
18093
|
-
return callback();
|
|
18094
|
-
} finally {
|
|
18095
|
-
currentStore = previousStore;
|
|
18096
|
-
}
|
|
18097
|
-
}
|
|
18098
|
-
};
|
|
18099
|
-
}
|
|
18100
|
-
var localToolContextStore = createLocalToolContextStore();
|
|
18101
|
-
var fallbackLocalToolParentResolver;
|
|
18102
|
-
function createClaudeLocalToolContext() {
|
|
18103
|
-
return {};
|
|
18104
|
-
}
|
|
18105
|
-
function runWithClaudeLocalToolContext(callback, context) {
|
|
18106
|
-
return localToolContextStore.run(
|
|
18107
|
-
context ?? createClaudeLocalToolContext(),
|
|
18108
|
-
callback
|
|
18109
|
-
);
|
|
18928
|
+
var localToolContextStore = isomorph_default.newAsyncLocalStorage();
|
|
18929
|
+
var localToolParentResolversByToolUseId = /* @__PURE__ */ new Map();
|
|
18930
|
+
function runWithClaudeLocalToolContext(callback, resolver) {
|
|
18931
|
+
return localToolContextStore.run(resolver, callback);
|
|
18110
18932
|
}
|
|
18111
|
-
function
|
|
18112
|
-
|
|
18113
|
-
if (existing) {
|
|
18114
|
-
return existing;
|
|
18115
|
-
}
|
|
18116
|
-
const created = {};
|
|
18117
|
-
localToolContextStore.enterWith(created);
|
|
18118
|
-
return created;
|
|
18933
|
+
function registerClaudeLocalToolParentResolver(toolUseId, resolver) {
|
|
18934
|
+
localToolParentResolversByToolUseId.set(toolUseId, resolver);
|
|
18119
18935
|
}
|
|
18120
|
-
function
|
|
18121
|
-
|
|
18122
|
-
|
|
18123
|
-
|
|
18124
|
-
return;
|
|
18936
|
+
function getClaudeLocalToolParentResolver(toolUseId) {
|
|
18937
|
+
const currentResolver = localToolContextStore.getStore();
|
|
18938
|
+
if (!toolUseId) {
|
|
18939
|
+
return currentResolver;
|
|
18125
18940
|
}
|
|
18126
|
-
|
|
18127
|
-
|
|
18128
|
-
|
|
18129
|
-
return localToolContextStore.getStore()?.resolveLocalToolParent ?? fallbackLocalToolParentResolver;
|
|
18130
|
-
}
|
|
18131
|
-
function isAsyncIterable3(value) {
|
|
18132
|
-
return value !== null && typeof value === "object" && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
|
|
18133
|
-
}
|
|
18134
|
-
function bindClaudeLocalToolContextToAsyncIterable(result, localToolContext) {
|
|
18135
|
-
if (!isAsyncIterable3(result) || Object.isFrozen(result) || Object.isSealed(result)) {
|
|
18136
|
-
return result;
|
|
18137
|
-
}
|
|
18138
|
-
const stream = result;
|
|
18139
|
-
const originalAsyncIterator = stream[Symbol.asyncIterator];
|
|
18140
|
-
if (originalAsyncIterator[LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED]) {
|
|
18141
|
-
return result;
|
|
18142
|
-
}
|
|
18143
|
-
const patchedAsyncIterator = function() {
|
|
18144
|
-
return runWithClaudeLocalToolContext(() => {
|
|
18145
|
-
const iterator = Reflect.apply(originalAsyncIterator, this, []);
|
|
18146
|
-
if (!iterator || typeof iterator !== "object") {
|
|
18147
|
-
return iterator;
|
|
18148
|
-
}
|
|
18149
|
-
const patchMethod = (methodName) => {
|
|
18150
|
-
const originalMethod = Reflect.get(iterator, methodName);
|
|
18151
|
-
if (typeof originalMethod !== "function") {
|
|
18152
|
-
return;
|
|
18153
|
-
}
|
|
18154
|
-
Reflect.set(
|
|
18155
|
-
iterator,
|
|
18156
|
-
methodName,
|
|
18157
|
-
(...args) => runWithClaudeLocalToolContext(
|
|
18158
|
-
() => Reflect.apply(
|
|
18159
|
-
originalMethod,
|
|
18160
|
-
iterator,
|
|
18161
|
-
args
|
|
18162
|
-
),
|
|
18163
|
-
localToolContext
|
|
18164
|
-
)
|
|
18165
|
-
);
|
|
18166
|
-
};
|
|
18167
|
-
patchMethod("next");
|
|
18168
|
-
patchMethod("return");
|
|
18169
|
-
patchMethod("throw");
|
|
18170
|
-
return iterator;
|
|
18171
|
-
}, localToolContext);
|
|
18172
|
-
};
|
|
18173
|
-
Object.defineProperty(
|
|
18174
|
-
patchedAsyncIterator,
|
|
18175
|
-
LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED,
|
|
18176
|
-
{
|
|
18177
|
-
configurable: false,
|
|
18178
|
-
enumerable: false,
|
|
18179
|
-
value: true,
|
|
18180
|
-
writable: false
|
|
18181
|
-
}
|
|
18182
|
-
);
|
|
18183
|
-
Reflect.set(stream, Symbol.asyncIterator, patchedAsyncIterator);
|
|
18184
|
-
return result;
|
|
18941
|
+
const registeredResolver = localToolParentResolversByToolUseId.get(toolUseId);
|
|
18942
|
+
localToolParentResolversByToolUseId.delete(toolUseId);
|
|
18943
|
+
return currentResolver ?? registeredResolver;
|
|
18185
18944
|
}
|
|
18186
18945
|
|
|
18187
18946
|
// src/instrumentation/plugins/claude-agent-sdk-local-tool-spans.ts
|
|
@@ -18207,7 +18966,7 @@ function wrapLocalClaudeToolHandler(handler, getMetadata) {
|
|
|
18207
18966
|
const metadata = getMetadata();
|
|
18208
18967
|
const rawToolName = metadata.serverName ? `mcp__${metadata.serverName}__${metadata.toolName}` : metadata.toolName;
|
|
18209
18968
|
const toolUseId = getToolUseIdFromExtra(handlerArgs[1]);
|
|
18210
|
-
const localToolParentResolver = getClaudeLocalToolParentResolver();
|
|
18969
|
+
const localToolParentResolver = getClaudeLocalToolParentResolver(toolUseId);
|
|
18211
18970
|
const spanName = metadata.serverName ? `tool: ${metadata.serverName}/${metadata.toolName}` : `tool: ${metadata.toolName}`;
|
|
18212
18971
|
const runWithResolvedParent = async () => {
|
|
18213
18972
|
const parent = toolUseId && localToolParentResolver ? await localToolParentResolver(toolUseId).catch(() => void 0) : void 0;
|
|
@@ -18734,6 +19493,7 @@ function createToolTracingHooks(resolveParentSpan, taskIdToToolUseId, toolUseToP
|
|
|
18734
19493
|
}
|
|
18735
19494
|
}
|
|
18736
19495
|
if (skipLocalToolHooks && (isLocalToolUse(input.tool_name, mcpServers) || localToolHookNames.has(input.tool_name))) {
|
|
19496
|
+
registerClaudeLocalToolParentResolver(toolUseID, resolveParentSpan);
|
|
18737
19497
|
return {};
|
|
18738
19498
|
}
|
|
18739
19499
|
const parsed = parseToolName(input.tool_name);
|
|
@@ -19444,7 +20204,7 @@ async function finalizeQuerySpan(state) {
|
|
|
19444
20204
|
}
|
|
19445
20205
|
var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
19446
20206
|
onEnable() {
|
|
19447
|
-
this.
|
|
20207
|
+
this.interceptQuery();
|
|
19448
20208
|
}
|
|
19449
20209
|
onDisable() {
|
|
19450
20210
|
for (const unsubscribe of this.unsubscribers) {
|
|
@@ -19452,211 +20212,218 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
19452
20212
|
}
|
|
19453
20213
|
this.unsubscribers = [];
|
|
19454
20214
|
}
|
|
19455
|
-
|
|
19456
|
-
const
|
|
19457
|
-
|
|
19458
|
-
|
|
19459
|
-
|
|
19460
|
-
|
|
19461
|
-
|
|
19462
|
-
|
|
19463
|
-
|
|
19464
|
-
|
|
19465
|
-
|
|
19466
|
-
|
|
19467
|
-
|
|
19468
|
-
|
|
19469
|
-
|
|
19470
|
-
|
|
19471
|
-
|
|
19472
|
-
|
|
19473
|
-
|
|
19474
|
-
|
|
19475
|
-
try {
|
|
19476
|
-
for await (const message of promptStream) {
|
|
19477
|
-
capturedPromptMessages.push(message);
|
|
19478
|
-
yield message;
|
|
19479
|
-
}
|
|
19480
|
-
} finally {
|
|
19481
|
-
resolvePromptDone?.();
|
|
20215
|
+
interceptQuery() {
|
|
20216
|
+
const startQuery = (params) => {
|
|
20217
|
+
const originalPrompt = params.prompt;
|
|
20218
|
+
const options = params.options ?? {};
|
|
20219
|
+
const promptIsAsyncIterable = isAsyncIterable(originalPrompt);
|
|
20220
|
+
let promptStarted = false;
|
|
20221
|
+
let capturedPromptMessages;
|
|
20222
|
+
let resolvePromptDone;
|
|
20223
|
+
const promptDone = new Promise((resolve) => {
|
|
20224
|
+
resolvePromptDone = resolve;
|
|
20225
|
+
});
|
|
20226
|
+
if (promptIsAsyncIterable) {
|
|
20227
|
+
capturedPromptMessages = [];
|
|
20228
|
+
const promptStream = originalPrompt;
|
|
20229
|
+
params.prompt = (async function* () {
|
|
20230
|
+
promptStarted = true;
|
|
20231
|
+
try {
|
|
20232
|
+
for await (const message of promptStream) {
|
|
20233
|
+
capturedPromptMessages.push(message);
|
|
20234
|
+
yield message;
|
|
19482
20235
|
}
|
|
19483
|
-
}
|
|
19484
|
-
|
|
19485
|
-
const span = startSpan(
|
|
19486
|
-
withSpanInstrumentationName(
|
|
19487
|
-
{
|
|
19488
|
-
name: "Claude Agent",
|
|
19489
|
-
spanAttributes: {
|
|
19490
|
-
type: "task" /* TASK */
|
|
19491
|
-
}
|
|
19492
|
-
},
|
|
19493
|
-
INSTRUMENTATION_NAMES.CLAUDE_AGENT_SDK
|
|
19494
|
-
)
|
|
19495
|
-
);
|
|
19496
|
-
const startTime = getCurrentUnixTimestamp();
|
|
19497
|
-
try {
|
|
19498
|
-
span.log({
|
|
19499
|
-
input: typeof originalPrompt === "string" ? originalPrompt : promptIsAsyncIterable ? void 0 : originalPrompt !== void 0 ? String(originalPrompt) : void 0,
|
|
19500
|
-
metadata: filterSerializableOptions(options)
|
|
19501
|
-
});
|
|
19502
|
-
} catch (error) {
|
|
19503
|
-
console.error("Error extracting input for Claude Agent SDK:", error);
|
|
19504
|
-
}
|
|
19505
|
-
const activeToolSpans = /* @__PURE__ */ new Map();
|
|
19506
|
-
const activeLlmSpansByParentToolUse = /* @__PURE__ */ new Map();
|
|
19507
|
-
const conversationHistoryByParentKey = /* @__PURE__ */ new Map();
|
|
19508
|
-
const subAgentSpans = /* @__PURE__ */ new Map();
|
|
19509
|
-
const endedSubAgentSpans = /* @__PURE__ */ new Set();
|
|
19510
|
-
const toolUseToParent = /* @__PURE__ */ new Map();
|
|
19511
|
-
const latestLlmParentBySubAgentToolUse = /* @__PURE__ */ new Map();
|
|
19512
|
-
const latestRootLlmParentRef = {
|
|
19513
|
-
value: void 0
|
|
19514
|
-
};
|
|
19515
|
-
const subAgentDetailsByToolUseId = /* @__PURE__ */ new Map();
|
|
19516
|
-
const taskIdToToolUseId = /* @__PURE__ */ new Map();
|
|
19517
|
-
const promptMessagesByParentKey = /* @__PURE__ */ new Map();
|
|
19518
|
-
const promptSourcePriorityByParentKey = /* @__PURE__ */ new Map();
|
|
19519
|
-
const localToolContext = createClaudeLocalToolContext();
|
|
19520
|
-
const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
|
|
19521
|
-
const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
|
|
19522
|
-
const resolveToolUseParentSpan = async (toolUseID, context) => {
|
|
19523
|
-
const trackedParentToolUseId = toolUseToParent.get(toolUseID);
|
|
19524
|
-
const parentToolUseId = trackedParentToolUseId ?? (context?.agentId ? taskIdToToolUseId.get(context.agentId) ?? null : null);
|
|
19525
|
-
const parentKey = llmParentKey(parentToolUseId);
|
|
19526
|
-
const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
|
|
19527
|
-
const latestLlmParent = parentToolUseId ? latestLlmParentBySubAgentToolUse.get(parentToolUseId) : latestRootLlmParentRef.value;
|
|
19528
|
-
if (!activeLlmSpan && !latestLlmParent) {
|
|
19529
|
-
await ensureActiveLlmSpanForParentToolUse(
|
|
19530
|
-
span,
|
|
19531
|
-
activeLlmSpansByParentToolUse,
|
|
19532
|
-
subAgentDetailsByToolUseId,
|
|
19533
|
-
activeToolSpans,
|
|
19534
|
-
subAgentSpans,
|
|
19535
|
-
parentToolUseId,
|
|
19536
|
-
getCurrentUnixTimestamp()
|
|
19537
|
-
);
|
|
19538
|
-
}
|
|
19539
|
-
if (parentToolUseId) {
|
|
19540
|
-
const subAgentSpan = await ensureSubAgentSpan(
|
|
19541
|
-
subAgentDetailsByToolUseId,
|
|
19542
|
-
span,
|
|
19543
|
-
activeToolSpans,
|
|
19544
|
-
subAgentSpans,
|
|
19545
|
-
parentToolUseId
|
|
19546
|
-
);
|
|
19547
|
-
return subAgentSpan.export();
|
|
20236
|
+
} finally {
|
|
20237
|
+
resolvePromptDone?.();
|
|
19548
20238
|
}
|
|
19549
|
-
|
|
19550
|
-
|
|
19551
|
-
|
|
19552
|
-
|
|
19553
|
-
|
|
19554
|
-
|
|
19555
|
-
|
|
19556
|
-
|
|
19557
|
-
|
|
19558
|
-
|
|
19559
|
-
|
|
19560
|
-
|
|
19561
|
-
|
|
19562
|
-
|
|
19563
|
-
|
|
19564
|
-
|
|
19565
|
-
|
|
19566
|
-
|
|
19567
|
-
spans.set(event, {
|
|
19568
|
-
activeLlmSpansByParentToolUse,
|
|
19569
|
-
activePartialMessageIdByParentKey: /* @__PURE__ */ new Map(),
|
|
19570
|
-
activeToolSpans,
|
|
19571
|
-
conversationHistoryByParentKey,
|
|
19572
|
-
capturedPromptMessages,
|
|
19573
|
-
currentMessageId: void 0,
|
|
19574
|
-
currentMessageStartTime: startTime,
|
|
19575
|
-
currentMessages: [],
|
|
19576
|
-
endedSubAgentSpans,
|
|
19577
|
-
finalOutputUsageMessageIds: /* @__PURE__ */ new Set(),
|
|
19578
|
-
finalResults: [],
|
|
19579
|
-
options: optionsWithHooks,
|
|
19580
|
-
originalPrompt,
|
|
19581
|
-
processing: Promise.resolve(),
|
|
19582
|
-
promptDone,
|
|
19583
|
-
promptMessagesByParentKey,
|
|
19584
|
-
promptStarted: () => promptStarted,
|
|
19585
|
-
promptSourcePriorityByParentKey,
|
|
19586
|
-
span,
|
|
19587
|
-
subAgentDetailsByToolUseId,
|
|
19588
|
-
subAgentSpans,
|
|
19589
|
-
taskIdToToolUseId,
|
|
19590
|
-
latestLlmParentBySubAgentToolUse,
|
|
19591
|
-
latestRootLlmParentRef,
|
|
19592
|
-
toolUseToParent,
|
|
19593
|
-
usageByMessageId: /* @__PURE__ */ new Map(),
|
|
19594
|
-
localToolContext
|
|
20239
|
+
})();
|
|
20240
|
+
}
|
|
20241
|
+
const span = startSpan(
|
|
20242
|
+
withSpanInstrumentationName(
|
|
20243
|
+
{
|
|
20244
|
+
name: "Claude Agent",
|
|
20245
|
+
spanAttributes: {
|
|
20246
|
+
type: "task" /* TASK */
|
|
20247
|
+
}
|
|
20248
|
+
},
|
|
20249
|
+
INSTRUMENTATION_NAMES.CLAUDE_AGENT_SDK
|
|
20250
|
+
)
|
|
20251
|
+
);
|
|
20252
|
+
const startTime = getCurrentUnixTimestamp();
|
|
20253
|
+
try {
|
|
20254
|
+
span.log({
|
|
20255
|
+
input: typeof originalPrompt === "string" ? originalPrompt : promptIsAsyncIterable ? void 0 : originalPrompt !== void 0 ? String(originalPrompt) : void 0,
|
|
20256
|
+
metadata: filterSerializableOptions(options)
|
|
19595
20257
|
});
|
|
19596
|
-
}
|
|
19597
|
-
|
|
19598
|
-
|
|
19599
|
-
|
|
19600
|
-
|
|
19601
|
-
|
|
19602
|
-
|
|
19603
|
-
|
|
19604
|
-
|
|
19605
|
-
|
|
19606
|
-
|
|
19607
|
-
|
|
19608
|
-
|
|
19609
|
-
|
|
19610
|
-
|
|
19611
|
-
|
|
19612
|
-
|
|
19613
|
-
|
|
19614
|
-
|
|
19615
|
-
|
|
19616
|
-
|
|
19617
|
-
|
|
19618
|
-
|
|
19619
|
-
|
|
19620
|
-
|
|
19621
|
-
|
|
19622
|
-
|
|
19623
|
-
|
|
19624
|
-
|
|
19625
|
-
|
|
19626
|
-
|
|
19627
|
-
|
|
19628
|
-
|
|
19629
|
-
|
|
19630
|
-
|
|
19631
|
-
})
|
|
19632
|
-
});
|
|
19633
|
-
return;
|
|
19634
|
-
}
|
|
19635
|
-
try {
|
|
19636
|
-
state.span.log({ output: eventResult });
|
|
19637
|
-
} catch (error) {
|
|
19638
|
-
console.error("Error extracting output for Claude Agent SDK:", error);
|
|
19639
|
-
} finally {
|
|
19640
|
-
state.span.end();
|
|
19641
|
-
spans.delete(event);
|
|
20258
|
+
} catch (error) {
|
|
20259
|
+
console.error("Error extracting input for Claude Agent SDK:", error);
|
|
20260
|
+
}
|
|
20261
|
+
const activeToolSpans = /* @__PURE__ */ new Map();
|
|
20262
|
+
const activeLlmSpansByParentToolUse = /* @__PURE__ */ new Map();
|
|
20263
|
+
const conversationHistoryByParentKey = /* @__PURE__ */ new Map();
|
|
20264
|
+
const subAgentSpans = /* @__PURE__ */ new Map();
|
|
20265
|
+
const endedSubAgentSpans = /* @__PURE__ */ new Set();
|
|
20266
|
+
const toolUseToParent = /* @__PURE__ */ new Map();
|
|
20267
|
+
const latestLlmParentBySubAgentToolUse = /* @__PURE__ */ new Map();
|
|
20268
|
+
const latestRootLlmParentRef = {
|
|
20269
|
+
value: void 0
|
|
20270
|
+
};
|
|
20271
|
+
const subAgentDetailsByToolUseId = /* @__PURE__ */ new Map();
|
|
20272
|
+
const taskIdToToolUseId = /* @__PURE__ */ new Map();
|
|
20273
|
+
const promptMessagesByParentKey = /* @__PURE__ */ new Map();
|
|
20274
|
+
const promptSourcePriorityByParentKey = /* @__PURE__ */ new Map();
|
|
20275
|
+
const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
|
|
20276
|
+
const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
|
|
20277
|
+
const resolveToolUseParentSpan = async (toolUseID, context) => {
|
|
20278
|
+
const trackedParentToolUseId = toolUseToParent.get(toolUseID);
|
|
20279
|
+
const parentToolUseId = trackedParentToolUseId ?? (context?.agentId ? taskIdToToolUseId.get(context.agentId) ?? null : null);
|
|
20280
|
+
const parentKey = llmParentKey(parentToolUseId);
|
|
20281
|
+
const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
|
|
20282
|
+
const latestLlmParent = parentToolUseId ? latestLlmParentBySubAgentToolUse.get(parentToolUseId) : latestRootLlmParentRef.value;
|
|
20283
|
+
if (!activeLlmSpan && !latestLlmParent) {
|
|
20284
|
+
await ensureActiveLlmSpanForParentToolUse(
|
|
20285
|
+
span,
|
|
20286
|
+
activeLlmSpansByParentToolUse,
|
|
20287
|
+
subAgentDetailsByToolUseId,
|
|
20288
|
+
activeToolSpans,
|
|
20289
|
+
subAgentSpans,
|
|
20290
|
+
parentToolUseId,
|
|
20291
|
+
getCurrentUnixTimestamp()
|
|
20292
|
+
);
|
|
19642
20293
|
}
|
|
19643
|
-
|
|
19644
|
-
|
|
19645
|
-
|
|
19646
|
-
|
|
19647
|
-
|
|
20294
|
+
if (parentToolUseId) {
|
|
20295
|
+
const subAgentSpan = await ensureSubAgentSpan(
|
|
20296
|
+
subAgentDetailsByToolUseId,
|
|
20297
|
+
span,
|
|
20298
|
+
activeToolSpans,
|
|
20299
|
+
subAgentSpans,
|
|
20300
|
+
parentToolUseId
|
|
20301
|
+
);
|
|
20302
|
+
return subAgentSpan.export();
|
|
19648
20303
|
}
|
|
19649
|
-
|
|
19650
|
-
|
|
20304
|
+
return span.export();
|
|
20305
|
+
};
|
|
20306
|
+
const optionsWithHooks = injectTracingHooks(
|
|
20307
|
+
options,
|
|
20308
|
+
resolveToolUseParentSpan,
|
|
20309
|
+
taskIdToToolUseId,
|
|
20310
|
+
toolUseToParent,
|
|
20311
|
+
activeToolSpans,
|
|
20312
|
+
localToolHookNames,
|
|
20313
|
+
skipLocalToolHooks,
|
|
20314
|
+
subAgentDetailsByToolUseId,
|
|
20315
|
+
subAgentSpans,
|
|
20316
|
+
endedSubAgentSpans
|
|
20317
|
+
);
|
|
20318
|
+
params.options = optionsWithHooks;
|
|
20319
|
+
return {
|
|
20320
|
+
activeLlmSpansByParentToolUse,
|
|
20321
|
+
activePartialMessageIdByParentKey: /* @__PURE__ */ new Map(),
|
|
20322
|
+
activeToolSpans,
|
|
20323
|
+
conversationHistoryByParentKey,
|
|
20324
|
+
capturedPromptMessages,
|
|
20325
|
+
currentMessageId: void 0,
|
|
20326
|
+
currentMessageStartTime: startTime,
|
|
20327
|
+
currentMessages: [],
|
|
20328
|
+
endedSubAgentSpans,
|
|
20329
|
+
finalOutputUsageMessageIds: /* @__PURE__ */ new Set(),
|
|
20330
|
+
finalResults: [],
|
|
20331
|
+
options: optionsWithHooks,
|
|
20332
|
+
originalPrompt,
|
|
20333
|
+
processing: Promise.resolve(),
|
|
20334
|
+
promptDone,
|
|
20335
|
+
promptMessagesByParentKey,
|
|
20336
|
+
promptStarted: () => promptStarted,
|
|
20337
|
+
promptSourcePriorityByParentKey,
|
|
20338
|
+
span,
|
|
20339
|
+
subAgentDetailsByToolUseId,
|
|
20340
|
+
subAgentSpans,
|
|
20341
|
+
taskIdToToolUseId,
|
|
20342
|
+
latestLlmParentBySubAgentToolUse,
|
|
20343
|
+
latestRootLlmParentRef,
|
|
20344
|
+
toolUseToParent,
|
|
20345
|
+
usageByMessageId: /* @__PURE__ */ new Map(),
|
|
20346
|
+
localToolParentResolver: resolveToolUseParentSpan
|
|
20347
|
+
};
|
|
20348
|
+
};
|
|
20349
|
+
const finishQuery = (state, result) => {
|
|
20350
|
+
if (isAsyncIterable(result)) {
|
|
20351
|
+
patchStreamIfNeeded(result, {
|
|
20352
|
+
aroundNext: (callback) => runWithClaudeLocalToolContext(
|
|
20353
|
+
callback,
|
|
20354
|
+
state.localToolParentResolver
|
|
20355
|
+
),
|
|
20356
|
+
onChunk: (message) => {
|
|
20357
|
+
maybeTrackToolUseContext(state, message);
|
|
20358
|
+
state.processing = state.processing.then(() => handleStreamMessage(state, message)).catch((error) => {
|
|
20359
|
+
console.error(
|
|
20360
|
+
"Error processing Claude Agent SDK stream chunk:",
|
|
20361
|
+
error
|
|
20362
|
+
);
|
|
20363
|
+
});
|
|
20364
|
+
},
|
|
20365
|
+
onComplete: () => state.processing.then(() => finalizeQuerySpan(state)),
|
|
20366
|
+
onError: (error) => state.processing.then(() => {
|
|
20367
|
+
state.span.log({ error: error.message });
|
|
20368
|
+
}).then(() => finalizeQuerySpan(state))
|
|
19651
20369
|
});
|
|
20370
|
+
return;
|
|
20371
|
+
}
|
|
20372
|
+
try {
|
|
20373
|
+
state.span.log({ output: result });
|
|
20374
|
+
} catch (error) {
|
|
20375
|
+
console.error("Error extracting output for Claude Agent SDK:", error);
|
|
20376
|
+
} finally {
|
|
19652
20377
|
state.span.end();
|
|
19653
|
-
spans.delete(event);
|
|
19654
20378
|
}
|
|
19655
20379
|
};
|
|
19656
|
-
|
|
19657
|
-
|
|
19658
|
-
|
|
19659
|
-
|
|
20380
|
+
this.unsubscribers.push(
|
|
20381
|
+
claudeAgentSDKChannels.query.intercept((target, thisArg, args) => {
|
|
20382
|
+
let state;
|
|
20383
|
+
try {
|
|
20384
|
+
args[0] ??= {};
|
|
20385
|
+
state = startQuery(args[0]);
|
|
20386
|
+
} catch (error) {
|
|
20387
|
+
debugLogger.error(
|
|
20388
|
+
"Error starting Claude Agent SDK instrumentation:",
|
|
20389
|
+
error
|
|
20390
|
+
);
|
|
20391
|
+
}
|
|
20392
|
+
const invokeTarget = () => Reflect.apply(target, thisArg, args);
|
|
20393
|
+
try {
|
|
20394
|
+
const result = state ? runWithClaudeLocalToolContext(
|
|
20395
|
+
invokeTarget,
|
|
20396
|
+
state.localToolParentResolver
|
|
20397
|
+
) : invokeTarget();
|
|
20398
|
+
if (state) {
|
|
20399
|
+
try {
|
|
20400
|
+
finishQuery(state, result);
|
|
20401
|
+
} catch (error) {
|
|
20402
|
+
debugLogger.error(
|
|
20403
|
+
"Error finalizing Claude Agent SDK instrumentation:",
|
|
20404
|
+
error
|
|
20405
|
+
);
|
|
20406
|
+
}
|
|
20407
|
+
}
|
|
20408
|
+
return result;
|
|
20409
|
+
} catch (error) {
|
|
20410
|
+
if (state) {
|
|
20411
|
+
try {
|
|
20412
|
+
state.span.log({
|
|
20413
|
+
error: error instanceof Error ? error.message : String(error)
|
|
20414
|
+
});
|
|
20415
|
+
state.span.end();
|
|
20416
|
+
} catch (instrumentationError) {
|
|
20417
|
+
debugLogger.error(
|
|
20418
|
+
"Error handling Claude Agent SDK instrumentation failure:",
|
|
20419
|
+
instrumentationError
|
|
20420
|
+
);
|
|
20421
|
+
}
|
|
20422
|
+
}
|
|
20423
|
+
throw error;
|
|
20424
|
+
}
|
|
20425
|
+
})
|
|
20426
|
+
);
|
|
19660
20427
|
}
|
|
19661
20428
|
};
|
|
19662
20429
|
|
|
@@ -23770,7 +24537,7 @@ function patchOpenRouterCallModelResult(args) {
|
|
|
23770
24537
|
span,
|
|
23771
24538
|
() => originalMethod.apply(resultLike, args2)
|
|
23772
24539
|
);
|
|
23773
|
-
if (!
|
|
24540
|
+
if (!isAsyncIterable3(stream)) {
|
|
23774
24541
|
return stream;
|
|
23775
24542
|
}
|
|
23776
24543
|
return wrapAsyncIterableWithSpan({
|
|
@@ -23965,7 +24732,7 @@ function wrapAsyncIterableWithSpan(args) {
|
|
|
23965
24732
|
}
|
|
23966
24733
|
};
|
|
23967
24734
|
}
|
|
23968
|
-
function
|
|
24735
|
+
function isAsyncIterable3(value) {
|
|
23969
24736
|
return !!value && (typeof value === "object" || typeof value === "function") && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
|
|
23970
24737
|
}
|
|
23971
24738
|
function normalizeError(error) {
|
|
@@ -24843,7 +25610,7 @@ function patchOpenRouterCallModelResult2(args) {
|
|
|
24843
25610
|
span,
|
|
24844
25611
|
() => originalMethod.apply(resultLike, args2)
|
|
24845
25612
|
);
|
|
24846
|
-
if (!
|
|
25613
|
+
if (!isAsyncIterable4(stream)) {
|
|
24847
25614
|
return stream;
|
|
24848
25615
|
}
|
|
24849
25616
|
return wrapAsyncIterableWithSpan2({
|
|
@@ -25038,7 +25805,7 @@ function wrapAsyncIterableWithSpan2(args) {
|
|
|
25038
25805
|
}
|
|
25039
25806
|
};
|
|
25040
25807
|
}
|
|
25041
|
-
function
|
|
25808
|
+
function isAsyncIterable4(value) {
|
|
25042
25809
|
return !!value && (typeof value === "object" || typeof value === "function") && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
|
|
25043
25810
|
}
|
|
25044
25811
|
function normalizeError2(error) {
|
|
@@ -31030,12 +31797,14 @@ function getMetricsFromResponse(response) {
|
|
|
31030
31797
|
continue;
|
|
31031
31798
|
}
|
|
31032
31799
|
const inputTokenDetails = usageMetadata.input_token_details;
|
|
31800
|
+
const outputTokenDetails = usageMetadata.output_token_details;
|
|
31033
31801
|
return normalizeTokenMetrics({
|
|
31034
31802
|
total_tokens: usageMetadata.total_tokens,
|
|
31035
31803
|
prompt_tokens: usageMetadata.input_tokens,
|
|
31036
31804
|
completion_tokens: usageMetadata.output_tokens,
|
|
31037
31805
|
prompt_cache_creation_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_creation : void 0,
|
|
31038
|
-
prompt_cached_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_read : void 0
|
|
31806
|
+
prompt_cached_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_read : void 0,
|
|
31807
|
+
completion_reasoning_tokens: isRecord(outputTokenDetails) ? outputTokenDetails.reasoning : void 0
|
|
31039
31808
|
});
|
|
31040
31809
|
}
|
|
31041
31810
|
const llmOutput = response.llmOutput || {};
|
|
@@ -31622,6 +32391,9 @@ var piCodingAgentChannels = defineChannels(
|
|
|
31622
32391
|
// src/instrumentation/plugins/pi-coding-agent-plugin.ts
|
|
31623
32392
|
var piAgentPatchStates = /* @__PURE__ */ new WeakMap();
|
|
31624
32393
|
var piAgentEventSubscriptions = /* @__PURE__ */ new WeakSet();
|
|
32394
|
+
var PI_TOOL_EXECUTE_WRAPPED = /* @__PURE__ */ Symbol.for(
|
|
32395
|
+
"braintrust.pi_coding_agent.tool_execute_wrapped"
|
|
32396
|
+
);
|
|
31625
32397
|
var piPromptContextStore;
|
|
31626
32398
|
var PiCodingAgentPlugin = class extends BasePlugin {
|
|
31627
32399
|
activePromptStates = /* @__PURE__ */ new Set();
|
|
@@ -31702,6 +32474,7 @@ function startPiPromptRun(event, onFinalize) {
|
|
|
31702
32474
|
return void 0;
|
|
31703
32475
|
}
|
|
31704
32476
|
installPiAgentInstrumentation(agent);
|
|
32477
|
+
wrapPiToolExecutors(agent.state?.tools);
|
|
31705
32478
|
const metadata = {
|
|
31706
32479
|
...extractSessionMetadata(session),
|
|
31707
32480
|
...extractPromptOptionsMetadata(event.arguments[1]),
|
|
@@ -31798,6 +32571,7 @@ function makeInstrumentedStreamFn(agent, originalStreamFn) {
|
|
|
31798
32571
|
if (!state || state.agent !== agent || state.finalized) {
|
|
31799
32572
|
return invokeOriginal();
|
|
31800
32573
|
}
|
|
32574
|
+
wrapPiToolExecutors(context.tools);
|
|
31801
32575
|
const llmState = await startPiLlmSpan(state, model, context, options);
|
|
31802
32576
|
try {
|
|
31803
32577
|
const stream = await runWithAutoInstrumentationSuppressed(invokeOriginal);
|
|
@@ -31808,6 +32582,33 @@ function makeInstrumentedStreamFn(agent, originalStreamFn) {
|
|
|
31808
32582
|
}
|
|
31809
32583
|
};
|
|
31810
32584
|
}
|
|
32585
|
+
function wrapPiToolExecutors(tools) {
|
|
32586
|
+
if (!tools) {
|
|
32587
|
+
return;
|
|
32588
|
+
}
|
|
32589
|
+
for (const tool of tools) {
|
|
32590
|
+
try {
|
|
32591
|
+
const execute = tool.execute;
|
|
32592
|
+
if (typeof execute !== "function" || execute[PI_TOOL_EXECUTE_WRAPPED]) {
|
|
32593
|
+
continue;
|
|
32594
|
+
}
|
|
32595
|
+
const wrappedExecute = function(...args) {
|
|
32596
|
+
return runWithAutoInstrumentationAllowed(
|
|
32597
|
+
() => Reflect.apply(execute, this, args)
|
|
32598
|
+
);
|
|
32599
|
+
};
|
|
32600
|
+
Object.defineProperty(wrappedExecute, PI_TOOL_EXECUTE_WRAPPED, {
|
|
32601
|
+
configurable: false,
|
|
32602
|
+
enumerable: false,
|
|
32603
|
+
value: true,
|
|
32604
|
+
writable: false
|
|
32605
|
+
});
|
|
32606
|
+
tool.execute = wrappedExecute;
|
|
32607
|
+
} catch (error) {
|
|
32608
|
+
logInstrumentationError4("Pi Coding Agent tool wrapping", error);
|
|
32609
|
+
}
|
|
32610
|
+
}
|
|
32611
|
+
}
|
|
31811
32612
|
async function startPiLlmSpan(state, model, context, options) {
|
|
31812
32613
|
const metadata = {
|
|
31813
32614
|
...extractModelMetadata2(model),
|
|
@@ -31979,35 +32780,26 @@ async function startPiToolSpan(state, event) {
|
|
|
31979
32780
|
if (!event.toolCallId || state.activeToolSpans.has(event.toolCallId)) {
|
|
31980
32781
|
return;
|
|
31981
32782
|
}
|
|
31982
|
-
const restoreAutoInstrumentation = enterAutoInstrumentationAllowed();
|
|
31983
32783
|
const metadata = {
|
|
31984
32784
|
"gen_ai.tool.call.id": event.toolCallId,
|
|
31985
32785
|
"gen_ai.tool.name": event.toolName,
|
|
31986
32786
|
"pi_coding_agent.tool.name": event.toolName
|
|
31987
32787
|
};
|
|
31988
|
-
|
|
31989
|
-
|
|
31990
|
-
|
|
31991
|
-
{
|
|
31992
|
-
|
|
31993
|
-
|
|
31994
|
-
metadata
|
|
31995
|
-
},
|
|
31996
|
-
name: event.toolName || "tool",
|
|
31997
|
-
parent: await state.span.export(),
|
|
31998
|
-
spanAttributes: { type: "tool" /* TOOL */ }
|
|
32788
|
+
const span = startSpan(
|
|
32789
|
+
withSpanInstrumentationName(
|
|
32790
|
+
{
|
|
32791
|
+
event: {
|
|
32792
|
+
input: event.args,
|
|
32793
|
+
metadata
|
|
31999
32794
|
},
|
|
32000
|
-
|
|
32001
|
-
|
|
32002
|
-
|
|
32003
|
-
|
|
32004
|
-
|
|
32005
|
-
|
|
32006
|
-
|
|
32007
|
-
|
|
32008
|
-
restoreAutoInstrumentation();
|
|
32009
|
-
throw error;
|
|
32010
|
-
}
|
|
32795
|
+
name: event.toolName || "tool",
|
|
32796
|
+
parent: await state.span.export(),
|
|
32797
|
+
spanAttributes: { type: "tool" /* TOOL */ }
|
|
32798
|
+
},
|
|
32799
|
+
INSTRUMENTATION_NAMES.PI_CODING_AGENT
|
|
32800
|
+
)
|
|
32801
|
+
);
|
|
32802
|
+
state.activeToolSpans.set(event.toolCallId, { span });
|
|
32011
32803
|
}
|
|
32012
32804
|
function finishPiToolSpan(state, event) {
|
|
32013
32805
|
const toolState = state.activeToolSpans.get(event.toolCallId);
|
|
@@ -32028,11 +32820,7 @@ function finishPiToolSpan(state, event) {
|
|
|
32028
32820
|
output: event.result
|
|
32029
32821
|
});
|
|
32030
32822
|
} finally {
|
|
32031
|
-
|
|
32032
|
-
toolState.span.end();
|
|
32033
|
-
} finally {
|
|
32034
|
-
toolState.restoreAutoInstrumentation?.();
|
|
32035
|
-
}
|
|
32823
|
+
toolState.span.end();
|
|
32036
32824
|
}
|
|
32037
32825
|
}
|
|
32038
32826
|
function finishPiPromptRun(state, error) {
|
|
@@ -32082,10 +32870,10 @@ function finishPiLlmSpan(promptState, llmState, message, error) {
|
|
|
32082
32870
|
...cleanMetrics5(llmState.metrics),
|
|
32083
32871
|
...buildDurationMetrics3(llmState.startTime)
|
|
32084
32872
|
};
|
|
32085
|
-
const
|
|
32086
|
-
if (Object.keys(
|
|
32873
|
+
const usageMetrics2 = extractUsageMetrics2(message?.usage);
|
|
32874
|
+
if (Object.keys(usageMetrics2).length > 0) {
|
|
32087
32875
|
promptState.collectedLlmUsageMetrics = true;
|
|
32088
|
-
addMetrics(promptState.metrics,
|
|
32876
|
+
addMetrics(promptState.metrics, usageMetrics2);
|
|
32089
32877
|
}
|
|
32090
32878
|
try {
|
|
32091
32879
|
safeLog4(llmState.span, {
|
|
@@ -32103,14 +32891,10 @@ function finishPiLlmSpan(promptState, llmState, message, error) {
|
|
|
32103
32891
|
}
|
|
32104
32892
|
function finishOpenToolSpans(state, error) {
|
|
32105
32893
|
for (const [, toolState] of state.activeToolSpans) {
|
|
32106
|
-
|
|
32107
|
-
|
|
32108
|
-
|
|
32109
|
-
|
|
32110
|
-
toolState.span.end();
|
|
32111
|
-
} finally {
|
|
32112
|
-
toolState.restoreAutoInstrumentation?.();
|
|
32113
|
-
}
|
|
32894
|
+
safeLog4(toolState.span, {
|
|
32895
|
+
error: error ? toLoggedError(error) : "Pi tool did not complete"
|
|
32896
|
+
});
|
|
32897
|
+
toolState.span.end();
|
|
32114
32898
|
}
|
|
32115
32899
|
state.activeToolSpans.clear();
|
|
32116
32900
|
}
|
|
@@ -32429,12 +33213,12 @@ var MAX_STRANDS_STRING_ATTACHMENT_CACHE_ENTRIES = 32;
|
|
|
32429
33213
|
var StrandsAgentSDKPlugin = class extends BasePlugin {
|
|
32430
33214
|
activeChildParents = /* @__PURE__ */ new WeakMap();
|
|
32431
33215
|
onEnable() {
|
|
32432
|
-
this.
|
|
32433
|
-
this.
|
|
33216
|
+
this.interceptAgentStream();
|
|
33217
|
+
this.interceptMultiAgentStream(
|
|
32434
33218
|
strandsAgentSDKChannels.graphStream,
|
|
32435
33219
|
"Graph.stream"
|
|
32436
33220
|
);
|
|
32437
|
-
this.
|
|
33221
|
+
this.interceptMultiAgentStream(
|
|
32438
33222
|
strandsAgentSDKChannels.swarmStream,
|
|
32439
33223
|
"Swarm.stream"
|
|
32440
33224
|
);
|
|
@@ -32445,122 +33229,92 @@ var StrandsAgentSDKPlugin = class extends BasePlugin {
|
|
|
32445
33229
|
}
|
|
32446
33230
|
this.unsubscribers = [];
|
|
32447
33231
|
}
|
|
32448
|
-
|
|
32449
|
-
|
|
32450
|
-
|
|
32451
|
-
|
|
32452
|
-
|
|
32453
|
-
|
|
32454
|
-
|
|
32455
|
-
|
|
32456
|
-
|
|
32457
|
-
|
|
32458
|
-
|
|
32459
|
-
|
|
32460
|
-
|
|
32461
|
-
|
|
32462
|
-
|
|
32463
|
-
|
|
32464
|
-
const result = event.result;
|
|
32465
|
-
if (isAsyncIterable(result)) {
|
|
32466
|
-
patchStreamIfNeeded(result, {
|
|
32467
|
-
aroundNext: (callback) => runWithAutoInstrumentationSuppressed(callback),
|
|
32468
|
-
onChunk: (chunk) => handleAgentStreamEvent(state, chunk),
|
|
32469
|
-
onComplete: () => {
|
|
32470
|
-
finalizeAgentStream(state);
|
|
32471
|
-
states.delete(event);
|
|
32472
|
-
},
|
|
32473
|
-
onError: (error) => {
|
|
32474
|
-
finalizeAgentStream(state, error);
|
|
32475
|
-
states.delete(event);
|
|
32476
|
-
}
|
|
32477
|
-
});
|
|
32478
|
-
return;
|
|
32479
|
-
}
|
|
32480
|
-
finalizeAgentStream(state, void 0, result);
|
|
32481
|
-
states.delete(event);
|
|
32482
|
-
},
|
|
32483
|
-
error: (event) => {
|
|
32484
|
-
const state = states.get(event);
|
|
32485
|
-
if (!state || !event.error) {
|
|
32486
|
-
return;
|
|
32487
|
-
}
|
|
32488
|
-
finalizeAgentStream(state, event.error);
|
|
32489
|
-
states.delete(event);
|
|
32490
|
-
}
|
|
32491
|
-
};
|
|
32492
|
-
channel2.subscribe(handlers);
|
|
32493
|
-
this.unsubscribers.push(() => {
|
|
32494
|
-
unbindAutoInstrumentationSuppression?.();
|
|
32495
|
-
channel2.unsubscribe(handlers);
|
|
32496
|
-
});
|
|
33232
|
+
interceptAgentStream() {
|
|
33233
|
+
this.unsubscribers.push(
|
|
33234
|
+
strandsAgentSDKChannels.agentStream.intercept(
|
|
33235
|
+
(target, thisArg, args, additional) => instrumentStrandsStreamInvocation({
|
|
33236
|
+
finalize: finalizeAgentStream,
|
|
33237
|
+
handleChunk: handleAgentStreamEvent,
|
|
33238
|
+
invoke: () => Reflect.apply(target, thisArg, args),
|
|
33239
|
+
name: "Strands Agent SDK",
|
|
33240
|
+
start: () => startAgentStream(
|
|
33241
|
+
args[0],
|
|
33242
|
+
extractAgent(additional.agent, thisArg),
|
|
33243
|
+
this.activeChildParents
|
|
33244
|
+
)
|
|
33245
|
+
})
|
|
33246
|
+
)
|
|
33247
|
+
);
|
|
32497
33248
|
}
|
|
32498
|
-
|
|
32499
|
-
|
|
32500
|
-
|
|
32501
|
-
|
|
32502
|
-
|
|
32503
|
-
|
|
32504
|
-
|
|
32505
|
-
|
|
32506
|
-
|
|
32507
|
-
|
|
32508
|
-
|
|
32509
|
-
|
|
32510
|
-
|
|
32511
|
-
|
|
32512
|
-
|
|
32513
|
-
|
|
32514
|
-
|
|
32515
|
-
|
|
32516
|
-
|
|
32517
|
-
}
|
|
32518
|
-
|
|
32519
|
-
|
|
32520
|
-
|
|
32521
|
-
|
|
32522
|
-
|
|
32523
|
-
|
|
32524
|
-
|
|
32525
|
-
|
|
32526
|
-
|
|
32527
|
-
|
|
32528
|
-
|
|
32529
|
-
|
|
32530
|
-
|
|
32531
|
-
|
|
32532
|
-
|
|
32533
|
-
|
|
32534
|
-
|
|
32535
|
-
|
|
32536
|
-
|
|
32537
|
-
|
|
32538
|
-
|
|
32539
|
-
|
|
32540
|
-
this.activeChildParents,
|
|
32541
|
-
void 0,
|
|
32542
|
-
result
|
|
33249
|
+
interceptMultiAgentStream(channel2, operation) {
|
|
33250
|
+
this.unsubscribers.push(
|
|
33251
|
+
channel2.intercept(
|
|
33252
|
+
(target, thisArg, args, additional) => instrumentStrandsStreamInvocation({
|
|
33253
|
+
finalize: (state, error, output) => finalizeMultiAgentStream(
|
|
33254
|
+
state,
|
|
33255
|
+
this.activeChildParents,
|
|
33256
|
+
error,
|
|
33257
|
+
output
|
|
33258
|
+
),
|
|
33259
|
+
handleChunk: (state, chunk) => handleMultiAgentStreamEvent(state, chunk, this.activeChildParents),
|
|
33260
|
+
invoke: () => Reflect.apply(target, thisArg, args),
|
|
33261
|
+
name: "Strands multi-agent",
|
|
33262
|
+
start: () => startMultiAgentStream(
|
|
33263
|
+
args[0],
|
|
33264
|
+
extractOrchestrator(additional.orchestrator, thisArg),
|
|
33265
|
+
operation,
|
|
33266
|
+
this.activeChildParents
|
|
33267
|
+
)
|
|
33268
|
+
})
|
|
33269
|
+
)
|
|
33270
|
+
);
|
|
33271
|
+
}
|
|
33272
|
+
};
|
|
33273
|
+
function instrumentStrandsStreamInvocation(options) {
|
|
33274
|
+
let state;
|
|
33275
|
+
try {
|
|
33276
|
+
state = options.start();
|
|
33277
|
+
} catch (error) {
|
|
33278
|
+
debugLogger.error(`Error starting ${options.name} instrumentation:`, error);
|
|
33279
|
+
}
|
|
33280
|
+
let result;
|
|
33281
|
+
try {
|
|
33282
|
+
result = runWithAutoInstrumentationSuppressed(options.invoke);
|
|
33283
|
+
} catch (error) {
|
|
33284
|
+
if (state) {
|
|
33285
|
+
try {
|
|
33286
|
+
options.finalize(state, error);
|
|
33287
|
+
} catch (instrumentationError) {
|
|
33288
|
+
debugLogger.error(
|
|
33289
|
+
`Error handling ${options.name} instrumentation failure:`,
|
|
33290
|
+
instrumentationError
|
|
32543
33291
|
);
|
|
32544
|
-
states.delete(event);
|
|
32545
|
-
},
|
|
32546
|
-
error: (event) => {
|
|
32547
|
-
const state = states.get(event);
|
|
32548
|
-
if (!state || !event.error) {
|
|
32549
|
-
return;
|
|
32550
|
-
}
|
|
32551
|
-
finalizeMultiAgentStream(state, this.activeChildParents, event.error);
|
|
32552
|
-
states.delete(event);
|
|
32553
33292
|
}
|
|
32554
|
-
}
|
|
32555
|
-
|
|
32556
|
-
this.unsubscribers.push(() => {
|
|
32557
|
-
unbindAutoInstrumentationSuppression?.();
|
|
32558
|
-
tracingChannel.unsubscribe(handlers);
|
|
32559
|
-
});
|
|
33293
|
+
}
|
|
33294
|
+
throw error;
|
|
32560
33295
|
}
|
|
32561
|
-
|
|
32562
|
-
|
|
32563
|
-
|
|
33296
|
+
if (state) {
|
|
33297
|
+
try {
|
|
33298
|
+
if (isAsyncIterable(result)) {
|
|
33299
|
+
patchStreamIfNeeded(result, {
|
|
33300
|
+
aroundNext: (callback) => runWithAutoInstrumentationSuppressed(callback),
|
|
33301
|
+
onChunk: (chunk) => options.handleChunk(state, chunk),
|
|
33302
|
+
onComplete: () => options.finalize(state),
|
|
33303
|
+
onError: (error) => options.finalize(state, error)
|
|
33304
|
+
});
|
|
33305
|
+
} else {
|
|
33306
|
+
options.finalize(state, void 0, result);
|
|
33307
|
+
}
|
|
33308
|
+
} catch (error) {
|
|
33309
|
+
debugLogger.error(
|
|
33310
|
+
`Error finalizing ${options.name} instrumentation:`,
|
|
33311
|
+
error
|
|
33312
|
+
);
|
|
33313
|
+
}
|
|
33314
|
+
}
|
|
33315
|
+
return result;
|
|
33316
|
+
}
|
|
33317
|
+
function startAgentStream(input, agent, activeChildParents) {
|
|
32564
33318
|
const model = agent?.model;
|
|
32565
33319
|
const metadata = {
|
|
32566
33320
|
...extractAgentMetadata2(agent),
|
|
@@ -32570,17 +33324,14 @@ function startAgentStream(event, activeChildParents) {
|
|
|
32570
33324
|
};
|
|
32571
33325
|
const parentSpan = agent ? getOnlyChildParent(activeChildParents, agent) : void 0;
|
|
32572
33326
|
const attachmentCache = createStrandsAttachmentCache();
|
|
32573
|
-
const
|
|
32574
|
-
event.arguments[0],
|
|
32575
|
-
attachmentCache
|
|
32576
|
-
);
|
|
33327
|
+
const processedInput = processStrandsInputAttachments(input, attachmentCache);
|
|
32577
33328
|
const span = parentSpan ? withCurrent(
|
|
32578
33329
|
parentSpan,
|
|
32579
33330
|
() => startSpan(
|
|
32580
33331
|
withSpanInstrumentationName(
|
|
32581
33332
|
{
|
|
32582
33333
|
event: {
|
|
32583
|
-
input,
|
|
33334
|
+
input: processedInput,
|
|
32584
33335
|
metadata
|
|
32585
33336
|
},
|
|
32586
33337
|
name: formatAgentSpanName(agent),
|
|
@@ -32593,7 +33344,7 @@ function startAgentStream(event, activeChildParents) {
|
|
|
32593
33344
|
withSpanInstrumentationName(
|
|
32594
33345
|
{
|
|
32595
33346
|
event: {
|
|
32596
|
-
input,
|
|
33347
|
+
input: processedInput,
|
|
32597
33348
|
metadata
|
|
32598
33349
|
},
|
|
32599
33350
|
name: formatAgentSpanName(agent),
|
|
@@ -32611,22 +33362,21 @@ function startAgentStream(event, activeChildParents) {
|
|
|
32611
33362
|
startTime: getCurrentUnixTimestamp()
|
|
32612
33363
|
};
|
|
32613
33364
|
}
|
|
32614
|
-
function startMultiAgentStream(
|
|
32615
|
-
const orchestrator = extractOrchestrator(event);
|
|
33365
|
+
function startMultiAgentStream(input, orchestrator, operation, activeChildParents) {
|
|
32616
33366
|
const metadata = {
|
|
32617
33367
|
"strands.operation": operation,
|
|
32618
33368
|
provider: "strands",
|
|
32619
33369
|
...orchestrator?.id ? { "strands.orchestrator.id": orchestrator.id } : {}
|
|
32620
33370
|
};
|
|
32621
33371
|
const parentSpan = orchestrator ? getOnlyChildParent(activeChildParents, orchestrator) : void 0;
|
|
32622
|
-
const
|
|
33372
|
+
const processedInput = processStrandsInputAttachments(input);
|
|
32623
33373
|
const span = parentSpan ? withCurrent(
|
|
32624
33374
|
parentSpan,
|
|
32625
33375
|
() => startSpan(
|
|
32626
33376
|
withSpanInstrumentationName(
|
|
32627
33377
|
{
|
|
32628
33378
|
event: {
|
|
32629
|
-
input,
|
|
33379
|
+
input: processedInput,
|
|
32630
33380
|
metadata
|
|
32631
33381
|
},
|
|
32632
33382
|
name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
|
|
@@ -32639,7 +33389,7 @@ function startMultiAgentStream(event, operation, activeChildParents) {
|
|
|
32639
33389
|
withSpanInstrumentationName(
|
|
32640
33390
|
{
|
|
32641
33391
|
event: {
|
|
32642
|
-
input,
|
|
33392
|
+
input: processedInput,
|
|
32643
33393
|
metadata
|
|
32644
33394
|
},
|
|
32645
33395
|
name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
|
|
@@ -33010,12 +33760,12 @@ function finalizeMultiAgentStream(state, activeChildParents, error, output) {
|
|
|
33010
33760
|
});
|
|
33011
33761
|
state.span.end();
|
|
33012
33762
|
}
|
|
33013
|
-
function extractAgent(
|
|
33014
|
-
const candidate =
|
|
33763
|
+
function extractAgent(agent, self) {
|
|
33764
|
+
const candidate = agent ?? self;
|
|
33015
33765
|
return isObject(candidate) && typeof candidate.stream === "function" ? candidate : void 0;
|
|
33016
33766
|
}
|
|
33017
|
-
function extractOrchestrator(
|
|
33018
|
-
const candidate =
|
|
33767
|
+
function extractOrchestrator(orchestrator, self) {
|
|
33768
|
+
const candidate = orchestrator ?? self;
|
|
33019
33769
|
return isObject(candidate) && typeof candidate.stream === "function" ? candidate : void 0;
|
|
33020
33770
|
}
|
|
33021
33771
|
function extractAgentMetadata2(agent) {
|
|
@@ -34535,7 +35285,7 @@ function braintrustEveHook(options) {
|
|
|
34535
35285
|
}
|
|
34536
35286
|
};
|
|
34537
35287
|
}
|
|
34538
|
-
function
|
|
35288
|
+
function createLegacyEveInstrumentation(options) {
|
|
34539
35289
|
const state = options.defineState(EVE_TRACE_STATE_KEY, emptyEveTraceState);
|
|
34540
35290
|
return {
|
|
34541
35291
|
events: {
|
|
@@ -35923,8 +36673,10 @@ function capturedModelInput(modelInput) {
|
|
|
35923
36673
|
const value = [];
|
|
35924
36674
|
if (typeof instructions === "string") {
|
|
35925
36675
|
value.push({ content: instructions, role: "system" });
|
|
35926
|
-
} else if (instructions) {
|
|
36676
|
+
} else if (Array.isArray(instructions)) {
|
|
35927
36677
|
value.push(...instructions.map(capturedEveModelMessage));
|
|
36678
|
+
} else if (instructions) {
|
|
36679
|
+
value.push(capturedEveModelMessage(instructions));
|
|
35928
36680
|
}
|
|
35929
36681
|
value.push(...messages.map(capturedEveModelMessage));
|
|
35930
36682
|
try {
|
|
@@ -36168,6 +36920,464 @@ async function deterministicEveId(...parts) {
|
|
|
36168
36920
|
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
36169
36921
|
}
|
|
36170
36922
|
|
|
36923
|
+
// src/instrumentation/plugins/eve-provider.ts
|
|
36924
|
+
var MAX_EVE_PROVIDER_CACHE_ENTRIES = 1e4;
|
|
36925
|
+
function createEveInstrumentationProvider(options = {}) {
|
|
36926
|
+
const bridge = new EveProviderBridge(options.metadata);
|
|
36927
|
+
return {
|
|
36928
|
+
capture: "content",
|
|
36929
|
+
events: {
|
|
36930
|
+
"action.completed": (event, context) => bridge.handleActionTerminal(event, context),
|
|
36931
|
+
"action.failed": (event, context) => bridge.handleActionTerminal(event, context),
|
|
36932
|
+
"action.started": (event, context) => bridge.handleActionStarted(event, context),
|
|
36933
|
+
"model.call.completed": (event, context) => bridge.handleModelTerminal(event, context),
|
|
36934
|
+
"model.call.failed": (event, context) => bridge.handleModelTerminal(event, context),
|
|
36935
|
+
"model.call.started": (event, context) => bridge.handleModelStarted(event, context),
|
|
36936
|
+
"step.attempt.completed": (event) => bridge.handleStepAttemptTerminal(event),
|
|
36937
|
+
"step.attempt.failed": (event) => bridge.handleStepAttemptTerminal(event),
|
|
36938
|
+
"turn.cancelled": (event, context) => bridge.handleTurnTerminal(event, context),
|
|
36939
|
+
"turn.completed": (event, context) => bridge.handleTurnTerminal(event, context),
|
|
36940
|
+
"turn.failed": (event, context) => bridge.handleTurnTerminal(event, context),
|
|
36941
|
+
"turn.started": (event, context) => bridge.handleTurnStarted(event, context)
|
|
36942
|
+
},
|
|
36943
|
+
flush,
|
|
36944
|
+
setup: options.setup
|
|
36945
|
+
};
|
|
36946
|
+
}
|
|
36947
|
+
var EveProviderBridge = class {
|
|
36948
|
+
constructor(metadata) {
|
|
36949
|
+
this.metadata = metadata;
|
|
36950
|
+
}
|
|
36951
|
+
metadata;
|
|
36952
|
+
activeActions = /* @__PURE__ */ new Map();
|
|
36953
|
+
activeModels = /* @__PURE__ */ new Map();
|
|
36954
|
+
modelsByAttempt = /* @__PURE__ */ new Map();
|
|
36955
|
+
settledOperations = new LRUCache({
|
|
36956
|
+
max: MAX_EVE_PROVIDER_CACHE_ENTRIES
|
|
36957
|
+
});
|
|
36958
|
+
turns = new LRUCache({
|
|
36959
|
+
max: MAX_EVE_PROVIDER_CACHE_ENTRIES
|
|
36960
|
+
});
|
|
36961
|
+
async handleTurnStarted(event, context) {
|
|
36962
|
+
await this.contain("turn start", async () => {
|
|
36963
|
+
if (this.settledOperations.has(event.idempotencyKey)) {
|
|
36964
|
+
context.state.set({ skip: true });
|
|
36965
|
+
return;
|
|
36966
|
+
}
|
|
36967
|
+
const { rowId, spanId } = await generateEveIds(
|
|
36968
|
+
"turn",
|
|
36969
|
+
event.idempotencyKey
|
|
36970
|
+
);
|
|
36971
|
+
const key = turnKey3(event.sessionId, event.turnId);
|
|
36972
|
+
const stored = storedSpan(context);
|
|
36973
|
+
if (stored && "exported" in stored && stored.rootSpanId) {
|
|
36974
|
+
this.turns.set(key, { rootSpanId: stored.rootSpanId, spanId });
|
|
36975
|
+
return;
|
|
36976
|
+
}
|
|
36977
|
+
let rootSpanId = spanId;
|
|
36978
|
+
let parentSpanId;
|
|
36979
|
+
if (event.parentLineage) {
|
|
36980
|
+
const parentTurnKey = turnKey3(
|
|
36981
|
+
event.parentLineage.sessionId,
|
|
36982
|
+
event.parentLineage.turnId
|
|
36983
|
+
);
|
|
36984
|
+
const parentTurn = this.turns.get(parentTurnKey);
|
|
36985
|
+
rootSpanId = parentTurn?.rootSpanId ?? // Eve propagates the root session through every nested subagent. Use
|
|
36986
|
+
// it instead of the immediate parent session when no ancestor ran
|
|
36987
|
+
// in-process.
|
|
36988
|
+
(await generateEveIds(
|
|
36989
|
+
"turn",
|
|
36990
|
+
turnIdempotencyKey(
|
|
36991
|
+
event.rootSessionId,
|
|
36992
|
+
event.parentLineage.turnId
|
|
36993
|
+
)
|
|
36994
|
+
)).spanId;
|
|
36995
|
+
parentSpanId = (await generateEveIds(
|
|
36996
|
+
"subagent",
|
|
36997
|
+
actionIdempotencyKey(
|
|
36998
|
+
event.parentLineage.sessionId,
|
|
36999
|
+
event.parentLineage.turnId,
|
|
37000
|
+
event.parentLineage.callId
|
|
37001
|
+
)
|
|
37002
|
+
)).spanId;
|
|
37003
|
+
}
|
|
37004
|
+
const metadata = this.spanMetadata(event.sessionId);
|
|
37005
|
+
const span = await this.startSpan(
|
|
37006
|
+
context,
|
|
37007
|
+
{
|
|
37008
|
+
event: { id: rowId, metadata },
|
|
37009
|
+
name: "eve.turn",
|
|
37010
|
+
parentSpanIds: parentSpanId ? { rootSpanId, spanId: parentSpanId } : { parentSpanIds: [], rootSpanId },
|
|
37011
|
+
spanAttributes: { type: "task" /* TASK */ },
|
|
37012
|
+
spanId
|
|
37013
|
+
},
|
|
37014
|
+
rootSpanId
|
|
37015
|
+
);
|
|
37016
|
+
span?.log({ metadata });
|
|
37017
|
+
this.turns.set(key, {
|
|
37018
|
+
rootSpanId,
|
|
37019
|
+
spanId
|
|
37020
|
+
});
|
|
37021
|
+
});
|
|
37022
|
+
}
|
|
37023
|
+
async handleTurnTerminal(event, context) {
|
|
37024
|
+
await this.contain("turn terminal", async () => {
|
|
37025
|
+
if (this.settledOperations.has(event.idempotencyKey)) {
|
|
37026
|
+
context.state.set(void 0);
|
|
37027
|
+
return;
|
|
37028
|
+
}
|
|
37029
|
+
const error = event.type === "turn.failed" ? event.error : void 0;
|
|
37030
|
+
this.drainActionsForTurn(event.sessionId, event.turnId, error);
|
|
37031
|
+
const stored = storedSpan(context);
|
|
37032
|
+
if (stored && "exported" in stored) {
|
|
37033
|
+
updateSpan({
|
|
37034
|
+
exported: stored.exported,
|
|
37035
|
+
...error !== void 0 ? { error } : {},
|
|
37036
|
+
metrics: { end: Date.now() / 1e3 }
|
|
37037
|
+
});
|
|
37038
|
+
}
|
|
37039
|
+
this.settledOperations.set(event.idempotencyKey, true);
|
|
37040
|
+
context.state.set(void 0);
|
|
37041
|
+
this.turns.delete(turnKey3(event.sessionId, event.turnId));
|
|
37042
|
+
});
|
|
37043
|
+
}
|
|
37044
|
+
async handleModelStarted(event, context) {
|
|
37045
|
+
await this.contain("model start", async () => {
|
|
37046
|
+
if (this.settledOperations.has(event.idempotencyKey)) {
|
|
37047
|
+
context.state.set({ skip: true });
|
|
37048
|
+
return;
|
|
37049
|
+
}
|
|
37050
|
+
const parent = await this.parentForScope(event.scope);
|
|
37051
|
+
const { rowId, spanId } = await generateEveIds(
|
|
37052
|
+
"step",
|
|
37053
|
+
event.idempotencyKey
|
|
37054
|
+
);
|
|
37055
|
+
const input = event.input ? capturedModelInput(event.input) : void 0;
|
|
37056
|
+
const metadata = {
|
|
37057
|
+
...this.spanMetadata(event.scope.sessionId),
|
|
37058
|
+
model: event.model.modelId,
|
|
37059
|
+
provider: event.model.provider
|
|
37060
|
+
};
|
|
37061
|
+
const span = await this.startSpan(context, {
|
|
37062
|
+
event: {
|
|
37063
|
+
id: rowId,
|
|
37064
|
+
...input !== void 0 ? { input } : {},
|
|
37065
|
+
metadata
|
|
37066
|
+
},
|
|
37067
|
+
name: "eve.step",
|
|
37068
|
+
parentSpanIds: parent,
|
|
37069
|
+
spanAttributes: { type: "llm" /* LLM */ },
|
|
37070
|
+
spanId
|
|
37071
|
+
});
|
|
37072
|
+
if (!span) return;
|
|
37073
|
+
span.log({ ...input !== void 0 ? { input } : {}, metadata });
|
|
37074
|
+
this.activeModels.set(event.idempotencyKey, {
|
|
37075
|
+
span,
|
|
37076
|
+
turnKey: turnKey3(event.scope.sessionId, event.scope.turnId)
|
|
37077
|
+
});
|
|
37078
|
+
const keys = this.modelsByAttempt.get(event.scope.attemptId) ?? /* @__PURE__ */ new Set();
|
|
37079
|
+
keys.add(event.idempotencyKey);
|
|
37080
|
+
this.modelsByAttempt.set(event.scope.attemptId, keys);
|
|
37081
|
+
});
|
|
37082
|
+
}
|
|
37083
|
+
async handleModelTerminal(event, context) {
|
|
37084
|
+
await this.contain("model terminal", async () => {
|
|
37085
|
+
if (this.settledOperations.has(event.idempotencyKey)) {
|
|
37086
|
+
context.state.set(void 0);
|
|
37087
|
+
return;
|
|
37088
|
+
}
|
|
37089
|
+
const active = this.activeModels.get(event.idempotencyKey);
|
|
37090
|
+
if (active) {
|
|
37091
|
+
const span = active.span;
|
|
37092
|
+
if (event.type === "model.call.failed") {
|
|
37093
|
+
if (event.error !== void 0) span.log({ error: event.error });
|
|
37094
|
+
} else {
|
|
37095
|
+
span.log({
|
|
37096
|
+
metrics: usageMetrics(event.usage),
|
|
37097
|
+
output: modelOutput(event)
|
|
37098
|
+
});
|
|
37099
|
+
}
|
|
37100
|
+
span.end();
|
|
37101
|
+
} else {
|
|
37102
|
+
const stored = storedSpan(context);
|
|
37103
|
+
if (stored && "exported" in stored) {
|
|
37104
|
+
updateSpan({
|
|
37105
|
+
exported: stored.exported,
|
|
37106
|
+
...event.type === "model.call.failed" ? event.error !== void 0 ? { error: event.error } : {} : { output: modelOutput(event) },
|
|
37107
|
+
metrics: {
|
|
37108
|
+
...event.type === "model.call.completed" ? usageMetrics(event.usage) : {},
|
|
37109
|
+
end: Date.now() / 1e3
|
|
37110
|
+
}
|
|
37111
|
+
});
|
|
37112
|
+
}
|
|
37113
|
+
}
|
|
37114
|
+
this.settledOperations.set(event.idempotencyKey, true);
|
|
37115
|
+
this.forgetModel(event.scope.attemptId, event.idempotencyKey);
|
|
37116
|
+
context.state.set(void 0);
|
|
37117
|
+
});
|
|
37118
|
+
}
|
|
37119
|
+
async handleActionStarted(event, context) {
|
|
37120
|
+
await this.contain("action start", async () => {
|
|
37121
|
+
if (event.kind === "load-skill" || this.settledOperations.has(event.idempotencyKey)) {
|
|
37122
|
+
context.state.set({ skip: true });
|
|
37123
|
+
return;
|
|
37124
|
+
}
|
|
37125
|
+
const parent = await this.parentForScope(event.scope);
|
|
37126
|
+
const { rowId, spanId } = await generateEveIds(
|
|
37127
|
+
event.kind === "subagent-call" ? "subagent" : "tool",
|
|
37128
|
+
event.idempotencyKey
|
|
37129
|
+
);
|
|
37130
|
+
const metadata = {
|
|
37131
|
+
...this.spanMetadata(event.scope.sessionId),
|
|
37132
|
+
"eve.action_kind": event.kind
|
|
37133
|
+
};
|
|
37134
|
+
const span = await this.startSpan(context, {
|
|
37135
|
+
event: {
|
|
37136
|
+
id: rowId,
|
|
37137
|
+
...event.input !== void 0 ? { input: event.input } : {},
|
|
37138
|
+
metadata
|
|
37139
|
+
},
|
|
37140
|
+
name: event.name,
|
|
37141
|
+
parentSpanIds: parent,
|
|
37142
|
+
spanAttributes: { type: "tool" /* TOOL */ },
|
|
37143
|
+
spanId
|
|
37144
|
+
});
|
|
37145
|
+
if (!span) return;
|
|
37146
|
+
span.log({
|
|
37147
|
+
...event.input !== void 0 ? { input: event.input } : {},
|
|
37148
|
+
metadata
|
|
37149
|
+
});
|
|
37150
|
+
this.activeActions.set(event.idempotencyKey, {
|
|
37151
|
+
span,
|
|
37152
|
+
turnKey: turnKey3(event.scope.sessionId, event.scope.turnId)
|
|
37153
|
+
});
|
|
37154
|
+
});
|
|
37155
|
+
}
|
|
37156
|
+
async handleActionTerminal(event, context) {
|
|
37157
|
+
await this.contain("action terminal", async () => {
|
|
37158
|
+
if (this.settledOperations.has(event.idempotencyKey)) {
|
|
37159
|
+
context.state.set(void 0);
|
|
37160
|
+
return;
|
|
37161
|
+
}
|
|
37162
|
+
const stored = storedSpan(context);
|
|
37163
|
+
if (stored?.skip) {
|
|
37164
|
+
context.state.set(void 0);
|
|
37165
|
+
return;
|
|
37166
|
+
}
|
|
37167
|
+
const active = this.activeActions.get(event.idempotencyKey);
|
|
37168
|
+
const end = finiteTimestamp(event.acceptedAtMs) ?? Date.now();
|
|
37169
|
+
if (active) {
|
|
37170
|
+
const span = active.span;
|
|
37171
|
+
if (event.type === "action.failed") {
|
|
37172
|
+
span.log({
|
|
37173
|
+
error: event.error ?? new Error(event.errorCode ?? `Eve action ${event.outcome}`)
|
|
37174
|
+
});
|
|
37175
|
+
} else if (event.output.type === "error") {
|
|
37176
|
+
span.log({
|
|
37177
|
+
error: event.output.error ?? new Error("Eve action returned an error")
|
|
37178
|
+
});
|
|
37179
|
+
} else {
|
|
37180
|
+
span.log({ output: event.output.output });
|
|
37181
|
+
}
|
|
37182
|
+
span.end({ endTime: end / 1e3 });
|
|
37183
|
+
} else {
|
|
37184
|
+
const stored2 = storedSpan(context);
|
|
37185
|
+
if (stored2 && "exported" in stored2) {
|
|
37186
|
+
updateSpan({
|
|
37187
|
+
exported: stored2.exported,
|
|
37188
|
+
...event.type === "action.failed" ? {
|
|
37189
|
+
error: event.error ?? new Error(event.errorCode ?? `Eve action ${event.outcome}`)
|
|
37190
|
+
} : event.output.type === "error" ? {
|
|
37191
|
+
error: event.output.error ?? new Error("Eve action returned an error")
|
|
37192
|
+
} : { output: event.output.output },
|
|
37193
|
+
metrics: { end: end / 1e3 }
|
|
37194
|
+
});
|
|
37195
|
+
}
|
|
37196
|
+
}
|
|
37197
|
+
this.settledOperations.set(event.idempotencyKey, true);
|
|
37198
|
+
this.activeActions.delete(event.idempotencyKey);
|
|
37199
|
+
context.state.set(void 0);
|
|
37200
|
+
});
|
|
37201
|
+
}
|
|
37202
|
+
handleStepAttemptTerminal(event) {
|
|
37203
|
+
void this.contain("step attempt terminal", () => {
|
|
37204
|
+
const keys = this.modelsByAttempt.get(event.scope.attemptId);
|
|
37205
|
+
if (!keys) return;
|
|
37206
|
+
for (const key of keys) {
|
|
37207
|
+
const active = this.activeModels.get(key);
|
|
37208
|
+
if (!active) continue;
|
|
37209
|
+
if (event.type === "step.attempt.failed" && event.error !== void 0) {
|
|
37210
|
+
active.span.log({ error: event.error });
|
|
37211
|
+
}
|
|
37212
|
+
active.span.end();
|
|
37213
|
+
this.activeModels.delete(key);
|
|
37214
|
+
}
|
|
37215
|
+
this.modelsByAttempt.delete(event.scope.attemptId);
|
|
37216
|
+
});
|
|
37217
|
+
}
|
|
37218
|
+
async parentForScope(scope) {
|
|
37219
|
+
const key = turnKey3(scope.sessionId, scope.turnId);
|
|
37220
|
+
const known = this.turns.get(key);
|
|
37221
|
+
if (known) {
|
|
37222
|
+
return { rootSpanId: known.rootSpanId, spanId: known.spanId };
|
|
37223
|
+
}
|
|
37224
|
+
const [{ spanId }, { spanId: rootSpanId }] = await Promise.all([
|
|
37225
|
+
generateEveIds("turn", turnIdempotencyKey(scope.sessionId, scope.turnId)),
|
|
37226
|
+
generateEveIds(
|
|
37227
|
+
"turn",
|
|
37228
|
+
turnIdempotencyKey(
|
|
37229
|
+
scope.rootSessionId ?? scope.sessionId,
|
|
37230
|
+
scope.turnId
|
|
37231
|
+
)
|
|
37232
|
+
)
|
|
37233
|
+
]);
|
|
37234
|
+
return { rootSpanId, spanId };
|
|
37235
|
+
}
|
|
37236
|
+
async startSpan(context, args, rootSpanId) {
|
|
37237
|
+
const span = withCurrent(
|
|
37238
|
+
NOOP_SPAN,
|
|
37239
|
+
() => _internalStartSpanWithInitialMerge(
|
|
37240
|
+
withSpanInstrumentationName(args ?? {}, INSTRUMENTATION_NAMES.EVE)
|
|
37241
|
+
)
|
|
37242
|
+
);
|
|
37243
|
+
try {
|
|
37244
|
+
context.state.set({
|
|
37245
|
+
exported: await span.export(),
|
|
37246
|
+
...rootSpanId ? { rootSpanId } : {}
|
|
37247
|
+
});
|
|
37248
|
+
} catch (error) {
|
|
37249
|
+
debugLogger.warn("Error exporting Eve provider span:", error);
|
|
37250
|
+
}
|
|
37251
|
+
return span;
|
|
37252
|
+
}
|
|
37253
|
+
drainActionsForTurn(sessionId, turnId, error) {
|
|
37254
|
+
const key = turnKey3(sessionId, turnId);
|
|
37255
|
+
for (const [idempotencyKey, active] of this.activeActions) {
|
|
37256
|
+
if (active.turnKey !== key) continue;
|
|
37257
|
+
if (error !== void 0) active.span.log({ error });
|
|
37258
|
+
active.span.end();
|
|
37259
|
+
this.activeActions.delete(idempotencyKey);
|
|
37260
|
+
}
|
|
37261
|
+
}
|
|
37262
|
+
forgetModel(attemptId, idempotencyKey) {
|
|
37263
|
+
this.activeModels.delete(idempotencyKey);
|
|
37264
|
+
const keys = this.modelsByAttempt.get(attemptId);
|
|
37265
|
+
keys?.delete(idempotencyKey);
|
|
37266
|
+
if (keys?.size === 0) this.modelsByAttempt.delete(attemptId);
|
|
37267
|
+
}
|
|
37268
|
+
spanMetadata(sessionId) {
|
|
37269
|
+
return {
|
|
37270
|
+
...this.metadata ?? {},
|
|
37271
|
+
"eve.session_id": sessionId
|
|
37272
|
+
};
|
|
37273
|
+
}
|
|
37274
|
+
async contain(operation, fn) {
|
|
37275
|
+
try {
|
|
37276
|
+
await fn();
|
|
37277
|
+
} catch (error) {
|
|
37278
|
+
debugLogger.warn(`Error in Eve provider ${operation}:`, error);
|
|
37279
|
+
}
|
|
37280
|
+
}
|
|
37281
|
+
};
|
|
37282
|
+
function storedSpan(context) {
|
|
37283
|
+
const value = context.state.get();
|
|
37284
|
+
if (!isObject(value)) return void 0;
|
|
37285
|
+
if (value["skip"] === true) return { skip: true };
|
|
37286
|
+
return typeof value["exported"] === "string" ? {
|
|
37287
|
+
exported: value["exported"],
|
|
37288
|
+
...typeof value["rootSpanId"] === "string" && value["rootSpanId"].length > 0 ? { rootSpanId: value["rootSpanId"] } : {}
|
|
37289
|
+
} : void 0;
|
|
37290
|
+
}
|
|
37291
|
+
function modelOutput(event) {
|
|
37292
|
+
const content = event.content ?? [];
|
|
37293
|
+
let text = "";
|
|
37294
|
+
const reasoning = [];
|
|
37295
|
+
const toolCalls = [];
|
|
37296
|
+
for (const part of content) {
|
|
37297
|
+
if (part.type === "text") {
|
|
37298
|
+
text += part.text;
|
|
37299
|
+
} else if (part.type === "reasoning" && part.text.trim().length > 0) {
|
|
37300
|
+
reasoning.push({ content: part.text });
|
|
37301
|
+
} else if (part.type === "tool-call") {
|
|
37302
|
+
toolCalls.push({
|
|
37303
|
+
function: {
|
|
37304
|
+
arguments: safeJsonStringify(part.input),
|
|
37305
|
+
name: part.toolName
|
|
37306
|
+
},
|
|
37307
|
+
id: part.callId,
|
|
37308
|
+
type: "function"
|
|
37309
|
+
});
|
|
37310
|
+
}
|
|
37311
|
+
}
|
|
37312
|
+
return [
|
|
37313
|
+
{
|
|
37314
|
+
finish_reason: normalizeFinishReason2(event.finishReason),
|
|
37315
|
+
index: 0,
|
|
37316
|
+
message: {
|
|
37317
|
+
content: text || null,
|
|
37318
|
+
...reasoning.length > 0 ? { reasoning } : {},
|
|
37319
|
+
role: "assistant",
|
|
37320
|
+
...toolCalls.length > 0 ? { tool_calls: toolCalls } : {}
|
|
37321
|
+
}
|
|
37322
|
+
}
|
|
37323
|
+
];
|
|
37324
|
+
}
|
|
37325
|
+
function usageMetrics(usage) {
|
|
37326
|
+
const promptTokens = nonNegativeNumber(usage.inputTokens);
|
|
37327
|
+
const completionTokens = nonNegativeNumber(usage.outputTokens);
|
|
37328
|
+
const cachedTokens = nonNegativeNumber(
|
|
37329
|
+
usage.inputTokenDetails?.cacheReadTokens
|
|
37330
|
+
);
|
|
37331
|
+
const cacheCreationTokens = nonNegativeNumber(
|
|
37332
|
+
usage.inputTokenDetails?.cacheWriteTokens
|
|
37333
|
+
);
|
|
37334
|
+
return {
|
|
37335
|
+
...promptTokens !== void 0 ? { prompt_tokens: promptTokens } : {},
|
|
37336
|
+
...completionTokens !== void 0 ? { completion_tokens: completionTokens } : {},
|
|
37337
|
+
...promptTokens !== void 0 && completionTokens !== void 0 ? { tokens: promptTokens + completionTokens } : {},
|
|
37338
|
+
...cachedTokens !== void 0 ? { prompt_cached_tokens: cachedTokens } : {},
|
|
37339
|
+
...cacheCreationTokens !== void 0 ? { prompt_cache_creation_tokens: cacheCreationTokens } : {}
|
|
37340
|
+
};
|
|
37341
|
+
}
|
|
37342
|
+
function nonNegativeNumber(value) {
|
|
37343
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
|
|
37344
|
+
}
|
|
37345
|
+
function finiteTimestamp(value) {
|
|
37346
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
37347
|
+
}
|
|
37348
|
+
function normalizeFinishReason2(value) {
|
|
37349
|
+
if (value === "content-filter") return "content_filter";
|
|
37350
|
+
if (value === "tool-calls") return "tool_calls";
|
|
37351
|
+
return value;
|
|
37352
|
+
}
|
|
37353
|
+
function safeJsonStringify(value) {
|
|
37354
|
+
try {
|
|
37355
|
+
return JSON.stringify(value) ?? "null";
|
|
37356
|
+
} catch {
|
|
37357
|
+
return "null";
|
|
37358
|
+
}
|
|
37359
|
+
}
|
|
37360
|
+
function turnKey3(sessionId, turnId) {
|
|
37361
|
+
return `${sessionId}:${turnId}`;
|
|
37362
|
+
}
|
|
37363
|
+
function turnIdempotencyKey(sessionId, turnId) {
|
|
37364
|
+
return `turn:${sessionId}:${turnId}`;
|
|
37365
|
+
}
|
|
37366
|
+
function actionIdempotencyKey(sessionId, turnId, callId) {
|
|
37367
|
+
return `action:${sessionId}:${turnId}:${callId}`;
|
|
37368
|
+
}
|
|
37369
|
+
|
|
37370
|
+
// src/instrumentation/plugins/eve-instrumentation.ts
|
|
37371
|
+
var EVE_INSTRUMENTATION_PROVIDER = /* @__PURE__ */ Symbol.for("eve.instrumentation.provider");
|
|
37372
|
+
function braintrustEveInstrumentation(options) {
|
|
37373
|
+
const definition = "defineState" in options ? createLegacyEveInstrumentation(options) : createEveInstrumentationProvider(options);
|
|
37374
|
+
const declaration = {
|
|
37375
|
+
...definition,
|
|
37376
|
+
[EVE_INSTRUMENTATION_PROVIDER]: true
|
|
37377
|
+
};
|
|
37378
|
+
return declaration;
|
|
37379
|
+
}
|
|
37380
|
+
|
|
36171
37381
|
// src/instrumentation/config.ts
|
|
36172
37382
|
var envIntegrationAliases = {
|
|
36173
37383
|
openai: "openai",
|