braintrust 3.28.0 → 3.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dev/dist/index.d.mts +356 -7
- package/dev/dist/index.d.ts +356 -7
- package/dev/dist/index.js +2679 -1828
- package/dev/dist/index.mjs +1862 -1011
- package/dist/apply-auto-instrumentation.js +298 -265
- package/dist/apply-auto-instrumentation.mjs +85 -52
- package/dist/auto-instrumentations/bundler/esbuild.cjs +56 -6
- package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
- package/dist/auto-instrumentations/bundler/next.cjs +56 -6
- package/dist/auto-instrumentations/bundler/next.mjs +3 -3
- package/dist/auto-instrumentations/bundler/rollup.cjs +56 -6
- package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
- package/dist/auto-instrumentations/bundler/vite.cjs +56 -6
- package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
- package/dist/auto-instrumentations/bundler/webpack-loader.cjs +56 -6
- package/dist/auto-instrumentations/bundler/webpack.cjs +56 -6
- package/dist/auto-instrumentations/bundler/webpack.mjs +3 -3
- package/dist/auto-instrumentations/{chunk-26PKVUKB.mjs → chunk-LW4HDHXT.mjs} +12 -4
- package/dist/auto-instrumentations/{chunk-HD35AM3M.mjs → chunk-OXINGIEZ.mjs} +1 -1
- package/dist/auto-instrumentations/{chunk-NP7V4XB2.mjs → chunk-U64OYU4Q.mjs} +45 -3
- package/dist/auto-instrumentations/hook.mjs +967 -136
- package/dist/auto-instrumentations/index.cjs +45 -3
- package/dist/auto-instrumentations/index.mjs +1 -1
- package/dist/browser.d.mts +893 -24
- package/dist/browser.d.ts +893 -24
- package/dist/browser.js +2795 -1136
- package/dist/browser.mjs +2795 -1136
- package/dist/{chunk-BBE7SNRV.js → chunk-2XDW3UCG.js} +155 -23
- package/dist/{chunk-UPFNQCGB.mjs → chunk-BU6SM54N.mjs} +1830 -1045
- package/dist/{chunk-ZHUHZWFY.mjs → chunk-N3JKQ3D3.mjs} +152 -20
- package/dist/{chunk-OBBWQW6K.js → chunk-TWCDSYJN.js} +2890 -2105
- package/dist/cli.js +5976 -1348
- package/dist/edge-light.d.mts +1 -1
- package/dist/edge-light.d.ts +1 -1
- package/dist/edge-light.js +2795 -1136
- package/dist/edge-light.mjs +2795 -1136
- package/dist/index.d.mts +893 -24
- package/dist/index.d.ts +893 -24
- package/dist/index.js +1448 -699
- package/dist/index.mjs +848 -99
- package/dist/instrumentation/index.d.mts +563 -9
- package/dist/instrumentation/index.d.ts +563 -9
- package/dist/instrumentation/index.js +2794 -989
- package/dist/instrumentation/index.mjs +2794 -989
- package/dist/vitest-evals-reporter.js +16 -16
- package/dist/vitest-evals-reporter.mjs +2 -2
- package/dist/workerd.d.mts +1 -1
- package/dist/workerd.d.ts +1 -1
- package/dist/workerd.js +2795 -1136
- package/dist/workerd.mjs +2795 -1136
- package/package.json +1 -1
- package/util/dist/index.d.mts +42 -0
- package/util/dist/index.d.ts +42 -0
|
@@ -10,11 +10,13 @@ import {
|
|
|
10
10
|
cloudflareThinkChannels,
|
|
11
11
|
cohereChannels,
|
|
12
12
|
cursorSDKChannels,
|
|
13
|
+
debugLogger,
|
|
13
14
|
detectSpanOriginEnvironment,
|
|
14
15
|
flueChannels,
|
|
15
16
|
genkitChannels,
|
|
16
17
|
genkitCoreChannels,
|
|
17
18
|
getDefaultInstrumentationIntegrations,
|
|
19
|
+
getEnvDebugLogLevel,
|
|
18
20
|
getHuggingFaceTransformersPipelineInfo,
|
|
19
21
|
getSpanInstrumentationName,
|
|
20
22
|
gitHubCopilotChannels,
|
|
@@ -32,6 +34,7 @@ import {
|
|
|
32
34
|
langSmithChannels,
|
|
33
35
|
mergeSpanOriginContext,
|
|
34
36
|
mistralChannels,
|
|
37
|
+
normalizeDebugLogLevelOption,
|
|
35
38
|
ollamaChannels,
|
|
36
39
|
openAIAgentsCoreChannels,
|
|
37
40
|
openAIChannels,
|
|
@@ -41,130 +44,18 @@ import {
|
|
|
41
44
|
piCodingAgentChannels,
|
|
42
45
|
readDisabledInstrumentationEnvConfig,
|
|
43
46
|
registerHuggingFaceTransformersPipeline,
|
|
44
|
-
|
|
47
|
+
resetDebugLoggerForTests,
|
|
48
|
+
setDebugLogStateResolver,
|
|
49
|
+
setGlobalDebugLogLevel,
|
|
45
50
|
smithyClientChannels,
|
|
46
51
|
smithyCoreChannels,
|
|
47
52
|
strandsAgentSDKChannels,
|
|
48
53
|
voyageAIChannels,
|
|
49
54
|
withSpanInstrumentationName
|
|
50
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-N3JKQ3D3.mjs";
|
|
51
56
|
|
|
52
57
|
// src/id-gen.ts
|
|
53
58
|
import { v4 as uuidv4 } from "uuid";
|
|
54
|
-
|
|
55
|
-
// src/debug-logger.ts
|
|
56
|
-
var PREFIX = "[braintrust]";
|
|
57
|
-
var DEBUG_LOG_LEVEL_SYMBOL = /* @__PURE__ */ Symbol.for("braintrust-debug-log-level");
|
|
58
|
-
var LOG_LEVEL_PRIORITY = {
|
|
59
|
-
error: 0,
|
|
60
|
-
warn: 1,
|
|
61
|
-
info: 2,
|
|
62
|
-
debug: 3
|
|
63
|
-
};
|
|
64
|
-
var hasWarnedAboutInvalidEnvValue = false;
|
|
65
|
-
var debugLogStateResolver = void 0;
|
|
66
|
-
function warnInvalidEnvValue(value) {
|
|
67
|
-
if (hasWarnedAboutInvalidEnvValue) {
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
hasWarnedAboutInvalidEnvValue = true;
|
|
71
|
-
console.warn(
|
|
72
|
-
PREFIX,
|
|
73
|
-
`Invalid BRAINTRUST_DEBUG_LOG_LEVEL value "${value}". Expected "error", "warn", "info", or "debug".`
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
function normalizeDebugLogLevelOption(option) {
|
|
77
|
-
if (option === false) {
|
|
78
|
-
return void 0;
|
|
79
|
-
}
|
|
80
|
-
if (option === "error" || option === "warn" || option === "info" || option === "debug") {
|
|
81
|
-
return option;
|
|
82
|
-
}
|
|
83
|
-
throw new Error(
|
|
84
|
-
`Invalid debugLogLevel value "${option}". Expected false, "error", "warn", "info", or "debug".`
|
|
85
|
-
);
|
|
86
|
-
}
|
|
87
|
-
function parseDebugLogLevelEnv(value) {
|
|
88
|
-
if (!value) {
|
|
89
|
-
return void 0;
|
|
90
|
-
}
|
|
91
|
-
if (value === "error" || value === "warn" || value === "info" || value === "debug") {
|
|
92
|
-
return value;
|
|
93
|
-
}
|
|
94
|
-
warnInvalidEnvValue(value);
|
|
95
|
-
return void 0;
|
|
96
|
-
}
|
|
97
|
-
function getEnvDebugLogLevel() {
|
|
98
|
-
return parseDebugLogLevelEnv(isomorph_default.getEnv("BRAINTRUST_DEBUG_LOG_LEVEL"));
|
|
99
|
-
}
|
|
100
|
-
function setGlobalDebugLogLevel(level) {
|
|
101
|
-
globalThis[DEBUG_LOG_LEVEL_SYMBOL] = level;
|
|
102
|
-
}
|
|
103
|
-
function resetDebugLoggerForTests() {
|
|
104
|
-
hasWarnedAboutInvalidEnvValue = false;
|
|
105
|
-
setGlobalDebugLogLevel(void 0);
|
|
106
|
-
}
|
|
107
|
-
function setDebugLogStateResolver(resolver) {
|
|
108
|
-
debugLogStateResolver = resolver;
|
|
109
|
-
}
|
|
110
|
-
function resolveDebugLogLevel(state) {
|
|
111
|
-
const stateLevel = state?.getDebugLogLevel?.();
|
|
112
|
-
const hasStateOverride = state?.hasDebugLogLevelOverride?.() ?? false;
|
|
113
|
-
if (hasStateOverride) {
|
|
114
|
-
return stateLevel;
|
|
115
|
-
}
|
|
116
|
-
const globalLevel = (
|
|
117
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
118
|
-
globalThis[DEBUG_LOG_LEVEL_SYMBOL]
|
|
119
|
-
);
|
|
120
|
-
if (globalLevel !== void 0) {
|
|
121
|
-
return globalLevel === false ? void 0 : globalLevel;
|
|
122
|
-
}
|
|
123
|
-
return getEnvDebugLogLevel();
|
|
124
|
-
}
|
|
125
|
-
function emit(method, state, args) {
|
|
126
|
-
const level = resolveDebugLogLevel(state);
|
|
127
|
-
if (!level || LOG_LEVEL_PRIORITY[method] > LOG_LEVEL_PRIORITY[level]) {
|
|
128
|
-
return;
|
|
129
|
-
}
|
|
130
|
-
if (method === "info") {
|
|
131
|
-
console.log(PREFIX, ...args);
|
|
132
|
-
} else if (method === "debug") {
|
|
133
|
-
console.debug(PREFIX, ...args);
|
|
134
|
-
} else if (method === "warn") {
|
|
135
|
-
console.warn(PREFIX, ...args);
|
|
136
|
-
} else {
|
|
137
|
-
console.error(PREFIX, ...args);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
function createDebugLogger(state) {
|
|
141
|
-
const resolveState = () => state ?? debugLogStateResolver?.();
|
|
142
|
-
return {
|
|
143
|
-
info(...args) {
|
|
144
|
-
emit("info", resolveState(), args);
|
|
145
|
-
},
|
|
146
|
-
debug(...args) {
|
|
147
|
-
emit("debug", resolveState(), args);
|
|
148
|
-
},
|
|
149
|
-
warn(...args) {
|
|
150
|
-
emit("warn", resolveState(), args);
|
|
151
|
-
},
|
|
152
|
-
error(...args) {
|
|
153
|
-
emit("error", resolveState(), args);
|
|
154
|
-
}
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
var debugLogger = {
|
|
158
|
-
...createDebugLogger(),
|
|
159
|
-
forState(state) {
|
|
160
|
-
return createDebugLogger(state);
|
|
161
|
-
}
|
|
162
|
-
};
|
|
163
|
-
setGlobalHookErrorReporter((error) => {
|
|
164
|
-
debugLogger.error("Global instrumentation hook error:", error);
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
// src/id-gen.ts
|
|
168
59
|
var IDGenerator = class {
|
|
169
60
|
};
|
|
170
61
|
var UUIDGenerator = class extends IDGenerator {
|
|
@@ -1782,7 +1673,9 @@ var AclObjectType = z6.union([
|
|
|
1782
1673
|
"project_log",
|
|
1783
1674
|
"org_project",
|
|
1784
1675
|
"org_audit_logs",
|
|
1785
|
-
"project_group"
|
|
1676
|
+
"project_group",
|
|
1677
|
+
"ai_secret",
|
|
1678
|
+
"org_ai_secret"
|
|
1786
1679
|
]),
|
|
1787
1680
|
z6.null()
|
|
1788
1681
|
]);
|
|
@@ -2615,7 +2508,7 @@ var PromptParserNullish = z6.union([
|
|
|
2615
2508
|
}),
|
|
2616
2509
|
z6.null()
|
|
2617
2510
|
]);
|
|
2618
|
-
var
|
|
2511
|
+
var PreprocessorId = z6.union([
|
|
2619
2512
|
z6.object({
|
|
2620
2513
|
type: z6.literal("function"),
|
|
2621
2514
|
id: z6.string(),
|
|
@@ -2626,6 +2519,7 @@ var PreprocessorSavedFunctionId = z6.union([
|
|
|
2626
2519
|
name: z6.string(),
|
|
2627
2520
|
function_type: z6.literal("preprocessor").optional().default("preprocessor")
|
|
2628
2521
|
}),
|
|
2522
|
+
z6.object({ type: z6.literal("inline"), code: z6.string().min(1) }),
|
|
2629
2523
|
z6.null()
|
|
2630
2524
|
]);
|
|
2631
2525
|
var PromptDataNullish = z6.union([
|
|
@@ -2633,7 +2527,7 @@ var PromptDataNullish = z6.union([
|
|
|
2633
2527
|
prompt: PromptBlockDataNullish,
|
|
2634
2528
|
options: PromptOptionsNullish,
|
|
2635
2529
|
parser: PromptParserNullish,
|
|
2636
|
-
preprocessor:
|
|
2530
|
+
preprocessor: PreprocessorId,
|
|
2637
2531
|
tool_functions: z6.union([z6.array(SavedFunctionId), z6.null()]),
|
|
2638
2532
|
template_format: z6.union([
|
|
2639
2533
|
z6.enum(["mustache", "nunjucks", "none"]),
|
|
@@ -2835,7 +2729,7 @@ var PromptData = z6.object({
|
|
|
2835
2729
|
prompt: PromptBlockDataNullish,
|
|
2836
2730
|
options: PromptOptionsNullish,
|
|
2837
2731
|
parser: PromptParserNullish,
|
|
2838
|
-
preprocessor:
|
|
2732
|
+
preprocessor: PreprocessorId,
|
|
2839
2733
|
tool_functions: z6.union([z6.array(SavedFunctionId), z6.null()]),
|
|
2840
2734
|
template_format: z6.union([
|
|
2841
2735
|
z6.enum(["mustache", "nunjucks", "none"]),
|
|
@@ -3779,6 +3673,7 @@ var View = z6.object({
|
|
|
3779
3673
|
]),
|
|
3780
3674
|
name: z6.string(),
|
|
3781
3675
|
description: z6.union([z6.string(), z6.null()]).optional(),
|
|
3676
|
+
starred: z6.boolean().optional(),
|
|
3782
3677
|
created: z6.union([z6.string(), z6.null()]).optional(),
|
|
3783
3678
|
updated_at: z6.union([z6.string(), z6.null()]).optional(),
|
|
3784
3679
|
view_data: ViewData.optional(),
|
|
@@ -4539,44 +4434,72 @@ function createCacheLayers({
|
|
|
4539
4434
|
}
|
|
4540
4435
|
|
|
4541
4436
|
// src/prompt-cache/prompt-cache.ts
|
|
4542
|
-
function createCacheKey(key) {
|
|
4437
|
+
function createCacheKey(key, namespace) {
|
|
4438
|
+
let cacheKey;
|
|
4543
4439
|
if (key.id) {
|
|
4544
|
-
|
|
4545
|
-
}
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
4549
|
-
|
|
4550
|
-
|
|
4551
|
-
|
|
4440
|
+
cacheKey = `id:${key.id}`;
|
|
4441
|
+
} else {
|
|
4442
|
+
const prefix = key.projectId ?? key.projectName;
|
|
4443
|
+
if (!prefix) {
|
|
4444
|
+
throw new Error("Either projectId or projectName must be provided");
|
|
4445
|
+
}
|
|
4446
|
+
if (!key.slug) {
|
|
4447
|
+
throw new Error("Slug must be provided when not using ID");
|
|
4448
|
+
}
|
|
4449
|
+
cacheKey = `${prefix}:${key.slug}:${key.version ?? "latest"}`;
|
|
4552
4450
|
}
|
|
4553
|
-
return `${
|
|
4451
|
+
return namespace === void 0 ? cacheKey : `${namespace.length}:${namespace}:${cacheKey}`;
|
|
4554
4452
|
}
|
|
4555
|
-
var PromptCache = class {
|
|
4453
|
+
var PromptCache = class _PromptCache {
|
|
4556
4454
|
memoryCache;
|
|
4557
4455
|
diskCache;
|
|
4456
|
+
namespace;
|
|
4457
|
+
expectedResolvedOrgIdentity;
|
|
4558
4458
|
constructor(options) {
|
|
4559
4459
|
this.memoryCache = options.memoryCache;
|
|
4560
4460
|
this.diskCache = options.diskCache;
|
|
4461
|
+
this.namespace = options.namespace;
|
|
4462
|
+
this.expectedResolvedOrgIdentity = options.expectedResolvedOrgIdentity;
|
|
4463
|
+
}
|
|
4464
|
+
/**
|
|
4465
|
+
* Returns a cache view that shares the same storage layers but isolates all
|
|
4466
|
+
* entries under the provided namespace.
|
|
4467
|
+
*/
|
|
4468
|
+
withNamespace(namespace, expectedResolvedOrgIdentity) {
|
|
4469
|
+
return new _PromptCache({
|
|
4470
|
+
memoryCache: this.memoryCache,
|
|
4471
|
+
diskCache: this.diskCache,
|
|
4472
|
+
namespace,
|
|
4473
|
+
expectedResolvedOrgIdentity
|
|
4474
|
+
});
|
|
4561
4475
|
}
|
|
4562
4476
|
/**
|
|
4563
4477
|
* Retrieves a prompt from the cache.
|
|
4564
4478
|
* First checks the in-memory LRU cache, then falls back to checking the disk cache if available.
|
|
4565
4479
|
*/
|
|
4566
4480
|
async get(key) {
|
|
4567
|
-
const cacheKey = createCacheKey(key);
|
|
4481
|
+
const cacheKey = createCacheKey(key, this.namespace);
|
|
4568
4482
|
if (this.memoryCache) {
|
|
4569
|
-
const
|
|
4570
|
-
if (
|
|
4571
|
-
return
|
|
4483
|
+
const memoryEntry = this.memoryCache.get(cacheKey);
|
|
4484
|
+
if (memoryEntry !== void 0 && (this.expectedResolvedOrgIdentity === void 0 || memoryEntry.resolvedOrgIdentity === this.expectedResolvedOrgIdentity)) {
|
|
4485
|
+
return memoryEntry.value;
|
|
4572
4486
|
}
|
|
4573
4487
|
}
|
|
4574
4488
|
if (this.diskCache) {
|
|
4575
|
-
const
|
|
4576
|
-
if (!
|
|
4489
|
+
const diskEntry = await this.diskCache.get(cacheKey);
|
|
4490
|
+
if (!diskEntry || this.expectedResolvedOrgIdentity !== void 0 && diskEntry.resolvedOrgIdentity !== this.expectedResolvedOrgIdentity) {
|
|
4577
4491
|
return void 0;
|
|
4578
4492
|
}
|
|
4579
|
-
|
|
4493
|
+
const serializedPrompt = diskEntry.value;
|
|
4494
|
+
const diskPrompt = new Prompt2(
|
|
4495
|
+
serializedPrompt.metadata,
|
|
4496
|
+
serializedPrompt.defaults,
|
|
4497
|
+
serializedPrompt.noTrace
|
|
4498
|
+
);
|
|
4499
|
+
this.memoryCache?.set(cacheKey, {
|
|
4500
|
+
value: diskPrompt,
|
|
4501
|
+
resolvedOrgIdentity: diskEntry.resolvedOrgIdentity
|
|
4502
|
+
});
|
|
4580
4503
|
return diskPrompt;
|
|
4581
4504
|
}
|
|
4582
4505
|
return void 0;
|
|
@@ -4590,58 +4513,91 @@ var PromptCache = class {
|
|
|
4590
4513
|
* @throws If there is an error writing to the disk cache.
|
|
4591
4514
|
*/
|
|
4592
4515
|
async set(key, value) {
|
|
4593
|
-
const cacheKey = createCacheKey(key);
|
|
4594
|
-
|
|
4516
|
+
const cacheKey = createCacheKey(key, this.namespace);
|
|
4517
|
+
const memoryEntry = {
|
|
4518
|
+
value,
|
|
4519
|
+
resolvedOrgIdentity: this.expectedResolvedOrgIdentity
|
|
4520
|
+
};
|
|
4521
|
+
this.memoryCache?.set(cacheKey, memoryEntry);
|
|
4595
4522
|
if (this.diskCache) {
|
|
4596
|
-
await this.diskCache.set(cacheKey,
|
|
4523
|
+
await this.diskCache.set(cacheKey, {
|
|
4524
|
+
value: value._internalSerializeForCache(),
|
|
4525
|
+
resolvedOrgIdentity: this.expectedResolvedOrgIdentity
|
|
4526
|
+
});
|
|
4597
4527
|
}
|
|
4598
4528
|
}
|
|
4599
4529
|
};
|
|
4600
4530
|
|
|
4601
4531
|
// src/prompt-cache/parameters-cache.ts
|
|
4602
|
-
function createCacheKey2(key) {
|
|
4532
|
+
function createCacheKey2(key, namespace) {
|
|
4533
|
+
let cacheKey;
|
|
4603
4534
|
if (key.id) {
|
|
4604
|
-
|
|
4605
|
-
}
|
|
4606
|
-
|
|
4607
|
-
|
|
4608
|
-
|
|
4609
|
-
|
|
4610
|
-
|
|
4611
|
-
|
|
4535
|
+
cacheKey = `parameters:id:${key.id}`;
|
|
4536
|
+
} else {
|
|
4537
|
+
const prefix = key.projectId ?? key.projectName;
|
|
4538
|
+
if (!prefix) {
|
|
4539
|
+
throw new Error("Either projectId or projectName must be provided");
|
|
4540
|
+
}
|
|
4541
|
+
if (!key.slug) {
|
|
4542
|
+
throw new Error("Slug must be provided when not using ID");
|
|
4543
|
+
}
|
|
4544
|
+
cacheKey = `parameters:${prefix}:${key.slug}:${key.version ?? "latest"}`;
|
|
4612
4545
|
}
|
|
4613
|
-
return
|
|
4546
|
+
return namespace === void 0 ? cacheKey : `${namespace.length}:${namespace}:${cacheKey}`;
|
|
4614
4547
|
}
|
|
4615
|
-
var ParametersCache = class {
|
|
4548
|
+
var ParametersCache = class _ParametersCache {
|
|
4616
4549
|
memoryCache;
|
|
4617
4550
|
diskCache;
|
|
4551
|
+
namespace;
|
|
4552
|
+
expectedResolvedOrgIdentity;
|
|
4618
4553
|
constructor(options) {
|
|
4619
4554
|
this.memoryCache = options.memoryCache;
|
|
4620
4555
|
this.diskCache = options.diskCache;
|
|
4556
|
+
this.namespace = options.namespace;
|
|
4557
|
+
this.expectedResolvedOrgIdentity = options.expectedResolvedOrgIdentity;
|
|
4558
|
+
}
|
|
4559
|
+
withNamespace(namespace, expectedResolvedOrgIdentity) {
|
|
4560
|
+
return new _ParametersCache({
|
|
4561
|
+
memoryCache: this.memoryCache,
|
|
4562
|
+
diskCache: this.diskCache,
|
|
4563
|
+
namespace,
|
|
4564
|
+
expectedResolvedOrgIdentity
|
|
4565
|
+
});
|
|
4621
4566
|
}
|
|
4622
4567
|
async get(key) {
|
|
4623
|
-
const cacheKey = createCacheKey2(key);
|
|
4568
|
+
const cacheKey = createCacheKey2(key, this.namespace);
|
|
4624
4569
|
if (this.memoryCache) {
|
|
4625
|
-
const
|
|
4626
|
-
if (
|
|
4627
|
-
return
|
|
4570
|
+
const memoryEntry = this.memoryCache.get(cacheKey);
|
|
4571
|
+
if (memoryEntry !== void 0 && (this.expectedResolvedOrgIdentity === void 0 || memoryEntry.resolvedOrgIdentity === this.expectedResolvedOrgIdentity)) {
|
|
4572
|
+
return memoryEntry.value;
|
|
4628
4573
|
}
|
|
4629
4574
|
}
|
|
4630
4575
|
if (this.diskCache) {
|
|
4631
|
-
const
|
|
4632
|
-
if (!
|
|
4576
|
+
const diskEntry = await this.diskCache.get(cacheKey);
|
|
4577
|
+
if (!diskEntry || this.expectedResolvedOrgIdentity !== void 0 && diskEntry.resolvedOrgIdentity !== this.expectedResolvedOrgIdentity) {
|
|
4633
4578
|
return void 0;
|
|
4634
4579
|
}
|
|
4635
|
-
|
|
4636
|
-
|
|
4580
|
+
const diskParameters = new RemoteEvalParameters(diskEntry.value.metadata);
|
|
4581
|
+
this.memoryCache?.set(cacheKey, {
|
|
4582
|
+
value: diskParameters,
|
|
4583
|
+
resolvedOrgIdentity: diskEntry.resolvedOrgIdentity
|
|
4584
|
+
});
|
|
4585
|
+
return diskParameters;
|
|
4637
4586
|
}
|
|
4638
4587
|
return void 0;
|
|
4639
4588
|
}
|
|
4640
4589
|
async set(key, value) {
|
|
4641
|
-
const cacheKey = createCacheKey2(key);
|
|
4642
|
-
|
|
4590
|
+
const cacheKey = createCacheKey2(key, this.namespace);
|
|
4591
|
+
const memoryEntry = {
|
|
4592
|
+
value,
|
|
4593
|
+
resolvedOrgIdentity: this.expectedResolvedOrgIdentity
|
|
4594
|
+
};
|
|
4595
|
+
this.memoryCache?.set(cacheKey, memoryEntry);
|
|
4643
4596
|
if (this.diskCache) {
|
|
4644
|
-
await this.diskCache.set(cacheKey,
|
|
4597
|
+
await this.diskCache.set(cacheKey, {
|
|
4598
|
+
value: value._internalSerializeForCache(),
|
|
4599
|
+
resolvedOrgIdentity: this.expectedResolvedOrgIdentity
|
|
4600
|
+
});
|
|
4645
4601
|
}
|
|
4646
4602
|
}
|
|
4647
4603
|
};
|
|
@@ -4946,6 +4902,16 @@ var datasetSnapshotRegisterResponseSchema = z8.object({
|
|
|
4946
4902
|
dataset_snapshot: DatasetSnapshot,
|
|
4947
4903
|
found_existing: z8.boolean().optional()
|
|
4948
4904
|
});
|
|
4905
|
+
var datasetObjectInfoSchema = z8.object({
|
|
4906
|
+
object_id: z8.string(),
|
|
4907
|
+
object_name: z8.string(),
|
|
4908
|
+
parent_cols: z8.object({
|
|
4909
|
+
project: z8.object({
|
|
4910
|
+
id: z8.string(),
|
|
4911
|
+
name: z8.string()
|
|
4912
|
+
})
|
|
4913
|
+
})
|
|
4914
|
+
});
|
|
4949
4915
|
var datasetRestorePreviewResultSchema = z8.object({
|
|
4950
4916
|
rows_to_restore: z8.number(),
|
|
4951
4917
|
rows_to_delete: z8.number()
|
|
@@ -5159,12 +5125,53 @@ var loginSchema = z8.strictObject({
|
|
|
5159
5125
|
});
|
|
5160
5126
|
var stateNonce = 0;
|
|
5161
5127
|
var V1_PROXY_SUFFIX = "/v1/proxy";
|
|
5128
|
+
var LOADER_LOGIN_CACHE_MAX = 16;
|
|
5162
5129
|
function normalizeProxyConnUrl(proxyUrl) {
|
|
5163
5130
|
return proxyUrl.endsWith(V1_PROXY_SUFFIX) ? proxyUrl.slice(0, proxyUrl.length - V1_PROXY_SUFFIX.length) : proxyUrl;
|
|
5164
5131
|
}
|
|
5165
5132
|
var BraintrustState = class _BraintrustState {
|
|
5133
|
+
id;
|
|
5134
|
+
currentExperiment;
|
|
5135
|
+
// Note: the value of IsAsyncFlush doesn't really matter here, since we
|
|
5136
|
+
// (safely) dynamically cast it whenever retrieving the logger.
|
|
5137
|
+
currentLogger;
|
|
5138
|
+
currentParent;
|
|
5139
|
+
currentSpan;
|
|
5140
|
+
// Any time we re-log in, we directly update the apiConn inside the logger.
|
|
5141
|
+
// This is preferable to replacing the whole logger, which would create the
|
|
5142
|
+
// possibility of multiple loggers floating around, which may not log in a
|
|
5143
|
+
// deterministic order.
|
|
5144
|
+
_bgLogger;
|
|
5145
|
+
_overrideBgLogger = null;
|
|
5146
|
+
appUrl = null;
|
|
5147
|
+
appPublicUrl = null;
|
|
5148
|
+
loginToken = null;
|
|
5149
|
+
orgId = null;
|
|
5150
|
+
orgName = null;
|
|
5151
|
+
apiUrl = null;
|
|
5152
|
+
proxyUrl = null;
|
|
5153
|
+
loggedIn = false;
|
|
5154
|
+
gitMetadataSettings;
|
|
5155
|
+
debugLogLevel;
|
|
5156
|
+
debugLogLevelConfigured = false;
|
|
5157
|
+
fetch = globalThis.fetch;
|
|
5158
|
+
_appConn = null;
|
|
5159
|
+
_apiConn = null;
|
|
5160
|
+
_proxyConn = null;
|
|
5161
|
+
promptCache;
|
|
5162
|
+
parametersCache;
|
|
5163
|
+
spanCache;
|
|
5164
|
+
_idGenerator = null;
|
|
5165
|
+
_contextManager = null;
|
|
5166
|
+
_otelFlushCallback = null;
|
|
5167
|
+
spanOriginEnvironment;
|
|
5168
|
+
traceContextSigningSecret;
|
|
5169
|
+
loaderLoginCache = /* @__PURE__ */ new WeakMap();
|
|
5170
|
+
loginParams;
|
|
5171
|
+
activeLoginOrgNameSelector;
|
|
5166
5172
|
constructor(loginParams) {
|
|
5167
|
-
this.loginParams = loginParams;
|
|
5173
|
+
this.loginParams = { ...loginParams };
|
|
5174
|
+
this.activeLoginOrgNameSelector = loginParams.orgName ?? isomorph_default.getEnv("BRAINTRUST_ORG_NAME");
|
|
5168
5175
|
this.id = `${(/* @__PURE__ */ new Date()).toLocaleString()}-${stateNonce++}`;
|
|
5169
5176
|
this.currentExperiment = void 0;
|
|
5170
5177
|
this.currentLogger = void 0;
|
|
@@ -5201,12 +5208,14 @@ var BraintrustState = class _BraintrustState {
|
|
|
5201
5208
|
const {
|
|
5202
5209
|
memoryCache: parametersMemoryCache,
|
|
5203
5210
|
diskCache: parametersDiskCache
|
|
5204
|
-
} = createCacheLayers(
|
|
5205
|
-
|
|
5206
|
-
|
|
5207
|
-
|
|
5208
|
-
|
|
5209
|
-
|
|
5211
|
+
} = createCacheLayers(
|
|
5212
|
+
{
|
|
5213
|
+
memoryMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_MEMORY_MAX",
|
|
5214
|
+
diskCacheDirEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DIR",
|
|
5215
|
+
diskMaxEnvVar: "BRAINTRUST_PARAMETERS_CACHE_DISK_MAX",
|
|
5216
|
+
getDefaultDiskCacheDir: () => `${isomorph_default.getEnv("HOME") ?? isomorph_default.homedir()}/.braintrust/parameters_cache`
|
|
5217
|
+
}
|
|
5218
|
+
);
|
|
5210
5219
|
this.parametersCache = new ParametersCache({
|
|
5211
5220
|
memoryCache: parametersMemoryCache,
|
|
5212
5221
|
diskCache: parametersDiskCache
|
|
@@ -5215,43 +5224,6 @@ var BraintrustState = class _BraintrustState {
|
|
|
5215
5224
|
this.spanOriginEnvironment = detectSpanOriginEnvironment();
|
|
5216
5225
|
this._internalSetTraceContextSigningSecret(loginParams.apiKey);
|
|
5217
5226
|
}
|
|
5218
|
-
loginParams;
|
|
5219
|
-
id;
|
|
5220
|
-
currentExperiment;
|
|
5221
|
-
// Note: the value of IsAsyncFlush doesn't really matter here, since we
|
|
5222
|
-
// (safely) dynamically cast it whenever retrieving the logger.
|
|
5223
|
-
currentLogger;
|
|
5224
|
-
currentParent;
|
|
5225
|
-
currentSpan;
|
|
5226
|
-
// Any time we re-log in, we directly update the apiConn inside the logger.
|
|
5227
|
-
// This is preferable to replacing the whole logger, which would create the
|
|
5228
|
-
// possibility of multiple loggers floating around, which may not log in a
|
|
5229
|
-
// deterministic order.
|
|
5230
|
-
_bgLogger;
|
|
5231
|
-
_overrideBgLogger = null;
|
|
5232
|
-
appUrl = null;
|
|
5233
|
-
appPublicUrl = null;
|
|
5234
|
-
loginToken = null;
|
|
5235
|
-
orgId = null;
|
|
5236
|
-
orgName = null;
|
|
5237
|
-
apiUrl = null;
|
|
5238
|
-
proxyUrl = null;
|
|
5239
|
-
loggedIn = false;
|
|
5240
|
-
gitMetadataSettings;
|
|
5241
|
-
debugLogLevel;
|
|
5242
|
-
debugLogLevelConfigured = false;
|
|
5243
|
-
fetch = globalThis.fetch;
|
|
5244
|
-
_appConn = null;
|
|
5245
|
-
_apiConn = null;
|
|
5246
|
-
_proxyConn = null;
|
|
5247
|
-
promptCache;
|
|
5248
|
-
parametersCache;
|
|
5249
|
-
spanCache;
|
|
5250
|
-
_idGenerator = null;
|
|
5251
|
-
_contextManager = null;
|
|
5252
|
-
_otelFlushCallback = null;
|
|
5253
|
-
spanOriginEnvironment;
|
|
5254
|
-
traceContextSigningSecret;
|
|
5255
5227
|
/** @internal */
|
|
5256
5228
|
_internalSetTraceContextSigningSecret(secret) {
|
|
5257
5229
|
const normalizedSecret = secret?.trim();
|
|
@@ -5276,6 +5248,101 @@ var BraintrustState = class _BraintrustState {
|
|
|
5276
5248
|
this._appConn = null;
|
|
5277
5249
|
this._apiConn = null;
|
|
5278
5250
|
this._proxyConn = null;
|
|
5251
|
+
this.loaderLoginCache = /* @__PURE__ */ new WeakMap();
|
|
5252
|
+
}
|
|
5253
|
+
/** @internal */
|
|
5254
|
+
async _internalResolveLoaderLoginOptions({
|
|
5255
|
+
apiKey,
|
|
5256
|
+
appUrl,
|
|
5257
|
+
orgName,
|
|
5258
|
+
fetch: fetch2,
|
|
5259
|
+
forceLogin
|
|
5260
|
+
}) {
|
|
5261
|
+
const resolvedAppUrl = appUrl ?? (this.loggedIn ? this.appUrl ?? void 0 : void 0) ?? this.loginParams.appUrl ?? isomorph_default.getEnv("BRAINTRUST_APP_URL") ?? "https://www.braintrust.dev";
|
|
5262
|
+
const resolvedApiKey = apiKey ?? (this.loggedIn ? this.loginToken ?? void 0 : void 0) ?? this.loginParams.apiKey ?? await isomorph_default.getBraintrustApiKey();
|
|
5263
|
+
if (!resolvedApiKey) {
|
|
5264
|
+
throw new Error(
|
|
5265
|
+
"Please specify an api key (e.g. by setting BRAINTRUST_API_KEY)."
|
|
5266
|
+
);
|
|
5267
|
+
}
|
|
5268
|
+
const normalizedApiKey = HTTPConnection.sanitize_token(resolvedApiKey);
|
|
5269
|
+
const usesActiveCredential = this.loggedIn && normalizedApiKey === this.loginToken;
|
|
5270
|
+
const requestedOrgName = orgName ?? (usesActiveCredential ? this.activeLoginOrgNameSelector : void 0) ?? this.loginParams.orgName ?? isomorph_default.getEnv("BRAINTRUST_ORG_NAME");
|
|
5271
|
+
const resolvedOrgName = orgName ?? (usesActiveCredential ? this.orgName ?? void 0 : void 0) ?? requestedOrgName;
|
|
5272
|
+
const resolvedFetch = fetch2 ?? (this.loggedIn ? this.fetch : void 0) ?? this.loginParams.fetch ?? globalThis.fetch;
|
|
5273
|
+
const credentialCacheNamespace = JSON.stringify([
|
|
5274
|
+
"loader-credential",
|
|
5275
|
+
resolvedAppUrl,
|
|
5276
|
+
requestedOrgName,
|
|
5277
|
+
normalizedApiKey
|
|
5278
|
+
]);
|
|
5279
|
+
return {
|
|
5280
|
+
apiKey: normalizedApiKey,
|
|
5281
|
+
appUrl: resolvedAppUrl,
|
|
5282
|
+
orgName: resolvedOrgName,
|
|
5283
|
+
fetch: resolvedFetch,
|
|
5284
|
+
forceLogin,
|
|
5285
|
+
credentialCacheNamespace,
|
|
5286
|
+
existingState: !forceLogin && usesActiveCredential && resolvedAppUrl === this.appUrl && resolvedOrgName === this.orgName && resolvedFetch === this.fetch ? this : void 0
|
|
5287
|
+
};
|
|
5288
|
+
}
|
|
5289
|
+
/** @internal */
|
|
5290
|
+
_internalGetLoaderCacheViews(loginOptions, requestState) {
|
|
5291
|
+
const expectedResolvedOrgIdentity = requestState?.orgId && requestState.appUrl ? JSON.stringify([
|
|
5292
|
+
"loader-org",
|
|
5293
|
+
requestState.appUrl,
|
|
5294
|
+
requestState.orgId
|
|
5295
|
+
]) : void 0;
|
|
5296
|
+
return {
|
|
5297
|
+
promptCache: this.promptCache.withNamespace(
|
|
5298
|
+
loginOptions.credentialCacheNamespace,
|
|
5299
|
+
expectedResolvedOrgIdentity
|
|
5300
|
+
),
|
|
5301
|
+
parametersCache: this.parametersCache.withNamespace(
|
|
5302
|
+
loginOptions.credentialCacheNamespace,
|
|
5303
|
+
expectedResolvedOrgIdentity
|
|
5304
|
+
)
|
|
5305
|
+
};
|
|
5306
|
+
}
|
|
5307
|
+
/** @internal */
|
|
5308
|
+
async _internalGetLoaderState({
|
|
5309
|
+
apiKey,
|
|
5310
|
+
appUrl,
|
|
5311
|
+
orgName,
|
|
5312
|
+
fetch: fetch2,
|
|
5313
|
+
forceLogin,
|
|
5314
|
+
existingState
|
|
5315
|
+
}) {
|
|
5316
|
+
if (existingState) {
|
|
5317
|
+
return existingState;
|
|
5318
|
+
}
|
|
5319
|
+
let cache = this.loaderLoginCache.get(fetch2);
|
|
5320
|
+
if (!cache) {
|
|
5321
|
+
cache = new LRUCache({ max: LOADER_LOGIN_CACHE_MAX });
|
|
5322
|
+
this.loaderLoginCache.set(fetch2, cache);
|
|
5323
|
+
}
|
|
5324
|
+
const cacheKey = JSON.stringify([appUrl, orgName, apiKey]);
|
|
5325
|
+
if (!forceLogin) {
|
|
5326
|
+
const cachedState = cache.get(cacheKey);
|
|
5327
|
+
if (cachedState) {
|
|
5328
|
+
return cachedState;
|
|
5329
|
+
}
|
|
5330
|
+
}
|
|
5331
|
+
const statePromise = loginToLoaderRequestState({
|
|
5332
|
+
orgName,
|
|
5333
|
+
apiKey,
|
|
5334
|
+
appUrl,
|
|
5335
|
+
fetch: fetch2
|
|
5336
|
+
});
|
|
5337
|
+
cache.set(cacheKey, statePromise);
|
|
5338
|
+
try {
|
|
5339
|
+
return await statePromise;
|
|
5340
|
+
} catch (error) {
|
|
5341
|
+
if (cache.get(cacheKey) === statePromise) {
|
|
5342
|
+
cache.delete(cacheKey);
|
|
5343
|
+
}
|
|
5344
|
+
throw error;
|
|
5345
|
+
}
|
|
5279
5346
|
}
|
|
5280
5347
|
resetIdGenState() {
|
|
5281
5348
|
this._idGenerator = null;
|
|
@@ -5324,6 +5391,8 @@ var BraintrustState = class _BraintrustState {
|
|
|
5324
5391
|
this.debugLogLevel = other.debugLogLevel;
|
|
5325
5392
|
this.debugLogLevelConfigured = other.debugLogLevelConfigured;
|
|
5326
5393
|
this.traceContextSigningSecret = other.traceContextSigningSecret;
|
|
5394
|
+
this.fetch = other.fetch;
|
|
5395
|
+
this.activeLoginOrgNameSelector = other.activeLoginOrgNameSelector;
|
|
5327
5396
|
setGlobalDebugLogLevel(
|
|
5328
5397
|
this.debugLogLevelConfigured ? this.debugLogLevel ?? false : void 0
|
|
5329
5398
|
);
|
|
@@ -5563,36 +5632,85 @@ var FailedHTTPResponse = class extends Error {
|
|
|
5563
5632
|
status;
|
|
5564
5633
|
text;
|
|
5565
5634
|
data;
|
|
5566
|
-
|
|
5635
|
+
cause;
|
|
5636
|
+
constructor(status, text, data, cause) {
|
|
5567
5637
|
super(`${status}: ${text} (${data})`);
|
|
5568
5638
|
this.status = status;
|
|
5569
5639
|
this.text = text;
|
|
5570
5640
|
this.data = data;
|
|
5641
|
+
this.cause = cause;
|
|
5642
|
+
}
|
|
5643
|
+
};
|
|
5644
|
+
var HTTPTransportError = class extends Error {
|
|
5645
|
+
cause;
|
|
5646
|
+
constructor(cause) {
|
|
5647
|
+
super(cause instanceof Error ? cause.message : String(cause));
|
|
5648
|
+
this.name = "HTTPTransportError";
|
|
5649
|
+
this.cause = cause;
|
|
5571
5650
|
}
|
|
5572
5651
|
};
|
|
5652
|
+
var httpTransportErrorCauses = /* @__PURE__ */ new WeakSet();
|
|
5653
|
+
function recordHTTPTransportError(error) {
|
|
5654
|
+
if (typeof error === "object" && error !== null || typeof error === "function") {
|
|
5655
|
+
httpTransportErrorCauses.add(error);
|
|
5656
|
+
}
|
|
5657
|
+
}
|
|
5658
|
+
function rethrowHTTPTransportError(error, classifyTransportErrors) {
|
|
5659
|
+
if (classifyTransportErrors) {
|
|
5660
|
+
throw new HTTPTransportError(error);
|
|
5661
|
+
}
|
|
5662
|
+
recordHTTPTransportError(error);
|
|
5663
|
+
throw error;
|
|
5664
|
+
}
|
|
5665
|
+
function isLoaderCacheFallbackError(error) {
|
|
5666
|
+
if (error instanceof FailedHTTPResponse) {
|
|
5667
|
+
return error.status === 408 || error.status === 429 || error.status >= 500;
|
|
5668
|
+
}
|
|
5669
|
+
if (error instanceof HTTPTransportError) {
|
|
5670
|
+
return true;
|
|
5671
|
+
}
|
|
5672
|
+
return (typeof error === "object" && error !== null || typeof error === "function") && httpTransportErrorCauses.has(error);
|
|
5673
|
+
}
|
|
5674
|
+
async function readJSONResponse(response, classifyTransportErrors = false) {
|
|
5675
|
+
let data;
|
|
5676
|
+
try {
|
|
5677
|
+
data = await response.text();
|
|
5678
|
+
} catch (error) {
|
|
5679
|
+
rethrowHTTPTransportError(error, classifyTransportErrors);
|
|
5680
|
+
}
|
|
5681
|
+
return JSON.parse(data);
|
|
5682
|
+
}
|
|
5573
5683
|
async function checkResponse(resp) {
|
|
5574
5684
|
if (resp.ok) {
|
|
5575
5685
|
return resp;
|
|
5576
|
-
}
|
|
5686
|
+
}
|
|
5687
|
+
let data;
|
|
5688
|
+
try {
|
|
5689
|
+
data = await resp.text();
|
|
5690
|
+
} catch (error) {
|
|
5577
5691
|
throw new FailedHTTPResponse(
|
|
5578
5692
|
resp.status,
|
|
5579
5693
|
resp.statusText,
|
|
5580
|
-
|
|
5694
|
+
"Unable to read response body",
|
|
5695
|
+
error
|
|
5581
5696
|
);
|
|
5582
5697
|
}
|
|
5698
|
+
throw new FailedHTTPResponse(resp.status, resp.statusText, data);
|
|
5583
5699
|
}
|
|
5584
5700
|
var HTTPConnection = class _HTTPConnection {
|
|
5585
|
-
base_url
|
|
5586
|
-
|
|
5587
|
-
headers;
|
|
5588
|
-
fetch;
|
|
5589
|
-
constructor(base_url, fetch2) {
|
|
5701
|
+
constructor(base_url, fetch2, classifyTransportErrors = false) {
|
|
5702
|
+
this.classifyTransportErrors = classifyTransportErrors;
|
|
5590
5703
|
this.base_url = base_url;
|
|
5591
5704
|
this.token = null;
|
|
5592
5705
|
this.headers = {};
|
|
5593
5706
|
this._reset();
|
|
5594
5707
|
this.fetch = fetch2;
|
|
5595
5708
|
}
|
|
5709
|
+
classifyTransportErrors;
|
|
5710
|
+
base_url;
|
|
5711
|
+
token;
|
|
5712
|
+
headers;
|
|
5713
|
+
fetch;
|
|
5596
5714
|
setFetch(fetch2) {
|
|
5597
5715
|
this.fetch = fetch2;
|
|
5598
5716
|
}
|
|
@@ -5632,9 +5750,9 @@ var HTTPConnection = class _HTTPConnection {
|
|
|
5632
5750
|
).toString();
|
|
5633
5751
|
const this_fetch = this.fetch;
|
|
5634
5752
|
const this_headers = this.headers;
|
|
5635
|
-
|
|
5636
|
-
|
|
5637
|
-
await this_fetch(url.toString(), {
|
|
5753
|
+
let response;
|
|
5754
|
+
try {
|
|
5755
|
+
response = await this_fetch(url.toString(), {
|
|
5638
5756
|
headers: {
|
|
5639
5757
|
Accept: "application/json",
|
|
5640
5758
|
...this_headers,
|
|
@@ -5642,8 +5760,14 @@ var HTTPConnection = class _HTTPConnection {
|
|
|
5642
5760
|
},
|
|
5643
5761
|
keepalive: true,
|
|
5644
5762
|
...rest
|
|
5645
|
-
})
|
|
5646
|
-
)
|
|
5763
|
+
});
|
|
5764
|
+
} catch (error) {
|
|
5765
|
+
if (config?.signal?.aborted) {
|
|
5766
|
+
throw getAbortReason(config.signal);
|
|
5767
|
+
}
|
|
5768
|
+
rethrowHTTPTransportError(error, this.classifyTransportErrors);
|
|
5769
|
+
}
|
|
5770
|
+
return await checkResponse(response);
|
|
5647
5771
|
}
|
|
5648
5772
|
async post(path3, params, config, retries = 0) {
|
|
5649
5773
|
const { headers, ...rest } = config || {};
|
|
@@ -5653,8 +5777,9 @@ var HTTPConnection = class _HTTPConnection {
|
|
|
5653
5777
|
const tries = retries + 1;
|
|
5654
5778
|
for (let i = 0; i < tries; i++) {
|
|
5655
5779
|
try {
|
|
5656
|
-
|
|
5657
|
-
|
|
5780
|
+
let response;
|
|
5781
|
+
try {
|
|
5782
|
+
response = await this_fetch(_urljoin(this_base_url, path3), {
|
|
5658
5783
|
method: "POST",
|
|
5659
5784
|
headers: {
|
|
5660
5785
|
Accept: "application/json",
|
|
@@ -5665,8 +5790,14 @@ var HTTPConnection = class _HTTPConnection {
|
|
|
5665
5790
|
body: typeof params === "string" ? params : params ? JSON.stringify(params) : void 0,
|
|
5666
5791
|
keepalive: true,
|
|
5667
5792
|
...rest
|
|
5668
|
-
})
|
|
5669
|
-
)
|
|
5793
|
+
});
|
|
5794
|
+
} catch (error) {
|
|
5795
|
+
if (config?.signal?.aborted) {
|
|
5796
|
+
throw getAbortReason(config.signal);
|
|
5797
|
+
}
|
|
5798
|
+
rethrowHTTPTransportError(error, this.classifyTransportErrors);
|
|
5799
|
+
}
|
|
5800
|
+
return await checkResponse(response);
|
|
5670
5801
|
} catch (error) {
|
|
5671
5802
|
if (config?.signal?.aborted) {
|
|
5672
5803
|
throw getAbortReason(config.signal);
|
|
@@ -5691,7 +5822,7 @@ var HTTPConnection = class _HTTPConnection {
|
|
|
5691
5822
|
for (let i = 0; i < tries; i++) {
|
|
5692
5823
|
try {
|
|
5693
5824
|
const resp = await this.get(`${object_type}`, args);
|
|
5694
|
-
return await resp.
|
|
5825
|
+
return await readJSONResponse(resp, this.classifyTransportErrors);
|
|
5695
5826
|
} catch (e) {
|
|
5696
5827
|
if (i < tries - 1) {
|
|
5697
5828
|
debugLogger.debug(
|
|
@@ -5714,7 +5845,7 @@ var HTTPConnection = class _HTTPConnection {
|
|
|
5714
5845
|
const resp = await this.post(`${object_type}`, args, {
|
|
5715
5846
|
headers: { "Content-Type": "application/json" }
|
|
5716
5847
|
});
|
|
5717
|
-
return await resp.
|
|
5848
|
+
return await readJSONResponse(resp, this.classifyTransportErrors);
|
|
5718
5849
|
}
|
|
5719
5850
|
// Custom inspect for Node.js console.log
|
|
5720
5851
|
[/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")]() {
|
|
@@ -7762,6 +7893,7 @@ function initDataset(projectOrOptions, optionalOptions) {
|
|
|
7762
7893
|
const {
|
|
7763
7894
|
project,
|
|
7764
7895
|
dataset,
|
|
7896
|
+
datasetId,
|
|
7765
7897
|
description,
|
|
7766
7898
|
version,
|
|
7767
7899
|
snapshotName,
|
|
@@ -7777,6 +7909,11 @@ function initDataset(projectOrOptions, optionalOptions) {
|
|
|
7777
7909
|
state: stateArg,
|
|
7778
7910
|
_internal_btql
|
|
7779
7911
|
} = options;
|
|
7912
|
+
if (datasetId !== void 0 && (description !== void 0 || metadata !== void 0)) {
|
|
7913
|
+
throw new Error(
|
|
7914
|
+
"Cannot specify description or metadata when datasetId is provided"
|
|
7915
|
+
);
|
|
7916
|
+
}
|
|
7780
7917
|
const selection = normalizeDatasetSelection({
|
|
7781
7918
|
version,
|
|
7782
7919
|
environment,
|
|
@@ -7797,6 +7934,35 @@ function initDataset(projectOrOptions, optionalOptions) {
|
|
|
7797
7934
|
fetch: fetch2,
|
|
7798
7935
|
forceLogin
|
|
7799
7936
|
});
|
|
7937
|
+
if (datasetId !== void 0) {
|
|
7938
|
+
const objectInfo = datasetObjectInfoSchema.array().parse(
|
|
7939
|
+
await state.appConn().post_json("api/self/get_object_info", {
|
|
7940
|
+
object_type: "dataset",
|
|
7941
|
+
object_ids: [datasetId]
|
|
7942
|
+
})
|
|
7943
|
+
);
|
|
7944
|
+
if (objectInfo.length === 0) {
|
|
7945
|
+
throw new Error(`Dataset with ID ${datasetId} not found`);
|
|
7946
|
+
}
|
|
7947
|
+
if (objectInfo.length !== 1) {
|
|
7948
|
+
throw new Error(
|
|
7949
|
+
`Expected exactly one dataset with ID ${datasetId}, but found ${objectInfo.length}`
|
|
7950
|
+
);
|
|
7951
|
+
}
|
|
7952
|
+
const datasetInfo = objectInfo[0];
|
|
7953
|
+
return {
|
|
7954
|
+
project: {
|
|
7955
|
+
id: datasetInfo.parent_cols.project.id,
|
|
7956
|
+
name: datasetInfo.parent_cols.project.name,
|
|
7957
|
+
fullInfo: datasetInfo.parent_cols.project
|
|
7958
|
+
},
|
|
7959
|
+
dataset: {
|
|
7960
|
+
id: datasetInfo.object_id,
|
|
7961
|
+
name: datasetInfo.object_name,
|
|
7962
|
+
fullInfo: datasetInfo
|
|
7963
|
+
}
|
|
7964
|
+
};
|
|
7965
|
+
}
|
|
7800
7966
|
const args = {
|
|
7801
7967
|
org_id: state.orgId,
|
|
7802
7968
|
project_name: project,
|
|
@@ -7950,6 +8116,24 @@ function initLogger(options = {}) {
|
|
|
7950
8116
|
}
|
|
7951
8117
|
return ret;
|
|
7952
8118
|
}
|
|
8119
|
+
async function runCredentialScopedLoaderRequest(state, loginOptions, request) {
|
|
8120
|
+
const resolvedLoginOptions = await state._internalResolveLoaderLoginOptions(loginOptions);
|
|
8121
|
+
let cacheViews = state._internalGetLoaderCacheViews(resolvedLoginOptions);
|
|
8122
|
+
try {
|
|
8123
|
+
const requestState = await state._internalGetLoaderState(resolvedLoginOptions);
|
|
8124
|
+
cacheViews = state._internalGetLoaderCacheViews(
|
|
8125
|
+
resolvedLoginOptions,
|
|
8126
|
+
requestState
|
|
8127
|
+
);
|
|
8128
|
+
return {
|
|
8129
|
+
ok: true,
|
|
8130
|
+
response: await request(requestState),
|
|
8131
|
+
...cacheViews
|
|
8132
|
+
};
|
|
8133
|
+
} catch (error) {
|
|
8134
|
+
return { ok: false, error, ...cacheViews };
|
|
8135
|
+
}
|
|
8136
|
+
}
|
|
7953
8137
|
async function loadPrompt({
|
|
7954
8138
|
projectName,
|
|
7955
8139
|
projectId,
|
|
@@ -7974,43 +8158,47 @@ async function loadPrompt({
|
|
|
7974
8158
|
throw new Error("Must specify slug");
|
|
7975
8159
|
}
|
|
7976
8160
|
const state = stateArg ?? _globalState;
|
|
7977
|
-
|
|
7978
|
-
|
|
7979
|
-
|
|
7980
|
-
|
|
7981
|
-
|
|
7982
|
-
|
|
7983
|
-
|
|
7984
|
-
|
|
7985
|
-
|
|
7986
|
-
|
|
7987
|
-
|
|
7988
|
-
|
|
7989
|
-
|
|
8161
|
+
const result = await runCredentialScopedLoaderRequest(
|
|
8162
|
+
state,
|
|
8163
|
+
{ orgName, apiKey, appUrl, fetch: fetch2, forceLogin },
|
|
8164
|
+
async (requestState) => {
|
|
8165
|
+
let response2;
|
|
8166
|
+
if (id) {
|
|
8167
|
+
response2 = await requestState.apiConn().get_json(`v1/prompt/${id}`, versionOrEnvironment);
|
|
8168
|
+
if (response2) {
|
|
8169
|
+
response2 = { objects: [response2] };
|
|
8170
|
+
}
|
|
8171
|
+
} else {
|
|
8172
|
+
response2 = await requestState.apiConn().get_json("v1/prompt", {
|
|
8173
|
+
project_name: projectName,
|
|
8174
|
+
project_id: projectId,
|
|
8175
|
+
slug,
|
|
8176
|
+
...versionOrEnvironment
|
|
8177
|
+
});
|
|
7990
8178
|
}
|
|
7991
|
-
|
|
7992
|
-
|
|
7993
|
-
|
|
7994
|
-
|
|
7995
|
-
|
|
7996
|
-
|
|
7997
|
-
|
|
8179
|
+
return response2;
|
|
8180
|
+
}
|
|
8181
|
+
);
|
|
8182
|
+
const { promptCache } = result;
|
|
8183
|
+
if (!result.ok) {
|
|
8184
|
+
const e = result.error;
|
|
8185
|
+
if (!isLoaderCacheFallbackError(e)) {
|
|
8186
|
+
throw e;
|
|
7998
8187
|
}
|
|
7999
|
-
} catch (e) {
|
|
8000
8188
|
if (version || environment) {
|
|
8001
8189
|
throw new Error(`Prompt not found with specified parameters: ${e}`);
|
|
8002
8190
|
}
|
|
8003
8191
|
debugLogger.forState(state).warn("Failed to load prompt, attempting to fall back to cache:", e);
|
|
8004
8192
|
let prompt2;
|
|
8005
8193
|
if (id) {
|
|
8006
|
-
prompt2 = await
|
|
8194
|
+
prompt2 = await promptCache.get({ id });
|
|
8007
8195
|
if (!prompt2) {
|
|
8008
8196
|
throw new Error(
|
|
8009
8197
|
`Prompt with id ${id} not found (not found on server or in local cache): ${e}`
|
|
8010
8198
|
);
|
|
8011
8199
|
}
|
|
8012
8200
|
} else {
|
|
8013
|
-
prompt2 = await
|
|
8201
|
+
prompt2 = await promptCache.get({
|
|
8014
8202
|
slug,
|
|
8015
8203
|
projectId,
|
|
8016
8204
|
projectName,
|
|
@@ -8026,6 +8214,7 @@ async function loadPrompt({
|
|
|
8026
8214
|
}
|
|
8027
8215
|
return prompt2;
|
|
8028
8216
|
}
|
|
8217
|
+
const { response } = result;
|
|
8029
8218
|
if (!("objects" in response) || response.objects.length === 0) {
|
|
8030
8219
|
if (id) {
|
|
8031
8220
|
throw new Error(`Prompt with id ${id} not found.`);
|
|
@@ -8049,9 +8238,9 @@ async function loadPrompt({
|
|
|
8049
8238
|
const prompt = new Prompt2(metadata, defaults || {}, noTrace);
|
|
8050
8239
|
try {
|
|
8051
8240
|
if (id) {
|
|
8052
|
-
await
|
|
8241
|
+
await promptCache.set({ id }, prompt);
|
|
8053
8242
|
} else if (slug) {
|
|
8054
|
-
await
|
|
8243
|
+
await promptCache.set(
|
|
8055
8244
|
{ slug, projectId, projectName, version: version ?? "latest" },
|
|
8056
8245
|
prompt
|
|
8057
8246
|
);
|
|
@@ -8083,46 +8272,50 @@ async function loadParameters({
|
|
|
8083
8272
|
throw new Error("Must specify slug");
|
|
8084
8273
|
}
|
|
8085
8274
|
const state = stateArg ?? _globalState;
|
|
8086
|
-
|
|
8087
|
-
|
|
8088
|
-
|
|
8089
|
-
|
|
8090
|
-
|
|
8091
|
-
|
|
8092
|
-
|
|
8093
|
-
|
|
8094
|
-
|
|
8095
|
-
|
|
8096
|
-
|
|
8097
|
-
|
|
8098
|
-
}
|
|
8099
|
-
|
|
8100
|
-
|
|
8275
|
+
const result = await runCredentialScopedLoaderRequest(
|
|
8276
|
+
state,
|
|
8277
|
+
{ orgName, apiKey, appUrl, fetch: fetch2, forceLogin },
|
|
8278
|
+
async (requestState) => {
|
|
8279
|
+
let response2;
|
|
8280
|
+
if (id) {
|
|
8281
|
+
response2 = await requestState.apiConn().get_json(`v1/function/${id}`, {
|
|
8282
|
+
...versionOrEnvironment
|
|
8283
|
+
});
|
|
8284
|
+
if (response2) {
|
|
8285
|
+
response2 = { objects: [response2] };
|
|
8286
|
+
}
|
|
8287
|
+
} else {
|
|
8288
|
+
response2 = await requestState.apiConn().get_json("v1/function", {
|
|
8289
|
+
project_name: projectName,
|
|
8290
|
+
project_id: projectId,
|
|
8291
|
+
slug,
|
|
8292
|
+
function_type: "parameters",
|
|
8293
|
+
...versionOrEnvironment
|
|
8294
|
+
});
|
|
8101
8295
|
}
|
|
8102
|
-
|
|
8103
|
-
|
|
8104
|
-
|
|
8105
|
-
|
|
8106
|
-
|
|
8107
|
-
|
|
8108
|
-
|
|
8109
|
-
|
|
8296
|
+
return response2;
|
|
8297
|
+
}
|
|
8298
|
+
);
|
|
8299
|
+
const { parametersCache } = result;
|
|
8300
|
+
if (!result.ok) {
|
|
8301
|
+
const e = result.error;
|
|
8302
|
+
if (!isLoaderCacheFallbackError(e)) {
|
|
8303
|
+
throw e;
|
|
8110
8304
|
}
|
|
8111
|
-
} catch (e) {
|
|
8112
8305
|
if (version || environment) {
|
|
8113
8306
|
throw new Error(`Parameters not found with specified parameters: ${e}`);
|
|
8114
8307
|
}
|
|
8115
8308
|
debugLogger.forState(state).warn("Failed to load parameters, attempting to fall back to cache:", e);
|
|
8116
8309
|
let parameters2;
|
|
8117
8310
|
if (id) {
|
|
8118
|
-
parameters2 = await
|
|
8311
|
+
parameters2 = await parametersCache.get({ id });
|
|
8119
8312
|
if (!parameters2) {
|
|
8120
8313
|
throw new Error(
|
|
8121
8314
|
`Parameters with id ${id} not found (not found on server or in local cache): ${e}`
|
|
8122
8315
|
);
|
|
8123
8316
|
}
|
|
8124
8317
|
} else {
|
|
8125
|
-
parameters2 = await
|
|
8318
|
+
parameters2 = await parametersCache.get({
|
|
8126
8319
|
slug,
|
|
8127
8320
|
projectId,
|
|
8128
8321
|
projectName,
|
|
@@ -8138,6 +8331,7 @@ async function loadParameters({
|
|
|
8138
8331
|
}
|
|
8139
8332
|
return parameters2;
|
|
8140
8333
|
}
|
|
8334
|
+
const { response } = result;
|
|
8141
8335
|
if (!("objects" in response) || response.objects.length === 0) {
|
|
8142
8336
|
if (id) {
|
|
8143
8337
|
throw new Error(`Parameters with id ${id} not found.`);
|
|
@@ -8161,9 +8355,9 @@ async function loadParameters({
|
|
|
8161
8355
|
const parameters = new RemoteEvalParameters(metadata);
|
|
8162
8356
|
try {
|
|
8163
8357
|
if (id) {
|
|
8164
|
-
await
|
|
8358
|
+
await parametersCache.set({ id }, parameters);
|
|
8165
8359
|
} else if (slug) {
|
|
8166
|
-
await
|
|
8360
|
+
await parametersCache.set(
|
|
8167
8361
|
{ slug, projectId, projectName, version: version ?? "latest" },
|
|
8168
8362
|
parameters
|
|
8169
8363
|
);
|
|
@@ -8204,6 +8398,52 @@ async function login(options = {}) {
|
|
|
8204
8398
|
await state.login(options);
|
|
8205
8399
|
return state;
|
|
8206
8400
|
}
|
|
8401
|
+
async function loginToLoaderRequestState({
|
|
8402
|
+
appUrl,
|
|
8403
|
+
apiKey,
|
|
8404
|
+
orgName,
|
|
8405
|
+
fetch: fetch2
|
|
8406
|
+
}) {
|
|
8407
|
+
let orgId;
|
|
8408
|
+
let apiUrl;
|
|
8409
|
+
if (apiKey === TEST_API_KEY) {
|
|
8410
|
+
orgId = "test-org-id";
|
|
8411
|
+
apiUrl = "https://braintrust.dev/fake-api-url";
|
|
8412
|
+
} else {
|
|
8413
|
+
let loginResponse;
|
|
8414
|
+
try {
|
|
8415
|
+
loginResponse = await fetch2(_urljoin(appUrl, `/api/apikey/login`), {
|
|
8416
|
+
method: "POST",
|
|
8417
|
+
headers: {
|
|
8418
|
+
"Content-Type": "application/json",
|
|
8419
|
+
Authorization: `Bearer ${apiKey}`
|
|
8420
|
+
}
|
|
8421
|
+
});
|
|
8422
|
+
} catch (error) {
|
|
8423
|
+
throw new HTTPTransportError(error);
|
|
8424
|
+
}
|
|
8425
|
+
const info = await readJSONResponse(
|
|
8426
|
+
await checkResponse(loginResponse),
|
|
8427
|
+
true
|
|
8428
|
+
);
|
|
8429
|
+
const org = selectLoginOrg(info.org_info, orgName);
|
|
8430
|
+
orgId = org.id;
|
|
8431
|
+
apiUrl = isomorph_default.getEnv("BRAINTRUST_API_URL") ?? org.api_url;
|
|
8432
|
+
if (!apiUrl) {
|
|
8433
|
+
throw new Error(
|
|
8434
|
+
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."
|
|
8435
|
+
);
|
|
8436
|
+
}
|
|
8437
|
+
}
|
|
8438
|
+
const apiConnection = new HTTPConnection(apiUrl, fetch2, true);
|
|
8439
|
+
apiConnection.set_token(apiKey);
|
|
8440
|
+
apiConnection.make_long_lived();
|
|
8441
|
+
return {
|
|
8442
|
+
appUrl,
|
|
8443
|
+
orgId,
|
|
8444
|
+
apiConn: () => apiConnection
|
|
8445
|
+
};
|
|
8446
|
+
}
|
|
8207
8447
|
async function loginToState(options = {}) {
|
|
8208
8448
|
const {
|
|
8209
8449
|
appUrl = isomorph_default.getEnv("BRAINTRUST_APP_URL") || "https://www.braintrust.dev",
|
|
@@ -8235,16 +8475,18 @@ async function loginToState(options = {}) {
|
|
|
8235
8475
|
_saveOrgInfo(state, testOrgInfo, testOrgInfo[0].name);
|
|
8236
8476
|
return state;
|
|
8237
8477
|
} else {
|
|
8238
|
-
const
|
|
8239
|
-
|
|
8478
|
+
const loginResponse = await fetch2(
|
|
8479
|
+
_urljoin(state.appUrl, `/api/apikey/login`),
|
|
8480
|
+
{
|
|
8240
8481
|
method: "POST",
|
|
8241
8482
|
headers: {
|
|
8242
8483
|
"Content-Type": "application/json",
|
|
8243
8484
|
Authorization: `Bearer ${apiKey}`
|
|
8244
8485
|
}
|
|
8245
|
-
}
|
|
8486
|
+
}
|
|
8246
8487
|
);
|
|
8247
|
-
const
|
|
8488
|
+
const resp = await checkResponse(loginResponse);
|
|
8489
|
+
const info = await readJSONResponse(resp);
|
|
8248
8490
|
_saveOrgInfo(state, info.org_info, orgName);
|
|
8249
8491
|
if (!state.apiUrl) {
|
|
8250
8492
|
if (orgName) {
|
|
@@ -8747,11 +8989,11 @@ function wrapTraced(fn, args) {
|
|
|
8747
8989
|
}
|
|
8748
8990
|
if (args?.asyncFlush) {
|
|
8749
8991
|
return ((...fnArgs) => traced((span) => {
|
|
8750
|
-
if (!hasExplicitInput) {
|
|
8992
|
+
if (!args?.noTraceIO && !hasExplicitInput) {
|
|
8751
8993
|
span.log({ input: fnArgs });
|
|
8752
8994
|
}
|
|
8753
8995
|
const output = fn(...fnArgs);
|
|
8754
|
-
if (!hasExplicitOutput) {
|
|
8996
|
+
if (!args?.noTraceIO && !hasExplicitOutput) {
|
|
8755
8997
|
if (output instanceof Promise) {
|
|
8756
8998
|
return (async () => {
|
|
8757
8999
|
const result = await output;
|
|
@@ -8766,12 +9008,12 @@ function wrapTraced(fn, args) {
|
|
|
8766
9008
|
}, spanArgs));
|
|
8767
9009
|
} else {
|
|
8768
9010
|
return ((...fnArgs) => traced(async (span) => {
|
|
8769
|
-
if (!hasExplicitInput) {
|
|
9011
|
+
if (!args?.noTraceIO && !hasExplicitInput) {
|
|
8770
9012
|
span.log({ input: fnArgs });
|
|
8771
9013
|
}
|
|
8772
9014
|
const outputResult = fn(...fnArgs);
|
|
8773
9015
|
const output = await outputResult;
|
|
8774
|
-
if (!hasExplicitOutput) {
|
|
9016
|
+
if (!args?.noTraceIO && !hasExplicitOutput) {
|
|
8775
9017
|
span.log({ output });
|
|
8776
9018
|
}
|
|
8777
9019
|
return output;
|
|
@@ -8788,6 +9030,15 @@ function _internalStartSpanWithInitialMerge(args) {
|
|
|
8788
9030
|
[INITIAL_SPAN_WRITE_AS_MERGE]: true
|
|
8789
9031
|
}).span;
|
|
8790
9032
|
}
|
|
9033
|
+
function _internalStartSpanWithInitialMergeAndParentSpanIds(args) {
|
|
9034
|
+
return startSpanAndIsLogger(
|
|
9035
|
+
{
|
|
9036
|
+
...args,
|
|
9037
|
+
[INITIAL_SPAN_WRITE_AS_MERGE]: true
|
|
9038
|
+
},
|
|
9039
|
+
{ useParentSpanIdsForObjectParent: true }
|
|
9040
|
+
).span;
|
|
9041
|
+
}
|
|
8791
9042
|
function _internalStartSpanWithContext(args, context) {
|
|
8792
9043
|
return startSpanAndIsLogger({
|
|
8793
9044
|
...args,
|
|
@@ -8801,7 +9052,7 @@ async function flush(options) {
|
|
|
8801
9052
|
function setFetch(fetch2) {
|
|
8802
9053
|
_internalGetGlobalState().setFetch(fetch2);
|
|
8803
9054
|
}
|
|
8804
|
-
function startSpanAndIsLogger(args) {
|
|
9055
|
+
function startSpanAndIsLogger(args, internalOptions) {
|
|
8805
9056
|
const state = args?.state ?? _globalState;
|
|
8806
9057
|
const { parentObject, propagatedState } = getSpanParentObjectAndPropagatedState({
|
|
8807
9058
|
asyncFlush: args?.asyncFlush,
|
|
@@ -8815,7 +9066,7 @@ function startSpanAndIsLogger(args) {
|
|
|
8815
9066
|
) ? {
|
|
8816
9067
|
spanId: parentObject.data.span_id,
|
|
8817
9068
|
rootSpanId: parentObject.data.root_span_id
|
|
8818
|
-
} : void 0;
|
|
9069
|
+
} : internalOptions?.useParentSpanIdsForObjectParent ? args?.parentSpanIds : void 0;
|
|
8819
9070
|
const { parent: _ignoredParent, ...spanArgs } = args ?? {};
|
|
8820
9071
|
const span = new SpanImpl({
|
|
8821
9072
|
state,
|
|
@@ -8897,27 +9148,28 @@ async function* asyncGeneratorWithCurrent(span, gen, state = void 0) {
|
|
|
8897
9148
|
function withParent(parent, callback, state = void 0) {
|
|
8898
9149
|
return (state ?? _globalState).currentParent.run(parent, () => callback());
|
|
8899
9150
|
}
|
|
8900
|
-
function _saveOrgInfo(state,
|
|
8901
|
-
|
|
9151
|
+
function _saveOrgInfo(state, orgInfo, orgName) {
|
|
9152
|
+
const org = selectLoginOrg(orgInfo, orgName);
|
|
9153
|
+
state.orgId = org.id;
|
|
9154
|
+
state.orgName = org.name;
|
|
9155
|
+
state.apiUrl = isomorph_default.getEnv("BRAINTRUST_API_URL") ?? org.api_url;
|
|
9156
|
+
state.proxyUrl = isomorph_default.getEnv("BRAINTRUST_PROXY_URL") ?? org.proxy_url;
|
|
9157
|
+
state.gitMetadataSettings = org.git_metadata || void 0;
|
|
9158
|
+
}
|
|
9159
|
+
function selectLoginOrg(orgInfo, orgName) {
|
|
9160
|
+
if (orgInfo.length === 0) {
|
|
8902
9161
|
throw new LoginInvalidOrgError(
|
|
8903
9162
|
"This user is not part of any organizations."
|
|
8904
9163
|
);
|
|
8905
9164
|
}
|
|
8906
|
-
for (const org of
|
|
8907
|
-
if (
|
|
8908
|
-
|
|
8909
|
-
state.orgName = org.name;
|
|
8910
|
-
state.apiUrl = isomorph_default.getEnv("BRAINTRUST_API_URL") ?? org.api_url;
|
|
8911
|
-
state.proxyUrl = isomorph_default.getEnv("BRAINTRUST_PROXY_URL") ?? org.proxy_url;
|
|
8912
|
-
state.gitMetadataSettings = org.git_metadata || void 0;
|
|
8913
|
-
break;
|
|
9165
|
+
for (const org of orgInfo) {
|
|
9166
|
+
if (orgName === void 0 || org.name === orgName) {
|
|
9167
|
+
return org;
|
|
8914
9168
|
}
|
|
8915
9169
|
}
|
|
8916
|
-
|
|
8917
|
-
|
|
8918
|
-
|
|
8919
|
-
);
|
|
8920
|
-
}
|
|
9170
|
+
throw new LoginInvalidOrgError(
|
|
9171
|
+
`Organization ${orgName} not found. Must be one of ${orgInfo.map((org) => org.name).join(", ")}`
|
|
9172
|
+
);
|
|
8921
9173
|
}
|
|
8922
9174
|
function validateTags(tags) {
|
|
8923
9175
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -10823,6 +11075,14 @@ var Prompt2 = class _Prompt {
|
|
|
10823
11075
|
static isPrompt(data) {
|
|
10824
11076
|
return typeof data === "object" && data !== null && "__braintrust_prompt_marker" in data;
|
|
10825
11077
|
}
|
|
11078
|
+
/** @internal */
|
|
11079
|
+
_internalSerializeForCache() {
|
|
11080
|
+
return {
|
|
11081
|
+
metadata: this.metadata,
|
|
11082
|
+
defaults: this.defaults,
|
|
11083
|
+
noTrace: this.noTrace
|
|
11084
|
+
};
|
|
11085
|
+
}
|
|
10826
11086
|
static fromPromptData(name, promptData) {
|
|
10827
11087
|
return new _Prompt(
|
|
10828
11088
|
{
|
|
@@ -10863,6 +11123,10 @@ var RemoteEvalParameters = class {
|
|
|
10863
11123
|
get data() {
|
|
10864
11124
|
return this.metadata.function_data.data ?? {};
|
|
10865
11125
|
}
|
|
11126
|
+
/** @internal */
|
|
11127
|
+
_internalSerializeForCache() {
|
|
11128
|
+
return { metadata: this.metadata };
|
|
11129
|
+
}
|
|
10866
11130
|
validate(data) {
|
|
10867
11131
|
if (typeof data !== "object" || data === null) {
|
|
10868
11132
|
return false;
|
|
@@ -11723,56 +11987,14 @@ function suppressionStore() {
|
|
|
11723
11987
|
autoInstrumentationSuppressionStore ??= isomorph_default.newAsyncLocalStorage();
|
|
11724
11988
|
return autoInstrumentationSuppressionStore;
|
|
11725
11989
|
}
|
|
11726
|
-
function currentFrames() {
|
|
11727
|
-
return suppressionStore().getStore()?.frames ?? [];
|
|
11728
|
-
}
|
|
11729
11990
|
function isAutoInstrumentationSuppressed() {
|
|
11730
|
-
|
|
11731
|
-
return frames[frames.length - 1]?.mode === "suppress";
|
|
11991
|
+
return suppressionStore().getStore() === true;
|
|
11732
11992
|
}
|
|
11733
11993
|
function runWithAutoInstrumentationSuppressed(callback) {
|
|
11734
|
-
|
|
11735
|
-
id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
|
|
11736
|
-
mode: "suppress"
|
|
11737
|
-
};
|
|
11738
|
-
return suppressionStore().run(
|
|
11739
|
-
{ frames: [...currentFrames(), frame] },
|
|
11740
|
-
callback
|
|
11741
|
-
);
|
|
11994
|
+
return suppressionStore().run(true, callback);
|
|
11742
11995
|
}
|
|
11743
|
-
function
|
|
11744
|
-
|
|
11745
|
-
if (!startChannel) {
|
|
11746
|
-
return void 0;
|
|
11747
|
-
}
|
|
11748
|
-
const store = suppressionStore();
|
|
11749
|
-
startChannel.bindStore(store, () => ({
|
|
11750
|
-
frames: [
|
|
11751
|
-
...currentFrames(),
|
|
11752
|
-
{
|
|
11753
|
-
id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-suppress"),
|
|
11754
|
-
mode: "suppress"
|
|
11755
|
-
}
|
|
11756
|
-
]
|
|
11757
|
-
}));
|
|
11758
|
-
return () => {
|
|
11759
|
-
startChannel.unbindStore(store);
|
|
11760
|
-
};
|
|
11761
|
-
}
|
|
11762
|
-
function enterAutoInstrumentationAllowed() {
|
|
11763
|
-
const frame = {
|
|
11764
|
-
id: /* @__PURE__ */ Symbol("braintrust.auto-instrumentation-allow"),
|
|
11765
|
-
mode: "allow"
|
|
11766
|
-
};
|
|
11767
|
-
suppressionStore().enterWith({
|
|
11768
|
-
frames: [...currentFrames(), frame]
|
|
11769
|
-
});
|
|
11770
|
-
return () => {
|
|
11771
|
-
const frames = currentFrames().filter(
|
|
11772
|
-
(candidate) => candidate.id !== frame.id
|
|
11773
|
-
);
|
|
11774
|
-
suppressionStore().enterWith(frames.length > 0 ? { frames } : void 0);
|
|
11775
|
-
};
|
|
11996
|
+
function runWithAutoInstrumentationAllowed(callback) {
|
|
11997
|
+
return suppressionStore().run(void 0, callback);
|
|
11776
11998
|
}
|
|
11777
11999
|
|
|
11778
12000
|
// src/instrumentation/core/channel-tracing.ts
|
|
@@ -13025,7 +13247,7 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
13025
13247
|
}
|
|
13026
13248
|
subscribeToAISDK() {
|
|
13027
13249
|
const denyOutputPaths = this.config.denyOutputPaths || DEFAULT_DENY_OUTPUT_PATHS;
|
|
13028
|
-
this.unsubscribers.push(
|
|
13250
|
+
this.unsubscribers.push(interceptAISDKV7TelemetryDispatcher());
|
|
13029
13251
|
this.unsubscribers.push(subscribeToHarnessAgentCreateSession());
|
|
13030
13252
|
this.unsubscribers.push(
|
|
13031
13253
|
subscribeToHarnessContinuation(
|
|
@@ -13053,6 +13275,18 @@ var AISDKPlugin = class extends BasePlugin {
|
|
|
13053
13275
|
aggregateChunks: aggregateAISDKChunks
|
|
13054
13276
|
})
|
|
13055
13277
|
);
|
|
13278
|
+
this.unsubscribers.push(
|
|
13279
|
+
traceAsyncChannel(aiSDKChannels.generateImage, {
|
|
13280
|
+
name: "generateImage",
|
|
13281
|
+
type: "llm" /* LLM */,
|
|
13282
|
+
extractInput: ([params], event) => prepareAISDKGenerateImageInput(params, event.self),
|
|
13283
|
+
extractOutput: (result, endEvent) => processAISDKGenerateImageOutput(
|
|
13284
|
+
result,
|
|
13285
|
+
resolveDenyOutputPaths(endEvent, denyOutputPaths)
|
|
13286
|
+
),
|
|
13287
|
+
extractMetrics: (result) => extractTokenMetrics(result)
|
|
13288
|
+
})
|
|
13289
|
+
);
|
|
13056
13290
|
this.unsubscribers.push(
|
|
13057
13291
|
traceStreamingChannel(aiSDKChannels.streamText, {
|
|
13058
13292
|
name: "streamText",
|
|
@@ -13542,26 +13776,29 @@ function subscribeToHarnessContinuation(continuationChannel, defaultDenyOutputPa
|
|
|
13542
13776
|
channel.unsubscribe(handlers);
|
|
13543
13777
|
};
|
|
13544
13778
|
}
|
|
13545
|
-
function
|
|
13546
|
-
const channel = aiSDKChannels.v7CreateTelemetryDispatcher.tracingChannel();
|
|
13779
|
+
function interceptAISDKV7TelemetryDispatcher() {
|
|
13547
13780
|
const telemetry = braintrustAISDKTelemetry();
|
|
13548
|
-
|
|
13549
|
-
|
|
13550
|
-
const
|
|
13551
|
-
|
|
13552
|
-
|
|
13781
|
+
return aiSDKChannels.v7CreateTelemetryDispatcher.intercept(
|
|
13782
|
+
(target, thisArg, args) => {
|
|
13783
|
+
const dispatcher = Reflect.apply(target, thisArg, args);
|
|
13784
|
+
const telemetryOptions = args[0]?.telemetry;
|
|
13785
|
+
if (telemetryOptions?.isEnabled !== false) {
|
|
13786
|
+
try {
|
|
13787
|
+
patchAISDKV7TelemetryDispatcher(
|
|
13788
|
+
dispatcher,
|
|
13789
|
+
telemetry,
|
|
13790
|
+
telemetryOptions
|
|
13791
|
+
);
|
|
13792
|
+
} catch (error) {
|
|
13793
|
+
debugLogger.error(
|
|
13794
|
+
"Error instrumenting AI SDK v7 telemetry dispatcher:",
|
|
13795
|
+
error
|
|
13796
|
+
);
|
|
13797
|
+
}
|
|
13553
13798
|
}
|
|
13554
|
-
|
|
13555
|
-
event.result,
|
|
13556
|
-
telemetry,
|
|
13557
|
-
telemetryOptions
|
|
13558
|
-
);
|
|
13799
|
+
return dispatcher;
|
|
13559
13800
|
}
|
|
13560
|
-
|
|
13561
|
-
channel.subscribe(handlers);
|
|
13562
|
-
return () => {
|
|
13563
|
-
channel.unsubscribe(handlers);
|
|
13564
|
-
};
|
|
13801
|
+
);
|
|
13565
13802
|
}
|
|
13566
13803
|
function patchAISDKV7TelemetryDispatcher(dispatcher, telemetry, telemetryOptions) {
|
|
13567
13804
|
if (!isObject(dispatcher)) {
|
|
@@ -13886,16 +14123,10 @@ var convertImageToAttachment = (image, explicitMimeType) => {
|
|
|
13886
14123
|
}
|
|
13887
14124
|
}
|
|
13888
14125
|
if (explicitMimeType) {
|
|
13889
|
-
|
|
14126
|
+
const blob = convertDataToBlob(image, explicitMimeType);
|
|
14127
|
+
if (blob) {
|
|
13890
14128
|
return new Attachment({
|
|
13891
|
-
data:
|
|
13892
|
-
filename: `image.${getExtensionFromMediaType(explicitMimeType)}`,
|
|
13893
|
-
contentType: explicitMimeType
|
|
13894
|
-
});
|
|
13895
|
-
}
|
|
13896
|
-
if (typeof Buffer !== "undefined" && Buffer.isBuffer(image)) {
|
|
13897
|
-
return new Attachment({
|
|
13898
|
-
data: new Blob([image], { type: explicitMimeType }),
|
|
14129
|
+
data: blob,
|
|
13899
14130
|
filename: `image.${getExtensionFromMediaType(explicitMimeType)}`,
|
|
13900
14131
|
contentType: explicitMimeType
|
|
13901
14132
|
});
|
|
@@ -13949,6 +14180,25 @@ var convertDataToAttachment = (data, mimeType, filename) => {
|
|
|
13949
14180
|
function processAISDKCallInput(params) {
|
|
13950
14181
|
return processInputAttachmentsSync(params);
|
|
13951
14182
|
}
|
|
14183
|
+
function processAISDKGenerateImageInput(params) {
|
|
14184
|
+
const prompt = params.prompt;
|
|
14185
|
+
if (!isObject(prompt) || Array.isArray(prompt)) {
|
|
14186
|
+
return processAISDKCallInput(params);
|
|
14187
|
+
}
|
|
14188
|
+
const processedPrompt = { ...prompt };
|
|
14189
|
+
if (Array.isArray(prompt.images)) {
|
|
14190
|
+
processedPrompt.images = prompt.images.map(
|
|
14191
|
+
(image) => convertImageToAttachment(image, "image/png") ?? image
|
|
14192
|
+
);
|
|
14193
|
+
}
|
|
14194
|
+
if (prompt.mask !== void 0) {
|
|
14195
|
+
processedPrompt.mask = convertImageToAttachment(prompt.mask, "image/png") ?? prompt.mask;
|
|
14196
|
+
}
|
|
14197
|
+
return processAISDKCallInput({
|
|
14198
|
+
...params,
|
|
14199
|
+
prompt: processedPrompt
|
|
14200
|
+
});
|
|
14201
|
+
}
|
|
13952
14202
|
function processAISDKWorkflowAgentCallInput(params) {
|
|
13953
14203
|
const processed = processAISDKCallInput(params);
|
|
13954
14204
|
return {
|
|
@@ -14087,6 +14337,12 @@ function prepareAISDKEmbedInput(params, self) {
|
|
|
14087
14337
|
metadata: extractMetadataFromEmbedParams(params, self)
|
|
14088
14338
|
};
|
|
14089
14339
|
}
|
|
14340
|
+
function prepareAISDKGenerateImageInput(params, self) {
|
|
14341
|
+
return {
|
|
14342
|
+
input: processAISDKGenerateImageInput(params).input,
|
|
14343
|
+
metadata: extractMetadataFromCallParams(params, self)
|
|
14344
|
+
};
|
|
14345
|
+
}
|
|
14090
14346
|
function prepareAISDKRerankInput(params, self) {
|
|
14091
14347
|
const { documents, query } = params;
|
|
14092
14348
|
return {
|
|
@@ -15462,6 +15718,57 @@ function processAISDKOutput(output, denyOutputPaths) {
|
|
|
15462
15718
|
}
|
|
15463
15719
|
return normalizeAISDKLoggedOutput(sanitized);
|
|
15464
15720
|
}
|
|
15721
|
+
function processAISDKGenerateImageOutput(output, denyOutputPaths) {
|
|
15722
|
+
if (!output || typeof output !== "object") {
|
|
15723
|
+
return output;
|
|
15724
|
+
}
|
|
15725
|
+
const summarized = {};
|
|
15726
|
+
for (const field of [
|
|
15727
|
+
"usage",
|
|
15728
|
+
"warnings",
|
|
15729
|
+
"providerMetadata",
|
|
15730
|
+
"experimental_providerMetadata",
|
|
15731
|
+
"responses"
|
|
15732
|
+
]) {
|
|
15733
|
+
const value = safeSerializableFieldRead(output, field);
|
|
15734
|
+
if (value !== void 0 && isSerializableOutputValue(value)) {
|
|
15735
|
+
summarized[field] = value;
|
|
15736
|
+
}
|
|
15737
|
+
}
|
|
15738
|
+
const images = safeSerializableFieldRead(output, "images");
|
|
15739
|
+
const image = safeSerializableFieldRead(output, "image");
|
|
15740
|
+
const generatedFiles = Array.isArray(images) && images.length > 0 ? images : image !== void 0 ? [image] : [];
|
|
15741
|
+
const loggedOutput = normalizeAISDKLoggedOutput(
|
|
15742
|
+
omit(summarized, denyOutputPaths)
|
|
15743
|
+
);
|
|
15744
|
+
if (generatedFiles.length > 0) {
|
|
15745
|
+
loggedOutput.images = generatedFiles.map(
|
|
15746
|
+
(file, index) => convertAISDKGeneratedFileToAttachment(file, index)
|
|
15747
|
+
);
|
|
15748
|
+
}
|
|
15749
|
+
return loggedOutput;
|
|
15750
|
+
}
|
|
15751
|
+
function convertAISDKGeneratedFileToAttachment(file, index) {
|
|
15752
|
+
if (!file || typeof file !== "object") {
|
|
15753
|
+
return file;
|
|
15754
|
+
}
|
|
15755
|
+
const generatedFile = file;
|
|
15756
|
+
const generatedMediaType = safeSerializableFieldRead(
|
|
15757
|
+
generatedFile,
|
|
15758
|
+
"mediaType"
|
|
15759
|
+
);
|
|
15760
|
+
const mediaType = typeof generatedMediaType === "string" ? generatedMediaType : "application/octet-stream";
|
|
15761
|
+
const data = safeSerializableFieldRead(generatedFile, "base64") ?? safeSerializableFieldRead(generatedFile, "uint8Array");
|
|
15762
|
+
const blob = convertDataToBlob(data, mediaType);
|
|
15763
|
+
if (blob) {
|
|
15764
|
+
return new Attachment({
|
|
15765
|
+
data: blob,
|
|
15766
|
+
filename: `generated_image_${index}.${getExtensionFromMediaType(mediaType)}`,
|
|
15767
|
+
contentType: mediaType
|
|
15768
|
+
});
|
|
15769
|
+
}
|
|
15770
|
+
return file;
|
|
15771
|
+
}
|
|
15465
15772
|
function processAISDKEmbeddingOutput(output, denyOutputPaths) {
|
|
15466
15773
|
if (!output || typeof output !== "object") {
|
|
15467
15774
|
return output;
|
|
@@ -15950,7 +16257,6 @@ function omit(obj, paths, deletePaths = []) {
|
|
|
15950
16257
|
function braintrustAISDKTelemetry() {
|
|
15951
16258
|
const operations = /* @__PURE__ */ new Map();
|
|
15952
16259
|
const operationKeysByCallId = /* @__PURE__ */ new Map();
|
|
15953
|
-
const workflowOperationKeyStore = isomorph_default.newAsyncLocalStorage();
|
|
15954
16260
|
const modelSpans = /* @__PURE__ */ new Map();
|
|
15955
16261
|
const objectSpans = /* @__PURE__ */ new Map();
|
|
15956
16262
|
const embedSpans = /* @__PURE__ */ new Map();
|
|
@@ -15993,9 +16299,6 @@ function braintrustAISDKTelemetry() {
|
|
|
15993
16299
|
return;
|
|
15994
16300
|
}
|
|
15995
16301
|
operations.delete(operationKey);
|
|
15996
|
-
if (workflowOperationKeyStore.getStore() === operationKey) {
|
|
15997
|
-
workflowOperationKeyStore.enterWith(void 0);
|
|
15998
|
-
}
|
|
15999
16302
|
const keys = operationKeysByCallId.get(state.callId);
|
|
16000
16303
|
if (!keys) {
|
|
16001
16304
|
return;
|
|
@@ -16043,14 +16346,7 @@ function braintrustAISDKTelemetry() {
|
|
|
16043
16346
|
return key;
|
|
16044
16347
|
}
|
|
16045
16348
|
}
|
|
16046
|
-
|
|
16047
|
-
if (workflowOperationKey && keys.includes(workflowOperationKey)) {
|
|
16048
|
-
return workflowOperationKey;
|
|
16049
|
-
}
|
|
16050
|
-
if (callId === "workflow-agent") {
|
|
16051
|
-
return void 0;
|
|
16052
|
-
}
|
|
16053
|
-
return mode === "finish" ? keys[0] : keys[keys.length - 1];
|
|
16349
|
+
return callId === "workflow-agent" || mode === "active" ? keys[keys.length - 1] : keys[0];
|
|
16054
16350
|
};
|
|
16055
16351
|
const operationKeyFromEvent = (event, mode = "active") => {
|
|
16056
16352
|
const explicit = explicitOperationKey(event);
|
|
@@ -16064,17 +16360,13 @@ function braintrustAISDKTelemetry() {
|
|
|
16064
16360
|
if (operationKey) {
|
|
16065
16361
|
return operationKey;
|
|
16066
16362
|
}
|
|
16067
|
-
const
|
|
16068
|
-
if (
|
|
16069
|
-
return
|
|
16363
|
+
const workflowAgentKeys2 = operationKeysByCallId.get("workflow-agent");
|
|
16364
|
+
if (workflowAgentKeys2?.length) {
|
|
16365
|
+
return workflowAgentKeys2[workflowAgentKeys2.length - 1];
|
|
16070
16366
|
}
|
|
16071
16367
|
return callId === "workflow-agent" ? void 0 : callId;
|
|
16072
16368
|
}
|
|
16073
16369
|
}
|
|
16074
|
-
const workflowOperationKey = workflowOperationKeyStore.getStore();
|
|
16075
|
-
if (workflowOperationKey && operations.has(workflowOperationKey)) {
|
|
16076
|
-
return workflowOperationKey;
|
|
16077
|
-
}
|
|
16078
16370
|
const wrapperSpan = currentWorkflowAgentWrapperSpan();
|
|
16079
16371
|
if (wrapperSpan?.spanId) {
|
|
16080
16372
|
for (const [operationKey, state] of operations) {
|
|
@@ -16084,8 +16376,8 @@ function braintrustAISDKTelemetry() {
|
|
|
16084
16376
|
}
|
|
16085
16377
|
}
|
|
16086
16378
|
const workflowAgentKeys = operationKeysByCallId.get("workflow-agent");
|
|
16087
|
-
if (workflowAgentKeys?.length
|
|
16088
|
-
return workflowAgentKeys[
|
|
16379
|
+
if (workflowAgentKeys?.length) {
|
|
16380
|
+
return workflowAgentKeys[workflowAgentKeys.length - 1];
|
|
16089
16381
|
}
|
|
16090
16382
|
if (operations.size === 1) {
|
|
16091
16383
|
return operations.keys().next().value;
|
|
@@ -16288,9 +16580,6 @@ function braintrustAISDKTelemetry() {
|
|
|
16288
16580
|
if (!ownsSpan) {
|
|
16289
16581
|
return;
|
|
16290
16582
|
}
|
|
16291
|
-
if (workflowAgent) {
|
|
16292
|
-
workflowOperationKeyStore.enterWith(operationKey);
|
|
16293
|
-
}
|
|
16294
16583
|
let metadata = metadataFromEvent(event);
|
|
16295
16584
|
const logPayload = { metadata };
|
|
16296
16585
|
const workflowAgentCallInput = workflowAgent ? operationInput(event, operationName) : void 0;
|
|
@@ -18284,12 +18573,14 @@ function getMetricsFromResponse(response) {
|
|
|
18284
18573
|
continue;
|
|
18285
18574
|
}
|
|
18286
18575
|
const inputTokenDetails = usageMetadata.input_token_details;
|
|
18576
|
+
const outputTokenDetails = usageMetadata.output_token_details;
|
|
18287
18577
|
return normalizeTokenMetrics({
|
|
18288
18578
|
total_tokens: usageMetadata.total_tokens,
|
|
18289
18579
|
prompt_tokens: usageMetadata.input_tokens,
|
|
18290
18580
|
completion_tokens: usageMetadata.output_tokens,
|
|
18291
18581
|
prompt_cache_creation_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_creation : void 0,
|
|
18292
|
-
prompt_cached_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_read : void 0
|
|
18582
|
+
prompt_cached_tokens: isRecord(inputTokenDetails) ? inputTokenDetails.cache_read : void 0,
|
|
18583
|
+
completion_reasoning_tokens: isRecord(outputTokenDetails) ? outputTokenDetails.reasoning : void 0
|
|
18293
18584
|
});
|
|
18294
18585
|
}
|
|
18295
18586
|
const llmOutput = response.llmOutput || {};
|
|
@@ -18311,23 +18602,659 @@ function isRecord(value) {
|
|
|
18311
18602
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
18312
18603
|
}
|
|
18313
18604
|
|
|
18605
|
+
// src/instrumentation/plugins/openai-span-data.ts
|
|
18606
|
+
var OPENAI_METADATA_KEYS = [
|
|
18607
|
+
"model",
|
|
18608
|
+
"temperature",
|
|
18609
|
+
"top_p",
|
|
18610
|
+
"max_tokens",
|
|
18611
|
+
"frequency_penalty",
|
|
18612
|
+
"presence_penalty",
|
|
18613
|
+
"stop",
|
|
18614
|
+
"response_format",
|
|
18615
|
+
"tools",
|
|
18616
|
+
"tool_choice",
|
|
18617
|
+
"parallel_tool_calls",
|
|
18618
|
+
"max_tool_calls"
|
|
18619
|
+
];
|
|
18620
|
+
function batchMetadata(params) {
|
|
18621
|
+
const metadata = { provider: "openai" };
|
|
18622
|
+
for (const key of OPENAI_METADATA_KEYS) {
|
|
18623
|
+
try {
|
|
18624
|
+
const value = Reflect.get(params, key);
|
|
18625
|
+
if (value !== void 0) {
|
|
18626
|
+
metadata[key] = value;
|
|
18627
|
+
}
|
|
18628
|
+
} catch {
|
|
18629
|
+
}
|
|
18630
|
+
}
|
|
18631
|
+
return metadata;
|
|
18632
|
+
}
|
|
18633
|
+
function extractOpenAIBatchInput(endpoint, params) {
|
|
18634
|
+
const input = endpoint === "/v1/chat/completions" ? params.messages : params.input;
|
|
18635
|
+
return {
|
|
18636
|
+
input: processInputAttachments(input),
|
|
18637
|
+
metadata: batchMetadata(params)
|
|
18638
|
+
};
|
|
18639
|
+
}
|
|
18640
|
+
function extractOpenAIChatInput(params) {
|
|
18641
|
+
const { messages, ...metadata } = params;
|
|
18642
|
+
return {
|
|
18643
|
+
input: processInputAttachments(messages),
|
|
18644
|
+
metadata: { ...metadata, provider: "openai" }
|
|
18645
|
+
};
|
|
18646
|
+
}
|
|
18647
|
+
function extractOpenAIResponsesInput(params) {
|
|
18648
|
+
const { input, ...metadata } = params;
|
|
18649
|
+
return {
|
|
18650
|
+
input: processInputAttachments(input),
|
|
18651
|
+
metadata: { ...metadata, provider: "openai" }
|
|
18652
|
+
};
|
|
18653
|
+
}
|
|
18654
|
+
function extractOpenAIResponsesMetadata(result) {
|
|
18655
|
+
if (!result) {
|
|
18656
|
+
return void 0;
|
|
18657
|
+
}
|
|
18658
|
+
const { output: _output, usage: _usage, ...metadata } = result;
|
|
18659
|
+
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
18660
|
+
}
|
|
18661
|
+
function processImagesInOutput(output) {
|
|
18662
|
+
if (Array.isArray(output)) {
|
|
18663
|
+
return output.map(processImagesInOutput);
|
|
18664
|
+
}
|
|
18665
|
+
if (isObject(output) && output.type === "image_generation_call" && typeof output.result === "string" && output.result) {
|
|
18666
|
+
const fileExtension = output.output_format || "png";
|
|
18667
|
+
const contentType = `image/${fileExtension}`;
|
|
18668
|
+
const baseFilename = typeof output.revised_prompt === "string" ? output.revised_prompt.slice(0, 50).replace(/[^a-zA-Z0-9]/g, "_") : "generated_image";
|
|
18669
|
+
let binaryString;
|
|
18670
|
+
try {
|
|
18671
|
+
binaryString = atob(output.result);
|
|
18672
|
+
} catch {
|
|
18673
|
+
return output;
|
|
18674
|
+
}
|
|
18675
|
+
const bytes = new Uint8Array(binaryString.length);
|
|
18676
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
18677
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
18678
|
+
}
|
|
18679
|
+
return {
|
|
18680
|
+
...output,
|
|
18681
|
+
result: new Attachment({
|
|
18682
|
+
data: new Blob([bytes], { type: contentType }),
|
|
18683
|
+
filename: `${baseFilename}.${fileExtension}`,
|
|
18684
|
+
contentType
|
|
18685
|
+
})
|
|
18686
|
+
};
|
|
18687
|
+
}
|
|
18688
|
+
return output;
|
|
18689
|
+
}
|
|
18690
|
+
|
|
18691
|
+
// src/instrumentation/plugins/openai-batch-instrumentation.ts
|
|
18692
|
+
var SUPPORTED_ENDPOINTS = /* @__PURE__ */ new Set(["/v1/chat/completions", "/v1/responses"]);
|
|
18693
|
+
var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
|
|
18694
|
+
"completed",
|
|
18695
|
+
"failed",
|
|
18696
|
+
"expired",
|
|
18697
|
+
"cancelled"
|
|
18698
|
+
]);
|
|
18699
|
+
var pendingBatchTraces = /* @__PURE__ */ new Map();
|
|
18700
|
+
function read(value, key) {
|
|
18701
|
+
if (!isObject(value)) {
|
|
18702
|
+
return void 0;
|
|
18703
|
+
}
|
|
18704
|
+
try {
|
|
18705
|
+
return Reflect.get(value, key);
|
|
18706
|
+
} catch {
|
|
18707
|
+
return void 0;
|
|
18708
|
+
}
|
|
18709
|
+
}
|
|
18710
|
+
function isBatchRecordIterable(value) {
|
|
18711
|
+
if (value === null || typeof value !== "object" && typeof value !== "function") {
|
|
18712
|
+
return false;
|
|
18713
|
+
}
|
|
18714
|
+
return typeof read(value, Symbol.iterator) === "function" || typeof read(value, Symbol.asyncIterator) === "function";
|
|
18715
|
+
}
|
|
18716
|
+
function validCustomId(value) {
|
|
18717
|
+
return typeof value === "string" && value.length > 0 && value.length <= 64;
|
|
18718
|
+
}
|
|
18719
|
+
function logBatchInstrumentationError(context, error) {
|
|
18720
|
+
debugLogger.debug(`OpenAI Batch instrumentation ${context}:`, error);
|
|
18721
|
+
}
|
|
18722
|
+
async function exportParent(parent) {
|
|
18723
|
+
if ("toStr" in parent && typeof parent.toStr === "function") {
|
|
18724
|
+
return parent.toStr();
|
|
18725
|
+
}
|
|
18726
|
+
if ("export" in parent && typeof parent.export === "function") {
|
|
18727
|
+
return await parent.export();
|
|
18728
|
+
}
|
|
18729
|
+
return void 0;
|
|
18730
|
+
}
|
|
18731
|
+
async function deterministicDigest(namespace, ...parts) {
|
|
18732
|
+
const encoded = new TextEncoder().encode(
|
|
18733
|
+
[namespace, ...parts].map((part) => `${part.length}:${part}`).join("\0")
|
|
18734
|
+
);
|
|
18735
|
+
return new Uint8Array(
|
|
18736
|
+
await globalThis.crypto.subtle.digest("SHA-256", encoded)
|
|
18737
|
+
);
|
|
18738
|
+
}
|
|
18739
|
+
function digestHex(bytes, length) {
|
|
18740
|
+
return Array.from(bytes.slice(0, length)).map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
18741
|
+
}
|
|
18742
|
+
function digestUuid(bytes) {
|
|
18743
|
+
const hex = digestHex(bytes, 16);
|
|
18744
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
18745
|
+
}
|
|
18746
|
+
async function batchSpanIds(inputFileId) {
|
|
18747
|
+
const [row, span, root] = await Promise.all([
|
|
18748
|
+
deterministicDigest("openai:batch:row", inputFileId),
|
|
18749
|
+
deterministicDigest("openai:batch:span", inputFileId),
|
|
18750
|
+
deterministicDigest("openai:batch:root", inputFileId)
|
|
18751
|
+
]);
|
|
18752
|
+
return {
|
|
18753
|
+
rowId: digestUuid(row),
|
|
18754
|
+
spanId: digestHex(span, 8),
|
|
18755
|
+
rootSpanId: digestHex(root, 16)
|
|
18756
|
+
};
|
|
18757
|
+
}
|
|
18758
|
+
async function childSpanIds(inputFileId, customId) {
|
|
18759
|
+
const [row, span] = await Promise.all([
|
|
18760
|
+
deterministicDigest("openai:batch:child:row", inputFileId, customId),
|
|
18761
|
+
deterministicDigest("openai:batch:child:span", inputFileId, customId)
|
|
18762
|
+
]);
|
|
18763
|
+
return { rowId: digestUuid(row), spanId: digestHex(span, 8) };
|
|
18764
|
+
}
|
|
18765
|
+
async function startBatchSpan(context) {
|
|
18766
|
+
const ids = await batchSpanIds(context.inputFileId);
|
|
18767
|
+
const parent = SpanComponentsV4.fromStr(context.parent);
|
|
18768
|
+
const hasParentSpan = Boolean(
|
|
18769
|
+
parent.data.row_id && parent.data.span_id && parent.data.root_span_id
|
|
18770
|
+
);
|
|
18771
|
+
return withCurrent(
|
|
18772
|
+
NOOP_SPAN,
|
|
18773
|
+
() => _internalStartSpanWithInitialMergeAndParentSpanIds(
|
|
18774
|
+
withSpanInstrumentationName(
|
|
18775
|
+
{
|
|
18776
|
+
name: "openai.batch",
|
|
18777
|
+
type: "task" /* TASK */,
|
|
18778
|
+
parent: context.parent,
|
|
18779
|
+
...!hasParentSpan ? {
|
|
18780
|
+
parentSpanIds: {
|
|
18781
|
+
parentSpanIds: [],
|
|
18782
|
+
rootSpanId: ids.rootSpanId
|
|
18783
|
+
}
|
|
18784
|
+
} : {},
|
|
18785
|
+
spanId: ids.spanId,
|
|
18786
|
+
startTime: context.taskStartTime,
|
|
18787
|
+
event: {
|
|
18788
|
+
id: ids.rowId,
|
|
18789
|
+
metadata: {
|
|
18790
|
+
endpoint: context.endpoint,
|
|
18791
|
+
input_file_id: context.inputFileId,
|
|
18792
|
+
provider: "openai"
|
|
18793
|
+
}
|
|
18794
|
+
}
|
|
18795
|
+
},
|
|
18796
|
+
INSTRUMENTATION_NAMES.OPENAI
|
|
18797
|
+
)
|
|
18798
|
+
)
|
|
18799
|
+
);
|
|
18800
|
+
}
|
|
18801
|
+
async function startBatchChild(context, taskParent, input) {
|
|
18802
|
+
const ids = await childSpanIds(context.inputFileId, input.customId);
|
|
18803
|
+
return withCurrent(
|
|
18804
|
+
NOOP_SPAN,
|
|
18805
|
+
() => _internalStartSpanWithInitialMerge(
|
|
18806
|
+
withSpanInstrumentationName(
|
|
18807
|
+
{
|
|
18808
|
+
name: context.endpoint === "/v1/chat/completions" ? "Chat Completion" : "openai.responses.create",
|
|
18809
|
+
type: "llm" /* LLM */,
|
|
18810
|
+
parent: taskParent,
|
|
18811
|
+
spanId: ids.spanId,
|
|
18812
|
+
startTime: context.childStartTime,
|
|
18813
|
+
event: {
|
|
18814
|
+
id: ids.rowId,
|
|
18815
|
+
...input.spanData?.input !== void 0 ? { input: input.spanData.input } : {},
|
|
18816
|
+
metadata: {
|
|
18817
|
+
...input.spanData?.metadata,
|
|
18818
|
+
custom_id: input.customId,
|
|
18819
|
+
provider: "openai"
|
|
18820
|
+
}
|
|
18821
|
+
}
|
|
18822
|
+
},
|
|
18823
|
+
INSTRUMENTATION_NAMES.OPENAI
|
|
18824
|
+
)
|
|
18825
|
+
)
|
|
18826
|
+
);
|
|
18827
|
+
}
|
|
18828
|
+
async function* jsonlRecords(file, onIssue = () => {
|
|
18829
|
+
}) {
|
|
18830
|
+
const resolvedFile = await file;
|
|
18831
|
+
if (typeof resolvedFile === "string") {
|
|
18832
|
+
for (const line of resolvedFile.split("\n")) {
|
|
18833
|
+
if (!line.trim()) {
|
|
18834
|
+
continue;
|
|
18835
|
+
}
|
|
18836
|
+
try {
|
|
18837
|
+
yield JSON.parse(line.replace(/\r$/, ""));
|
|
18838
|
+
} catch (error) {
|
|
18839
|
+
logBatchInstrumentationError("skipped malformed JSONL", error);
|
|
18840
|
+
onIssue(new Error("OpenAI Batch file contains malformed JSONL"));
|
|
18841
|
+
}
|
|
18842
|
+
}
|
|
18843
|
+
return;
|
|
18844
|
+
}
|
|
18845
|
+
const body = read(resolvedFile, "body");
|
|
18846
|
+
const getReader = read(body, "getReader");
|
|
18847
|
+
if (isObject(body) && typeof getReader === "function") {
|
|
18848
|
+
let reader;
|
|
18849
|
+
try {
|
|
18850
|
+
reader = Reflect.apply(getReader, body, []);
|
|
18851
|
+
const decoder = new TextDecoder();
|
|
18852
|
+
let pending = "";
|
|
18853
|
+
while (true) {
|
|
18854
|
+
const readChunk = read(reader, "read");
|
|
18855
|
+
if (typeof readChunk !== "function") {
|
|
18856
|
+
throw new Error("Response body stream has no read method");
|
|
18857
|
+
}
|
|
18858
|
+
const chunk = await Reflect.apply(readChunk, reader, []);
|
|
18859
|
+
if (!isObject(chunk)) {
|
|
18860
|
+
throw new Error("Response body stream returned an invalid chunk");
|
|
18861
|
+
}
|
|
18862
|
+
if (chunk.done === true) {
|
|
18863
|
+
pending += decoder.decode();
|
|
18864
|
+
break;
|
|
18865
|
+
}
|
|
18866
|
+
if (!(chunk.value instanceof Uint8Array)) {
|
|
18867
|
+
throw new Error("Response body stream returned a non-byte chunk");
|
|
18868
|
+
}
|
|
18869
|
+
pending += decoder.decode(chunk.value, { stream: true });
|
|
18870
|
+
let newline = pending.indexOf("\n");
|
|
18871
|
+
while (newline !== -1) {
|
|
18872
|
+
const line = pending.slice(0, newline).replace(/\r$/, "");
|
|
18873
|
+
pending = pending.slice(newline + 1);
|
|
18874
|
+
if (line.trim()) {
|
|
18875
|
+
try {
|
|
18876
|
+
yield JSON.parse(line);
|
|
18877
|
+
} catch (error) {
|
|
18878
|
+
logBatchInstrumentationError("skipped malformed JSONL", error);
|
|
18879
|
+
onIssue(new Error("OpenAI Batch file contains malformed JSONL"));
|
|
18880
|
+
}
|
|
18881
|
+
}
|
|
18882
|
+
newline = pending.indexOf("\n");
|
|
18883
|
+
}
|
|
18884
|
+
}
|
|
18885
|
+
if (pending.trim()) {
|
|
18886
|
+
try {
|
|
18887
|
+
yield JSON.parse(pending.replace(/\r$/, ""));
|
|
18888
|
+
} catch (error) {
|
|
18889
|
+
logBatchInstrumentationError("skipped malformed JSONL", error);
|
|
18890
|
+
onIssue(new Error("OpenAI Batch file contains malformed JSONL"));
|
|
18891
|
+
}
|
|
18892
|
+
}
|
|
18893
|
+
} catch (error) {
|
|
18894
|
+
logBatchInstrumentationError("could not read JSONL response body", error);
|
|
18895
|
+
onIssue(new Error("OpenAI Batch response body could not be read"));
|
|
18896
|
+
} finally {
|
|
18897
|
+
const releaseLock = read(reader, "releaseLock");
|
|
18898
|
+
if (typeof releaseLock === "function") {
|
|
18899
|
+
try {
|
|
18900
|
+
Reflect.apply(releaseLock, reader, []);
|
|
18901
|
+
} catch (error) {
|
|
18902
|
+
logBatchInstrumentationError(
|
|
18903
|
+
"could not release stream reader",
|
|
18904
|
+
error
|
|
18905
|
+
);
|
|
18906
|
+
}
|
|
18907
|
+
}
|
|
18908
|
+
}
|
|
18909
|
+
return;
|
|
18910
|
+
}
|
|
18911
|
+
if (isBatchRecordIterable(resolvedFile)) {
|
|
18912
|
+
for await (const record of resolvedFile) {
|
|
18913
|
+
yield record;
|
|
18914
|
+
}
|
|
18915
|
+
return;
|
|
18916
|
+
}
|
|
18917
|
+
logBatchInstrumentationError("skipped invalid JSONL source", resolvedFile);
|
|
18918
|
+
onIssue(new Error("OpenAI Batch file source is invalid"));
|
|
18919
|
+
}
|
|
18920
|
+
async function readBatchInputs(file) {
|
|
18921
|
+
const inputs = /* @__PURE__ */ new Map();
|
|
18922
|
+
const issues = [];
|
|
18923
|
+
let endpoint;
|
|
18924
|
+
try {
|
|
18925
|
+
for await (const value of jsonlRecords(
|
|
18926
|
+
file,
|
|
18927
|
+
(issue) => issues.push(issue)
|
|
18928
|
+
)) {
|
|
18929
|
+
const customId = read(value, "custom_id");
|
|
18930
|
+
const url = read(value, "url");
|
|
18931
|
+
const body = read(value, "body");
|
|
18932
|
+
if (!validCustomId(customId) || inputs.has(customId) || read(value, "method") !== "POST" || typeof url !== "string" || !SUPPORTED_ENDPOINTS.has(url) || endpoint !== void 0 && endpoint !== url || !isObject(body)) {
|
|
18933
|
+
issues.push(new Error("OpenAI Batch input contains an invalid record"));
|
|
18934
|
+
continue;
|
|
18935
|
+
}
|
|
18936
|
+
endpoint = url;
|
|
18937
|
+
let spanData;
|
|
18938
|
+
try {
|
|
18939
|
+
spanData = extractOpenAIBatchInput(url, body);
|
|
18940
|
+
} catch (error) {
|
|
18941
|
+
logBatchInstrumentationError("could not extract batch input", error);
|
|
18942
|
+
}
|
|
18943
|
+
inputs.set(customId, { customId, spanData });
|
|
18944
|
+
}
|
|
18945
|
+
} catch (error) {
|
|
18946
|
+
logBatchInstrumentationError("could not process input file", error);
|
|
18947
|
+
issues.push(new Error("OpenAI Batch input file could not be processed"));
|
|
18948
|
+
}
|
|
18949
|
+
if (!endpoint || inputs.size === 0) {
|
|
18950
|
+
issues.push(new Error("OpenAI Batch input contains no supported records"));
|
|
18951
|
+
}
|
|
18952
|
+
return { endpoint, inputs, issues };
|
|
18953
|
+
}
|
|
18954
|
+
async function writePendingSpans(trace, endTime) {
|
|
18955
|
+
const task = await startBatchSpan(trace.context);
|
|
18956
|
+
const taskParent = await task.export();
|
|
18957
|
+
for (const input of trace.inputs.values()) {
|
|
18958
|
+
try {
|
|
18959
|
+
const child = await startBatchChild(trace.context, taskParent, input);
|
|
18960
|
+
if (endTime !== void 0) {
|
|
18961
|
+
child.end({ endTime });
|
|
18962
|
+
}
|
|
18963
|
+
} catch (error) {
|
|
18964
|
+
logBatchInstrumentationError("could not write batch request span", error);
|
|
18965
|
+
}
|
|
18966
|
+
}
|
|
18967
|
+
if (endTime !== void 0) {
|
|
18968
|
+
if (trace.status && trace.status !== "completed") {
|
|
18969
|
+
task.log({ error: new Error(`OpenAI Batch ${trace.status}`) });
|
|
18970
|
+
}
|
|
18971
|
+
task.end({ endTime });
|
|
18972
|
+
}
|
|
18973
|
+
}
|
|
18974
|
+
var interceptOpenAIFilesCreateTraced = async (target, thisArg, args) => {
|
|
18975
|
+
const startTime = getCurrentUnixTimestamp();
|
|
18976
|
+
const inputPromise = readBatchInputs(args[0].inputFileContent);
|
|
18977
|
+
const parentPromise = exportParent(args[0].parent);
|
|
18978
|
+
const file = await Reflect.apply(target, thisArg, args);
|
|
18979
|
+
try {
|
|
18980
|
+
const inputFileId = read(file, "id");
|
|
18981
|
+
const [inputData, exportedParent2] = await Promise.all([
|
|
18982
|
+
inputPromise,
|
|
18983
|
+
parentPromise
|
|
18984
|
+
]);
|
|
18985
|
+
if (typeof inputFileId !== "string" || !exportedParent2 || !inputData.endpoint || inputData.issues.length > 0) {
|
|
18986
|
+
if (inputData.issues[0]) {
|
|
18987
|
+
logBatchInstrumentationError(
|
|
18988
|
+
"skipped invalid input file",
|
|
18989
|
+
inputData.issues[0]
|
|
18990
|
+
);
|
|
18991
|
+
}
|
|
18992
|
+
return file;
|
|
18993
|
+
}
|
|
18994
|
+
const trace = {
|
|
18995
|
+
context: {
|
|
18996
|
+
inputFileId,
|
|
18997
|
+
endpoint: inputData.endpoint,
|
|
18998
|
+
parent: exportedParent2,
|
|
18999
|
+
taskStartTime: startTime,
|
|
19000
|
+
childStartTime: startTime
|
|
19001
|
+
},
|
|
19002
|
+
inputs: inputData.inputs
|
|
19003
|
+
};
|
|
19004
|
+
pendingBatchTraces.set(inputFileId, trace);
|
|
19005
|
+
await writePendingSpans(trace);
|
|
19006
|
+
} catch (error) {
|
|
19007
|
+
logBatchInstrumentationError("could not start batch spans", error);
|
|
19008
|
+
}
|
|
19009
|
+
return file;
|
|
19010
|
+
};
|
|
19011
|
+
function validTimestamp(value) {
|
|
19012
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0;
|
|
19013
|
+
}
|
|
19014
|
+
function terminalEndTime(batch, startTime) {
|
|
19015
|
+
let timestamp;
|
|
19016
|
+
switch (batch.status) {
|
|
19017
|
+
case "completed":
|
|
19018
|
+
timestamp = batch.completed_at;
|
|
19019
|
+
break;
|
|
19020
|
+
case "failed":
|
|
19021
|
+
timestamp = batch.failed_at;
|
|
19022
|
+
break;
|
|
19023
|
+
case "expired":
|
|
19024
|
+
timestamp = batch.expired_at;
|
|
19025
|
+
break;
|
|
19026
|
+
default:
|
|
19027
|
+
timestamp = batch.cancelled_at;
|
|
19028
|
+
}
|
|
19029
|
+
return validTimestamp(timestamp) ? Math.max(timestamp, startTime) : Math.max(getCurrentUnixTimestamp(), startTime);
|
|
19030
|
+
}
|
|
19031
|
+
async function updateBatchTimestamps(batch) {
|
|
19032
|
+
const trace = pendingBatchTraces.get(batch.input_file_id);
|
|
19033
|
+
if (!trace || trace.context.endpoint !== batch.endpoint) {
|
|
19034
|
+
return;
|
|
19035
|
+
}
|
|
19036
|
+
if (validTimestamp(batch.created_at)) {
|
|
19037
|
+
trace.context.taskStartTime = batch.created_at;
|
|
19038
|
+
}
|
|
19039
|
+
trace.context.childStartTime = validTimestamp(batch.in_progress_at) ? Math.max(batch.in_progress_at, trace.context.taskStartTime) : trace.context.taskStartTime;
|
|
19040
|
+
trace.status = batch.status;
|
|
19041
|
+
if (TERMINAL_STATUSES.has(batch.status)) {
|
|
19042
|
+
trace.endTime = terminalEndTime(batch, trace.context.childStartTime);
|
|
19043
|
+
}
|
|
19044
|
+
await writePendingSpans(trace, trace.endTime);
|
|
19045
|
+
}
|
|
19046
|
+
var interceptOpenAIBatchesRetrieveTraced = (target, thisArg, args) => Promise.resolve(Reflect.apply(target, thisArg, args)).then(async (batch) => {
|
|
19047
|
+
try {
|
|
19048
|
+
await updateBatchTimestamps(batch);
|
|
19049
|
+
} catch (error) {
|
|
19050
|
+
logBatchInstrumentationError("could not update batch timestamps", error);
|
|
19051
|
+
}
|
|
19052
|
+
return batch;
|
|
19053
|
+
});
|
|
19054
|
+
function errorFromResult(result) {
|
|
19055
|
+
const error = read(result.value, "error");
|
|
19056
|
+
if (isObject(error)) {
|
|
19057
|
+
const message = read(error, "message");
|
|
19058
|
+
return new Error(
|
|
19059
|
+
typeof message === "string" ? message : "OpenAI Batch request failed"
|
|
19060
|
+
);
|
|
19061
|
+
}
|
|
19062
|
+
const response = read(result.value, "response");
|
|
19063
|
+
const statusCode = read(response, "status_code");
|
|
19064
|
+
if (result.source === "error" || typeof statusCode === "number" && (statusCode < 200 || statusCode >= 300)) {
|
|
19065
|
+
const message = read(read(read(response, "body"), "error"), "message");
|
|
19066
|
+
return new Error(
|
|
19067
|
+
typeof message === "string" ? message : "OpenAI Batch request failed"
|
|
19068
|
+
);
|
|
19069
|
+
}
|
|
19070
|
+
return void 0;
|
|
19071
|
+
}
|
|
19072
|
+
async function completeBatchResult(context, taskParent, endTime, input, result) {
|
|
19073
|
+
const child = await startBatchChild(context, taskParent, input);
|
|
19074
|
+
try {
|
|
19075
|
+
const resultError = errorFromResult(result);
|
|
19076
|
+
const responseBody = read(read(result.value, "response"), "body");
|
|
19077
|
+
if (resultError) {
|
|
19078
|
+
child.log({ error: resultError });
|
|
19079
|
+
} else if (isObject(responseBody)) {
|
|
19080
|
+
const model = read(responseBody, "model");
|
|
19081
|
+
child.log({
|
|
19082
|
+
output: context.endpoint === "/v1/chat/completions" ? read(responseBody, "choices") : processImagesInOutput(read(responseBody, "output")),
|
|
19083
|
+
...typeof model === "string" ? { metadata: { model } } : {},
|
|
19084
|
+
metrics: parseMetricsFromUsage(read(responseBody, "usage"))
|
|
19085
|
+
});
|
|
19086
|
+
} else {
|
|
19087
|
+
child.log({ error: new Error("OpenAI Batch response body is missing") });
|
|
19088
|
+
}
|
|
19089
|
+
} catch (error) {
|
|
19090
|
+
child.log({ error });
|
|
19091
|
+
} finally {
|
|
19092
|
+
child.end({ endTime });
|
|
19093
|
+
}
|
|
19094
|
+
}
|
|
19095
|
+
async function completeResultFile({
|
|
19096
|
+
context,
|
|
19097
|
+
endTime,
|
|
19098
|
+
file,
|
|
19099
|
+
inputs,
|
|
19100
|
+
issues,
|
|
19101
|
+
seen,
|
|
19102
|
+
source,
|
|
19103
|
+
taskParent
|
|
19104
|
+
}) {
|
|
19105
|
+
if (file === void 0) {
|
|
19106
|
+
return;
|
|
19107
|
+
}
|
|
19108
|
+
for await (const value of jsonlRecords(file, (issue) => issues.push(issue))) {
|
|
19109
|
+
const customId = read(value, "custom_id");
|
|
19110
|
+
if (!validCustomId(customId) || !isObject(value)) {
|
|
19111
|
+
issues.push(
|
|
19112
|
+
new Error("OpenAI Batch result is missing a valid custom_id")
|
|
19113
|
+
);
|
|
19114
|
+
continue;
|
|
19115
|
+
}
|
|
19116
|
+
if (seen.has(customId)) {
|
|
19117
|
+
issues.push(new Error("OpenAI Batch result contains a duplicate"));
|
|
19118
|
+
continue;
|
|
19119
|
+
}
|
|
19120
|
+
const input = inputs.get(customId);
|
|
19121
|
+
if (!input) {
|
|
19122
|
+
issues.push(
|
|
19123
|
+
new Error("OpenAI Batch result does not match an input record")
|
|
19124
|
+
);
|
|
19125
|
+
continue;
|
|
19126
|
+
}
|
|
19127
|
+
seen.add(customId);
|
|
19128
|
+
await completeBatchResult(context, taskParent, endTime, input, {
|
|
19129
|
+
value,
|
|
19130
|
+
source
|
|
19131
|
+
});
|
|
19132
|
+
}
|
|
19133
|
+
}
|
|
19134
|
+
function sameInputs(first, second) {
|
|
19135
|
+
return first.size === second.size && [...first.keys()].every((customId) => second.has(customId));
|
|
19136
|
+
}
|
|
19137
|
+
async function contextForCompletion(inputFileId, inputData) {
|
|
19138
|
+
if (!inputData.endpoint || inputData.issues.length > 0) {
|
|
19139
|
+
return void 0;
|
|
19140
|
+
}
|
|
19141
|
+
const existing = pendingBatchTraces.get(inputFileId);
|
|
19142
|
+
if (existing) {
|
|
19143
|
+
if (existing.context.endpoint !== inputData.endpoint || !sameInputs(existing.inputs, inputData.inputs)) {
|
|
19144
|
+
return void 0;
|
|
19145
|
+
}
|
|
19146
|
+
return { ...existing, inputs: inputData.inputs };
|
|
19147
|
+
}
|
|
19148
|
+
const parent = await exportParent(getSpanParentObject());
|
|
19149
|
+
if (!parent) {
|
|
19150
|
+
return void 0;
|
|
19151
|
+
}
|
|
19152
|
+
const startTime = getCurrentUnixTimestamp();
|
|
19153
|
+
return {
|
|
19154
|
+
context: {
|
|
19155
|
+
inputFileId,
|
|
19156
|
+
endpoint: inputData.endpoint,
|
|
19157
|
+
parent,
|
|
19158
|
+
taskStartTime: startTime,
|
|
19159
|
+
childStartTime: startTime
|
|
19160
|
+
},
|
|
19161
|
+
inputs: inputData.inputs
|
|
19162
|
+
};
|
|
19163
|
+
}
|
|
19164
|
+
async function completeBatch(args) {
|
|
19165
|
+
const inputData = await readBatchInputs(args.inputFileContent);
|
|
19166
|
+
const trace = await contextForCompletion(args.inputFileId, inputData);
|
|
19167
|
+
if (!trace) {
|
|
19168
|
+
logBatchInstrumentationError(
|
|
19169
|
+
"left batch spans pending",
|
|
19170
|
+
inputData.issues[0] ?? new Error("OpenAI Batch input does not match")
|
|
19171
|
+
);
|
|
19172
|
+
return;
|
|
19173
|
+
}
|
|
19174
|
+
const endTime = trace.endTime ?? getCurrentUnixTimestamp();
|
|
19175
|
+
const task = await startBatchSpan(trace.context);
|
|
19176
|
+
const taskParent = await task.export();
|
|
19177
|
+
const issues = [];
|
|
19178
|
+
const seen = /* @__PURE__ */ new Set();
|
|
19179
|
+
await Promise.all([
|
|
19180
|
+
completeResultFile({
|
|
19181
|
+
context: trace.context,
|
|
19182
|
+
endTime,
|
|
19183
|
+
file: args.outputFileContent,
|
|
19184
|
+
inputs: trace.inputs,
|
|
19185
|
+
issues,
|
|
19186
|
+
seen,
|
|
19187
|
+
source: "output",
|
|
19188
|
+
taskParent
|
|
19189
|
+
}),
|
|
19190
|
+
completeResultFile({
|
|
19191
|
+
context: trace.context,
|
|
19192
|
+
endTime,
|
|
19193
|
+
file: args.errorFileContent,
|
|
19194
|
+
inputs: trace.inputs,
|
|
19195
|
+
issues,
|
|
19196
|
+
seen,
|
|
19197
|
+
source: "error",
|
|
19198
|
+
taskParent
|
|
19199
|
+
})
|
|
19200
|
+
]);
|
|
19201
|
+
if (issues.length > 0) {
|
|
19202
|
+
logBatchInstrumentationError("left batch spans pending", issues[0]);
|
|
19203
|
+
return;
|
|
19204
|
+
}
|
|
19205
|
+
const missing = [...trace.inputs.values()].filter(
|
|
19206
|
+
({ customId }) => !seen.has(customId)
|
|
19207
|
+
);
|
|
19208
|
+
if (!trace.status || trace.status === "completed") {
|
|
19209
|
+
if (missing.length > 0) {
|
|
19210
|
+
logBatchInstrumentationError(
|
|
19211
|
+
"left batch spans pending",
|
|
19212
|
+
new Error("OpenAI Batch result files are incomplete")
|
|
19213
|
+
);
|
|
19214
|
+
return;
|
|
19215
|
+
}
|
|
19216
|
+
} else {
|
|
19217
|
+
for (const input of missing) {
|
|
19218
|
+
const child = await startBatchChild(trace.context, taskParent, input);
|
|
19219
|
+
child.log({ error: new Error(`OpenAI Batch ${trace.status}`) });
|
|
19220
|
+
child.end({ endTime });
|
|
19221
|
+
}
|
|
19222
|
+
task.log({ error: new Error(`OpenAI Batch ${trace.status}`) });
|
|
19223
|
+
}
|
|
19224
|
+
task.end({ endTime });
|
|
19225
|
+
pendingBatchTraces.delete(args.inputFileId);
|
|
19226
|
+
}
|
|
19227
|
+
var interceptOpenAIBatchTraceComplete = (target, thisArg, args) => Promise.resolve(Reflect.apply(target, thisArg, args)).then(async (result) => {
|
|
19228
|
+
try {
|
|
19229
|
+
await completeBatch(args[0]);
|
|
19230
|
+
} catch (error) {
|
|
19231
|
+
logBatchInstrumentationError("could not complete batch", error);
|
|
19232
|
+
}
|
|
19233
|
+
return result;
|
|
19234
|
+
});
|
|
19235
|
+
|
|
18314
19236
|
// src/instrumentation/plugins/openai-plugin.ts
|
|
18315
19237
|
var OpenAIPlugin = class extends BasePlugin {
|
|
18316
19238
|
constructor() {
|
|
18317
19239
|
super();
|
|
18318
19240
|
}
|
|
18319
19241
|
onEnable() {
|
|
19242
|
+
this.unsubscribers.push(
|
|
19243
|
+
openAIChannels.filesCreateTraced.intercept(
|
|
19244
|
+
interceptOpenAIFilesCreateTraced
|
|
19245
|
+
),
|
|
19246
|
+
openAIChannels.batchesRetrieveTraced.intercept(
|
|
19247
|
+
interceptOpenAIBatchesRetrieveTraced
|
|
19248
|
+
),
|
|
19249
|
+
openAIChannels.batchesCompleteTrace.intercept(
|
|
19250
|
+
interceptOpenAIBatchTraceComplete
|
|
19251
|
+
)
|
|
19252
|
+
);
|
|
18320
19253
|
this.unsubscribers.push(
|
|
18321
19254
|
traceStreamingChannel(openAIChannels.chatCompletionsCreate, {
|
|
18322
19255
|
name: "Chat Completion",
|
|
18323
19256
|
type: "llm" /* LLM */,
|
|
18324
|
-
extractInput: ([params]) =>
|
|
18325
|
-
const { messages, ...metadata } = params;
|
|
18326
|
-
return {
|
|
18327
|
-
input: processInputAttachments(messages),
|
|
18328
|
-
metadata: { ...metadata, provider: "openai" }
|
|
18329
|
-
};
|
|
18330
|
-
},
|
|
19257
|
+
extractInput: ([params]) => extractOpenAIChatInput(params),
|
|
18331
19258
|
extractOutput: (result) => {
|
|
18332
19259
|
return result?.choices;
|
|
18333
19260
|
},
|
|
@@ -18373,13 +19300,7 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
18373
19300
|
traceStreamingChannel(openAIChannels.betaChatCompletionsParse, {
|
|
18374
19301
|
name: "Chat Completion",
|
|
18375
19302
|
type: "llm" /* LLM */,
|
|
18376
|
-
extractInput: ([params]) =>
|
|
18377
|
-
const { messages, ...metadata } = params;
|
|
18378
|
-
return {
|
|
18379
|
-
input: processInputAttachments(messages),
|
|
18380
|
-
metadata: { ...metadata, provider: "openai" }
|
|
18381
|
-
};
|
|
18382
|
-
},
|
|
19303
|
+
extractInput: ([params]) => extractOpenAIChatInput(params),
|
|
18383
19304
|
extractOutput: (result) => {
|
|
18384
19305
|
return result?.choices;
|
|
18385
19306
|
},
|
|
@@ -18401,13 +19322,7 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
18401
19322
|
traceSyncStreamChannel(openAIChannels.betaChatCompletionsStream, {
|
|
18402
19323
|
name: "Chat Completion",
|
|
18403
19324
|
type: "llm" /* LLM */,
|
|
18404
|
-
extractInput: ([params]) =>
|
|
18405
|
-
const { messages, ...metadata } = params;
|
|
18406
|
-
return {
|
|
18407
|
-
input: processInputAttachments(messages),
|
|
18408
|
-
metadata: { ...metadata, provider: "openai" }
|
|
18409
|
-
};
|
|
18410
|
-
}
|
|
19325
|
+
extractInput: ([params]) => extractOpenAIChatInput(params)
|
|
18411
19326
|
})
|
|
18412
19327
|
);
|
|
18413
19328
|
this.unsubscribers.push(
|
|
@@ -18437,23 +19352,11 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
18437
19352
|
traceStreamingChannel(openAIChannels.responsesCreate, {
|
|
18438
19353
|
name: "openai.responses.create",
|
|
18439
19354
|
type: "llm" /* LLM */,
|
|
18440
|
-
extractInput: ([params]) =>
|
|
18441
|
-
const { input, ...metadata } = params;
|
|
18442
|
-
return {
|
|
18443
|
-
input: processInputAttachments(input),
|
|
18444
|
-
metadata: { ...metadata, provider: "openai" }
|
|
18445
|
-
};
|
|
18446
|
-
},
|
|
19355
|
+
extractInput: ([params]) => extractOpenAIResponsesInput(params),
|
|
18447
19356
|
extractOutput: (result) => {
|
|
18448
19357
|
return processImagesInOutput(result?.output);
|
|
18449
19358
|
},
|
|
18450
|
-
extractMetadata: (result) =>
|
|
18451
|
-
if (!result) {
|
|
18452
|
-
return void 0;
|
|
18453
|
-
}
|
|
18454
|
-
const { output: _output, usage: _usage, ...metadata } = result;
|
|
18455
|
-
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
18456
|
-
},
|
|
19359
|
+
extractMetadata: (result) => extractOpenAIResponsesMetadata(result),
|
|
18457
19360
|
extractMetrics: (result, startTime, endEvent) => {
|
|
18458
19361
|
const metrics = withCachedMetric(
|
|
18459
19362
|
parseMetricsFromUsage(result?.usage),
|
|
@@ -18472,13 +19375,7 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
18472
19375
|
traceSyncStreamChannel(openAIChannels.responsesStream, {
|
|
18473
19376
|
name: "openai.responses.create",
|
|
18474
19377
|
type: "llm" /* LLM */,
|
|
18475
|
-
extractInput: ([params]) =>
|
|
18476
|
-
const { input, ...metadata } = params;
|
|
18477
|
-
return {
|
|
18478
|
-
input: processInputAttachments(input),
|
|
18479
|
-
metadata: { ...metadata, provider: "openai" }
|
|
18480
|
-
};
|
|
18481
|
-
},
|
|
19378
|
+
extractInput: ([params]) => extractOpenAIResponsesInput(params),
|
|
18482
19379
|
extractFromEvent: (event) => {
|
|
18483
19380
|
if (event.type !== "response.completed" || !event.response) {
|
|
18484
19381
|
return {};
|
|
@@ -18501,23 +19398,11 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
18501
19398
|
traceStreamingChannel(openAIChannels.responsesParse, {
|
|
18502
19399
|
name: "openai.responses.parse",
|
|
18503
19400
|
type: "llm" /* LLM */,
|
|
18504
|
-
extractInput: ([params]) =>
|
|
18505
|
-
const { input, ...metadata } = params;
|
|
18506
|
-
return {
|
|
18507
|
-
input: processInputAttachments(input),
|
|
18508
|
-
metadata: { ...metadata, provider: "openai" }
|
|
18509
|
-
};
|
|
18510
|
-
},
|
|
19401
|
+
extractInput: ([params]) => extractOpenAIResponsesInput(params),
|
|
18511
19402
|
extractOutput: (result) => {
|
|
18512
19403
|
return processImagesInOutput(result?.output);
|
|
18513
19404
|
},
|
|
18514
|
-
extractMetadata: (result) =>
|
|
18515
|
-
if (!result) {
|
|
18516
|
-
return void 0;
|
|
18517
|
-
}
|
|
18518
|
-
const { output: _output, usage: _usage, ...metadata } = result;
|
|
18519
|
-
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
18520
|
-
},
|
|
19405
|
+
extractMetadata: (result) => extractOpenAIResponsesMetadata(result),
|
|
18521
19406
|
extractMetrics: (result, startTime, endEvent) => {
|
|
18522
19407
|
const metrics = withCachedMetric(
|
|
18523
19408
|
parseMetricsFromUsage(result?.usage),
|
|
@@ -18536,23 +19421,11 @@ var OpenAIPlugin = class extends BasePlugin {
|
|
|
18536
19421
|
traceAsyncChannel(openAIChannels.responsesCompact, {
|
|
18537
19422
|
name: "openai.responses.compact",
|
|
18538
19423
|
type: "llm" /* LLM */,
|
|
18539
|
-
extractInput: ([params]) =>
|
|
18540
|
-
const { input, ...metadata } = params;
|
|
18541
|
-
return {
|
|
18542
|
-
input: processInputAttachments(input),
|
|
18543
|
-
metadata: { ...metadata, provider: "openai" }
|
|
18544
|
-
};
|
|
18545
|
-
},
|
|
19424
|
+
extractInput: ([params]) => extractOpenAIResponsesInput(params),
|
|
18546
19425
|
extractOutput: (result) => {
|
|
18547
19426
|
return processImagesInOutput(result?.output);
|
|
18548
19427
|
},
|
|
18549
|
-
extractMetadata: (result) =>
|
|
18550
|
-
if (!result) {
|
|
18551
|
-
return void 0;
|
|
18552
|
-
}
|
|
18553
|
-
const { output: _output, usage: _usage, ...metadata } = result;
|
|
18554
|
-
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
18555
|
-
},
|
|
19428
|
+
extractMetadata: (result) => extractOpenAIResponsesMetadata(result),
|
|
18556
19429
|
extractMetrics: (result, startTime, endEvent) => {
|
|
18557
19430
|
const metrics = withCachedMetric(
|
|
18558
19431
|
parseMetricsFromUsage(result?.usage),
|
|
@@ -18608,35 +19481,6 @@ function withCachedMetric(metrics, result, endEvent) {
|
|
|
18608
19481
|
cached
|
|
18609
19482
|
};
|
|
18610
19483
|
}
|
|
18611
|
-
function processImagesInOutput(output) {
|
|
18612
|
-
if (Array.isArray(output)) {
|
|
18613
|
-
return output.map(processImagesInOutput);
|
|
18614
|
-
}
|
|
18615
|
-
if (isObject(output)) {
|
|
18616
|
-
if (output.type === "image_generation_call" && output.result && typeof output.result === "string") {
|
|
18617
|
-
const fileExtension = output.output_format || "png";
|
|
18618
|
-
const contentType = `image/${fileExtension}`;
|
|
18619
|
-
const baseFilename = output.revised_prompt && typeof output.revised_prompt === "string" ? output.revised_prompt.slice(0, 50).replace(/[^a-zA-Z0-9]/g, "_") : "generated_image";
|
|
18620
|
-
const filename = `${baseFilename}.${fileExtension}`;
|
|
18621
|
-
const binaryString = atob(output.result);
|
|
18622
|
-
const bytes = new Uint8Array(binaryString.length);
|
|
18623
|
-
for (let i = 0; i < binaryString.length; i++) {
|
|
18624
|
-
bytes[i] = binaryString.charCodeAt(i);
|
|
18625
|
-
}
|
|
18626
|
-
const blob = new Blob([bytes], { type: contentType });
|
|
18627
|
-
const attachment = new Attachment({
|
|
18628
|
-
data: blob,
|
|
18629
|
-
filename,
|
|
18630
|
-
contentType
|
|
18631
|
-
});
|
|
18632
|
-
return {
|
|
18633
|
-
...output,
|
|
18634
|
-
result: attachment
|
|
18635
|
-
};
|
|
18636
|
-
}
|
|
18637
|
-
}
|
|
18638
|
-
return output;
|
|
18639
|
-
}
|
|
18640
19484
|
function mergeLogprobTokens(existing, incoming) {
|
|
18641
19485
|
if (incoming === void 0) {
|
|
18642
19486
|
return existing;
|
|
@@ -18667,13 +19511,33 @@ function aggregateChatLogprobs(existing, incoming) {
|
|
|
18667
19511
|
}
|
|
18668
19512
|
return aggregated;
|
|
18669
19513
|
}
|
|
19514
|
+
function createAggregatedChatChoice(index) {
|
|
19515
|
+
return {
|
|
19516
|
+
index,
|
|
19517
|
+
role: void 0,
|
|
19518
|
+
content: void 0,
|
|
19519
|
+
refusal: void 0,
|
|
19520
|
+
toolCallsByIndex: /* @__PURE__ */ new Map(),
|
|
19521
|
+
logprobs: void 0,
|
|
19522
|
+
finish_reason: void 0
|
|
19523
|
+
};
|
|
19524
|
+
}
|
|
19525
|
+
function toChatChoice(choice) {
|
|
19526
|
+
const toolCalls = Array.from(choice.toolCallsByIndex.entries()).sort(([left], [right]) => left - right).map(([, toolCall]) => toolCall);
|
|
19527
|
+
return {
|
|
19528
|
+
index: choice.index,
|
|
19529
|
+
message: {
|
|
19530
|
+
role: choice.role,
|
|
19531
|
+
content: choice.content,
|
|
19532
|
+
...choice.refusal !== void 0 ? { refusal: choice.refusal } : {},
|
|
19533
|
+
tool_calls: toolCalls.length > 0 ? toolCalls : void 0
|
|
19534
|
+
},
|
|
19535
|
+
logprobs: choice.logprobs ?? null,
|
|
19536
|
+
finish_reason: choice.finish_reason
|
|
19537
|
+
};
|
|
19538
|
+
}
|
|
18670
19539
|
function aggregateChatCompletionChunks(chunks, streamResult, endEvent) {
|
|
18671
|
-
|
|
18672
|
-
let content = void 0;
|
|
18673
|
-
let refusal = void 0;
|
|
18674
|
-
let tool_calls = void 0;
|
|
18675
|
-
let logprobs = void 0;
|
|
18676
|
-
let finish_reason = void 0;
|
|
19540
|
+
const choicesByIndex = /* @__PURE__ */ new Map();
|
|
18677
19541
|
let metrics = {};
|
|
18678
19542
|
for (const chunk of chunks) {
|
|
18679
19543
|
if (chunk.usage) {
|
|
@@ -18682,62 +19546,75 @@ function aggregateChatCompletionChunks(chunks, streamResult, endEvent) {
|
|
|
18682
19546
|
...parseMetricsFromUsage(chunk.usage)
|
|
18683
19547
|
};
|
|
18684
19548
|
}
|
|
18685
|
-
const
|
|
18686
|
-
if (!
|
|
19549
|
+
const choices = chunk.choices;
|
|
19550
|
+
if (!choices?.length) {
|
|
18687
19551
|
continue;
|
|
18688
19552
|
}
|
|
18689
|
-
|
|
18690
|
-
|
|
18691
|
-
|
|
18692
|
-
|
|
18693
|
-
|
|
18694
|
-
|
|
18695
|
-
|
|
18696
|
-
|
|
18697
|
-
|
|
18698
|
-
|
|
18699
|
-
|
|
18700
|
-
|
|
18701
|
-
|
|
18702
|
-
|
|
18703
|
-
|
|
18704
|
-
|
|
18705
|
-
|
|
18706
|
-
|
|
18707
|
-
|
|
18708
|
-
|
|
18709
|
-
|
|
18710
|
-
|
|
18711
|
-
|
|
18712
|
-
|
|
18713
|
-
|
|
18714
|
-
|
|
18715
|
-
|
|
18716
|
-
|
|
18717
|
-
|
|
19553
|
+
for (const choice of choices) {
|
|
19554
|
+
const choiceIndex = choice.index;
|
|
19555
|
+
let aggregatedChoice = choicesByIndex.get(choiceIndex);
|
|
19556
|
+
if (!aggregatedChoice) {
|
|
19557
|
+
aggregatedChoice = createAggregatedChatChoice(choiceIndex);
|
|
19558
|
+
choicesByIndex.set(choiceIndex, aggregatedChoice);
|
|
19559
|
+
}
|
|
19560
|
+
if (choice.finish_reason) {
|
|
19561
|
+
aggregatedChoice.finish_reason = choice.finish_reason;
|
|
19562
|
+
}
|
|
19563
|
+
aggregatedChoice.logprobs = aggregateChatLogprobs(
|
|
19564
|
+
aggregatedChoice.logprobs,
|
|
19565
|
+
choice.logprobs
|
|
19566
|
+
);
|
|
19567
|
+
const delta = choice.delta;
|
|
19568
|
+
if (!delta) {
|
|
19569
|
+
continue;
|
|
19570
|
+
}
|
|
19571
|
+
if (delta.finish_reason) {
|
|
19572
|
+
aggregatedChoice.finish_reason = delta.finish_reason;
|
|
19573
|
+
}
|
|
19574
|
+
if (!aggregatedChoice.role && delta.role) {
|
|
19575
|
+
aggregatedChoice.role = delta.role;
|
|
19576
|
+
}
|
|
19577
|
+
if (delta.content) {
|
|
19578
|
+
aggregatedChoice.content = (aggregatedChoice.content || "") + delta.content;
|
|
19579
|
+
}
|
|
19580
|
+
if (delta.refusal) {
|
|
19581
|
+
aggregatedChoice.refusal = (aggregatedChoice.refusal || "") + delta.refusal;
|
|
19582
|
+
}
|
|
19583
|
+
if (delta.tool_calls) {
|
|
19584
|
+
for (const toolDelta of delta.tool_calls) {
|
|
19585
|
+
let aggregatedToolCall = aggregatedChoice.toolCallsByIndex.get(
|
|
19586
|
+
toolDelta.index
|
|
19587
|
+
);
|
|
19588
|
+
if (!aggregatedToolCall) {
|
|
19589
|
+
aggregatedToolCall = {
|
|
19590
|
+
function: { arguments: "" }
|
|
19591
|
+
};
|
|
19592
|
+
aggregatedChoice.toolCallsByIndex.set(
|
|
19593
|
+
toolDelta.index,
|
|
19594
|
+
aggregatedToolCall
|
|
19595
|
+
);
|
|
18718
19596
|
}
|
|
18719
|
-
|
|
18720
|
-
|
|
18721
|
-
|
|
19597
|
+
if (toolDelta.id !== void 0) {
|
|
19598
|
+
aggregatedToolCall.id = toolDelta.id;
|
|
19599
|
+
}
|
|
19600
|
+
if (toolDelta.type !== void 0) {
|
|
19601
|
+
aggregatedToolCall.type = toolDelta.type;
|
|
19602
|
+
}
|
|
19603
|
+
if (toolDelta.function?.name !== void 0) {
|
|
19604
|
+
aggregatedToolCall.function.name = toolDelta.function.name;
|
|
19605
|
+
}
|
|
19606
|
+
if (toolDelta.function?.arguments !== void 0) {
|
|
19607
|
+
aggregatedToolCall.function.arguments += toolDelta.function.arguments;
|
|
19608
|
+
}
|
|
19609
|
+
}
|
|
18722
19610
|
}
|
|
18723
19611
|
}
|
|
18724
19612
|
}
|
|
18725
19613
|
metrics = withCachedMetric(metrics, streamResult, endEvent);
|
|
19614
|
+
const output = Array.from(choicesByIndex.values()).sort((left, right) => left.index - right.index).map(toChatChoice);
|
|
18726
19615
|
return {
|
|
18727
19616
|
metrics,
|
|
18728
|
-
output: [
|
|
18729
|
-
{
|
|
18730
|
-
index: 0,
|
|
18731
|
-
message: {
|
|
18732
|
-
role,
|
|
18733
|
-
content,
|
|
18734
|
-
...refusal !== void 0 ? { refusal } : {},
|
|
18735
|
-
tool_calls
|
|
18736
|
-
},
|
|
18737
|
-
logprobs: logprobs ?? null,
|
|
18738
|
-
finish_reason
|
|
18739
|
-
}
|
|
18740
|
-
]
|
|
19617
|
+
output: output.length > 0 ? output : [toChatChoice(createAggregatedChatChoice(0))]
|
|
18741
19618
|
};
|
|
18742
19619
|
}
|
|
18743
19620
|
function aggregateResponseStreamEvents(chunks, _streamResult, endEvent) {
|
|
@@ -20010,6 +20887,12 @@ function parseMetricsFromUsage2(usage) {
|
|
|
20010
20887
|
}
|
|
20011
20888
|
}
|
|
20012
20889
|
}
|
|
20890
|
+
if (isObject(usage.output_tokens_details)) {
|
|
20891
|
+
const thinkingTokens = usage.output_tokens_details.thinking_tokens;
|
|
20892
|
+
if (typeof thinkingTokens === "number") {
|
|
20893
|
+
metrics.completion_reasoning_tokens = thinkingTokens;
|
|
20894
|
+
}
|
|
20895
|
+
}
|
|
20013
20896
|
if (isObject(usage.server_tool_use)) {
|
|
20014
20897
|
for (const [name, value] of Object.entries(usage.server_tool_use)) {
|
|
20015
20898
|
if (typeof value === "number") {
|
|
@@ -20575,118 +21458,22 @@ function coalesceInput(messages, system) {
|
|
|
20575
21458
|
var CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION = "__braintrust_skip_local_tool_hooks";
|
|
20576
21459
|
|
|
20577
21460
|
// src/instrumentation/plugins/claude-agent-sdk-local-tool-context.ts
|
|
20578
|
-
var
|
|
20579
|
-
|
|
20580
|
-
)
|
|
20581
|
-
|
|
20582
|
-
const maybeIsoWithAsyncLocalStorage = isomorph_default;
|
|
20583
|
-
if (typeof maybeIsoWithAsyncLocalStorage.newAsyncLocalStorage === "function") {
|
|
20584
|
-
return maybeIsoWithAsyncLocalStorage.newAsyncLocalStorage();
|
|
20585
|
-
}
|
|
20586
|
-
let currentStore;
|
|
20587
|
-
return {
|
|
20588
|
-
enterWith(store) {
|
|
20589
|
-
currentStore = store;
|
|
20590
|
-
},
|
|
20591
|
-
getStore() {
|
|
20592
|
-
return currentStore;
|
|
20593
|
-
},
|
|
20594
|
-
run(store, callback) {
|
|
20595
|
-
const previousStore = currentStore;
|
|
20596
|
-
currentStore = store;
|
|
20597
|
-
try {
|
|
20598
|
-
return callback();
|
|
20599
|
-
} finally {
|
|
20600
|
-
currentStore = previousStore;
|
|
20601
|
-
}
|
|
20602
|
-
}
|
|
20603
|
-
};
|
|
20604
|
-
}
|
|
20605
|
-
var localToolContextStore = createLocalToolContextStore();
|
|
20606
|
-
var fallbackLocalToolParentResolver;
|
|
20607
|
-
function createClaudeLocalToolContext() {
|
|
20608
|
-
return {};
|
|
20609
|
-
}
|
|
20610
|
-
function runWithClaudeLocalToolContext(callback, context) {
|
|
20611
|
-
return localToolContextStore.run(
|
|
20612
|
-
context ?? createClaudeLocalToolContext(),
|
|
20613
|
-
callback
|
|
20614
|
-
);
|
|
21461
|
+
var localToolContextStore = isomorph_default.newAsyncLocalStorage();
|
|
21462
|
+
var localToolParentResolversByToolUseId = /* @__PURE__ */ new Map();
|
|
21463
|
+
function runWithClaudeLocalToolContext(callback, resolver) {
|
|
21464
|
+
return localToolContextStore.run(resolver, callback);
|
|
20615
21465
|
}
|
|
20616
|
-
function
|
|
20617
|
-
|
|
20618
|
-
if (existing) {
|
|
20619
|
-
return existing;
|
|
20620
|
-
}
|
|
20621
|
-
const created = {};
|
|
20622
|
-
localToolContextStore.enterWith(created);
|
|
20623
|
-
return created;
|
|
21466
|
+
function registerClaudeLocalToolParentResolver(toolUseId, resolver) {
|
|
21467
|
+
localToolParentResolversByToolUseId.set(toolUseId, resolver);
|
|
20624
21468
|
}
|
|
20625
|
-
function
|
|
20626
|
-
|
|
20627
|
-
|
|
20628
|
-
|
|
20629
|
-
return;
|
|
20630
|
-
}
|
|
20631
|
-
context.resolveLocalToolParent = resolver;
|
|
20632
|
-
}
|
|
20633
|
-
function getClaudeLocalToolParentResolver() {
|
|
20634
|
-
return localToolContextStore.getStore()?.resolveLocalToolParent ?? fallbackLocalToolParentResolver;
|
|
20635
|
-
}
|
|
20636
|
-
function isAsyncIterable3(value) {
|
|
20637
|
-
return value !== null && typeof value === "object" && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
|
|
20638
|
-
}
|
|
20639
|
-
function bindClaudeLocalToolContextToAsyncIterable(result, localToolContext) {
|
|
20640
|
-
if (!isAsyncIterable3(result) || Object.isFrozen(result) || Object.isSealed(result)) {
|
|
20641
|
-
return result;
|
|
20642
|
-
}
|
|
20643
|
-
const stream = result;
|
|
20644
|
-
const originalAsyncIterator = stream[Symbol.asyncIterator];
|
|
20645
|
-
if (originalAsyncIterator[LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED]) {
|
|
20646
|
-
return result;
|
|
21469
|
+
function getClaudeLocalToolParentResolver(toolUseId) {
|
|
21470
|
+
const currentResolver = localToolContextStore.getStore();
|
|
21471
|
+
if (!toolUseId) {
|
|
21472
|
+
return currentResolver;
|
|
20647
21473
|
}
|
|
20648
|
-
const
|
|
20649
|
-
|
|
20650
|
-
|
|
20651
|
-
if (!iterator || typeof iterator !== "object") {
|
|
20652
|
-
return iterator;
|
|
20653
|
-
}
|
|
20654
|
-
const patchMethod = (methodName) => {
|
|
20655
|
-
const originalMethod = Reflect.get(iterator, methodName);
|
|
20656
|
-
if (typeof originalMethod !== "function") {
|
|
20657
|
-
return;
|
|
20658
|
-
}
|
|
20659
|
-
Reflect.set(
|
|
20660
|
-
iterator,
|
|
20661
|
-
methodName,
|
|
20662
|
-
(...args) => runWithClaudeLocalToolContext(
|
|
20663
|
-
() => Reflect.apply(
|
|
20664
|
-
originalMethod,
|
|
20665
|
-
iterator,
|
|
20666
|
-
args
|
|
20667
|
-
),
|
|
20668
|
-
localToolContext
|
|
20669
|
-
)
|
|
20670
|
-
);
|
|
20671
|
-
};
|
|
20672
|
-
patchMethod("next");
|
|
20673
|
-
patchMethod("return");
|
|
20674
|
-
patchMethod("throw");
|
|
20675
|
-
return iterator;
|
|
20676
|
-
}, localToolContext);
|
|
20677
|
-
};
|
|
20678
|
-
Object.defineProperty(
|
|
20679
|
-
patchedAsyncIterator,
|
|
20680
|
-
LOCAL_TOOL_CONTEXT_ASYNC_ITERATOR_PATCHED,
|
|
20681
|
-
{
|
|
20682
|
-
configurable: false,
|
|
20683
|
-
enumerable: false,
|
|
20684
|
-
value: true,
|
|
20685
|
-
writable: false
|
|
20686
|
-
}
|
|
20687
|
-
);
|
|
20688
|
-
Reflect.set(stream, Symbol.asyncIterator, patchedAsyncIterator);
|
|
20689
|
-
return result;
|
|
21474
|
+
const registeredResolver = localToolParentResolversByToolUseId.get(toolUseId);
|
|
21475
|
+
localToolParentResolversByToolUseId.delete(toolUseId);
|
|
21476
|
+
return currentResolver ?? registeredResolver;
|
|
20690
21477
|
}
|
|
20691
21478
|
|
|
20692
21479
|
// src/instrumentation/plugins/claude-agent-sdk-local-tool-spans.ts
|
|
@@ -20712,7 +21499,7 @@ function wrapLocalClaudeToolHandler(handler, getMetadata) {
|
|
|
20712
21499
|
const metadata = getMetadata();
|
|
20713
21500
|
const rawToolName = metadata.serverName ? `mcp__${metadata.serverName}__${metadata.toolName}` : metadata.toolName;
|
|
20714
21501
|
const toolUseId = getToolUseIdFromExtra(handlerArgs[1]);
|
|
20715
|
-
const localToolParentResolver = getClaudeLocalToolParentResolver();
|
|
21502
|
+
const localToolParentResolver = getClaudeLocalToolParentResolver(toolUseId);
|
|
20716
21503
|
const spanName = metadata.serverName ? `tool: ${metadata.serverName}/${metadata.toolName}` : `tool: ${metadata.toolName}`;
|
|
20717
21504
|
const runWithResolvedParent = async () => {
|
|
20718
21505
|
const parent = toolUseId && localToolParentResolver ? await localToolParentResolver(toolUseId).catch(() => void 0) : void 0;
|
|
@@ -21239,6 +22026,7 @@ function createToolTracingHooks(resolveParentSpan, taskIdToToolUseId, toolUseToP
|
|
|
21239
22026
|
}
|
|
21240
22027
|
}
|
|
21241
22028
|
if (skipLocalToolHooks && (isLocalToolUse(input.tool_name, mcpServers) || localToolHookNames.has(input.tool_name))) {
|
|
22029
|
+
registerClaudeLocalToolParentResolver(toolUseID, resolveParentSpan);
|
|
21242
22030
|
return {};
|
|
21243
22031
|
}
|
|
21244
22032
|
const parsed = parseToolName(input.tool_name);
|
|
@@ -21949,7 +22737,7 @@ async function finalizeQuerySpan(state) {
|
|
|
21949
22737
|
}
|
|
21950
22738
|
var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
21951
22739
|
onEnable() {
|
|
21952
|
-
this.
|
|
22740
|
+
this.interceptQuery();
|
|
21953
22741
|
}
|
|
21954
22742
|
onDisable() {
|
|
21955
22743
|
for (const unsubscribe of this.unsubscribers) {
|
|
@@ -21957,211 +22745,218 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
21957
22745
|
}
|
|
21958
22746
|
this.unsubscribers = [];
|
|
21959
22747
|
}
|
|
21960
|
-
|
|
21961
|
-
const
|
|
21962
|
-
|
|
21963
|
-
|
|
21964
|
-
|
|
21965
|
-
|
|
21966
|
-
|
|
21967
|
-
|
|
21968
|
-
|
|
21969
|
-
|
|
21970
|
-
|
|
21971
|
-
|
|
21972
|
-
|
|
21973
|
-
|
|
21974
|
-
|
|
21975
|
-
|
|
21976
|
-
|
|
21977
|
-
|
|
21978
|
-
|
|
21979
|
-
|
|
21980
|
-
try {
|
|
21981
|
-
for await (const message of promptStream) {
|
|
21982
|
-
capturedPromptMessages.push(message);
|
|
21983
|
-
yield message;
|
|
21984
|
-
}
|
|
21985
|
-
} finally {
|
|
21986
|
-
resolvePromptDone?.();
|
|
22748
|
+
interceptQuery() {
|
|
22749
|
+
const startQuery = (params) => {
|
|
22750
|
+
const originalPrompt = params.prompt;
|
|
22751
|
+
const options = params.options ?? {};
|
|
22752
|
+
const promptIsAsyncIterable = isAsyncIterable(originalPrompt);
|
|
22753
|
+
let promptStarted = false;
|
|
22754
|
+
let capturedPromptMessages;
|
|
22755
|
+
let resolvePromptDone;
|
|
22756
|
+
const promptDone = new Promise((resolve) => {
|
|
22757
|
+
resolvePromptDone = resolve;
|
|
22758
|
+
});
|
|
22759
|
+
if (promptIsAsyncIterable) {
|
|
22760
|
+
capturedPromptMessages = [];
|
|
22761
|
+
const promptStream = originalPrompt;
|
|
22762
|
+
params.prompt = (async function* () {
|
|
22763
|
+
promptStarted = true;
|
|
22764
|
+
try {
|
|
22765
|
+
for await (const message of promptStream) {
|
|
22766
|
+
capturedPromptMessages.push(message);
|
|
22767
|
+
yield message;
|
|
21987
22768
|
}
|
|
21988
|
-
}
|
|
21989
|
-
|
|
21990
|
-
const span = startSpan(
|
|
21991
|
-
withSpanInstrumentationName(
|
|
21992
|
-
{
|
|
21993
|
-
name: "Claude Agent",
|
|
21994
|
-
spanAttributes: {
|
|
21995
|
-
type: "task" /* TASK */
|
|
21996
|
-
}
|
|
21997
|
-
},
|
|
21998
|
-
INSTRUMENTATION_NAMES.CLAUDE_AGENT_SDK
|
|
21999
|
-
)
|
|
22000
|
-
);
|
|
22001
|
-
const startTime = getCurrentUnixTimestamp();
|
|
22002
|
-
try {
|
|
22003
|
-
span.log({
|
|
22004
|
-
input: typeof originalPrompt === "string" ? originalPrompt : promptIsAsyncIterable ? void 0 : originalPrompt !== void 0 ? String(originalPrompt) : void 0,
|
|
22005
|
-
metadata: filterSerializableOptions(options)
|
|
22006
|
-
});
|
|
22007
|
-
} catch (error) {
|
|
22008
|
-
console.error("Error extracting input for Claude Agent SDK:", error);
|
|
22009
|
-
}
|
|
22010
|
-
const activeToolSpans = /* @__PURE__ */ new Map();
|
|
22011
|
-
const activeLlmSpansByParentToolUse = /* @__PURE__ */ new Map();
|
|
22012
|
-
const conversationHistoryByParentKey = /* @__PURE__ */ new Map();
|
|
22013
|
-
const subAgentSpans = /* @__PURE__ */ new Map();
|
|
22014
|
-
const endedSubAgentSpans = /* @__PURE__ */ new Set();
|
|
22015
|
-
const toolUseToParent = /* @__PURE__ */ new Map();
|
|
22016
|
-
const latestLlmParentBySubAgentToolUse = /* @__PURE__ */ new Map();
|
|
22017
|
-
const latestRootLlmParentRef = {
|
|
22018
|
-
value: void 0
|
|
22019
|
-
};
|
|
22020
|
-
const subAgentDetailsByToolUseId = /* @__PURE__ */ new Map();
|
|
22021
|
-
const taskIdToToolUseId = /* @__PURE__ */ new Map();
|
|
22022
|
-
const promptMessagesByParentKey = /* @__PURE__ */ new Map();
|
|
22023
|
-
const promptSourcePriorityByParentKey = /* @__PURE__ */ new Map();
|
|
22024
|
-
const localToolContext = createClaudeLocalToolContext();
|
|
22025
|
-
const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
|
|
22026
|
-
const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
|
|
22027
|
-
const resolveToolUseParentSpan = async (toolUseID, context) => {
|
|
22028
|
-
const trackedParentToolUseId = toolUseToParent.get(toolUseID);
|
|
22029
|
-
const parentToolUseId = trackedParentToolUseId ?? (context?.agentId ? taskIdToToolUseId.get(context.agentId) ?? null : null);
|
|
22030
|
-
const parentKey = llmParentKey(parentToolUseId);
|
|
22031
|
-
const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
|
|
22032
|
-
const latestLlmParent = parentToolUseId ? latestLlmParentBySubAgentToolUse.get(parentToolUseId) : latestRootLlmParentRef.value;
|
|
22033
|
-
if (!activeLlmSpan && !latestLlmParent) {
|
|
22034
|
-
await ensureActiveLlmSpanForParentToolUse(
|
|
22035
|
-
span,
|
|
22036
|
-
activeLlmSpansByParentToolUse,
|
|
22037
|
-
subAgentDetailsByToolUseId,
|
|
22038
|
-
activeToolSpans,
|
|
22039
|
-
subAgentSpans,
|
|
22040
|
-
parentToolUseId,
|
|
22041
|
-
getCurrentUnixTimestamp()
|
|
22042
|
-
);
|
|
22043
|
-
}
|
|
22044
|
-
if (parentToolUseId) {
|
|
22045
|
-
const subAgentSpan = await ensureSubAgentSpan(
|
|
22046
|
-
subAgentDetailsByToolUseId,
|
|
22047
|
-
span,
|
|
22048
|
-
activeToolSpans,
|
|
22049
|
-
subAgentSpans,
|
|
22050
|
-
parentToolUseId
|
|
22051
|
-
);
|
|
22052
|
-
return subAgentSpan.export();
|
|
22769
|
+
} finally {
|
|
22770
|
+
resolvePromptDone?.();
|
|
22053
22771
|
}
|
|
22054
|
-
|
|
22055
|
-
|
|
22056
|
-
|
|
22057
|
-
|
|
22058
|
-
|
|
22059
|
-
|
|
22060
|
-
|
|
22061
|
-
|
|
22062
|
-
|
|
22063
|
-
|
|
22064
|
-
|
|
22065
|
-
|
|
22066
|
-
|
|
22067
|
-
|
|
22068
|
-
|
|
22069
|
-
|
|
22070
|
-
|
|
22071
|
-
|
|
22072
|
-
spans.set(event, {
|
|
22073
|
-
activeLlmSpansByParentToolUse,
|
|
22074
|
-
activePartialMessageIdByParentKey: /* @__PURE__ */ new Map(),
|
|
22075
|
-
activeToolSpans,
|
|
22076
|
-
conversationHistoryByParentKey,
|
|
22077
|
-
capturedPromptMessages,
|
|
22078
|
-
currentMessageId: void 0,
|
|
22079
|
-
currentMessageStartTime: startTime,
|
|
22080
|
-
currentMessages: [],
|
|
22081
|
-
endedSubAgentSpans,
|
|
22082
|
-
finalOutputUsageMessageIds: /* @__PURE__ */ new Set(),
|
|
22083
|
-
finalResults: [],
|
|
22084
|
-
options: optionsWithHooks,
|
|
22085
|
-
originalPrompt,
|
|
22086
|
-
processing: Promise.resolve(),
|
|
22087
|
-
promptDone,
|
|
22088
|
-
promptMessagesByParentKey,
|
|
22089
|
-
promptStarted: () => promptStarted,
|
|
22090
|
-
promptSourcePriorityByParentKey,
|
|
22091
|
-
span,
|
|
22092
|
-
subAgentDetailsByToolUseId,
|
|
22093
|
-
subAgentSpans,
|
|
22094
|
-
taskIdToToolUseId,
|
|
22095
|
-
latestLlmParentBySubAgentToolUse,
|
|
22096
|
-
latestRootLlmParentRef,
|
|
22097
|
-
toolUseToParent,
|
|
22098
|
-
usageByMessageId: /* @__PURE__ */ new Map(),
|
|
22099
|
-
localToolContext
|
|
22772
|
+
})();
|
|
22773
|
+
}
|
|
22774
|
+
const span = startSpan(
|
|
22775
|
+
withSpanInstrumentationName(
|
|
22776
|
+
{
|
|
22777
|
+
name: "Claude Agent",
|
|
22778
|
+
spanAttributes: {
|
|
22779
|
+
type: "task" /* TASK */
|
|
22780
|
+
}
|
|
22781
|
+
},
|
|
22782
|
+
INSTRUMENTATION_NAMES.CLAUDE_AGENT_SDK
|
|
22783
|
+
)
|
|
22784
|
+
);
|
|
22785
|
+
const startTime = getCurrentUnixTimestamp();
|
|
22786
|
+
try {
|
|
22787
|
+
span.log({
|
|
22788
|
+
input: typeof originalPrompt === "string" ? originalPrompt : promptIsAsyncIterable ? void 0 : originalPrompt !== void 0 ? String(originalPrompt) : void 0,
|
|
22789
|
+
metadata: filterSerializableOptions(options)
|
|
22100
22790
|
});
|
|
22101
|
-
}
|
|
22102
|
-
|
|
22103
|
-
|
|
22104
|
-
|
|
22105
|
-
|
|
22106
|
-
|
|
22107
|
-
|
|
22108
|
-
|
|
22109
|
-
|
|
22110
|
-
|
|
22111
|
-
|
|
22112
|
-
|
|
22113
|
-
|
|
22114
|
-
|
|
22115
|
-
|
|
22116
|
-
|
|
22117
|
-
|
|
22118
|
-
|
|
22119
|
-
|
|
22120
|
-
|
|
22121
|
-
|
|
22122
|
-
|
|
22123
|
-
|
|
22124
|
-
|
|
22125
|
-
|
|
22126
|
-
|
|
22127
|
-
|
|
22128
|
-
|
|
22129
|
-
|
|
22130
|
-
|
|
22131
|
-
|
|
22132
|
-
|
|
22133
|
-
|
|
22134
|
-
|
|
22135
|
-
|
|
22136
|
-
})
|
|
22137
|
-
});
|
|
22138
|
-
return;
|
|
22139
|
-
}
|
|
22140
|
-
try {
|
|
22141
|
-
state.span.log({ output: eventResult });
|
|
22142
|
-
} catch (error) {
|
|
22143
|
-
console.error("Error extracting output for Claude Agent SDK:", error);
|
|
22144
|
-
} finally {
|
|
22145
|
-
state.span.end();
|
|
22146
|
-
spans.delete(event);
|
|
22791
|
+
} catch (error) {
|
|
22792
|
+
console.error("Error extracting input for Claude Agent SDK:", error);
|
|
22793
|
+
}
|
|
22794
|
+
const activeToolSpans = /* @__PURE__ */ new Map();
|
|
22795
|
+
const activeLlmSpansByParentToolUse = /* @__PURE__ */ new Map();
|
|
22796
|
+
const conversationHistoryByParentKey = /* @__PURE__ */ new Map();
|
|
22797
|
+
const subAgentSpans = /* @__PURE__ */ new Map();
|
|
22798
|
+
const endedSubAgentSpans = /* @__PURE__ */ new Set();
|
|
22799
|
+
const toolUseToParent = /* @__PURE__ */ new Map();
|
|
22800
|
+
const latestLlmParentBySubAgentToolUse = /* @__PURE__ */ new Map();
|
|
22801
|
+
const latestRootLlmParentRef = {
|
|
22802
|
+
value: void 0
|
|
22803
|
+
};
|
|
22804
|
+
const subAgentDetailsByToolUseId = /* @__PURE__ */ new Map();
|
|
22805
|
+
const taskIdToToolUseId = /* @__PURE__ */ new Map();
|
|
22806
|
+
const promptMessagesByParentKey = /* @__PURE__ */ new Map();
|
|
22807
|
+
const promptSourcePriorityByParentKey = /* @__PURE__ */ new Map();
|
|
22808
|
+
const { hasLocalToolHandlers, localToolHookNames } = prepareLocalToolHandlersInMcpServers(options.mcpServers);
|
|
22809
|
+
const skipLocalToolHooks = options[CLAUDE_AGENT_SDK_SKIP_LOCAL_TOOL_HOOKS_OPTION] === true || hasLocalToolHandlers;
|
|
22810
|
+
const resolveToolUseParentSpan = async (toolUseID, context) => {
|
|
22811
|
+
const trackedParentToolUseId = toolUseToParent.get(toolUseID);
|
|
22812
|
+
const parentToolUseId = trackedParentToolUseId ?? (context?.agentId ? taskIdToToolUseId.get(context.agentId) ?? null : null);
|
|
22813
|
+
const parentKey = llmParentKey(parentToolUseId);
|
|
22814
|
+
const activeLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
|
|
22815
|
+
const latestLlmParent = parentToolUseId ? latestLlmParentBySubAgentToolUse.get(parentToolUseId) : latestRootLlmParentRef.value;
|
|
22816
|
+
if (!activeLlmSpan && !latestLlmParent) {
|
|
22817
|
+
await ensureActiveLlmSpanForParentToolUse(
|
|
22818
|
+
span,
|
|
22819
|
+
activeLlmSpansByParentToolUse,
|
|
22820
|
+
subAgentDetailsByToolUseId,
|
|
22821
|
+
activeToolSpans,
|
|
22822
|
+
subAgentSpans,
|
|
22823
|
+
parentToolUseId,
|
|
22824
|
+
getCurrentUnixTimestamp()
|
|
22825
|
+
);
|
|
22147
22826
|
}
|
|
22148
|
-
|
|
22149
|
-
|
|
22150
|
-
|
|
22151
|
-
|
|
22152
|
-
|
|
22827
|
+
if (parentToolUseId) {
|
|
22828
|
+
const subAgentSpan = await ensureSubAgentSpan(
|
|
22829
|
+
subAgentDetailsByToolUseId,
|
|
22830
|
+
span,
|
|
22831
|
+
activeToolSpans,
|
|
22832
|
+
subAgentSpans,
|
|
22833
|
+
parentToolUseId
|
|
22834
|
+
);
|
|
22835
|
+
return subAgentSpan.export();
|
|
22153
22836
|
}
|
|
22154
|
-
|
|
22155
|
-
|
|
22837
|
+
return span.export();
|
|
22838
|
+
};
|
|
22839
|
+
const optionsWithHooks = injectTracingHooks(
|
|
22840
|
+
options,
|
|
22841
|
+
resolveToolUseParentSpan,
|
|
22842
|
+
taskIdToToolUseId,
|
|
22843
|
+
toolUseToParent,
|
|
22844
|
+
activeToolSpans,
|
|
22845
|
+
localToolHookNames,
|
|
22846
|
+
skipLocalToolHooks,
|
|
22847
|
+
subAgentDetailsByToolUseId,
|
|
22848
|
+
subAgentSpans,
|
|
22849
|
+
endedSubAgentSpans
|
|
22850
|
+
);
|
|
22851
|
+
params.options = optionsWithHooks;
|
|
22852
|
+
return {
|
|
22853
|
+
activeLlmSpansByParentToolUse,
|
|
22854
|
+
activePartialMessageIdByParentKey: /* @__PURE__ */ new Map(),
|
|
22855
|
+
activeToolSpans,
|
|
22856
|
+
conversationHistoryByParentKey,
|
|
22857
|
+
capturedPromptMessages,
|
|
22858
|
+
currentMessageId: void 0,
|
|
22859
|
+
currentMessageStartTime: startTime,
|
|
22860
|
+
currentMessages: [],
|
|
22861
|
+
endedSubAgentSpans,
|
|
22862
|
+
finalOutputUsageMessageIds: /* @__PURE__ */ new Set(),
|
|
22863
|
+
finalResults: [],
|
|
22864
|
+
options: optionsWithHooks,
|
|
22865
|
+
originalPrompt,
|
|
22866
|
+
processing: Promise.resolve(),
|
|
22867
|
+
promptDone,
|
|
22868
|
+
promptMessagesByParentKey,
|
|
22869
|
+
promptStarted: () => promptStarted,
|
|
22870
|
+
promptSourcePriorityByParentKey,
|
|
22871
|
+
span,
|
|
22872
|
+
subAgentDetailsByToolUseId,
|
|
22873
|
+
subAgentSpans,
|
|
22874
|
+
taskIdToToolUseId,
|
|
22875
|
+
latestLlmParentBySubAgentToolUse,
|
|
22876
|
+
latestRootLlmParentRef,
|
|
22877
|
+
toolUseToParent,
|
|
22878
|
+
usageByMessageId: /* @__PURE__ */ new Map(),
|
|
22879
|
+
localToolParentResolver: resolveToolUseParentSpan
|
|
22880
|
+
};
|
|
22881
|
+
};
|
|
22882
|
+
const finishQuery = (state, result) => {
|
|
22883
|
+
if (isAsyncIterable(result)) {
|
|
22884
|
+
patchStreamIfNeeded(result, {
|
|
22885
|
+
aroundNext: (callback) => runWithClaudeLocalToolContext(
|
|
22886
|
+
callback,
|
|
22887
|
+
state.localToolParentResolver
|
|
22888
|
+
),
|
|
22889
|
+
onChunk: (message) => {
|
|
22890
|
+
maybeTrackToolUseContext(state, message);
|
|
22891
|
+
state.processing = state.processing.then(() => handleStreamMessage(state, message)).catch((error) => {
|
|
22892
|
+
console.error(
|
|
22893
|
+
"Error processing Claude Agent SDK stream chunk:",
|
|
22894
|
+
error
|
|
22895
|
+
);
|
|
22896
|
+
});
|
|
22897
|
+
},
|
|
22898
|
+
onComplete: () => state.processing.then(() => finalizeQuerySpan(state)),
|
|
22899
|
+
onError: (error) => state.processing.then(() => {
|
|
22900
|
+
state.span.log({ error: error.message });
|
|
22901
|
+
}).then(() => finalizeQuerySpan(state))
|
|
22156
22902
|
});
|
|
22903
|
+
return;
|
|
22904
|
+
}
|
|
22905
|
+
try {
|
|
22906
|
+
state.span.log({ output: result });
|
|
22907
|
+
} catch (error) {
|
|
22908
|
+
console.error("Error extracting output for Claude Agent SDK:", error);
|
|
22909
|
+
} finally {
|
|
22157
22910
|
state.span.end();
|
|
22158
|
-
spans.delete(event);
|
|
22159
22911
|
}
|
|
22160
22912
|
};
|
|
22161
|
-
|
|
22162
|
-
|
|
22163
|
-
|
|
22164
|
-
|
|
22913
|
+
this.unsubscribers.push(
|
|
22914
|
+
claudeAgentSDKChannels.query.intercept((target, thisArg, args) => {
|
|
22915
|
+
let state;
|
|
22916
|
+
try {
|
|
22917
|
+
args[0] ??= {};
|
|
22918
|
+
state = startQuery(args[0]);
|
|
22919
|
+
} catch (error) {
|
|
22920
|
+
debugLogger.error(
|
|
22921
|
+
"Error starting Claude Agent SDK instrumentation:",
|
|
22922
|
+
error
|
|
22923
|
+
);
|
|
22924
|
+
}
|
|
22925
|
+
const invokeTarget = () => Reflect.apply(target, thisArg, args);
|
|
22926
|
+
try {
|
|
22927
|
+
const result = state ? runWithClaudeLocalToolContext(
|
|
22928
|
+
invokeTarget,
|
|
22929
|
+
state.localToolParentResolver
|
|
22930
|
+
) : invokeTarget();
|
|
22931
|
+
if (state) {
|
|
22932
|
+
try {
|
|
22933
|
+
finishQuery(state, result);
|
|
22934
|
+
} catch (error) {
|
|
22935
|
+
debugLogger.error(
|
|
22936
|
+
"Error finalizing Claude Agent SDK instrumentation:",
|
|
22937
|
+
error
|
|
22938
|
+
);
|
|
22939
|
+
}
|
|
22940
|
+
}
|
|
22941
|
+
return result;
|
|
22942
|
+
} catch (error) {
|
|
22943
|
+
if (state) {
|
|
22944
|
+
try {
|
|
22945
|
+
state.span.log({
|
|
22946
|
+
error: error instanceof Error ? error.message : String(error)
|
|
22947
|
+
});
|
|
22948
|
+
state.span.end();
|
|
22949
|
+
} catch (instrumentationError) {
|
|
22950
|
+
debugLogger.error(
|
|
22951
|
+
"Error handling Claude Agent SDK instrumentation failure:",
|
|
22952
|
+
instrumentationError
|
|
22953
|
+
);
|
|
22954
|
+
}
|
|
22955
|
+
}
|
|
22956
|
+
throw error;
|
|
22957
|
+
}
|
|
22958
|
+
})
|
|
22959
|
+
);
|
|
22165
22960
|
}
|
|
22166
22961
|
};
|
|
22167
22962
|
|
|
@@ -26103,7 +26898,7 @@ function patchOpenRouterCallModelResult(args) {
|
|
|
26103
26898
|
span,
|
|
26104
26899
|
() => originalMethod.apply(resultLike, args2)
|
|
26105
26900
|
);
|
|
26106
|
-
if (!
|
|
26901
|
+
if (!isAsyncIterable3(stream)) {
|
|
26107
26902
|
return stream;
|
|
26108
26903
|
}
|
|
26109
26904
|
return wrapAsyncIterableWithSpan({
|
|
@@ -26298,7 +27093,7 @@ function wrapAsyncIterableWithSpan(args) {
|
|
|
26298
27093
|
}
|
|
26299
27094
|
};
|
|
26300
27095
|
}
|
|
26301
|
-
function
|
|
27096
|
+
function isAsyncIterable3(value) {
|
|
26302
27097
|
return !!value && (typeof value === "object" || typeof value === "function") && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
|
|
26303
27098
|
}
|
|
26304
27099
|
function normalizeError(error) {
|
|
@@ -27140,7 +27935,7 @@ function patchOpenRouterCallModelResult2(args) {
|
|
|
27140
27935
|
span,
|
|
27141
27936
|
() => originalMethod.apply(resultLike, args2)
|
|
27142
27937
|
);
|
|
27143
|
-
if (!
|
|
27938
|
+
if (!isAsyncIterable4(stream)) {
|
|
27144
27939
|
return stream;
|
|
27145
27940
|
}
|
|
27146
27941
|
return wrapAsyncIterableWithSpan2({
|
|
@@ -27335,7 +28130,7 @@ function wrapAsyncIterableWithSpan2(args) {
|
|
|
27335
28130
|
}
|
|
27336
28131
|
};
|
|
27337
28132
|
}
|
|
27338
|
-
function
|
|
28133
|
+
function isAsyncIterable4(value) {
|
|
27339
28134
|
return !!value && (typeof value === "object" || typeof value === "function") && Symbol.asyncIterator in value && typeof value[Symbol.asyncIterator] === "function";
|
|
27340
28135
|
}
|
|
27341
28136
|
function normalizeError2(error) {
|
|
@@ -32081,6 +32876,9 @@ function sanitizeLoggedValue(value, seen = /* @__PURE__ */ new WeakSet(), depth
|
|
|
32081
32876
|
// src/instrumentation/plugins/pi-coding-agent-plugin.ts
|
|
32082
32877
|
var piAgentPatchStates = /* @__PURE__ */ new WeakMap();
|
|
32083
32878
|
var piAgentEventSubscriptions = /* @__PURE__ */ new WeakSet();
|
|
32879
|
+
var PI_TOOL_EXECUTE_WRAPPED = /* @__PURE__ */ Symbol.for(
|
|
32880
|
+
"braintrust.pi_coding_agent.tool_execute_wrapped"
|
|
32881
|
+
);
|
|
32084
32882
|
var piPromptContextStore;
|
|
32085
32883
|
var PiCodingAgentPlugin = class extends BasePlugin {
|
|
32086
32884
|
activePromptStates = /* @__PURE__ */ new Set();
|
|
@@ -32161,6 +32959,7 @@ function startPiPromptRun(event, onFinalize) {
|
|
|
32161
32959
|
return void 0;
|
|
32162
32960
|
}
|
|
32163
32961
|
installPiAgentInstrumentation(agent);
|
|
32962
|
+
wrapPiToolExecutors(agent.state?.tools);
|
|
32164
32963
|
const metadata = {
|
|
32165
32964
|
...extractSessionMetadata(session),
|
|
32166
32965
|
...extractPromptOptionsMetadata(event.arguments[1]),
|
|
@@ -32205,7 +33004,7 @@ function extractSession(event) {
|
|
|
32205
33004
|
return isObject(candidate) && typeof candidate.prompt === "function" ? candidate : void 0;
|
|
32206
33005
|
}
|
|
32207
33006
|
function isPiAgent(value) {
|
|
32208
|
-
return isObject(value) && typeof value.streamFn === "function" && typeof value.subscribe === "function";
|
|
33007
|
+
return isObject(value) && (typeof value.streamFunction === "function" || typeof value.streamFn === "function") && typeof value.subscribe === "function";
|
|
32209
33008
|
}
|
|
32210
33009
|
function promptContextStore() {
|
|
32211
33010
|
piPromptContextStore ??= isomorph_default.newAsyncLocalStorage();
|
|
@@ -32215,17 +33014,21 @@ function currentPiPromptState() {
|
|
|
32215
33014
|
return promptContextStore().getStore();
|
|
32216
33015
|
}
|
|
32217
33016
|
function installPiAgentInstrumentation(agent) {
|
|
33017
|
+
const property = typeof agent.streamFunction === "function" ? "streamFunction" : "streamFn";
|
|
33018
|
+
const streamFunction = agent[property];
|
|
32218
33019
|
const existing = piAgentPatchStates.get(agent);
|
|
32219
|
-
if (!existing ||
|
|
33020
|
+
if (streamFunction && (!existing || existing.property !== property || streamFunction !== existing.wrappedStreamFunction)) {
|
|
32220
33021
|
const patchState = {
|
|
32221
|
-
|
|
32222
|
-
|
|
33022
|
+
originalStreamFunction: streamFunction,
|
|
33023
|
+
property,
|
|
33024
|
+
wrappedStreamFunction: streamFunction
|
|
32223
33025
|
};
|
|
32224
|
-
patchState.
|
|
33026
|
+
patchState.wrappedStreamFunction = makeInstrumentedStreamFunction(
|
|
32225
33027
|
agent,
|
|
32226
|
-
patchState.
|
|
33028
|
+
patchState.originalStreamFunction,
|
|
33029
|
+
property
|
|
32227
33030
|
);
|
|
32228
|
-
agent
|
|
33031
|
+
agent[property] = patchState.wrappedStreamFunction;
|
|
32229
33032
|
piAgentPatchStates.set(agent, patchState);
|
|
32230
33033
|
}
|
|
32231
33034
|
if (piAgentEventSubscriptions.has(agent)) {
|
|
@@ -32250,14 +33053,21 @@ function installPiAgentInstrumentation(agent) {
|
|
|
32250
33053
|
logInstrumentationError4("Pi Coding Agent event subscription", error);
|
|
32251
33054
|
}
|
|
32252
33055
|
}
|
|
32253
|
-
function
|
|
32254
|
-
return async function
|
|
32255
|
-
const invokeOriginal = () => Reflect.apply(
|
|
33056
|
+
function makeInstrumentedStreamFunction(agent, originalStreamFunction, property) {
|
|
33057
|
+
return async function instrumentedPiStreamFunction(model, context, options) {
|
|
33058
|
+
const invokeOriginal = () => Reflect.apply(originalStreamFunction, this, [model, context, options]);
|
|
32256
33059
|
const state = currentPiPromptState();
|
|
32257
33060
|
if (!state || state.agent !== agent || state.finalized) {
|
|
32258
33061
|
return invokeOriginal();
|
|
32259
33062
|
}
|
|
32260
|
-
|
|
33063
|
+
wrapPiToolExecutors(context.tools);
|
|
33064
|
+
const llmState = await startPiLlmSpan(
|
|
33065
|
+
state,
|
|
33066
|
+
model,
|
|
33067
|
+
context,
|
|
33068
|
+
property,
|
|
33069
|
+
options
|
|
33070
|
+
);
|
|
32261
33071
|
try {
|
|
32262
33072
|
const stream = await runWithAutoInstrumentationSuppressed(invokeOriginal);
|
|
32263
33073
|
return patchAssistantMessageStream(stream, state, llmState);
|
|
@@ -32267,12 +33077,39 @@ function makeInstrumentedStreamFn(agent, originalStreamFn) {
|
|
|
32267
33077
|
}
|
|
32268
33078
|
};
|
|
32269
33079
|
}
|
|
32270
|
-
|
|
33080
|
+
function wrapPiToolExecutors(tools) {
|
|
33081
|
+
if (!tools) {
|
|
33082
|
+
return;
|
|
33083
|
+
}
|
|
33084
|
+
for (const tool of tools) {
|
|
33085
|
+
try {
|
|
33086
|
+
const execute = tool.execute;
|
|
33087
|
+
if (typeof execute !== "function" || execute[PI_TOOL_EXECUTE_WRAPPED]) {
|
|
33088
|
+
continue;
|
|
33089
|
+
}
|
|
33090
|
+
const wrappedExecute = function(...args) {
|
|
33091
|
+
return runWithAutoInstrumentationAllowed(
|
|
33092
|
+
() => Reflect.apply(execute, this, args)
|
|
33093
|
+
);
|
|
33094
|
+
};
|
|
33095
|
+
Object.defineProperty(wrappedExecute, PI_TOOL_EXECUTE_WRAPPED, {
|
|
33096
|
+
configurable: false,
|
|
33097
|
+
enumerable: false,
|
|
33098
|
+
value: true,
|
|
33099
|
+
writable: false
|
|
33100
|
+
});
|
|
33101
|
+
tool.execute = wrappedExecute;
|
|
33102
|
+
} catch (error) {
|
|
33103
|
+
logInstrumentationError4("Pi Coding Agent tool wrapping", error);
|
|
33104
|
+
}
|
|
33105
|
+
}
|
|
33106
|
+
}
|
|
33107
|
+
async function startPiLlmSpan(state, model, context, property, options) {
|
|
32271
33108
|
const metadata = {
|
|
32272
33109
|
...extractModelMetadata2(model),
|
|
32273
33110
|
...extractStreamOptionsMetadata(options),
|
|
32274
33111
|
...extractToolMetadata(context.tools),
|
|
32275
|
-
"pi_coding_agent.operation":
|
|
33112
|
+
"pi_coding_agent.operation": `agent.${property}`
|
|
32276
33113
|
};
|
|
32277
33114
|
const span = startSpan(
|
|
32278
33115
|
withSpanInstrumentationName(
|
|
@@ -32438,35 +33275,26 @@ async function startPiToolSpan(state, event) {
|
|
|
32438
33275
|
if (!event.toolCallId || state.activeToolSpans.has(event.toolCallId)) {
|
|
32439
33276
|
return;
|
|
32440
33277
|
}
|
|
32441
|
-
const restoreAutoInstrumentation = enterAutoInstrumentationAllowed();
|
|
32442
33278
|
const metadata = {
|
|
32443
33279
|
"gen_ai.tool.call.id": event.toolCallId,
|
|
32444
33280
|
"gen_ai.tool.name": event.toolName,
|
|
32445
33281
|
"pi_coding_agent.tool.name": event.toolName
|
|
32446
33282
|
};
|
|
32447
|
-
|
|
32448
|
-
|
|
32449
|
-
|
|
32450
|
-
{
|
|
32451
|
-
|
|
32452
|
-
|
|
32453
|
-
metadata
|
|
32454
|
-
},
|
|
32455
|
-
name: event.toolName || "tool",
|
|
32456
|
-
parent: await state.span.export(),
|
|
32457
|
-
spanAttributes: { type: "tool" /* TOOL */ }
|
|
33283
|
+
const span = startSpan(
|
|
33284
|
+
withSpanInstrumentationName(
|
|
33285
|
+
{
|
|
33286
|
+
event: {
|
|
33287
|
+
input: event.args,
|
|
33288
|
+
metadata
|
|
32458
33289
|
},
|
|
32459
|
-
|
|
32460
|
-
|
|
32461
|
-
|
|
32462
|
-
|
|
32463
|
-
|
|
32464
|
-
|
|
32465
|
-
|
|
32466
|
-
|
|
32467
|
-
restoreAutoInstrumentation();
|
|
32468
|
-
throw error;
|
|
32469
|
-
}
|
|
33290
|
+
name: event.toolName || "tool",
|
|
33291
|
+
parent: await state.span.export(),
|
|
33292
|
+
spanAttributes: { type: "tool" /* TOOL */ }
|
|
33293
|
+
},
|
|
33294
|
+
INSTRUMENTATION_NAMES.PI_CODING_AGENT
|
|
33295
|
+
)
|
|
33296
|
+
);
|
|
33297
|
+
state.activeToolSpans.set(event.toolCallId, { span });
|
|
32470
33298
|
}
|
|
32471
33299
|
function finishPiToolSpan(state, event) {
|
|
32472
33300
|
const toolState = state.activeToolSpans.get(event.toolCallId);
|
|
@@ -32487,11 +33315,7 @@ function finishPiToolSpan(state, event) {
|
|
|
32487
33315
|
output: event.result
|
|
32488
33316
|
});
|
|
32489
33317
|
} finally {
|
|
32490
|
-
|
|
32491
|
-
toolState.span.end();
|
|
32492
|
-
} finally {
|
|
32493
|
-
toolState.restoreAutoInstrumentation?.();
|
|
32494
|
-
}
|
|
33318
|
+
toolState.span.end();
|
|
32495
33319
|
}
|
|
32496
33320
|
}
|
|
32497
33321
|
function finishPiPromptRun(state, error) {
|
|
@@ -32562,14 +33386,10 @@ function finishPiLlmSpan(promptState, llmState, message, error) {
|
|
|
32562
33386
|
}
|
|
32563
33387
|
function finishOpenToolSpans(state, error) {
|
|
32564
33388
|
for (const [, toolState] of state.activeToolSpans) {
|
|
32565
|
-
|
|
32566
|
-
|
|
32567
|
-
|
|
32568
|
-
|
|
32569
|
-
toolState.span.end();
|
|
32570
|
-
} finally {
|
|
32571
|
-
toolState.restoreAutoInstrumentation?.();
|
|
32572
|
-
}
|
|
33389
|
+
safeLog4(toolState.span, {
|
|
33390
|
+
error: error ? toLoggedError(error) : "Pi tool did not complete"
|
|
33391
|
+
});
|
|
33392
|
+
toolState.span.end();
|
|
32573
33393
|
}
|
|
32574
33394
|
state.activeToolSpans.clear();
|
|
32575
33395
|
}
|
|
@@ -32868,12 +33688,12 @@ var MAX_STRANDS_STRING_ATTACHMENT_CACHE_ENTRIES = 32;
|
|
|
32868
33688
|
var StrandsAgentSDKPlugin = class extends BasePlugin {
|
|
32869
33689
|
activeChildParents = /* @__PURE__ */ new WeakMap();
|
|
32870
33690
|
onEnable() {
|
|
32871
|
-
this.
|
|
32872
|
-
this.
|
|
33691
|
+
this.interceptAgentStream();
|
|
33692
|
+
this.interceptMultiAgentStream(
|
|
32873
33693
|
strandsAgentSDKChannels.graphStream,
|
|
32874
33694
|
"Graph.stream"
|
|
32875
33695
|
);
|
|
32876
|
-
this.
|
|
33696
|
+
this.interceptMultiAgentStream(
|
|
32877
33697
|
strandsAgentSDKChannels.swarmStream,
|
|
32878
33698
|
"Swarm.stream"
|
|
32879
33699
|
);
|
|
@@ -32884,122 +33704,92 @@ var StrandsAgentSDKPlugin = class extends BasePlugin {
|
|
|
32884
33704
|
}
|
|
32885
33705
|
this.unsubscribers = [];
|
|
32886
33706
|
}
|
|
32887
|
-
|
|
32888
|
-
|
|
32889
|
-
|
|
32890
|
-
|
|
32891
|
-
|
|
32892
|
-
|
|
32893
|
-
|
|
32894
|
-
|
|
32895
|
-
|
|
32896
|
-
|
|
32897
|
-
|
|
32898
|
-
|
|
32899
|
-
|
|
32900
|
-
|
|
32901
|
-
|
|
32902
|
-
|
|
32903
|
-
const result = event.result;
|
|
32904
|
-
if (isAsyncIterable(result)) {
|
|
32905
|
-
patchStreamIfNeeded(result, {
|
|
32906
|
-
aroundNext: (callback) => runWithAutoInstrumentationSuppressed(callback),
|
|
32907
|
-
onChunk: (chunk) => handleAgentStreamEvent(state, chunk),
|
|
32908
|
-
onComplete: () => {
|
|
32909
|
-
finalizeAgentStream(state);
|
|
32910
|
-
states.delete(event);
|
|
32911
|
-
},
|
|
32912
|
-
onError: (error) => {
|
|
32913
|
-
finalizeAgentStream(state, error);
|
|
32914
|
-
states.delete(event);
|
|
32915
|
-
}
|
|
32916
|
-
});
|
|
32917
|
-
return;
|
|
32918
|
-
}
|
|
32919
|
-
finalizeAgentStream(state, void 0, result);
|
|
32920
|
-
states.delete(event);
|
|
32921
|
-
},
|
|
32922
|
-
error: (event) => {
|
|
32923
|
-
const state = states.get(event);
|
|
32924
|
-
if (!state || !event.error) {
|
|
32925
|
-
return;
|
|
32926
|
-
}
|
|
32927
|
-
finalizeAgentStream(state, event.error);
|
|
32928
|
-
states.delete(event);
|
|
32929
|
-
}
|
|
32930
|
-
};
|
|
32931
|
-
channel.subscribe(handlers);
|
|
32932
|
-
this.unsubscribers.push(() => {
|
|
32933
|
-
unbindAutoInstrumentationSuppression?.();
|
|
32934
|
-
channel.unsubscribe(handlers);
|
|
32935
|
-
});
|
|
33707
|
+
interceptAgentStream() {
|
|
33708
|
+
this.unsubscribers.push(
|
|
33709
|
+
strandsAgentSDKChannels.agentStream.intercept(
|
|
33710
|
+
(target, thisArg, args, additional) => instrumentStrandsStreamInvocation({
|
|
33711
|
+
finalize: finalizeAgentStream,
|
|
33712
|
+
handleChunk: handleAgentStreamEvent,
|
|
33713
|
+
invoke: () => Reflect.apply(target, thisArg, args),
|
|
33714
|
+
name: "Strands Agent SDK",
|
|
33715
|
+
start: () => startAgentStream(
|
|
33716
|
+
args[0],
|
|
33717
|
+
extractAgent(additional.agent, thisArg),
|
|
33718
|
+
this.activeChildParents
|
|
33719
|
+
)
|
|
33720
|
+
})
|
|
33721
|
+
)
|
|
33722
|
+
);
|
|
32936
33723
|
}
|
|
32937
|
-
|
|
32938
|
-
|
|
32939
|
-
|
|
32940
|
-
|
|
32941
|
-
|
|
32942
|
-
|
|
32943
|
-
|
|
32944
|
-
|
|
32945
|
-
|
|
32946
|
-
|
|
32947
|
-
|
|
32948
|
-
|
|
32949
|
-
|
|
32950
|
-
|
|
32951
|
-
|
|
32952
|
-
|
|
32953
|
-
|
|
32954
|
-
|
|
32955
|
-
|
|
32956
|
-
}
|
|
32957
|
-
|
|
32958
|
-
|
|
32959
|
-
|
|
32960
|
-
|
|
32961
|
-
|
|
32962
|
-
|
|
32963
|
-
|
|
32964
|
-
|
|
32965
|
-
|
|
32966
|
-
|
|
32967
|
-
|
|
32968
|
-
|
|
32969
|
-
|
|
32970
|
-
|
|
32971
|
-
|
|
32972
|
-
|
|
32973
|
-
|
|
32974
|
-
|
|
32975
|
-
|
|
32976
|
-
|
|
32977
|
-
|
|
32978
|
-
|
|
32979
|
-
this.activeChildParents,
|
|
32980
|
-
void 0,
|
|
32981
|
-
result
|
|
33724
|
+
interceptMultiAgentStream(channel, operation) {
|
|
33725
|
+
this.unsubscribers.push(
|
|
33726
|
+
channel.intercept(
|
|
33727
|
+
(target, thisArg, args, additional) => instrumentStrandsStreamInvocation({
|
|
33728
|
+
finalize: (state, error, output) => finalizeMultiAgentStream(
|
|
33729
|
+
state,
|
|
33730
|
+
this.activeChildParents,
|
|
33731
|
+
error,
|
|
33732
|
+
output
|
|
33733
|
+
),
|
|
33734
|
+
handleChunk: (state, chunk) => handleMultiAgentStreamEvent(state, chunk, this.activeChildParents),
|
|
33735
|
+
invoke: () => Reflect.apply(target, thisArg, args),
|
|
33736
|
+
name: "Strands multi-agent",
|
|
33737
|
+
start: () => startMultiAgentStream(
|
|
33738
|
+
args[0],
|
|
33739
|
+
extractOrchestrator(additional.orchestrator, thisArg),
|
|
33740
|
+
operation,
|
|
33741
|
+
this.activeChildParents
|
|
33742
|
+
)
|
|
33743
|
+
})
|
|
33744
|
+
)
|
|
33745
|
+
);
|
|
33746
|
+
}
|
|
33747
|
+
};
|
|
33748
|
+
function instrumentStrandsStreamInvocation(options) {
|
|
33749
|
+
let state;
|
|
33750
|
+
try {
|
|
33751
|
+
state = options.start();
|
|
33752
|
+
} catch (error) {
|
|
33753
|
+
debugLogger.error(`Error starting ${options.name} instrumentation:`, error);
|
|
33754
|
+
}
|
|
33755
|
+
let result;
|
|
33756
|
+
try {
|
|
33757
|
+
result = runWithAutoInstrumentationSuppressed(options.invoke);
|
|
33758
|
+
} catch (error) {
|
|
33759
|
+
if (state) {
|
|
33760
|
+
try {
|
|
33761
|
+
options.finalize(state, error);
|
|
33762
|
+
} catch (instrumentationError) {
|
|
33763
|
+
debugLogger.error(
|
|
33764
|
+
`Error handling ${options.name} instrumentation failure:`,
|
|
33765
|
+
instrumentationError
|
|
32982
33766
|
);
|
|
32983
|
-
states.delete(event);
|
|
32984
|
-
},
|
|
32985
|
-
error: (event) => {
|
|
32986
|
-
const state = states.get(event);
|
|
32987
|
-
if (!state || !event.error) {
|
|
32988
|
-
return;
|
|
32989
|
-
}
|
|
32990
|
-
finalizeMultiAgentStream(state, this.activeChildParents, event.error);
|
|
32991
|
-
states.delete(event);
|
|
32992
33767
|
}
|
|
32993
|
-
}
|
|
32994
|
-
|
|
32995
|
-
this.unsubscribers.push(() => {
|
|
32996
|
-
unbindAutoInstrumentationSuppression?.();
|
|
32997
|
-
tracingChannel.unsubscribe(handlers);
|
|
32998
|
-
});
|
|
33768
|
+
}
|
|
33769
|
+
throw error;
|
|
32999
33770
|
}
|
|
33000
|
-
|
|
33001
|
-
|
|
33002
|
-
|
|
33771
|
+
if (state) {
|
|
33772
|
+
try {
|
|
33773
|
+
if (isAsyncIterable(result)) {
|
|
33774
|
+
patchStreamIfNeeded(result, {
|
|
33775
|
+
aroundNext: (callback) => runWithAutoInstrumentationSuppressed(callback),
|
|
33776
|
+
onChunk: (chunk) => options.handleChunk(state, chunk),
|
|
33777
|
+
onComplete: () => options.finalize(state),
|
|
33778
|
+
onError: (error) => options.finalize(state, error)
|
|
33779
|
+
});
|
|
33780
|
+
} else {
|
|
33781
|
+
options.finalize(state, void 0, result);
|
|
33782
|
+
}
|
|
33783
|
+
} catch (error) {
|
|
33784
|
+
debugLogger.error(
|
|
33785
|
+
`Error finalizing ${options.name} instrumentation:`,
|
|
33786
|
+
error
|
|
33787
|
+
);
|
|
33788
|
+
}
|
|
33789
|
+
}
|
|
33790
|
+
return result;
|
|
33791
|
+
}
|
|
33792
|
+
function startAgentStream(input, agent, activeChildParents) {
|
|
33003
33793
|
const model = agent?.model;
|
|
33004
33794
|
const metadata = {
|
|
33005
33795
|
...extractAgentMetadata2(agent),
|
|
@@ -33009,17 +33799,14 @@ function startAgentStream(event, activeChildParents) {
|
|
|
33009
33799
|
};
|
|
33010
33800
|
const parentSpan = agent ? getOnlyChildParent(activeChildParents, agent) : void 0;
|
|
33011
33801
|
const attachmentCache = createStrandsAttachmentCache();
|
|
33012
|
-
const
|
|
33013
|
-
event.arguments[0],
|
|
33014
|
-
attachmentCache
|
|
33015
|
-
);
|
|
33802
|
+
const processedInput = processStrandsInputAttachments(input, attachmentCache);
|
|
33016
33803
|
const span = parentSpan ? withCurrent(
|
|
33017
33804
|
parentSpan,
|
|
33018
33805
|
() => startSpan(
|
|
33019
33806
|
withSpanInstrumentationName(
|
|
33020
33807
|
{
|
|
33021
33808
|
event: {
|
|
33022
|
-
input,
|
|
33809
|
+
input: processedInput,
|
|
33023
33810
|
metadata
|
|
33024
33811
|
},
|
|
33025
33812
|
name: formatAgentSpanName(agent),
|
|
@@ -33032,7 +33819,7 @@ function startAgentStream(event, activeChildParents) {
|
|
|
33032
33819
|
withSpanInstrumentationName(
|
|
33033
33820
|
{
|
|
33034
33821
|
event: {
|
|
33035
|
-
input,
|
|
33822
|
+
input: processedInput,
|
|
33036
33823
|
metadata
|
|
33037
33824
|
},
|
|
33038
33825
|
name: formatAgentSpanName(agent),
|
|
@@ -33050,22 +33837,21 @@ function startAgentStream(event, activeChildParents) {
|
|
|
33050
33837
|
startTime: getCurrentUnixTimestamp()
|
|
33051
33838
|
};
|
|
33052
33839
|
}
|
|
33053
|
-
function startMultiAgentStream(
|
|
33054
|
-
const orchestrator = extractOrchestrator(event);
|
|
33840
|
+
function startMultiAgentStream(input, orchestrator, operation, activeChildParents) {
|
|
33055
33841
|
const metadata = {
|
|
33056
33842
|
"strands.operation": operation,
|
|
33057
33843
|
provider: "strands",
|
|
33058
33844
|
...orchestrator?.id ? { "strands.orchestrator.id": orchestrator.id } : {}
|
|
33059
33845
|
};
|
|
33060
33846
|
const parentSpan = orchestrator ? getOnlyChildParent(activeChildParents, orchestrator) : void 0;
|
|
33061
|
-
const
|
|
33847
|
+
const processedInput = processStrandsInputAttachments(input);
|
|
33062
33848
|
const span = parentSpan ? withCurrent(
|
|
33063
33849
|
parentSpan,
|
|
33064
33850
|
() => startSpan(
|
|
33065
33851
|
withSpanInstrumentationName(
|
|
33066
33852
|
{
|
|
33067
33853
|
event: {
|
|
33068
|
-
input,
|
|
33854
|
+
input: processedInput,
|
|
33069
33855
|
metadata
|
|
33070
33856
|
},
|
|
33071
33857
|
name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
|
|
@@ -33078,7 +33864,7 @@ function startMultiAgentStream(event, operation, activeChildParents) {
|
|
|
33078
33864
|
withSpanInstrumentationName(
|
|
33079
33865
|
{
|
|
33080
33866
|
event: {
|
|
33081
|
-
input,
|
|
33867
|
+
input: processedInput,
|
|
33082
33868
|
metadata
|
|
33083
33869
|
},
|
|
33084
33870
|
name: operation === "Graph.stream" ? "Strands Graph" : "Strands Swarm",
|
|
@@ -33449,12 +34235,12 @@ function finalizeMultiAgentStream(state, activeChildParents, error, output) {
|
|
|
33449
34235
|
});
|
|
33450
34236
|
state.span.end();
|
|
33451
34237
|
}
|
|
33452
|
-
function extractAgent(
|
|
33453
|
-
const candidate =
|
|
34238
|
+
function extractAgent(agent, self) {
|
|
34239
|
+
const candidate = agent ?? self;
|
|
33454
34240
|
return isObject(candidate) && typeof candidate.stream === "function" ? candidate : void 0;
|
|
33455
34241
|
}
|
|
33456
|
-
function extractOrchestrator(
|
|
33457
|
-
const candidate =
|
|
34242
|
+
function extractOrchestrator(orchestrator, self) {
|
|
34243
|
+
const candidate = orchestrator ?? self;
|
|
33458
34244
|
return isObject(candidate) && typeof candidate.stream === "function" ? candidate : void 0;
|
|
33459
34245
|
}
|
|
33460
34246
|
function extractAgentMetadata2(agent) {
|
|
@@ -35703,7 +36489,6 @@ async function summarizeAndFlush(experiment, options) {
|
|
|
35703
36489
|
}
|
|
35704
36490
|
|
|
35705
36491
|
export {
|
|
35706
|
-
debugLogger,
|
|
35707
36492
|
IDGenerator,
|
|
35708
36493
|
UUIDGenerator,
|
|
35709
36494
|
OTELIDGenerator,
|