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/workerd.js
CHANGED
|
@@ -38,6 +38,8 @@ __export(workerd_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(workerd_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(workerd_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(workerd_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(workerd_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() {
|
|
@@ -13254,6 +13412,22 @@ function processInputAttachments(input) {
|
|
|
13254
13412
|
};
|
|
13255
13413
|
}
|
|
13256
13414
|
}
|
|
13415
|
+
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;
|
|
13416
|
+
const voyageBase64Value = voyageBase64Key ? node[voyageBase64Key] : void 0;
|
|
13417
|
+
if (voyageBase64Key && typeof voyageBase64Value === "string" && voyageBase64Value.startsWith("data:")) {
|
|
13418
|
+
const mediaType = inferMediaTypeFromDataUrl(
|
|
13419
|
+
voyageBase64Value,
|
|
13420
|
+
node.type === "video_base64" ? "video/mp4" : "image/png"
|
|
13421
|
+
);
|
|
13422
|
+
const filename = `${node.type === "video_base64" ? "video" : "image"}.${getExtensionFromMediaType(mediaType)}`;
|
|
13423
|
+
const attachment = toAttachment(voyageBase64Value, mediaType, filename);
|
|
13424
|
+
if (attachment) {
|
|
13425
|
+
return {
|
|
13426
|
+
...node,
|
|
13427
|
+
[voyageBase64Key]: attachment
|
|
13428
|
+
};
|
|
13429
|
+
}
|
|
13430
|
+
}
|
|
13257
13431
|
if (node.type === "file" && node.file && typeof node.file === "object" && typeof node.file.file_data === "string" && node.file.file_data.startsWith("data:")) {
|
|
13258
13432
|
const mediaType = inferMediaTypeFromDataUrl(
|
|
13259
13433
|
node.file.file_data,
|
|
@@ -14601,12 +14775,30 @@ function logInstrumentationError(context, error) {
|
|
|
14601
14775
|
|
|
14602
14776
|
// src/wrappers/anthropic-tokens-util.ts
|
|
14603
14777
|
function finalizeAnthropicTokens(metrics) {
|
|
14604
|
-
const
|
|
14605
|
-
|
|
14778
|
+
const hasSplitCacheCreationTokens = metrics.prompt_cache_creation_5m_tokens !== void 0 || metrics.prompt_cache_creation_1h_tokens !== void 0;
|
|
14779
|
+
const splitCacheCreationTokens = (metrics.prompt_cache_creation_5m_tokens || 0) + (metrics.prompt_cache_creation_1h_tokens || 0);
|
|
14780
|
+
const aggregateCacheCreationTokens = metrics.prompt_cache_creation_tokens || 0;
|
|
14781
|
+
const effectiveCacheCreationTokens = Math.max(
|
|
14782
|
+
aggregateCacheCreationTokens,
|
|
14783
|
+
splitCacheCreationTokens
|
|
14784
|
+
);
|
|
14785
|
+
const prompt_tokens = (metrics.prompt_tokens || 0) + (metrics.prompt_cached_tokens || 0) + effectiveCacheCreationTokens;
|
|
14786
|
+
const finalized = {
|
|
14606
14787
|
...metrics,
|
|
14607
14788
|
prompt_tokens,
|
|
14608
14789
|
tokens: prompt_tokens + (metrics.completion_tokens || 0)
|
|
14609
14790
|
};
|
|
14791
|
+
if (hasSplitCacheCreationTokens && splitCacheCreationTokens >= aggregateCacheCreationTokens) {
|
|
14792
|
+
delete finalized.prompt_cache_creation_tokens;
|
|
14793
|
+
}
|
|
14794
|
+
return finalized;
|
|
14795
|
+
}
|
|
14796
|
+
function toNumericMetrics(metrics) {
|
|
14797
|
+
return Object.fromEntries(
|
|
14798
|
+
Object.entries(metrics).filter(
|
|
14799
|
+
(entry) => entry[1] !== void 0
|
|
14800
|
+
)
|
|
14801
|
+
);
|
|
14610
14802
|
}
|
|
14611
14803
|
function extractAnthropicCacheTokens(cacheReadTokens = 0, cacheCreationTokens = 0) {
|
|
14612
14804
|
const cacheTokens = {};
|
|
@@ -15212,6 +15404,18 @@ function parseMetricsFromUsage2(usage) {
|
|
|
15212
15404
|
saveIfExistsTo("output_tokens", "completion_tokens");
|
|
15213
15405
|
saveIfExistsTo("cache_read_input_tokens", "prompt_cached_tokens");
|
|
15214
15406
|
saveIfExistsTo("cache_creation_input_tokens", "prompt_cache_creation_tokens");
|
|
15407
|
+
if (isObject(usage.cache_creation)) {
|
|
15408
|
+
const cacheCreation = usage.cache_creation;
|
|
15409
|
+
for (const [source, target] of [
|
|
15410
|
+
["ephemeral_5m_input_tokens", "prompt_cache_creation_5m_tokens"],
|
|
15411
|
+
["ephemeral_1h_input_tokens", "prompt_cache_creation_1h_tokens"]
|
|
15412
|
+
]) {
|
|
15413
|
+
const value = cacheCreation[source];
|
|
15414
|
+
if (typeof value === "number") {
|
|
15415
|
+
metrics[target] = value;
|
|
15416
|
+
}
|
|
15417
|
+
}
|
|
15418
|
+
}
|
|
15215
15419
|
if (isObject(usage.server_tool_use)) {
|
|
15216
15420
|
for (const [name, value] of Object.entries(usage.server_tool_use)) {
|
|
15217
15421
|
if (typeof value === "number") {
|
|
@@ -20510,37 +20714,97 @@ function seedTaskToolUseIdMapping(taskIdToToolUseId, message) {
|
|
|
20510
20714
|
taskIdToToolUseId.set(message.task_id, message.tool_use_id);
|
|
20511
20715
|
}
|
|
20512
20716
|
}
|
|
20513
|
-
function
|
|
20514
|
-
|
|
20515
|
-
|
|
20516
|
-
|
|
20517
|
-
usage = message.message?.usage;
|
|
20518
|
-
} else if (message.type === "result") {
|
|
20519
|
-
usage = message.usage;
|
|
20520
|
-
}
|
|
20717
|
+
function tokenCount(value) {
|
|
20718
|
+
return typeof value === "number" && Number.isFinite(value) && Number.isInteger(value) && value >= 0 ? value : void 0;
|
|
20719
|
+
}
|
|
20720
|
+
function copyUsage(usage) {
|
|
20521
20721
|
if (!usage || typeof usage !== "object") {
|
|
20522
|
-
return
|
|
20722
|
+
return void 0;
|
|
20723
|
+
}
|
|
20724
|
+
const copy = {};
|
|
20725
|
+
for (const key of [
|
|
20726
|
+
"input_tokens",
|
|
20727
|
+
"output_tokens",
|
|
20728
|
+
"cache_read_input_tokens",
|
|
20729
|
+
"cache_creation_input_tokens"
|
|
20730
|
+
]) {
|
|
20731
|
+
const value = tokenCount(Reflect.get(usage, key));
|
|
20732
|
+
if (value !== void 0) {
|
|
20733
|
+
copy[key] = value;
|
|
20734
|
+
}
|
|
20735
|
+
}
|
|
20736
|
+
const cacheCreation = Reflect.get(usage, "cache_creation");
|
|
20737
|
+
if (cacheCreation && typeof cacheCreation === "object") {
|
|
20738
|
+
const cacheCreationCopy = {};
|
|
20739
|
+
for (const key of [
|
|
20740
|
+
"ephemeral_5m_input_tokens",
|
|
20741
|
+
"ephemeral_1h_input_tokens"
|
|
20742
|
+
]) {
|
|
20743
|
+
const value = tokenCount(Reflect.get(cacheCreation, key));
|
|
20744
|
+
if (value !== void 0) {
|
|
20745
|
+
cacheCreationCopy[key] = value;
|
|
20746
|
+
}
|
|
20747
|
+
}
|
|
20748
|
+
if (Object.keys(cacheCreationCopy).length > 0) {
|
|
20749
|
+
copy.cache_creation = cacheCreationCopy;
|
|
20750
|
+
}
|
|
20751
|
+
}
|
|
20752
|
+
return Object.keys(copy).length > 0 ? copy : void 0;
|
|
20753
|
+
}
|
|
20754
|
+
function mergeUsage(base, override) {
|
|
20755
|
+
if (!base || !override) {
|
|
20756
|
+
return override ?? base;
|
|
20757
|
+
}
|
|
20758
|
+
const cacheCreation = base.cache_creation || override.cache_creation ? { ...base.cache_creation, ...override.cache_creation } : void 0;
|
|
20759
|
+
return {
|
|
20760
|
+
...base,
|
|
20761
|
+
...override,
|
|
20762
|
+
...cacheCreation && { cache_creation: cacheCreation }
|
|
20763
|
+
};
|
|
20764
|
+
}
|
|
20765
|
+
function extractUsage(usage, includeOutput) {
|
|
20766
|
+
const metrics = {};
|
|
20767
|
+
if (!usage) {
|
|
20768
|
+
return {};
|
|
20523
20769
|
}
|
|
20524
20770
|
const inputTokens = getNumberProperty(usage, "input_tokens");
|
|
20525
20771
|
if (inputTokens !== void 0) {
|
|
20526
20772
|
metrics.prompt_tokens = inputTokens;
|
|
20527
20773
|
}
|
|
20528
|
-
|
|
20529
|
-
|
|
20530
|
-
|
|
20774
|
+
if (includeOutput) {
|
|
20775
|
+
const outputTokens = getNumberProperty(usage, "output_tokens");
|
|
20776
|
+
if (outputTokens !== void 0) {
|
|
20777
|
+
metrics.completion_tokens = outputTokens;
|
|
20778
|
+
}
|
|
20531
20779
|
}
|
|
20532
20780
|
const cacheReadTokens = getNumberProperty(usage, "cache_read_input_tokens") || 0;
|
|
20533
20781
|
const cacheCreationTokens = getNumberProperty(usage, "cache_creation_input_tokens") || 0;
|
|
20534
|
-
|
|
20535
|
-
|
|
20536
|
-
|
|
20537
|
-
|
|
20538
|
-
|
|
20782
|
+
Object.assign(
|
|
20783
|
+
metrics,
|
|
20784
|
+
extractAnthropicCacheTokens(cacheReadTokens, cacheCreationTokens)
|
|
20785
|
+
);
|
|
20786
|
+
const cacheCreation5mTokens = getNumberProperty(
|
|
20787
|
+
usage.cache_creation,
|
|
20788
|
+
"ephemeral_5m_input_tokens"
|
|
20789
|
+
);
|
|
20790
|
+
const cacheCreation1hTokens = getNumberProperty(
|
|
20791
|
+
usage.cache_creation,
|
|
20792
|
+
"ephemeral_1h_input_tokens"
|
|
20793
|
+
);
|
|
20794
|
+
if (cacheCreation5mTokens !== void 0) {
|
|
20795
|
+
metrics.prompt_cache_creation_5m_tokens = cacheCreation5mTokens;
|
|
20539
20796
|
}
|
|
20540
|
-
if (
|
|
20541
|
-
|
|
20797
|
+
if (cacheCreation1hTokens !== void 0) {
|
|
20798
|
+
metrics.prompt_cache_creation_1h_tokens = cacheCreation1hTokens;
|
|
20542
20799
|
}
|
|
20543
|
-
|
|
20800
|
+
if (Object.keys(metrics).length === 0) {
|
|
20801
|
+
return {};
|
|
20802
|
+
}
|
|
20803
|
+
const finalized = finalizeAnthropicTokens(metrics);
|
|
20804
|
+
if (metrics.completion_tokens === void 0) {
|
|
20805
|
+
delete finalized.tokens;
|
|
20806
|
+
}
|
|
20807
|
+
return toNumericMetrics(finalized);
|
|
20544
20808
|
}
|
|
20545
20809
|
function buildLLMInput(promptMessages, conversationHistory) {
|
|
20546
20810
|
const inputParts = [...promptMessages, ...conversationHistory];
|
|
@@ -20574,16 +20838,16 @@ function buildRootPromptMessages(prompt, capturedPromptMessages) {
|
|
|
20574
20838
|
function formatCapturedMessages(messages) {
|
|
20575
20839
|
return messages.length > 0 ? messages : [];
|
|
20576
20840
|
}
|
|
20577
|
-
async function createLLMSpanForMessages(messages, promptMessages, conversationHistory, options, startTime, parentSpan, existingSpan) {
|
|
20841
|
+
async function createLLMSpanForMessages(messages, promptMessages, conversationHistory, options, startTime, parentSpan, usage, hasFinalOutputUsage, existingSpan) {
|
|
20578
20842
|
if (messages.length === 0) {
|
|
20579
20843
|
return void 0;
|
|
20580
20844
|
}
|
|
20581
20845
|
const lastMessage = messages[messages.length - 1];
|
|
20582
|
-
if (lastMessage.type !== "assistant"
|
|
20846
|
+
if (lastMessage.type !== "assistant") {
|
|
20583
20847
|
return void 0;
|
|
20584
20848
|
}
|
|
20585
|
-
const model = lastMessage.message
|
|
20586
|
-
const
|
|
20849
|
+
const model = lastMessage.message?.model || options.model;
|
|
20850
|
+
const metrics = options.includePartialMessages ? extractUsage(usage, hasFinalOutputUsage) : {};
|
|
20587
20851
|
const input = buildLLMInput(promptMessages, conversationHistory);
|
|
20588
20852
|
const outputs = messages.map(
|
|
20589
20853
|
(m) => m.message?.content && m.message?.role ? { content: m.message.content, role: m.message.role } : void 0
|
|
@@ -20605,8 +20869,8 @@ async function createLLMSpanForMessages(messages, promptMessages, conversationHi
|
|
|
20605
20869
|
);
|
|
20606
20870
|
span.log({
|
|
20607
20871
|
input,
|
|
20608
|
-
metadata: model
|
|
20609
|
-
metrics:
|
|
20872
|
+
metadata: { ...model && { model }, provider: "anthropic" },
|
|
20873
|
+
...Object.keys(metrics).length > 0 ? { metrics } : {},
|
|
20610
20874
|
output: outputs
|
|
20611
20875
|
});
|
|
20612
20876
|
const spanExport = await span.export();
|
|
@@ -20696,11 +20960,17 @@ function prepareLocalToolHandlersInMcpServers(mcpServers) {
|
|
|
20696
20960
|
}
|
|
20697
20961
|
return { hasLocalToolHandlers, localToolHookNames };
|
|
20698
20962
|
}
|
|
20699
|
-
function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers, localToolHookNames, skipLocalToolHooks, subAgentDetailsByToolUseId, subAgentSpans, endedSubAgentSpans) {
|
|
20963
|
+
function createToolTracingHooks(resolveParentSpan, taskIdToToolUseId, toolUseToParent, activeToolSpans, mcpServers, localToolHookNames, skipLocalToolHooks, subAgentDetailsByToolUseId, subAgentSpans, endedSubAgentSpans) {
|
|
20700
20964
|
const preToolUse = async (input, toolUseID) => {
|
|
20701
20965
|
if (input.hook_event_name !== "PreToolUse" || !toolUseID) {
|
|
20702
20966
|
return {};
|
|
20703
20967
|
}
|
|
20968
|
+
if (!toolUseToParent.has(toolUseID) && input.agent_id) {
|
|
20969
|
+
const parentToolUseId = taskIdToToolUseId.get(input.agent_id);
|
|
20970
|
+
if (parentToolUseId) {
|
|
20971
|
+
toolUseToParent.set(toolUseID, parentToolUseId);
|
|
20972
|
+
}
|
|
20973
|
+
}
|
|
20704
20974
|
if (skipLocalToolHooks && (isLocalToolUse(input.tool_name, mcpServers) || localToolHookNames.has(input.tool_name))) {
|
|
20705
20975
|
return {};
|
|
20706
20976
|
}
|
|
@@ -20896,9 +21166,6 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
|
|
|
20896
21166
|
}
|
|
20897
21167
|
const metadata = {
|
|
20898
21168
|
...subAgentDetailsToMetadata(details),
|
|
20899
|
-
...input.agent_transcript_path && {
|
|
20900
|
-
"claude_agent_sdk.agent_transcript_path": input.agent_transcript_path
|
|
20901
|
-
},
|
|
20902
21169
|
"claude_agent_sdk.stop_hook_active": input.stop_hook_active
|
|
20903
21170
|
};
|
|
20904
21171
|
try {
|
|
@@ -20920,7 +21187,7 @@ function createToolTracingHooks(resolveParentSpan, activeToolSpans, mcpServers,
|
|
|
20920
21187
|
subagentStop
|
|
20921
21188
|
};
|
|
20922
21189
|
}
|
|
20923
|
-
function injectTracingHooks(options, resolveParentSpan, activeToolSpans, localToolHookNames, skipLocalToolHooks, subAgentDetailsByToolUseId, subAgentSpans, endedSubAgentSpans) {
|
|
21190
|
+
function injectTracingHooks(options, resolveParentSpan, taskIdToToolUseId, toolUseToParent, activeToolSpans, localToolHookNames, skipLocalToolHooks, subAgentDetailsByToolUseId, subAgentSpans, endedSubAgentSpans) {
|
|
20924
21191
|
const {
|
|
20925
21192
|
preToolUse,
|
|
20926
21193
|
postToolUse,
|
|
@@ -20929,6 +21196,8 @@ function injectTracingHooks(options, resolveParentSpan, activeToolSpans, localTo
|
|
|
20929
21196
|
subagentStop
|
|
20930
21197
|
} = createToolTracingHooks(
|
|
20931
21198
|
resolveParentSpan,
|
|
21199
|
+
taskIdToToolUseId,
|
|
21200
|
+
toolUseToParent,
|
|
20932
21201
|
activeToolSpans,
|
|
20933
21202
|
options.mcpServers,
|
|
20934
21203
|
localToolHookNames,
|
|
@@ -21010,6 +21279,13 @@ async function finalizeCurrentMessageGroup(state) {
|
|
|
21010
21279
|
}
|
|
21011
21280
|
}
|
|
21012
21281
|
const existingLlmSpan = state.activeLlmSpansByParentToolUse.get(parentKey);
|
|
21282
|
+
const lastMessage = state.currentMessages[state.currentMessages.length - 1];
|
|
21283
|
+
const messageId = lastMessage?.message?.id;
|
|
21284
|
+
const usage = state.options.includePartialMessages ? mergeUsage(
|
|
21285
|
+
copyUsage(lastMessage?.message?.usage),
|
|
21286
|
+
messageId ? state.usageByMessageId.get(messageId) : void 0
|
|
21287
|
+
) : void 0;
|
|
21288
|
+
const hasFinalOutputUsage = messageId !== void 0 && state.finalOutputUsageMessageIds.has(messageId);
|
|
21013
21289
|
const llmSpanResult = await createLLMSpanForMessages(
|
|
21014
21290
|
state.currentMessages,
|
|
21015
21291
|
promptMessages,
|
|
@@ -21017,6 +21293,8 @@ async function finalizeCurrentMessageGroup(state) {
|
|
|
21017
21293
|
state.options,
|
|
21018
21294
|
state.currentMessageStartTime,
|
|
21019
21295
|
parentSpan,
|
|
21296
|
+
usage,
|
|
21297
|
+
hasFinalOutputUsage,
|
|
21020
21298
|
existingLlmSpan
|
|
21021
21299
|
);
|
|
21022
21300
|
if (llmSpanResult) {
|
|
@@ -21034,9 +21312,17 @@ async function finalizeCurrentMessageGroup(state) {
|
|
|
21034
21312
|
}
|
|
21035
21313
|
}
|
|
21036
21314
|
state.activeLlmSpansByParentToolUse.delete(parentKey);
|
|
21037
|
-
|
|
21038
|
-
|
|
21039
|
-
state.
|
|
21315
|
+
if (messageId) {
|
|
21316
|
+
state.usageByMessageId.delete(messageId);
|
|
21317
|
+
state.finalOutputUsageMessageIds.delete(messageId);
|
|
21318
|
+
for (const [
|
|
21319
|
+
parent,
|
|
21320
|
+
activeMessageId
|
|
21321
|
+
] of state.activePartialMessageIdByParentKey) {
|
|
21322
|
+
if (activeMessageId === messageId) {
|
|
21323
|
+
state.activePartialMessageIdByParentKey.delete(parent);
|
|
21324
|
+
}
|
|
21325
|
+
}
|
|
21040
21326
|
}
|
|
21041
21327
|
state.currentMessages.length = 0;
|
|
21042
21328
|
}
|
|
@@ -21127,6 +21413,10 @@ async function ensureActiveLlmSpanForParentToolUse(rootSpan, activeLlmSpansByPar
|
|
|
21127
21413
|
);
|
|
21128
21414
|
llmParentSpan = await subAgentSpan.export();
|
|
21129
21415
|
}
|
|
21416
|
+
const racedLlmSpan = activeLlmSpansByParentToolUse.get(parentKey);
|
|
21417
|
+
if (racedLlmSpan) {
|
|
21418
|
+
return racedLlmSpan;
|
|
21419
|
+
}
|
|
21130
21420
|
const llmSpan = startSpan(
|
|
21131
21421
|
withSpanInstrumentationName(
|
|
21132
21422
|
{
|
|
@@ -21246,7 +21536,49 @@ async function maybeHandleTaskLifecycleMessage(state, message) {
|
|
|
21246
21536
|
}
|
|
21247
21537
|
return true;
|
|
21248
21538
|
}
|
|
21539
|
+
function handlePartialUsageMessage(state, message) {
|
|
21540
|
+
if (message.type !== "stream_event") {
|
|
21541
|
+
return false;
|
|
21542
|
+
}
|
|
21543
|
+
const event = message.event;
|
|
21544
|
+
if (!event || typeof event !== "object") {
|
|
21545
|
+
return true;
|
|
21546
|
+
}
|
|
21547
|
+
const parentKey = llmParentKey(message.parent_tool_use_id ?? null);
|
|
21548
|
+
if (event.type === "message_start") {
|
|
21549
|
+
const messageId2 = event.message?.id;
|
|
21550
|
+
const usage = copyUsage(event.message?.usage);
|
|
21551
|
+
if (messageId2) {
|
|
21552
|
+
state.activePartialMessageIdByParentKey.set(parentKey, messageId2);
|
|
21553
|
+
if (usage) {
|
|
21554
|
+
state.usageByMessageId.set(messageId2, usage);
|
|
21555
|
+
}
|
|
21556
|
+
}
|
|
21557
|
+
return true;
|
|
21558
|
+
}
|
|
21559
|
+
const messageId = state.activePartialMessageIdByParentKey.get(parentKey);
|
|
21560
|
+
if (!messageId) {
|
|
21561
|
+
return true;
|
|
21562
|
+
}
|
|
21563
|
+
if (event.type === "message_delta") {
|
|
21564
|
+
const update = copyUsage(event.usage);
|
|
21565
|
+
if (update) {
|
|
21566
|
+
const usage = state.usageByMessageId.get(messageId) ?? {};
|
|
21567
|
+
Object.assign(usage, update);
|
|
21568
|
+
state.usageByMessageId.set(messageId, usage);
|
|
21569
|
+
if (update.output_tokens !== void 0) {
|
|
21570
|
+
state.finalOutputUsageMessageIds.add(messageId);
|
|
21571
|
+
}
|
|
21572
|
+
}
|
|
21573
|
+
} else if (event.type === "message_stop") {
|
|
21574
|
+
state.activePartialMessageIdByParentKey.delete(parentKey);
|
|
21575
|
+
}
|
|
21576
|
+
return true;
|
|
21577
|
+
}
|
|
21249
21578
|
async function handleStreamMessage(state, message) {
|
|
21579
|
+
if (handlePartialUsageMessage(state, message)) {
|
|
21580
|
+
return;
|
|
21581
|
+
}
|
|
21250
21582
|
maybeTrackToolUseContext(state, message);
|
|
21251
21583
|
if (await maybeHandleTaskLifecycleMessage(state, message)) {
|
|
21252
21584
|
return;
|
|
@@ -21293,36 +21625,9 @@ async function handleStreamMessage(state, message) {
|
|
|
21293
21625
|
);
|
|
21294
21626
|
state.currentMessages.push(message);
|
|
21295
21627
|
}
|
|
21296
|
-
if (message.type !== "result"
|
|
21628
|
+
if (message.type !== "result") {
|
|
21297
21629
|
return;
|
|
21298
21630
|
}
|
|
21299
|
-
const finalUsageMetrics = extractUsageFromMessage(message);
|
|
21300
|
-
if (state.currentMessages.length > 0 && finalUsageMetrics.completion_tokens !== void 0) {
|
|
21301
|
-
const lastMessage = state.currentMessages[state.currentMessages.length - 1];
|
|
21302
|
-
if (lastMessage?.message?.usage) {
|
|
21303
|
-
const adjustedTokens = finalUsageMetrics.completion_tokens - state.accumulatedOutputTokens;
|
|
21304
|
-
if (adjustedTokens >= 0) {
|
|
21305
|
-
lastMessage.message.usage.output_tokens = adjustedTokens;
|
|
21306
|
-
}
|
|
21307
|
-
const resultUsage = message.usage;
|
|
21308
|
-
if (resultUsage && typeof resultUsage === "object") {
|
|
21309
|
-
const cacheReadTokens = getNumberProperty(
|
|
21310
|
-
resultUsage,
|
|
21311
|
-
"cache_read_input_tokens"
|
|
21312
|
-
);
|
|
21313
|
-
if (cacheReadTokens !== void 0) {
|
|
21314
|
-
lastMessage.message.usage.cache_read_input_tokens = cacheReadTokens;
|
|
21315
|
-
}
|
|
21316
|
-
const cacheCreationTokens = getNumberProperty(
|
|
21317
|
-
resultUsage,
|
|
21318
|
-
"cache_creation_input_tokens"
|
|
21319
|
-
);
|
|
21320
|
-
if (cacheCreationTokens !== void 0) {
|
|
21321
|
-
lastMessage.message.usage.cache_creation_input_tokens = cacheCreationTokens;
|
|
21322
|
-
}
|
|
21323
|
-
}
|
|
21324
|
-
}
|
|
21325
|
-
}
|
|
21326
21631
|
const metadata = {};
|
|
21327
21632
|
if (message.num_turns !== void 0) {
|
|
21328
21633
|
metadata.num_turns = message.num_turns;
|
|
@@ -21330,8 +21635,12 @@ async function handleStreamMessage(state, message) {
|
|
|
21330
21635
|
if (message.session_id !== void 0) {
|
|
21331
21636
|
metadata.session_id = message.session_id;
|
|
21332
21637
|
}
|
|
21333
|
-
|
|
21334
|
-
|
|
21638
|
+
const metrics = state.options.includePartialMessages ? {} : extractUsage(copyUsage(message.usage), true);
|
|
21639
|
+
if (Object.keys(metadata).length > 0 || Object.keys(metrics).length > 0) {
|
|
21640
|
+
state.span.log({
|
|
21641
|
+
...Object.keys(metadata).length > 0 ? { metadata } : {},
|
|
21642
|
+
...Object.keys(metrics).length > 0 ? { metrics } : {}
|
|
21643
|
+
});
|
|
21335
21644
|
}
|
|
21336
21645
|
}
|
|
21337
21646
|
async function finalizeQuerySpan(state) {
|
|
@@ -21355,6 +21664,9 @@ async function finalizeQuerySpan(state) {
|
|
|
21355
21664
|
llmSpan.end();
|
|
21356
21665
|
}
|
|
21357
21666
|
state.activeLlmSpansByParentToolUse.clear();
|
|
21667
|
+
state.activePartialMessageIdByParentKey.clear();
|
|
21668
|
+
state.finalOutputUsageMessageIds.clear();
|
|
21669
|
+
state.usageByMessageId.clear();
|
|
21358
21670
|
for (const toolSpan of state.activeToolSpans.values()) {
|
|
21359
21671
|
toolSpan.end();
|
|
21360
21672
|
}
|
|
@@ -21479,6 +21791,8 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
21479
21791
|
const optionsWithHooks = injectTracingHooks(
|
|
21480
21792
|
options,
|
|
21481
21793
|
resolveToolUseParentSpan,
|
|
21794
|
+
taskIdToToolUseId,
|
|
21795
|
+
toolUseToParent,
|
|
21482
21796
|
activeToolSpans,
|
|
21483
21797
|
localToolHookNames,
|
|
21484
21798
|
skipLocalToolHooks,
|
|
@@ -21489,8 +21803,8 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
21489
21803
|
params.options = optionsWithHooks;
|
|
21490
21804
|
event.arguments[0] = params;
|
|
21491
21805
|
spans.set(event, {
|
|
21492
|
-
accumulatedOutputTokens: 0,
|
|
21493
21806
|
activeLlmSpansByParentToolUse,
|
|
21807
|
+
activePartialMessageIdByParentKey: /* @__PURE__ */ new Map(),
|
|
21494
21808
|
activeToolSpans,
|
|
21495
21809
|
conversationHistoryByParentKey,
|
|
21496
21810
|
capturedPromptMessages,
|
|
@@ -21498,6 +21812,7 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
21498
21812
|
currentMessageStartTime: startTime,
|
|
21499
21813
|
currentMessages: [],
|
|
21500
21814
|
endedSubAgentSpans,
|
|
21815
|
+
finalOutputUsageMessageIds: /* @__PURE__ */ new Set(),
|
|
21501
21816
|
finalResults: [],
|
|
21502
21817
|
options: optionsWithHooks,
|
|
21503
21818
|
originalPrompt,
|
|
@@ -21513,6 +21828,7 @@ var ClaudeAgentSDKPlugin = class extends BasePlugin {
|
|
|
21513
21828
|
latestLlmParentBySubAgentToolUse,
|
|
21514
21829
|
latestRootLlmParentRef,
|
|
21515
21830
|
toolUseToParent,
|
|
21831
|
+
usageByMessageId: /* @__PURE__ */ new Map(),
|
|
21516
21832
|
localToolContext
|
|
21517
21833
|
});
|
|
21518
21834
|
},
|
|
@@ -23987,9 +24303,9 @@ function extractEmbedPromptTokenCount(response) {
|
|
|
23987
24303
|
let sawAny = false;
|
|
23988
24304
|
for (const embedding of embeddings) {
|
|
23989
24305
|
const embeddingStats = tryToDict(tryToDict(embedding)?.statistics);
|
|
23990
|
-
const
|
|
23991
|
-
if (typeof
|
|
23992
|
-
total +=
|
|
24306
|
+
const tokenCount2 = embeddingStats?.tokenCount;
|
|
24307
|
+
if (typeof tokenCount2 === "number" && Number.isFinite(tokenCount2)) {
|
|
24308
|
+
total += tokenCount2;
|
|
23993
24309
|
sawAny = true;
|
|
23994
24310
|
}
|
|
23995
24311
|
}
|
|
@@ -30884,7 +31200,7 @@ function getStringProperty2(obj, key) {
|
|
|
30884
31200
|
return typeof value === "string" ? value : void 0;
|
|
30885
31201
|
}
|
|
30886
31202
|
function extractMetricsFromUsage(usage) {
|
|
30887
|
-
const
|
|
31203
|
+
const rawMetrics = {
|
|
30888
31204
|
prompt_tokens: usage.inputTokens,
|
|
30889
31205
|
completion_tokens: usage.outputTokens,
|
|
30890
31206
|
...extractAnthropicCacheTokens(
|
|
@@ -30893,10 +31209,10 @@ function extractMetricsFromUsage(usage) {
|
|
|
30893
31209
|
)
|
|
30894
31210
|
};
|
|
30895
31211
|
if (usage.reasoningTokens !== void 0) {
|
|
30896
|
-
|
|
30897
|
-
|
|
31212
|
+
rawMetrics.completion_reasoning_tokens = usage.reasoningTokens;
|
|
31213
|
+
rawMetrics.reasoning_tokens = usage.reasoningTokens;
|
|
30898
31214
|
}
|
|
30899
|
-
|
|
31215
|
+
const metrics = finalizeAnthropicTokens(rawMetrics);
|
|
30900
31216
|
const metadata = {
|
|
30901
31217
|
model: usage.model
|
|
30902
31218
|
};
|
|
@@ -31835,17 +32151,20 @@ var FlueObserveBridge = class {
|
|
|
31835
32151
|
return;
|
|
31836
32152
|
}
|
|
31837
32153
|
const metadata = {
|
|
32154
|
+
...event.runId ? this.runsById.get(event.runId)?.metadata : {},
|
|
31838
32155
|
...extractEventMetadata(event),
|
|
31839
32156
|
"flue.operation": event.operationKind,
|
|
31840
32157
|
provider: "flue"
|
|
31841
32158
|
};
|
|
31842
32159
|
const parent = this.parentSpanForEvent(event);
|
|
31843
|
-
const
|
|
32160
|
+
const args = {
|
|
31844
32161
|
name: `flue.${event.operationKind}`,
|
|
31845
32162
|
spanAttributes: { type: "task" /* TASK */ },
|
|
31846
32163
|
startTime: eventTime(event.timestamp),
|
|
31847
32164
|
event: { metadata }
|
|
31848
|
-
}
|
|
32165
|
+
};
|
|
32166
|
+
const runSpan = event.runId ? this.runsById.get(event.runId)?.span : void 0;
|
|
32167
|
+
const span = event.operationKind === "prompt" && (!parent || parent === runSpan) ? startFlueRootSpan(args) : startFlueSpan(parent, args);
|
|
31849
32168
|
this.operationsById.set(event.operationId, { metadata, span });
|
|
31850
32169
|
}
|
|
31851
32170
|
handleOperation(event) {
|
|
@@ -31860,6 +32179,11 @@ var FlueObserveBridge = class {
|
|
|
31860
32179
|
...event.isError !== void 0 ? { "flue.is_error": event.isError } : {},
|
|
31861
32180
|
...event.usage ? { "flue.usage": event.usage } : {}
|
|
31862
32181
|
};
|
|
32182
|
+
const input = flueOperationInput(event);
|
|
32183
|
+
if (!state.loggedInput && input !== void 0) {
|
|
32184
|
+
safeLog3(state.span, { input });
|
|
32185
|
+
state.loggedInput = true;
|
|
32186
|
+
}
|
|
31863
32187
|
this.finishPendingChildrenForOperation(event, output);
|
|
31864
32188
|
safeLog3(state.span, {
|
|
31865
32189
|
...event.isError ? { error: toLoggedError(event.errorInfo ?? event.error) } : {},
|
|
@@ -31876,6 +32200,8 @@ var FlueObserveBridge = class {
|
|
|
31876
32200
|
return;
|
|
31877
32201
|
}
|
|
31878
32202
|
const input = flueTurnRequestInput(event);
|
|
32203
|
+
const operation = event.operationId ? this.operationsById.get(event.operationId) : void 0;
|
|
32204
|
+
const turnInput = prepareFlueTurnInput(event, input, operation);
|
|
31879
32205
|
const model = flueTurnRequestModel(event);
|
|
31880
32206
|
const provider = flueTurnRequestProvider(event);
|
|
31881
32207
|
const api = flueTurnRequestApi(event);
|
|
@@ -31888,8 +32214,7 @@ var FlueObserveBridge = class {
|
|
|
31888
32214
|
...provider ? { "flue.provider": provider } : {},
|
|
31889
32215
|
...event.purpose ? { "flue.turn_purpose": event.purpose } : {},
|
|
31890
32216
|
...reasoning ? { reasoning } : {},
|
|
31891
|
-
...
|
|
31892
|
-
...input?.tools ? { tools: input.tools } : {}
|
|
32217
|
+
...turnInput.metadata
|
|
31893
32218
|
};
|
|
31894
32219
|
const parent = this.parentSpanForTurn(event);
|
|
31895
32220
|
const span = startFlueSpan(parent, {
|
|
@@ -31897,11 +32222,14 @@ var FlueObserveBridge = class {
|
|
|
31897
32222
|
spanAttributes: { type: "llm" /* LLM */ },
|
|
31898
32223
|
startTime: eventTime(event.timestamp),
|
|
31899
32224
|
event: {
|
|
31900
|
-
input:
|
|
32225
|
+
input: turnInput.messages,
|
|
31901
32226
|
metadata
|
|
31902
32227
|
}
|
|
31903
32228
|
});
|
|
31904
|
-
this.logOperationInput(
|
|
32229
|
+
this.logOperationInput(
|
|
32230
|
+
event.operationId,
|
|
32231
|
+
latestUserMessageInput(input?.messages)
|
|
32232
|
+
);
|
|
31905
32233
|
this.turnsByKey.set(key, { metadata, span });
|
|
31906
32234
|
}
|
|
31907
32235
|
handleTurn(event) {
|
|
@@ -32148,16 +32476,20 @@ var FlueObserveBridge = class {
|
|
|
32148
32476
|
}
|
|
32149
32477
|
startSyntheticOperation(event) {
|
|
32150
32478
|
const metadata = {
|
|
32479
|
+
...event.runId ? this.runsById.get(event.runId)?.metadata : {},
|
|
32151
32480
|
...extractEventMetadata(event),
|
|
32152
32481
|
"flue.operation": event.operationKind,
|
|
32153
32482
|
provider: "flue"
|
|
32154
32483
|
};
|
|
32155
|
-
const
|
|
32484
|
+
const args = {
|
|
32156
32485
|
name: `flue.${event.operationKind}`,
|
|
32157
32486
|
spanAttributes: { type: "task" /* TASK */ },
|
|
32158
32487
|
startTime: eventTime(event.timestamp),
|
|
32159
32488
|
event: { metadata }
|
|
32160
|
-
}
|
|
32489
|
+
};
|
|
32490
|
+
const parent = this.parentSpanForEvent(event);
|
|
32491
|
+
const runSpan = event.runId ? this.runsById.get(event.runId)?.span : void 0;
|
|
32492
|
+
const span = event.operationKind === "prompt" && (!parent || parent === runSpan) ? startFlueRootSpan(args) : startFlueSpan(parent, args);
|
|
32161
32493
|
return { metadata, span };
|
|
32162
32494
|
}
|
|
32163
32495
|
startSyntheticTurn(event) {
|
|
@@ -32336,6 +32668,71 @@ function flueRunInput(event) {
|
|
|
32336
32668
|
function flueTurnRequestInput(event) {
|
|
32337
32669
|
return event.request?.input ?? event.input;
|
|
32338
32670
|
}
|
|
32671
|
+
function prepareFlueTurnInput(event, input, operation) {
|
|
32672
|
+
const messages = input?.messages;
|
|
32673
|
+
const tracksUserTurn = event.purpose === "agent" && operation?.metadata["flue.operation"] === "prompt" && Array.isArray(messages);
|
|
32674
|
+
if (!tracksUserTurn) {
|
|
32675
|
+
return {
|
|
32676
|
+
messages,
|
|
32677
|
+
metadata: {
|
|
32678
|
+
...input?.systemPrompt ? { "flue.system_prompt": input.systemPrompt } : {},
|
|
32679
|
+
...input?.tools ? { tools: input.tools } : {}
|
|
32680
|
+
}
|
|
32681
|
+
};
|
|
32682
|
+
}
|
|
32683
|
+
const previous = operation.turnInputState;
|
|
32684
|
+
const previousMessageCount = previous?.messageCount ?? 0;
|
|
32685
|
+
const boundaryFingerprint = messages.length > 0 ? fingerprintJsonValue(messages[messages.length - 1]) : void 0;
|
|
32686
|
+
const continuesPreviousInput = previous !== void 0 && messages.length >= previousMessageCount && (previousMessageCount === 0 || previous.boundaryFingerprint !== void 0 && previous.boundaryFingerprint === fingerprintJsonValue(messages[previousMessageCount - 1]));
|
|
32687
|
+
const inputMode = previous === void 0 ? "full" : continuesPreviousInput ? "delta" : "reset";
|
|
32688
|
+
const systemPromptFingerprint = fingerprintJsonValue(input?.systemPrompt);
|
|
32689
|
+
const toolsFingerprint = fingerprintJsonValue(input?.tools);
|
|
32690
|
+
operation.turnInputState = {
|
|
32691
|
+
...boundaryFingerprint !== void 0 ? { boundaryFingerprint } : {},
|
|
32692
|
+
messageCount: messages.length,
|
|
32693
|
+
...systemPromptFingerprint !== void 0 ? { systemPromptFingerprint } : {},
|
|
32694
|
+
...toolsFingerprint !== void 0 ? { toolsFingerprint } : {}
|
|
32695
|
+
};
|
|
32696
|
+
return {
|
|
32697
|
+
messages: continuesPreviousInput ? messages.slice(previousMessageCount) : messages,
|
|
32698
|
+
metadata: {
|
|
32699
|
+
"flue.input_mode": inputMode,
|
|
32700
|
+
...continuesPreviousInput ? { "flue.input_message_offset": previousMessageCount } : {},
|
|
32701
|
+
...input?.systemPrompt && (!continuesPreviousInput || systemPromptFingerprint !== previous?.systemPromptFingerprint) ? { "flue.system_prompt": input.systemPrompt } : {},
|
|
32702
|
+
...input?.tools && (!continuesPreviousInput || toolsFingerprint !== previous?.toolsFingerprint) ? { tools: input.tools } : {}
|
|
32703
|
+
}
|
|
32704
|
+
};
|
|
32705
|
+
}
|
|
32706
|
+
function fingerprintJsonValue(value) {
|
|
32707
|
+
try {
|
|
32708
|
+
const serialized = JSON.stringify(value);
|
|
32709
|
+
if (serialized === void 0) {
|
|
32710
|
+
return void 0;
|
|
32711
|
+
}
|
|
32712
|
+
let hash = 2166136261;
|
|
32713
|
+
for (let i = 0; i < serialized.length; i++) {
|
|
32714
|
+
hash = Math.imul(hash ^ serialized.charCodeAt(i), 16777619);
|
|
32715
|
+
}
|
|
32716
|
+
return `${serialized.length}:${hash >>> 0}`;
|
|
32717
|
+
} catch {
|
|
32718
|
+
return void 0;
|
|
32719
|
+
}
|
|
32720
|
+
}
|
|
32721
|
+
function latestUserMessageInput(messages) {
|
|
32722
|
+
if (!messages) {
|
|
32723
|
+
return void 0;
|
|
32724
|
+
}
|
|
32725
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
32726
|
+
const message = messages[i];
|
|
32727
|
+
if (isObjectLike(message) && Reflect.get(message, "role") === "user") {
|
|
32728
|
+
return [message];
|
|
32729
|
+
}
|
|
32730
|
+
}
|
|
32731
|
+
return void 0;
|
|
32732
|
+
}
|
|
32733
|
+
function flueOperationInput(event) {
|
|
32734
|
+
return typeof event.agentInput?.text === "string" ? [{ content: event.agentInput.text, role: "user" }] : void 0;
|
|
32735
|
+
}
|
|
32339
32736
|
function flueTurnRequestModel(event) {
|
|
32340
32737
|
return event.request?.requestedModel ?? event.request?.model ?? event.model;
|
|
32341
32738
|
}
|
|
@@ -32493,6 +32890,21 @@ function startFlueSpan(parent, args) {
|
|
|
32493
32890
|
withSpanInstrumentationName(args, INSTRUMENTATION_NAMES.FLUE)
|
|
32494
32891
|
);
|
|
32495
32892
|
}
|
|
32893
|
+
function startFlueRootSpan(args) {
|
|
32894
|
+
const state = _internalGetGlobalState();
|
|
32895
|
+
const spanId = state.idGenerator.getSpanId();
|
|
32896
|
+
const rootSpanId = state.idGenerator.shareRootSpanId() ? spanId : state.idGenerator.getTraceId();
|
|
32897
|
+
return withCurrent(
|
|
32898
|
+
NOOP_SPAN,
|
|
32899
|
+
() => startSpan({
|
|
32900
|
+
...withSpanInstrumentationName(args, INSTRUMENTATION_NAMES.FLUE),
|
|
32901
|
+
parentSpanIds: { parentSpanIds: [], rootSpanId },
|
|
32902
|
+
spanId,
|
|
32903
|
+
state
|
|
32904
|
+
}),
|
|
32905
|
+
state
|
|
32906
|
+
);
|
|
32907
|
+
}
|
|
32496
32908
|
function runWithCurrentSpanStore(span, next) {
|
|
32497
32909
|
const state = _internalGetGlobalState();
|
|
32498
32910
|
const contextManager = state?.contextManager;
|
|
@@ -34392,8 +34804,7 @@ function startAgentStream(event, activeChildParents) {
|
|
|
34392
34804
|
...extractAgentMetadata2(agent),
|
|
34393
34805
|
...extractModelMetadata3(model),
|
|
34394
34806
|
"strands.operation": "Agent.stream",
|
|
34395
|
-
provider: extractProvider(model)
|
|
34396
|
-
...event.moduleVersion ? { "strands_agent_sdk.version": event.moduleVersion } : {}
|
|
34807
|
+
provider: extractProvider(model)
|
|
34397
34808
|
};
|
|
34398
34809
|
const parentSpan = agent ? getOnlyChildParent(activeChildParents, agent) : void 0;
|
|
34399
34810
|
const attachmentCache = createStrandsAttachmentCache();
|
|
@@ -34443,8 +34854,7 @@ function startMultiAgentStream(event, operation, activeChildParents) {
|
|
|
34443
34854
|
const metadata = {
|
|
34444
34855
|
"strands.operation": operation,
|
|
34445
34856
|
provider: "strands",
|
|
34446
|
-
...orchestrator?.id ? { "strands.orchestrator.id": orchestrator.id } : {}
|
|
34447
|
-
...event.moduleVersion ? { "strands_agent_sdk.version": event.moduleVersion } : {}
|
|
34857
|
+
...orchestrator?.id ? { "strands.orchestrator.id": orchestrator.id } : {}
|
|
34448
34858
|
};
|
|
34449
34859
|
const parentSpan = orchestrator ? getOnlyChildParent(activeChildParents, orchestrator) : void 0;
|
|
34450
34860
|
const input = processStrandsInputAttachments(event.arguments[0]);
|
|
@@ -35230,6 +35640,320 @@ function logInstrumentationError5(context, error) {
|
|
|
35230
35640
|
debugLogger.debug(`${context}:`, error);
|
|
35231
35641
|
}
|
|
35232
35642
|
|
|
35643
|
+
// src/instrumentation/plugins/voyageai-channels.ts
|
|
35644
|
+
var voyageAIChannels = defineChannels(
|
|
35645
|
+
"voyageai",
|
|
35646
|
+
{
|
|
35647
|
+
embed: channel({
|
|
35648
|
+
channelName: "embed",
|
|
35649
|
+
kind: "async"
|
|
35650
|
+
}),
|
|
35651
|
+
multimodalEmbed: channel({
|
|
35652
|
+
channelName: "multimodalEmbed",
|
|
35653
|
+
kind: "async"
|
|
35654
|
+
}),
|
|
35655
|
+
rerank: channel({
|
|
35656
|
+
channelName: "rerank",
|
|
35657
|
+
kind: "async"
|
|
35658
|
+
}),
|
|
35659
|
+
contextualizedEmbed: channel({
|
|
35660
|
+
channelName: "contextualizedEmbed",
|
|
35661
|
+
kind: "async"
|
|
35662
|
+
})
|
|
35663
|
+
},
|
|
35664
|
+
{ instrumentationName: INSTRUMENTATION_NAMES.VOYAGEAI }
|
|
35665
|
+
);
|
|
35666
|
+
|
|
35667
|
+
// src/instrumentation/plugins/voyageai-plugin.ts
|
|
35668
|
+
var RERANK_METADATA_ALLOWLIST = /* @__PURE__ */ new Set([
|
|
35669
|
+
"model",
|
|
35670
|
+
"returnDocuments",
|
|
35671
|
+
"topK",
|
|
35672
|
+
"truncation"
|
|
35673
|
+
]);
|
|
35674
|
+
var VoyageAIPlugin = class extends BasePlugin {
|
|
35675
|
+
onEnable() {
|
|
35676
|
+
this.unsubscribers.push(
|
|
35677
|
+
interceptVoyageAICall(
|
|
35678
|
+
voyageAIChannels.embed,
|
|
35679
|
+
"voyageai.embed",
|
|
35680
|
+
extractTextEmbeddingInput,
|
|
35681
|
+
summarizeEmbeddingOutput,
|
|
35682
|
+
extractEmbeddingUsageMetrics
|
|
35683
|
+
),
|
|
35684
|
+
interceptVoyageAICall(
|
|
35685
|
+
voyageAIChannels.multimodalEmbed,
|
|
35686
|
+
"voyageai.multimodalEmbed",
|
|
35687
|
+
extractMultimodalEmbeddingInput,
|
|
35688
|
+
summarizeEmbeddingOutput,
|
|
35689
|
+
extractEmbeddingUsageMetrics
|
|
35690
|
+
),
|
|
35691
|
+
interceptVoyageAICall(
|
|
35692
|
+
voyageAIChannels.rerank,
|
|
35693
|
+
"voyageai.rerank",
|
|
35694
|
+
extractRerankInput,
|
|
35695
|
+
summarizeRerankOutput
|
|
35696
|
+
),
|
|
35697
|
+
interceptVoyageAICall(
|
|
35698
|
+
voyageAIChannels.contextualizedEmbed,
|
|
35699
|
+
"voyageai.contextualizedEmbed",
|
|
35700
|
+
extractContextualizedEmbeddingInput,
|
|
35701
|
+
summarizeContextualizedEmbeddingOutput,
|
|
35702
|
+
extractEmbeddingUsageMetrics
|
|
35703
|
+
)
|
|
35704
|
+
);
|
|
35705
|
+
}
|
|
35706
|
+
onDisable() {
|
|
35707
|
+
this.unsubscribers = unsubscribeAll(this.unsubscribers);
|
|
35708
|
+
}
|
|
35709
|
+
};
|
|
35710
|
+
function interceptVoyageAICall(channel2, name, extractInput3, extractOutput2, extractMetrics2 = extractUsageMetrics3) {
|
|
35711
|
+
return channel2.intercept((target, thisArg, args) => {
|
|
35712
|
+
const invokeTarget = () => Reflect.apply(target, thisArg, args);
|
|
35713
|
+
if (isAutoInstrumentationSuppressed()) {
|
|
35714
|
+
return invokeTarget();
|
|
35715
|
+
}
|
|
35716
|
+
let span;
|
|
35717
|
+
try {
|
|
35718
|
+
const { input, metadata } = extractInput3(args);
|
|
35719
|
+
span = startSpan(
|
|
35720
|
+
withSpanInstrumentationName(
|
|
35721
|
+
{
|
|
35722
|
+
event: { input, metadata },
|
|
35723
|
+
name,
|
|
35724
|
+
spanAttributes: { type: "llm" /* LLM */ }
|
|
35725
|
+
},
|
|
35726
|
+
INSTRUMENTATION_NAMES.VOYAGEAI
|
|
35727
|
+
)
|
|
35728
|
+
);
|
|
35729
|
+
} catch (error) {
|
|
35730
|
+
debugLogger.error(`Error starting span for ${name}:`, error);
|
|
35731
|
+
return invokeTarget();
|
|
35732
|
+
}
|
|
35733
|
+
let result;
|
|
35734
|
+
try {
|
|
35735
|
+
result = withCurrent(
|
|
35736
|
+
span,
|
|
35737
|
+
() => runWithAutoInstrumentationSuppressed(invokeTarget)
|
|
35738
|
+
);
|
|
35739
|
+
} catch (error) {
|
|
35740
|
+
finishVoyageAISpan(span, name, () => span.log({ error }));
|
|
35741
|
+
throw error;
|
|
35742
|
+
}
|
|
35743
|
+
void Promise.resolve(result).then(
|
|
35744
|
+
(value) => finishVoyageAISpan(span, name, () => {
|
|
35745
|
+
const metadata = extractResponseMetadata3(value);
|
|
35746
|
+
span.log({
|
|
35747
|
+
output: extractOutput2(value),
|
|
35748
|
+
...metadata ? { metadata } : {},
|
|
35749
|
+
metrics: extractMetrics2(value)
|
|
35750
|
+
});
|
|
35751
|
+
}),
|
|
35752
|
+
(error) => finishVoyageAISpan(span, name, () => span.log({ error }))
|
|
35753
|
+
);
|
|
35754
|
+
return result;
|
|
35755
|
+
});
|
|
35756
|
+
}
|
|
35757
|
+
function finishVoyageAISpan(span, name, log3) {
|
|
35758
|
+
try {
|
|
35759
|
+
log3();
|
|
35760
|
+
} catch (error) {
|
|
35761
|
+
debugLogger.error(`Error logging span for ${name}:`, error);
|
|
35762
|
+
}
|
|
35763
|
+
try {
|
|
35764
|
+
span.end();
|
|
35765
|
+
} catch (error) {
|
|
35766
|
+
debugLogger.error(`Error ending span for ${name}:`, error);
|
|
35767
|
+
}
|
|
35768
|
+
}
|
|
35769
|
+
function getRequestArg2(args) {
|
|
35770
|
+
if (Array.isArray(args)) {
|
|
35771
|
+
return isObject(args[0]) ? args[0] : void 0;
|
|
35772
|
+
}
|
|
35773
|
+
if (!isObject(args)) {
|
|
35774
|
+
return void 0;
|
|
35775
|
+
}
|
|
35776
|
+
const firstArg = Reflect.get(args, "0");
|
|
35777
|
+
return isObject(firstArg) ? firstArg : void 0;
|
|
35778
|
+
}
|
|
35779
|
+
function pickMetadata(request, allowlist) {
|
|
35780
|
+
const metadata = {};
|
|
35781
|
+
if (request) {
|
|
35782
|
+
for (const key of allowlist) {
|
|
35783
|
+
if (!Object.hasOwn(request, key)) {
|
|
35784
|
+
continue;
|
|
35785
|
+
}
|
|
35786
|
+
const value = request[key];
|
|
35787
|
+
if (value !== void 0) {
|
|
35788
|
+
metadata[key] = value;
|
|
35789
|
+
}
|
|
35790
|
+
}
|
|
35791
|
+
}
|
|
35792
|
+
return {
|
|
35793
|
+
...metadata,
|
|
35794
|
+
provider: "voyage"
|
|
35795
|
+
};
|
|
35796
|
+
}
|
|
35797
|
+
function buildEmbeddingInput(inputs, request) {
|
|
35798
|
+
const outputDimensions = request?.outputDimension;
|
|
35799
|
+
return {
|
|
35800
|
+
inputs,
|
|
35801
|
+
...typeof outputDimensions === "number" && Number.isFinite(outputDimensions) ? { output_dimensions: outputDimensions } : {}
|
|
35802
|
+
};
|
|
35803
|
+
}
|
|
35804
|
+
function embeddingMetadata(request) {
|
|
35805
|
+
return {
|
|
35806
|
+
...typeof request?.model === "string" ? { model: request.model } : {},
|
|
35807
|
+
provider: "voyage"
|
|
35808
|
+
};
|
|
35809
|
+
}
|
|
35810
|
+
function extractTextEmbeddingInput(args) {
|
|
35811
|
+
const request = getRequestArg2(args);
|
|
35812
|
+
const rawInput = request?.input;
|
|
35813
|
+
const values = Array.isArray(rawInput) ? rawInput : [rawInput];
|
|
35814
|
+
return {
|
|
35815
|
+
input: buildEmbeddingInput(
|
|
35816
|
+
values.flatMap(
|
|
35817
|
+
(value) => typeof value === "string" ? [{ content: value }] : []
|
|
35818
|
+
),
|
|
35819
|
+
request
|
|
35820
|
+
),
|
|
35821
|
+
metadata: embeddingMetadata(request)
|
|
35822
|
+
};
|
|
35823
|
+
}
|
|
35824
|
+
function extractContextualizedEmbeddingInput(args) {
|
|
35825
|
+
const request = getRequestArg2(args);
|
|
35826
|
+
const rawInputs = request?.inputs;
|
|
35827
|
+
const values = Array.isArray(rawInputs) ? rawInputs.flatMap((value) => Array.isArray(value) ? value : [value]) : [];
|
|
35828
|
+
return {
|
|
35829
|
+
input: buildEmbeddingInput(
|
|
35830
|
+
values.flatMap(
|
|
35831
|
+
(value) => typeof value === "string" ? [{ content: value }] : []
|
|
35832
|
+
),
|
|
35833
|
+
request
|
|
35834
|
+
),
|
|
35835
|
+
metadata: embeddingMetadata(request)
|
|
35836
|
+
};
|
|
35837
|
+
}
|
|
35838
|
+
function extractMultimodalEmbeddingInput(args) {
|
|
35839
|
+
const request = getRequestArg2(args);
|
|
35840
|
+
const rawInputs = request?.inputs;
|
|
35841
|
+
const inputs = Array.isArray(rawInputs) ? rawInputs.map((rawInput) => {
|
|
35842
|
+
const rawContent = isObject(rawInput) ? rawInput.content : void 0;
|
|
35843
|
+
return {
|
|
35844
|
+
content: Array.isArray(rawContent) ? rawContent.flatMap(normalizeMultimodalContentPart) : []
|
|
35845
|
+
};
|
|
35846
|
+
}) : [];
|
|
35847
|
+
const input = buildEmbeddingInput(inputs, request);
|
|
35848
|
+
const processedInput = processInputAttachments(input);
|
|
35849
|
+
return {
|
|
35850
|
+
input: hasInlineEmbeddingMedia(processedInput) ? input : processedInput,
|
|
35851
|
+
metadata: embeddingMetadata(request)
|
|
35852
|
+
};
|
|
35853
|
+
}
|
|
35854
|
+
function normalizeMultimodalContentPart(part) {
|
|
35855
|
+
if (!isObject(part) || typeof part.type !== "string") {
|
|
35856
|
+
return [];
|
|
35857
|
+
}
|
|
35858
|
+
if (part.type === "text") {
|
|
35859
|
+
return typeof part.text === "string" ? [{ type: "text", text: part.text }] : [];
|
|
35860
|
+
}
|
|
35861
|
+
const camelCaseField = {
|
|
35862
|
+
image_base64: "imageBase64",
|
|
35863
|
+
image_url: "imageUrl",
|
|
35864
|
+
video_base64: "videoBase64",
|
|
35865
|
+
video_url: "videoUrl"
|
|
35866
|
+
};
|
|
35867
|
+
const field = camelCaseField[part.type];
|
|
35868
|
+
if (!field) {
|
|
35869
|
+
return [];
|
|
35870
|
+
}
|
|
35871
|
+
const data = typeof part[field] === "string" ? part[field] : part[part.type];
|
|
35872
|
+
if (typeof data !== "string") {
|
|
35873
|
+
return [];
|
|
35874
|
+
}
|
|
35875
|
+
return part.type.startsWith("image_") ? [{ type: "image_url", image_url: { url: data } }] : [{ type: "file", file: { file_data: data } }];
|
|
35876
|
+
}
|
|
35877
|
+
function hasInlineEmbeddingMedia(input) {
|
|
35878
|
+
return input.inputs.some(
|
|
35879
|
+
({ content }) => Array.isArray(content) ? content.some((part) => {
|
|
35880
|
+
const value = part.type === "image_url" ? part.image_url.url : part.type === "file" ? part.file.file_data : void 0;
|
|
35881
|
+
return typeof value === "string" && value.startsWith("data:");
|
|
35882
|
+
}) : false
|
|
35883
|
+
);
|
|
35884
|
+
}
|
|
35885
|
+
function extractRerankInput(args) {
|
|
35886
|
+
const request = getRequestArg2(args);
|
|
35887
|
+
const documents = request?.documents;
|
|
35888
|
+
return {
|
|
35889
|
+
input: {
|
|
35890
|
+
documents,
|
|
35891
|
+
query: request?.query
|
|
35892
|
+
},
|
|
35893
|
+
metadata: {
|
|
35894
|
+
...pickMetadata(request, RERANK_METADATA_ALLOWLIST),
|
|
35895
|
+
...Array.isArray(documents) ? { document_count: documents.length } : {}
|
|
35896
|
+
}
|
|
35897
|
+
};
|
|
35898
|
+
}
|
|
35899
|
+
function extractResponseMetadata3(result) {
|
|
35900
|
+
if (!isObject(result)) {
|
|
35901
|
+
return void 0;
|
|
35902
|
+
}
|
|
35903
|
+
const rawResponse = isObject(result.rawResponse) ? result.rawResponse : void 0;
|
|
35904
|
+
const model = typeof result.model === "string" ? result.model : typeof rawResponse?.model === "string" ? rawResponse.model : void 0;
|
|
35905
|
+
return model ? { model } : void 0;
|
|
35906
|
+
}
|
|
35907
|
+
function summarizeEmbeddingOutput(result) {
|
|
35908
|
+
return {
|
|
35909
|
+
count: isObject(result) && Array.isArray(result.data) ? result.data.length : 0
|
|
35910
|
+
};
|
|
35911
|
+
}
|
|
35912
|
+
function summarizeRerankOutput(result) {
|
|
35913
|
+
if (!isObject(result) || !Array.isArray(result.data)) {
|
|
35914
|
+
return void 0;
|
|
35915
|
+
}
|
|
35916
|
+
return result.data.slice(0, 100).map((item) => ({
|
|
35917
|
+
index: isObject(item) ? item.index : void 0,
|
|
35918
|
+
relevance_score: isObject(item) ? (typeof item.relevanceScore === "number" ? item.relevanceScore : item.relevance_score) ?? null : null
|
|
35919
|
+
}));
|
|
35920
|
+
}
|
|
35921
|
+
function summarizeContextualizedEmbeddingOutput(result) {
|
|
35922
|
+
if (!isObject(result)) {
|
|
35923
|
+
return { count: 0 };
|
|
35924
|
+
}
|
|
35925
|
+
if (Array.isArray(result.results)) {
|
|
35926
|
+
return {
|
|
35927
|
+
count: result.results.reduce(
|
|
35928
|
+
(count, item) => count + (isObject(item) && Array.isArray(item.embeddings) ? item.embeddings.length : 0),
|
|
35929
|
+
0
|
|
35930
|
+
)
|
|
35931
|
+
};
|
|
35932
|
+
}
|
|
35933
|
+
if (!Array.isArray(result.data)) {
|
|
35934
|
+
return { count: 0 };
|
|
35935
|
+
}
|
|
35936
|
+
return {
|
|
35937
|
+
count: result.data.reduce(
|
|
35938
|
+
(count, item) => count + (isObject(item) && Array.isArray(item.data) ? item.data.length : 0),
|
|
35939
|
+
0
|
|
35940
|
+
)
|
|
35941
|
+
};
|
|
35942
|
+
}
|
|
35943
|
+
function extractEmbeddingUsageMetrics(result) {
|
|
35944
|
+
const metrics = extractUsageMetrics3(result);
|
|
35945
|
+
return typeof metrics.tokens === "number" ? { prompt_tokens: metrics.tokens, tokens: metrics.tokens } : {};
|
|
35946
|
+
}
|
|
35947
|
+
function extractUsageMetrics3(result) {
|
|
35948
|
+
if (!isObject(result)) {
|
|
35949
|
+
return {};
|
|
35950
|
+
}
|
|
35951
|
+
const rawResponse = isObject(result.rawResponse) ? result.rawResponse : void 0;
|
|
35952
|
+
const usage = isObject(result.usage) ? result.usage : isObject(rawResponse?.usage) ? rawResponse.usage : void 0;
|
|
35953
|
+
const tokens = typeof result.totalTokens === "number" ? result.totalTokens : usage?.totalTokens ?? usage?.total_tokens;
|
|
35954
|
+
return typeof tokens === "number" && Number.isFinite(tokens) && tokens >= 0 ? { tokens } : {};
|
|
35955
|
+
}
|
|
35956
|
+
|
|
35233
35957
|
// src/instrumentation/plugins/cloudflare-ai-chat-channels.ts
|
|
35234
35958
|
var cloudflareAIChatChannels = defineChannels(
|
|
35235
35959
|
"@cloudflare/ai-chat",
|
|
@@ -35808,6 +36532,7 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
35808
36532
|
langSmithPlugin = null;
|
|
35809
36533
|
piCodingAgentPlugin = null;
|
|
35810
36534
|
strandsAgentSDKPlugin = null;
|
|
36535
|
+
voyageAIPlugin = null;
|
|
35811
36536
|
cloudflareAIChatPlugin = null;
|
|
35812
36537
|
cloudflareAgentsPlugin = null;
|
|
35813
36538
|
constructor(config = {}) {
|
|
@@ -35882,6 +36607,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
35882
36607
|
this.coherePlugin = new CoherePlugin();
|
|
35883
36608
|
this.coherePlugin.enable();
|
|
35884
36609
|
}
|
|
36610
|
+
if (integrations.voyageai !== false) {
|
|
36611
|
+
this.voyageAIPlugin = new VoyageAIPlugin();
|
|
36612
|
+
this.voyageAIPlugin.enable();
|
|
36613
|
+
}
|
|
35885
36614
|
if (integrations.groq !== false) {
|
|
35886
36615
|
this.groqPlugin = new GroqPlugin();
|
|
35887
36616
|
this.groqPlugin.enable();
|
|
@@ -35998,6 +36727,10 @@ var BraintrustPlugin = class extends BasePlugin {
|
|
|
35998
36727
|
this.coherePlugin.disable();
|
|
35999
36728
|
this.coherePlugin = null;
|
|
36000
36729
|
}
|
|
36730
|
+
if (this.voyageAIPlugin) {
|
|
36731
|
+
this.voyageAIPlugin.disable();
|
|
36732
|
+
this.voyageAIPlugin = null;
|
|
36733
|
+
}
|
|
36001
36734
|
if (this.groqPlugin) {
|
|
36002
36735
|
this.groqPlugin.disable();
|
|
36003
36736
|
this.groqPlugin = null;
|
|
@@ -36117,7 +36850,10 @@ var envIntegrationAliases = {
|
|
|
36117
36850
|
"langchain-js": "langchain",
|
|
36118
36851
|
"@langchain": "langchain",
|
|
36119
36852
|
langgraph: "langgraph",
|
|
36120
|
-
langsmith: "langsmith"
|
|
36853
|
+
langsmith: "langsmith",
|
|
36854
|
+
voyage: "voyageai",
|
|
36855
|
+
"voyage-ai": "voyageai",
|
|
36856
|
+
voyageai: "voyageai"
|
|
36121
36857
|
};
|
|
36122
36858
|
function getDefaultInstrumentationIntegrations() {
|
|
36123
36859
|
return {
|
|
@@ -36152,6 +36888,7 @@ function getDefaultInstrumentationIntegrations() {
|
|
|
36152
36888
|
langchain: true,
|
|
36153
36889
|
langgraph: true,
|
|
36154
36890
|
langsmith: true,
|
|
36891
|
+
voyageai: true,
|
|
36155
36892
|
piCodingAgent: true,
|
|
36156
36893
|
strandsAgentSDK: true,
|
|
36157
36894
|
cloudflareAgents: true
|
|
@@ -36315,6 +37052,8 @@ __export(exports_exports, {
|
|
|
36315
37052
|
BRAINTRUST_PARENT_KEY: () => BRAINTRUST_PARENT_KEY,
|
|
36316
37053
|
BaseAttachment: () => BaseAttachment,
|
|
36317
37054
|
BaseExperiment: () => BaseExperiment,
|
|
37055
|
+
BatchScorer: () => BatchScorer,
|
|
37056
|
+
BatchTask: () => BatchTask,
|
|
36318
37057
|
BraintrustLangChainCallbackHandler: () => BraintrustLangChainCallbackHandler,
|
|
36319
37058
|
BraintrustMiddleware: () => BraintrustMiddleware,
|
|
36320
37059
|
BraintrustObservabilityExporter: () => BraintrustObservabilityExporter,
|
|
@@ -36328,6 +37067,8 @@ __export(exports_exports, {
|
|
|
36328
37067
|
DEFAULT_MAX_REQUEST_SIZE: () => DEFAULT_MAX_REQUEST_SIZE,
|
|
36329
37068
|
Dataset: () => Dataset2,
|
|
36330
37069
|
DatasetPipeline: () => DatasetPipeline,
|
|
37070
|
+
DurableEvalMemoryStore: () => DurableEvalMemoryStore,
|
|
37071
|
+
DurableEvalRedisStore: () => DurableEvalRedisStore,
|
|
36331
37072
|
ERR_PERMALINK: () => ERR_PERMALINK,
|
|
36332
37073
|
Eval: () => Eval,
|
|
36333
37074
|
EvalResultWithSummary: () => EvalResultWithSummary,
|
|
@@ -36385,6 +37126,7 @@ __export(exports_exports, {
|
|
|
36385
37126
|
currentSpan: () => currentSpan,
|
|
36386
37127
|
deepCopyEvent: () => deepCopyEvent,
|
|
36387
37128
|
defaultErrorScoreHandler: () => defaultErrorScoreHandler,
|
|
37129
|
+
defineDurableEval: () => defineDurableEval,
|
|
36388
37130
|
deserializePlainStringAsJSON: () => deserializePlainStringAsJSON,
|
|
36389
37131
|
devNullWritableStream: () => devNullWritableStream,
|
|
36390
37132
|
evaluatorDefinitionSchema: () => evaluatorDefinitionSchema,
|
|
@@ -36480,7 +37222,8 @@ __export(exports_exports, {
|
|
|
36480
37222
|
wrapPiCodingAgentSDK: () => wrapPiCodingAgentSDK,
|
|
36481
37223
|
wrapStrandsAgentSDK: () => wrapStrandsAgentSDK,
|
|
36482
37224
|
wrapTraced: () => wrapTraced,
|
|
36483
|
-
wrapVitest: () => wrapVitest
|
|
37225
|
+
wrapVitest: () => wrapVitest,
|
|
37226
|
+
wrapVoyageAI: () => wrapVoyageAI
|
|
36484
37227
|
});
|
|
36485
37228
|
|
|
36486
37229
|
// src/sandbox.ts
|
|
@@ -37741,7 +38484,7 @@ function normalizeUsageMetrics(usage, provider, providerMetadata) {
|
|
|
37741
38484
|
cacheCreationTokens
|
|
37742
38485
|
);
|
|
37743
38486
|
Object.assign(metrics, cacheTokens);
|
|
37744
|
-
|
|
38487
|
+
return toNumericMetrics(finalizeAnthropicTokens(metrics));
|
|
37745
38488
|
}
|
|
37746
38489
|
}
|
|
37747
38490
|
return metrics;
|
|
@@ -42074,6 +42817,84 @@ function wrapRerank3(rerank) {
|
|
|
42074
42817
|
});
|
|
42075
42818
|
}
|
|
42076
42819
|
|
|
42820
|
+
// src/wrappers/voyageai.ts
|
|
42821
|
+
function wrapVoyageAI(client) {
|
|
42822
|
+
if (!isSupportedVoyageAIClient(client)) {
|
|
42823
|
+
console.warn("Unsupported Voyage AI library. Not wrapping.");
|
|
42824
|
+
return client;
|
|
42825
|
+
}
|
|
42826
|
+
return voyageAIProxy(client);
|
|
42827
|
+
}
|
|
42828
|
+
var voyageAIProxyCache = /* @__PURE__ */ new WeakMap();
|
|
42829
|
+
function isObject3(value) {
|
|
42830
|
+
return typeof value === "object" && value !== null;
|
|
42831
|
+
}
|
|
42832
|
+
function hasFunction5(value, name) {
|
|
42833
|
+
return typeof Reflect.get(value, name) === "function";
|
|
42834
|
+
}
|
|
42835
|
+
function isSupportedVoyageAIClient(value) {
|
|
42836
|
+
if (!isObject3(value)) {
|
|
42837
|
+
return false;
|
|
42838
|
+
}
|
|
42839
|
+
return hasFunction5(value, "embed") || hasFunction5(value, "multimodalEmbed") || hasFunction5(value, "rerank") || hasFunction5(value, "contextualizedEmbed");
|
|
42840
|
+
}
|
|
42841
|
+
function voyageAIProxy(client) {
|
|
42842
|
+
const cached = voyageAIProxyCache.get(client);
|
|
42843
|
+
if (cached) {
|
|
42844
|
+
return cached;
|
|
42845
|
+
}
|
|
42846
|
+
const proxy = new Proxy(client, {
|
|
42847
|
+
get(target, prop, receiver) {
|
|
42848
|
+
switch (prop) {
|
|
42849
|
+
case "embed":
|
|
42850
|
+
if (typeof target.embed !== "function") {
|
|
42851
|
+
return target.embed;
|
|
42852
|
+
}
|
|
42853
|
+
return (request, options) => voyageAIChannels.embed.invoke(
|
|
42854
|
+
target.embed,
|
|
42855
|
+
target,
|
|
42856
|
+
[request, options],
|
|
42857
|
+
{}
|
|
42858
|
+
);
|
|
42859
|
+
case "multimodalEmbed":
|
|
42860
|
+
if (typeof target.multimodalEmbed !== "function") {
|
|
42861
|
+
return target.multimodalEmbed;
|
|
42862
|
+
}
|
|
42863
|
+
return (request, options) => voyageAIChannels.multimodalEmbed.invoke(
|
|
42864
|
+
target.multimodalEmbed,
|
|
42865
|
+
target,
|
|
42866
|
+
[request, options],
|
|
42867
|
+
{}
|
|
42868
|
+
);
|
|
42869
|
+
case "rerank":
|
|
42870
|
+
if (typeof target.rerank !== "function") {
|
|
42871
|
+
return target.rerank;
|
|
42872
|
+
}
|
|
42873
|
+
return (request, options) => voyageAIChannels.rerank.invoke(
|
|
42874
|
+
target.rerank,
|
|
42875
|
+
target,
|
|
42876
|
+
[request, options],
|
|
42877
|
+
{}
|
|
42878
|
+
);
|
|
42879
|
+
case "contextualizedEmbed":
|
|
42880
|
+
if (typeof target.contextualizedEmbed !== "function") {
|
|
42881
|
+
return target.contextualizedEmbed;
|
|
42882
|
+
}
|
|
42883
|
+
return (request, options) => voyageAIChannels.contextualizedEmbed.invoke(
|
|
42884
|
+
target.contextualizedEmbed,
|
|
42885
|
+
target,
|
|
42886
|
+
[request, options],
|
|
42887
|
+
{}
|
|
42888
|
+
);
|
|
42889
|
+
default:
|
|
42890
|
+
return Reflect.get(target, prop, receiver);
|
|
42891
|
+
}
|
|
42892
|
+
}
|
|
42893
|
+
});
|
|
42894
|
+
voyageAIProxyCache.set(client, proxy);
|
|
42895
|
+
return proxy;
|
|
42896
|
+
}
|
|
42897
|
+
|
|
42077
42898
|
// src/wrappers/groq.ts
|
|
42078
42899
|
function wrapGroq(groq) {
|
|
42079
42900
|
if (isSupportedGroqClient(groq)) {
|
|
@@ -42085,14 +42906,14 @@ function wrapGroq(groq) {
|
|
|
42085
42906
|
function isRecord6(value) {
|
|
42086
42907
|
return typeof value === "object" && value !== null;
|
|
42087
42908
|
}
|
|
42088
|
-
function
|
|
42909
|
+
function hasFunction6(value, methodName) {
|
|
42089
42910
|
return isRecord6(value) && methodName in value && typeof value[methodName] === "function";
|
|
42090
42911
|
}
|
|
42091
42912
|
function hasChat2(value) {
|
|
42092
|
-
return isRecord6(value) && isRecord6(value.completions) &&
|
|
42913
|
+
return isRecord6(value) && isRecord6(value.completions) && hasFunction6(value.completions, "create");
|
|
42093
42914
|
}
|
|
42094
42915
|
function hasEmbeddings2(value) {
|
|
42095
|
-
return
|
|
42916
|
+
return hasFunction6(value, "create");
|
|
42096
42917
|
}
|
|
42097
42918
|
function isSupportedGroqClient(value) {
|
|
42098
42919
|
return isRecord6(value) && (value.chat !== void 0 && hasChat2(value.chat) || value.embeddings !== void 0 && hasEmbeddings2(value.embeddings));
|
|
@@ -42675,7 +43496,7 @@ async function flushExperimentWithSync(context, config) {
|
|
|
42675
43496
|
// src/wrappers/shared/scorers.ts
|
|
42676
43497
|
async function runScorers(args) {
|
|
42677
43498
|
const { scorers, output, expected, input, metadata, span } = args;
|
|
42678
|
-
const
|
|
43499
|
+
const scorerArgs2 = {
|
|
42679
43500
|
output,
|
|
42680
43501
|
expected,
|
|
42681
43502
|
input,
|
|
@@ -42684,7 +43505,7 @@ async function runScorers(args) {
|
|
|
42684
43505
|
await Promise.all(
|
|
42685
43506
|
scorers.map(async (scorer) => {
|
|
42686
43507
|
try {
|
|
42687
|
-
const result = await scorer(
|
|
43508
|
+
const result = await scorer(scorerArgs2);
|
|
42688
43509
|
const scores = normalizeScores(result);
|
|
42689
43510
|
if (scores.length > 0) {
|
|
42690
43511
|
const accScores = {};
|
|
@@ -45043,6 +45864,26 @@ async function getExperimentParametersRef(parameters) {
|
|
|
45043
45864
|
version: resolvedParameters.version
|
|
45044
45865
|
};
|
|
45045
45866
|
}
|
|
45867
|
+
async function _internalInitEvaluatorExperiment(projectName, evaluator, data, options = {}) {
|
|
45868
|
+
if (options.disabled) return null;
|
|
45869
|
+
const { baseExperiment } = callEvaluatorData(data);
|
|
45870
|
+
const parameters = await getExperimentParametersRef(evaluator.parameters);
|
|
45871
|
+
return initExperiment2(evaluator.state, {
|
|
45872
|
+
...evaluator.projectId ? { projectId: evaluator.projectId } : { project: projectName },
|
|
45873
|
+
experiment: options.experimentName ?? evaluator.experimentName,
|
|
45874
|
+
description: evaluator.description,
|
|
45875
|
+
metadata: evaluator.metadata,
|
|
45876
|
+
tags: evaluator.tags,
|
|
45877
|
+
isPublic: evaluator.isPublic,
|
|
45878
|
+
update: options.update ?? evaluator.update,
|
|
45879
|
+
baseExperiment: evaluator.baseExperimentName ?? baseExperiment,
|
|
45880
|
+
baseExperimentId: evaluator.baseExperimentId,
|
|
45881
|
+
gitMetadataSettings: evaluator.gitMetadataSettings,
|
|
45882
|
+
repoInfo: evaluator.repoInfo,
|
|
45883
|
+
dataset: Dataset2.isDataset(data) ? data : void 0,
|
|
45884
|
+
parameters
|
|
45885
|
+
});
|
|
45886
|
+
}
|
|
45046
45887
|
function callEvaluatorData(data) {
|
|
45047
45888
|
const dataResult = typeof data === "function" ? data() : data;
|
|
45048
45889
|
let baseExperiment = void 0;
|
|
@@ -45060,6 +45901,48 @@ function isAsyncIterable7(value) {
|
|
|
45060
45901
|
function isIterable(value) {
|
|
45061
45902
|
return typeof value === "object" && value !== null && Symbol.iterator in value && typeof value[Symbol.iterator] === "function";
|
|
45062
45903
|
}
|
|
45904
|
+
async function _internalResolveEvaluatorData(evaluator, experiment) {
|
|
45905
|
+
if (typeof evaluator.data === "string") {
|
|
45906
|
+
throw new Error("Unimplemented: string data paths");
|
|
45907
|
+
}
|
|
45908
|
+
let dataResult = typeof evaluator.data === "function" ? evaluator.data() : evaluator.data;
|
|
45909
|
+
if ("_type" in dataResult) {
|
|
45910
|
+
if (dataResult._type !== "BaseExperiment") {
|
|
45911
|
+
throw new Error("Invalid _type");
|
|
45912
|
+
}
|
|
45913
|
+
if (!experiment) {
|
|
45914
|
+
throw new Error(
|
|
45915
|
+
"Cannot use BaseExperiment() without connecting to Braintrust (you most likely set --no-send-logs)"
|
|
45916
|
+
);
|
|
45917
|
+
}
|
|
45918
|
+
let name = dataResult.name;
|
|
45919
|
+
if (isEmpty2(name)) {
|
|
45920
|
+
const baseExperiment = await experiment.fetchBaseExperiment();
|
|
45921
|
+
if (!baseExperiment) {
|
|
45922
|
+
throw new Error("BaseExperiment() failed to fetch base experiment");
|
|
45923
|
+
}
|
|
45924
|
+
name = baseExperiment.name;
|
|
45925
|
+
}
|
|
45926
|
+
dataResult = initExperiment2(evaluator.state, {
|
|
45927
|
+
...evaluator.projectId ? { projectId: evaluator.projectId } : { project: evaluator.projectName },
|
|
45928
|
+
experiment: name,
|
|
45929
|
+
open: true
|
|
45930
|
+
}).asDataset();
|
|
45931
|
+
}
|
|
45932
|
+
const resolvedDataResult = dataResult instanceof Promise ? await dataResult : dataResult;
|
|
45933
|
+
if (isAsyncIterable7(resolvedDataResult)) {
|
|
45934
|
+
return resolvedDataResult;
|
|
45935
|
+
}
|
|
45936
|
+
if (Array.isArray(resolvedDataResult) || isIterable(resolvedDataResult)) {
|
|
45937
|
+
const iterable = resolvedDataResult;
|
|
45938
|
+
return (async function* () {
|
|
45939
|
+
for (const datum of iterable) yield datum;
|
|
45940
|
+
})();
|
|
45941
|
+
}
|
|
45942
|
+
throw new Error(
|
|
45943
|
+
"Evaluator data must be an array, iterable, or async iterable"
|
|
45944
|
+
);
|
|
45945
|
+
}
|
|
45063
45946
|
globalThis._evals = {
|
|
45064
45947
|
functions: [],
|
|
45065
45948
|
prompts: [],
|
|
@@ -45106,25 +45989,13 @@ async function Eval(name, evaluator, reporterOrOpts) {
|
|
|
45106
45989
|
}
|
|
45107
45990
|
const resolvedReporter = options.reporter || defaultReporter;
|
|
45108
45991
|
try {
|
|
45109
|
-
const { data
|
|
45110
|
-
|
|
45111
|
-
|
|
45112
|
-
|
|
45113
|
-
|
|
45114
|
-
|
|
45115
|
-
|
|
45116
|
-
description: evaluator.description,
|
|
45117
|
-
metadata: evaluator.metadata,
|
|
45118
|
-
tags: evaluator.tags,
|
|
45119
|
-
isPublic: evaluator.isPublic,
|
|
45120
|
-
update: evaluator.update,
|
|
45121
|
-
baseExperiment: evaluator.baseExperimentName ?? defaultBaseExperiment,
|
|
45122
|
-
baseExperimentId: evaluator.baseExperimentId,
|
|
45123
|
-
gitMetadataSettings: evaluator.gitMetadataSettings,
|
|
45124
|
-
repoInfo: evaluator.repoInfo,
|
|
45125
|
-
dataset: Dataset2.isDataset(data) ? data : void 0,
|
|
45126
|
-
parameters
|
|
45127
|
-
});
|
|
45992
|
+
const { data } = callEvaluatorData(evaluator.data);
|
|
45993
|
+
const experiment = await _internalInitEvaluatorExperiment(
|
|
45994
|
+
name,
|
|
45995
|
+
evaluator,
|
|
45996
|
+
data,
|
|
45997
|
+
{ disabled: Boolean(options.parent || options.noSendLogs) }
|
|
45998
|
+
);
|
|
45128
45999
|
if (experiment && typeof process !== "undefined" && globalThis.BRAINTRUST_CONTEXT_MANAGER !== void 0) {
|
|
45129
46000
|
await experiment._waitForId();
|
|
45130
46001
|
}
|
|
@@ -45222,19 +46093,74 @@ function scorerName(scorer, scorer_idx) {
|
|
|
45222
46093
|
function classifierName(classifier, classifier_idx) {
|
|
45223
46094
|
return classifier.name || `classifier_${classifier_idx}`;
|
|
45224
46095
|
}
|
|
46096
|
+
async function _internalRunEvaluatorTask(task, datum, trialIndex, parameters, span, reportProgress = () => void 0) {
|
|
46097
|
+
const metadata = {
|
|
46098
|
+
..."metadata" in datum ? datum.metadata : {}
|
|
46099
|
+
};
|
|
46100
|
+
const hooks = {
|
|
46101
|
+
meta(value) {
|
|
46102
|
+
Object.assign(metadata, value);
|
|
46103
|
+
},
|
|
46104
|
+
metadata,
|
|
46105
|
+
expected: "expected" in datum ? datum.expected : void 0,
|
|
46106
|
+
span,
|
|
46107
|
+
parameters,
|
|
46108
|
+
reportProgress,
|
|
46109
|
+
trialIndex,
|
|
46110
|
+
tags: [...datum.tags ?? []]
|
|
46111
|
+
};
|
|
46112
|
+
const output = await task(datum.input, hooks);
|
|
46113
|
+
span.log({ output });
|
|
46114
|
+
return {
|
|
46115
|
+
output,
|
|
46116
|
+
metadata: hooks.metadata,
|
|
46117
|
+
tags: hooks.tags ?? []
|
|
46118
|
+
};
|
|
46119
|
+
}
|
|
45225
46120
|
function buildSpanMetadata(results) {
|
|
45226
|
-
return results.length === 1 ? results[0].metadata :
|
|
45227
|
-
(
|
|
45228
|
-
{}
|
|
46121
|
+
return results.length === 1 ? results[0].metadata : Object.fromEntries(
|
|
46122
|
+
results.map((result) => [result.name, result.metadata])
|
|
45229
46123
|
);
|
|
45230
46124
|
}
|
|
45231
46125
|
function buildSpanScores(results) {
|
|
45232
|
-
const scoresRecord =
|
|
45233
|
-
(
|
|
45234
|
-
{}
|
|
46126
|
+
const scoresRecord = Object.fromEntries(
|
|
46127
|
+
results.map((result) => [result.name, result.score])
|
|
45235
46128
|
);
|
|
45236
46129
|
return { resultMetadata: buildSpanMetadata(results), scoresRecord };
|
|
45237
46130
|
}
|
|
46131
|
+
function _internalPrepareEvaluatorScore(scoreValue, name) {
|
|
46132
|
+
if (scoreValue === null) return { results: null };
|
|
46133
|
+
if (Array.isArray(scoreValue)) {
|
|
46134
|
+
for (const score of scoreValue) {
|
|
46135
|
+
if (!(typeof score === "object" && !isEmpty2(score))) {
|
|
46136
|
+
throw new Error(
|
|
46137
|
+
`When returning an array of scores, each score must be a non-empty object. Got: ${JSON.stringify(score)}`
|
|
46138
|
+
);
|
|
46139
|
+
}
|
|
46140
|
+
}
|
|
46141
|
+
}
|
|
46142
|
+
let results;
|
|
46143
|
+
if (Array.isArray(scoreValue)) {
|
|
46144
|
+
results = scoreValue;
|
|
46145
|
+
} else if (typeof scoreValue === "object" && !isEmpty2(scoreValue)) {
|
|
46146
|
+
results = [scoreValue];
|
|
46147
|
+
} else {
|
|
46148
|
+
results = [{ name, score: scoreValue }];
|
|
46149
|
+
}
|
|
46150
|
+
const { resultMetadata, scoresRecord } = buildSpanScores(results);
|
|
46151
|
+
const fields = (score) => {
|
|
46152
|
+
const { metadata: _metadata, name: _name, ...rest } = score;
|
|
46153
|
+
return rest;
|
|
46154
|
+
};
|
|
46155
|
+
return {
|
|
46156
|
+
results,
|
|
46157
|
+
output: results.length === 1 ? fields(results[0]) : Object.fromEntries(
|
|
46158
|
+
results.map((score) => [score.name ?? name, fields(score)])
|
|
46159
|
+
),
|
|
46160
|
+
metadata: resultMetadata,
|
|
46161
|
+
scores: scoresRecord
|
|
46162
|
+
};
|
|
46163
|
+
}
|
|
45238
46164
|
async function runInScorerSpan(rootSpan, spanName, spanType, propagatedEvent, eventInput, fn) {
|
|
45239
46165
|
try {
|
|
45240
46166
|
const value = await rootSpan.traced(fn, {
|
|
@@ -45279,6 +46205,27 @@ function toClassificationItem(c) {
|
|
|
45279
46205
|
...c.metadata !== void 0 ? { metadata: c.metadata } : {}
|
|
45280
46206
|
};
|
|
45281
46207
|
}
|
|
46208
|
+
function _internalPrepareEvaluatorClassification(value, name) {
|
|
46209
|
+
if (value === null) return { results: null };
|
|
46210
|
+
const results = (Array.isArray(value) ? value : [value]).map(
|
|
46211
|
+
(result) => validateClassificationResult(result, name)
|
|
46212
|
+
);
|
|
46213
|
+
const classifications = /* @__PURE__ */ Object.create(null);
|
|
46214
|
+
for (const result of results) {
|
|
46215
|
+
(classifications[result.name] ??= []).push(toClassificationItem(result));
|
|
46216
|
+
}
|
|
46217
|
+
return {
|
|
46218
|
+
results,
|
|
46219
|
+
output: results.length === 1 ? toClassificationItem(results[0]) : Object.fromEntries(
|
|
46220
|
+
results.map((result) => [
|
|
46221
|
+
result.name,
|
|
46222
|
+
toClassificationItem(result)
|
|
46223
|
+
])
|
|
46224
|
+
),
|
|
46225
|
+
metadata: buildSpanMetadata(results),
|
|
46226
|
+
classifications
|
|
46227
|
+
};
|
|
46228
|
+
}
|
|
45282
46229
|
function logScoringFailures(kind, failures, metadata, rootSpan, state) {
|
|
45283
46230
|
if (!failures.length) return [];
|
|
45284
46231
|
const errorMap = Object.fromEntries(
|
|
@@ -45326,54 +46273,14 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
|
|
|
45326
46273
|
(evaluator.state ?? _internalGetGlobalState())?.spanCache?.start();
|
|
45327
46274
|
}
|
|
45328
46275
|
try {
|
|
45329
|
-
if (typeof evaluator.data === "string") {
|
|
45330
|
-
throw new Error("Unimplemented: string data paths");
|
|
45331
|
-
}
|
|
45332
|
-
let dataResult = typeof evaluator.data === "function" ? evaluator.data() : evaluator.data;
|
|
45333
46276
|
parameters = await validateParameters(
|
|
45334
46277
|
parameters ?? {},
|
|
45335
46278
|
evaluator.parameters
|
|
45336
46279
|
);
|
|
45337
|
-
|
|
45338
|
-
|
|
45339
|
-
|
|
45340
|
-
|
|
45341
|
-
if (!experiment) {
|
|
45342
|
-
throw new Error(
|
|
45343
|
-
"Cannot use BaseExperiment() without connecting to Braintrust (you most likely set --no-send-logs)"
|
|
45344
|
-
);
|
|
45345
|
-
}
|
|
45346
|
-
let name = dataResult.name;
|
|
45347
|
-
if (isEmpty2(name)) {
|
|
45348
|
-
const baseExperiment = await experiment.fetchBaseExperiment();
|
|
45349
|
-
if (!baseExperiment) {
|
|
45350
|
-
throw new Error("BaseExperiment() failed to fetch base experiment");
|
|
45351
|
-
}
|
|
45352
|
-
name = baseExperiment.name;
|
|
45353
|
-
}
|
|
45354
|
-
dataResult = initExperiment2(evaluator.state, {
|
|
45355
|
-
...evaluator.projectId ? { projectId: evaluator.projectId } : { project: evaluator.projectName },
|
|
45356
|
-
experiment: name,
|
|
45357
|
-
open: true
|
|
45358
|
-
}).asDataset();
|
|
45359
|
-
}
|
|
45360
|
-
const resolvedDataResult = dataResult instanceof Promise ? await dataResult : dataResult;
|
|
45361
|
-
const dataIterable = (() => {
|
|
45362
|
-
if (isAsyncIterable7(resolvedDataResult)) {
|
|
45363
|
-
return resolvedDataResult;
|
|
45364
|
-
}
|
|
45365
|
-
if (Array.isArray(resolvedDataResult) || isIterable(resolvedDataResult)) {
|
|
45366
|
-
const iterable = resolvedDataResult;
|
|
45367
|
-
return (async function* () {
|
|
45368
|
-
for (const datum of iterable) {
|
|
45369
|
-
yield datum;
|
|
45370
|
-
}
|
|
45371
|
-
})();
|
|
45372
|
-
}
|
|
45373
|
-
throw new Error(
|
|
45374
|
-
"Evaluator data must be an array, iterable, or async iterable"
|
|
45375
|
-
);
|
|
45376
|
-
})();
|
|
46280
|
+
const dataIterable = await _internalResolveEvaluatorData(
|
|
46281
|
+
evaluator,
|
|
46282
|
+
experiment
|
|
46283
|
+
);
|
|
45377
46284
|
progressReporter.start(evaluator.evalName, 0);
|
|
45378
46285
|
const experimentIdPromise = experiment ? (async () => {
|
|
45379
46286
|
try {
|
|
@@ -45442,57 +46349,45 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
|
|
|
45442
46349
|
ensureSpansFlushed,
|
|
45443
46350
|
state
|
|
45444
46351
|
}) : void 0;
|
|
45445
|
-
let metadata = {
|
|
45446
|
-
..."metadata" in datum ? datum.metadata : {}
|
|
45447
|
-
};
|
|
46352
|
+
let metadata = {};
|
|
45448
46353
|
const expected = "expected" in datum ? datum.expected : void 0;
|
|
45449
46354
|
let output = void 0;
|
|
45450
46355
|
let error = void 0;
|
|
45451
|
-
let tags = [
|
|
45452
|
-
const scores =
|
|
45453
|
-
const classifications =
|
|
46356
|
+
let tags = [];
|
|
46357
|
+
const scores = /* @__PURE__ */ Object.create(null);
|
|
46358
|
+
const classifications = /* @__PURE__ */ Object.create(null);
|
|
45454
46359
|
const scorerNames = (evaluator.scores ?? []).map(scorerName);
|
|
45455
46360
|
const classifierNames = (evaluator.classifiers ?? []).map(
|
|
45456
46361
|
classifierName
|
|
45457
46362
|
);
|
|
45458
46363
|
let unhandledScores = scorerNames;
|
|
45459
46364
|
try {
|
|
45460
|
-
const
|
|
45461
|
-
|
|
45462
|
-
|
|
45463
|
-
|
|
45464
|
-
|
|
45465
|
-
|
|
45466
|
-
|
|
45467
|
-
|
|
45468
|
-
|
|
45469
|
-
|
|
45470
|
-
|
|
45471
|
-
|
|
45472
|
-
|
|
45473
|
-
|
|
45474
|
-
|
|
45475
|
-
object_type: "task"
|
|
45476
|
-
});
|
|
45477
|
-
},
|
|
45478
|
-
trialIndex,
|
|
45479
|
-
tags
|
|
45480
|
-
};
|
|
45481
|
-
const outputResult = evaluator.task(datum.input, hooksForTask);
|
|
45482
|
-
if (outputResult instanceof Promise) {
|
|
45483
|
-
output = await outputResult;
|
|
45484
|
-
} else {
|
|
45485
|
-
output = outputResult;
|
|
46365
|
+
const taskResult = await rootSpan.traced(
|
|
46366
|
+
(span) => _internalRunEvaluatorTask(
|
|
46367
|
+
evaluator.task,
|
|
46368
|
+
datum,
|
|
46369
|
+
trialIndex,
|
|
46370
|
+
parameters ?? {},
|
|
46371
|
+
span,
|
|
46372
|
+
(event) => {
|
|
46373
|
+
stream?.({
|
|
46374
|
+
...event,
|
|
46375
|
+
id: rootSpan.id,
|
|
46376
|
+
origin: baseEvent.event?.origin,
|
|
46377
|
+
name: evaluator.evalName,
|
|
46378
|
+
object_type: "task"
|
|
46379
|
+
});
|
|
45486
46380
|
}
|
|
45487
|
-
|
|
45488
|
-
span.log({ output });
|
|
45489
|
-
},
|
|
46381
|
+
),
|
|
45490
46382
|
{
|
|
45491
46383
|
name: "task",
|
|
45492
46384
|
spanAttributes: { type: "task" /* TASK */ },
|
|
45493
46385
|
event: { input: datum.input }
|
|
45494
46386
|
}
|
|
45495
46387
|
);
|
|
46388
|
+
output = taskResult.output;
|
|
46389
|
+
metadata = taskResult.metadata;
|
|
46390
|
+
tags = taskResult.tags;
|
|
45496
46391
|
if (tags.length) {
|
|
45497
46392
|
rootSpan.log({ output, metadata, expected, tags });
|
|
45498
46393
|
} else {
|
|
@@ -45502,20 +46397,18 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
|
|
|
45502
46397
|
await rootSpan.flush();
|
|
45503
46398
|
}
|
|
45504
46399
|
const scoringArgs = {
|
|
46400
|
+
id: datum.id,
|
|
45505
46401
|
input: datum.input,
|
|
45506
46402
|
expected: "expected" in datum ? datum.expected : void 0,
|
|
45507
46403
|
metadata,
|
|
45508
46404
|
output,
|
|
46405
|
+
tags,
|
|
45509
46406
|
trace
|
|
45510
46407
|
};
|
|
45511
46408
|
const { trace: _trace, ...scoringArgsForLogging } = scoringArgs;
|
|
45512
46409
|
const propagatedEvent = makeScorerPropagatedEvent(
|
|
45513
46410
|
await rootSpan.export()
|
|
45514
46411
|
);
|
|
45515
|
-
const getOtherFields = (s) => {
|
|
45516
|
-
const { metadata: _metadata, name: _name, ...rest } = s;
|
|
45517
|
-
return rest;
|
|
45518
|
-
};
|
|
45519
46412
|
const [scoreResults, classificationResults] = await Promise.all([
|
|
45520
46413
|
Promise.all(
|
|
45521
46414
|
(evaluator.scores ?? []).map(
|
|
@@ -45529,35 +46422,17 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
|
|
|
45529
46422
|
const scoreValue = await Promise.resolve(
|
|
45530
46423
|
score(scoringArgs)
|
|
45531
46424
|
);
|
|
45532
|
-
|
|
45533
|
-
|
|
45534
|
-
|
|
45535
|
-
if (!(typeof s === "object" && !isEmpty2(s))) {
|
|
45536
|
-
throw new Error(
|
|
45537
|
-
`When returning an array of scores, each score must be a non-empty object. Got: ${JSON.stringify(s)}`
|
|
45538
|
-
);
|
|
45539
|
-
}
|
|
45540
|
-
}
|
|
45541
|
-
}
|
|
45542
|
-
const results = Array.isArray(scoreValue) ? scoreValue : typeof scoreValue === "object" && !isEmpty2(scoreValue) ? [scoreValue] : [
|
|
45543
|
-
{
|
|
45544
|
-
name: scorerNames[score_idx],
|
|
45545
|
-
score: scoreValue
|
|
45546
|
-
}
|
|
45547
|
-
];
|
|
45548
|
-
const { resultMetadata, scoresRecord } = buildSpanScores(results);
|
|
45549
|
-
const resultOutput = results.length === 1 ? getOtherFields(results[0]) : results.reduce(
|
|
45550
|
-
(prev, s) => mergeDicts(prev, {
|
|
45551
|
-
[s.name]: getOtherFields(s)
|
|
45552
|
-
}),
|
|
45553
|
-
{}
|
|
46425
|
+
const prepared = _internalPrepareEvaluatorScore(
|
|
46426
|
+
scoreValue,
|
|
46427
|
+
scorerNames[score_idx]
|
|
45554
46428
|
);
|
|
46429
|
+
if (prepared.results === null) return null;
|
|
45555
46430
|
span.log({
|
|
45556
|
-
output:
|
|
45557
|
-
metadata:
|
|
45558
|
-
scores:
|
|
46431
|
+
output: prepared.output,
|
|
46432
|
+
metadata: prepared.metadata,
|
|
46433
|
+
scores: prepared.scores
|
|
45559
46434
|
});
|
|
45560
|
-
return results;
|
|
46435
|
+
return prepared.results;
|
|
45561
46436
|
}
|
|
45562
46437
|
)
|
|
45563
46438
|
)
|
|
@@ -45574,24 +46449,16 @@ async function runEvaluatorInternal(experiment, evaluator, progressReporter, fil
|
|
|
45574
46449
|
const classifierValue = await Promise.resolve(
|
|
45575
46450
|
classifier(scoringArgs)
|
|
45576
46451
|
);
|
|
45577
|
-
|
|
45578
|
-
|
|
45579
|
-
|
|
45580
|
-
result,
|
|
45581
|
-
classifierNames[idx]
|
|
45582
|
-
)
|
|
45583
|
-
);
|
|
45584
|
-
const resultOutput = rawResults.length === 1 ? toClassificationItem(rawResults[0]) : rawResults.reduce(
|
|
45585
|
-
(prev, r) => mergeDicts(prev, {
|
|
45586
|
-
[r.name]: toClassificationItem(r)
|
|
45587
|
-
}),
|
|
45588
|
-
{}
|
|
46452
|
+
const prepared = _internalPrepareEvaluatorClassification(
|
|
46453
|
+
classifierValue,
|
|
46454
|
+
classifierNames[idx]
|
|
45589
46455
|
);
|
|
46456
|
+
if (prepared.results === null) return null;
|
|
45590
46457
|
span.log({
|
|
45591
|
-
output:
|
|
45592
|
-
metadata:
|
|
46458
|
+
output: prepared.output,
|
|
46459
|
+
metadata: prepared.metadata
|
|
45593
46460
|
});
|
|
45594
|
-
return
|
|
46461
|
+
return prepared.results;
|
|
45595
46462
|
}
|
|
45596
46463
|
)
|
|
45597
46464
|
)
|
|
@@ -45820,7 +46687,7 @@ function accumulateScores(accumulator, scores) {
|
|
|
45820
46687
|
}
|
|
45821
46688
|
}
|
|
45822
46689
|
function ensureScoreAccumulator(results) {
|
|
45823
|
-
const accumulator =
|
|
46690
|
+
const accumulator = /* @__PURE__ */ Object.create(null);
|
|
45824
46691
|
for (const result of results) {
|
|
45825
46692
|
accumulateScores(accumulator, result.scores);
|
|
45826
46693
|
}
|
|
@@ -45963,6 +46830,1156 @@ var defaultReporter = {
|
|
|
45963
46830
|
}
|
|
45964
46831
|
};
|
|
45965
46832
|
|
|
46833
|
+
// src/durable-eval.ts
|
|
46834
|
+
var encoder = new TextEncoder();
|
|
46835
|
+
var decoder = new TextDecoder();
|
|
46836
|
+
var BATCH_TASK_KIND = "braintrust.durable.batch-task";
|
|
46837
|
+
var BATCH_SCORER_KIND = "braintrust.durable.batch-scorer";
|
|
46838
|
+
var DEFAULT_BATCH_SIZE = 1e3;
|
|
46839
|
+
var DurableEvalMemoryStore = class {
|
|
46840
|
+
values = /* @__PURE__ */ new Map();
|
|
46841
|
+
async read(key) {
|
|
46842
|
+
return this.values.get(key)?.slice();
|
|
46843
|
+
}
|
|
46844
|
+
async write(key, value) {
|
|
46845
|
+
this.values.set(key, value.slice());
|
|
46846
|
+
}
|
|
46847
|
+
async getOrSet(key, value) {
|
|
46848
|
+
const existing = this.values.get(key);
|
|
46849
|
+
if (existing) return { value: existing.slice(), created: false };
|
|
46850
|
+
this.values.set(key, value.slice());
|
|
46851
|
+
return { value: value.slice(), created: true };
|
|
46852
|
+
}
|
|
46853
|
+
};
|
|
46854
|
+
var DurableEvalRedisStore = class {
|
|
46855
|
+
client;
|
|
46856
|
+
keyPrefix;
|
|
46857
|
+
ttlMs;
|
|
46858
|
+
constructor(options) {
|
|
46859
|
+
this.client = options.client;
|
|
46860
|
+
this.keyPrefix = options.keyPrefix ?? "braintrust-eval:";
|
|
46861
|
+
this.ttlMs = options.ttlMs ?? 1e3 * 60 * 60 * 24 * 7;
|
|
46862
|
+
if (!Number.isInteger(this.ttlMs) || this.ttlMs < 1) {
|
|
46863
|
+
throw new Error("DurableEvalRedisStore ttlMs must be a positive integer");
|
|
46864
|
+
}
|
|
46865
|
+
}
|
|
46866
|
+
async read(key) {
|
|
46867
|
+
const value = await this.client.get(`${this.keyPrefix}${key}`);
|
|
46868
|
+
if (value == null) return void 0;
|
|
46869
|
+
if (typeof value !== "string") {
|
|
46870
|
+
throw new Error("DurableEvalRedisStore expected GET to return a string");
|
|
46871
|
+
}
|
|
46872
|
+
return base64ToUint8Array(value);
|
|
46873
|
+
}
|
|
46874
|
+
async write(key, value) {
|
|
46875
|
+
const client = this.client;
|
|
46876
|
+
const set = client.set;
|
|
46877
|
+
const redisKey = `${this.keyPrefix}${key}`;
|
|
46878
|
+
const encoded = uint8ArrayToBase64(value);
|
|
46879
|
+
if (typeof client.defineCommand === "function") {
|
|
46880
|
+
await set.call(client, redisKey, encoded, "PX", this.ttlMs);
|
|
46881
|
+
} else if (typeof client.sendCommand === "function") {
|
|
46882
|
+
await set.call(client, redisKey, encoded, { PX: this.ttlMs });
|
|
46883
|
+
} else if (typeof client.createScript === "function") {
|
|
46884
|
+
await set.call(client, redisKey, encoded, { px: this.ttlMs });
|
|
46885
|
+
} else {
|
|
46886
|
+
throw new Error(
|
|
46887
|
+
"DurableEvalRedisStore requires a node-redis, ioredis, or @upstash/redis client"
|
|
46888
|
+
);
|
|
46889
|
+
}
|
|
46890
|
+
}
|
|
46891
|
+
async getOrSet(key, value) {
|
|
46892
|
+
const redisKey = `${this.keyPrefix}${key}`;
|
|
46893
|
+
const encoded = uint8ArrayToBase64(value);
|
|
46894
|
+
const client = this.client;
|
|
46895
|
+
const set = client.set;
|
|
46896
|
+
let setOptions;
|
|
46897
|
+
if (typeof client.defineCommand === "function") {
|
|
46898
|
+
setOptions = ["PX", this.ttlMs, "NX", "GET"];
|
|
46899
|
+
} else if (typeof client.sendCommand === "function") {
|
|
46900
|
+
setOptions = [{ PX: this.ttlMs, NX: true, GET: true }];
|
|
46901
|
+
} else if (typeof client.createScript === "function") {
|
|
46902
|
+
setOptions = [{ px: this.ttlMs, nx: true, get: true }];
|
|
46903
|
+
} else {
|
|
46904
|
+
throw new Error(
|
|
46905
|
+
"DurableEvalRedisStore getOrSet requires a node-redis, ioredis, or @upstash/redis client"
|
|
46906
|
+
);
|
|
46907
|
+
}
|
|
46908
|
+
const existing = await set.call(client, redisKey, encoded, ...setOptions);
|
|
46909
|
+
if (existing === null) return { value: value.slice(), created: true };
|
|
46910
|
+
if (typeof existing !== "string") {
|
|
46911
|
+
throw new Error(
|
|
46912
|
+
"DurableEvalRedisStore expected atomic SET to return a string or null"
|
|
46913
|
+
);
|
|
46914
|
+
}
|
|
46915
|
+
return { value: base64ToUint8Array(existing), created: false };
|
|
46916
|
+
}
|
|
46917
|
+
};
|
|
46918
|
+
var BatchTask = class {
|
|
46919
|
+
constructor(processor) {
|
|
46920
|
+
this.processor = processor;
|
|
46921
|
+
}
|
|
46922
|
+
processor;
|
|
46923
|
+
kind = BATCH_TASK_KIND;
|
|
46924
|
+
};
|
|
46925
|
+
var BatchScorer = class {
|
|
46926
|
+
constructor(processor) {
|
|
46927
|
+
this.processor = processor;
|
|
46928
|
+
this.name = processor.name;
|
|
46929
|
+
}
|
|
46930
|
+
processor;
|
|
46931
|
+
kind = BATCH_SCORER_KIND;
|
|
46932
|
+
name;
|
|
46933
|
+
};
|
|
46934
|
+
function defineDurableEval(projectName, evaluator) {
|
|
46935
|
+
const definition = {
|
|
46936
|
+
projectName,
|
|
46937
|
+
evalName: evaluator.experimentName ?? projectName,
|
|
46938
|
+
evaluator
|
|
46939
|
+
};
|
|
46940
|
+
return {
|
|
46941
|
+
start: (options = {}) => startDurableEval(definition, options),
|
|
46942
|
+
status: (options) => getDurableEvalStatus(definition, options),
|
|
46943
|
+
poll: (options) => pollDurableEval(definition, options),
|
|
46944
|
+
processBatchResult: (result) => processDurableBatchResult(definition, result)
|
|
46945
|
+
};
|
|
46946
|
+
}
|
|
46947
|
+
async function startDurableEval(definition, options) {
|
|
46948
|
+
const store = definition.evaluator.store;
|
|
46949
|
+
const runId = newId();
|
|
46950
|
+
const key = runKey(definition.projectName, definition.evalName, runId);
|
|
46951
|
+
const { data } = callEvaluatorData(definition.evaluator.data);
|
|
46952
|
+
const parameters = await validateParameters(
|
|
46953
|
+
options.parameters ?? {},
|
|
46954
|
+
definition.evaluator.parameters
|
|
46955
|
+
);
|
|
46956
|
+
const experimentName = definition.evaluator.experimentName ?? `${definition.evalName}-${runId}`;
|
|
46957
|
+
const experiment = await _internalInitEvaluatorExperiment(
|
|
46958
|
+
definition.projectName,
|
|
46959
|
+
{ ...definition.evaluator, data },
|
|
46960
|
+
data,
|
|
46961
|
+
{
|
|
46962
|
+
disabled: options.noSendLogs ?? false,
|
|
46963
|
+
experimentName,
|
|
46964
|
+
update: true
|
|
46965
|
+
}
|
|
46966
|
+
);
|
|
46967
|
+
if (!isBatchTask(definition.evaluator.task) && !(definition.evaluator.scores ?? []).some(isBatchScorer)) {
|
|
46968
|
+
const result = await runEvaluator(
|
|
46969
|
+
experiment,
|
|
46970
|
+
{
|
|
46971
|
+
...definition.evaluator,
|
|
46972
|
+
projectName: definition.projectName,
|
|
46973
|
+
evalName: definition.evalName,
|
|
46974
|
+
data
|
|
46975
|
+
},
|
|
46976
|
+
{
|
|
46977
|
+
start: () => void 0,
|
|
46978
|
+
stop: () => void 0,
|
|
46979
|
+
increment: () => void 0
|
|
46980
|
+
},
|
|
46981
|
+
[],
|
|
46982
|
+
void 0,
|
|
46983
|
+
parameters,
|
|
46984
|
+
true,
|
|
46985
|
+
true
|
|
46986
|
+
);
|
|
46987
|
+
const state2 = {
|
|
46988
|
+
runId,
|
|
46989
|
+
experimentName,
|
|
46990
|
+
noSendLogs: options.noSendLogs ?? false,
|
|
46991
|
+
parameters: assertJsonValue(parameters, "eval parameters"),
|
|
46992
|
+
status: "completed",
|
|
46993
|
+
summary: result.summary,
|
|
46994
|
+
cases: [],
|
|
46995
|
+
batches: []
|
|
46996
|
+
};
|
|
46997
|
+
await experiment?.flush();
|
|
46998
|
+
await writeRunRecord(store, key, state2);
|
|
46999
|
+
return currentStatus(definition, state2);
|
|
47000
|
+
}
|
|
47001
|
+
const state = {
|
|
47002
|
+
runId,
|
|
47003
|
+
experimentName,
|
|
47004
|
+
noSendLogs: options.noSendLogs ?? false,
|
|
47005
|
+
parameters: assertJsonValue(parameters, "eval parameters"),
|
|
47006
|
+
status: "running",
|
|
47007
|
+
cases: await materializeCases(definition, data, experiment),
|
|
47008
|
+
batches: []
|
|
47009
|
+
};
|
|
47010
|
+
await writeCaseBaseRecords(store, key, state.cases);
|
|
47011
|
+
await writeRunRecord(store, key, state);
|
|
47012
|
+
return advanceDurableEval(definition, state, store, key, experiment);
|
|
47013
|
+
}
|
|
47014
|
+
async function getDurableEvalStatus(definition, options) {
|
|
47015
|
+
const store = definition.evaluator.store;
|
|
47016
|
+
const state = await readRunState(
|
|
47017
|
+
definition,
|
|
47018
|
+
store,
|
|
47019
|
+
runKey(definition.projectName, definition.evalName, options.runId)
|
|
47020
|
+
);
|
|
47021
|
+
if (!state) throw new Error(`Durable eval run ${options.runId} is missing`);
|
|
47022
|
+
return currentStatus(definition, state);
|
|
47023
|
+
}
|
|
47024
|
+
async function processDurableBatchResult(definition, result) {
|
|
47025
|
+
if (!result.batchId && !result.externalId) {
|
|
47026
|
+
throw new Error("Batch results require batchId or externalId");
|
|
47027
|
+
}
|
|
47028
|
+
const store = definition.evaluator.store;
|
|
47029
|
+
const key = runKey(definition.projectName, definition.evalName, result.runId);
|
|
47030
|
+
const state = await readRunState(definition, store, key);
|
|
47031
|
+
if (!state) throw new Error(`Durable eval run ${result.runId} is missing`);
|
|
47032
|
+
const byBatch = result.batchId ? state.batches.find((candidate) => candidate.id === result.batchId) : void 0;
|
|
47033
|
+
const byExternal = result.externalId ? state.batches.find(
|
|
47034
|
+
(candidate) => candidate.externalId === result.externalId
|
|
47035
|
+
) : void 0;
|
|
47036
|
+
if (byBatch && byExternal && byBatch.id !== byExternal.id) {
|
|
47037
|
+
throw new Error("batchId and externalId identify different batches");
|
|
47038
|
+
}
|
|
47039
|
+
const batch = byBatch ?? byExternal;
|
|
47040
|
+
if (!batch) throw new Error("No submitted batch matches this result");
|
|
47041
|
+
if (batch.status !== "complete") {
|
|
47042
|
+
const records = await collectBatch(definition, state, batch);
|
|
47043
|
+
batch.status = "complete";
|
|
47044
|
+
await writeCaseRecords(store, key, records);
|
|
47045
|
+
await writeBatchRecords(store, key, [batch]);
|
|
47046
|
+
}
|
|
47047
|
+
return advanceDurableEval(
|
|
47048
|
+
definition,
|
|
47049
|
+
await readRunState(definition, store, key),
|
|
47050
|
+
store,
|
|
47051
|
+
key
|
|
47052
|
+
);
|
|
47053
|
+
}
|
|
47054
|
+
async function pollDurableEval(definition, options) {
|
|
47055
|
+
const store = definition.evaluator.store;
|
|
47056
|
+
const key = runKey(
|
|
47057
|
+
definition.projectName,
|
|
47058
|
+
definition.evalName,
|
|
47059
|
+
options.runId
|
|
47060
|
+
);
|
|
47061
|
+
const state = await readRunState(definition, store, key);
|
|
47062
|
+
if (!state) throw new Error(`Durable eval run ${options.runId} is missing`);
|
|
47063
|
+
const batches = state.batches.filter((batch) => {
|
|
47064
|
+
if (batch.status === "complete") return false;
|
|
47065
|
+
return processorForStage(definition, batch.kind, batch.scorerName).completion.mode === "poll";
|
|
47066
|
+
});
|
|
47067
|
+
const results = await Promise.all(
|
|
47068
|
+
batches.map(async (batch) => ({
|
|
47069
|
+
batch,
|
|
47070
|
+
result: await processorForStage(definition, batch.kind, batch.scorerName).completion.poll(batch.submissionData, {
|
|
47071
|
+
runId: state.runId,
|
|
47072
|
+
batchId: batch.id
|
|
47073
|
+
})
|
|
47074
|
+
}))
|
|
47075
|
+
);
|
|
47076
|
+
const changedCases = /* @__PURE__ */ new Map();
|
|
47077
|
+
const changedBatches = [];
|
|
47078
|
+
for (const { batch, result } of results) {
|
|
47079
|
+
if (result.status === "failed") throw asError(result.error);
|
|
47080
|
+
if (result.status !== "complete") continue;
|
|
47081
|
+
for (const record of await collectBatch(definition, state, batch)) {
|
|
47082
|
+
changedCases.set(record.id, record);
|
|
47083
|
+
}
|
|
47084
|
+
batch.status = "complete";
|
|
47085
|
+
changedBatches.push(batch);
|
|
47086
|
+
}
|
|
47087
|
+
if (changedBatches.length > 0) {
|
|
47088
|
+
await writeCaseRecords(store, key, [...changedCases.values()]);
|
|
47089
|
+
await writeBatchRecords(store, key, changedBatches);
|
|
47090
|
+
}
|
|
47091
|
+
const currentState = changedBatches.length > 0 ? await readRunState(definition, store, key) : state;
|
|
47092
|
+
return advanceDurableEval(definition, currentState, store, key);
|
|
47093
|
+
}
|
|
47094
|
+
async function openDurableExperiment(definition, state) {
|
|
47095
|
+
const data = [];
|
|
47096
|
+
return await _internalInitEvaluatorExperiment(
|
|
47097
|
+
definition.projectName,
|
|
47098
|
+
{ ...definition.evaluator, data },
|
|
47099
|
+
data,
|
|
47100
|
+
{
|
|
47101
|
+
disabled: state.noSendLogs,
|
|
47102
|
+
experimentName: state.experimentName,
|
|
47103
|
+
update: true
|
|
47104
|
+
}
|
|
47105
|
+
);
|
|
47106
|
+
}
|
|
47107
|
+
async function advanceDurableEval(definition, state, store, key, existingExperiment) {
|
|
47108
|
+
if (state.status === "completed") return currentStatus(definition, state);
|
|
47109
|
+
const experiment = existingExperiment === void 0 ? await openDurableExperiment(definition, state) : existingExperiment;
|
|
47110
|
+
await runTaskStage(definition, state, store, key, experiment);
|
|
47111
|
+
await logCompletedTasks(definition, state, store, key, experiment);
|
|
47112
|
+
state = await readRunState(definition, store, key) ?? state;
|
|
47113
|
+
if (state.cases.some((record) => !record.taskComplete || !record.taskLogged)) {
|
|
47114
|
+
return currentStatus(definition, state);
|
|
47115
|
+
}
|
|
47116
|
+
await runScoreStages(definition, state, store, key, experiment);
|
|
47117
|
+
state = await readRunState(definition, store, key) ?? state;
|
|
47118
|
+
const scorerNames = resolveScorers(definition.evaluator.scores ?? []).map(
|
|
47119
|
+
({ name }) => name
|
|
47120
|
+
);
|
|
47121
|
+
const classifierNames = (definition.evaluator.classifiers ?? []).map(
|
|
47122
|
+
classifierName
|
|
47123
|
+
);
|
|
47124
|
+
if (state.cases.some(
|
|
47125
|
+
(record) => scorerNames.some(
|
|
47126
|
+
(name) => !Object.hasOwn(record.scores, name) || !Object.hasOwn(record.loggedScores, name)
|
|
47127
|
+
) || classifierNames.some(
|
|
47128
|
+
(name) => !Object.hasOwn(record.loggedClassifications, name)
|
|
47129
|
+
)
|
|
47130
|
+
)) {
|
|
47131
|
+
return currentStatus(definition, state);
|
|
47132
|
+
}
|
|
47133
|
+
if (!await claimAction(store, key, "finish")) {
|
|
47134
|
+
const latest = await readRunState(definition, store, key);
|
|
47135
|
+
return currentStatus(definition, latest ?? state);
|
|
47136
|
+
}
|
|
47137
|
+
state.summary = await finishExperiment(definition, state, experiment);
|
|
47138
|
+
state.status = "completed";
|
|
47139
|
+
await writeRunRecord(store, key, state);
|
|
47140
|
+
return currentStatus(definition, state);
|
|
47141
|
+
}
|
|
47142
|
+
function currentStatus(definition, state) {
|
|
47143
|
+
if (state.status === "completed") {
|
|
47144
|
+
if (!state.summary) {
|
|
47145
|
+
throw new Error(`Durable eval run ${state.runId} has no saved summary`);
|
|
47146
|
+
}
|
|
47147
|
+
return {
|
|
47148
|
+
status: "completed",
|
|
47149
|
+
runId: state.runId,
|
|
47150
|
+
pending: { poll: 0, webhook: 0 },
|
|
47151
|
+
summary: state.summary
|
|
47152
|
+
};
|
|
47153
|
+
}
|
|
47154
|
+
const pending = { poll: 0, webhook: 0 };
|
|
47155
|
+
for (const batch of state.batches) {
|
|
47156
|
+
if (batch.status === "complete") continue;
|
|
47157
|
+
pending[processorForStage(definition, batch.kind, batch.scorerName).completion.mode]++;
|
|
47158
|
+
}
|
|
47159
|
+
return { status: "waiting", runId: state.runId, pending };
|
|
47160
|
+
}
|
|
47161
|
+
async function startCaseRoot(definition, state, record, experiment) {
|
|
47162
|
+
if (!experiment) return NOOP_SPAN;
|
|
47163
|
+
const datum = record.datum;
|
|
47164
|
+
return _internalStartSpanWithInitialMerge({
|
|
47165
|
+
...definition.evaluator.state ? { state: definition.evaluator.state } : {},
|
|
47166
|
+
parent: await experiment.export(),
|
|
47167
|
+
name: "eval",
|
|
47168
|
+
spanId: deterministicId(`${state.runId}:${record.id}:span`),
|
|
47169
|
+
spanAttributes: { type: "eval" /* EVAL */ },
|
|
47170
|
+
event: {
|
|
47171
|
+
id: deterministicId(`${state.runId}:${record.id}:row`),
|
|
47172
|
+
input: datum.input,
|
|
47173
|
+
expected: "expected" in datum ? datum.expected : void 0,
|
|
47174
|
+
tags: datum.tags,
|
|
47175
|
+
origin: datum.origin
|
|
47176
|
+
}
|
|
47177
|
+
});
|
|
47178
|
+
}
|
|
47179
|
+
async function logTaskResult(definition, state, record, experiment, task) {
|
|
47180
|
+
const datum = record.datum;
|
|
47181
|
+
const root = await startCaseRoot(definition, state, record, experiment);
|
|
47182
|
+
try {
|
|
47183
|
+
if (task) {
|
|
47184
|
+
const result = await root.traced(
|
|
47185
|
+
(span) => _internalRunEvaluatorTask(
|
|
47186
|
+
task,
|
|
47187
|
+
datum,
|
|
47188
|
+
record.trialIndex,
|
|
47189
|
+
state.parameters,
|
|
47190
|
+
span
|
|
47191
|
+
),
|
|
47192
|
+
{
|
|
47193
|
+
name: "task",
|
|
47194
|
+
spanId: deterministicId(`${state.runId}:${record.id}:task`),
|
|
47195
|
+
spanAttributes: { type: "task" /* TASK */ },
|
|
47196
|
+
event: { input: datum.input }
|
|
47197
|
+
}
|
|
47198
|
+
);
|
|
47199
|
+
record.output = assertJsonValue(
|
|
47200
|
+
result.output,
|
|
47201
|
+
`task output for ${record.caseId}`
|
|
47202
|
+
);
|
|
47203
|
+
record.metadata = assertJsonValue(result.metadata, "task metadata");
|
|
47204
|
+
record.tags = result.tags;
|
|
47205
|
+
record.taskComplete = true;
|
|
47206
|
+
} else {
|
|
47207
|
+
await root.traced((span) => span.log({ output: record.output }), {
|
|
47208
|
+
name: "task",
|
|
47209
|
+
spanId: deterministicId(`${state.runId}:${record.id}:task`),
|
|
47210
|
+
spanAttributes: { type: "task" /* TASK */ },
|
|
47211
|
+
event: { input: datum.input }
|
|
47212
|
+
});
|
|
47213
|
+
}
|
|
47214
|
+
root.log({
|
|
47215
|
+
output: record.output,
|
|
47216
|
+
expected: "expected" in datum ? datum.expected : void 0,
|
|
47217
|
+
metadata: {
|
|
47218
|
+
...record.metadata,
|
|
47219
|
+
durable_eval: {
|
|
47220
|
+
run_id: state.runId,
|
|
47221
|
+
case_id: record.caseId,
|
|
47222
|
+
trial_index: record.trialIndex
|
|
47223
|
+
}
|
|
47224
|
+
},
|
|
47225
|
+
tags: record.tags
|
|
47226
|
+
});
|
|
47227
|
+
record.rootSpan = await root.export();
|
|
47228
|
+
record.taskLogged = true;
|
|
47229
|
+
} catch (error) {
|
|
47230
|
+
logError(root, error);
|
|
47231
|
+
throw error;
|
|
47232
|
+
} finally {
|
|
47233
|
+
root.end();
|
|
47234
|
+
}
|
|
47235
|
+
}
|
|
47236
|
+
async function logCompletedTasks(definition, state, store, key, experiment) {
|
|
47237
|
+
const changed = [];
|
|
47238
|
+
for (const record of state.cases) {
|
|
47239
|
+
if (!record.taskComplete || record.taskLogged) continue;
|
|
47240
|
+
if (!await claimAction(store, key, "task-log", record.id)) continue;
|
|
47241
|
+
await logTaskResult(definition, state, record, experiment);
|
|
47242
|
+
changed.push(record);
|
|
47243
|
+
}
|
|
47244
|
+
if (changed.length > 0) {
|
|
47245
|
+
await experiment?.flush();
|
|
47246
|
+
await writeCaseRecords(store, key, changed);
|
|
47247
|
+
}
|
|
47248
|
+
}
|
|
47249
|
+
async function runTaskStage(definition, state, store, key, experiment) {
|
|
47250
|
+
if (isBatchTask(definition.evaluator.task)) {
|
|
47251
|
+
await ensureBatches(definition, state, store, key, "task");
|
|
47252
|
+
return;
|
|
47253
|
+
}
|
|
47254
|
+
const task = definition.evaluator.task;
|
|
47255
|
+
const changed = [];
|
|
47256
|
+
for (const record of state.cases) {
|
|
47257
|
+
if (record.taskComplete) continue;
|
|
47258
|
+
if (!await claimAction(store, key, "task", record.id)) continue;
|
|
47259
|
+
await logTaskResult(definition, state, record, experiment, task);
|
|
47260
|
+
changed.push(record);
|
|
47261
|
+
}
|
|
47262
|
+
if (changed.length > 0) {
|
|
47263
|
+
await experiment?.flush();
|
|
47264
|
+
await writeCaseRecords(store, key, changed);
|
|
47265
|
+
}
|
|
47266
|
+
}
|
|
47267
|
+
async function runScoreStages(definition, state, store, key, experiment) {
|
|
47268
|
+
const scorers = resolveScorers(definition.evaluator.scores ?? []);
|
|
47269
|
+
const changed = /* @__PURE__ */ new Map();
|
|
47270
|
+
const persistChangedCases = async () => {
|
|
47271
|
+
if (changed.size === 0) return;
|
|
47272
|
+
await experiment?.flush();
|
|
47273
|
+
await writeCaseRecords(store, key, [...changed.values()]);
|
|
47274
|
+
changed.clear();
|
|
47275
|
+
};
|
|
47276
|
+
for (const { name, scorer } of scorers) {
|
|
47277
|
+
if (isBatchScorer(scorer)) {
|
|
47278
|
+
for (const record of state.cases) {
|
|
47279
|
+
if (Object.hasOwn(record.scores, name) && !Object.hasOwn(record.loggedScores, name)) {
|
|
47280
|
+
if (!await claimAction(store, key, "score-log", record.id, name)) {
|
|
47281
|
+
continue;
|
|
47282
|
+
}
|
|
47283
|
+
await evaluateAndLogScore(
|
|
47284
|
+
definition,
|
|
47285
|
+
state,
|
|
47286
|
+
record,
|
|
47287
|
+
name,
|
|
47288
|
+
experiment
|
|
47289
|
+
);
|
|
47290
|
+
changed.set(record.id, record);
|
|
47291
|
+
}
|
|
47292
|
+
}
|
|
47293
|
+
await persistChangedCases();
|
|
47294
|
+
await ensureBatches(definition, state, store, key, "score", name);
|
|
47295
|
+
continue;
|
|
47296
|
+
}
|
|
47297
|
+
for (const record of state.cases) {
|
|
47298
|
+
if (Object.hasOwn(record.loggedScores, name)) continue;
|
|
47299
|
+
if (!await claimAction(store, key, "score", record.id, name)) continue;
|
|
47300
|
+
await evaluateAndLogScore(
|
|
47301
|
+
definition,
|
|
47302
|
+
state,
|
|
47303
|
+
record,
|
|
47304
|
+
name,
|
|
47305
|
+
experiment,
|
|
47306
|
+
scorer
|
|
47307
|
+
);
|
|
47308
|
+
changed.set(record.id, record);
|
|
47309
|
+
}
|
|
47310
|
+
}
|
|
47311
|
+
for (const [index, classifier] of (definition.evaluator.classifiers ?? []).entries()) {
|
|
47312
|
+
const name = classifierName(classifier, index);
|
|
47313
|
+
for (const record of state.cases) {
|
|
47314
|
+
if (Object.hasOwn(record.loggedClassifications, name)) continue;
|
|
47315
|
+
if (!await claimAction(store, key, "classification", record.id, name)) {
|
|
47316
|
+
continue;
|
|
47317
|
+
}
|
|
47318
|
+
await evaluateAndLogClassification(
|
|
47319
|
+
definition,
|
|
47320
|
+
state,
|
|
47321
|
+
record,
|
|
47322
|
+
name,
|
|
47323
|
+
classifier,
|
|
47324
|
+
experiment
|
|
47325
|
+
);
|
|
47326
|
+
changed.set(record.id, record);
|
|
47327
|
+
}
|
|
47328
|
+
}
|
|
47329
|
+
await persistChangedCases();
|
|
47330
|
+
}
|
|
47331
|
+
function scorerArgs(record) {
|
|
47332
|
+
const datum = record.datum;
|
|
47333
|
+
return {
|
|
47334
|
+
...datum,
|
|
47335
|
+
metadata: record.metadata,
|
|
47336
|
+
output: record.output
|
|
47337
|
+
};
|
|
47338
|
+
}
|
|
47339
|
+
function resumeCaseRoot(definition, record, experiment) {
|
|
47340
|
+
if (!experiment) return NOOP_SPAN;
|
|
47341
|
+
if (!record.rootSpan) {
|
|
47342
|
+
throw new Error(`Durable eval case ${record.caseId} has no root span`);
|
|
47343
|
+
}
|
|
47344
|
+
return _internalResumeSpan({
|
|
47345
|
+
exported: record.rootSpan,
|
|
47346
|
+
state: definition.evaluator.state
|
|
47347
|
+
});
|
|
47348
|
+
}
|
|
47349
|
+
async function evaluateAndLogScore(definition, state, record, name, experiment, scorer) {
|
|
47350
|
+
const root = resumeCaseRoot(definition, record, experiment);
|
|
47351
|
+
try {
|
|
47352
|
+
const rootExport = await root.export();
|
|
47353
|
+
const prepared = await root.traced(
|
|
47354
|
+
async (span) => {
|
|
47355
|
+
const value = scorer ? await scorer(scorerArgs(record)) : record.scores[name];
|
|
47356
|
+
if (scorer) {
|
|
47357
|
+
record.scores[name] = assertJsonValue(value, `scorer ${name} output`);
|
|
47358
|
+
}
|
|
47359
|
+
const result = _internalPrepareEvaluatorScore(value, name);
|
|
47360
|
+
if (result.results !== null) {
|
|
47361
|
+
span.log({
|
|
47362
|
+
output: result.output,
|
|
47363
|
+
metadata: result.metadata,
|
|
47364
|
+
scores: result.scores
|
|
47365
|
+
});
|
|
47366
|
+
}
|
|
47367
|
+
return result;
|
|
47368
|
+
},
|
|
47369
|
+
{
|
|
47370
|
+
name,
|
|
47371
|
+
spanId: deterministicId(`${state.runId}:${record.id}:score:${name}`),
|
|
47372
|
+
spanAttributes: {
|
|
47373
|
+
type: "score" /* SCORE */,
|
|
47374
|
+
purpose: "scorer"
|
|
47375
|
+
},
|
|
47376
|
+
propagatedEvent: makeScorerPropagatedEvent(rootExport || void 0),
|
|
47377
|
+
event: { input: scorerArgs(record) }
|
|
47378
|
+
}
|
|
47379
|
+
);
|
|
47380
|
+
if (prepared.scores) root.log({ scores: prepared.scores });
|
|
47381
|
+
record.loggedScores[name] = true;
|
|
47382
|
+
} catch (error) {
|
|
47383
|
+
logError(root, error);
|
|
47384
|
+
throw error;
|
|
47385
|
+
} finally {
|
|
47386
|
+
root.end();
|
|
47387
|
+
}
|
|
47388
|
+
}
|
|
47389
|
+
async function evaluateAndLogClassification(definition, state, record, name, classifier, experiment) {
|
|
47390
|
+
const root = resumeCaseRoot(definition, record, experiment);
|
|
47391
|
+
try {
|
|
47392
|
+
const rootExport = await root.export();
|
|
47393
|
+
const prepared = await root.traced(
|
|
47394
|
+
async (span) => {
|
|
47395
|
+
const value = await classifier(scorerArgs(record));
|
|
47396
|
+
record.classifications[name] = assertJsonValue(
|
|
47397
|
+
value,
|
|
47398
|
+
`classifier ${name} output`
|
|
47399
|
+
);
|
|
47400
|
+
const result = _internalPrepareEvaluatorClassification(value, name);
|
|
47401
|
+
if (result.results !== null) {
|
|
47402
|
+
span.log({ output: result.output, metadata: result.metadata });
|
|
47403
|
+
}
|
|
47404
|
+
return result;
|
|
47405
|
+
},
|
|
47406
|
+
{
|
|
47407
|
+
name,
|
|
47408
|
+
spanId: deterministicId(
|
|
47409
|
+
`${state.runId}:${record.id}:classification:${name}`
|
|
47410
|
+
),
|
|
47411
|
+
spanAttributes: {
|
|
47412
|
+
type: "classifier" /* CLASSIFIER */,
|
|
47413
|
+
purpose: "scorer"
|
|
47414
|
+
},
|
|
47415
|
+
propagatedEvent: makeScorerPropagatedEvent(rootExport || void 0),
|
|
47416
|
+
event: { input: scorerArgs(record) }
|
|
47417
|
+
}
|
|
47418
|
+
);
|
|
47419
|
+
if (prepared.classifications) {
|
|
47420
|
+
root.log({ classifications: prepared.classifications });
|
|
47421
|
+
}
|
|
47422
|
+
record.loggedClassifications[name] = true;
|
|
47423
|
+
} catch (error) {
|
|
47424
|
+
logError(root, error);
|
|
47425
|
+
throw error;
|
|
47426
|
+
} finally {
|
|
47427
|
+
root.end();
|
|
47428
|
+
}
|
|
47429
|
+
}
|
|
47430
|
+
async function ensureBatches(definition, state, store, key, kind, scorerName2) {
|
|
47431
|
+
const processor = processorForStage(definition, kind, scorerName2);
|
|
47432
|
+
const plans = plannedBatches(
|
|
47433
|
+
definition,
|
|
47434
|
+
state.runId,
|
|
47435
|
+
state.cases.map(({ id }) => id)
|
|
47436
|
+
);
|
|
47437
|
+
const casesById = new Map(state.cases.map((record) => [record.id, record]));
|
|
47438
|
+
for (const plan of plans) {
|
|
47439
|
+
if (plan.kind !== kind || plan.scorerName !== scorerName2) continue;
|
|
47440
|
+
if (state.batches.some(({ id }) => id === plan.id)) continue;
|
|
47441
|
+
const records = plan.itemIds.map((id) => casesById.get(id));
|
|
47442
|
+
const ready = records.every(
|
|
47443
|
+
(record) => kind === "task" ? !record.taskComplete : !Object.hasOwn(record.scores, scorerName2)
|
|
47444
|
+
);
|
|
47445
|
+
if (!ready) continue;
|
|
47446
|
+
const batchId = plan.id;
|
|
47447
|
+
const claim = await store.getOrSet(
|
|
47448
|
+
claimRecordKey(key, "batch", batchId),
|
|
47449
|
+
encoder.encode(batchId)
|
|
47450
|
+
);
|
|
47451
|
+
if (!claim.created) continue;
|
|
47452
|
+
const context = { runId: state.runId, batchId };
|
|
47453
|
+
const items = records.map(
|
|
47454
|
+
(record) => kind === "task" ? taskBatchItem(record, state.parameters) : scorerBatchItem(record)
|
|
47455
|
+
);
|
|
47456
|
+
const submissionData = assertJsonValue(
|
|
47457
|
+
await processor.submit(items, context),
|
|
47458
|
+
`submission data for batch ${batchId}`
|
|
47459
|
+
);
|
|
47460
|
+
const externalId = processor.completion.mode === "webhook" ? processor.completion.getExternalId(submissionData, context) : void 0;
|
|
47461
|
+
if (externalId !== void 0 && !externalId.trim()) {
|
|
47462
|
+
throw new Error(`Batch ${batchId} produced an empty externalId`);
|
|
47463
|
+
}
|
|
47464
|
+
const batch = {
|
|
47465
|
+
id: batchId,
|
|
47466
|
+
kind,
|
|
47467
|
+
scorerName: scorerName2,
|
|
47468
|
+
itemIds: records.map((record) => record.id),
|
|
47469
|
+
submissionData,
|
|
47470
|
+
externalId,
|
|
47471
|
+
status: "submitted"
|
|
47472
|
+
};
|
|
47473
|
+
state.batches.push(batch);
|
|
47474
|
+
await writeBatchRecords(store, key, [batch]);
|
|
47475
|
+
}
|
|
47476
|
+
}
|
|
47477
|
+
async function collectBatch(definition, state, batch) {
|
|
47478
|
+
const processor = processorForStage(definition, batch.kind, batch.scorerName);
|
|
47479
|
+
const context = { runId: state.runId, batchId: batch.id };
|
|
47480
|
+
const results = await processor.collect(batch.submissionData, context);
|
|
47481
|
+
if (!Array.isArray(results)) {
|
|
47482
|
+
throw new Error(`collect for batch ${batch.id} must return an array`);
|
|
47483
|
+
}
|
|
47484
|
+
const expectedIds = new Set(batch.itemIds);
|
|
47485
|
+
const seen = /* @__PURE__ */ new Set();
|
|
47486
|
+
const records = [];
|
|
47487
|
+
for (const result of results) {
|
|
47488
|
+
const id = resultItemId(result);
|
|
47489
|
+
if (!expectedIds.has(id)) {
|
|
47490
|
+
throw new Error(`Batch ${batch.id} returned unknown item ${id}`);
|
|
47491
|
+
}
|
|
47492
|
+
if (seen.has(id)) {
|
|
47493
|
+
throw new Error(`Batch ${batch.id} returned item ${id} more than once`);
|
|
47494
|
+
}
|
|
47495
|
+
seen.add(id);
|
|
47496
|
+
const record = state.cases.find((candidate) => candidate.id === id);
|
|
47497
|
+
records.push(record);
|
|
47498
|
+
if (batch.kind === "task") {
|
|
47499
|
+
record.output = assertJsonValue(
|
|
47500
|
+
result.output,
|
|
47501
|
+
`task output for item ${id}`
|
|
47502
|
+
);
|
|
47503
|
+
if ("metadata" in result && result.metadata !== void 0) {
|
|
47504
|
+
record.metadata = assertJsonValue(
|
|
47505
|
+
{
|
|
47506
|
+
...record.metadata,
|
|
47507
|
+
...result.metadata
|
|
47508
|
+
},
|
|
47509
|
+
`metadata for ${id}`
|
|
47510
|
+
);
|
|
47511
|
+
}
|
|
47512
|
+
if ("tags" in result && result.tags !== void 0)
|
|
47513
|
+
record.tags = result.tags;
|
|
47514
|
+
record.taskComplete = true;
|
|
47515
|
+
} else {
|
|
47516
|
+
record.scores[batch.scorerName] = assertJsonValue(
|
|
47517
|
+
result.score,
|
|
47518
|
+
`score output for item ${id}`
|
|
47519
|
+
);
|
|
47520
|
+
}
|
|
47521
|
+
}
|
|
47522
|
+
const missing = batch.itemIds.filter((id) => !seen.has(id));
|
|
47523
|
+
if (missing.length > 0) {
|
|
47524
|
+
throw new Error(
|
|
47525
|
+
`Batch ${batch.id} did not return results for: ${missing.join(", ")}`
|
|
47526
|
+
);
|
|
47527
|
+
}
|
|
47528
|
+
return records;
|
|
47529
|
+
}
|
|
47530
|
+
function processorForStage(definition, kind, scorerName2) {
|
|
47531
|
+
if (kind === "task") {
|
|
47532
|
+
if (!isBatchTask(definition.evaluator.task)) {
|
|
47533
|
+
throw new Error("Definition no longer contains the batch task");
|
|
47534
|
+
}
|
|
47535
|
+
return definition.evaluator.task.processor;
|
|
47536
|
+
}
|
|
47537
|
+
const scorer = resolveScorers(definition.evaluator.scores ?? []).find(
|
|
47538
|
+
({ name }) => name === scorerName2
|
|
47539
|
+
)?.scorer;
|
|
47540
|
+
if (!isBatchScorer(scorer)) {
|
|
47541
|
+
throw new Error(`Definition no longer contains scorer ${scorerName2}`);
|
|
47542
|
+
}
|
|
47543
|
+
return scorer.processor;
|
|
47544
|
+
}
|
|
47545
|
+
async function materializeCases(definition, data, experiment) {
|
|
47546
|
+
const evaluator = definition.evaluator;
|
|
47547
|
+
const iterable = await _internalResolveEvaluatorData(
|
|
47548
|
+
{
|
|
47549
|
+
data,
|
|
47550
|
+
projectName: definition.projectName,
|
|
47551
|
+
projectId: evaluator.projectId,
|
|
47552
|
+
state: evaluator.state
|
|
47553
|
+
},
|
|
47554
|
+
experiment
|
|
47555
|
+
);
|
|
47556
|
+
const records = [];
|
|
47557
|
+
const seen = /* @__PURE__ */ new Set();
|
|
47558
|
+
for await (const datum of iterable) {
|
|
47559
|
+
const caseId = datum.id ?? datum.upsert_id ?? (evaluator.caseId ? await evaluator.caseId(datum) : void 0);
|
|
47560
|
+
if (!caseId) {
|
|
47561
|
+
throw new Error(
|
|
47562
|
+
"Every durable eval case requires id, upsert_id, or caseId"
|
|
47563
|
+
);
|
|
47564
|
+
}
|
|
47565
|
+
if (seen.has(caseId))
|
|
47566
|
+
throw new Error(`Duplicate durable eval case id: ${caseId}`);
|
|
47567
|
+
seen.add(caseId);
|
|
47568
|
+
const trialCount = datum.trialCount ?? evaluator.trialCount ?? 1;
|
|
47569
|
+
if (!Number.isInteger(trialCount) || trialCount < 1) {
|
|
47570
|
+
throw new Error(`Invalid trialCount for durable eval case ${caseId}`);
|
|
47571
|
+
}
|
|
47572
|
+
for (let trialIndex = 0; trialIndex < trialCount; trialIndex++) {
|
|
47573
|
+
records.push({
|
|
47574
|
+
id: `${caseId}:trial:${trialIndex}`,
|
|
47575
|
+
caseId,
|
|
47576
|
+
trialIndex,
|
|
47577
|
+
datum: assertJsonValue(datum, `case ${caseId}`),
|
|
47578
|
+
metadata: assertJsonValue(
|
|
47579
|
+
"metadata" in datum ? datum.metadata : {},
|
|
47580
|
+
`metadata for ${caseId}`
|
|
47581
|
+
),
|
|
47582
|
+
tags: datum.tags,
|
|
47583
|
+
taskComplete: false,
|
|
47584
|
+
taskLogged: false,
|
|
47585
|
+
scores: /* @__PURE__ */ Object.create(null),
|
|
47586
|
+
loggedScores: /* @__PURE__ */ Object.create(null),
|
|
47587
|
+
classifications: /* @__PURE__ */ Object.create(null),
|
|
47588
|
+
loggedClassifications: /* @__PURE__ */ Object.create(null)
|
|
47589
|
+
});
|
|
47590
|
+
}
|
|
47591
|
+
}
|
|
47592
|
+
return records;
|
|
47593
|
+
}
|
|
47594
|
+
function taskBatchItem(record, parameters) {
|
|
47595
|
+
const datum = record.datum;
|
|
47596
|
+
return {
|
|
47597
|
+
id: record.id,
|
|
47598
|
+
input: datum.input,
|
|
47599
|
+
expected: "expected" in datum ? datum.expected : void 0,
|
|
47600
|
+
metadata: record.metadata,
|
|
47601
|
+
tags: record.tags,
|
|
47602
|
+
parameters,
|
|
47603
|
+
trialIndex: record.trialIndex
|
|
47604
|
+
};
|
|
47605
|
+
}
|
|
47606
|
+
function scorerBatchItem(record) {
|
|
47607
|
+
const datum = record.datum;
|
|
47608
|
+
return {
|
|
47609
|
+
id: record.id,
|
|
47610
|
+
input: datum.input,
|
|
47611
|
+
output: record.output,
|
|
47612
|
+
expected: "expected" in datum ? datum.expected : void 0,
|
|
47613
|
+
metadata: record.metadata,
|
|
47614
|
+
tags: record.tags,
|
|
47615
|
+
trialIndex: record.trialIndex
|
|
47616
|
+
};
|
|
47617
|
+
}
|
|
47618
|
+
async function finishExperiment(definition, state, experiment) {
|
|
47619
|
+
const scorerNames = resolveScorers(definition.evaluator.scores ?? []).map(
|
|
47620
|
+
({ name }) => name
|
|
47621
|
+
);
|
|
47622
|
+
const results = state.cases.map((record) => {
|
|
47623
|
+
const datum = record.datum;
|
|
47624
|
+
const scores = Object.fromEntries(
|
|
47625
|
+
scorerNames.flatMap(
|
|
47626
|
+
(name) => Object.entries(
|
|
47627
|
+
_internalPrepareEvaluatorScore(
|
|
47628
|
+
record.scores[name],
|
|
47629
|
+
name
|
|
47630
|
+
).scores ?? {}
|
|
47631
|
+
)
|
|
47632
|
+
)
|
|
47633
|
+
);
|
|
47634
|
+
const classifications = Object.fromEntries(
|
|
47635
|
+
Object.entries(record.classifications).flatMap(
|
|
47636
|
+
([name, value]) => Object.entries(
|
|
47637
|
+
_internalPrepareEvaluatorClassification(value, name).classifications ?? {}
|
|
47638
|
+
)
|
|
47639
|
+
)
|
|
47640
|
+
);
|
|
47641
|
+
return {
|
|
47642
|
+
...datum,
|
|
47643
|
+
output: record.output,
|
|
47644
|
+
metadata: record.metadata,
|
|
47645
|
+
tags: record.tags,
|
|
47646
|
+
scores,
|
|
47647
|
+
error: void 0,
|
|
47648
|
+
...Object.keys(classifications).length > 0 ? { classifications } : {}
|
|
47649
|
+
};
|
|
47650
|
+
});
|
|
47651
|
+
if (!experiment) {
|
|
47652
|
+
return buildLocalSummary(
|
|
47653
|
+
{
|
|
47654
|
+
...definition.evaluator,
|
|
47655
|
+
projectName: definition.projectName,
|
|
47656
|
+
evalName: state.experimentName
|
|
47657
|
+
},
|
|
47658
|
+
results
|
|
47659
|
+
);
|
|
47660
|
+
}
|
|
47661
|
+
await experiment.flush();
|
|
47662
|
+
let comparisonExperimentId = definition.evaluator.baseExperimentId;
|
|
47663
|
+
if (!comparisonExperimentId) {
|
|
47664
|
+
try {
|
|
47665
|
+
comparisonExperimentId = await experiment._getBaseExperimentId();
|
|
47666
|
+
} catch {
|
|
47667
|
+
comparisonExperimentId = void 0;
|
|
47668
|
+
}
|
|
47669
|
+
}
|
|
47670
|
+
return await experiment.summarize({
|
|
47671
|
+
summarizeScores: definition.evaluator.summarizeScores,
|
|
47672
|
+
...comparisonExperimentId ? { comparisonExperimentId } : {}
|
|
47673
|
+
});
|
|
47674
|
+
}
|
|
47675
|
+
function resolveScorers(scorers) {
|
|
47676
|
+
return scorers.map((scorer, index) => ({
|
|
47677
|
+
name: isBatchScorer(scorer) ? scorer.name : scorer.name || `scorer_${index}`,
|
|
47678
|
+
scorer
|
|
47679
|
+
}));
|
|
47680
|
+
}
|
|
47681
|
+
function runKey(projectName, evalName, runId) {
|
|
47682
|
+
return `durable-eval/v1/runs/${contentVersion(encoder.encode(`${projectName}\0${evalName}\0${runId}`))}`;
|
|
47683
|
+
}
|
|
47684
|
+
function encodedKeyPart(value) {
|
|
47685
|
+
return uint8ArrayToBase64(encoder.encode(value)).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/, "");
|
|
47686
|
+
}
|
|
47687
|
+
function caseRecordKey(key, caseId, kind, ...names) {
|
|
47688
|
+
const suffix = names.map(encodedKeyPart).join("/");
|
|
47689
|
+
return `${key}/cases/${encodedKeyPart(caseId)}/${kind}${suffix ? `/${suffix}` : ""}`;
|
|
47690
|
+
}
|
|
47691
|
+
function batchRecordKey(key, batchId) {
|
|
47692
|
+
return `${key}/batches/${encodedKeyPart(batchId)}`;
|
|
47693
|
+
}
|
|
47694
|
+
function claimRecordKey(key, kind, ...parts) {
|
|
47695
|
+
const identity = stableStringify([kind, parts]);
|
|
47696
|
+
return `${key}/claims/${contentVersion(encoder.encode(identity))}`;
|
|
47697
|
+
}
|
|
47698
|
+
async function claimAction(store, key, kind, ...parts) {
|
|
47699
|
+
return (await store.getOrSet(
|
|
47700
|
+
claimRecordKey(key, kind, ...parts),
|
|
47701
|
+
encoder.encode("claimed")
|
|
47702
|
+
)).created;
|
|
47703
|
+
}
|
|
47704
|
+
function plannedBatches(definition, runId, caseIds) {
|
|
47705
|
+
const stages = [];
|
|
47706
|
+
if (isBatchTask(definition.evaluator.task)) stages.push({ kind: "task" });
|
|
47707
|
+
for (const { name, scorer } of resolveScorers(
|
|
47708
|
+
definition.evaluator.scores ?? []
|
|
47709
|
+
)) {
|
|
47710
|
+
if (isBatchScorer(scorer)) {
|
|
47711
|
+
stages.push({ kind: "score", scorerName: name });
|
|
47712
|
+
}
|
|
47713
|
+
}
|
|
47714
|
+
const plans = [];
|
|
47715
|
+
for (const { kind, scorerName: scorerName2 } of stages) {
|
|
47716
|
+
const batchSize = processorForStage(definition, kind, scorerName2).batchSize ?? DEFAULT_BATCH_SIZE;
|
|
47717
|
+
if (!Number.isInteger(batchSize) || batchSize < 1) {
|
|
47718
|
+
throw new Error(
|
|
47719
|
+
`Invalid batchSize for ${scorerName2 ?? "task"}: ${batchSize}`
|
|
47720
|
+
);
|
|
47721
|
+
}
|
|
47722
|
+
for (let offset = 0; offset < caseIds.length; offset += batchSize) {
|
|
47723
|
+
const itemIds = caseIds.slice(offset, offset + batchSize);
|
|
47724
|
+
plans.push({
|
|
47725
|
+
id: deterministicId(
|
|
47726
|
+
stableStringify([runId, kind, scorerName2, itemIds])
|
|
47727
|
+
),
|
|
47728
|
+
kind,
|
|
47729
|
+
scorerName: scorerName2,
|
|
47730
|
+
itemIds
|
|
47731
|
+
});
|
|
47732
|
+
}
|
|
47733
|
+
}
|
|
47734
|
+
return plans;
|
|
47735
|
+
}
|
|
47736
|
+
async function readCaseRecord(definition, store, key, id) {
|
|
47737
|
+
const scorers = resolveScorers(definition.evaluator.scores ?? []);
|
|
47738
|
+
const classifiers = (definition.evaluator.classifiers ?? []).map(
|
|
47739
|
+
classifierName
|
|
47740
|
+
);
|
|
47741
|
+
const [
|
|
47742
|
+
base,
|
|
47743
|
+
task,
|
|
47744
|
+
taskLog,
|
|
47745
|
+
scoreValues,
|
|
47746
|
+
scoreLogValues,
|
|
47747
|
+
classificationValues,
|
|
47748
|
+
classificationLogValues
|
|
47749
|
+
] = await Promise.all([
|
|
47750
|
+
readJson(store, caseRecordKey(key, id, "base")),
|
|
47751
|
+
readJson(store, caseRecordKey(key, id, "task")),
|
|
47752
|
+
readJson(store, caseRecordKey(key, id, "task-log")),
|
|
47753
|
+
Promise.all(
|
|
47754
|
+
scorers.map(async ({ name }) => ({
|
|
47755
|
+
name,
|
|
47756
|
+
value: await readJson(
|
|
47757
|
+
store,
|
|
47758
|
+
caseRecordKey(key, id, "score", name)
|
|
47759
|
+
)
|
|
47760
|
+
}))
|
|
47761
|
+
),
|
|
47762
|
+
Promise.all(
|
|
47763
|
+
scorers.map(async ({ name }) => ({
|
|
47764
|
+
name,
|
|
47765
|
+
value: await readJson(
|
|
47766
|
+
store,
|
|
47767
|
+
caseRecordKey(key, id, "score-log", name)
|
|
47768
|
+
)
|
|
47769
|
+
}))
|
|
47770
|
+
),
|
|
47771
|
+
Promise.all(
|
|
47772
|
+
classifiers.map(async (name) => ({
|
|
47773
|
+
name,
|
|
47774
|
+
value: await readJson(
|
|
47775
|
+
store,
|
|
47776
|
+
caseRecordKey(key, id, "classification", name)
|
|
47777
|
+
)
|
|
47778
|
+
}))
|
|
47779
|
+
),
|
|
47780
|
+
Promise.all(
|
|
47781
|
+
classifiers.map(async (name) => ({
|
|
47782
|
+
name,
|
|
47783
|
+
value: await readJson(
|
|
47784
|
+
store,
|
|
47785
|
+
caseRecordKey(key, id, "classification-log", name)
|
|
47786
|
+
)
|
|
47787
|
+
}))
|
|
47788
|
+
)
|
|
47789
|
+
]);
|
|
47790
|
+
if (!base) throw new Error(`Durable eval case ${id} is missing`);
|
|
47791
|
+
const scores = /* @__PURE__ */ Object.create(null);
|
|
47792
|
+
for (const { name, value } of scoreValues) {
|
|
47793
|
+
if (value !== void 0) scores[name] = value;
|
|
47794
|
+
}
|
|
47795
|
+
const loggedScores = /* @__PURE__ */ Object.create(null);
|
|
47796
|
+
for (const { name, value } of scoreLogValues) {
|
|
47797
|
+
if (value) loggedScores[name] = true;
|
|
47798
|
+
}
|
|
47799
|
+
const classifications = /* @__PURE__ */ Object.create(null);
|
|
47800
|
+
for (const { name, value } of classificationValues) {
|
|
47801
|
+
if (value !== void 0) classifications[name] = value;
|
|
47802
|
+
}
|
|
47803
|
+
const loggedClassifications = /* @__PURE__ */ Object.create(null);
|
|
47804
|
+
for (const { name, value } of classificationLogValues) {
|
|
47805
|
+
if (value) loggedClassifications[name] = true;
|
|
47806
|
+
}
|
|
47807
|
+
return {
|
|
47808
|
+
...base,
|
|
47809
|
+
metadata: task?.metadata ?? base.metadata,
|
|
47810
|
+
tags: task ? task.tags : base.tags,
|
|
47811
|
+
taskComplete: task !== void 0,
|
|
47812
|
+
taskLogged: taskLog !== void 0,
|
|
47813
|
+
output: task?.output,
|
|
47814
|
+
rootSpan: taskLog?.rootSpan,
|
|
47815
|
+
scores,
|
|
47816
|
+
loggedScores,
|
|
47817
|
+
classifications,
|
|
47818
|
+
loggedClassifications
|
|
47819
|
+
};
|
|
47820
|
+
}
|
|
47821
|
+
async function readRunState(definition, store, key) {
|
|
47822
|
+
const record = await readJson(store, key);
|
|
47823
|
+
if (!record) return void 0;
|
|
47824
|
+
const plans = plannedBatches(definition, record.runId, record.caseIds);
|
|
47825
|
+
const [cases, batchRecords] = await Promise.all([
|
|
47826
|
+
Promise.all(
|
|
47827
|
+
record.caseIds.map((id) => readCaseRecord(definition, store, key, id))
|
|
47828
|
+
),
|
|
47829
|
+
Promise.all(
|
|
47830
|
+
plans.map(async ({ id }) => {
|
|
47831
|
+
return readJson(store, batchRecordKey(key, id));
|
|
47832
|
+
})
|
|
47833
|
+
)
|
|
47834
|
+
]);
|
|
47835
|
+
const batches = batchRecords.filter(
|
|
47836
|
+
(value) => value !== void 0
|
|
47837
|
+
);
|
|
47838
|
+
const { caseIds: _caseIds, ...state } = record;
|
|
47839
|
+
return { ...state, cases, batches };
|
|
47840
|
+
}
|
|
47841
|
+
async function writeRunRecord(store, key, state) {
|
|
47842
|
+
const { cases, batches: _batches, ...record } = state;
|
|
47843
|
+
await writeJson(store, key, {
|
|
47844
|
+
...record,
|
|
47845
|
+
caseIds: cases.map(({ id }) => id)
|
|
47846
|
+
});
|
|
47847
|
+
}
|
|
47848
|
+
async function writeCaseBaseRecords(store, key, records) {
|
|
47849
|
+
await Promise.all(
|
|
47850
|
+
records.map(
|
|
47851
|
+
({ id, caseId, trialIndex, datum, metadata, tags }) => writeJson(store, caseRecordKey(key, id, "base"), {
|
|
47852
|
+
id,
|
|
47853
|
+
caseId,
|
|
47854
|
+
trialIndex,
|
|
47855
|
+
datum,
|
|
47856
|
+
metadata,
|
|
47857
|
+
tags
|
|
47858
|
+
})
|
|
47859
|
+
)
|
|
47860
|
+
);
|
|
47861
|
+
}
|
|
47862
|
+
async function writeCaseRecords(store, key, records) {
|
|
47863
|
+
const writes = [];
|
|
47864
|
+
for (const record of records) {
|
|
47865
|
+
if (record.taskComplete) {
|
|
47866
|
+
writes.push(
|
|
47867
|
+
writeJson(store, caseRecordKey(key, record.id, "task"), {
|
|
47868
|
+
output: record.output,
|
|
47869
|
+
metadata: record.metadata,
|
|
47870
|
+
tags: record.tags,
|
|
47871
|
+
taskComplete: true
|
|
47872
|
+
})
|
|
47873
|
+
);
|
|
47874
|
+
}
|
|
47875
|
+
if (record.taskLogged) {
|
|
47876
|
+
writes.push(
|
|
47877
|
+
writeJson(store, caseRecordKey(key, record.id, "task-log"), {
|
|
47878
|
+
rootSpan: record.rootSpan,
|
|
47879
|
+
taskLogged: true
|
|
47880
|
+
})
|
|
47881
|
+
);
|
|
47882
|
+
}
|
|
47883
|
+
for (const [name, value] of Object.entries(record.scores)) {
|
|
47884
|
+
writes.push(
|
|
47885
|
+
writeJson(store, caseRecordKey(key, record.id, "score", name), value)
|
|
47886
|
+
);
|
|
47887
|
+
}
|
|
47888
|
+
for (const name of Object.keys(record.loggedScores)) {
|
|
47889
|
+
writes.push(
|
|
47890
|
+
writeJson(
|
|
47891
|
+
store,
|
|
47892
|
+
caseRecordKey(key, record.id, "score-log", name),
|
|
47893
|
+
true
|
|
47894
|
+
)
|
|
47895
|
+
);
|
|
47896
|
+
}
|
|
47897
|
+
for (const [name, value] of Object.entries(record.classifications)) {
|
|
47898
|
+
writes.push(
|
|
47899
|
+
writeJson(
|
|
47900
|
+
store,
|
|
47901
|
+
caseRecordKey(key, record.id, "classification", name),
|
|
47902
|
+
value
|
|
47903
|
+
)
|
|
47904
|
+
);
|
|
47905
|
+
}
|
|
47906
|
+
for (const name of Object.keys(record.loggedClassifications)) {
|
|
47907
|
+
writes.push(
|
|
47908
|
+
writeJson(
|
|
47909
|
+
store,
|
|
47910
|
+
caseRecordKey(key, record.id, "classification-log", name),
|
|
47911
|
+
true
|
|
47912
|
+
)
|
|
47913
|
+
);
|
|
47914
|
+
}
|
|
47915
|
+
}
|
|
47916
|
+
await Promise.all(writes);
|
|
47917
|
+
}
|
|
47918
|
+
async function writeBatchRecords(store, key, records) {
|
|
47919
|
+
await Promise.all(
|
|
47920
|
+
records.map(
|
|
47921
|
+
(record) => writeJson(store, batchRecordKey(key, record.id), record)
|
|
47922
|
+
)
|
|
47923
|
+
);
|
|
47924
|
+
}
|
|
47925
|
+
function deterministicId(value) {
|
|
47926
|
+
const hex = contentVersion(encoder.encode(value)).padEnd(32, "0").slice(0, 32);
|
|
47927
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-5${hex.slice(13, 16)}-a${hex.slice(17, 20)}-${hex.slice(20, 32)}`;
|
|
47928
|
+
}
|
|
47929
|
+
function contentVersion(value) {
|
|
47930
|
+
if (isomorph_default.hash) return isomorph_default.hash(decoder.decode(value));
|
|
47931
|
+
let hash = 2166136261;
|
|
47932
|
+
for (const byte of value) {
|
|
47933
|
+
hash ^= byte;
|
|
47934
|
+
hash = Math.imul(hash, 16777619);
|
|
47935
|
+
}
|
|
47936
|
+
return (hash >>> 0).toString(16).padStart(8, "0");
|
|
47937
|
+
}
|
|
47938
|
+
async function readJson(store, key) {
|
|
47939
|
+
const value = await store.read(key);
|
|
47940
|
+
return value ? JSON.parse(decoder.decode(value)) : void 0;
|
|
47941
|
+
}
|
|
47942
|
+
async function writeJson(store, key, value) {
|
|
47943
|
+
await store.write(key, encoder.encode(stableStringify(value)));
|
|
47944
|
+
}
|
|
47945
|
+
function stableStringify(value) {
|
|
47946
|
+
return JSON.stringify(value, (_key, nested) => {
|
|
47947
|
+
if (nested && typeof nested === "object" && !Array.isArray(nested)) {
|
|
47948
|
+
return Object.fromEntries(
|
|
47949
|
+
Object.entries(nested).sort(
|
|
47950
|
+
([left], [right]) => left.localeCompare(right)
|
|
47951
|
+
)
|
|
47952
|
+
);
|
|
47953
|
+
}
|
|
47954
|
+
return nested;
|
|
47955
|
+
});
|
|
47956
|
+
}
|
|
47957
|
+
function assertJsonValue(value, label) {
|
|
47958
|
+
try {
|
|
47959
|
+
const serialized = JSON.stringify(value);
|
|
47960
|
+
if (serialized === void 0)
|
|
47961
|
+
throw new Error("value serializes to undefined");
|
|
47962
|
+
return JSON.parse(serialized);
|
|
47963
|
+
} catch (error) {
|
|
47964
|
+
throw new Error(`${label} must be JSON serializable`, { cause: error });
|
|
47965
|
+
}
|
|
47966
|
+
}
|
|
47967
|
+
function resultItemId(value) {
|
|
47968
|
+
if (typeof value !== "object" || value === null || !("id" in value) || typeof value.id !== "string") {
|
|
47969
|
+
throw new Error("Batch results must contain a string id");
|
|
47970
|
+
}
|
|
47971
|
+
return value.id;
|
|
47972
|
+
}
|
|
47973
|
+
function isBatchTask(value) {
|
|
47974
|
+
return typeof value === "object" && value !== null && "kind" in value && value.kind === BATCH_TASK_KIND;
|
|
47975
|
+
}
|
|
47976
|
+
function isBatchScorer(value) {
|
|
47977
|
+
return typeof value === "object" && value !== null && "kind" in value && value.kind === BATCH_SCORER_KIND;
|
|
47978
|
+
}
|
|
47979
|
+
function asError(error) {
|
|
47980
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
47981
|
+
}
|
|
47982
|
+
|
|
45966
47983
|
// src/agent-assertions.ts
|
|
45967
47984
|
function agentAssertionScorer(callback, options = {}) {
|
|
45968
47985
|
return async (args) => {
|