braintrust 3.27.0 → 3.28.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/dev/dist/index.d.mts +519 -186
- package/dev/dist/index.d.ts +519 -186
- package/dev/dist/index.js +1837 -1009
- package/dev/dist/index.mjs +1172 -344
- package/dist/apply-auto-instrumentation.js +262 -210
- package/dist/apply-auto-instrumentation.mjs +54 -2
- package/dist/auto-instrumentations/bundler/esbuild.cjs +81 -2
- package/dist/auto-instrumentations/bundler/esbuild.mjs +2 -2
- package/dist/auto-instrumentations/bundler/next.cjs +81 -2
- package/dist/auto-instrumentations/bundler/next.mjs +3 -3
- package/dist/auto-instrumentations/bundler/rollup.cjs +81 -2
- package/dist/auto-instrumentations/bundler/rollup.mjs +2 -2
- package/dist/auto-instrumentations/bundler/vite.cjs +81 -2
- package/dist/auto-instrumentations/bundler/vite.mjs +2 -2
- package/dist/auto-instrumentations/bundler/webpack-loader.cjs +81 -2
- package/dist/auto-instrumentations/bundler/webpack.cjs +81 -2
- package/dist/auto-instrumentations/bundler/webpack.mjs +3 -3
- package/dist/auto-instrumentations/{chunk-XEYKUBLY.mjs → chunk-26PKVUKB.mjs} +80 -2
- package/dist/auto-instrumentations/{chunk-BW33ULMW.mjs → chunk-HD35AM3M.mjs} +1 -1
- package/dist/auto-instrumentations/{chunk-ZNHTSSGI.mjs → chunk-NP7V4XB2.mjs} +2 -1
- package/dist/auto-instrumentations/hook.mjs +236 -30
- package/dist/auto-instrumentations/index.cjs +2 -1
- package/dist/auto-instrumentations/index.mjs +1 -1
- package/dist/browser.d.mts +628 -53
- package/dist/browser.d.ts +628 -53
- package/dist/browser.js +2301 -284
- package/dist/browser.mjs +2301 -284
- package/dist/{chunk-MF7NU6BT.js → chunk-BBE7SNRV.js} +34 -4
- package/dist/{chunk-QRHGVBKU.js → chunk-OBBWQW6K.js} +1799 -1023
- package/dist/{chunk-YKD22IMR.mjs → chunk-UPFNQCGB.mjs} +966 -190
- package/dist/{chunk-CZM5JIQL.mjs → chunk-ZHUHZWFY.mjs} +33 -3
- package/dist/cli.js +1224 -398
- package/dist/edge-light.d.mts +1 -1
- package/dist/edge-light.d.ts +1 -1
- package/dist/edge-light.js +2301 -284
- package/dist/edge-light.mjs +2301 -284
- package/dist/index.d.mts +1212 -637
- package/dist/index.d.ts +1212 -637
- package/dist/index.js +1880 -590
- package/dist/index.mjs +1450 -160
- package/dist/instrumentation/index.d.mts +190 -6
- package/dist/instrumentation/index.d.ts +190 -6
- package/dist/instrumentation/index.js +823 -116
- package/dist/instrumentation/index.mjs +823 -116
- 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 +2301 -284
- package/dist/workerd.mjs +2301 -284
- package/package.json +2 -3
- package/util/dist/index.d.mts +1545 -100
- package/util/dist/index.d.ts +1545 -100
package/dist/browser.js
CHANGED
|
@@ -38,6 +38,8 @@ __export(browser_exports, {
|
|
|
38
38
|
BRAINTRUST_PARENT_KEY: () => BRAINTRUST_PARENT_KEY,
|
|
39
39
|
BaseAttachment: () => BaseAttachment,
|
|
40
40
|
BaseExperiment: () => BaseExperiment,
|
|
41
|
+
BatchScorer: () => BatchScorer,
|
|
42
|
+
BatchTask: () => BatchTask,
|
|
41
43
|
BraintrustLangChainCallbackHandler: () => BraintrustLangChainCallbackHandler,
|
|
42
44
|
BraintrustMiddleware: () => BraintrustMiddleware,
|
|
43
45
|
BraintrustObservabilityExporter: () => BraintrustObservabilityExporter,
|
|
@@ -51,6 +53,8 @@ __export(browser_exports, {
|
|
|
51
53
|
DEFAULT_MAX_REQUEST_SIZE: () => DEFAULT_MAX_REQUEST_SIZE,
|
|
52
54
|
Dataset: () => Dataset2,
|
|
53
55
|
DatasetPipeline: () => DatasetPipeline,
|
|
56
|
+
DurableEvalMemoryStore: () => DurableEvalMemoryStore,
|
|
57
|
+
DurableEvalRedisStore: () => DurableEvalRedisStore,
|
|
54
58
|
ERR_PERMALINK: () => ERR_PERMALINK,
|
|
55
59
|
Eval: () => Eval,
|
|
56
60
|
EvalResultWithSummary: () => EvalResultWithSummary,
|
|
@@ -109,6 +113,7 @@ __export(browser_exports, {
|
|
|
109
113
|
deepCopyEvent: () => deepCopyEvent,
|
|
110
114
|
default: () => exports_exports,
|
|
111
115
|
defaultErrorScoreHandler: () => defaultErrorScoreHandler,
|
|
116
|
+
defineDurableEval: () => defineDurableEval,
|
|
112
117
|
deserializePlainStringAsJSON: () => deserializePlainStringAsJSON,
|
|
113
118
|
devNullWritableStream: () => devNullWritableStream,
|
|
114
119
|
evaluatorDefinitionSchema: () => evaluatorDefinitionSchema,
|
|
@@ -204,7 +209,8 @@ __export(browser_exports, {
|
|
|
204
209
|
wrapPiCodingAgentSDK: () => wrapPiCodingAgentSDK,
|
|
205
210
|
wrapStrandsAgentSDK: () => wrapStrandsAgentSDK,
|
|
206
211
|
wrapTraced: () => wrapTraced,
|
|
207
|
-
wrapVitest: () => wrapVitest
|
|
212
|
+
wrapVitest: () => wrapVitest,
|
|
213
|
+
wrapVoyageAI: () => wrapVoyageAI
|
|
208
214
|
});
|
|
209
215
|
module.exports = __toCommonJS(browser_exports);
|
|
210
216
|
|
|
@@ -1771,12 +1777,12 @@ function base64ToUint8Array(base64) {
|
|
|
1771
1777
|
return uint8Array;
|
|
1772
1778
|
}
|
|
1773
1779
|
function uint8ArrayToString(uint8Array) {
|
|
1774
|
-
const
|
|
1775
|
-
return
|
|
1780
|
+
const decoder2 = new TextDecoder("utf-8");
|
|
1781
|
+
return decoder2.decode(uint8Array);
|
|
1776
1782
|
}
|
|
1777
1783
|
function stringToUint8Array(str) {
|
|
1778
|
-
const
|
|
1779
|
-
return
|
|
1784
|
+
const encoder2 = new TextEncoder();
|
|
1785
|
+
return encoder2.encode(str);
|
|
1780
1786
|
}
|
|
1781
1787
|
|
|
1782
1788
|
// util/span_identifier_v3.ts
|
|
@@ -2680,7 +2686,8 @@ var AclObjectType = import_v36.z.union([
|
|
|
2680
2686
|
"org_member",
|
|
2681
2687
|
"project_log",
|
|
2682
2688
|
"org_project",
|
|
2683
|
-
"org_audit_logs"
|
|
2689
|
+
"org_audit_logs",
|
|
2690
|
+
"project_group"
|
|
2684
2691
|
]),
|
|
2685
2692
|
import_v36.z.null()
|
|
2686
2693
|
]);
|
|
@@ -2809,7 +2816,8 @@ var AsyncScoringState = import_v36.z.union([
|
|
|
2809
2816
|
token: import_v36.z.string(),
|
|
2810
2817
|
function_ids: import_v36.z.array(import_v36.z.unknown()),
|
|
2811
2818
|
skip_logging: import_v36.z.union([import_v36.z.boolean(), import_v36.z.null()]).optional(),
|
|
2812
|
-
triggered_functions: import_v36.z.union([import_v36.z.record(TriggeredFunctionState), import_v36.z.null()]).optional()
|
|
2819
|
+
triggered_functions: import_v36.z.union([import_v36.z.record(TriggeredFunctionState), import_v36.z.null()]).optional(),
|
|
2820
|
+
last_triggered_xact_id: import_v36.z.union([import_v36.z.string(), import_v36.z.number(), import_v36.z.null()]).optional()
|
|
2813
2821
|
}),
|
|
2814
2822
|
import_v36.z.object({ status: import_v36.z.literal("disabled") }),
|
|
2815
2823
|
import_v36.z.null(),
|
|
@@ -2878,7 +2886,7 @@ var FunctionTypeEnum = import_v36.z.enum([
|
|
|
2878
2886
|
"parameters",
|
|
2879
2887
|
"sandbox"
|
|
2880
2888
|
]);
|
|
2881
|
-
var
|
|
2889
|
+
var FacetPreprocessorId = import_v36.z.union([
|
|
2882
2890
|
import_v36.z.object({
|
|
2883
2891
|
type: import_v36.z.literal("function"),
|
|
2884
2892
|
id: import_v36.z.string(),
|
|
@@ -2889,10 +2897,23 @@ var NullableSavedFunctionId = import_v36.z.union([
|
|
|
2889
2897
|
name: import_v36.z.string(),
|
|
2890
2898
|
function_type: FunctionTypeEnum.optional().default("scorer")
|
|
2891
2899
|
}),
|
|
2900
|
+
import_v36.z.object({ type: import_v36.z.literal("inline"), code: import_v36.z.string().min(1) }),
|
|
2892
2901
|
import_v36.z.null()
|
|
2893
2902
|
]);
|
|
2903
|
+
var SavedFunctionId = import_v36.z.union([
|
|
2904
|
+
import_v36.z.object({
|
|
2905
|
+
type: import_v36.z.literal("function"),
|
|
2906
|
+
id: import_v36.z.string(),
|
|
2907
|
+
version: import_v36.z.string().optional()
|
|
2908
|
+
}),
|
|
2909
|
+
import_v36.z.object({
|
|
2910
|
+
type: import_v36.z.literal("global"),
|
|
2911
|
+
name: import_v36.z.string(),
|
|
2912
|
+
function_type: FunctionTypeEnum.optional().default("scorer")
|
|
2913
|
+
})
|
|
2914
|
+
]);
|
|
2894
2915
|
var TopicMapGenerationSettings = import_v36.z.object({
|
|
2895
|
-
algorithm: import_v36.z.enum(["hdbscan", "kmeans"]),
|
|
2916
|
+
algorithm: import_v36.z.enum(["hdbscan", "kmeans", "community"]),
|
|
2896
2917
|
dimension_reduction: import_v36.z.enum(["umap", "pca", "none"]),
|
|
2897
2918
|
sample_size: import_v36.z.number().int().gt(0).optional(),
|
|
2898
2919
|
n_clusters: import_v36.z.number().int().gt(0).optional(),
|
|
@@ -2904,6 +2925,7 @@ var TopicMapGenerationSettings = import_v36.z.object({
|
|
|
2904
2925
|
var TopicMapData = import_v36.z.object({
|
|
2905
2926
|
type: import_v36.z.literal("topic_map"),
|
|
2906
2927
|
source_facet: import_v36.z.string(),
|
|
2928
|
+
source_facet_function: SavedFunctionId.and(import_v36.z.unknown()).optional(),
|
|
2907
2929
|
embedding_model: import_v36.z.string(),
|
|
2908
2930
|
bundle_key: import_v36.z.string().optional(),
|
|
2909
2931
|
report_key: import_v36.z.string().optional(),
|
|
@@ -2917,7 +2939,7 @@ var TopicMapData = import_v36.z.object({
|
|
|
2917
2939
|
});
|
|
2918
2940
|
var BatchedFacetData = import_v36.z.object({
|
|
2919
2941
|
type: import_v36.z.literal("batched_facet"),
|
|
2920
|
-
preprocessor:
|
|
2942
|
+
preprocessor: FacetPreprocessorId.optional(),
|
|
2921
2943
|
facets: import_v36.z.array(
|
|
2922
2944
|
import_v36.z.object({
|
|
2923
2945
|
name: import_v36.z.string(),
|
|
@@ -3178,18 +3200,6 @@ var ObjectReferenceNullish = import_v36.z.union([
|
|
|
3178
3200
|
}),
|
|
3179
3201
|
import_v36.z.null()
|
|
3180
3202
|
]);
|
|
3181
|
-
var SavedFunctionId = import_v36.z.union([
|
|
3182
|
-
import_v36.z.object({
|
|
3183
|
-
type: import_v36.z.literal("function"),
|
|
3184
|
-
id: import_v36.z.string(),
|
|
3185
|
-
version: import_v36.z.string().optional()
|
|
3186
|
-
}),
|
|
3187
|
-
import_v36.z.object({
|
|
3188
|
-
type: import_v36.z.literal("global"),
|
|
3189
|
-
name: import_v36.z.string(),
|
|
3190
|
-
function_type: FunctionTypeEnum.optional().default("scorer")
|
|
3191
|
-
})
|
|
3192
|
-
]);
|
|
3193
3203
|
var DatasetEvent = import_v36.z.object({
|
|
3194
3204
|
id: import_v36.z.string(),
|
|
3195
3205
|
_xact_id: import_v36.z.string(),
|
|
@@ -3411,7 +3421,7 @@ var ExtendedSavedFunctionId = import_v36.z.union([
|
|
|
3411
3421
|
]);
|
|
3412
3422
|
var FacetData = import_v36.z.object({
|
|
3413
3423
|
type: import_v36.z.literal("facet"),
|
|
3414
|
-
preprocessor:
|
|
3424
|
+
preprocessor: FacetPreprocessorId.optional(),
|
|
3415
3425
|
prompt: import_v36.z.string(),
|
|
3416
3426
|
model: import_v36.z.string().optional(),
|
|
3417
3427
|
embedding_model: import_v36.z.string().optional(),
|
|
@@ -3916,6 +3926,19 @@ var MessageRole = import_v36.z.enum([
|
|
|
3916
3926
|
"model",
|
|
3917
3927
|
"developer"
|
|
3918
3928
|
]);
|
|
3929
|
+
var NullableSavedFunctionId = import_v36.z.union([
|
|
3930
|
+
import_v36.z.object({
|
|
3931
|
+
type: import_v36.z.literal("function"),
|
|
3932
|
+
id: import_v36.z.string(),
|
|
3933
|
+
version: import_v36.z.string().optional()
|
|
3934
|
+
}),
|
|
3935
|
+
import_v36.z.object({
|
|
3936
|
+
type: import_v36.z.literal("global"),
|
|
3937
|
+
name: import_v36.z.string(),
|
|
3938
|
+
function_type: FunctionTypeEnum.optional().default("scorer")
|
|
3939
|
+
}),
|
|
3940
|
+
import_v36.z.null()
|
|
3941
|
+
]);
|
|
3919
3942
|
var ObjectReference = import_v36.z.object({
|
|
3920
3943
|
object_type: import_v36.z.enum([
|
|
3921
3944
|
"project_logs",
|
|
@@ -3937,6 +3960,7 @@ var TraceScope = import_v36.z.object({
|
|
|
3937
3960
|
});
|
|
3938
3961
|
var OnlineScoreConfig = import_v36.z.union([
|
|
3939
3962
|
import_v36.z.object({
|
|
3963
|
+
status: AutomationStatus.optional(),
|
|
3940
3964
|
sampling_rate: import_v36.z.number().gte(0).lte(1),
|
|
3941
3965
|
scorers: import_v36.z.array(SavedFunctionId),
|
|
3942
3966
|
btql_filter: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
|
|
@@ -4017,6 +4041,72 @@ var Project = import_v36.z.object({
|
|
|
4017
4041
|
user_id: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
|
|
4018
4042
|
settings: ProjectSettings.optional()
|
|
4019
4043
|
});
|
|
4044
|
+
var WindowedAutomationConfig = import_v36.z.object({
|
|
4045
|
+
event_type: import_v36.z.literal("windowed"),
|
|
4046
|
+
product_origin: import_v36.z.union([import_v36.z.literal("patterns"), import_v36.z.null()]).optional(),
|
|
4047
|
+
status: AutomationStatus.optional(),
|
|
4048
|
+
threshold: import_v36.z.object({
|
|
4049
|
+
calculation: import_v36.z.object({
|
|
4050
|
+
type: import_v36.z.literal("btql"),
|
|
4051
|
+
btql_query: import_v36.z.string().min(1),
|
|
4052
|
+
output: import_v36.z.object({
|
|
4053
|
+
type: import_v36.z.literal("scalar"),
|
|
4054
|
+
value_column: import_v36.z.string().min(1)
|
|
4055
|
+
})
|
|
4056
|
+
}),
|
|
4057
|
+
policy: import_v36.z.object({
|
|
4058
|
+
condition: import_v36.z.object({
|
|
4059
|
+
type: import_v36.z.literal("threshold"),
|
|
4060
|
+
operator: import_v36.z.enum(["lt", "lte", "gt", "gte", "eq", "neq"]),
|
|
4061
|
+
threshold: import_v36.z.number()
|
|
4062
|
+
}),
|
|
4063
|
+
pending_seconds: import_v36.z.number().int().gte(0).lte(2592e3),
|
|
4064
|
+
no_data_behavior: import_v36.z.enum(["keep_last", "resolve", "alert"]),
|
|
4065
|
+
renotify_interval_seconds: import_v36.z.union([import_v36.z.number(), import_v36.z.null()]).optional(),
|
|
4066
|
+
notify_on_recovery: import_v36.z.boolean().optional().default(true)
|
|
4067
|
+
})
|
|
4068
|
+
}).optional(),
|
|
4069
|
+
window: import_v36.z.object({
|
|
4070
|
+
window_seconds: import_v36.z.number().int().gte(1).lte(2592e3),
|
|
4071
|
+
schedule: import_v36.z.union([
|
|
4072
|
+
import_v36.z.object({
|
|
4073
|
+
type: import_v36.z.literal("interval"),
|
|
4074
|
+
evaluation_interval_seconds: import_v36.z.number().int().gte(1).lte(2592e3)
|
|
4075
|
+
}),
|
|
4076
|
+
import_v36.z.object({
|
|
4077
|
+
type: import_v36.z.literal("cron"),
|
|
4078
|
+
cron_expression: import_v36.z.string().min(1),
|
|
4079
|
+
timezone: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional()
|
|
4080
|
+
})
|
|
4081
|
+
]),
|
|
4082
|
+
evaluation_delay_seconds: import_v36.z.number().int().gte(0).lte(2592e3)
|
|
4083
|
+
}),
|
|
4084
|
+
loop: import_v36.z.object({
|
|
4085
|
+
prompt: import_v36.z.string().min(1).max(1e4),
|
|
4086
|
+
include_trigger_input: import_v36.z.boolean().optional().default(false),
|
|
4087
|
+
agent_slug: import_v36.z.string().min(1),
|
|
4088
|
+
auto_approve_tools: import_v36.z.array(import_v36.z.string().min(1)).optional().default([]),
|
|
4089
|
+
harness: import_v36.z.enum(["native", "codex", "claude-code"]).optional(),
|
|
4090
|
+
model: import_v36.z.string().min(1).optional(),
|
|
4091
|
+
reasoning_effort: import_v36.z.enum(["none", "minimal", "low", "medium", "high", "xhigh", "max"]).optional()
|
|
4092
|
+
}).optional(),
|
|
4093
|
+
actions: import_v36.z.array(
|
|
4094
|
+
import_v36.z.union([
|
|
4095
|
+
import_v36.z.object({
|
|
4096
|
+
type: import_v36.z.literal("webhook"),
|
|
4097
|
+
url: import_v36.z.string(),
|
|
4098
|
+
formatting_prompt: import_v36.z.string().min(1).max(1e4).optional()
|
|
4099
|
+
}),
|
|
4100
|
+
import_v36.z.object({
|
|
4101
|
+
type: import_v36.z.literal("slack"),
|
|
4102
|
+
workspace_id: import_v36.z.string(),
|
|
4103
|
+
channel: import_v36.z.string(),
|
|
4104
|
+
message_template: import_v36.z.string().optional(),
|
|
4105
|
+
formatting_prompt: import_v36.z.string().min(1).max(1e4).optional()
|
|
4106
|
+
})
|
|
4107
|
+
])
|
|
4108
|
+
).max(20).optional().default([])
|
|
4109
|
+
});
|
|
4020
4110
|
var TopicAutomationFacetModel = import_v36.z.union([
|
|
4021
4111
|
import_v36.z.enum(["brain-facet-latest", "brain-facet-1", "brain-facet-2"]),
|
|
4022
4112
|
import_v36.z.null()
|
|
@@ -4058,7 +4148,8 @@ var TopicDigestAutomationConfig = import_v36.z.object({
|
|
|
4058
4148
|
type: import_v36.z.literal("slack"),
|
|
4059
4149
|
workspace_id: import_v36.z.string(),
|
|
4060
4150
|
channel: import_v36.z.string(),
|
|
4061
|
-
message_template: import_v36.z.string().optional()
|
|
4151
|
+
message_template: import_v36.z.string().optional(),
|
|
4152
|
+
formatting_prompt: import_v36.z.string().min(1).max(1e4).optional()
|
|
4062
4153
|
}),
|
|
4063
4154
|
topic_map_function_ids: import_v36.z.array(import_v36.z.string()).max(10).optional()
|
|
4064
4155
|
});
|
|
@@ -4072,15 +4163,21 @@ var ProjectAutomation = import_v36.z.object({
|
|
|
4072
4163
|
config: import_v36.z.union([
|
|
4073
4164
|
import_v36.z.object({
|
|
4074
4165
|
event_type: import_v36.z.literal("logs"),
|
|
4166
|
+
status: AutomationStatus.optional(),
|
|
4075
4167
|
btql_filter: import_v36.z.string(),
|
|
4076
4168
|
interval_seconds: import_v36.z.number().gte(1).lte(2592e3),
|
|
4077
4169
|
action: import_v36.z.union([
|
|
4078
|
-
import_v36.z.object({
|
|
4170
|
+
import_v36.z.object({
|
|
4171
|
+
type: import_v36.z.literal("webhook"),
|
|
4172
|
+
url: import_v36.z.string(),
|
|
4173
|
+
formatting_prompt: import_v36.z.string().min(1).max(1e4).optional()
|
|
4174
|
+
}),
|
|
4079
4175
|
import_v36.z.object({
|
|
4080
4176
|
type: import_v36.z.literal("slack"),
|
|
4081
4177
|
workspace_id: import_v36.z.string(),
|
|
4082
4178
|
channel: import_v36.z.string(),
|
|
4083
|
-
message_template: import_v36.z.string().optional()
|
|
4179
|
+
message_template: import_v36.z.string().optional(),
|
|
4180
|
+
formatting_prompt: import_v36.z.string().min(1).max(1e4).optional()
|
|
4084
4181
|
})
|
|
4085
4182
|
])
|
|
4086
4183
|
}),
|
|
@@ -4131,21 +4228,38 @@ var ProjectAutomation = import_v36.z.object({
|
|
|
4131
4228
|
}),
|
|
4132
4229
|
import_v36.z.object({
|
|
4133
4230
|
event_type: import_v36.z.literal("environment_update"),
|
|
4231
|
+
status: AutomationStatus.optional(),
|
|
4134
4232
|
environment_filter: import_v36.z.array(import_v36.z.string()).optional(),
|
|
4135
4233
|
action: import_v36.z.union([
|
|
4136
|
-
import_v36.z.object({
|
|
4234
|
+
import_v36.z.object({
|
|
4235
|
+
type: import_v36.z.literal("webhook"),
|
|
4236
|
+
url: import_v36.z.string(),
|
|
4237
|
+
formatting_prompt: import_v36.z.string().min(1).max(1e4).optional()
|
|
4238
|
+
}),
|
|
4137
4239
|
import_v36.z.object({
|
|
4138
4240
|
type: import_v36.z.literal("slack"),
|
|
4139
4241
|
workspace_id: import_v36.z.string(),
|
|
4140
4242
|
channel: import_v36.z.string(),
|
|
4141
|
-
message_template: import_v36.z.string().optional()
|
|
4243
|
+
message_template: import_v36.z.string().optional(),
|
|
4244
|
+
formatting_prompt: import_v36.z.string().min(1).max(1e4).optional()
|
|
4142
4245
|
})
|
|
4143
4246
|
])
|
|
4144
4247
|
}),
|
|
4248
|
+
WindowedAutomationConfig,
|
|
4145
4249
|
TopicAutomationConfig,
|
|
4146
4250
|
TopicDigestAutomationConfig
|
|
4147
4251
|
])
|
|
4148
4252
|
});
|
|
4253
|
+
var ProjectGroup = import_v36.z.object({
|
|
4254
|
+
id: import_v36.z.string().uuid(),
|
|
4255
|
+
org_id: import_v36.z.string().uuid(),
|
|
4256
|
+
user_id: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
|
|
4257
|
+
created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
|
|
4258
|
+
name: import_v36.z.string(),
|
|
4259
|
+
description: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
|
|
4260
|
+
deleted_at: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
|
|
4261
|
+
member_projects: import_v36.z.array(import_v36.z.string().uuid()).max(1e4)
|
|
4262
|
+
});
|
|
4149
4263
|
var ProjectLogsEvent = import_v36.z.object({
|
|
4150
4264
|
id: import_v36.z.string(),
|
|
4151
4265
|
_xact_id: import_v36.z.string(),
|
|
@@ -4363,7 +4477,8 @@ var RunEval = import_v36.z.object({
|
|
|
4363
4477
|
dataset_environment: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
|
|
4364
4478
|
_internal_btql: import_v36.z.union([import_v36.z.object({}).partial().passthrough(), import_v36.z.null()]).optional()
|
|
4365
4479
|
}),
|
|
4366
|
-
import_v36.z.object({ data: import_v36.z.array(import_v36.z.unknown()) })
|
|
4480
|
+
import_v36.z.object({ data: import_v36.z.array(import_v36.z.unknown()) }),
|
|
4481
|
+
import_v36.z.object({ experiment_name: import_v36.z.string() })
|
|
4367
4482
|
]),
|
|
4368
4483
|
name: import_v36.z.string().optional(),
|
|
4369
4484
|
parameters: import_v36.z.object({}).partial().passthrough().optional(),
|
|
@@ -4568,7 +4683,9 @@ var View = import_v36.z.object({
|
|
|
4568
4683
|
"for_review_datasets"
|
|
4569
4684
|
]),
|
|
4570
4685
|
name: import_v36.z.string(),
|
|
4686
|
+
description: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
|
|
4571
4687
|
created: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
|
|
4688
|
+
updated_at: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
|
|
4572
4689
|
view_data: ViewData.optional(),
|
|
4573
4690
|
options: ViewOptions.optional(),
|
|
4574
4691
|
user_id: import_v36.z.union([import_v36.z.string(), import_v36.z.null()]).optional(),
|
|
@@ -4902,7 +5019,7 @@ var BraintrustStream = class _BraintrustStream {
|
|
|
4902
5019
|
}
|
|
4903
5020
|
};
|
|
4904
5021
|
function btStreamParser() {
|
|
4905
|
-
const
|
|
5022
|
+
const decoder2 = new TextDecoder();
|
|
4906
5023
|
let parser;
|
|
4907
5024
|
return new TransformStream({
|
|
4908
5025
|
async start(controller) {
|
|
@@ -4919,7 +5036,7 @@ function btStreamParser() {
|
|
|
4919
5036
|
},
|
|
4920
5037
|
async transform(chunk, controller) {
|
|
4921
5038
|
if (chunk instanceof Uint8Array) {
|
|
4922
|
-
parser.feed(
|
|
5039
|
+
parser.feed(decoder2.decode(chunk, { stream: true }));
|
|
4923
5040
|
} else if (typeof chunk === "string") {
|
|
4924
5041
|
parser.feed(chunk);
|
|
4925
5042
|
} else {
|
|
@@ -4927,7 +5044,7 @@ function btStreamParser() {
|
|
|
4927
5044
|
}
|
|
4928
5045
|
},
|
|
4929
5046
|
async flush(controller) {
|
|
4930
|
-
const tail =
|
|
5047
|
+
const tail = decoder2.decode();
|
|
4931
5048
|
if (tail) {
|
|
4932
5049
|
parser.feed(tail);
|
|
4933
5050
|
}
|
|
@@ -4936,7 +5053,7 @@ function btStreamParser() {
|
|
|
4936
5053
|
});
|
|
4937
5054
|
}
|
|
4938
5055
|
function createFinalValuePassThroughStream(onFinal, onError) {
|
|
4939
|
-
const
|
|
5056
|
+
const decoder2 = new TextDecoder();
|
|
4940
5057
|
const textChunks = [];
|
|
4941
5058
|
const jsonChunks = [];
|
|
4942
5059
|
const reasoningChunks = [];
|
|
@@ -4949,10 +5066,10 @@ function createFinalValuePassThroughStream(onFinal, onError) {
|
|
|
4949
5066
|
data: chunk
|
|
4950
5067
|
});
|
|
4951
5068
|
} else if (chunk instanceof Uint8Array) {
|
|
4952
|
-
textChunks.push(
|
|
5069
|
+
textChunks.push(decoder2.decode(chunk));
|
|
4953
5070
|
controller.enqueue({
|
|
4954
5071
|
type: "text_delta",
|
|
4955
|
-
data:
|
|
5072
|
+
data: decoder2.decode(chunk)
|
|
4956
5073
|
});
|
|
4957
5074
|
} else if (braintrustStreamChunkSchema.safeParse(chunk).success) {
|
|
4958
5075
|
const chunkType = chunk.type;
|
|
@@ -5693,12 +5810,13 @@ var INSTRUMENTATION_NAMES = {
|
|
|
5693
5810
|
OPENROUTER: "openrouter",
|
|
5694
5811
|
OPENROUTER_AGENT: "openrouter-agent",
|
|
5695
5812
|
PI_CODING_AGENT: "pi-coding-agent",
|
|
5696
|
-
STRANDS_AGENT_SDK: "strands-agent-sdk"
|
|
5813
|
+
STRANDS_AGENT_SDK: "strands-agent-sdk",
|
|
5814
|
+
VOYAGEAI: "voyageai"
|
|
5697
5815
|
};
|
|
5698
5816
|
var INTERNAL_SPAN_INSTRUMENTATION_NAME = /* @__PURE__ */ Symbol.for(
|
|
5699
5817
|
"braintrust.spanInstrumentationName"
|
|
5700
5818
|
);
|
|
5701
|
-
var SDK_VERSION = true ? "3.
|
|
5819
|
+
var SDK_VERSION = true ? "3.28.0" : "0.0.0";
|
|
5702
5820
|
function withSpanInstrumentationName(args, instrumentationName) {
|
|
5703
5821
|
return {
|
|
5704
5822
|
...args,
|
|
@@ -5893,6 +6011,9 @@ function applyMaskingToField(maskingFunction, data, fieldName) {
|
|
|
5893
6011
|
var INITIAL_SPAN_WRITE_AS_MERGE = /* @__PURE__ */ Symbol(
|
|
5894
6012
|
"braintrust.initial-span-write-as-merge"
|
|
5895
6013
|
);
|
|
6014
|
+
var RESUME_SPAN_WITHOUT_INITIAL_WRITE = /* @__PURE__ */ Symbol(
|
|
6015
|
+
"braintrust.resume-span-without-initial-write"
|
|
6016
|
+
);
|
|
5896
6017
|
var INTERNAL_SPAN_CONTEXT = /* @__PURE__ */ Symbol("braintrust.internal-span-context");
|
|
5897
6018
|
var BRAINTRUST_CURRENT_SPAN_STORE = /* @__PURE__ */ Symbol.for(
|
|
5898
6019
|
"braintrust.currentSpanStore"
|
|
@@ -7116,6 +7237,30 @@ function updateSpan({
|
|
|
7116
7237
|
event
|
|
7117
7238
|
});
|
|
7118
7239
|
}
|
|
7240
|
+
function _internalResumeSpan({
|
|
7241
|
+
exported,
|
|
7242
|
+
state
|
|
7243
|
+
}) {
|
|
7244
|
+
const resolvedState = state ?? _globalState;
|
|
7245
|
+
const components = SpanComponentsV4.fromStr(exported);
|
|
7246
|
+
const { row_id, root_span_id, span_id } = components.data;
|
|
7247
|
+
if (!row_id || !root_span_id || !span_id) {
|
|
7248
|
+
throw new Error("Only exported root spans can be resumed");
|
|
7249
|
+
}
|
|
7250
|
+
return new SpanImpl({
|
|
7251
|
+
state: resolvedState,
|
|
7252
|
+
parentObjectType: components.data.object_type,
|
|
7253
|
+
parentObjectId: new LazyValue(
|
|
7254
|
+
spanComponentsToObjectIdLambda(resolvedState, components)
|
|
7255
|
+
),
|
|
7256
|
+
parentComputeObjectMetadataArgs: void 0,
|
|
7257
|
+
parentSpanIds: { parentSpanIds: [], rootSpanId: root_span_id },
|
|
7258
|
+
spanId: span_id,
|
|
7259
|
+
event: { id: row_id },
|
|
7260
|
+
propagatedEvent: components.data.propagated_event ?? void 0,
|
|
7261
|
+
[RESUME_SPAN_WITHOUT_INITIAL_WRITE]: true
|
|
7262
|
+
});
|
|
7263
|
+
}
|
|
7119
7264
|
function spanComponentsToObjectIdLambda(state, components) {
|
|
7120
7265
|
if (components.data.object_id) {
|
|
7121
7266
|
const ret = components.data.object_id;
|
|
@@ -9996,7 +10141,7 @@ var ObjectFetcher = class {
|
|
|
9996
10141
|
const objectId = await this.id;
|
|
9997
10142
|
const batchLimit = batchSize ?? DEFAULT_FETCH_BATCH_SIZE;
|
|
9998
10143
|
const internalLimit = getInternalBtqlLimit(this._internal_btql);
|
|
9999
|
-
|
|
10144
|
+
let remainingLimit = internalLimit;
|
|
10000
10145
|
const internalBtqlWithoutReservedQueryKeys = Object.fromEntries(
|
|
10001
10146
|
Object.entries(this._internal_btql ?? {}).filter(
|
|
10002
10147
|
([key]) => key !== "cursor" && key !== "limit" && key !== "select" && key !== "from"
|
|
@@ -10005,6 +10150,10 @@ var ObjectFetcher = class {
|
|
|
10005
10150
|
let cursor = void 0;
|
|
10006
10151
|
let iterations = 0;
|
|
10007
10152
|
while (true) {
|
|
10153
|
+
if (remainingLimit !== void 0 && remainingLimit <= 0) {
|
|
10154
|
+
return;
|
|
10155
|
+
}
|
|
10156
|
+
const limit = remainingLimit === void 0 ? batchLimit : Math.min(batchLimit, remainingLimit);
|
|
10008
10157
|
const resp = await state.apiConn().post(
|
|
10009
10158
|
`btql`,
|
|
10010
10159
|
{
|
|
@@ -10044,7 +10193,14 @@ var ObjectFetcher = class {
|
|
|
10044
10193
|
const respJson = await resp.json();
|
|
10045
10194
|
const mutate = this.mutateRecord;
|
|
10046
10195
|
for (const record of respJson.data ?? []) {
|
|
10047
|
-
|
|
10196
|
+
if (remainingLimit !== void 0 && remainingLimit <= 0) {
|
|
10197
|
+
return;
|
|
10198
|
+
}
|
|
10199
|
+
const mutatedRecord = mutate ? mutate(record) : record;
|
|
10200
|
+
if (remainingLimit !== void 0) {
|
|
10201
|
+
remainingLimit--;
|
|
10202
|
+
}
|
|
10203
|
+
yield mutatedRecord;
|
|
10048
10204
|
}
|
|
10049
10205
|
if (!respJson.cursor) {
|
|
10050
10206
|
break;
|
|
@@ -10564,7 +10720,9 @@ var SpanImpl = class _SpanImpl {
|
|
|
10564
10720
|
this._rootSpanId = resolvedIds.rootSpanId;
|
|
10565
10721
|
this._spanParents = resolvedIds.spanParents;
|
|
10566
10722
|
this.isMerge = args[INITIAL_SPAN_WRITE_AS_MERGE] === true;
|
|
10567
|
-
|
|
10723
|
+
if (!args[RESUME_SPAN_WITHOUT_INITIAL_WRITE]) {
|
|
10724
|
+
this.logInternal({ event, internalData });
|
|
10725
|
+
}
|
|
10568
10726
|
this.isMerge = true;
|
|
10569
10727
|
}
|
|
10570
10728
|
getParentInfo() {
|
|
@@ -13220,6 +13378,22 @@ function processInputAttachments(input) {
|
|
|
13220
13378
|
};
|
|
13221
13379
|
}
|
|
13222
13380
|
}
|
|
13381
|
+
const voyageBase64Key = node.type === "image_base64" ? Object.hasOwn(node, "imageBase64") ? "imageBase64" : "image_base64" : node.type === "video_base64" ? Object.hasOwn(node, "videoBase64") ? "videoBase64" : "video_base64" : void 0;
|
|
13382
|
+
const voyageBase64Value = voyageBase64Key ? node[voyageBase64Key] : void 0;
|
|
13383
|
+
if (voyageBase64Key && typeof voyageBase64Value === "string" && voyageBase64Value.startsWith("data:")) {
|
|
13384
|
+
const mediaType = inferMediaTypeFromDataUrl(
|
|
13385
|
+
voyageBase64Value,
|
|
13386
|
+
node.type === "video_base64" ? "video/mp4" : "image/png"
|
|
13387
|
+
);
|
|
13388
|
+
const filename = `${node.type === "video_base64" ? "video" : "image"}.${getExtensionFromMediaType(mediaType)}`;
|
|
13389
|
+
const attachment = toAttachment(voyageBase64Value, mediaType, filename);
|
|
13390
|
+
if (attachment) {
|
|
13391
|
+
return {
|
|
13392
|
+
...node,
|
|
13393
|
+
[voyageBase64Key]: attachment
|
|
13394
|
+
};
|
|
13395
|
+
}
|
|
13396
|
+
}
|
|
13223
13397
|
if (node.type === "file" && node.file && typeof node.file === "object" && typeof node.file.file_data === "string" && node.file.file_data.startsWith("data:")) {
|
|
13224
13398
|
const mediaType = inferMediaTypeFromDataUrl(
|
|
13225
13399
|
node.file.file_data,
|
|
@@ -14567,12 +14741,30 @@ function logInstrumentationError(context, error) {
|
|
|
14567
14741
|
|
|
14568
14742
|
// src/wrappers/anthropic-tokens-util.ts
|
|
14569
14743
|
function finalizeAnthropicTokens(metrics) {
|
|
14570
|
-
const
|
|
14571
|
-
|
|
14744
|
+
const hasSplitCacheCreationTokens = metrics.prompt_cache_creation_5m_tokens !== void 0 || metrics.prompt_cache_creation_1h_tokens !== void 0;
|
|
14745
|
+
const splitCacheCreationTokens = (metrics.prompt_cache_creation_5m_tokens || 0) + (metrics.prompt_cache_creation_1h_tokens || 0);
|
|
14746
|
+
const aggregateCacheCreationTokens = metrics.prompt_cache_creation_tokens || 0;
|
|
14747
|
+
const effectiveCacheCreationTokens = Math.max(
|
|
14748
|
+
aggregateCacheCreationTokens,
|
|
14749
|
+
splitCacheCreationTokens
|
|
14750
|
+
);
|
|
14751
|
+
const prompt_tokens = (metrics.prompt_tokens || 0) + (metrics.prompt_cached_tokens || 0) + effectiveCacheCreationTokens;
|
|
14752
|
+
const finalized = {
|
|
14572
14753
|
...metrics,
|
|
14573
14754
|
prompt_tokens,
|
|
14574
14755
|
tokens: prompt_tokens + (metrics.completion_tokens || 0)
|
|
14575
14756
|
};
|
|
14757
|
+
if (hasSplitCacheCreationTokens && splitCacheCreationTokens >= aggregateCacheCreationTokens) {
|
|
14758
|
+
delete finalized.prompt_cache_creation_tokens;
|
|
14759
|
+
}
|
|
14760
|
+
return finalized;
|
|
14761
|
+
}
|
|
14762
|
+
function toNumericMetrics(metrics) {
|
|
14763
|
+
return Object.fromEntries(
|
|
14764
|
+
Object.entries(metrics).filter(
|
|
14765
|
+
(entry) => entry[1] !== void 0
|
|
14766
|
+
)
|
|
14767
|
+
);
|
|
14576
14768
|
}
|
|
14577
14769
|
function extractAnthropicCacheTokens(cacheReadTokens = 0, cacheCreationTokens = 0) {
|
|
14578
14770
|
const cacheTokens = {};
|
|
@@ -15178,6 +15370,18 @@ function parseMetricsFromUsage2(usage) {
|
|
|
15178
15370
|
saveIfExistsTo("output_tokens", "completion_tokens");
|
|
15179
15371
|
saveIfExistsTo("cache_read_input_tokens", "prompt_cached_tokens");
|
|
15180
15372
|
saveIfExistsTo("cache_creation_input_tokens", "prompt_cache_creation_tokens");
|
|
15373
|
+
if (isObject(usage.cache_creation)) {
|
|
15374
|
+
const cacheCreation = usage.cache_creation;
|
|
15375
|
+
for (const [source, target] of [
|
|
15376
|
+
["ephemeral_5m_input_tokens", "prompt_cache_creation_5m_tokens"],
|
|
15377
|
+
["ephemeral_1h_input_tokens", "prompt_cache_creation_1h_tokens"]
|
|
15378
|
+
]) {
|
|
15379
|
+
const value = cacheCreation[source];
|
|
15380
|
+
if (typeof value === "number") {
|
|
15381
|
+
metrics[target] = value;
|
|
15382
|
+
}
|
|
15383
|
+
}
|
|
15384
|
+
}
|
|
15181
15385
|
if (isObject(usage.server_tool_use)) {
|
|
15182
15386
|
for (const [name, value] of Object.entries(usage.server_tool_use)) {
|
|
15183
15387
|
if (typeof value === "number") {
|
|
@@ -20476,37 +20680,97 @@ function seedTaskToolUseIdMapping(taskIdToToolUseId, message) {
|
|
|
20476
20680
|
taskIdToToolUseId.set(message.task_id, message.tool_use_id);
|
|
20477
20681
|
}
|
|
20478
20682
|
}
|
|
20479
|
-
function
|
|
20480
|
-
|
|
20481
|
-
|
|
20482
|
-
|
|
20483
|
-
usage = message.message?.usage;
|
|
20484
|
-
} else if (message.type === "result") {
|
|
20485
|
-
usage = message.usage;
|
|
20486
|
-
}
|
|
20683
|
+
function tokenCount(value) {
|
|
20684
|
+
return typeof value === "number" && Number.isFinite(value) && Number.isInteger(value) && value >= 0 ? value : void 0;
|
|
20685
|
+
}
|
|
20686
|
+
function copyUsage(usage) {
|
|
20487
20687
|
if (!usage || typeof usage !== "object") {
|
|
20488
|
-
return
|
|
20688
|
+
return void 0;
|
|
20689
|
+
}
|
|
20690
|
+
const copy = {};
|
|
20691
|
+
for (const key of [
|
|
20692
|
+
"input_tokens",
|
|
20693
|
+
"output_tokens",
|
|
20694
|
+
"cache_read_input_tokens",
|
|
20695
|
+
"cache_creation_input_tokens"
|
|
20696
|
+
]) {
|
|
20697
|
+
const value = tokenCount(Reflect.get(usage, key));
|
|
20698
|
+
if (value !== void 0) {
|
|
20699
|
+
copy[key] = value;
|
|
20700
|
+
}
|
|
20701
|
+
}
|
|
20702
|
+
const cacheCreation = Reflect.get(usage, "cache_creation");
|
|
20703
|
+
if (cacheCreation && typeof cacheCreation === "object") {
|
|
20704
|
+
const cacheCreationCopy = {};
|
|
20705
|
+
for (const key of [
|
|
20706
|
+
"ephemeral_5m_input_tokens",
|
|
20707
|
+
"ephemeral_1h_input_tokens"
|
|
20708
|
+
]) {
|
|
20709
|
+
const value = tokenCount(Reflect.get(cacheCreation, key));
|
|
20710
|
+
if (value !== void 0) {
|
|
20711
|
+
cacheCreationCopy[key] = value;
|
|
20712
|
+
}
|
|
20713
|
+
}
|
|
20714
|
+
if (Object.keys(cacheCreationCopy).length > 0) {
|
|
20715
|
+
copy.cache_creation = cacheCreationCopy;
|
|
20716
|
+
}
|
|
20717
|
+
}
|
|
20718
|
+
return Object.keys(copy).length > 0 ? copy : void 0;
|
|
20719
|
+
}
|
|
20720
|
+
function mergeUsage(base, override) {
|
|
20721
|
+
if (!base || !override) {
|
|
20722
|
+
return override ?? base;
|
|
20723
|
+
}
|
|
20724
|
+
const cacheCreation = base.cache_creation || override.cache_creation ? { ...base.cache_creation, ...override.cache_creation } : void 0;
|
|
20725
|
+
return {
|
|
20726
|
+
...base,
|
|
20727
|
+
...override,
|
|
20728
|
+
...cacheCreation && { cache_creation: cacheCreation }
|
|
20729
|
+
};
|
|
20730
|
+
}
|
|
20731
|
+
function extractUsage(usage, includeOutput) {
|
|
20732
|
+
const metrics = {};
|
|
20733
|
+
if (!usage) {
|
|
20734
|
+
return {};
|
|
20489
20735
|
}
|
|
20490
20736
|
const inputTokens = getNumberProperty(usage, "input_tokens");
|
|
20491
20737
|
if (inputTokens !== void 0) {
|
|
20492
20738
|
metrics.prompt_tokens = inputTokens;
|
|
20493
20739
|
}
|
|
20494
|
-
|
|
20495
|
-
|
|
20496
|
-
|
|
20740
|
+
if (includeOutput) {
|
|
20741
|
+
const outputTokens = getNumberProperty(usage, "output_tokens");
|
|
20742
|
+
if (outputTokens !== void 0) {
|
|
20743
|
+
metrics.completion_tokens = outputTokens;
|
|
20744
|
+
}
|
|
20497
20745
|
}
|
|
20498
20746
|
const cacheReadTokens = getNumberProperty(usage, "cache_read_input_tokens") || 0;
|
|
20499
20747
|
const cacheCreationTokens = getNumberProperty(usage, "cache_creation_input_tokens") || 0;
|
|
20500
|
-
|
|
20501
|
-
|
|
20502
|
-
|
|
20503
|
-
|
|
20504
|
-
|
|
20748
|
+
Object.assign(
|
|
20749
|
+
metrics,
|
|
20750
|
+
extractAnthropicCacheTokens(cacheReadTokens, cacheCreationTokens)
|
|
20751
|
+
);
|
|
20752
|
+
const cacheCreation5mTokens = getNumberProperty(
|
|
20753
|
+
usage.cache_creation,
|
|
20754
|
+
"ephemeral_5m_input_tokens"
|
|
20755
|
+
);
|
|
20756
|
+
const cacheCreation1hTokens = getNumberProperty(
|
|
20757
|
+
usage.cache_creation,
|
|
20758
|
+
"ephemeral_1h_input_tokens"
|
|
20759
|
+
);
|
|
20760
|
+
if (cacheCreation5mTokens !== void 0) {
|
|
20761
|
+
metrics.prompt_cache_creation_5m_tokens = cacheCreation5mTokens;
|
|
20505
20762
|
}
|
|
20506
|
-
if (
|
|
20507
|
-
|
|
20763
|
+
if (cacheCreation1hTokens !== void 0) {
|
|
20764
|
+
metrics.prompt_cache_creation_1h_tokens = cacheCreation1hTokens;
|
|
20508
20765
|
}
|
|
20509
|
-
|
|
20766
|
+
if (Object.keys(metrics).length === 0) {
|
|
20767
|
+
return {};
|
|
20768
|
+
}
|
|
20769
|
+
const finalized = finalizeAnthropicTokens(metrics);
|
|
20770
|
+
if (metrics.completion_tokens === void 0) {
|
|
20771
|
+
delete finalized.tokens;
|
|
20772
|
+
}
|
|
20773
|
+
return toNumericMetrics(finalized);
|
|
20510
20774
|
}
|
|
20511
20775
|
function buildLLMInput(promptMessages, conversationHistory) {
|
|
20512
20776
|
const inputParts = [...promptMessages, ...conversationHistory];
|
|
@@ -20540,16 +20804,16 @@ function buildRootPromptMessages(prompt, capturedPromptMessages) {
|
|
|
20540
20804
|
function formatCapturedMessages(messages) {
|
|
20541
20805
|
return messages.length > 0 ? messages : [];
|
|
20542
20806
|
}
|
|
20543
|
-
async function createLLMSpanForMessages(messages, promptMessages, conversationHistory, options, startTime, parentSpan, existingSpan) {
|
|
20807
|
+
async function createLLMSpanForMessages(messages, promptMessages, conversationHistory, options, startTime, parentSpan, usage, hasFinalOutputUsage, existingSpan) {
|
|
20544
20808
|
if (messages.length === 0) {
|
|
20545
20809
|
return void 0;
|
|
20546
20810
|
}
|
|
20547
20811
|
const lastMessage = messages[messages.length - 1];
|
|
20548
|
-
if (lastMessage.type !== "assistant"
|
|
20812
|
+
if (lastMessage.type !== "assistant") {
|
|
20549
20813
|
return void 0;
|
|
20550
20814
|
}
|
|
20551
|
-
const model = lastMessage.message
|
|
20552
|
-
const
|
|
20815
|
+
const model = lastMessage.message?.model || options.model;
|
|
20816
|
+
const metrics = options.includePartialMessages ? extractUsage(usage, hasFinalOutputUsage) : {};
|
|
20553
20817
|
const input = buildLLMInput(promptMessages, conversationHistory);
|
|
20554
20818
|
const outputs = messages.map(
|
|
20555
20819
|
(m) => m.message?.content && m.message?.role ? { content: m.message.content, role: m.message.role } : void 0
|
|
@@ -20571,8 +20835,8 @@ async function createLLMSpanForMessages(messages, promptMessages, conversationHi
|
|
|
20571
20835
|
);
|
|
20572
20836
|
span.log({
|
|
20573
20837
|
input,
|
|
20574
|
-
metadata: model
|
|
20575
|
-
metrics:
|
|
20838
|
+
metadata: { ...model && { model }, provider: "anthropic" },
|
|
20839
|
+
...Object.keys(metrics).length > 0 ? { metrics } : {},
|
|
20576
20840
|
output: outputs
|
|
20577
20841
|
});
|
|
20578
20842
|
const spanExport = await span.export();
|
|
@@ -20662,11 +20926,17 @@ function prepareLocalToolHandlersInMcpServers(mcpServers) {
|
|
|
20662
20926
|
}
|
|
20663
20927
|
return { hasLocalToolHandlers, localToolHookNames };
|
|
20664
20928
|
}
|
|
20665
|
-
function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers, localToolHookNames, skipLocalToolHooks, subAgentDetailsByToolUseId, subAgentSpans, endedSubAgentSpans) {
|
|
20929
|
+
function createToolTracingHooks(resolveParentSpan, taskIdToToolUseId, toolUseToParent, activeToolSpans, mcpServers, localToolHookNames, skipLocalToolHooks, subAgentDetailsByToolUseId, subAgentSpans, endedSubAgentSpans) {
|
|
20666
20930
|
const preToolUse = async (input, toolUseID) => {
|
|
20667
20931
|
if (input.hook_event_name !== "PreToolUse" || !toolUseID) {
|
|
20668
20932
|
return {};
|
|
20669
20933
|
}
|
|
20934
|
+
if (!toolUseToParent.has(toolUseID) && input.agent_id) {
|
|
20935
|
+
const parentToolUseId = taskIdToToolUseId.get(input.agent_id);
|
|
20936
|
+
if (parentToolUseId) {
|
|
20937
|
+
toolUseToParent.set(toolUseID, parentToolUseId);
|
|
20938
|
+
}
|
|
20939
|
+
}
|
|
20670
20940
|
if (skipLocalToolHooks && (isLocalToolUse(input.tool_name, mcpServers) || localToolHookNames.has(input.tool_name))) {
|
|
20671
20941
|
return {};
|
|
20672
20942
|
}
|
|
@@ -20862,9 +21132,6 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
|
|
|
20862
21132
|
}
|
|
20863
21133
|
const metadata = {
|
|
20864
21134
|
...subAgentDetailsToMetadata(details),
|
|
20865
|
-
...input.agent_transcript_path && {
|
|
20866
|
-
"claude_agent_sdk.agent_transcript_path": input.agent_transcript_path
|
|
20867
|
-
},
|
|
20868
21135
|
"claude_agent_sdk.stop_hook_active": input.stop_hook_active
|
|
20869
21136
|
};
|
|
20870
21137
|
try {
|
|
@@ -20886,7 +21153,7 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
|
|
|
20886
21153
|
subagentStop
|
|
20887
21154
|
};
|
|
20888
21155
|
}
|
|
20889
|
-
function injectTracingHooks(options, resolveParentSpan, activeToolSpans, localToolHookNames, skipLocalToolHooks, subAgentDetailsByToolUseId, subAgentSpans, endedSubAgentSpans) {
|
|
21156
|
+
function injectTracingHooks(options, resolveParentSpan, taskIdToToolUseId, toolUseToParent, activeToolSpans, localToolHookNames, skipLocalToolHooks, subAgentDetailsByToolUseId, subAgentSpans, endedSubAgentSpans) {
|
|
20890
21157
|
const {
|
|
20891
21158
|
preToolUse,
|
|
20892
21159
|
postToolUse,
|
|
@@ -20895,6 +21162,8 @@ function injectTracingHooks(options, resolveParentSpan, activeToolSpans, localTo
|
|
|
20895
21162
|
subagentStop
|
|
20896
21163
|
} = createToolTracingHooks(
|
|
20897
21164
|
resolveParentSpan,
|
|
21165
|
+
taskIdToToolUseId,
|
|
21166
|
+
toolUseToParent,
|
|
20898
21167
|
activeToolSpans,
|
|
20899
21168
|
options.mcpServers,
|
|
20900
21169
|
localToolHookNames,
|
|
@@ -20976,6 +21245,13 @@ async function finalizeCurrentMessageGroup(state) {
|
|
|
20976
21245
|
}
|
|
20977
21246
|
}
|
|
20978
21247
|
const existingLlmSpan = state.activeLlmSpansByParentToolUse.get(parentKey);
|
|
21248
|
+
const lastMessage = state.currentMessages[state.currentMessages.length - 1];
|
|
21249
|
+
const messageId = lastMessage?.message?.id;
|
|
21250
|
+
const usage = state.options.includePartialMessages ? mergeUsage(
|
|
21251
|
+
copyUsage(lastMessage?.message?.usage),
|
|
21252
|
+
messageId ? state.usageByMessageId.get(messageId) : void 0
|
|
21253
|
+
) : void 0;
|
|
21254
|
+
const hasFinalOutputUsage = messageId !== void 0 && state.finalOutputUsageMessageIds.has(messageId);
|
|
20979
21255
|
const llmSpanResult = await createLLMSpanForMessages(
|
|
20980
21256
|
state.currentMessages,
|
|
20981
21257
|
promptMessages,
|
|
@@ -20983,6 +21259,8 @@ async function finalizeCurrentMessageGroup(state) {
|
|
|
20983
21259
|
state.options,
|
|
20984
21260
|
state.currentMessageStartTime,
|
|
20985
21261
|
parentSpan,
|
|
21262
|
+
usage,
|
|
21263
|
+
hasFinalOutputUsage,
|
|
20986
21264
|
existingLlmSpan
|
|
20987
21265
|
);
|
|
20988
21266
|
if (llmSpanResult) {
|
|
@@ -21000,9 +21278,17 @@ async function finalizeCurrentMessageGroup(state) {
|
|
|
21000
21278
|
}
|
|
21001
21279
|
}
|
|
21002
21280
|
state.activeLlmSpansByParentToolUse.delete(parentKey);
|
|
21003
|
-
|
|
21004
|
-
|
|
21005
|
-
state.
|
|
21281
|
+
if (messageId) {
|
|
21282
|
+
state.usageByMessageId.delete(messageId);
|
|
21283
|
+
state.finalOutputUsageMessageIds.delete(messageId);
|
|
21284
|
+
for (const [
|
|
21285
|
+
parent,
|
|
21286
|
+
activeMessageId
|
|
21287
|
+
] of state.activePartialMessageIdByParentKey) {
|
|
21288
|
+
if (activeMessageId === messageId) {
|
|
21289
|
+
state.activePartialMessageIdByParentKey.delete(parent);
|
|
21290
|
+
}
|
|
21291
|
+
}
|
|
21006
21292
|
}
|
|
21007
21293
|
state.currentMessages.length = 0;
|
|
21008
21294
|
}
|
|
@@ -21093,6 +21379,10 @@ async function ensureActiveLlmSpanForParentToolUse(rootSpan, activeLlmSpansByPar
|
|
|
21093
21379
|
);
|
|
21094
21380
|
llmParentSpan = await subAgentSpan.export();
|
|
21095
21381
|
}
|
|
21382
|
+
const racedLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
|
|
21383
|
+
if (racedLlmSpan) {
|
|
21384
|
+
return racedLlmSpan;
|
|
21385
|
+
}
|
|
21096
21386
|
const llmSpan = startSpan(
|
|
21097
21387
|
withSpanInstrumentationName(
|
|
21098
21388
|
{
|
|
@@ -21212,7 +21502,49 @@ async function maybeHandleTaskLifecycleMessage(state, message) {
|
|
|
21212
21502
|
}
|
|
21213
21503
|
return true;
|
|
21214
21504
|
}
|
|
21505
|
+
function handlePartialUsageMessage(state, message) {
|
|
21506
|
+
if (message.type !== "stream_event") {
|
|
21507
|
+
return false;
|
|
21508
|
+
}
|
|
21509
|
+
const event = message.event;
|
|
21510
|
+
if (!event || typeof event !== "object") {
|
|
21511
|
+
return true;
|
|
21512
|
+
}
|
|
21513
|
+
const parentKey = llmParentKey(message.parent_tool_use_id ?? null);
|
|
21514
|
+
if (event.type === "message_start") {
|
|
21515
|
+
const messageId2 = event.message?.id;
|
|
21516
|
+
const usage = copyUsage(event.message?.usage);
|
|
21517
|
+
if (messageId2) {
|
|
21518
|
+
state.activePartialMessageIdByParentKey.set(parentKey, messageId2);
|
|
21519
|
+
if (usage) {
|
|
21520
|
+
state.usageByMessageId.set(messageId2, usage);
|
|
21521
|
+
}
|
|
21522
|
+
}
|
|
21523
|
+
return true;
|
|
21524
|
+
}
|
|
21525
|
+
const messageId = state.activePartialMessageIdByParentKey.get(parentKey);
|
|
21526
|
+
if (!messageId) {
|
|
21527
|
+
return true;
|
|
21528
|
+
}
|
|
21529
|
+
if (event.type === "message_delta") {
|
|
21530
|
+
const update = copyUsage(event.usage);
|
|
21531
|
+
if (update) {
|
|
21532
|
+
const usage = state.usageByMessageId.get(messageId) ?? {};
|
|
21533
|
+
Object.assign(usage, update);
|
|
21534
|
+
state.usageByMessageId.set(messageId, usage);
|
|
21535
|
+
if (update.output_tokens !== void 0) {
|
|
21536
|
+
state.finalOutputUsageMessageIds.add(messageId);
|
|
21537
|
+
}
|
|
21538
|
+
}
|
|
21539
|
+
} else if (event.type === "message_stop") {
|
|
21540
|
+
state.activePartialMessageIdByParentKey.delete(parentKey);
|
|
21541
|
+
}
|
|
21542
|
+
return true;
|
|
21543
|
+
}
|
|
21215
21544
|
async function handleStreamMessage(state, message) {
|
|
21545
|
+
if (handlePartialUsageMessage(state, message)) {
|
|
21546
|
+
return;
|
|
21547
|
+
}
|
|
21216
21548
|
maybeTrackToolUseContext(state, message);
|
|
21217
21549
|
if (await maybeHandleTaskLifecycleMessage(state, message)) {
|
|
21218
21550
|
return;
|
|
@@ -21259,36 +21591,9 @@ async function handleStreamMessage(state, message) {
|
|
|
21259
21591
|
);
|
|
21260
21592
|
state.currentMessages.push(message);
|
|
21261
21593
|
}
|
|
21262
|
-
if (message.type !== "result"
|
|
21594
|
+
if (message.type !== "result") {
|
|
21263
21595
|
return;
|
|
21264
21596
|
}
|
|
21265
|
-
const finalUsageMetrics = extractUsageFromMessage(message);
|
|
21266
|
-
if (state.currentMessages.length > 0 && finalUsageMetrics.completion_tokens !== void 0) {
|
|
21267
|
-
const lastMessage = state.currentMessages[state.currentMessages.length - 1];
|
|
21268
|
-
if (lastMessage?.message?.usage) {
|
|
21269
|
-
const adjustedTokens = finalUsageMetrics.completion_tokens - state.accumulatedOutputTokens;
|
|
21270
|
-
if (adjustedTokens >= 0) {
|
|
21271
|
-
lastMessage.message.usage.output_tokens = adjustedTokens;
|
|
21272
|
-
}
|
|
21273
|
-
const resultUsage = message.usage;
|
|
21274
|
-
if (resultUsage && typeof resultUsage === "object") {
|
|
21275
|
-
const cacheReadTokens = getNumberProperty(
|
|
21276
|
-
resultUsage,
|
|
21277
|
-
"cache_read_input_tokens"
|
|
21278
|
-
);
|
|
21279
|
-
if (cacheReadTokens !== void 0) {
|
|
21280
|
-
lastMessage.message.usage.cache_read_input_tokens = cacheReadTokens;
|
|
21281
|
-
}
|
|
21282
|
-
const cacheCreationTokens = getNumberProperty(
|
|
21283
|
-
resultUsage,
|
|
21284
|
-
"cache_creation_input_tokens"
|
|
21285
|
-
);
|
|
21286
|
-
if (cacheCreationTokens !== void 0) {
|
|
21287
|
-
lastMessage.message.usage.cache_creation_input_tokens = cacheCreationTokens;
|
|
21288
|
-
}
|
|
21289
|
-
}
|
|
21290
|
-
}
|
|
21291
|
-
}
|
|
21292
21597
|
const metadata = {};
|
|
21293
21598
|
if (message.num_turns !== void 0) {
|
|
21294
21599
|
metadata.num_turns = message.num_turns;
|
|
@@ -21296,8 +21601,12 @@ async function handleStreamMessage(state, message) {
|
|
|
21296
21601
|
if (message.session_id !== void 0) {
|
|
21297
21602
|
metadata.session_id = message.session_id;
|
|
21298
21603
|
}
|
|
21299
|
-
|
|
21300
|
-
|
|
21604
|
+
const metrics = state.options.includePartialMessages ? {} : extractUsage(copyUsage(message.usage), true);
|
|
21605
|
+
if (Object.keys(metadata).length > 0 || Object.keys(metrics).length > 0) {
|
|
21606
|
+
state.span.log({
|
|
21607
|
+
...Object.keys(metadata).length > 0 ? { metadata } : {},
|
|
21608
|
+
...Object.keys(metrics).length > 0 ? { metrics } : {}
|
|
21609
|
+
});
|
|
21301
21610
|
}
|
|
21302
21611
|
}
|
|
21303
21612
|
async function finalizeQuerySpan(state) {
|
|
@@ -21321,6 +21630,9 @@ async function finalizeQuerySpan(state) {
|
|
|
21321
21630
|
llmSpan.end();
|
|
21322
21631
|
}
|
|
21323
21632
|
state.activeLlmSpansByParentToolUse.clear();
|
|
21633
|
+
state.activePartialMessageIdByParentKey.clear();
|
|
21634
|
+
state.finalOutputUsageMessageIds.clear();
|
|
21635
|
+
state.usageByMessageId.clear();
|
|
21324
21636
|
for (const toolSpan of state.activeToolSpans.values()) {
|
|
21325
21637
|
toolSpan.end();
|
|
21326
21638
|
}
|
|
@@ -21445,6 +21757,8 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
21445
21757
|
const optionsWithHooks = injectTracingHooks(
|
|
21446
21758
|
options,
|
|
21447
21759
|
resolveToolUseParentSpan,
|
|
21760
|
+
taskIdToToolUseId,
|
|
21761
|
+
toolUseToParent,
|
|
21448
21762
|
activeToolSpans,
|
|
21449
21763
|
localToolHookNames,
|
|
21450
21764
|
skipLocalToolHooks,
|
|
@@ -21455,8 +21769,8 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
21455
21769
|
params.options = optionsWithHooks;
|
|
21456
21770
|
event.arguments[0] = params;
|
|
21457
21771
|
spans.set(event, {
|
|
21458
|
-
accumulatedOutputTokens: 0,
|
|
21459
21772
|
activeLlmSpansByParentToolUse,
|
|
21773
|
+
activePartialMessageIdByParentKey: /* @__PURE__ */ new Map(),
|
|
21460
21774
|
activeToolSpans,
|
|
21461
21775
|
conversationHistoryByParentKey,
|
|
21462
21776
|
capturedPromptMessages,
|
|
@@ -21464,6 +21778,7 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
21464
21778
|
currentMessageStartTime: startTime,
|
|
21465
21779
|
currentMessages: [],
|
|
21466
21780
|
endedSubAgentSpans,
|
|
21781
|
+
finalOutputUsageMessageIds: /* @__PURE__ */ new Set(),
|
|
21467
21782
|
finalResults: [],
|
|
21468
21783
|
options: optionsWithHooks,
|
|
21469
21784
|
originalPrompt,
|
|
@@ -21479,6 +21794,7 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
21479
21794
|
latestLlmParentBySubAgentToolUse,
|
|
21480
21795
|
latestRootLlmParentRef,
|
|
21481
21796
|
toolUseToParent,
|
|
21797
|
+
usageByMessageId: /* @__PURE__ */ new Map(),
|
|
21482
21798
|
localToolContext
|
|
21483
21799
|
});
|
|
21484
21800
|
},
|
|
@@ -23953,9 +24269,9 @@ function extractEmbedPromptTokenCount(response) {
|
|
|
23953
24269
|
let sawAny = false;
|
|
23954
24270
|
for (const embedding of embeddings) {
|
|
23955
24271
|
const embeddingStats = tryToDict(tryToDict(embedding)?.statistics);
|
|
23956
|
-
const
|
|
23957
|
-
if (typeof
|
|
23958
|
-
total +=
|
|
24272
|
+
const tokenCount2 = embeddingStats?.tokenCount;
|
|
24273
|
+
if (typeof tokenCount2 === "number" && Number.isFinite(tokenCount2)) {
|
|
24274
|
+
total += tokenCount2;
|
|
23959
24275
|
sawAny = true;
|
|
23960
24276
|
}
|
|
23961
24277
|
}
|
|
@@ -30850,7 +31166,7 @@ function getStringProperty2(obj, key) {
|
|
|
30850
31166
|
return typeof value === "string" ? value : void 0;
|
|
30851
31167
|
}
|
|
30852
31168
|
function extractMetricsFromUsage(usage) {
|
|
30853
|
-
const
|
|
31169
|
+
const rawMetrics = {
|
|
30854
31170
|
prompt_tokens: usage.inputTokens,
|
|
30855
31171
|
completion_tokens: usage.outputTokens,
|
|
30856
31172
|
...extractAnthropicCacheTokens(
|
|
@@ -30859,10 +31175,10 @@ function extractMetricsFromUsage(usage) {
|
|
|
30859
31175
|
)
|
|
30860
31176
|
};
|
|
30861
31177
|
if (usage.reasoningTokens !== void 0) {
|
|
30862
|
-
|
|
30863
|
-
|
|
31178
|
+
rawMetrics.completion_reasoning_tokens = usage.reasoningTokens;
|
|
31179
|
+
rawMetrics.reasoning_tokens = usage.reasoningTokens;
|
|
30864
31180
|
}
|
|
30865
|
-
|
|
31181
|
+
const metrics = finalizeAnthropicTokens(rawMetrics);
|
|
30866
31182
|
const metadata = {
|
|
30867
31183
|
model: usage.model
|
|
30868
31184
|
};
|
|
@@ -31801,17 +32117,20 @@ var FlueObserveBridge = class {
|
|
|
31801
32117
|
return;
|
|
31802
32118
|
}
|
|
31803
32119
|
const metadata = {
|
|
32120
|
+
...event.runId ? this.runsById.get(event.runId)?.metadata : {},
|
|
31804
32121
|
...extractEventMetadata(event),
|
|
31805
32122
|
"flue.operation": event.operationKind,
|
|
31806
32123
|
provider: "flue"
|
|
31807
32124
|
};
|
|
31808
32125
|
const parent = this.parentSpanForEvent(event);
|
|
31809
|
-
const
|
|
32126
|
+
const args = {
|
|
31810
32127
|
name: `flue.${event.operationKind}`,
|
|
31811
32128
|
spanAttributes: { type: "task" /* TASK */ },
|
|
31812
32129
|
startTime: eventTime(event.timestamp),
|
|
31813
32130
|
event: { metadata }
|
|
31814
|
-
}
|
|
32131
|
+
};
|
|
32132
|
+
const runSpan = event.runId ? this.runsById.get(event.runId)?.span : void 0;
|
|
32133
|
+
const span = event.operationKind === "prompt" && (!parent || parent === runSpan) ? startFlueRootSpan(args) : startFlueSpan(parent, args);
|
|
31815
32134
|
this.operationsById.set(event.operationId, { metadata, span });
|
|
31816
32135
|
}
|
|
31817
32136
|
handleOperation(event) {
|
|
@@ -31826,6 +32145,11 @@ var FlueObserveBridge = class {
|
|
|
31826
32145
|
...event.isError !== void 0 ? { "flue.is_error": event.isError } : {},
|
|
31827
32146
|
...event.usage ? { "flue.usage": event.usage } : {}
|
|
31828
32147
|
};
|
|
32148
|
+
const input = flueOperationInput(event);
|
|
32149
|
+
if (!state.loggedInput && input !== void 0) {
|
|
32150
|
+
safeLog3(state.span, { input });
|
|
32151
|
+
state.loggedInput = true;
|
|
32152
|
+
}
|
|
31829
32153
|
this.finishPendingChildrenForOperation(event, output);
|
|
31830
32154
|
safeLog3(state.span, {
|
|
31831
32155
|
...event.isError ? { error: toLoggedError(event.errorInfo ?? event.error) } : {},
|
|
@@ -31842,6 +32166,8 @@ var FlueObserveBridge = class {
|
|
|
31842
32166
|
return;
|
|
31843
32167
|
}
|
|
31844
32168
|
const input = flueTurnRequestInput(event);
|
|
32169
|
+
const operation = event.operationId ? this.operationsById.get(event.operationId) : void 0;
|
|
32170
|
+
const turnInput = prepareFlueTurnInput(event, input, operation);
|
|
31845
32171
|
const model = flueTurnRequestModel(event);
|
|
31846
32172
|
const provider = flueTurnRequestProvider(event);
|
|
31847
32173
|
const api = flueTurnRequestApi(event);
|
|
@@ -31854,8 +32180,7 @@ var FlueObserveBridge = class {
|
|
|
31854
32180
|
...provider ? { "flue.provider": provider } : {},
|
|
31855
32181
|
...event.purpose ? { "flue.turn_purpose": event.purpose } : {},
|
|
31856
32182
|
...reasoning ? { reasoning } : {},
|
|
31857
|
-
...
|
|
31858
|
-
...input?.tools ? { tools: input.tools } : {}
|
|
32183
|
+
...turnInput.metadata
|
|
31859
32184
|
};
|
|
31860
32185
|
const parent = this.parentSpanForTurn(event);
|
|
31861
32186
|
const span = startFlueSpan(parent, {
|
|
@@ -31863,11 +32188,14 @@ var FlueObserveBridge = class {
|
|
|
31863
32188
|
spanAttributes: { type: "llm" /* LLM */ },
|
|
31864
32189
|
startTime: eventTime(event.timestamp),
|
|
31865
32190
|
event: {
|
|
31866
|
-
input:
|
|
32191
|
+
input: turnInput.messages,
|
|
31867
32192
|
metadata
|
|
31868
32193
|
}
|
|
31869
32194
|
});
|
|
31870
|
-
this.logOperationInput(
|
|
32195
|
+
this.logOperationInput(
|
|
32196
|
+
event.operationId,
|
|
32197
|
+
latestUserMessageInput(input?.messages)
|
|
32198
|
+
);
|
|
31871
32199
|
this.turnsByKey.set(key, { metadata, span });
|
|
31872
32200
|
}
|
|
31873
32201
|
handleTurn(event) {
|
|
@@ -32114,16 +32442,20 @@ var FlueObserveBridge = class {
|
|
|
32114
32442
|
}
|
|
32115
32443
|
startSyntheticOperation(event) {
|
|
32116
32444
|
const metadata = {
|
|
32445
|
+
...event.runId ? this.runsById.get(event.runId)?.metadata : {},
|
|
32117
32446
|
...extractEventMetadata(event),
|
|
32118
32447
|
"flue.operation": event.operationKind,
|
|
32119
32448
|
provider: "flue"
|
|
32120
32449
|
};
|
|
32121
|
-
const
|
|
32450
|
+
const args = {
|
|
32122
32451
|
name: `flue.${event.operationKind}`,
|
|
32123
32452
|
spanAttributes: { type: "task" /* TASK */ },
|
|
32124
32453
|
startTime: eventTime(event.timestamp),
|
|
32125
32454
|
event: { metadata }
|
|
32126
|
-
}
|
|
32455
|
+
};
|
|
32456
|
+
const parent = this.parentSpanForEvent(event);
|
|
32457
|
+
const runSpan = event.runId ? this.runsById.get(event.runId)?.span : void 0;
|
|
32458
|
+
const span = event.operationKind === "prompt" && (!parent || parent === runSpan) ? startFlueRootSpan(args) : startFlueSpan(parent, args);
|
|
32127
32459
|
return { metadata, span };
|
|
32128
32460
|
}
|
|
32129
32461
|
startSyntheticTurn(event) {
|
|
@@ -32302,6 +32634,71 @@ function flueRunInput(event) {
|
|
|
32302
32634
|
function flueTurnRequestInput(event) {
|
|
32303
32635
|
return event.request?.input ?? event.input;
|
|
32304
32636
|
}
|
|
32637
|
+
function prepareFlueTurnInput(event, input, operation) {
|
|
32638
|
+
const messages = input?.messages;
|
|
32639
|
+
const tracksUserTurn = event.purpose === "agent" && operation?.metadata["flue.operation"] === "prompt" && Array.isArray(messages);
|
|
32640
|
+
if (!tracksUserTurn) {
|
|
32641
|
+
return {
|
|
32642
|
+
messages,
|
|
32643
|
+
metadata: {
|
|
32644
|
+
...input?.systemPrompt ? { "flue.system_prompt": input.systemPrompt } : {},
|
|
32645
|
+
...input?.tools ? { tools: input.tools } : {}
|
|
32646
|
+
}
|
|
32647
|
+
};
|
|
32648
|
+
}
|
|
32649
|
+
const previous = operation.turnInputState;
|
|
32650
|
+
const previousMessageCount = previous?.messageCount ?? 0;
|
|
32651
|
+
const boundaryFingerprint = messages.length > 0 ? fingerprintJsonValue(messages[messages.length - 1]) : void 0;
|
|
32652
|
+
const continuesPreviousInput = previous !== void 0 && messages.length >= previousMessageCount && (previousMessageCount === 0 || previous.boundaryFingerprint !== void 0 && previous.boundaryFingerprint === fingerprintJsonValue(messages[previousMessageCount - 1]));
|
|
32653
|
+
const inputMode = previous === void 0 ? "full" : continuesPreviousInput ? "delta" : "reset";
|
|
32654
|
+
const systemPromptFingerprint = fingerprintJsonValue(input?.systemPrompt);
|
|
32655
|
+
const toolsFingerprint = fingerprintJsonValue(input?.tools);
|
|
32656
|
+
operation.turnInputState = {
|
|
32657
|
+
...boundaryFingerprint !== void 0 ? { boundaryFingerprint } : {},
|
|
32658
|
+
messageCount: messages.length,
|
|
32659
|
+
...systemPromptFingerprint !== void 0 ? { systemPromptFingerprint } : {},
|
|
32660
|
+
...toolsFingerprint !== void 0 ? { toolsFingerprint } : {}
|
|
32661
|
+
};
|
|
32662
|
+
return {
|
|
32663
|
+
messages: continuesPreviousInput ? messages.slice(previousMessageCount) : messages,
|
|
32664
|
+
metadata: {
|
|
32665
|
+
"flue.input_mode": inputMode,
|
|
32666
|
+
...continuesPreviousInput ? { "flue.input_message_offset": previousMessageCount } : {},
|
|
32667
|
+
...input?.systemPrompt && (!continuesPreviousInput || systemPromptFingerprint !== previous?.systemPromptFingerprint) ? { "flue.system_prompt": input.systemPrompt } : {},
|
|
32668
|
+
...input?.tools && (!continuesPreviousInput || toolsFingerprint !== previous?.toolsFingerprint) ? { tools: input.tools } : {}
|
|
32669
|
+
}
|
|
32670
|
+
};
|
|
32671
|
+
}
|
|
32672
|
+
function fingerprintJsonValue(value) {
|
|
32673
|
+
try {
|
|
32674
|
+
const serialized = JSON.stringify(value);
|
|
32675
|
+
if (serialized === void 0) {
|
|
32676
|
+
return void 0;
|
|
32677
|
+
}
|
|
32678
|
+
let hash = 2166136261;
|
|
32679
|
+
for (let i = 0; i < serialized.length; i++) {
|
|
32680
|
+
hash = Math.imul(hash ^ serialized.charCodeAt(i), 16777619);
|
|
32681
|
+
}
|
|
32682
|
+
return `${serialized.length}:${hash >>> 0}`;
|
|
32683
|
+
} catch {
|
|
32684
|
+
return void 0;
|
|
32685
|
+
}
|
|
32686
|
+
}
|
|
32687
|
+
function latestUserMessageInput(messages) {
|
|
32688
|
+
if (!messages) {
|
|
32689
|
+
return void 0;
|
|
32690
|
+
}
|
|
32691
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
32692
|
+
const message = messages[i];
|
|
32693
|
+
if (isObjectLike(message) && Reflect.get(message, "role") === "user") {
|
|
32694
|
+
return [message];
|
|
32695
|
+
}
|
|
32696
|
+
}
|
|
32697
|
+
return void 0;
|
|
32698
|
+
}
|
|
32699
|
+
function flueOperationInput(event) {
|
|
32700
|
+
return typeof event.agentInput?.text === "string" ? [{ content: event.agentInput.text, role: "user" }] : void 0;
|
|
32701
|
+
}
|
|
32305
32702
|
function flueTurnRequestModel(event) {
|
|
32306
32703
|
return event.request?.requestedModel ?? event.request?.model ?? event.model;
|
|
32307
32704
|
}
|
|
@@ -32459,6 +32856,21 @@ function startFlueSpan(parent, args) {
|
|
|
32459
32856
|
withSpanInstrumentationName(args, INSTRUMENTATION_NAMES.FLUE)
|
|
32460
32857
|
);
|
|
32461
32858
|
}
|
|
32859
|
+
function startFlueRootSpan(args) {
|
|
32860
|
+
const state = _internalGetGlobalState();
|
|
32861
|
+
const spanId = state.idGenerator.getSpanId();
|
|
32862
|
+
const rootSpanId = state.idGenerator.shareRootSpanId() ? spanId : state.idGenerator.getTraceId();
|
|
32863
|
+
return withCurrent(
|
|
32864
|
+
NOOP_SPAN,
|
|
32865
|
+
() => startSpan({
|
|
32866
|
+
...withSpanInstrumentationName(args, INSTRUMENTATION_NAMES.FLUE),
|
|
32867
|
+
parentSpanIds: { parentSpanIds: [], rootSpanId },
|
|
32868
|
+
spanId,
|
|
32869
|
+
state
|
|
32870
|
+
}),
|
|
32871
|
+
state
|
|
32872
|
+
);
|
|
32873
|
+
}
|
|
32462
32874
|
function runWithCurrentSpanStore(span, next) {
|
|
32463
32875
|
const state = _internalGetGlobalState();
|
|
32464
32876
|
const contextManager = state?.contextManager;
|
|
@@ -34358,8 +34770,7 @@ function startAgentStream(event, activeChildParents) {
|
|
|
34358
34770
|
...extractAgentMetadata2(agent),
|
|
34359
34771
|
...extractModelMetadata3(model),
|
|
34360
34772
|
"strands.operation": "Agent.stream",
|
|
34361
|
-
provider: extractProvider(model)
|
|
34362
|
-
...event.moduleVersion ? { "strands_agent_sdk.version": event.moduleVersion } : {}
|
|
34773
|
+
provider: extractProvider(model)
|
|
34363
34774
|
};
|
|
34364
34775
|
const parentSpan = agent ? getOnlyChildParent(activeChildParents, agent) : void 0;
|
|
34365
34776
|
const attachmentCache = createStrandsAttachmentCache();
|
|
@@ -34409,8 +34820,7 @@ function startMultiAgentStream(event, operation, activeChildParents) {
|
|
|
34409
34820
|
const metadata = {
|
|
34410
34821
|
"strands.operation": operation,
|
|
34411
34822
|
provider: "strands",
|
|
34412
|
-
...orchestrator?.id ? { "strands.orchestrator.id": orchestrator.id } : {}
|
|
34413
|
-
...event.moduleVersion ? { "strands_agent_sdk.version": event.moduleVersion } : {}
|
|
34823
|
+
...orchestrator?.id ? { "strands.orchestrator.id": orchestrator.id } : {}
|
|
34414
34824
|
};
|
|
34415
34825
|
const parentSpan = orchestrator ? getOnlyChildParent(activeChildParents, orchestrator) : void 0;
|
|
34416
34826
|
const input = processStrandsInputAttachments(event.arguments[0]);
|
|
@@ -35196,6 +35606,320 @@ function logInstrumentationError5(context, error) {
|
|
|
35196
35606
|
debugLogger.debug(`${context}:`, error);
|
|
35197
35607
|
}
|
|
35198
35608
|
|
|
35609
|
+
// src/instrumentation/plugins/voyageai-channels.ts
|
|
35610
|
+
var voyageAIChannels = defineChannels(
|
|
35611
|
+
"voyageai",
|
|
35612
|
+
{
|
|
35613
|
+
embed: channel({
|
|
35614
|
+
channelName: "embed",
|
|
35615
|
+
kind: "async"
|
|
35616
|
+
}),
|
|
35617
|
+
multimodalEmbed: channel({
|
|
35618
|
+
channelName: "multimodalEmbed",
|
|
35619
|
+
kind: "async"
|
|
35620
|
+
}),
|
|
35621
|
+
rerank: channel({
|
|
35622
|
+
channelName: "rerank",
|
|
35623
|
+
kind: "async"
|
|
35624
|
+
}),
|
|
35625
|
+
contextualizedEmbed: channel({
|
|
35626
|
+
channelName: "contextualizedEmbed",
|
|
35627
|
+
kind: "async"
|
|
35628
|
+
})
|
|
35629
|
+
},
|
|
35630
|
+
{ instrumentationName: INSTRUMENTATION_NAMES.VOYAGEAI }
|
|
35631
|
+
);
|
|
35632
|
+
|
|
35633
|
+
// src/instrumentation/plugins/voyageai-plugin.ts
|
|
35634
|
+
var RERANK_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
|
|
35635
|
+
"model",
|
|
35636
|
+
"returnDocuments",
|
|
35637
|
+
"topK",
|
|
35638
|
+
"truncation"
|
|
35639
|
+
]);
|
|
35640
|
+
var VoyageAIPlugin = class extends BasePlugin {
|
|
35641
|
+
onEnable() {
|
|
35642
|
+
this.unsubscribers.push(
|
|
35643
|
+
interceptVoyageAICall(
|
|
35644
|
+
voyageAIChannels.embed,
|
|
35645
|
+
"voyageai.embed",
|
|
35646
|
+
extractTextEmbeddingInput,
|
|
35647
|
+
summarizeEmbeddingOutput,
|
|
35648
|
+
extractEmbeddingUsageMetrics
|
|
35649
|
+
),
|
|
35650
|
+
interceptVoyageAICall(
|
|
35651
|
+
voyageAIChannels.multimodalEmbed,
|
|
35652
|
+
"voyageai.multimodalEmbed",
|
|
35653
|
+
extractMultimodalEmbeddingInput,
|
|
35654
|
+
summarizeEmbeddingOutput,
|
|
35655
|
+
extractEmbeddingUsageMetrics
|
|
35656
|
+
),
|
|
35657
|
+
interceptVoyageAICall(
|
|
35658
|
+
voyageAIChannels.rerank,
|
|
35659
|
+
"voyageai.rerank",
|
|
35660
|
+
extractRerankInput,
|
|
35661
|
+
summarizeRerankOutput
|
|
35662
|
+
),
|
|
35663
|
+
interceptVoyageAICall(
|
|
35664
|
+
voyageAIChannels.contextualizedEmbed,
|
|
35665
|
+
"voyageai.contextualizedEmbed",
|
|
35666
|
+
extractContextualizedEmbeddingInput,
|
|
35667
|
+
summarizeContextualizedEmbeddingOutput,
|
|
35668
|
+
extractEmbeddingUsageMetrics
|
|
35669
|
+
)
|
|
35670
|
+
);
|
|
35671
|
+
}
|
|
35672
|
+
onDisable() {
|
|
35673
|
+
this.unsubscribers = unsubscribeAll(this.unsubscribers);
|
|
35674
|
+
}
|
|
35675
|
+
};
|
|
35676
|
+
function interceptVoyageAICall(channel2, name, extractInput3, extractOutput2, extractMetrics2 = extractUsageMetrics3) {
|
|
35677
|
+
return channel2.intercept((target, thisArg, args) => {
|
|
35678
|
+
const invokeTarget = () => Reflect.apply(target, thisArg, args);
|
|
35679
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
35680
|
+
return invokeTarget();
|
|
35681
|
+
}
|
|
35682
|
+
let span;
|
|
35683
|
+
try {
|
|
35684
|
+
const { input, metadata } = extractInput3(args);
|
|
35685
|
+
span = startSpan(
|
|
35686
|
+
withSpanInstrumentationName(
|
|
35687
|
+
{
|
|
35688
|
+
event: { input, metadata },
|
|
35689
|
+
name,
|
|
35690
|
+
spanAttributes: { type: "llm" /* LLM */ }
|
|
35691
|
+
},
|
|
35692
|
+
INSTRUMENTATION_NAMES.VOYAGEAI
|
|
35693
|
+
)
|
|
35694
|
+
);
|
|
35695
|
+
} catch (error) {
|
|
35696
|
+
debugLogger.error(`Error starting span for ${name}:`, error);
|
|
35697
|
+
return invokeTarget();
|
|
35698
|
+
}
|
|
35699
|
+
let result;
|
|
35700
|
+
try {
|
|
35701
|
+
result = withCurrent(
|
|
35702
|
+
span,
|
|
35703
|
+
() => runWithAutoInstrumentationSuppressed(invokeTarget)
|
|
35704
|
+
);
|
|
35705
|
+
} catch (error) {
|
|
35706
|
+
finishVoyageAISpan(span, name, () => span.log({ error }));
|
|
35707
|
+
throw error;
|
|
35708
|
+
}
|
|
35709
|
+
void Promise.resolve(result).then(
|
|
35710
|
+
(value) => finishVoyageAISpan(span, name, () => {
|
|
35711
|
+
const metadata = extractResponseMetadata3(value);
|
|
35712
|
+
span.log({
|
|
35713
|
+
output: extractOutput2(value),
|
|
35714
|
+
...metadata ? { metadata } : {},
|
|
35715
|
+
metrics: extractMetrics2(value)
|
|
35716
|
+
});
|
|
35717
|
+
}),
|
|
35718
|
+
(error) => finishVoyageAISpan(span, name, () => span.log({ error }))
|
|
35719
|
+
);
|
|
35720
|
+
return result;
|
|
35721
|
+
});
|
|
35722
|
+
}
|
|
35723
|
+
function finishVoyageAISpan(span, name, log3) {
|
|
35724
|
+
try {
|
|
35725
|
+
log3();
|
|
35726
|
+
} catch (error) {
|
|
35727
|
+
debugLogger.error(`Error logging span for ${name}:`, error);
|
|
35728
|
+
}
|
|
35729
|
+
try {
|
|
35730
|
+
span.end();
|
|
35731
|
+
} catch (error) {
|
|
35732
|
+
debugLogger.error(`Error ending span for ${name}:`, error);
|
|
35733
|
+
}
|
|
35734
|
+
}
|
|
35735
|
+
function getRequestArg2(args) {
|
|
35736
|
+
if (Array.isArray(args)) {
|
|
35737
|
+
return isObject(args[0]) ? args[0] : void 0;
|
|
35738
|
+
}
|
|
35739
|
+
if (!isObject(args)) {
|
|
35740
|
+
return void 0;
|
|
35741
|
+
}
|
|
35742
|
+
const firstArg = Reflect.get(args, "0");
|
|
35743
|
+
return isObject(firstArg) ? firstArg : void 0;
|
|
35744
|
+
}
|
|
35745
|
+
function pickMetadata(request, allowlist) {
|
|
35746
|
+
const metadata = {};
|
|
35747
|
+
if (request) {
|
|
35748
|
+
for (const key of allowlist) {
|
|
35749
|
+
if (!Object.hasOwn(request, key)) {
|
|
35750
|
+
continue;
|
|
35751
|
+
}
|
|
35752
|
+
const value = request[key];
|
|
35753
|
+
if (value !== void 0) {
|
|
35754
|
+
metadata[key] = value;
|
|
35755
|
+
}
|
|
35756
|
+
}
|
|
35757
|
+
}
|
|
35758
|
+
return {
|
|
35759
|
+
...metadata,
|
|
35760
|
+
provider: "voyage"
|
|
35761
|
+
};
|
|
35762
|
+
}
|
|
35763
|
+
function buildEmbeddingInput(inputs, request) {
|
|
35764
|
+
const outputDimensions = request?.outputDimension;
|
|
35765
|
+
return {
|
|
35766
|
+
inputs,
|
|
35767
|
+
...typeof outputDimensions === "number" && Number.isFinite(outputDimensions) ? { output_dimensions: outputDimensions } : {}
|
|
35768
|
+
};
|
|
35769
|
+
}
|
|
35770
|
+
function embeddingMetadata(request) {
|
|
35771
|
+
return {
|
|
35772
|
+
...typeof request?.model === "string" ? { model: request.model } : {},
|
|
35773
|
+
provider: "voyage"
|
|
35774
|
+
};
|
|
35775
|
+
}
|
|
35776
|
+
function extractTextEmbeddingInput(args) {
|
|
35777
|
+
const request = getRequestArg2(args);
|
|
35778
|
+
const rawInput = request?.input;
|
|
35779
|
+
const values = Array.isArray(rawInput) ? rawInput : [rawInput];
|
|
35780
|
+
return {
|
|
35781
|
+
input: buildEmbeddingInput(
|
|
35782
|
+
values.flatMap(
|
|
35783
|
+
(value) => typeof value === "string" ? [{ content: value }] : []
|
|
35784
|
+
),
|
|
35785
|
+
request
|
|
35786
|
+
),
|
|
35787
|
+
metadata: embeddingMetadata(request)
|
|
35788
|
+
};
|
|
35789
|
+
}
|
|
35790
|
+
function extractContextualizedEmbeddingInput(args) {
|
|
35791
|
+
const request = getRequestArg2(args);
|
|
35792
|
+
const rawInputs = request?.inputs;
|
|
35793
|
+
const values = Array.isArray(rawInputs) ? rawInputs.flatMap((value) => Array.isArray(value) ? value : [value]) : [];
|
|
35794
|
+
return {
|
|
35795
|
+
input: buildEmbeddingInput(
|
|
35796
|
+
values.flatMap(
|
|
35797
|
+
(value) => typeof value === "string" ? [{ content: value }] : []
|
|
35798
|
+
),
|
|
35799
|
+
request
|
|
35800
|
+
),
|
|
35801
|
+
metadata: embeddingMetadata(request)
|
|
35802
|
+
};
|
|
35803
|
+
}
|
|
35804
|
+
function extractMultimodalEmbeddingInput(args) {
|
|
35805
|
+
const request = getRequestArg2(args);
|
|
35806
|
+
const rawInputs = request?.inputs;
|
|
35807
|
+
const inputs = Array.isArray(rawInputs) ? rawInputs.map((rawInput) => {
|
|
35808
|
+
const rawContent = isObject(rawInput) ? rawInput.content : void 0;
|
|
35809
|
+
return {
|
|
35810
|
+
content: Array.isArray(rawContent) ? rawContent.flatMap(normalizeMultimodalContentPart) : []
|
|
35811
|
+
};
|
|
35812
|
+
}) : [];
|
|
35813
|
+
const input = buildEmbeddingInput(inputs, request);
|
|
35814
|
+
const processedInput = processInputAttachments(input);
|
|
35815
|
+
return {
|
|
35816
|
+
input: hasInlineEmbeddingMedia(processedInput) ? input : processedInput,
|
|
35817
|
+
metadata: embeddingMetadata(request)
|
|
35818
|
+
};
|
|
35819
|
+
}
|
|
35820
|
+
function normalizeMultimodalContentPart(part) {
|
|
35821
|
+
if (!isObject(part) || typeof part.type !== "string") {
|
|
35822
|
+
return [];
|
|
35823
|
+
}
|
|
35824
|
+
if (part.type === "text") {
|
|
35825
|
+
return typeof part.text === "string" ? [{ type: "text", text: part.text }] : [];
|
|
35826
|
+
}
|
|
35827
|
+
const camelCaseField = {
|
|
35828
|
+
image_base64: "imageBase64",
|
|
35829
|
+
image_url: "imageUrl",
|
|
35830
|
+
video_base64: "videoBase64",
|
|
35831
|
+
video_url: "videoUrl"
|
|
35832
|
+
};
|
|
35833
|
+
const field = camelCaseField[part.type];
|
|
35834
|
+
if (!field) {
|
|
35835
|
+
return [];
|
|
35836
|
+
}
|
|
35837
|
+
const data = typeof part[field] === "string" ? part[field] : part[part.type];
|
|
35838
|
+
if (typeof data !== "string") {
|
|
35839
|
+
return [];
|
|
35840
|
+
}
|
|
35841
|
+
return part.type.startsWith("image_") ? [{ type: "image_url", image_url: { url: data } }] : [{ type: "file", file: { file_data: data } }];
|
|
35842
|
+
}
|
|
35843
|
+
function hasInlineEmbeddingMedia(input) {
|
|
35844
|
+
return input.inputs.some(
|
|
35845
|
+
({ content }) => Array.isArray(content) ? content.some((part) => {
|
|
35846
|
+
const value = part.type === "image_url" ? part.image_url.url : part.type === "file" ? part.file.file_data : void 0;
|
|
35847
|
+
return typeof value === "string" && value.startsWith("data:");
|
|
35848
|
+
}) : false
|
|
35849
|
+
);
|
|
35850
|
+
}
|
|
35851
|
+
function extractRerankInput(args) {
|
|
35852
|
+
const request = getRequestArg2(args);
|
|
35853
|
+
const documents = request?.documents;
|
|
35854
|
+
return {
|
|
35855
|
+
input: {
|
|
35856
|
+
documents,
|
|
35857
|
+
query: request?.query
|
|
35858
|
+
},
|
|
35859
|
+
metadata: {
|
|
35860
|
+
...pickMetadata(request, RERANK_METADATA_ALLOWLIST),
|
|
35861
|
+
...Array.isArray(documents) ? { document_count: documents.length } : {}
|
|
35862
|
+
}
|
|
35863
|
+
};
|
|
35864
|
+
}
|
|
35865
|
+
function extractResponseMetadata3(result) {
|
|
35866
|
+
if (!isObject(result)) {
|
|
35867
|
+
return void 0;
|
|
35868
|
+
}
|
|
35869
|
+
const rawResponse = isObject(result.rawResponse) ? result.rawResponse : void 0;
|
|
35870
|
+
const model = typeof result.model === "string" ? result.model : typeof rawResponse?.model === "string" ? rawResponse.model : void 0;
|
|
35871
|
+
return model ? { model } : void 0;
|
|
35872
|
+
}
|
|
35873
|
+
function summarizeEmbeddingOutput(result) {
|
|
35874
|
+
return {
|
|
35875
|
+
count: isObject(result) && Array.isArray(result.data) ? result.data.length : 0
|
|
35876
|
+
};
|
|
35877
|
+
}
|
|
35878
|
+
function summarizeRerankOutput(result) {
|
|
35879
|
+
if (!isObject(result) || !Array.isArray(result.data)) {
|
|
35880
|
+
return void 0;
|
|
35881
|
+
}
|
|
35882
|
+
return result.data.slice(0, 100).map((item) => ({
|
|
35883
|
+
index: isObject(item) ? item.index : void 0,
|
|
35884
|
+
relevance_score: isObject(item) ? (typeof item.relevanceScore === "number" ? item.relevanceScore : item.relevance_score) ?? null : null
|
|
35885
|
+
}));
|
|
35886
|
+
}
|
|
35887
|
+
function summarizeContextualizedEmbeddingOutput(result) {
|
|
35888
|
+
if (!isObject(result)) {
|
|
35889
|
+
return { count: 0 };
|
|
35890
|
+
}
|
|
35891
|
+
if (Array.isArray(result.results)) {
|
|
35892
|
+
return {
|
|
35893
|
+
count: result.results.reduce(
|
|
35894
|
+
(count, item) => count + (isObject(item) && Array.isArray(item.embeddings) ? item.embeddings.length : 0),
|
|
35895
|
+
0
|
|
35896
|
+
)
|
|
35897
|
+
};
|
|
35898
|
+
}
|
|
35899
|
+
if (!Array.isArray(result.data)) {
|
|
35900
|
+
return { count: 0 };
|
|
35901
|
+
}
|
|
35902
|
+
return {
|
|
35903
|
+
count: result.data.reduce(
|
|
35904
|
+
(count, item) => count + (isObject(item) && Array.isArray(item.data) ? item.data.length : 0),
|
|
35905
|
+
0
|
|
35906
|
+
)
|
|
35907
|
+
};
|
|
35908
|
+
}
|
|
35909
|
+
function extractEmbeddingUsageMetrics(result) {
|
|
35910
|
+
const metrics = extractUsageMetrics3(result);
|
|
35911
|
+
return typeof metrics.tokens === "number" ? { prompt_tokens: metrics.tokens, tokens: metrics.tokens } : {};
|
|
35912
|
+
}
|
|
35913
|
+
function extractUsageMetrics3(result) {
|
|
35914
|
+
if (!isObject(result)) {
|
|
35915
|
+
return {};
|
|
35916
|
+
}
|
|
35917
|
+
const rawResponse = isObject(result.rawResponse) ? result.rawResponse : void 0;
|
|
35918
|
+
const usage = isObject(result.usage) ? result.usage : isObject(rawResponse?.usage) ? rawResponse.usage : void 0;
|
|
35919
|
+
const tokens = typeof result.totalTokens === "number" ? result.totalTokens : usage?.totalTokens ?? usage?.total_tokens;
|
|
35920
|
+
return typeof tokens === "number" && Number.isFinite(tokens) && tokens >= 0 ? { tokens } : {};
|
|
35921
|
+
}
|
|
35922
|
+
|
|
35199
35923
|
// src/instrumentation/plugins/cloudflare-ai-chat-channels.ts
|
|
35200
35924
|
var cloudflareAIChatChannels = defineChannels(
|
|
35201
35925
|
"@cloudflare/ai-chat",
|
|
@@ -35774,6 +36498,7 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
35774
36498
|
langSmithPlugin = null;
|
|
35775
36499
|
piCodingAgentPlugin = null;
|
|
35776
36500
|
strandsAgentSDKPlugin = null;
|
|
36501
|
+
voyageAIPlugin = null;
|
|
35777
36502
|
cloudflareAIChatPlugin = null;
|
|
35778
36503
|
cloudflareAgentsPlugin = null;
|
|
35779
36504
|
constructor(config = {}) {
|
|
@@ -35848,6 +36573,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
35848
36573
|
this.coherePlugin = new CoherePlugin();
|
|
35849
36574
|
this.coherePlugin.enable();
|
|
35850
36575
|
}
|
|
36576
|
+
if (integrations.voyageai !== false) {
|
|
36577
|
+
this.voyageAIPlugin = new VoyageAIPlugin();
|
|
36578
|
+
this.voyageAIPlugin.enable();
|
|
36579
|
+
}
|
|
35851
36580
|
if (integrations.groq !== false) {
|
|
35852
36581
|
this.groqPlugin = new GroqPlugin();
|
|
35853
36582
|
this.groqPlugin.enable();
|
|
@@ -35964,6 +36693,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
35964
36693
|
this.coherePlugin.disable();
|
|
35965
36694
|
this.coherePlugin = null;
|
|
35966
36695
|
}
|
|
36696
|
+
if (this.voyageAIPlugin) {
|
|
36697
|
+
this.voyageAIPlugin.disable();
|
|
36698
|
+
this.voyageAIPlugin = null;
|
|
36699
|
+
}
|
|
35967
36700
|
if (this.groqPlugin) {
|
|
35968
36701
|
this.groqPlugin.disable();
|
|
35969
36702
|
this.groqPlugin = null;
|
|
@@ -36083,7 +36816,10 @@ var envIntegrationAliases = {
|
|
|
36083
36816
|
"langchain-js": "langchain",
|
|
36084
36817
|
"@langchain": "langchain",
|
|
36085
36818
|
langgraph: "langgraph",
|
|
36086
|
-
langsmith: "langsmith"
|
|
36819
|
+
langsmith: "langsmith",
|
|
36820
|
+
voyage: "voyageai",
|
|
36821
|
+
"voyage-ai": "voyageai",
|
|
36822
|
+
voyageai: "voyageai"
|
|
36087
36823
|
};
|
|
36088
36824
|
function getDefaultInstrumentationIntegrations() {
|
|
36089
36825
|
return {
|
|
@@ -36118,6 +36854,7 @@ function getDefaultInstrumentationIntegrations() {
|
|
|
36118
36854
|
langchain: true,
|
|
36119
36855
|
langgraph: true,
|
|
36120
36856
|
langsmith: true,
|
|
36857
|
+
voyageai: true,
|
|
36121
36858
|
piCodingAgent: true,
|
|
36122
36859
|
strandsAgentSDK: true,
|
|
36123
36860
|
cloudflareAgents: true
|
|
@@ -36283,6 +37020,8 @@ __export(exports_exports, {
|
|
|
36283
37020
|
BRAINTRUST_PARENT_KEY: () => BRAINTRUST_PARENT_KEY,
|
|
36284
37021
|
BaseAttachment: () => BaseAttachment,
|
|
36285
37022
|
BaseExperiment: () => BaseExperiment,
|
|
37023
|
+
BatchScorer: () => BatchScorer,
|
|
37024
|
+
BatchTask: () => BatchTask,
|
|
36286
37025
|
BraintrustLangChainCallbackHandler: () => BraintrustLangChainCallbackHandler,
|
|
36287
37026
|
BraintrustMiddleware: () => BraintrustMiddleware,
|
|
36288
37027
|
BraintrustObservabilityExporter: () => BraintrustObservabilityExporter,
|
|
@@ -36296,6 +37035,8 @@ __export(exports_exports, {
|
|
|
36296
37035
|
DEFAULT_MAX_REQUEST_SIZE: () => DEFAULT_MAX_REQUEST_SIZE,
|
|
36297
37036
|
Dataset: () => Dataset2,
|
|
36298
37037
|
DatasetPipeline: () => DatasetPipeline,
|
|
37038
|
+
DurableEvalMemoryStore: () => DurableEvalMemoryStore,
|
|
37039
|
+
DurableEvalRedisStore: () => DurableEvalRedisStore,
|
|
36299
37040
|
ERR_PERMALINK: () => ERR_PERMALINK,
|
|
36300
37041
|
Eval: () => Eval,
|
|
36301
37042
|
EvalResultWithSummary: () => EvalResultWithSummary,
|
|
@@ -36353,6 +37094,7 @@ __export(exports_exports, {
|
|
|
36353
37094
|
currentSpan: () => currentSpan,
|
|
36354
37095
|
deepCopyEvent: () => deepCopyEvent,
|
|
36355
37096
|
defaultErrorScoreHandler: () => defaultErrorScoreHandler,
|
|
37097
|
+
defineDurableEval: () => defineDurableEval,
|
|
36356
37098
|
deserializePlainStringAsJSON: () => deserializePlainStringAsJSON,
|
|
36357
37099
|
devNullWritableStream: () => devNullWritableStream,
|
|
36358
37100
|
evaluatorDefinitionSchema: () => evaluatorDefinitionSchema,
|
|
@@ -36448,7 +37190,8 @@ __export(exports_exports, {
|
|
|
36448
37190
|
wrapPiCodingAgentSDK: () => wrapPiCodingAgentSDK,
|
|
36449
37191
|
wrapStrandsAgentSDK: () => wrapStrandsAgentSDK,
|
|
36450
37192
|
wrapTraced: () => wrapTraced,
|
|
36451
|
-
wrapVitest: () => wrapVitest
|
|
37193
|
+
wrapVitest: () => wrapVitest,
|
|
37194
|
+
wrapVoyageAI: () => wrapVoyageAI
|
|
36452
37195
|
});
|
|
36453
37196
|
|
|
36454
37197
|
// src/sandbox.ts
|
|
@@ -37709,7 +38452,7 @@ function normalizeUsageMetrics(usage, provider, providerMetadata) {
|
|
|
37709
38452
|
cacheCreationTokens
|
|
37710
38453
|
);
|
|
37711
38454
|
Object.assign(metrics, cacheTokens);
|
|
37712
|
-
|
|
38455
|
+
return toNumericMetrics(finalizeAnthropicTokens(metrics));
|
|
37713
38456
|
}
|
|
37714
38457
|
}
|
|
37715
38458
|
return metrics;
|
|
@@ -42042,6 +42785,84 @@ function wrapRerank3(rerank) {
|
|
|
42042
42785
|
});
|
|
42043
42786
|
}
|
|
42044
42787
|
|
|
42788
|
+
// src/wrappers/voyageai.ts
|
|
42789
|
+
function wrapVoyageAI(client) {
|
|
42790
|
+
if (!isSupportedVoyageAIClient(client)) {
|
|
42791
|
+
console.warn("Unsupported Voyage AI library. Not wrapping.");
|
|
42792
|
+
return client;
|
|
42793
|
+
}
|
|
42794
|
+
return voyageAIProxy(client);
|
|
42795
|
+
}
|
|
42796
|
+
var voyageAIProxyCache = /* @__PURE__ */ new WeakMap();
|
|
42797
|
+
function isObject3(value) {
|
|
42798
|
+
return typeof value === "object" && value !== null;
|
|
42799
|
+
}
|
|
42800
|
+
function hasFunction5(value, name) {
|
|
42801
|
+
return typeof Reflect.get(value, name) === "function";
|
|
42802
|
+
}
|
|
42803
|
+
function isSupportedVoyageAIClient(value) {
|
|
42804
|
+
if (!isObject3(value)) {
|
|
42805
|
+
return false;
|
|
42806
|
+
}
|
|
42807
|
+
return hasFunction5(value, "embed") || hasFunction5(value, "multimodalEmbed") || hasFunction5(value, "rerank") || hasFunction5(value, "contextualizedEmbed");
|
|
42808
|
+
}
|
|
42809
|
+
function voyageAIProxy(client) {
|
|
42810
|
+
const cached = voyageAIProxyCache.get(client);
|
|
42811
|
+
if (cached) {
|
|
42812
|
+
return cached;
|
|
42813
|
+
}
|
|
42814
|
+
const proxy = new Proxy(client, {
|
|
42815
|
+
get(target, prop, receiver) {
|
|
42816
|
+
switch (prop) {
|
|
42817
|
+
case "embed":
|
|
42818
|
+
if (typeof target.embed !== "function") {
|
|
42819
|
+
return target.embed;
|
|
42820
|
+
}
|
|
42821
|
+
return (request, options) => voyageAIChannels.embed.invoke(
|
|
42822
|
+
target.embed,
|
|
42823
|
+
target,
|
|
42824
|
+
[request, options],
|
|
42825
|
+
{}
|
|
42826
|
+
);
|
|
42827
|
+
case "multimodalEmbed":
|
|
42828
|
+
if (typeof target.multimodalEmbed !== "function") {
|
|
42829
|
+
return target.multimodalEmbed;
|
|
42830
|
+
}
|
|
42831
|
+
return (request, options) => voyageAIChannels.multimodalEmbed.invoke(
|
|
42832
|
+
target.multimodalEmbed,
|
|
42833
|
+
target,
|
|
42834
|
+
[request, options],
|
|
42835
|
+
{}
|
|
42836
|
+
);
|
|
42837
|
+
case "rerank":
|
|
42838
|
+
if (typeof target.rerank !== "function") {
|
|
42839
|
+
return target.rerank;
|
|
42840
|
+
}
|
|
42841
|
+
return (request, options) => voyageAIChannels.rerank.invoke(
|
|
42842
|
+
target.rerank,
|
|
42843
|
+
target,
|
|
42844
|
+
[request, options],
|
|
42845
|
+
{}
|
|
42846
|
+
);
|
|
42847
|
+
case "contextualizedEmbed":
|
|
42848
|
+
if (typeof target.contextualizedEmbed !== "function") {
|
|
42849
|
+
return target.contextualizedEmbed;
|
|
42850
|
+
}
|
|
42851
|
+
return (request, options) => voyageAIChannels.contextualizedEmbed.invoke(
|
|
42852
|
+
target.contextualizedEmbed,
|
|
42853
|
+
target,
|
|
42854
|
+
[request, options],
|
|
42855
|
+
{}
|
|
42856
|
+
);
|
|
42857
|
+
default:
|
|
42858
|
+
return Reflect.get(target, prop, receiver);
|
|
42859
|
+
}
|
|
42860
|
+
}
|
|
42861
|
+
});
|
|
42862
|
+
voyageAIProxyCache.set(client, proxy);
|
|
42863
|
+
return proxy;
|
|
42864
|
+
}
|
|
42865
|
+
|
|
42045
42866
|
// src/wrappers/groq.ts
|
|
42046
42867
|
function wrapGroq(groq) {
|
|
42047
42868
|
if (isSupportedGroqClient(groq)) {
|
|
@@ -42053,14 +42874,14 @@ function wrapGroq(groq) {
|
|
|
42053
42874
|
function isRecord6(value) {
|
|
42054
42875
|
return typeof value === "object" && value !== null;
|
|
42055
42876
|
}
|
|
42056
|
-
function
|
|
42877
|
+
function hasFunction6(value, methodName) {
|
|
42057
42878
|
return isRecord6(value) && methodName in value && typeof value[methodName] === "function";
|
|
42058
42879
|
}
|
|
42059
42880
|
function hasChat2(value) {
|
|
42060
|
-
return isRecord6(value) && isRecord6(value.completions) &&
|
|
42881
|
+
return isRecord6(value) && isRecord6(value.completions) && hasFunction6(value.completions, "create");
|
|
42061
42882
|
}
|
|
42062
42883
|
function hasEmbeddings2(value) {
|
|
42063
|
-
return
|
|
42884
|
+
return hasFunction6(value, "create");
|
|
42064
42885
|
}
|
|
42065
42886
|
function isSupportedGroqClient(value) {
|
|
42066
42887
|
return isRecord6(value) && (value.chat !== void 0 && hasChat2(value.chat) || value.embeddings !== void 0 && hasEmbeddings2(value.embeddings));
|
|
@@ -42643,7 +43464,7 @@ async function flushExperimentWithSync(context, config) {
|
|
|
42643
43464
|
// src/wrappers/shared/scorers.ts
|
|
42644
43465
|
async function runScorers(args) {
|
|
42645
43466
|
const { scorers, output, expected, input, metadata, span } = args;
|
|
42646
|
-
const
|
|
43467
|
+
const scorerArgs2 = {
|
|
42647
43468
|
output,
|
|
42648
43469
|
expected,
|
|
42649
43470
|
input,
|
|
@@ -42652,7 +43473,7 @@ async function runScorers(args) {
|
|
|
42652
43473
|
await Promise.all(
|
|
42653
43474
|
scorers.map(async (scorer) => {
|
|
42654
43475
|
try {
|
|
42655
|
-
const result = await scorer(
|
|
43476
|
+
const result = await scorer(scorerArgs2);
|
|
42656
43477
|
const scores = normalizeScores(result);
|
|
42657
43478
|
if (scores.length > 0) {
|
|
42658
43479
|
const accScores = {};
|
|
@@ -45011,6 +45832,26 @@ async function getExperimentParametersRef(parameters) {
|
|
|
45011
45832
|
version: resolvedParameters.version
|
|
45012
45833
|
};
|
|
45013
45834
|
}
|
|
45835
|
+
async function _internalInitEvaluatorExperiment(projectName, evaluator, data, options = {}) {
|
|
45836
|
+
if (options.disabled) return null;
|
|
45837
|
+
const { baseExperiment } = callEvaluatorData(data);
|
|
45838
|
+
const parameters = await getExperimentParametersRef(evaluator.parameters);
|
|
45839
|
+
return initExperiment2(evaluator.state, {
|
|
45840
|
+
...evaluator.projectId ? { projectId: evaluator.projectId } : { project: projectName },
|
|
45841
|
+
experiment: options.experimentName ?? evaluator.experimentName,
|
|
45842
|
+
description: evaluator.description,
|
|
45843
|
+
metadata: evaluator.metadata,
|
|
45844
|
+
tags: evaluator.tags,
|
|
45845
|
+
isPublic: evaluator.isPublic,
|
|
45846
|
+
update: options.update ?? evaluator.update,
|
|
45847
|
+
baseExperiment: evaluator.baseExperimentName ?? baseExperiment,
|
|
45848
|
+
baseExperimentId: evaluator.baseExperimentId,
|
|
45849
|
+
gitMetadataSettings: evaluator.gitMetadataSettings,
|
|
45850
|
+
repoInfo: evaluator.repoInfo,
|
|
45851
|
+
dataset: Dataset2.isDataset(data) ? data : void 0,
|
|
45852
|
+
parameters
|
|
45853
|
+
});
|
|
45854
|
+
}
|
|
45014
45855
|
function callEvaluatorData(data) {
|
|
45015
45856
|
const dataResult = typeof data === "function" ? data() : data;
|
|
45016
45857
|
let baseExperiment = void 0;
|
|
@@ -45028,6 +45869,48 @@ function isAsyncIterable7(value) {
|
|
|
45028
45869
|
function isIterable(value) {
|
|
45029
45870
|
return typeof value === "object" && value !== null && Symbol.iterator in value && typeof value[Symbol.iterator] === "function";
|
|
45030
45871
|
}
|
|
45872
|
+
async function _internalResolveEvaluatorData(evaluator, experiment) {
|
|
45873
|
+
if (typeof evaluator.data === "string") {
|
|
45874
|
+
throw new Error("Unimplemented: string data paths");
|
|
45875
|
+
}
|
|
45876
|
+
let dataResult = typeof evaluator.data === "function" ? evaluator.data() : evaluator.data;
|
|
45877
|
+
if ("_type" in dataResult) {
|
|
45878
|
+
if (dataResult._type !== "BaseExperiment") {
|
|
45879
|
+
throw new Error("Invalid _type");
|
|
45880
|
+
}
|
|
45881
|
+
if (!experiment) {
|
|
45882
|
+
throw new Error(
|
|
45883
|
+
"Cannot use BaseExperiment() without connecting to Braintrust (you most likely set --no-send-logs)"
|
|
45884
|
+
);
|
|
45885
|
+
}
|
|
45886
|
+
let name = dataResult.name;
|
|
45887
|
+
if (isEmpty2(name)) {
|
|
45888
|
+
const baseExperiment = await experiment.fetchBaseExperiment();
|
|
45889
|
+
if (!baseExperiment) {
|
|
45890
|
+
throw new Error("BaseExperiment() failed to fetch base experiment");
|
|
45891
|
+
}
|
|
45892
|
+
name = baseExperiment.name;
|
|
45893
|
+
}
|
|
45894
|
+
dataResult = initExperiment2(evaluator.state, {
|
|
45895
|
+
...evaluator.projectId ? { projectId: evaluator.projectId } : { project: evaluator.projectName },
|
|
45896
|
+
experiment: name,
|
|
45897
|
+
open: true
|
|
45898
|
+
}).asDataset();
|
|
45899
|
+
}
|
|
45900
|
+
const resolvedDataResult = dataResult instanceof Promise ? await dataResult : dataResult;
|
|
45901
|
+
if (isAsyncIterable7(resolvedDataResult)) {
|
|
45902
|
+
return resolvedDataResult;
|
|
45903
|
+
}
|
|
45904
|
+
if (Array.isArray(resolvedDataResult) || isIterable(resolvedDataResult)) {
|
|
45905
|
+
const iterable = resolvedDataResult;
|
|
45906
|
+
return (async function* () {
|
|
45907
|
+
for (const datum of iterable) yield datum;
|
|
45908
|
+
})();
|
|
45909
|
+
}
|
|
45910
|
+
throw new Error(
|
|
45911
|
+
"Evaluator data must be an array, iterable, or async iterable"
|
|
45912
|
+
);
|
|
45913
|
+
}
|
|
45031
45914
|
globalThis._evals = {
|
|
45032
45915
|
functions: [],
|
|
45033
45916
|
prompts: [],
|
|
@@ -45074,25 +45957,13 @@ async function Eval(name, evaluator, reporterOrOpts) {
|
|
|
45074
45957
|
}
|
|
45075
45958
|
const resolvedReporter = options.reporter || defaultReporter;
|
|
45076
45959
|
try {
|
|
45077
|
-
const { data
|
|
45078
|
-
|
|
45079
|
-
|
|
45080
|
-
|
|
45081
|
-
|
|
45082
|
-
|
|
45083
|
-
|
|
45084
|
-
description: evaluator.description,
|
|
45085
|
-
metadata: evaluator.metadata,
|
|
45086
|
-
tags: evaluator.tags,
|
|
45087
|
-
isPublic: evaluator.isPublic,
|
|
45088
|
-
update: evaluator.update,
|
|
45089
|
-
baseExperiment: evaluator.baseExperimentName ?? defaultBaseExperiment,
|
|
45090
|
-
baseExperimentId: evaluator.baseExperimentId,
|
|
45091
|
-
gitMetadataSettings: evaluator.gitMetadataSettings,
|
|
45092
|
-
repoInfo: evaluator.repoInfo,
|
|
45093
|
-
dataset: Dataset2.isDataset(data) ? data : void 0,
|
|
45094
|
-
parameters
|
|
45095
|
-
});
|
|
45960
|
+
const { data } = callEvaluatorData(evaluator.data);
|
|
45961
|
+
const experiment = await _internalInitEvaluatorExperiment(
|
|
45962
|
+
name,
|
|
45963
|
+
evaluator,
|
|
45964
|
+
data,
|
|
45965
|
+
{ disabled: Boolean(options.parent || options.noSendLogs) }
|
|
45966
|
+
);
|
|
45096
45967
|
if (experiment && typeof process !== "undefined" && globalThis.BRAINTRUST_CONTEXT_MANAGER !== void 0) {
|
|
45097
45968
|
await experiment._waitForId();
|
|
45098
45969
|
}
|
|
@@ -45190,19 +46061,74 @@ function scorerName(scorer, scorer_idx) {
|
|
|
45190
46061
|
function classifierName(classifier, classifier_idx) {
|
|
45191
46062
|
return classifier.name || `classifier_${classifier_idx}`;
|
|
45192
46063
|
}
|
|
46064
|
+
async function _internalRunEvaluatorTask(task, datum, trialIndex, parameters, span, reportProgress = () => void 0) {
|
|
46065
|
+
const metadata = {
|
|
46066
|
+
..."metadata" in datum ? datum.metadata : {}
|
|
46067
|
+
};
|
|
46068
|
+
const hooks = {
|
|
46069
|
+
meta(value) {
|
|
46070
|
+
Object.assign(metadata, value);
|
|
46071
|
+
},
|
|
46072
|
+
metadata,
|
|
46073
|
+
expected: "expected" in datum ? datum.expected : void 0,
|
|
46074
|
+
span,
|
|
46075
|
+
parameters,
|
|
46076
|
+
reportProgress,
|
|
46077
|
+
trialIndex,
|
|
46078
|
+
tags: [...datum.tags ?? []]
|
|
46079
|
+
};
|
|
46080
|
+
const output = await task(datum.input, hooks);
|
|
46081
|
+
span.log({ output });
|
|
46082
|
+
return {
|
|
46083
|
+
output,
|
|
46084
|
+
metadata: hooks.metadata,
|
|
46085
|
+
tags: hooks.tags ?? []
|
|
46086
|
+
};
|
|
46087
|
+
}
|
|
45193
46088
|
function buildSpanMetadata(results) {
|
|
45194
|
-
return results.length === 1 ? results[0].metadata :
|
|
45195
|
-
(
|
|
45196
|
-
{}
|
|
46089
|
+
return results.length === 1 ? results[0].metadata : Object.fromEntries(
|
|
46090
|
+
results.map((result) => [result.name, result.metadata])
|
|
45197
46091
|
);
|
|
45198
46092
|
}
|
|
45199
46093
|
function buildSpanScores(results) {
|
|
45200
|
-
const scoresRecord =
|
|
45201
|
-
(
|
|
45202
|
-
{}
|
|
46094
|
+
const scoresRecord = Object.fromEntries(
|
|
46095
|
+
results.map((result) => [result.name, result.score])
|
|
45203
46096
|
);
|
|
45204
46097
|
return { resultMetadata: buildSpanMetadata(results), scoresRecord };
|
|
45205
46098
|
}
|
|
46099
|
+
function _internalPrepareEvaluatorScore(scoreValue, name) {
|
|
46100
|
+
if (scoreValue === null) return { results: null };
|
|
46101
|
+
if (Array.isArray(scoreValue)) {
|
|
46102
|
+
for (const score of scoreValue) {
|
|
46103
|
+
if (!(typeof score === "object" && !isEmpty2(score))) {
|
|
46104
|
+
throw new Error(
|
|
46105
|
+
`When returning an array of scores, each score must be a non-empty object. Got: ${JSON.stringify(score)}`
|
|
46106
|
+
);
|
|
46107
|
+
}
|
|
46108
|
+
}
|
|
46109
|
+
}
|
|
46110
|
+
let results;
|
|
46111
|
+
if (Array.isArray(scoreValue)) {
|
|
46112
|
+
results = scoreValue;
|
|
46113
|
+
} else if (typeof scoreValue === "object" && !isEmpty2(scoreValue)) {
|
|
46114
|
+
results = [scoreValue];
|
|
46115
|
+
} else {
|
|
46116
|
+
results = [{ name, score: scoreValue }];
|
|
46117
|
+
}
|
|
46118
|
+
const { resultMetadata, scoresRecord } = buildSpanScores(results);
|
|
46119
|
+
const fields = (score) => {
|
|
46120
|
+
const { metadata: _metadata, name: _name, ...rest } = score;
|
|
46121
|
+
return rest;
|
|
46122
|
+
};
|
|
46123
|
+
return {
|
|
46124
|
+
results,
|
|
46125
|
+
output: results.length === 1 ? fields(results[0]) : Object.fromEntries(
|
|
46126
|
+
results.map((score) => [score.name ?? name, fields(score)])
|
|
46127
|
+
),
|
|
46128
|
+
metadata: resultMetadata,
|
|
46129
|
+
scores: scoresRecord
|
|
46130
|
+
};
|
|
46131
|
+
}
|
|
45206
46132
|
async function runInScorerSpan(rootSpan, spanName, spanType, propagatedEvent, eventInput, fn) {
|
|
45207
46133
|
try {
|
|
45208
46134
|
const value = await rootSpan.traced(fn, {
|
|
@@ -45247,6 +46173,27 @@ function toClassificationItem(c) {
|
|
|
45247
46173
|
...c.metadata !== void 0 ? { metadata: c.metadata } : {}
|
|
45248
46174
|
};
|
|
45249
46175
|
}
|
|
46176
|
+
function _internalPrepareEvaluatorClassification(value, name) {
|
|
46177
|
+
if (value === null) return { results: null };
|
|
46178
|
+
const results = (Array.isArray(value) ? value : [value]).map(
|
|
46179
|
+
(result) => validateClassificationResult(result, name)
|
|
46180
|
+
);
|
|
46181
|
+
const classifications = /* @__PURE__ */ Object.create(null);
|
|
46182
|
+
for (const result of results) {
|
|
46183
|
+
(classifications[result.name] ??= []).push(toClassificationItem(result));
|
|
46184
|
+
}
|
|
46185
|
+
return {
|
|
46186
|
+
results,
|
|
46187
|
+
output: results.length === 1 ? toClassificationItem(results[0]) : Object.fromEntries(
|
|
46188
|
+
results.map((result) => [
|
|
46189
|
+
result.name,
|
|
46190
|
+
toClassificationItem(result)
|
|
46191
|
+
])
|
|
46192
|
+
),
|
|
46193
|
+
metadata: buildSpanMetadata(results),
|
|
46194
|
+
classifications
|
|
46195
|
+
};
|
|
46196
|
+
}
|
|
45250
46197
|
function logScoringFailures(kind, failures, metadata, rootSpan, state) {
|
|
45251
46198
|
if (!failures.length) return [];
|
|
45252
46199
|
const errorMap = Object.fromEntries(
|
|
@@ -45294,54 +46241,14 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
|
|
|
45294
46241
|
(evaluator.state ?? _internalGetGlobalState())?.spanCache?.start();
|
|
45295
46242
|
}
|
|
45296
46243
|
try {
|
|
45297
|
-
if (typeof evaluator.data === "string") {
|
|
45298
|
-
throw new Error("Unimplemented: string data paths");
|
|
45299
|
-
}
|
|
45300
|
-
let dataResult = typeof evaluator.data === "function" ? evaluator.data() : evaluator.data;
|
|
45301
46244
|
parameters = await validateParameters(
|
|
45302
46245
|
parameters ?? {},
|
|
45303
46246
|
evaluator.parameters
|
|
45304
46247
|
);
|
|
45305
|
-
|
|
45306
|
-
|
|
45307
|
-
|
|
45308
|
-
|
|
45309
|
-
if (!experiment) {
|
|
45310
|
-
throw new Error(
|
|
45311
|
-
"Cannot use BaseExperiment() without connecting to Braintrust (you most likely set --no-send-logs)"
|
|
45312
|
-
);
|
|
45313
|
-
}
|
|
45314
|
-
let name = dataResult.name;
|
|
45315
|
-
if (isEmpty2(name)) {
|
|
45316
|
-
const baseExperiment = await experiment.fetchBaseExperiment();
|
|
45317
|
-
if (!baseExperiment) {
|
|
45318
|
-
throw new Error("BaseExperiment() failed to fetch base experiment");
|
|
45319
|
-
}
|
|
45320
|
-
name = baseExperiment.name;
|
|
45321
|
-
}
|
|
45322
|
-
dataResult = initExperiment2(evaluator.state, {
|
|
45323
|
-
...evaluator.projectId ? { projectId: evaluator.projectId } : { project: evaluator.projectName },
|
|
45324
|
-
experiment: name,
|
|
45325
|
-
open: true
|
|
45326
|
-
}).asDataset();
|
|
45327
|
-
}
|
|
45328
|
-
const resolvedDataResult = dataResult instanceof Promise ? await dataResult : dataResult;
|
|
45329
|
-
const dataIterable = (() => {
|
|
45330
|
-
if (isAsyncIterable7(resolvedDataResult)) {
|
|
45331
|
-
return resolvedDataResult;
|
|
45332
|
-
}
|
|
45333
|
-
if (Array.isArray(resolvedDataResult) || isIterable(resolvedDataResult)) {
|
|
45334
|
-
const iterable = resolvedDataResult;
|
|
45335
|
-
return (async function* () {
|
|
45336
|
-
for (const datum of iterable) {
|
|
45337
|
-
yield datum;
|
|
45338
|
-
}
|
|
45339
|
-
})();
|
|
45340
|
-
}
|
|
45341
|
-
throw new Error(
|
|
45342
|
-
"Evaluator data must be an array, iterable, or async iterable"
|
|
45343
|
-
);
|
|
45344
|
-
})();
|
|
46248
|
+
const dataIterable = await _internalResolveEvaluatorData(
|
|
46249
|
+
evaluator,
|
|
46250
|
+
experiment
|
|
46251
|
+
);
|
|
45345
46252
|
progressReporter.start(evaluator.evalName, 0);
|
|
45346
46253
|
const experimentIdPromise = experiment ? (async () => {
|
|
45347
46254
|
try {
|
|
@@ -45410,57 +46317,45 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
|
|
|
45410
46317
|
ensureSpansFlushed,
|
|
45411
46318
|
state
|
|
45412
46319
|
}) : void 0;
|
|
45413
|
-
let metadata = {
|
|
45414
|
-
..."metadata" in datum ? datum.metadata : {}
|
|
45415
|
-
};
|
|
46320
|
+
let metadata = {};
|
|
45416
46321
|
const expected = "expected" in datum ? datum.expected : void 0;
|
|
45417
46322
|
let output = void 0;
|
|
45418
46323
|
let error = void 0;
|
|
45419
|
-
let tags = [
|
|
45420
|
-
const scores =
|
|
45421
|
-
const classifications =
|
|
46324
|
+
let tags = [];
|
|
46325
|
+
const scores = /* @__PURE__ */ Object.create(null);
|
|
46326
|
+
const classifications = /* @__PURE__ */ Object.create(null);
|
|
45422
46327
|
const scorerNames = (evaluator.scores ?? []).map(scorerName);
|
|
45423
46328
|
const classifierNames = (evaluator.classifiers ?? []).map(
|
|
45424
46329
|
classifierName
|
|
45425
46330
|
);
|
|
45426
46331
|
let unhandledScores = scorerNames;
|
|
45427
46332
|
try {
|
|
45428
|
-
const
|
|
45429
|
-
|
|
45430
|
-
|
|
45431
|
-
|
|
45432
|
-
|
|
45433
|
-
|
|
45434
|
-
|
|
45435
|
-
|
|
45436
|
-
|
|
45437
|
-
|
|
45438
|
-
|
|
45439
|
-
|
|
45440
|
-
|
|
45441
|
-
|
|
45442
|
-
|
|
45443
|
-
object_type: "task"
|
|
45444
|
-
});
|
|
45445
|
-
},
|
|
45446
|
-
trialIndex,
|
|
45447
|
-
tags
|
|
45448
|
-
};
|
|
45449
|
-
const outputResult = evaluator.task(datum.input, hooksForTask);
|
|
45450
|
-
if (outputResult instanceof Promise) {
|
|
45451
|
-
output = await outputResult;
|
|
45452
|
-
} else {
|
|
45453
|
-
output = outputResult;
|
|
46333
|
+
const taskResult = await rootSpan.traced(
|
|
46334
|
+
(span) => _internalRunEvaluatorTask(
|
|
46335
|
+
evaluator.task,
|
|
46336
|
+
datum,
|
|
46337
|
+
trialIndex,
|
|
46338
|
+
parameters ?? {},
|
|
46339
|
+
span,
|
|
46340
|
+
(event) => {
|
|
46341
|
+
stream?.({
|
|
46342
|
+
...event,
|
|
46343
|
+
id: rootSpan.id,
|
|
46344
|
+
origin: baseEvent.event?.origin,
|
|
46345
|
+
name: evaluator.evalName,
|
|
46346
|
+
object_type: "task"
|
|
46347
|
+
});
|
|
45454
46348
|
}
|
|
45455
|
-
|
|
45456
|
-
span.log({ output });
|
|
45457
|
-
},
|
|
46349
|
+
),
|
|
45458
46350
|
{
|
|
45459
46351
|
name: "task",
|
|
45460
46352
|
spanAttributes: { type: "task" /* TASK */ },
|
|
45461
46353
|
event: { input: datum.input }
|
|
45462
46354
|
}
|
|
45463
46355
|
);
|
|
46356
|
+
output = taskResult.output;
|
|
46357
|
+
metadata = taskResult.metadata;
|
|
46358
|
+
tags = taskResult.tags;
|
|
45464
46359
|
if (tags.length) {
|
|
45465
46360
|
rootSpan.log({ output, metadata, expected, tags });
|
|
45466
46361
|
} else {
|
|
@@ -45470,20 +46365,18 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
|
|
|
45470
46365
|
await rootSpan.flush();
|
|
45471
46366
|
}
|
|
45472
46367
|
const scoringArgs = {
|
|
46368
|
+
id: datum.id,
|
|
45473
46369
|
input: datum.input,
|
|
45474
46370
|
expected: "expected" in datum ? datum.expected : void 0,
|
|
45475
46371
|
metadata,
|
|
45476
46372
|
output,
|
|
46373
|
+
tags,
|
|
45477
46374
|
trace
|
|
45478
46375
|
};
|
|
45479
46376
|
const { trace: _trace, ...scoringArgsForLogging } = scoringArgs;
|
|
45480
46377
|
const propagatedEvent = makeScorerPropagatedEvent(
|
|
45481
46378
|
await rootSpan.export()
|
|
45482
46379
|
);
|
|
45483
|
-
const getOtherFields = (s) => {
|
|
45484
|
-
const { metadata: _metadata, name: _name, ...rest } = s;
|
|
45485
|
-
return rest;
|
|
45486
|
-
};
|
|
45487
46380
|
const [scoreResults, classificationResults] = await Promise.all([
|
|
45488
46381
|
Promise.all(
|
|
45489
46382
|
(evaluator.scores ?? []).map(
|
|
@@ -45497,35 +46390,17 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
|
|
|
45497
46390
|
const scoreValue = await Promise.resolve(
|
|
45498
46391
|
score(scoringArgs)
|
|
45499
46392
|
);
|
|
45500
|
-
|
|
45501
|
-
|
|
45502
|
-
|
|
45503
|
-
if (!(typeof s === "object" && !isEmpty2(s))) {
|
|
45504
|
-
throw new Error(
|
|
45505
|
-
`When returning an array of scores, each score must be a non-empty object. Got: ${JSON.stringify(s)}`
|
|
45506
|
-
);
|
|
45507
|
-
}
|
|
45508
|
-
}
|
|
45509
|
-
}
|
|
45510
|
-
const results = Array.isArray(scoreValue) ? scoreValue : typeof scoreValue === "object" && !isEmpty2(scoreValue) ? [scoreValue] : [
|
|
45511
|
-
{
|
|
45512
|
-
name: scorerNames[score_idx],
|
|
45513
|
-
score: scoreValue
|
|
45514
|
-
}
|
|
45515
|
-
];
|
|
45516
|
-
const { resultMetadata, scoresRecord } = buildSpanScores(results);
|
|
45517
|
-
const resultOutput = results.length === 1 ? getOtherFields(results[0]) : results.reduce(
|
|
45518
|
-
(prev, s) => mergeDicts(prev, {
|
|
45519
|
-
[s.name]: getOtherFields(s)
|
|
45520
|
-
}),
|
|
45521
|
-
{}
|
|
46393
|
+
const prepared = _internalPrepareEvaluatorScore(
|
|
46394
|
+
scoreValue,
|
|
46395
|
+
scorerNames[score_idx]
|
|
45522
46396
|
);
|
|
46397
|
+
if (prepared.results === null) return null;
|
|
45523
46398
|
span.log({
|
|
45524
|
-
output:
|
|
45525
|
-
metadata:
|
|
45526
|
-
scores:
|
|
46399
|
+
output: prepared.output,
|
|
46400
|
+
metadata: prepared.metadata,
|
|
46401
|
+
scores: prepared.scores
|
|
45527
46402
|
});
|
|
45528
|
-
return results;
|
|
46403
|
+
return prepared.results;
|
|
45529
46404
|
}
|
|
45530
46405
|
)
|
|
45531
46406
|
)
|
|
@@ -45542,24 +46417,16 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
|
|
|
45542
46417
|
const classifierValue = await Promise.resolve(
|
|
45543
46418
|
classifier(scoringArgs)
|
|
45544
46419
|
);
|
|
45545
|
-
|
|
45546
|
-
|
|
45547
|
-
|
|
45548
|
-
result,
|
|
45549
|
-
classifierNames[idx]
|
|
45550
|
-
)
|
|
45551
|
-
);
|
|
45552
|
-
const resultOutput = rawResults.length === 1 ? toClassificationItem(rawResults[0]) : rawResults.reduce(
|
|
45553
|
-
(prev, r) => mergeDicts(prev, {
|
|
45554
|
-
[r.name]: toClassificationItem(r)
|
|
45555
|
-
}),
|
|
45556
|
-
{}
|
|
46420
|
+
const prepared = _internalPrepareEvaluatorClassification(
|
|
46421
|
+
classifierValue,
|
|
46422
|
+
classifierNames[idx]
|
|
45557
46423
|
);
|
|
46424
|
+
if (prepared.results === null) return null;
|
|
45558
46425
|
span.log({
|
|
45559
|
-
output:
|
|
45560
|
-
metadata:
|
|
46426
|
+
output: prepared.output,
|
|
46427
|
+
metadata: prepared.metadata
|
|
45561
46428
|
});
|
|
45562
|
-
return
|
|
46429
|
+
return prepared.results;
|
|
45563
46430
|
}
|
|
45564
46431
|
)
|
|
45565
46432
|
)
|
|
@@ -45788,7 +46655,7 @@ function accumulateScores(accumulator, scores) {
|
|
|
45788
46655
|
}
|
|
45789
46656
|
}
|
|
45790
46657
|
function ensureScoreAccumulator(results) {
|
|
45791
|
-
const accumulator =
|
|
46658
|
+
const accumulator = /* @__PURE__ */ Object.create(null);
|
|
45792
46659
|
for (const result of results) {
|
|
45793
46660
|
accumulateScores(accumulator, result.scores);
|
|
45794
46661
|
}
|
|
@@ -45931,6 +46798,1156 @@ var defaultReporter = {
|
|
|
45931
46798
|
}
|
|
45932
46799
|
};
|
|
45933
46800
|
|
|
46801
|
+
// src/durable-eval.ts
|
|
46802
|
+
var encoder = new TextEncoder();
|
|
46803
|
+
var decoder = new TextDecoder();
|
|
46804
|
+
var BATCH_TASK_KIND = "braintrust.durable.batch-task";
|
|
46805
|
+
var BATCH_SCORER_KIND = "braintrust.durable.batch-scorer";
|
|
46806
|
+
var DEFAULT_BATCH_SIZE = 1e3;
|
|
46807
|
+
var DurableEvalMemoryStore = class {
|
|
46808
|
+
values = /* @__PURE__ */ new Map();
|
|
46809
|
+
async read(key) {
|
|
46810
|
+
return this.values.get(key)?.slice();
|
|
46811
|
+
}
|
|
46812
|
+
async write(key, value) {
|
|
46813
|
+
this.values.set(key, value.slice());
|
|
46814
|
+
}
|
|
46815
|
+
async getOrSet(key, value) {
|
|
46816
|
+
const existing = this.values.get(key);
|
|
46817
|
+
if (existing) return { value: existing.slice(), created: false };
|
|
46818
|
+
this.values.set(key, value.slice());
|
|
46819
|
+
return { value: value.slice(), created: true };
|
|
46820
|
+
}
|
|
46821
|
+
};
|
|
46822
|
+
var DurableEvalRedisStore = class {
|
|
46823
|
+
client;
|
|
46824
|
+
keyPrefix;
|
|
46825
|
+
ttlMs;
|
|
46826
|
+
constructor(options) {
|
|
46827
|
+
this.client = options.client;
|
|
46828
|
+
this.keyPrefix = options.keyPrefix ?? "braintrust-eval:";
|
|
46829
|
+
this.ttlMs = options.ttlMs ?? 1e3 * 60 * 60 * 24 * 7;
|
|
46830
|
+
if (!Number.isInteger(this.ttlMs) || this.ttlMs < 1) {
|
|
46831
|
+
throw new Error("DurableEvalRedisStore ttlMs must be a positive integer");
|
|
46832
|
+
}
|
|
46833
|
+
}
|
|
46834
|
+
async read(key) {
|
|
46835
|
+
const value = await this.client.get(`${this.keyPrefix}${key}`);
|
|
46836
|
+
if (value == null) return void 0;
|
|
46837
|
+
if (typeof value !== "string") {
|
|
46838
|
+
throw new Error("DurableEvalRedisStore expected GET to return a string");
|
|
46839
|
+
}
|
|
46840
|
+
return base64ToUint8Array(value);
|
|
46841
|
+
}
|
|
46842
|
+
async write(key, value) {
|
|
46843
|
+
const client = this.client;
|
|
46844
|
+
const set = client.set;
|
|
46845
|
+
const redisKey = `${this.keyPrefix}${key}`;
|
|
46846
|
+
const encoded = uint8ArrayToBase64(value);
|
|
46847
|
+
if (typeof client.defineCommand === "function") {
|
|
46848
|
+
await set.call(client, redisKey, encoded, "PX", this.ttlMs);
|
|
46849
|
+
} else if (typeof client.sendCommand === "function") {
|
|
46850
|
+
await set.call(client, redisKey, encoded, { PX: this.ttlMs });
|
|
46851
|
+
} else if (typeof client.createScript === "function") {
|
|
46852
|
+
await set.call(client, redisKey, encoded, { px: this.ttlMs });
|
|
46853
|
+
} else {
|
|
46854
|
+
throw new Error(
|
|
46855
|
+
"DurableEvalRedisStore requires a node-redis, ioredis, or @upstash/redis client"
|
|
46856
|
+
);
|
|
46857
|
+
}
|
|
46858
|
+
}
|
|
46859
|
+
async getOrSet(key, value) {
|
|
46860
|
+
const redisKey = `${this.keyPrefix}${key}`;
|
|
46861
|
+
const encoded = uint8ArrayToBase64(value);
|
|
46862
|
+
const client = this.client;
|
|
46863
|
+
const set = client.set;
|
|
46864
|
+
let setOptions;
|
|
46865
|
+
if (typeof client.defineCommand === "function") {
|
|
46866
|
+
setOptions = ["PX", this.ttlMs, "NX", "GET"];
|
|
46867
|
+
} else if (typeof client.sendCommand === "function") {
|
|
46868
|
+
setOptions = [{ PX: this.ttlMs, NX: true, GET: true }];
|
|
46869
|
+
} else if (typeof client.createScript === "function") {
|
|
46870
|
+
setOptions = [{ px: this.ttlMs, nx: true, get: true }];
|
|
46871
|
+
} else {
|
|
46872
|
+
throw new Error(
|
|
46873
|
+
"DurableEvalRedisStore getOrSet requires a node-redis, ioredis, or @upstash/redis client"
|
|
46874
|
+
);
|
|
46875
|
+
}
|
|
46876
|
+
const existing = await set.call(client, redisKey, encoded, ...setOptions);
|
|
46877
|
+
if (existing === null) return { value: value.slice(), created: true };
|
|
46878
|
+
if (typeof existing !== "string") {
|
|
46879
|
+
throw new Error(
|
|
46880
|
+
"DurableEvalRedisStore expected atomic SET to return a string or null"
|
|
46881
|
+
);
|
|
46882
|
+
}
|
|
46883
|
+
return { value: base64ToUint8Array(existing), created: false };
|
|
46884
|
+
}
|
|
46885
|
+
};
|
|
46886
|
+
var BatchTask = class {
|
|
46887
|
+
constructor(processor) {
|
|
46888
|
+
this.processor = processor;
|
|
46889
|
+
}
|
|
46890
|
+
processor;
|
|
46891
|
+
kind = BATCH_TASK_KIND;
|
|
46892
|
+
};
|
|
46893
|
+
var BatchScorer = class {
|
|
46894
|
+
constructor(processor) {
|
|
46895
|
+
this.processor = processor;
|
|
46896
|
+
this.name = processor.name;
|
|
46897
|
+
}
|
|
46898
|
+
processor;
|
|
46899
|
+
kind = BATCH_SCORER_KIND;
|
|
46900
|
+
name;
|
|
46901
|
+
};
|
|
46902
|
+
function defineDurableEval(projectName, evaluator) {
|
|
46903
|
+
const definition = {
|
|
46904
|
+
projectName,
|
|
46905
|
+
evalName: evaluator.experimentName ?? projectName,
|
|
46906
|
+
evaluator
|
|
46907
|
+
};
|
|
46908
|
+
return {
|
|
46909
|
+
start: (options = {}) => startDurableEval(definition, options),
|
|
46910
|
+
status: (options) => getDurableEvalStatus(definition, options),
|
|
46911
|
+
poll: (options) => pollDurableEval(definition, options),
|
|
46912
|
+
processBatchResult: (result) => processDurableBatchResult(definition, result)
|
|
46913
|
+
};
|
|
46914
|
+
}
|
|
46915
|
+
async function startDurableEval(definition, options) {
|
|
46916
|
+
const store = definition.evaluator.store;
|
|
46917
|
+
const runId = newId();
|
|
46918
|
+
const key = runKey(definition.projectName, definition.evalName, runId);
|
|
46919
|
+
const { data } = callEvaluatorData(definition.evaluator.data);
|
|
46920
|
+
const parameters = await validateParameters(
|
|
46921
|
+
options.parameters ?? {},
|
|
46922
|
+
definition.evaluator.parameters
|
|
46923
|
+
);
|
|
46924
|
+
const experimentName = definition.evaluator.experimentName ?? `${definition.evalName}-${runId}`;
|
|
46925
|
+
const experiment = await _internalInitEvaluatorExperiment(
|
|
46926
|
+
definition.projectName,
|
|
46927
|
+
{ ...definition.evaluator, data },
|
|
46928
|
+
data,
|
|
46929
|
+
{
|
|
46930
|
+
disabled: options.noSendLogs ?? false,
|
|
46931
|
+
experimentName,
|
|
46932
|
+
update: true
|
|
46933
|
+
}
|
|
46934
|
+
);
|
|
46935
|
+
if (!isBatchTask(definition.evaluator.task) && !(definition.evaluator.scores ?? []).some(isBatchScorer)) {
|
|
46936
|
+
const result = await runEvaluator(
|
|
46937
|
+
experiment,
|
|
46938
|
+
{
|
|
46939
|
+
...definition.evaluator,
|
|
46940
|
+
projectName: definition.projectName,
|
|
46941
|
+
evalName: definition.evalName,
|
|
46942
|
+
data
|
|
46943
|
+
},
|
|
46944
|
+
{
|
|
46945
|
+
start: () => void 0,
|
|
46946
|
+
stop: () => void 0,
|
|
46947
|
+
increment: () => void 0
|
|
46948
|
+
},
|
|
46949
|
+
[],
|
|
46950
|
+
void 0,
|
|
46951
|
+
parameters,
|
|
46952
|
+
true,
|
|
46953
|
+
true
|
|
46954
|
+
);
|
|
46955
|
+
const state2 = {
|
|
46956
|
+
runId,
|
|
46957
|
+
experimentName,
|
|
46958
|
+
noSendLogs: options.noSendLogs ?? false,
|
|
46959
|
+
parameters: assertJsonValue(parameters, "eval parameters"),
|
|
46960
|
+
status: "completed",
|
|
46961
|
+
summary: result.summary,
|
|
46962
|
+
cases: [],
|
|
46963
|
+
batches: []
|
|
46964
|
+
};
|
|
46965
|
+
await experiment?.flush();
|
|
46966
|
+
await writeRunRecord(store, key, state2);
|
|
46967
|
+
return currentStatus(definition, state2);
|
|
46968
|
+
}
|
|
46969
|
+
const state = {
|
|
46970
|
+
runId,
|
|
46971
|
+
experimentName,
|
|
46972
|
+
noSendLogs: options.noSendLogs ?? false,
|
|
46973
|
+
parameters: assertJsonValue(parameters, "eval parameters"),
|
|
46974
|
+
status: "running",
|
|
46975
|
+
cases: await materializeCases(definition, data, experiment),
|
|
46976
|
+
batches: []
|
|
46977
|
+
};
|
|
46978
|
+
await writeCaseBaseRecords(store, key, state.cases);
|
|
46979
|
+
await writeRunRecord(store, key, state);
|
|
46980
|
+
return advanceDurableEval(definition, state, store, key, experiment);
|
|
46981
|
+
}
|
|
46982
|
+
async function getDurableEvalStatus(definition, options) {
|
|
46983
|
+
const store = definition.evaluator.store;
|
|
46984
|
+
const state = await readRunState(
|
|
46985
|
+
definition,
|
|
46986
|
+
store,
|
|
46987
|
+
runKey(definition.projectName, definition.evalName, options.runId)
|
|
46988
|
+
);
|
|
46989
|
+
if (!state) throw new Error(`Durable eval run ${options.runId} is missing`);
|
|
46990
|
+
return currentStatus(definition, state);
|
|
46991
|
+
}
|
|
46992
|
+
async function processDurableBatchResult(definition, result) {
|
|
46993
|
+
if (!result.batchId && !result.externalId) {
|
|
46994
|
+
throw new Error("Batch results require batchId or externalId");
|
|
46995
|
+
}
|
|
46996
|
+
const store = definition.evaluator.store;
|
|
46997
|
+
const key = runKey(definition.projectName, definition.evalName, result.runId);
|
|
46998
|
+
const state = await readRunState(definition, store, key);
|
|
46999
|
+
if (!state) throw new Error(`Durable eval run ${result.runId} is missing`);
|
|
47000
|
+
const byBatch = result.batchId ? state.batches.find((candidate) => candidate.id === result.batchId) : void 0;
|
|
47001
|
+
const byExternal = result.externalId ? state.batches.find(
|
|
47002
|
+
(candidate) => candidate.externalId === result.externalId
|
|
47003
|
+
) : void 0;
|
|
47004
|
+
if (byBatch && byExternal && byBatch.id !== byExternal.id) {
|
|
47005
|
+
throw new Error("batchId and externalId identify different batches");
|
|
47006
|
+
}
|
|
47007
|
+
const batch = byBatch ?? byExternal;
|
|
47008
|
+
if (!batch) throw new Error("No submitted batch matches this result");
|
|
47009
|
+
if (batch.status !== "complete") {
|
|
47010
|
+
const records = await collectBatch(definition, state, batch);
|
|
47011
|
+
batch.status = "complete";
|
|
47012
|
+
await writeCaseRecords(store, key, records);
|
|
47013
|
+
await writeBatchRecords(store, key, [batch]);
|
|
47014
|
+
}
|
|
47015
|
+
return advanceDurableEval(
|
|
47016
|
+
definition,
|
|
47017
|
+
await readRunState(definition, store, key),
|
|
47018
|
+
store,
|
|
47019
|
+
key
|
|
47020
|
+
);
|
|
47021
|
+
}
|
|
47022
|
+
async function pollDurableEval(definition, options) {
|
|
47023
|
+
const store = definition.evaluator.store;
|
|
47024
|
+
const key = runKey(
|
|
47025
|
+
definition.projectName,
|
|
47026
|
+
definition.evalName,
|
|
47027
|
+
options.runId
|
|
47028
|
+
);
|
|
47029
|
+
const state = await readRunState(definition, store, key);
|
|
47030
|
+
if (!state) throw new Error(`Durable eval run ${options.runId} is missing`);
|
|
47031
|
+
const batches = state.batches.filter((batch) => {
|
|
47032
|
+
if (batch.status === "complete") return false;
|
|
47033
|
+
return processorForStage(definition, batch.kind, batch.scorerName).completion.mode === "poll";
|
|
47034
|
+
});
|
|
47035
|
+
const results = await Promise.all(
|
|
47036
|
+
batches.map(async (batch) => ({
|
|
47037
|
+
batch,
|
|
47038
|
+
result: await processorForStage(definition, batch.kind, batch.scorerName).completion.poll(batch.submissionData, {
|
|
47039
|
+
runId: state.runId,
|
|
47040
|
+
batchId: batch.id
|
|
47041
|
+
})
|
|
47042
|
+
}))
|
|
47043
|
+
);
|
|
47044
|
+
const changedCases = /* @__PURE__ */ new Map();
|
|
47045
|
+
const changedBatches = [];
|
|
47046
|
+
for (const { batch, result } of results) {
|
|
47047
|
+
if (result.status === "failed") throw asError(result.error);
|
|
47048
|
+
if (result.status !== "complete") continue;
|
|
47049
|
+
for (const record of await collectBatch(definition, state, batch)) {
|
|
47050
|
+
changedCases.set(record.id, record);
|
|
47051
|
+
}
|
|
47052
|
+
batch.status = "complete";
|
|
47053
|
+
changedBatches.push(batch);
|
|
47054
|
+
}
|
|
47055
|
+
if (changedBatches.length > 0) {
|
|
47056
|
+
await writeCaseRecords(store, key, [...changedCases.values()]);
|
|
47057
|
+
await writeBatchRecords(store, key, changedBatches);
|
|
47058
|
+
}
|
|
47059
|
+
const currentState = changedBatches.length > 0 ? await readRunState(definition, store, key) : state;
|
|
47060
|
+
return advanceDurableEval(definition, currentState, store, key);
|
|
47061
|
+
}
|
|
47062
|
+
async function openDurableExperiment(definition, state) {
|
|
47063
|
+
const data = [];
|
|
47064
|
+
return await _internalInitEvaluatorExperiment(
|
|
47065
|
+
definition.projectName,
|
|
47066
|
+
{ ...definition.evaluator, data },
|
|
47067
|
+
data,
|
|
47068
|
+
{
|
|
47069
|
+
disabled: state.noSendLogs,
|
|
47070
|
+
experimentName: state.experimentName,
|
|
47071
|
+
update: true
|
|
47072
|
+
}
|
|
47073
|
+
);
|
|
47074
|
+
}
|
|
47075
|
+
async function advanceDurableEval(definition, state, store, key, existingExperiment) {
|
|
47076
|
+
if (state.status === "completed") return currentStatus(definition, state);
|
|
47077
|
+
const experiment = existingExperiment === void 0 ? await openDurableExperiment(definition, state) : existingExperiment;
|
|
47078
|
+
await runTaskStage(definition, state, store, key, experiment);
|
|
47079
|
+
await logCompletedTasks(definition, state, store, key, experiment);
|
|
47080
|
+
state = await readRunState(definition, store, key) ?? state;
|
|
47081
|
+
if (state.cases.some((record) => !record.taskComplete || !record.taskLogged)) {
|
|
47082
|
+
return currentStatus(definition, state);
|
|
47083
|
+
}
|
|
47084
|
+
await runScoreStages(definition, state, store, key, experiment);
|
|
47085
|
+
state = await readRunState(definition, store, key) ?? state;
|
|
47086
|
+
const scorerNames = resolveScorers(definition.evaluator.scores ?? []).map(
|
|
47087
|
+
({ name }) => name
|
|
47088
|
+
);
|
|
47089
|
+
const classifierNames = (definition.evaluator.classifiers ?? []).map(
|
|
47090
|
+
classifierName
|
|
47091
|
+
);
|
|
47092
|
+
if (state.cases.some(
|
|
47093
|
+
(record) => scorerNames.some(
|
|
47094
|
+
(name) => !Object.hasOwn(record.scores, name) || !Object.hasOwn(record.loggedScores, name)
|
|
47095
|
+
) || classifierNames.some(
|
|
47096
|
+
(name) => !Object.hasOwn(record.loggedClassifications, name)
|
|
47097
|
+
)
|
|
47098
|
+
)) {
|
|
47099
|
+
return currentStatus(definition, state);
|
|
47100
|
+
}
|
|
47101
|
+
if (!await claimAction(store, key, "finish")) {
|
|
47102
|
+
const latest = await readRunState(definition, store, key);
|
|
47103
|
+
return currentStatus(definition, latest ?? state);
|
|
47104
|
+
}
|
|
47105
|
+
state.summary = await finishExperiment(definition, state, experiment);
|
|
47106
|
+
state.status = "completed";
|
|
47107
|
+
await writeRunRecord(store, key, state);
|
|
47108
|
+
return currentStatus(definition, state);
|
|
47109
|
+
}
|
|
47110
|
+
function currentStatus(definition, state) {
|
|
47111
|
+
if (state.status === "completed") {
|
|
47112
|
+
if (!state.summary) {
|
|
47113
|
+
throw new Error(`Durable eval run ${state.runId} has no saved summary`);
|
|
47114
|
+
}
|
|
47115
|
+
return {
|
|
47116
|
+
status: "completed",
|
|
47117
|
+
runId: state.runId,
|
|
47118
|
+
pending: { poll: 0, webhook: 0 },
|
|
47119
|
+
summary: state.summary
|
|
47120
|
+
};
|
|
47121
|
+
}
|
|
47122
|
+
const pending = { poll: 0, webhook: 0 };
|
|
47123
|
+
for (const batch of state.batches) {
|
|
47124
|
+
if (batch.status === "complete") continue;
|
|
47125
|
+
pending[processorForStage(definition, batch.kind, batch.scorerName).completion.mode]++;
|
|
47126
|
+
}
|
|
47127
|
+
return { status: "waiting", runId: state.runId, pending };
|
|
47128
|
+
}
|
|
47129
|
+
async function startCaseRoot(definition, state, record, experiment) {
|
|
47130
|
+
if (!experiment) return NOOP_SPAN;
|
|
47131
|
+
const datum = record.datum;
|
|
47132
|
+
return _internalStartSpanWithInitialMerge({
|
|
47133
|
+
...definition.evaluator.state ? { state: definition.evaluator.state } : {},
|
|
47134
|
+
parent: await experiment.export(),
|
|
47135
|
+
name: "eval",
|
|
47136
|
+
spanId: deterministicId(`${state.runId}:${record.id}:span`),
|
|
47137
|
+
spanAttributes: { type: "eval" /* EVAL */ },
|
|
47138
|
+
event: {
|
|
47139
|
+
id: deterministicId(`${state.runId}:${record.id}:row`),
|
|
47140
|
+
input: datum.input,
|
|
47141
|
+
expected: "expected" in datum ? datum.expected : void 0,
|
|
47142
|
+
tags: datum.tags,
|
|
47143
|
+
origin: datum.origin
|
|
47144
|
+
}
|
|
47145
|
+
});
|
|
47146
|
+
}
|
|
47147
|
+
async function logTaskResult(definition, state, record, experiment, task) {
|
|
47148
|
+
const datum = record.datum;
|
|
47149
|
+
const root = await startCaseRoot(definition, state, record, experiment);
|
|
47150
|
+
try {
|
|
47151
|
+
if (task) {
|
|
47152
|
+
const result = await root.traced(
|
|
47153
|
+
(span) => _internalRunEvaluatorTask(
|
|
47154
|
+
task,
|
|
47155
|
+
datum,
|
|
47156
|
+
record.trialIndex,
|
|
47157
|
+
state.parameters,
|
|
47158
|
+
span
|
|
47159
|
+
),
|
|
47160
|
+
{
|
|
47161
|
+
name: "task",
|
|
47162
|
+
spanId: deterministicId(`${state.runId}:${record.id}:task`),
|
|
47163
|
+
spanAttributes: { type: "task" /* TASK */ },
|
|
47164
|
+
event: { input: datum.input }
|
|
47165
|
+
}
|
|
47166
|
+
);
|
|
47167
|
+
record.output = assertJsonValue(
|
|
47168
|
+
result.output,
|
|
47169
|
+
`task output for ${record.caseId}`
|
|
47170
|
+
);
|
|
47171
|
+
record.metadata = assertJsonValue(result.metadata, "task metadata");
|
|
47172
|
+
record.tags = result.tags;
|
|
47173
|
+
record.taskComplete = true;
|
|
47174
|
+
} else {
|
|
47175
|
+
await root.traced((span) => span.log({ output: record.output }), {
|
|
47176
|
+
name: "task",
|
|
47177
|
+
spanId: deterministicId(`${state.runId}:${record.id}:task`),
|
|
47178
|
+
spanAttributes: { type: "task" /* TASK */ },
|
|
47179
|
+
event: { input: datum.input }
|
|
47180
|
+
});
|
|
47181
|
+
}
|
|
47182
|
+
root.log({
|
|
47183
|
+
output: record.output,
|
|
47184
|
+
expected: "expected" in datum ? datum.expected : void 0,
|
|
47185
|
+
metadata: {
|
|
47186
|
+
...record.metadata,
|
|
47187
|
+
durable_eval: {
|
|
47188
|
+
run_id: state.runId,
|
|
47189
|
+
case_id: record.caseId,
|
|
47190
|
+
trial_index: record.trialIndex
|
|
47191
|
+
}
|
|
47192
|
+
},
|
|
47193
|
+
tags: record.tags
|
|
47194
|
+
});
|
|
47195
|
+
record.rootSpan = await root.export();
|
|
47196
|
+
record.taskLogged = true;
|
|
47197
|
+
} catch (error) {
|
|
47198
|
+
logError(root, error);
|
|
47199
|
+
throw error;
|
|
47200
|
+
} finally {
|
|
47201
|
+
root.end();
|
|
47202
|
+
}
|
|
47203
|
+
}
|
|
47204
|
+
async function logCompletedTasks(definition, state, store, key, experiment) {
|
|
47205
|
+
const changed = [];
|
|
47206
|
+
for (const record of state.cases) {
|
|
47207
|
+
if (!record.taskComplete || record.taskLogged) continue;
|
|
47208
|
+
if (!await claimAction(store, key, "task-log", record.id)) continue;
|
|
47209
|
+
await logTaskResult(definition, state, record, experiment);
|
|
47210
|
+
changed.push(record);
|
|
47211
|
+
}
|
|
47212
|
+
if (changed.length > 0) {
|
|
47213
|
+
await experiment?.flush();
|
|
47214
|
+
await writeCaseRecords(store, key, changed);
|
|
47215
|
+
}
|
|
47216
|
+
}
|
|
47217
|
+
async function runTaskStage(definition, state, store, key, experiment) {
|
|
47218
|
+
if (isBatchTask(definition.evaluator.task)) {
|
|
47219
|
+
await ensureBatches(definition, state, store, key, "task");
|
|
47220
|
+
return;
|
|
47221
|
+
}
|
|
47222
|
+
const task = definition.evaluator.task;
|
|
47223
|
+
const changed = [];
|
|
47224
|
+
for (const record of state.cases) {
|
|
47225
|
+
if (record.taskComplete) continue;
|
|
47226
|
+
if (!await claimAction(store, key, "task", record.id)) continue;
|
|
47227
|
+
await logTaskResult(definition, state, record, experiment, task);
|
|
47228
|
+
changed.push(record);
|
|
47229
|
+
}
|
|
47230
|
+
if (changed.length > 0) {
|
|
47231
|
+
await experiment?.flush();
|
|
47232
|
+
await writeCaseRecords(store, key, changed);
|
|
47233
|
+
}
|
|
47234
|
+
}
|
|
47235
|
+
async function runScoreStages(definition, state, store, key, experiment) {
|
|
47236
|
+
const scorers = resolveScorers(definition.evaluator.scores ?? []);
|
|
47237
|
+
const changed = /* @__PURE__ */ new Map();
|
|
47238
|
+
const persistChangedCases = async () => {
|
|
47239
|
+
if (changed.size === 0) return;
|
|
47240
|
+
await experiment?.flush();
|
|
47241
|
+
await writeCaseRecords(store, key, [...changed.values()]);
|
|
47242
|
+
changed.clear();
|
|
47243
|
+
};
|
|
47244
|
+
for (const { name, scorer } of scorers) {
|
|
47245
|
+
if (isBatchScorer(scorer)) {
|
|
47246
|
+
for (const record of state.cases) {
|
|
47247
|
+
if (Object.hasOwn(record.scores, name) && !Object.hasOwn(record.loggedScores, name)) {
|
|
47248
|
+
if (!await claimAction(store, key, "score-log", record.id, name)) {
|
|
47249
|
+
continue;
|
|
47250
|
+
}
|
|
47251
|
+
await evaluateAndLogScore(
|
|
47252
|
+
definition,
|
|
47253
|
+
state,
|
|
47254
|
+
record,
|
|
47255
|
+
name,
|
|
47256
|
+
experiment
|
|
47257
|
+
);
|
|
47258
|
+
changed.set(record.id, record);
|
|
47259
|
+
}
|
|
47260
|
+
}
|
|
47261
|
+
await persistChangedCases();
|
|
47262
|
+
await ensureBatches(definition, state, store, key, "score", name);
|
|
47263
|
+
continue;
|
|
47264
|
+
}
|
|
47265
|
+
for (const record of state.cases) {
|
|
47266
|
+
if (Object.hasOwn(record.loggedScores, name)) continue;
|
|
47267
|
+
if (!await claimAction(store, key, "score", record.id, name)) continue;
|
|
47268
|
+
await evaluateAndLogScore(
|
|
47269
|
+
definition,
|
|
47270
|
+
state,
|
|
47271
|
+
record,
|
|
47272
|
+
name,
|
|
47273
|
+
experiment,
|
|
47274
|
+
scorer
|
|
47275
|
+
);
|
|
47276
|
+
changed.set(record.id, record);
|
|
47277
|
+
}
|
|
47278
|
+
}
|
|
47279
|
+
for (const [index, classifier] of (definition.evaluator.classifiers ?? []).entries()) {
|
|
47280
|
+
const name = classifierName(classifier, index);
|
|
47281
|
+
for (const record of state.cases) {
|
|
47282
|
+
if (Object.hasOwn(record.loggedClassifications, name)) continue;
|
|
47283
|
+
if (!await claimAction(store, key, "classification", record.id, name)) {
|
|
47284
|
+
continue;
|
|
47285
|
+
}
|
|
47286
|
+
await evaluateAndLogClassification(
|
|
47287
|
+
definition,
|
|
47288
|
+
state,
|
|
47289
|
+
record,
|
|
47290
|
+
name,
|
|
47291
|
+
classifier,
|
|
47292
|
+
experiment
|
|
47293
|
+
);
|
|
47294
|
+
changed.set(record.id, record);
|
|
47295
|
+
}
|
|
47296
|
+
}
|
|
47297
|
+
await persistChangedCases();
|
|
47298
|
+
}
|
|
47299
|
+
function scorerArgs(record) {
|
|
47300
|
+
const datum = record.datum;
|
|
47301
|
+
return {
|
|
47302
|
+
...datum,
|
|
47303
|
+
metadata: record.metadata,
|
|
47304
|
+
output: record.output
|
|
47305
|
+
};
|
|
47306
|
+
}
|
|
47307
|
+
function resumeCaseRoot(definition, record, experiment) {
|
|
47308
|
+
if (!experiment) return NOOP_SPAN;
|
|
47309
|
+
if (!record.rootSpan) {
|
|
47310
|
+
throw new Error(`Durable eval case ${record.caseId} has no root span`);
|
|
47311
|
+
}
|
|
47312
|
+
return _internalResumeSpan({
|
|
47313
|
+
exported: record.rootSpan,
|
|
47314
|
+
state: definition.evaluator.state
|
|
47315
|
+
});
|
|
47316
|
+
}
|
|
47317
|
+
async function evaluateAndLogScore(definition, state, record, name, experiment, scorer) {
|
|
47318
|
+
const root = resumeCaseRoot(definition, record, experiment);
|
|
47319
|
+
try {
|
|
47320
|
+
const rootExport = await root.export();
|
|
47321
|
+
const prepared = await root.traced(
|
|
47322
|
+
async (span) => {
|
|
47323
|
+
const value = scorer ? await scorer(scorerArgs(record)) : record.scores[name];
|
|
47324
|
+
if (scorer) {
|
|
47325
|
+
record.scores[name] = assertJsonValue(value, `scorer ${name} output`);
|
|
47326
|
+
}
|
|
47327
|
+
const result = _internalPrepareEvaluatorScore(value, name);
|
|
47328
|
+
if (result.results !== null) {
|
|
47329
|
+
span.log({
|
|
47330
|
+
output: result.output,
|
|
47331
|
+
metadata: result.metadata,
|
|
47332
|
+
scores: result.scores
|
|
47333
|
+
});
|
|
47334
|
+
}
|
|
47335
|
+
return result;
|
|
47336
|
+
},
|
|
47337
|
+
{
|
|
47338
|
+
name,
|
|
47339
|
+
spanId: deterministicId(`${state.runId}:${record.id}:score:${name}`),
|
|
47340
|
+
spanAttributes: {
|
|
47341
|
+
type: "score" /* SCORE */,
|
|
47342
|
+
purpose: "scorer"
|
|
47343
|
+
},
|
|
47344
|
+
propagatedEvent: makeScorerPropagatedEvent(rootExport || void 0),
|
|
47345
|
+
event: { input: scorerArgs(record) }
|
|
47346
|
+
}
|
|
47347
|
+
);
|
|
47348
|
+
if (prepared.scores) root.log({ scores: prepared.scores });
|
|
47349
|
+
record.loggedScores[name] = true;
|
|
47350
|
+
} catch (error) {
|
|
47351
|
+
logError(root, error);
|
|
47352
|
+
throw error;
|
|
47353
|
+
} finally {
|
|
47354
|
+
root.end();
|
|
47355
|
+
}
|
|
47356
|
+
}
|
|
47357
|
+
async function evaluateAndLogClassification(definition, state, record, name, classifier, experiment) {
|
|
47358
|
+
const root = resumeCaseRoot(definition, record, experiment);
|
|
47359
|
+
try {
|
|
47360
|
+
const rootExport = await root.export();
|
|
47361
|
+
const prepared = await root.traced(
|
|
47362
|
+
async (span) => {
|
|
47363
|
+
const value = await classifier(scorerArgs(record));
|
|
47364
|
+
record.classifications[name] = assertJsonValue(
|
|
47365
|
+
value,
|
|
47366
|
+
`classifier ${name} output`
|
|
47367
|
+
);
|
|
47368
|
+
const result = _internalPrepareEvaluatorClassification(value, name);
|
|
47369
|
+
if (result.results !== null) {
|
|
47370
|
+
span.log({ output: result.output, metadata: result.metadata });
|
|
47371
|
+
}
|
|
47372
|
+
return result;
|
|
47373
|
+
},
|
|
47374
|
+
{
|
|
47375
|
+
name,
|
|
47376
|
+
spanId: deterministicId(
|
|
47377
|
+
`${state.runId}:${record.id}:classification:${name}`
|
|
47378
|
+
),
|
|
47379
|
+
spanAttributes: {
|
|
47380
|
+
type: "classifier" /* CLASSIFIER */,
|
|
47381
|
+
purpose: "scorer"
|
|
47382
|
+
},
|
|
47383
|
+
propagatedEvent: makeScorerPropagatedEvent(rootExport || void 0),
|
|
47384
|
+
event: { input: scorerArgs(record) }
|
|
47385
|
+
}
|
|
47386
|
+
);
|
|
47387
|
+
if (prepared.classifications) {
|
|
47388
|
+
root.log({ classifications: prepared.classifications });
|
|
47389
|
+
}
|
|
47390
|
+
record.loggedClassifications[name] = true;
|
|
47391
|
+
} catch (error) {
|
|
47392
|
+
logError(root, error);
|
|
47393
|
+
throw error;
|
|
47394
|
+
} finally {
|
|
47395
|
+
root.end();
|
|
47396
|
+
}
|
|
47397
|
+
}
|
|
47398
|
+
async function ensureBatches(definition, state, store, key, kind, scorerName2) {
|
|
47399
|
+
const processor = processorForStage(definition, kind, scorerName2);
|
|
47400
|
+
const plans = plannedBatches(
|
|
47401
|
+
definition,
|
|
47402
|
+
state.runId,
|
|
47403
|
+
state.cases.map(({ id }) => id)
|
|
47404
|
+
);
|
|
47405
|
+
const casesById = new Map(state.cases.map((record) => [record.id, record]));
|
|
47406
|
+
for (const plan of plans) {
|
|
47407
|
+
if (plan.kind !== kind || plan.scorerName !== scorerName2) continue;
|
|
47408
|
+
if (state.batches.some(({ id }) => id === plan.id)) continue;
|
|
47409
|
+
const records = plan.itemIds.map((id) => casesById.get(id));
|
|
47410
|
+
const ready = records.every(
|
|
47411
|
+
(record) => kind === "task" ? !record.taskComplete : !Object.hasOwn(record.scores, scorerName2)
|
|
47412
|
+
);
|
|
47413
|
+
if (!ready) continue;
|
|
47414
|
+
const batchId = plan.id;
|
|
47415
|
+
const claim = await store.getOrSet(
|
|
47416
|
+
claimRecordKey(key, "batch", batchId),
|
|
47417
|
+
encoder.encode(batchId)
|
|
47418
|
+
);
|
|
47419
|
+
if (!claim.created) continue;
|
|
47420
|
+
const context = { runId: state.runId, batchId };
|
|
47421
|
+
const items = records.map(
|
|
47422
|
+
(record) => kind === "task" ? taskBatchItem(record, state.parameters) : scorerBatchItem(record)
|
|
47423
|
+
);
|
|
47424
|
+
const submissionData = assertJsonValue(
|
|
47425
|
+
await processor.submit(items, context),
|
|
47426
|
+
`submission data for batch ${batchId}`
|
|
47427
|
+
);
|
|
47428
|
+
const externalId = processor.completion.mode === "webhook" ? processor.completion.getExternalId(submissionData, context) : void 0;
|
|
47429
|
+
if (externalId !== void 0 && !externalId.trim()) {
|
|
47430
|
+
throw new Error(`Batch ${batchId} produced an empty externalId`);
|
|
47431
|
+
}
|
|
47432
|
+
const batch = {
|
|
47433
|
+
id: batchId,
|
|
47434
|
+
kind,
|
|
47435
|
+
scorerName: scorerName2,
|
|
47436
|
+
itemIds: records.map((record) => record.id),
|
|
47437
|
+
submissionData,
|
|
47438
|
+
externalId,
|
|
47439
|
+
status: "submitted"
|
|
47440
|
+
};
|
|
47441
|
+
state.batches.push(batch);
|
|
47442
|
+
await writeBatchRecords(store, key, [batch]);
|
|
47443
|
+
}
|
|
47444
|
+
}
|
|
47445
|
+
async function collectBatch(definition, state, batch) {
|
|
47446
|
+
const processor = processorForStage(definition, batch.kind, batch.scorerName);
|
|
47447
|
+
const context = { runId: state.runId, batchId: batch.id };
|
|
47448
|
+
const results = await processor.collect(batch.submissionData, context);
|
|
47449
|
+
if (!Array.isArray(results)) {
|
|
47450
|
+
throw new Error(`collect for batch ${batch.id} must return an array`);
|
|
47451
|
+
}
|
|
47452
|
+
const expectedIds = new Set(batch.itemIds);
|
|
47453
|
+
const seen = /* @__PURE__ */ new Set();
|
|
47454
|
+
const records = [];
|
|
47455
|
+
for (const result of results) {
|
|
47456
|
+
const id = resultItemId(result);
|
|
47457
|
+
if (!expectedIds.has(id)) {
|
|
47458
|
+
throw new Error(`Batch ${batch.id} returned unknown item ${id}`);
|
|
47459
|
+
}
|
|
47460
|
+
if (seen.has(id)) {
|
|
47461
|
+
throw new Error(`Batch ${batch.id} returned item ${id} more than once`);
|
|
47462
|
+
}
|
|
47463
|
+
seen.add(id);
|
|
47464
|
+
const record = state.cases.find((candidate) => candidate.id === id);
|
|
47465
|
+
records.push(record);
|
|
47466
|
+
if (batch.kind === "task") {
|
|
47467
|
+
record.output = assertJsonValue(
|
|
47468
|
+
result.output,
|
|
47469
|
+
`task output for item ${id}`
|
|
47470
|
+
);
|
|
47471
|
+
if ("metadata" in result && result.metadata !== void 0) {
|
|
47472
|
+
record.metadata = assertJsonValue(
|
|
47473
|
+
{
|
|
47474
|
+
...record.metadata,
|
|
47475
|
+
...result.metadata
|
|
47476
|
+
},
|
|
47477
|
+
`metadata for ${id}`
|
|
47478
|
+
);
|
|
47479
|
+
}
|
|
47480
|
+
if ("tags" in result && result.tags !== void 0)
|
|
47481
|
+
record.tags = result.tags;
|
|
47482
|
+
record.taskComplete = true;
|
|
47483
|
+
} else {
|
|
47484
|
+
record.scores[batch.scorerName] = assertJsonValue(
|
|
47485
|
+
result.score,
|
|
47486
|
+
`score output for item ${id}`
|
|
47487
|
+
);
|
|
47488
|
+
}
|
|
47489
|
+
}
|
|
47490
|
+
const missing = batch.itemIds.filter((id) => !seen.has(id));
|
|
47491
|
+
if (missing.length > 0) {
|
|
47492
|
+
throw new Error(
|
|
47493
|
+
`Batch ${batch.id} did not return results for: ${missing.join(", ")}`
|
|
47494
|
+
);
|
|
47495
|
+
}
|
|
47496
|
+
return records;
|
|
47497
|
+
}
|
|
47498
|
+
function processorForStage(definition, kind, scorerName2) {
|
|
47499
|
+
if (kind === "task") {
|
|
47500
|
+
if (!isBatchTask(definition.evaluator.task)) {
|
|
47501
|
+
throw new Error("Definition no longer contains the batch task");
|
|
47502
|
+
}
|
|
47503
|
+
return definition.evaluator.task.processor;
|
|
47504
|
+
}
|
|
47505
|
+
const scorer = resolveScorers(definition.evaluator.scores ?? []).find(
|
|
47506
|
+
({ name }) => name === scorerName2
|
|
47507
|
+
)?.scorer;
|
|
47508
|
+
if (!isBatchScorer(scorer)) {
|
|
47509
|
+
throw new Error(`Definition no longer contains scorer ${scorerName2}`);
|
|
47510
|
+
}
|
|
47511
|
+
return scorer.processor;
|
|
47512
|
+
}
|
|
47513
|
+
async function materializeCases(definition, data, experiment) {
|
|
47514
|
+
const evaluator = definition.evaluator;
|
|
47515
|
+
const iterable = await _internalResolveEvaluatorData(
|
|
47516
|
+
{
|
|
47517
|
+
data,
|
|
47518
|
+
projectName: definition.projectName,
|
|
47519
|
+
projectId: evaluator.projectId,
|
|
47520
|
+
state: evaluator.state
|
|
47521
|
+
},
|
|
47522
|
+
experiment
|
|
47523
|
+
);
|
|
47524
|
+
const records = [];
|
|
47525
|
+
const seen = /* @__PURE__ */ new Set();
|
|
47526
|
+
for await (const datum of iterable) {
|
|
47527
|
+
const caseId = datum.id ?? datum.upsert_id ?? (evaluator.caseId ? await evaluator.caseId(datum) : void 0);
|
|
47528
|
+
if (!caseId) {
|
|
47529
|
+
throw new Error(
|
|
47530
|
+
"Every durable eval case requires id, upsert_id, or caseId"
|
|
47531
|
+
);
|
|
47532
|
+
}
|
|
47533
|
+
if (seen.has(caseId))
|
|
47534
|
+
throw new Error(`Duplicate durable eval case id: ${caseId}`);
|
|
47535
|
+
seen.add(caseId);
|
|
47536
|
+
const trialCount = datum.trialCount ?? evaluator.trialCount ?? 1;
|
|
47537
|
+
if (!Number.isInteger(trialCount) || trialCount < 1) {
|
|
47538
|
+
throw new Error(`Invalid trialCount for durable eval case ${caseId}`);
|
|
47539
|
+
}
|
|
47540
|
+
for (let trialIndex = 0; trialIndex < trialCount; trialIndex++) {
|
|
47541
|
+
records.push({
|
|
47542
|
+
id: `${caseId}:trial:${trialIndex}`,
|
|
47543
|
+
caseId,
|
|
47544
|
+
trialIndex,
|
|
47545
|
+
datum: assertJsonValue(datum, `case ${caseId}`),
|
|
47546
|
+
metadata: assertJsonValue(
|
|
47547
|
+
"metadata" in datum ? datum.metadata : {},
|
|
47548
|
+
`metadata for ${caseId}`
|
|
47549
|
+
),
|
|
47550
|
+
tags: datum.tags,
|
|
47551
|
+
taskComplete: false,
|
|
47552
|
+
taskLogged: false,
|
|
47553
|
+
scores: /* @__PURE__ */ Object.create(null),
|
|
47554
|
+
loggedScores: /* @__PURE__ */ Object.create(null),
|
|
47555
|
+
classifications: /* @__PURE__ */ Object.create(null),
|
|
47556
|
+
loggedClassifications: /* @__PURE__ */ Object.create(null)
|
|
47557
|
+
});
|
|
47558
|
+
}
|
|
47559
|
+
}
|
|
47560
|
+
return records;
|
|
47561
|
+
}
|
|
47562
|
+
function taskBatchItem(record, parameters) {
|
|
47563
|
+
const datum = record.datum;
|
|
47564
|
+
return {
|
|
47565
|
+
id: record.id,
|
|
47566
|
+
input: datum.input,
|
|
47567
|
+
expected: "expected" in datum ? datum.expected : void 0,
|
|
47568
|
+
metadata: record.metadata,
|
|
47569
|
+
tags: record.tags,
|
|
47570
|
+
parameters,
|
|
47571
|
+
trialIndex: record.trialIndex
|
|
47572
|
+
};
|
|
47573
|
+
}
|
|
47574
|
+
function scorerBatchItem(record) {
|
|
47575
|
+
const datum = record.datum;
|
|
47576
|
+
return {
|
|
47577
|
+
id: record.id,
|
|
47578
|
+
input: datum.input,
|
|
47579
|
+
output: record.output,
|
|
47580
|
+
expected: "expected" in datum ? datum.expected : void 0,
|
|
47581
|
+
metadata: record.metadata,
|
|
47582
|
+
tags: record.tags,
|
|
47583
|
+
trialIndex: record.trialIndex
|
|
47584
|
+
};
|
|
47585
|
+
}
|
|
47586
|
+
async function finishExperiment(definition, state, experiment) {
|
|
47587
|
+
const scorerNames = resolveScorers(definition.evaluator.scores ?? []).map(
|
|
47588
|
+
({ name }) => name
|
|
47589
|
+
);
|
|
47590
|
+
const results = state.cases.map((record) => {
|
|
47591
|
+
const datum = record.datum;
|
|
47592
|
+
const scores = Object.fromEntries(
|
|
47593
|
+
scorerNames.flatMap(
|
|
47594
|
+
(name) => Object.entries(
|
|
47595
|
+
_internalPrepareEvaluatorScore(
|
|
47596
|
+
record.scores[name],
|
|
47597
|
+
name
|
|
47598
|
+
).scores ?? {}
|
|
47599
|
+
)
|
|
47600
|
+
)
|
|
47601
|
+
);
|
|
47602
|
+
const classifications = Object.fromEntries(
|
|
47603
|
+
Object.entries(record.classifications).flatMap(
|
|
47604
|
+
([name, value]) => Object.entries(
|
|
47605
|
+
_internalPrepareEvaluatorClassification(value, name).classifications ?? {}
|
|
47606
|
+
)
|
|
47607
|
+
)
|
|
47608
|
+
);
|
|
47609
|
+
return {
|
|
47610
|
+
...datum,
|
|
47611
|
+
output: record.output,
|
|
47612
|
+
metadata: record.metadata,
|
|
47613
|
+
tags: record.tags,
|
|
47614
|
+
scores,
|
|
47615
|
+
error: void 0,
|
|
47616
|
+
...Object.keys(classifications).length > 0 ? { classifications } : {}
|
|
47617
|
+
};
|
|
47618
|
+
});
|
|
47619
|
+
if (!experiment) {
|
|
47620
|
+
return buildLocalSummary(
|
|
47621
|
+
{
|
|
47622
|
+
...definition.evaluator,
|
|
47623
|
+
projectName: definition.projectName,
|
|
47624
|
+
evalName: state.experimentName
|
|
47625
|
+
},
|
|
47626
|
+
results
|
|
47627
|
+
);
|
|
47628
|
+
}
|
|
47629
|
+
await experiment.flush();
|
|
47630
|
+
let comparisonExperimentId = definition.evaluator.baseExperimentId;
|
|
47631
|
+
if (!comparisonExperimentId) {
|
|
47632
|
+
try {
|
|
47633
|
+
comparisonExperimentId = await experiment._getBaseExperimentId();
|
|
47634
|
+
} catch {
|
|
47635
|
+
comparisonExperimentId = void 0;
|
|
47636
|
+
}
|
|
47637
|
+
}
|
|
47638
|
+
return await experiment.summarize({
|
|
47639
|
+
summarizeScores: definition.evaluator.summarizeScores,
|
|
47640
|
+
...comparisonExperimentId ? { comparisonExperimentId } : {}
|
|
47641
|
+
});
|
|
47642
|
+
}
|
|
47643
|
+
function resolveScorers(scorers) {
|
|
47644
|
+
return scorers.map((scorer, index) => ({
|
|
47645
|
+
name: isBatchScorer(scorer) ? scorer.name : scorer.name || `scorer_${index}`,
|
|
47646
|
+
scorer
|
|
47647
|
+
}));
|
|
47648
|
+
}
|
|
47649
|
+
function runKey(projectName, evalName, runId) {
|
|
47650
|
+
return `durable-eval/v1/runs/${contentVersion(encoder.encode(`${projectName}\0${evalName}\0${runId}`))}`;
|
|
47651
|
+
}
|
|
47652
|
+
function encodedKeyPart(value) {
|
|
47653
|
+
return uint8ArrayToBase64(encoder.encode(value)).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/, "");
|
|
47654
|
+
}
|
|
47655
|
+
function caseRecordKey(key, caseId, kind, ...names) {
|
|
47656
|
+
const suffix = names.map(encodedKeyPart).join("/");
|
|
47657
|
+
return `${key}/cases/${encodedKeyPart(caseId)}/${kind}${suffix ? `/${suffix}` : ""}`;
|
|
47658
|
+
}
|
|
47659
|
+
function batchRecordKey(key, batchId) {
|
|
47660
|
+
return `${key}/batches/${encodedKeyPart(batchId)}`;
|
|
47661
|
+
}
|
|
47662
|
+
function claimRecordKey(key, kind, ...parts) {
|
|
47663
|
+
const identity = stableStringify([kind, parts]);
|
|
47664
|
+
return `${key}/claims/${contentVersion(encoder.encode(identity))}`;
|
|
47665
|
+
}
|
|
47666
|
+
async function claimAction(store, key, kind, ...parts) {
|
|
47667
|
+
return (await store.getOrSet(
|
|
47668
|
+
claimRecordKey(key, kind, ...parts),
|
|
47669
|
+
encoder.encode("claimed")
|
|
47670
|
+
)).created;
|
|
47671
|
+
}
|
|
47672
|
+
function plannedBatches(definition, runId, caseIds) {
|
|
47673
|
+
const stages = [];
|
|
47674
|
+
if (isBatchTask(definition.evaluator.task)) stages.push({ kind: "task" });
|
|
47675
|
+
for (const { name, scorer } of resolveScorers(
|
|
47676
|
+
definition.evaluator.scores ?? []
|
|
47677
|
+
)) {
|
|
47678
|
+
if (isBatchScorer(scorer)) {
|
|
47679
|
+
stages.push({ kind: "score", scorerName: name });
|
|
47680
|
+
}
|
|
47681
|
+
}
|
|
47682
|
+
const plans = [];
|
|
47683
|
+
for (const { kind, scorerName: scorerName2 } of stages) {
|
|
47684
|
+
const batchSize = processorForStage(definition, kind, scorerName2).batchSize ?? DEFAULT_BATCH_SIZE;
|
|
47685
|
+
if (!Number.isInteger(batchSize) || batchSize < 1) {
|
|
47686
|
+
throw new Error(
|
|
47687
|
+
`Invalid batchSize for ${scorerName2 ?? "task"}: ${batchSize}`
|
|
47688
|
+
);
|
|
47689
|
+
}
|
|
47690
|
+
for (let offset = 0; offset < caseIds.length; offset += batchSize) {
|
|
47691
|
+
const itemIds = caseIds.slice(offset, offset + batchSize);
|
|
47692
|
+
plans.push({
|
|
47693
|
+
id: deterministicId(
|
|
47694
|
+
stableStringify([runId, kind, scorerName2, itemIds])
|
|
47695
|
+
),
|
|
47696
|
+
kind,
|
|
47697
|
+
scorerName: scorerName2,
|
|
47698
|
+
itemIds
|
|
47699
|
+
});
|
|
47700
|
+
}
|
|
47701
|
+
}
|
|
47702
|
+
return plans;
|
|
47703
|
+
}
|
|
47704
|
+
async function readCaseRecord(definition, store, key, id) {
|
|
47705
|
+
const scorers = resolveScorers(definition.evaluator.scores ?? []);
|
|
47706
|
+
const classifiers = (definition.evaluator.classifiers ?? []).map(
|
|
47707
|
+
classifierName
|
|
47708
|
+
);
|
|
47709
|
+
const [
|
|
47710
|
+
base,
|
|
47711
|
+
task,
|
|
47712
|
+
taskLog,
|
|
47713
|
+
scoreValues,
|
|
47714
|
+
scoreLogValues,
|
|
47715
|
+
classificationValues,
|
|
47716
|
+
classificationLogValues
|
|
47717
|
+
] = await Promise.all([
|
|
47718
|
+
readJson(store, caseRecordKey(key, id, "base")),
|
|
47719
|
+
readJson(store, caseRecordKey(key, id, "task")),
|
|
47720
|
+
readJson(store, caseRecordKey(key, id, "task-log")),
|
|
47721
|
+
Promise.all(
|
|
47722
|
+
scorers.map(async ({ name }) => ({
|
|
47723
|
+
name,
|
|
47724
|
+
value: await readJson(
|
|
47725
|
+
store,
|
|
47726
|
+
caseRecordKey(key, id, "score", name)
|
|
47727
|
+
)
|
|
47728
|
+
}))
|
|
47729
|
+
),
|
|
47730
|
+
Promise.all(
|
|
47731
|
+
scorers.map(async ({ name }) => ({
|
|
47732
|
+
name,
|
|
47733
|
+
value: await readJson(
|
|
47734
|
+
store,
|
|
47735
|
+
caseRecordKey(key, id, "score-log", name)
|
|
47736
|
+
)
|
|
47737
|
+
}))
|
|
47738
|
+
),
|
|
47739
|
+
Promise.all(
|
|
47740
|
+
classifiers.map(async (name) => ({
|
|
47741
|
+
name,
|
|
47742
|
+
value: await readJson(
|
|
47743
|
+
store,
|
|
47744
|
+
caseRecordKey(key, id, "classification", name)
|
|
47745
|
+
)
|
|
47746
|
+
}))
|
|
47747
|
+
),
|
|
47748
|
+
Promise.all(
|
|
47749
|
+
classifiers.map(async (name) => ({
|
|
47750
|
+
name,
|
|
47751
|
+
value: await readJson(
|
|
47752
|
+
store,
|
|
47753
|
+
caseRecordKey(key, id, "classification-log", name)
|
|
47754
|
+
)
|
|
47755
|
+
}))
|
|
47756
|
+
)
|
|
47757
|
+
]);
|
|
47758
|
+
if (!base) throw new Error(`Durable eval case ${id} is missing`);
|
|
47759
|
+
const scores = /* @__PURE__ */ Object.create(null);
|
|
47760
|
+
for (const { name, value } of scoreValues) {
|
|
47761
|
+
if (value !== void 0) scores[name] = value;
|
|
47762
|
+
}
|
|
47763
|
+
const loggedScores = /* @__PURE__ */ Object.create(null);
|
|
47764
|
+
for (const { name, value } of scoreLogValues) {
|
|
47765
|
+
if (value) loggedScores[name] = true;
|
|
47766
|
+
}
|
|
47767
|
+
const classifications = /* @__PURE__ */ Object.create(null);
|
|
47768
|
+
for (const { name, value } of classificationValues) {
|
|
47769
|
+
if (value !== void 0) classifications[name] = value;
|
|
47770
|
+
}
|
|
47771
|
+
const loggedClassifications = /* @__PURE__ */ Object.create(null);
|
|
47772
|
+
for (const { name, value } of classificationLogValues) {
|
|
47773
|
+
if (value) loggedClassifications[name] = true;
|
|
47774
|
+
}
|
|
47775
|
+
return {
|
|
47776
|
+
...base,
|
|
47777
|
+
metadata: task?.metadata ?? base.metadata,
|
|
47778
|
+
tags: task ? task.tags : base.tags,
|
|
47779
|
+
taskComplete: task !== void 0,
|
|
47780
|
+
taskLogged: taskLog !== void 0,
|
|
47781
|
+
output: task?.output,
|
|
47782
|
+
rootSpan: taskLog?.rootSpan,
|
|
47783
|
+
scores,
|
|
47784
|
+
loggedScores,
|
|
47785
|
+
classifications,
|
|
47786
|
+
loggedClassifications
|
|
47787
|
+
};
|
|
47788
|
+
}
|
|
47789
|
+
async function readRunState(definition, store, key) {
|
|
47790
|
+
const record = await readJson(store, key);
|
|
47791
|
+
if (!record) return void 0;
|
|
47792
|
+
const plans = plannedBatches(definition, record.runId, record.caseIds);
|
|
47793
|
+
const [cases, batchRecords] = await Promise.all([
|
|
47794
|
+
Promise.all(
|
|
47795
|
+
record.caseIds.map((id) => readCaseRecord(definition, store, key, id))
|
|
47796
|
+
),
|
|
47797
|
+
Promise.all(
|
|
47798
|
+
plans.map(async ({ id }) => {
|
|
47799
|
+
return readJson(store, batchRecordKey(key, id));
|
|
47800
|
+
})
|
|
47801
|
+
)
|
|
47802
|
+
]);
|
|
47803
|
+
const batches = batchRecords.filter(
|
|
47804
|
+
(value) => value !== void 0
|
|
47805
|
+
);
|
|
47806
|
+
const { caseIds: _caseIds, ...state } = record;
|
|
47807
|
+
return { ...state, cases, batches };
|
|
47808
|
+
}
|
|
47809
|
+
async function writeRunRecord(store, key, state) {
|
|
47810
|
+
const { cases, batches: _batches, ...record } = state;
|
|
47811
|
+
await writeJson(store, key, {
|
|
47812
|
+
...record,
|
|
47813
|
+
caseIds: cases.map(({ id }) => id)
|
|
47814
|
+
});
|
|
47815
|
+
}
|
|
47816
|
+
async function writeCaseBaseRecords(store, key, records) {
|
|
47817
|
+
await Promise.all(
|
|
47818
|
+
records.map(
|
|
47819
|
+
({ id, caseId, trialIndex, datum, metadata, tags }) => writeJson(store, caseRecordKey(key, id, "base"), {
|
|
47820
|
+
id,
|
|
47821
|
+
caseId,
|
|
47822
|
+
trialIndex,
|
|
47823
|
+
datum,
|
|
47824
|
+
metadata,
|
|
47825
|
+
tags
|
|
47826
|
+
})
|
|
47827
|
+
)
|
|
47828
|
+
);
|
|
47829
|
+
}
|
|
47830
|
+
async function writeCaseRecords(store, key, records) {
|
|
47831
|
+
const writes = [];
|
|
47832
|
+
for (const record of records) {
|
|
47833
|
+
if (record.taskComplete) {
|
|
47834
|
+
writes.push(
|
|
47835
|
+
writeJson(store, caseRecordKey(key, record.id, "task"), {
|
|
47836
|
+
output: record.output,
|
|
47837
|
+
metadata: record.metadata,
|
|
47838
|
+
tags: record.tags,
|
|
47839
|
+
taskComplete: true
|
|
47840
|
+
})
|
|
47841
|
+
);
|
|
47842
|
+
}
|
|
47843
|
+
if (record.taskLogged) {
|
|
47844
|
+
writes.push(
|
|
47845
|
+
writeJson(store, caseRecordKey(key, record.id, "task-log"), {
|
|
47846
|
+
rootSpan: record.rootSpan,
|
|
47847
|
+
taskLogged: true
|
|
47848
|
+
})
|
|
47849
|
+
);
|
|
47850
|
+
}
|
|
47851
|
+
for (const [name, value] of Object.entries(record.scores)) {
|
|
47852
|
+
writes.push(
|
|
47853
|
+
writeJson(store, caseRecordKey(key, record.id, "score", name), value)
|
|
47854
|
+
);
|
|
47855
|
+
}
|
|
47856
|
+
for (const name of Object.keys(record.loggedScores)) {
|
|
47857
|
+
writes.push(
|
|
47858
|
+
writeJson(
|
|
47859
|
+
store,
|
|
47860
|
+
caseRecordKey(key, record.id, "score-log", name),
|
|
47861
|
+
true
|
|
47862
|
+
)
|
|
47863
|
+
);
|
|
47864
|
+
}
|
|
47865
|
+
for (const [name, value] of Object.entries(record.classifications)) {
|
|
47866
|
+
writes.push(
|
|
47867
|
+
writeJson(
|
|
47868
|
+
store,
|
|
47869
|
+
caseRecordKey(key, record.id, "classification", name),
|
|
47870
|
+
value
|
|
47871
|
+
)
|
|
47872
|
+
);
|
|
47873
|
+
}
|
|
47874
|
+
for (const name of Object.keys(record.loggedClassifications)) {
|
|
47875
|
+
writes.push(
|
|
47876
|
+
writeJson(
|
|
47877
|
+
store,
|
|
47878
|
+
caseRecordKey(key, record.id, "classification-log", name),
|
|
47879
|
+
true
|
|
47880
|
+
)
|
|
47881
|
+
);
|
|
47882
|
+
}
|
|
47883
|
+
}
|
|
47884
|
+
await Promise.all(writes);
|
|
47885
|
+
}
|
|
47886
|
+
async function writeBatchRecords(store, key, records) {
|
|
47887
|
+
await Promise.all(
|
|
47888
|
+
records.map(
|
|
47889
|
+
(record) => writeJson(store, batchRecordKey(key, record.id), record)
|
|
47890
|
+
)
|
|
47891
|
+
);
|
|
47892
|
+
}
|
|
47893
|
+
function deterministicId(value) {
|
|
47894
|
+
const hex = contentVersion(encoder.encode(value)).padEnd(32, "0").slice(0, 32);
|
|
47895
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-5${hex.slice(13, 16)}-a${hex.slice(17, 20)}-${hex.slice(20, 32)}`;
|
|
47896
|
+
}
|
|
47897
|
+
function contentVersion(value) {
|
|
47898
|
+
if (isomorph_default.hash) return isomorph_default.hash(decoder.decode(value));
|
|
47899
|
+
let hash = 2166136261;
|
|
47900
|
+
for (const byte of value) {
|
|
47901
|
+
hash ^= byte;
|
|
47902
|
+
hash = Math.imul(hash, 16777619);
|
|
47903
|
+
}
|
|
47904
|
+
return (hash >>> 0).toString(16).padStart(8, "0");
|
|
47905
|
+
}
|
|
47906
|
+
async function readJson(store, key) {
|
|
47907
|
+
const value = await store.read(key);
|
|
47908
|
+
return value ? JSON.parse(decoder.decode(value)) : void 0;
|
|
47909
|
+
}
|
|
47910
|
+
async function writeJson(store, key, value) {
|
|
47911
|
+
await store.write(key, encoder.encode(stableStringify(value)));
|
|
47912
|
+
}
|
|
47913
|
+
function stableStringify(value) {
|
|
47914
|
+
return JSON.stringify(value, (_key, nested) => {
|
|
47915
|
+
if (nested && typeof nested === "object" && !Array.isArray(nested)) {
|
|
47916
|
+
return Object.fromEntries(
|
|
47917
|
+
Object.entries(nested).sort(
|
|
47918
|
+
([left], [right]) => left.localeCompare(right)
|
|
47919
|
+
)
|
|
47920
|
+
);
|
|
47921
|
+
}
|
|
47922
|
+
return nested;
|
|
47923
|
+
});
|
|
47924
|
+
}
|
|
47925
|
+
function assertJsonValue(value, label) {
|
|
47926
|
+
try {
|
|
47927
|
+
const serialized = JSON.stringify(value);
|
|
47928
|
+
if (serialized === void 0)
|
|
47929
|
+
throw new Error("value serializes to undefined");
|
|
47930
|
+
return JSON.parse(serialized);
|
|
47931
|
+
} catch (error) {
|
|
47932
|
+
throw new Error(`${label} must be JSON serializable`, { cause: error });
|
|
47933
|
+
}
|
|
47934
|
+
}
|
|
47935
|
+
function resultItemId(value) {
|
|
47936
|
+
if (typeof value !== "object" || value === null || !("id" in value) || typeof value.id !== "string") {
|
|
47937
|
+
throw new Error("Batch results must contain a string id");
|
|
47938
|
+
}
|
|
47939
|
+
return value.id;
|
|
47940
|
+
}
|
|
47941
|
+
function isBatchTask(value) {
|
|
47942
|
+
return typeof value === "object" && value !== null && "kind" in value && value.kind === BATCH_TASK_KIND;
|
|
47943
|
+
}
|
|
47944
|
+
function isBatchScorer(value) {
|
|
47945
|
+
return typeof value === "object" && value !== null && "kind" in value && value.kind === BATCH_SCORER_KIND;
|
|
47946
|
+
}
|
|
47947
|
+
function asError(error) {
|
|
47948
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
47949
|
+
}
|
|
47950
|
+
|
|
45934
47951
|
// src/agent-assertions.ts
|
|
45935
47952
|
function agentAssertionScorer(callback, options = {}) {
|
|
45936
47953
|
return async (args) => {
|