raindrop-ai 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +168 -0
- package/dist/{chunk-MZZJWWWB.mjs → chunk-AUNFORWV.mjs} +1213 -860
- package/dist/chunk-HFHHGRTW.mjs +1201 -0
- package/dist/index-CQj4bn2v.d.mts +60760 -0
- package/dist/index-CQj4bn2v.d.ts +60760 -0
- package/dist/index.d.mts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +11422 -6431
- package/dist/index.mjs +3397 -176
- package/dist/portable-runtime-GBE3SHBZ.mjs +193 -0
- package/dist/tracing/index.d.mts +2 -1
- package/dist/tracing/index.d.ts +2 -1
- package/dist/tracing/index.js +1301 -982
- package/dist/tracing/index.mjs +1 -1
- package/package.json +19 -12
- package/dist/index-CDmWtd83.d.mts +0 -1525
- package/dist/index-CDmWtd83.d.ts +0 -1525
|
@@ -0,0 +1,1201 @@
|
|
|
1
|
+
// src/evals/definition.ts
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
var EvalScoreSchema = z.union([
|
|
4
|
+
z.literal(1),
|
|
5
|
+
z.literal(2),
|
|
6
|
+
z.literal(3),
|
|
7
|
+
z.literal(4),
|
|
8
|
+
z.literal(5)
|
|
9
|
+
]);
|
|
10
|
+
var EVAL_DATASET = /* @__PURE__ */ Symbol.for("raindrop.evalDataset");
|
|
11
|
+
function defineDataset(dataset) {
|
|
12
|
+
const id = dataset.id.trim();
|
|
13
|
+
const name = dataset.name.trim();
|
|
14
|
+
const version = dataset.version.trim();
|
|
15
|
+
if (!id) throw new Error("Raindrop eval dataset ids cannot be empty");
|
|
16
|
+
if (!name) throw new Error("Raindrop eval dataset names cannot be empty");
|
|
17
|
+
if (!version) throw new Error("Raindrop eval dataset versions cannot be empty");
|
|
18
|
+
if (dataset.cases.length === 0)
|
|
19
|
+
throw new Error("Raindrop eval datasets require at least one case");
|
|
20
|
+
const ids = dataset.cases.map((entry) => entry.id.trim());
|
|
21
|
+
if (ids.some((caseId) => !caseId)) throw new Error("Raindrop eval case ids cannot be empty");
|
|
22
|
+
if (new Set(ids).size !== ids.length) throw new Error("Raindrop eval case ids must be unique");
|
|
23
|
+
if (dataset.remote) {
|
|
24
|
+
if (!dataset.remote.reference.trim())
|
|
25
|
+
throw new Error("Raindrop remote dataset reference cannot be empty");
|
|
26
|
+
if (!/^[a-f0-9]{64}$/.test(dataset.remote.fingerprint)) {
|
|
27
|
+
throw new Error("Raindrop remote dataset fingerprint must be a SHA-256 digest");
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const defined = {
|
|
31
|
+
...dataset,
|
|
32
|
+
id,
|
|
33
|
+
name,
|
|
34
|
+
version,
|
|
35
|
+
cases: dataset.cases.map((entry) => ({ ...entry, id: entry.id.trim() })),
|
|
36
|
+
[EVAL_DATASET]: true
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(defined, EVAL_DATASET, { enumerable: false });
|
|
39
|
+
return defined;
|
|
40
|
+
}
|
|
41
|
+
function isEvalDataset(value) {
|
|
42
|
+
return typeof value === "object" && value !== null && EVAL_DATASET in value && value[EVAL_DATASET] === true;
|
|
43
|
+
}
|
|
44
|
+
var BooleanThresholdSchema = z.object({ equals: z.boolean() }).strict();
|
|
45
|
+
var FiniteThresholdSchema = z.number().finite();
|
|
46
|
+
var EvalOutputSchema = z.enum(["boolean", "score", "number"]);
|
|
47
|
+
var NumericThresholdSchema = z.union([
|
|
48
|
+
z.object({ gte: FiniteThresholdSchema, lte: FiniteThresholdSchema.optional() }).strict(),
|
|
49
|
+
z.object({ lte: FiniteThresholdSchema }).strict()
|
|
50
|
+
]).refine(
|
|
51
|
+
(threshold) => !("gte" in threshold) || threshold.lte === void 0 || threshold.gte <= threshold.lte,
|
|
52
|
+
{ message: "Lower threshold cannot exceed upper threshold" }
|
|
53
|
+
);
|
|
54
|
+
function defineEvaluatorProgram(program) {
|
|
55
|
+
var _a, _b, _c;
|
|
56
|
+
const slug = program.slug.trim();
|
|
57
|
+
const name = program.name.trim();
|
|
58
|
+
const source = program.source.trim();
|
|
59
|
+
const intent = program.intent.trim();
|
|
60
|
+
if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(slug) || slug.length > 64) {
|
|
61
|
+
throw new Error(
|
|
62
|
+
"Raindrop evaluator program slugs must use lowercase letters, numbers, and single hyphens"
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
if (!name || name.length > 120) {
|
|
66
|
+
throw new Error("Raindrop evaluator program names must be between 1 and 120 characters");
|
|
67
|
+
}
|
|
68
|
+
if (!source) throw new Error(`Raindrop evaluator program ${slug} source cannot be empty`);
|
|
69
|
+
if (!intent || intent.length > 1e4) {
|
|
70
|
+
throw new Error(
|
|
71
|
+
`Raindrop evaluator program ${slug} intent must be between 1 and 10000 characters`
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
if (program.description != null && program.description.trim().length > 2e3) {
|
|
75
|
+
throw new Error(`Raindrop evaluator program ${slug} description exceeds 2000 characters`);
|
|
76
|
+
}
|
|
77
|
+
const rules = (_b = (_a = program.rules) == null ? void 0 : _a.map((rule) => rule.trim())) != null ? _b : [];
|
|
78
|
+
if (rules.length > 12 || rules.some((rule) => !rule || rule.length > 2e3)) {
|
|
79
|
+
throw new Error(`Raindrop evaluator program ${slug} rules are invalid`);
|
|
80
|
+
}
|
|
81
|
+
if (program.expected && (!z.string().uuid().safeParse(program.expected.evalId).success || !Number.isInteger(program.expected.programVersion) || program.expected.programVersion <= 0)) {
|
|
82
|
+
throw new Error(`Raindrop evaluator program ${slug} expected identity is invalid`);
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
...program,
|
|
86
|
+
kind: "program",
|
|
87
|
+
slug,
|
|
88
|
+
name,
|
|
89
|
+
source,
|
|
90
|
+
intent,
|
|
91
|
+
description: ((_c = program.description) == null ? void 0 : _c.trim()) || null,
|
|
92
|
+
rules
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function defineLocalEvaluator(evaluator) {
|
|
96
|
+
return evaluator;
|
|
97
|
+
}
|
|
98
|
+
var EVAL_DEFINITION = /* @__PURE__ */ Symbol.for("raindrop.evalDefinition");
|
|
99
|
+
function defineEvalSuite(definition) {
|
|
100
|
+
const name = definition.name.trim();
|
|
101
|
+
if (name.length === 0) throw new Error("Raindrop eval suite names cannot be empty");
|
|
102
|
+
const dataset = typeof definition.dataset === "string" ? definition.dataset.trim() : defineDataset(definition.dataset);
|
|
103
|
+
if (typeof dataset === "string" && dataset.length === 0) {
|
|
104
|
+
throw new Error("Raindrop eval suite datasets cannot be empty");
|
|
105
|
+
}
|
|
106
|
+
if (typeof definition.run !== "function") {
|
|
107
|
+
throw new Error("Raindrop eval suite run must be a function");
|
|
108
|
+
}
|
|
109
|
+
if (!Array.isArray(definition.evaluators) || definition.evaluators.length === 0) {
|
|
110
|
+
throw new Error("Raindrop eval suites require at least one evaluator");
|
|
111
|
+
}
|
|
112
|
+
validateOptionalNumber("concurrency", definition.concurrency, true, false);
|
|
113
|
+
validateOptionalNumber("traceWaitMs", definition.traceWaitMs, false, true);
|
|
114
|
+
validateOptionalNumber("evalWaitMs", definition.evalWaitMs, false, true);
|
|
115
|
+
validateOptionalNumber("evalPollIntervalMs", definition.evalPollIntervalMs, false, false);
|
|
116
|
+
const evaluators = definition.evaluators.map((evaluator) => validateEvaluator(evaluator));
|
|
117
|
+
const evaluatorNames = evaluators.map((entry) => evaluatorName(entry));
|
|
118
|
+
if (new Set(evaluatorNames).size !== evaluatorNames.length) {
|
|
119
|
+
throw new Error("Raindrop eval suite evaluators must be unique");
|
|
120
|
+
}
|
|
121
|
+
const branded = {
|
|
122
|
+
...definition,
|
|
123
|
+
[EVAL_DEFINITION]: true,
|
|
124
|
+
name,
|
|
125
|
+
dataset,
|
|
126
|
+
evaluators
|
|
127
|
+
};
|
|
128
|
+
Object.defineProperty(branded, EVAL_DEFINITION, { enumerable: false });
|
|
129
|
+
return branded;
|
|
130
|
+
}
|
|
131
|
+
function isEvalSuiteDefinition(value) {
|
|
132
|
+
return typeof value === "object" && value !== null && EVAL_DEFINITION in value && value[EVAL_DEFINITION] === true;
|
|
133
|
+
}
|
|
134
|
+
function evaluatorName(evaluator) {
|
|
135
|
+
return typeof evaluator.evaluator === "string" ? evaluator.evaluator.trim() : evaluator.evaluator.slug.trim();
|
|
136
|
+
}
|
|
137
|
+
function evaluatorOutput(evaluator) {
|
|
138
|
+
return typeof evaluator.evaluator === "string" ? void 0 : evaluator.evaluator.output;
|
|
139
|
+
}
|
|
140
|
+
function validateEvaluatorOutput(evaluator, rawOutput) {
|
|
141
|
+
const name = evaluatorName(evaluator);
|
|
142
|
+
const output = EvalOutputSchema.parse(rawOutput);
|
|
143
|
+
const localOutput = evaluatorOutput(evaluator);
|
|
144
|
+
if (localOutput !== void 0 && localOutput !== output) {
|
|
145
|
+
throw new Error(`Raindrop local evaluator ${name} expected ${localOutput}, received ${output}`);
|
|
146
|
+
}
|
|
147
|
+
switch (output) {
|
|
148
|
+
case "boolean":
|
|
149
|
+
parseBooleanThreshold(evaluator.threshold);
|
|
150
|
+
break;
|
|
151
|
+
case "score":
|
|
152
|
+
parseNumericThreshold(name, "score", evaluator.threshold);
|
|
153
|
+
break;
|
|
154
|
+
case "number":
|
|
155
|
+
parseNumericThreshold(name, "number", evaluator.threshold);
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
function validateEvaluator(evaluator) {
|
|
160
|
+
if (typeof evaluator !== "object" || evaluator === null || !("evaluator" in evaluator)) {
|
|
161
|
+
throw new Error("Raindrop eval evaluator entries must name an evaluator");
|
|
162
|
+
}
|
|
163
|
+
if ("output" in evaluator) {
|
|
164
|
+
throw new Error(
|
|
165
|
+
"Raindrop eval evaluator entries do not accept output; the evaluator definition owns it"
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
if (typeof evaluator.evaluator !== "string" && (typeof evaluator.evaluator !== "object" || evaluator.evaluator === null || typeof evaluator.evaluator.slug !== "string" || typeof evaluator.evaluator.name !== "string")) {
|
|
169
|
+
throw new Error("Raindrop local eval evaluators require a slug, name, output, and judge");
|
|
170
|
+
}
|
|
171
|
+
const name = evaluatorName(evaluator);
|
|
172
|
+
if (name.length === 0) throw new Error("Raindrop eval evaluator names cannot be empty");
|
|
173
|
+
if (typeof evaluator.evaluator === "string") {
|
|
174
|
+
const threshold = evaluator.threshold;
|
|
175
|
+
if (threshold !== void 0) {
|
|
176
|
+
const boolean = BooleanThresholdSchema.safeParse(threshold);
|
|
177
|
+
const numeric = NumericThresholdSchema.safeParse(threshold);
|
|
178
|
+
if (!boolean.success && !numeric.success) {
|
|
179
|
+
throw new Error(`Raindrop hosted evaluator ${name} has an invalid threshold`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return { ...evaluator, evaluator: name };
|
|
183
|
+
}
|
|
184
|
+
if ("kind" in evaluator.evaluator && evaluator.evaluator.kind === "portable") {
|
|
185
|
+
validateEvaluatorOutput(evaluator, evaluator.evaluator.output);
|
|
186
|
+
return evaluator;
|
|
187
|
+
}
|
|
188
|
+
if ("kind" in evaluator.evaluator && evaluator.evaluator.kind === "program") {
|
|
189
|
+
const program = defineEvaluatorProgram(evaluator.evaluator);
|
|
190
|
+
validateEvaluatorOutput({ ...evaluator, evaluator: program }, program.output);
|
|
191
|
+
return { ...evaluator, evaluator: program };
|
|
192
|
+
}
|
|
193
|
+
if (typeof evaluator.evaluator.judge !== "function") {
|
|
194
|
+
throw new Error(`Raindrop local evaluator ${name} judge must be a function`);
|
|
195
|
+
}
|
|
196
|
+
if (evaluator.evaluator.scope !== "case") {
|
|
197
|
+
throw new Error(`Raindrop local evaluator ${name} scope must be case`);
|
|
198
|
+
}
|
|
199
|
+
const output = EvalOutputSchema.parse(evaluator.evaluator.output);
|
|
200
|
+
validateEvaluatorOutput(evaluator, output);
|
|
201
|
+
return evaluator;
|
|
202
|
+
}
|
|
203
|
+
function validateOptionalNumber(name, value, integer, allowZero) {
|
|
204
|
+
if (value === void 0) return;
|
|
205
|
+
const valid = Number.isFinite(value) && (!integer || Number.isInteger(value)) && (allowZero ? value >= 0 : value > 0);
|
|
206
|
+
if (!valid) {
|
|
207
|
+
const kind = integer ? "a positive integer" : allowZero ? "non-negative" : "positive";
|
|
208
|
+
throw new Error(`Raindrop eval ${name} must be ${kind}`);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
function parseBooleanThreshold(threshold) {
|
|
212
|
+
return threshold === void 0 ? void 0 : BooleanThresholdSchema.parse(threshold);
|
|
213
|
+
}
|
|
214
|
+
function parseNumericThreshold(name, output, threshold) {
|
|
215
|
+
const parsed = threshold === void 0 ? void 0 : NumericThresholdSchema.parse(threshold);
|
|
216
|
+
if (output === "score" && parsed) {
|
|
217
|
+
const lower = "gte" in parsed ? parsed.gte : void 0;
|
|
218
|
+
const inRange = (lower === void 0 || lower >= 1 && lower <= 5) && (parsed.lte === void 0 || parsed.lte >= 1 && parsed.lte <= 5);
|
|
219
|
+
if (!inRange)
|
|
220
|
+
throw new Error(`Raindrop score evaluator ${name} thresholds must be from 1 to 5`);
|
|
221
|
+
}
|
|
222
|
+
return parsed;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// src/evals/generated/trace.ts
|
|
226
|
+
import z2 from "zod";
|
|
227
|
+
var stringToJSONSchema = z2.string().transform((str, ctx) => {
|
|
228
|
+
try {
|
|
229
|
+
return JSON.parse(str);
|
|
230
|
+
} catch (e) {
|
|
231
|
+
ctx.addIssue({ code: "custom", message: "Invalid JSON" });
|
|
232
|
+
return z2.NEVER;
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
var SignalPropertiesSchema = z2.union([stringToJSONSchema, z2.record(z2.unknown())]);
|
|
236
|
+
var AIEventMetadataSchema = z2.object({
|
|
237
|
+
input: z2.string().optional().nullable(),
|
|
238
|
+
output: z2.string().optional().nullable(),
|
|
239
|
+
model: z2.string().optional().nullable(),
|
|
240
|
+
convoId: z2.string().optional().nullable()
|
|
241
|
+
});
|
|
242
|
+
var AnalyticsEventSchema = z2.object({
|
|
243
|
+
name: z2.string(),
|
|
244
|
+
timestamp: z2.string(),
|
|
245
|
+
receivedAt: z2.string(),
|
|
246
|
+
id: z2.string(),
|
|
247
|
+
properties: z2.record(z2.unknown()).nullable(),
|
|
248
|
+
userId: z2.string(),
|
|
249
|
+
isPending: z2.boolean().optional()
|
|
250
|
+
});
|
|
251
|
+
var LensInfoSchema = z2.object({
|
|
252
|
+
lensId: z2.coerce.number(),
|
|
253
|
+
sourceId: z2.string(),
|
|
254
|
+
source: z2.string().optional(),
|
|
255
|
+
categoryId: z2.coerce.number()
|
|
256
|
+
});
|
|
257
|
+
var AttachmentSchema = z2.object({
|
|
258
|
+
attachment_id: z2.string(),
|
|
259
|
+
attachment_type: z2.enum(["text", "image", "iframe"]).default("text"),
|
|
260
|
+
value: z2.string(),
|
|
261
|
+
name: z2.string().optional().default("")
|
|
262
|
+
});
|
|
263
|
+
var SignalSchema = z2.object({
|
|
264
|
+
id: z2.string().optional(),
|
|
265
|
+
name: z2.string(),
|
|
266
|
+
timestamp: z2.string(),
|
|
267
|
+
attachmentId: z2.string().optional(),
|
|
268
|
+
properties: SignalPropertiesSchema,
|
|
269
|
+
signalType: z2.string().optional(),
|
|
270
|
+
score: z2.number().optional()
|
|
271
|
+
});
|
|
272
|
+
var RichTextContentSchema = z2.object({
|
|
273
|
+
type: z2.literal("text"),
|
|
274
|
+
text: z2.string(),
|
|
275
|
+
annotations: z2.array(z2.object({
|
|
276
|
+
type: z2.enum(["url", "file", "event", "user", "signal"]),
|
|
277
|
+
text: z2.string().optional(),
|
|
278
|
+
id: z2.string().optional(),
|
|
279
|
+
url: z2.string().optional(),
|
|
280
|
+
startIndex: z2.number().int().optional(),
|
|
281
|
+
endIndex: z2.number().int().optional()
|
|
282
|
+
})).optional()
|
|
283
|
+
});
|
|
284
|
+
var RichJsonContentSchema = z2.object({
|
|
285
|
+
type: z2.literal("json"),
|
|
286
|
+
value: z2.unknown(),
|
|
287
|
+
raw: z2.string().nullable()
|
|
288
|
+
});
|
|
289
|
+
var RichMediaContentSchema = z2.object({
|
|
290
|
+
type: z2.enum(["image", "file"]),
|
|
291
|
+
mimeType: z2.string().optional(),
|
|
292
|
+
url: z2.string().optional(),
|
|
293
|
+
fileId: z2.string().optional(),
|
|
294
|
+
name: z2.string().optional()
|
|
295
|
+
});
|
|
296
|
+
var RichReferenceContentSchema = z2.object({
|
|
297
|
+
type: z2.literal("reference"),
|
|
298
|
+
label: z2.string(),
|
|
299
|
+
refType: z2.enum(["stored_tool_result", "external"]),
|
|
300
|
+
href: z2.string().optional(),
|
|
301
|
+
metadata: z2.record(z2.unknown()).optional()
|
|
302
|
+
});
|
|
303
|
+
var RichContentSchema = z2.union([
|
|
304
|
+
RichTextContentSchema,
|
|
305
|
+
RichJsonContentSchema,
|
|
306
|
+
RichMediaContentSchema,
|
|
307
|
+
RichReferenceContentSchema
|
|
308
|
+
]);
|
|
309
|
+
var RichPayloadValueSchema = z2.object({
|
|
310
|
+
kind: z2.enum(["empty", "text", "json", "reference"]),
|
|
311
|
+
raw: z2.string().nullable(),
|
|
312
|
+
truncated: z2.boolean(),
|
|
313
|
+
sizeChars: z2.number().int().nullable()
|
|
314
|
+
});
|
|
315
|
+
var RichEntrySourceSchema = z2.object({
|
|
316
|
+
adapter: z2.string(),
|
|
317
|
+
confidence: z2.enum(["high", "medium", "low"]),
|
|
318
|
+
spanIds: z2.array(z2.string()),
|
|
319
|
+
parentSpanIds: z2.array(z2.string()),
|
|
320
|
+
attributeKeys: z2.array(z2.string())
|
|
321
|
+
});
|
|
322
|
+
var RichInteractionEntryBaseSchema = z2.object({
|
|
323
|
+
id: z2.string(),
|
|
324
|
+
order: z2.number().int(),
|
|
325
|
+
startMs: z2.number().int().nullable(),
|
|
326
|
+
endMs: z2.number().int().nullable(),
|
|
327
|
+
source: RichEntrySourceSchema
|
|
328
|
+
});
|
|
329
|
+
var RichSystemEntrySchema = RichInteractionEntryBaseSchema.extend({
|
|
330
|
+
type: z2.literal("system"),
|
|
331
|
+
role: z2.enum(["system", "developer"]),
|
|
332
|
+
content: RichTextContentSchema,
|
|
333
|
+
collapsed: z2.literal(true),
|
|
334
|
+
tokenEstimate: z2.number().int().nullable()
|
|
335
|
+
});
|
|
336
|
+
var RichUserMessageEntrySchema = RichInteractionEntryBaseSchema.extend({
|
|
337
|
+
type: z2.literal("user_message"),
|
|
338
|
+
role: z2.literal("user"),
|
|
339
|
+
content: z2.array(RichContentSchema)
|
|
340
|
+
});
|
|
341
|
+
var RichAssistantTextEntrySchema = RichInteractionEntryBaseSchema.extend({
|
|
342
|
+
type: z2.literal("assistant_text"),
|
|
343
|
+
role: z2.literal("assistant"),
|
|
344
|
+
content: z2.array(RichContentSchema),
|
|
345
|
+
format: z2.enum(["markdown", "text"]),
|
|
346
|
+
final: z2.boolean()
|
|
347
|
+
});
|
|
348
|
+
var RichReasoningEntrySchema = RichInteractionEntryBaseSchema.extend({
|
|
349
|
+
type: z2.literal("reasoning"),
|
|
350
|
+
content: RichTextContentSchema,
|
|
351
|
+
format: z2.literal("text"),
|
|
352
|
+
visibility: z2.enum(["collapsed", "expanded"]),
|
|
353
|
+
capturedAs: z2.enum(["provider_reasoning", "reasoning_summary", "thinking", "unknown"])
|
|
354
|
+
});
|
|
355
|
+
var RichToolCallEntrySchema = RichInteractionEntryBaseSchema.extend({
|
|
356
|
+
type: z2.literal("tool_call"),
|
|
357
|
+
callId: z2.string().nullable(),
|
|
358
|
+
name: z2.string(),
|
|
359
|
+
status: z2.enum(["pending", "completed", "error", "unknown"]),
|
|
360
|
+
durationMs: z2.number().int().nullable(),
|
|
361
|
+
input: RichPayloadValueSchema,
|
|
362
|
+
output: RichPayloadValueSchema.nullable(),
|
|
363
|
+
error: RichPayloadValueSchema.nullable()
|
|
364
|
+
});
|
|
365
|
+
var RichUnknownSpanEntrySchema = RichInteractionEntryBaseSchema.extend({
|
|
366
|
+
type: z2.literal("unknown_span"),
|
|
367
|
+
spanType: z2.string().nullable(),
|
|
368
|
+
name: z2.string(),
|
|
369
|
+
hiddenByDefault: z2.literal(true)
|
|
370
|
+
});
|
|
371
|
+
var RichSubAgentEntrySchema = RichInteractionEntryBaseSchema.extend({
|
|
372
|
+
type: z2.literal("sub_agent"),
|
|
373
|
+
rootSpanId: z2.string(),
|
|
374
|
+
name: z2.string(),
|
|
375
|
+
spanIds: z2.array(z2.string()),
|
|
376
|
+
toolCount: z2.number().int(),
|
|
377
|
+
llmCount: z2.number().int(),
|
|
378
|
+
durationMs: z2.number().int().nullable(),
|
|
379
|
+
inputPreview: z2.string().nullable(),
|
|
380
|
+
outputPreview: z2.string().nullable(),
|
|
381
|
+
status: z2.enum(["ok", "error", "unknown"]),
|
|
382
|
+
model: z2.string().nullable(),
|
|
383
|
+
totalInputTokens: z2.number().int().nullable(),
|
|
384
|
+
totalOutputTokens: z2.number().int().nullable()
|
|
385
|
+
});
|
|
386
|
+
var RichDetachedSubAgentEntrySchema = RichInteractionEntryBaseSchema.extend({
|
|
387
|
+
type: z2.literal("detached_sub_agent"),
|
|
388
|
+
rootSpanId: z2.string(),
|
|
389
|
+
name: z2.string(),
|
|
390
|
+
durationMs: z2.number().int().nullable(),
|
|
391
|
+
inputPreview: z2.string().nullable(),
|
|
392
|
+
outputPreview: z2.string().nullable(),
|
|
393
|
+
status: z2.enum(["ok", "error", "unknown"]),
|
|
394
|
+
childEventId: z2.string()
|
|
395
|
+
});
|
|
396
|
+
var RichAgentHandoffEntrySchema = RichInteractionEntryBaseSchema.extend({
|
|
397
|
+
type: z2.literal("agent_handoff"),
|
|
398
|
+
fromAgent: z2.string(),
|
|
399
|
+
toAgent: z2.string(),
|
|
400
|
+
reason: z2.string().nullable()
|
|
401
|
+
});
|
|
402
|
+
var RichInteractionEntrySchema = z2.discriminatedUnion("type", [
|
|
403
|
+
RichSystemEntrySchema,
|
|
404
|
+
RichUserMessageEntrySchema,
|
|
405
|
+
RichAssistantTextEntrySchema,
|
|
406
|
+
RichReasoningEntrySchema,
|
|
407
|
+
RichToolCallEntrySchema,
|
|
408
|
+
RichSubAgentEntrySchema,
|
|
409
|
+
RichDetachedSubAgentEntrySchema,
|
|
410
|
+
RichAgentHandoffEntrySchema,
|
|
411
|
+
RichUnknownSpanEntrySchema
|
|
412
|
+
]);
|
|
413
|
+
var RichSpanSummarySchema = z2.object({
|
|
414
|
+
spanId: z2.string(),
|
|
415
|
+
parentSpanId: z2.string().nullable(),
|
|
416
|
+
traceId: z2.string(),
|
|
417
|
+
name: z2.string(),
|
|
418
|
+
spanType: z2.string().nullable(),
|
|
419
|
+
status: z2.string().nullable(),
|
|
420
|
+
startMs: z2.number().int().nullable(),
|
|
421
|
+
endMs: z2.number().int().nullable(),
|
|
422
|
+
durationMs: z2.number().int().nullable(),
|
|
423
|
+
model: z2.string().nullable(),
|
|
424
|
+
provider: z2.string().nullable(),
|
|
425
|
+
rendered: z2.boolean()
|
|
426
|
+
});
|
|
427
|
+
var RichDiagnosticWarningSchema = z2.object({
|
|
428
|
+
code: z2.enum([
|
|
429
|
+
"no_spans",
|
|
430
|
+
"missing_llm_input",
|
|
431
|
+
"missing_llm_output",
|
|
432
|
+
"duplicate_output_suppressed",
|
|
433
|
+
"tool_call_unmatched",
|
|
434
|
+
"payload_truncated",
|
|
435
|
+
"unknown_span_shape"
|
|
436
|
+
]),
|
|
437
|
+
message: z2.string(),
|
|
438
|
+
spanIds: z2.array(z2.string()).optional()
|
|
439
|
+
});
|
|
440
|
+
var RichInteractionStatsSchema = z2.object({
|
|
441
|
+
agentCount: z2.number().int(),
|
|
442
|
+
llmCallCount: z2.number().int(),
|
|
443
|
+
toolCallCount: z2.number().int(),
|
|
444
|
+
errorCount: z2.number().int(),
|
|
445
|
+
agentNames: z2.array(z2.string())
|
|
446
|
+
});
|
|
447
|
+
var RichEventInteractionSchema = z2.object({
|
|
448
|
+
schemaVersion: z2.literal("2026-05-20"),
|
|
449
|
+
eventId: z2.string(),
|
|
450
|
+
traceIds: z2.array(z2.string()),
|
|
451
|
+
rootSpanIds: z2.array(z2.string()),
|
|
452
|
+
status: z2.enum(["complete", "partial", "missing_spans"]),
|
|
453
|
+
startedAt: z2.string().nullable(),
|
|
454
|
+
endedAt: z2.string().nullable(),
|
|
455
|
+
durationMs: z2.number().int().nullable(),
|
|
456
|
+
stats: RichInteractionStatsSchema,
|
|
457
|
+
entries: z2.array(RichInteractionEntrySchema),
|
|
458
|
+
spans: z2.array(RichSpanSummarySchema),
|
|
459
|
+
diagnostics: z2.object({
|
|
460
|
+
extractionVersion: z2.literal("rich-interaction/1"),
|
|
461
|
+
warnings: z2.array(RichDiagnosticWarningSchema),
|
|
462
|
+
unrenderedSpanCount: z2.number().int()
|
|
463
|
+
})
|
|
464
|
+
});
|
|
465
|
+
var CoreEventSchema = z2.object({
|
|
466
|
+
id: z2.string(),
|
|
467
|
+
_raindropDatabaseId: z2.string(),
|
|
468
|
+
projectId: z2.string().optional(),
|
|
469
|
+
name: z2.string(),
|
|
470
|
+
timestamp: z2.string(),
|
|
471
|
+
receivedAt: z2.string(),
|
|
472
|
+
userId: z2.string(),
|
|
473
|
+
aiData: AIEventMetadataSchema,
|
|
474
|
+
properties: z2.record(z2.unknown()).nullable()
|
|
475
|
+
});
|
|
476
|
+
var AIAnalyticsEventSchema = CoreEventSchema.extend({
|
|
477
|
+
customEventId: z2.string().optional().nullable(),
|
|
478
|
+
occurrencesInWindow: z2.number().optional(),
|
|
479
|
+
lensInfo: z2.array(LensInfoSchema).optional(),
|
|
480
|
+
topics: z2.array(z2.string()).optional(),
|
|
481
|
+
categories: z2.array(z2.tuple([z2.string(), z2.string().nullable(), z2.coerce.number().nullable()])).optional(),
|
|
482
|
+
categoryLog: z2.array(z2.object({
|
|
483
|
+
lensId: z2.coerce.number(),
|
|
484
|
+
categoryId: z2.coerce.string(),
|
|
485
|
+
action: z2.enum(["add_category", "remove_category", "skip_category"])
|
|
486
|
+
})).optional(),
|
|
487
|
+
inputAttachments: z2.array(z2.union([z2.string(), AttachmentSchema])).optional().transform((attachments) => (attachments == null ? void 0 : attachments.map((attachment) => {
|
|
488
|
+
if (typeof attachment === "string") {
|
|
489
|
+
try {
|
|
490
|
+
return AttachmentSchema.parse(JSON.parse(attachment));
|
|
491
|
+
} catch (e) {
|
|
492
|
+
return null;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
return attachment;
|
|
496
|
+
}).filter((a) => a !== null)) || []),
|
|
497
|
+
outputAttachments: z2.array(z2.union([z2.string(), AttachmentSchema])).optional().transform((attachments) => (attachments == null ? void 0 : attachments.map((attachment) => {
|
|
498
|
+
if (typeof attachment === "string") {
|
|
499
|
+
try {
|
|
500
|
+
return AttachmentSchema.parse(JSON.parse(attachment));
|
|
501
|
+
} catch (e) {
|
|
502
|
+
return null;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
return attachment;
|
|
506
|
+
}).filter((a) => a !== null)) || []),
|
|
507
|
+
signals: z2.array(SignalSchema).optional(),
|
|
508
|
+
errorSpans: z2.array(z2.object({
|
|
509
|
+
span_id: z2.string().optional(),
|
|
510
|
+
started_at: z2.string().optional(),
|
|
511
|
+
status: z2.string().optional(),
|
|
512
|
+
duration_ms: z2.coerce.number().optional(),
|
|
513
|
+
span_type: z2.string().optional(),
|
|
514
|
+
span_name: z2.string().optional(),
|
|
515
|
+
output_payload: z2.any().optional()
|
|
516
|
+
})).optional(),
|
|
517
|
+
regexSignals: z2.array(z2.string()).optional(),
|
|
518
|
+
toolCalls: z2.array(z2.any()).optional(),
|
|
519
|
+
toolCallNames: z2.array(z2.string()).optional(),
|
|
520
|
+
richInteraction: RichEventInteractionSchema.optional().nullable(),
|
|
521
|
+
_ai_output_words: z2.number().optional(),
|
|
522
|
+
_ai_input_words: z2.number().optional(),
|
|
523
|
+
userTraits: z2.record(z2.unknown()).optional().nullable(),
|
|
524
|
+
featureFlags: z2.record(z2.string()).optional().nullable(),
|
|
525
|
+
userCreatedAt: z2.string().optional().nullable(),
|
|
526
|
+
userPlan: z2.string().optional().nullable(),
|
|
527
|
+
userLastPlan: z2.string().optional().nullable(),
|
|
528
|
+
userPlanChangeTs: z2.string().optional().nullable(),
|
|
529
|
+
isPending: z2.boolean().optional()
|
|
530
|
+
});
|
|
531
|
+
var SpanStatusSchema = z2.enum(["UNSET", "OK", "ERROR"]);
|
|
532
|
+
var SpanTypeSchema = z2.enum([
|
|
533
|
+
"INTERNAL",
|
|
534
|
+
"LLM_GENERATION",
|
|
535
|
+
"LLM_GENERATION_STREAM",
|
|
536
|
+
"TOOL_CALL"
|
|
537
|
+
]);
|
|
538
|
+
var TracesListPipe = {
|
|
539
|
+
name: "traces_list",
|
|
540
|
+
input: z2.object({
|
|
541
|
+
event_id: z2.string().optional(),
|
|
542
|
+
trace_id: z2.string().optional(),
|
|
543
|
+
subagent_parent_event_ids: z2.array(z2.string()).optional(),
|
|
544
|
+
limit: z2.number().int().optional(),
|
|
545
|
+
offset: z2.number().int().optional(),
|
|
546
|
+
trunc_len: z2.number().int().nonnegative().optional(),
|
|
547
|
+
span_type_filter: SpanTypeSchema.optional(),
|
|
548
|
+
span_status_filter: SpanStatusSchema.optional(),
|
|
549
|
+
span_id_filter: z2.string().optional(),
|
|
550
|
+
start_unix_ns_min: z2.string().optional(),
|
|
551
|
+
start_unix_ns_max: z2.string().optional()
|
|
552
|
+
}),
|
|
553
|
+
output: z2.object({
|
|
554
|
+
project_id: z2.string().optional(),
|
|
555
|
+
convo_id: z2.string(),
|
|
556
|
+
event_id: z2.string(),
|
|
557
|
+
custom_event_id: z2.string(),
|
|
558
|
+
trace_id: z2.string(),
|
|
559
|
+
span_id: z2.string(),
|
|
560
|
+
parent_span_id: z2.string(),
|
|
561
|
+
span_type: SpanTypeSchema,
|
|
562
|
+
span_name: z2.string(),
|
|
563
|
+
status: SpanStatusSchema,
|
|
564
|
+
input_payload: z2.string(),
|
|
565
|
+
output_payload: z2.string(),
|
|
566
|
+
start_unix_ns: z2.number(),
|
|
567
|
+
end_unix_ns: z2.number(),
|
|
568
|
+
duration_ns: z2.number(),
|
|
569
|
+
input_tokens: z2.number(),
|
|
570
|
+
output_tokens: z2.number(),
|
|
571
|
+
model: z2.string(),
|
|
572
|
+
provider: z2.string(),
|
|
573
|
+
attributes_string: z2.record(z2.string(), z2.string()),
|
|
574
|
+
attributes_num: z2.record(z2.string(), z2.number())
|
|
575
|
+
})
|
|
576
|
+
};
|
|
577
|
+
var UINT64_MAX = BigInt("18446744073709551615");
|
|
578
|
+
var NANOSECONDS_PATTERN = /^\d{1,20}$/;
|
|
579
|
+
var NanosecondsStringSchema = z2.string().refine((value) => {
|
|
580
|
+
if (!NANOSECONDS_PATTERN.test(value))
|
|
581
|
+
return false;
|
|
582
|
+
return BigInt(value) <= UINT64_MAX;
|
|
583
|
+
}, "Nanoseconds must be a UInt64 decimal string");
|
|
584
|
+
var ReplayTraceSnapshotSpanSchema = TracesListPipe.output.extend({
|
|
585
|
+
org_public_id: z2.string().uuid(),
|
|
586
|
+
project_id: z2.string().min(1),
|
|
587
|
+
user_id: z2.string(),
|
|
588
|
+
start_unix_ns: NanosecondsStringSchema,
|
|
589
|
+
timestamp: z2.string().min(1),
|
|
590
|
+
end_unix_ns: NanosecondsStringSchema,
|
|
591
|
+
end_timestamp: z2.string().min(1),
|
|
592
|
+
duration_ns: NanosecondsStringSchema,
|
|
593
|
+
_inserted_at: z2.string().min(1)
|
|
594
|
+
}).strict();
|
|
595
|
+
var TraceSchema = z2.object({
|
|
596
|
+
origin: z2.enum(["production", "dataset", "simulation", "replay"]),
|
|
597
|
+
event: AIAnalyticsEventSchema,
|
|
598
|
+
entries: z2.array(RichInteractionEntrySchema)
|
|
599
|
+
});
|
|
600
|
+
var CapturedTraceSpanSchema = ReplayTraceSnapshotSpanSchema;
|
|
601
|
+
var EVAL_DATASET_MAX_SPANS_PER_TRACE = 500;
|
|
602
|
+
var EvalDatasetCaseIdSchema = z2.string().min(1).max(512).refine((value) => value === value.trim(), "Case id cannot have surrounding whitespace");
|
|
603
|
+
var CapturedTraceSnapshotSchema = z2.object({
|
|
604
|
+
event: AIAnalyticsEventSchema,
|
|
605
|
+
spans: z2.array(CapturedTraceSpanSchema).min(1).max(EVAL_DATASET_MAX_SPANS_PER_TRACE)
|
|
606
|
+
}).strict().superRefine(({ event, spans }, context) => {
|
|
607
|
+
var _a;
|
|
608
|
+
const spanIds = /* @__PURE__ */ new Set();
|
|
609
|
+
const traceIds = /* @__PURE__ */ new Set();
|
|
610
|
+
for (const [index, span] of spans.entries()) {
|
|
611
|
+
if (!/^[0-9a-f]{32}$/.test(span.trace_id)) {
|
|
612
|
+
context.addIssue({
|
|
613
|
+
code: z2.ZodIssueCode.custom,
|
|
614
|
+
message: "Captured trace id must be a lowercase 32-character hexadecimal value",
|
|
615
|
+
path: ["spans", index, "trace_id"]
|
|
616
|
+
});
|
|
617
|
+
}
|
|
618
|
+
if (!/^[0-9a-f]{16}$/.test(span.span_id)) {
|
|
619
|
+
context.addIssue({
|
|
620
|
+
code: z2.ZodIssueCode.custom,
|
|
621
|
+
message: "Captured span id must be a lowercase 16-character hexadecimal value",
|
|
622
|
+
path: ["spans", index, "span_id"]
|
|
623
|
+
});
|
|
624
|
+
}
|
|
625
|
+
if (span.parent_span_id !== "" && !/^[0-9a-f]{16}$/.test(span.parent_span_id)) {
|
|
626
|
+
context.addIssue({
|
|
627
|
+
code: z2.ZodIssueCode.custom,
|
|
628
|
+
message: "Captured parent span id must be empty or lowercase hexadecimal",
|
|
629
|
+
path: ["spans", index, "parent_span_id"]
|
|
630
|
+
});
|
|
631
|
+
}
|
|
632
|
+
if (span.event_id.length === 0) {
|
|
633
|
+
context.addIssue({
|
|
634
|
+
code: z2.ZodIssueCode.custom,
|
|
635
|
+
message: "Captured event id cannot be empty",
|
|
636
|
+
path: ["spans", index, "event_id"]
|
|
637
|
+
});
|
|
638
|
+
}
|
|
639
|
+
if (spanIds.has(span.span_id)) {
|
|
640
|
+
context.addIssue({
|
|
641
|
+
code: z2.ZodIssueCode.custom,
|
|
642
|
+
message: `Duplicate span id ${span.span_id}`,
|
|
643
|
+
path: ["spans", index, "span_id"]
|
|
644
|
+
});
|
|
645
|
+
}
|
|
646
|
+
spanIds.add(span.span_id);
|
|
647
|
+
traceIds.add(span.trace_id);
|
|
648
|
+
if (span.event_id !== event._raindropDatabaseId) {
|
|
649
|
+
context.addIssue({
|
|
650
|
+
code: z2.ZodIssueCode.custom,
|
|
651
|
+
message: "Span event identity does not match the captured event",
|
|
652
|
+
path: ["spans", index, "event_id"]
|
|
653
|
+
});
|
|
654
|
+
}
|
|
655
|
+
const validStart = /^\d{1,20}$/.test(span.start_unix_ns);
|
|
656
|
+
const validEnd = /^\d{1,20}$/.test(span.end_unix_ns);
|
|
657
|
+
if (validStart && validEnd && (BigInt(span.start_unix_ns) === BigInt(0) || BigInt(span.end_unix_ns) < BigInt(span.start_unix_ns))) {
|
|
658
|
+
context.addIssue({
|
|
659
|
+
code: z2.ZodIssueCode.custom,
|
|
660
|
+
message: "A captured span must have an end time at or after its start time",
|
|
661
|
+
path: ["spans", index, "end_unix_ns"]
|
|
662
|
+
});
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
if (traceIds.size !== 1) {
|
|
666
|
+
context.addIssue({
|
|
667
|
+
code: z2.ZodIssueCode.custom,
|
|
668
|
+
message: "A reference snapshot must contain exactly one trace id",
|
|
669
|
+
path: ["spans"]
|
|
670
|
+
});
|
|
671
|
+
}
|
|
672
|
+
for (const [index, span] of spans.entries()) {
|
|
673
|
+
if (span.parent_span_id && !spanIds.has(span.parent_span_id)) {
|
|
674
|
+
context.addIssue({
|
|
675
|
+
code: z2.ZodIssueCode.custom,
|
|
676
|
+
message: `Missing parent span ${span.parent_span_id}`,
|
|
677
|
+
path: ["spans", index, "parent_span_id"]
|
|
678
|
+
});
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
const parentBySpanId = new Map(spans.map((span) => [span.span_id, span.parent_span_id]));
|
|
682
|
+
for (const [index, span] of spans.entries()) {
|
|
683
|
+
const path = /* @__PURE__ */ new Set();
|
|
684
|
+
let spanId = span.span_id;
|
|
685
|
+
while (spanId !== "") {
|
|
686
|
+
if (path.has(spanId)) {
|
|
687
|
+
context.addIssue({
|
|
688
|
+
code: z2.ZodIssueCode.custom,
|
|
689
|
+
message: "Captured span parent relationships cannot contain a cycle",
|
|
690
|
+
path: ["spans", index, "parent_span_id"]
|
|
691
|
+
});
|
|
692
|
+
break;
|
|
693
|
+
}
|
|
694
|
+
path.add(spanId);
|
|
695
|
+
spanId = (_a = parentBySpanId.get(spanId)) != null ? _a : "";
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
});
|
|
699
|
+
var EvalCaseTraceSchema = z2.object({
|
|
700
|
+
snapshot: CapturedTraceSnapshotSchema,
|
|
701
|
+
trace: TraceSchema
|
|
702
|
+
});
|
|
703
|
+
var EvalCaseTracePairSchema = z2.object({
|
|
704
|
+
caseId: EvalDatasetCaseIdSchema,
|
|
705
|
+
candidate: EvalCaseTraceSchema.extend({
|
|
706
|
+
trace: TraceSchema.extend({ origin: z2.literal("replay") })
|
|
707
|
+
}),
|
|
708
|
+
reference: EvalCaseTraceSchema.extend({
|
|
709
|
+
trace: TraceSchema.extend({ origin: z2.literal("dataset") })
|
|
710
|
+
})
|
|
711
|
+
});
|
|
712
|
+
function compareNanoseconds(left, right) {
|
|
713
|
+
if (Number.isFinite(left) && Number.isFinite(right))
|
|
714
|
+
return Number(left) - Number(right);
|
|
715
|
+
const leftNs = BigInt(left != null ? left : 0);
|
|
716
|
+
const rightNs = BigInt(right != null ? right : 0);
|
|
717
|
+
return leftNs < rightNs ? -1 : leftNs > rightNs ? 1 : 0;
|
|
718
|
+
}
|
|
719
|
+
function nanosecondsToRoundedMilliseconds(value) {
|
|
720
|
+
if (Number.isFinite(value))
|
|
721
|
+
return Math.round(Number(value) / 1e6);
|
|
722
|
+
return Number((BigInt(value != null ? value : 0) + BigInt(5e5)) / BigInt(1e6));
|
|
723
|
+
}
|
|
724
|
+
var MAX_CUSTOM_ATTRIBUTES = 25;
|
|
725
|
+
var MAX_ATTRIBUTE_VALUE_CHARS = 500;
|
|
726
|
+
var KNOWN_ATTRIBUTE_PREFIXES = [
|
|
727
|
+
"ai.",
|
|
728
|
+
"gen_ai.",
|
|
729
|
+
"llm.",
|
|
730
|
+
"openinference.",
|
|
731
|
+
"traceloop.",
|
|
732
|
+
"raindrop.",
|
|
733
|
+
"otel.",
|
|
734
|
+
"telemetry.",
|
|
735
|
+
"service.",
|
|
736
|
+
"resource.",
|
|
737
|
+
"http.",
|
|
738
|
+
"net.",
|
|
739
|
+
"network.",
|
|
740
|
+
"server.",
|
|
741
|
+
"client.",
|
|
742
|
+
"url.",
|
|
743
|
+
"rpc.",
|
|
744
|
+
"db.",
|
|
745
|
+
"messaging.",
|
|
746
|
+
"code.",
|
|
747
|
+
"thread.",
|
|
748
|
+
"session.",
|
|
749
|
+
"user_agent.",
|
|
750
|
+
"process.",
|
|
751
|
+
"host.",
|
|
752
|
+
"os.",
|
|
753
|
+
"exception.",
|
|
754
|
+
"span."
|
|
755
|
+
];
|
|
756
|
+
var SENSITIVE_KEY_TOKENS = /* @__PURE__ */ new Set([
|
|
757
|
+
"secret",
|
|
758
|
+
"secrets",
|
|
759
|
+
"secretkey",
|
|
760
|
+
"password",
|
|
761
|
+
"passwd",
|
|
762
|
+
"pwd",
|
|
763
|
+
"token",
|
|
764
|
+
"tokens",
|
|
765
|
+
"auth",
|
|
766
|
+
"authorization",
|
|
767
|
+
"credential",
|
|
768
|
+
"credentials",
|
|
769
|
+
"bearer",
|
|
770
|
+
"cookie",
|
|
771
|
+
"cookies",
|
|
772
|
+
"apikey",
|
|
773
|
+
"accesskey",
|
|
774
|
+
"privatekey",
|
|
775
|
+
"sessionid"
|
|
776
|
+
]);
|
|
777
|
+
var SENSITIVE_KEY_TOKEN_PAIRS = /* @__PURE__ */ new Set([
|
|
778
|
+
"api key",
|
|
779
|
+
"access key",
|
|
780
|
+
"private key",
|
|
781
|
+
"secret key",
|
|
782
|
+
"session id",
|
|
783
|
+
"auth token",
|
|
784
|
+
"access token",
|
|
785
|
+
"refresh token"
|
|
786
|
+
]);
|
|
787
|
+
function isKnownAttributeKey(key) {
|
|
788
|
+
return KNOWN_ATTRIBUTE_PREFIXES.some((prefix) => key.startsWith(prefix));
|
|
789
|
+
}
|
|
790
|
+
function tokenizeKey(key) {
|
|
791
|
+
return key.replace(/([a-z0-9])([A-Z])/g, "$1 $2").split(/[^a-zA-Z0-9]+/).filter(Boolean).map((token) => token.toLowerCase());
|
|
792
|
+
}
|
|
793
|
+
function isSensitiveAttributeKey(key) {
|
|
794
|
+
const tokens = tokenizeKey(key);
|
|
795
|
+
if (tokens.some((token) => SENSITIVE_KEY_TOKENS.has(token)))
|
|
796
|
+
return true;
|
|
797
|
+
for (let index = 0; index < tokens.length - 1; index += 1) {
|
|
798
|
+
if (SENSITIVE_KEY_TOKEN_PAIRS.has(`${tokens[index]} ${tokens[index + 1]}`))
|
|
799
|
+
return true;
|
|
800
|
+
}
|
|
801
|
+
return false;
|
|
802
|
+
}
|
|
803
|
+
function extractCustomSpanAttributes(span) {
|
|
804
|
+
var _a, _b;
|
|
805
|
+
const attributes = {};
|
|
806
|
+
const strings = (_a = span.attributes_string) != null ? _a : {};
|
|
807
|
+
for (const [key, value] of Object.entries(strings)) {
|
|
808
|
+
if (Object.keys(attributes).length >= MAX_CUSTOM_ATTRIBUTES)
|
|
809
|
+
break;
|
|
810
|
+
if (isKnownAttributeKey(key) || isSensitiveAttributeKey(key)) {
|
|
811
|
+
continue;
|
|
812
|
+
}
|
|
813
|
+
attributes[key] = value.length > MAX_ATTRIBUTE_VALUE_CHARS ? `${value.slice(0, MAX_ATTRIBUTE_VALUE_CHARS)}\u2026` : value;
|
|
814
|
+
}
|
|
815
|
+
const numbers = (_b = span.attributes_num) != null ? _b : {};
|
|
816
|
+
for (const [key, value] of Object.entries(numbers)) {
|
|
817
|
+
if (Object.keys(attributes).length >= MAX_CUSTOM_ATTRIBUTES)
|
|
818
|
+
break;
|
|
819
|
+
if (isKnownAttributeKey(key) || isSensitiveAttributeKey(key)) {
|
|
820
|
+
continue;
|
|
821
|
+
}
|
|
822
|
+
attributes[key] = value;
|
|
823
|
+
}
|
|
824
|
+
return Object.keys(attributes).length > 0 ? attributes : void 0;
|
|
825
|
+
}
|
|
826
|
+
function extractFinishReason(span) {
|
|
827
|
+
var _a, _b, _c;
|
|
828
|
+
const strings = (_a = span.attributes_string) != null ? _a : {};
|
|
829
|
+
const value = (_c = (_b = strings["ai.response.finishReason"]) != null ? _b : strings["gen_ai.response.finish_reasons"]) != null ? _c : strings["llm.response.finish_reason"];
|
|
830
|
+
return value && value.length > 0 ? value : void 0;
|
|
831
|
+
}
|
|
832
|
+
function normalizePayload(value) {
|
|
833
|
+
return value != null ? value : void 0;
|
|
834
|
+
}
|
|
835
|
+
function buildTraceSteps(rawSpans, options = {}) {
|
|
836
|
+
var _a;
|
|
837
|
+
const includePayloads = (_a = options.includePayloads) != null ? _a : false;
|
|
838
|
+
const sorted = [...rawSpans].sort((left, right) => compareNanoseconds(left.start_unix_ns, right.start_unix_ns));
|
|
839
|
+
return sorted.map((span, index) => {
|
|
840
|
+
var _a2, _b;
|
|
841
|
+
const status = span.status === "OK" || span.status === "ERROR" ? span.status : "UNSET";
|
|
842
|
+
const step = {
|
|
843
|
+
step: index + 1,
|
|
844
|
+
type: span.span_type || "INTERNAL",
|
|
845
|
+
name: span.span_name || "unknown",
|
|
846
|
+
status,
|
|
847
|
+
duration_ms: nanosecondsToRoundedMilliseconds(span.duration_ns)
|
|
848
|
+
};
|
|
849
|
+
if (span.span_id)
|
|
850
|
+
step.span_id = span.span_id;
|
|
851
|
+
if (span.status === "ERROR" && span.output_payload) {
|
|
852
|
+
step.error = span.output_payload.slice(0, 500);
|
|
853
|
+
}
|
|
854
|
+
if (span.model)
|
|
855
|
+
step.model = span.model;
|
|
856
|
+
const finishReason = extractFinishReason(span);
|
|
857
|
+
if (finishReason)
|
|
858
|
+
step.finish_reason = finishReason;
|
|
859
|
+
if (((_a2 = span.input_tokens) != null ? _a2 : 0) > 0)
|
|
860
|
+
step.input_tokens = span.input_tokens;
|
|
861
|
+
if (((_b = span.output_tokens) != null ? _b : 0) > 0)
|
|
862
|
+
step.output_tokens = span.output_tokens;
|
|
863
|
+
if (includePayloads && step.type === "TOOL_CALL") {
|
|
864
|
+
const inputPayload = normalizePayload(span.input_payload);
|
|
865
|
+
const outputPayload = normalizePayload(span.output_payload);
|
|
866
|
+
if (inputPayload)
|
|
867
|
+
step.input_payload = inputPayload;
|
|
868
|
+
if (outputPayload)
|
|
869
|
+
step.output_payload = outputPayload;
|
|
870
|
+
}
|
|
871
|
+
const attributes = extractCustomSpanAttributes(span);
|
|
872
|
+
if (attributes)
|
|
873
|
+
step.attributes = attributes;
|
|
874
|
+
return step;
|
|
875
|
+
});
|
|
876
|
+
}
|
|
877
|
+
var MAX_EVAL_PAYLOAD_RAW_CHARS = 16 * 1024;
|
|
878
|
+
function boundEvalPayload(payload) {
|
|
879
|
+
var _a;
|
|
880
|
+
if (payload.raw === null)
|
|
881
|
+
return payload;
|
|
882
|
+
const sizeChars = (_a = payload.sizeChars) != null ? _a : payload.raw.length;
|
|
883
|
+
return {
|
|
884
|
+
...payload,
|
|
885
|
+
raw: payload.raw.slice(0, MAX_EVAL_PAYLOAD_RAW_CHARS),
|
|
886
|
+
sizeChars,
|
|
887
|
+
truncated: payload.truncated || sizeChars > MAX_EVAL_PAYLOAD_RAW_CHARS
|
|
888
|
+
};
|
|
889
|
+
}
|
|
890
|
+
function boundEvalEntry(entry) {
|
|
891
|
+
switch (entry.type) {
|
|
892
|
+
case "system":
|
|
893
|
+
case "reasoning":
|
|
894
|
+
return {
|
|
895
|
+
...entry,
|
|
896
|
+
content: {
|
|
897
|
+
...entry.content,
|
|
898
|
+
text: entry.content.text.slice(0, MAX_EVAL_PAYLOAD_RAW_CHARS)
|
|
899
|
+
}
|
|
900
|
+
};
|
|
901
|
+
case "user_message":
|
|
902
|
+
case "assistant_text":
|
|
903
|
+
return {
|
|
904
|
+
...entry,
|
|
905
|
+
content: entry.content.map((content) => content.type === "text" ? { ...content, text: content.text.slice(0, MAX_EVAL_PAYLOAD_RAW_CHARS) } : content.type === "json" && content.raw !== null ? { ...content, raw: content.raw.slice(0, MAX_EVAL_PAYLOAD_RAW_CHARS) } : content)
|
|
906
|
+
};
|
|
907
|
+
case "tool_call":
|
|
908
|
+
return {
|
|
909
|
+
...entry,
|
|
910
|
+
input: boundEvalPayload(entry.input),
|
|
911
|
+
output: entry.output === null ? null : boundEvalPayload(entry.output),
|
|
912
|
+
error: entry.error === null ? null : boundEvalPayload(entry.error)
|
|
913
|
+
};
|
|
914
|
+
default:
|
|
915
|
+
return entry;
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
function createTrace(origin, event, entries) {
|
|
919
|
+
return TraceSchema.parse({ origin, event, entries });
|
|
920
|
+
}
|
|
921
|
+
function traceStepsToEntries(steps) {
|
|
922
|
+
return steps.map((step, index) => {
|
|
923
|
+
var _a;
|
|
924
|
+
const source = {
|
|
925
|
+
adapter: "raw_spans",
|
|
926
|
+
confidence: "medium",
|
|
927
|
+
spanIds: step.span_id ? [step.span_id] : [],
|
|
928
|
+
parentSpanIds: [],
|
|
929
|
+
attributeKeys: []
|
|
930
|
+
};
|
|
931
|
+
const common = {
|
|
932
|
+
id: (_a = step.span_id) != null ? _a : `raw-step-${index}`,
|
|
933
|
+
order: index,
|
|
934
|
+
startMs: null,
|
|
935
|
+
endMs: null,
|
|
936
|
+
source
|
|
937
|
+
};
|
|
938
|
+
if (step.type === "TOOL_CALL") {
|
|
939
|
+
const payload = (raw) => {
|
|
940
|
+
var _a2;
|
|
941
|
+
return boundEvalPayload({
|
|
942
|
+
kind: raw ? "text" : "empty",
|
|
943
|
+
raw: raw != null ? raw : null,
|
|
944
|
+
truncated: false,
|
|
945
|
+
sizeChars: (_a2 = raw == null ? void 0 : raw.length) != null ? _a2 : null
|
|
946
|
+
});
|
|
947
|
+
};
|
|
948
|
+
return {
|
|
949
|
+
...common,
|
|
950
|
+
type: "tool_call",
|
|
951
|
+
callId: null,
|
|
952
|
+
name: step.name,
|
|
953
|
+
status: step.status === "ERROR" ? "error" : step.status === "OK" ? "completed" : "unknown",
|
|
954
|
+
durationMs: step.duration_ms,
|
|
955
|
+
input: payload(step.input_payload),
|
|
956
|
+
output: step.output_payload ? payload(step.output_payload) : null,
|
|
957
|
+
error: step.error ? payload(step.error) : null
|
|
958
|
+
};
|
|
959
|
+
}
|
|
960
|
+
return {
|
|
961
|
+
...common,
|
|
962
|
+
type: "unknown_span",
|
|
963
|
+
spanType: step.type,
|
|
964
|
+
name: step.name,
|
|
965
|
+
hiddenByDefault: true
|
|
966
|
+
};
|
|
967
|
+
});
|
|
968
|
+
}
|
|
969
|
+
function projectWorkshopTrace(input) {
|
|
970
|
+
return createTrace(input.origin, input.event, traceStepsToEntries(buildTraceSteps([...input.spans], { includePayloads: true })).map(boundEvalEntry));
|
|
971
|
+
}
|
|
972
|
+
function projectCapturedEvent(input) {
|
|
973
|
+
var _a, _b, _c, _d, _e, _f;
|
|
974
|
+
const ordered = [...input.spans].sort((left, right) => compareNanoseconds(left.start_unix_ns, right.start_unix_ns));
|
|
975
|
+
const eventSpan = ordered.find((span) => span.span_id === `evt_${input.eventId}`);
|
|
976
|
+
const llmSpans = ordered.filter((span) => span.span_type === "LLM_GENERATION" || span.span_type === "LLM_GENERATION_STREAM");
|
|
977
|
+
const inputSpan = ((_a = eventSpan == null ? void 0 : eventSpan.input_payload) == null ? void 0 : _a.trim()) ? eventSpan : llmSpans.find((span) => {
|
|
978
|
+
var _a2;
|
|
979
|
+
return Boolean((_a2 = span.input_payload) == null ? void 0 : _a2.trim());
|
|
980
|
+
});
|
|
981
|
+
const reverseLlmSpans = [...llmSpans].reverse();
|
|
982
|
+
const outputSpan = (_c = ((_b = eventSpan == null ? void 0 : eventSpan.output_payload) == null ? void 0 : _b.trim()) ? eventSpan : void 0) != null ? _c : reverseLlmSpans.find((span) => {
|
|
983
|
+
var _a2;
|
|
984
|
+
return Boolean((_a2 = span.output_payload) == null ? void 0 : _a2.trim()) && extractFinishReason(span) !== "tool-calls";
|
|
985
|
+
});
|
|
986
|
+
const modelSpan = (eventSpan == null ? void 0 : eventSpan.model) ? eventSpan : reverseLlmSpans.find((span) => Boolean(span.model));
|
|
987
|
+
return AIAnalyticsEventSchema.parse({
|
|
988
|
+
id: input.eventId,
|
|
989
|
+
_raindropDatabaseId: input.internalEventId,
|
|
990
|
+
name: input.name,
|
|
991
|
+
timestamp: input.timestamp,
|
|
992
|
+
receivedAt: input.receivedAt,
|
|
993
|
+
userId: input.userId,
|
|
994
|
+
aiData: {
|
|
995
|
+
input: (_d = inputSpan == null ? void 0 : inputSpan.input_payload) != null ? _d : null,
|
|
996
|
+
output: (_e = outputSpan == null ? void 0 : outputSpan.output_payload) != null ? _e : null,
|
|
997
|
+
model: (_f = modelSpan == null ? void 0 : modelSpan.model) != null ? _f : null,
|
|
998
|
+
convoId: input.convoId
|
|
999
|
+
},
|
|
1000
|
+
properties: input.properties
|
|
1001
|
+
});
|
|
1002
|
+
}
|
|
1003
|
+
function traceOutput(trace) {
|
|
1004
|
+
var _a;
|
|
1005
|
+
return (_a = trace.event.aiData.output) != null ? _a : null;
|
|
1006
|
+
}
|
|
1007
|
+
function traceToolCalls(trace, name) {
|
|
1008
|
+
return trace.entries.filter((entry) => entry.type === "tool_call" && (name === void 0 || entry.name === name));
|
|
1009
|
+
}
|
|
1010
|
+
var TRACE_PROJECTION_SHA256 = "8dab83087aa2def3d076324021d5e08911e37967b68597b58b793a80d54b5874";
|
|
1011
|
+
|
|
1012
|
+
// src/evals/portable.ts
|
|
1013
|
+
import { z as z3 } from "zod";
|
|
1014
|
+
var PortableEvalArtifactSchema = z3.object({
|
|
1015
|
+
format: z3.literal("raindrop.eval-program"),
|
|
1016
|
+
formatVersion: z3.literal(1),
|
|
1017
|
+
runtimeAbi: z3.literal("raindrop-eval-v2"),
|
|
1018
|
+
evaluator: z3.object({
|
|
1019
|
+
id: z3.string().uuid(),
|
|
1020
|
+
slug: z3.string().min(1),
|
|
1021
|
+
programVersion: z3.number().int().positive(),
|
|
1022
|
+
executionMode: z3.enum(["deterministic", "judge"]),
|
|
1023
|
+
outputType: z3.enum(["boolean", "score", "number"]),
|
|
1024
|
+
scope: z3.literal("batch")
|
|
1025
|
+
}).strict(),
|
|
1026
|
+
traceProjectionVersion: z3.literal(1),
|
|
1027
|
+
traceProjectionSha256: z3.string().regex(/^[a-f0-9]{64}$/),
|
|
1028
|
+
source: z3.string().min(1),
|
|
1029
|
+
sha256: z3.string().regex(/^[a-f0-9]{64}$/)
|
|
1030
|
+
}).strict();
|
|
1031
|
+
var PortableEvalResultSchema = z3.object({
|
|
1032
|
+
outcomes: z3.array(
|
|
1033
|
+
z3.union([
|
|
1034
|
+
z3.object({
|
|
1035
|
+
state: z3.literal("graded"),
|
|
1036
|
+
traceId: z3.string(),
|
|
1037
|
+
pass: z3.boolean(),
|
|
1038
|
+
note: z3.string().optional()
|
|
1039
|
+
}),
|
|
1040
|
+
z3.object({
|
|
1041
|
+
state: z3.literal("graded"),
|
|
1042
|
+
traceId: z3.string(),
|
|
1043
|
+
score: EvalScoreSchema,
|
|
1044
|
+
note: z3.string().optional()
|
|
1045
|
+
}),
|
|
1046
|
+
z3.object({
|
|
1047
|
+
state: z3.literal("graded"),
|
|
1048
|
+
traceId: z3.string(),
|
|
1049
|
+
value: z3.number().finite(),
|
|
1050
|
+
note: z3.string().optional()
|
|
1051
|
+
}),
|
|
1052
|
+
z3.object({ state: z3.literal("errored"), traceId: z3.string(), message: z3.string() }),
|
|
1053
|
+
z3.object({
|
|
1054
|
+
state: z3.literal("ungraded"),
|
|
1055
|
+
traceId: z3.string(),
|
|
1056
|
+
reason: z3.enum(["not sampled", "trace unavailable", "content unreadable"])
|
|
1057
|
+
})
|
|
1058
|
+
])
|
|
1059
|
+
),
|
|
1060
|
+
failures: z3.array(z3.string()),
|
|
1061
|
+
stats: z3.object({
|
|
1062
|
+
traceCount: z3.number().int().nonnegative(),
|
|
1063
|
+
hydratedCount: z3.number().int().nonnegative(),
|
|
1064
|
+
judgeCalls: z3.number().int().nonnegative(),
|
|
1065
|
+
durationMs: z3.number().nonnegative(),
|
|
1066
|
+
skippedRows: z3.number().int().nonnegative(),
|
|
1067
|
+
skippedReason: z3.literal("no trace").nullable()
|
|
1068
|
+
})
|
|
1069
|
+
});
|
|
1070
|
+
function parsePortableEvalResult(value) {
|
|
1071
|
+
return PortableEvalResultSchema.parse(value);
|
|
1072
|
+
}
|
|
1073
|
+
function importPortableEvaluator(rawArtifact, options = {}) {
|
|
1074
|
+
var _a;
|
|
1075
|
+
const artifact = PortableEvalArtifactSchema.parse(rawArtifact);
|
|
1076
|
+
if (options.expectedSha256 && !/^[a-f0-9]{64}$/.test(options.expectedSha256)) {
|
|
1077
|
+
throw new Error(
|
|
1078
|
+
"Raindrop portable evaluator expectedSha256 must be a lowercase SHA-256 digest"
|
|
1079
|
+
);
|
|
1080
|
+
}
|
|
1081
|
+
return {
|
|
1082
|
+
kind: "portable",
|
|
1083
|
+
artifact,
|
|
1084
|
+
expectedSha256: options.expectedSha256,
|
|
1085
|
+
judge: options.judge,
|
|
1086
|
+
limits: options.limits,
|
|
1087
|
+
slug: artifact.evaluator.slug,
|
|
1088
|
+
name: ((_a = options.name) == null ? void 0 : _a.trim()) || artifact.evaluator.slug,
|
|
1089
|
+
output: artifact.evaluator.outputType,
|
|
1090
|
+
scope: artifact.evaluator.scope
|
|
1091
|
+
};
|
|
1092
|
+
}
|
|
1093
|
+
async function evaluatePortableEvaluator(evaluator, input) {
|
|
1094
|
+
var _a;
|
|
1095
|
+
const artifact = await verifyPortableEvalArtifact(evaluator.artifact, {
|
|
1096
|
+
expectedSha256: evaluator.expectedSha256
|
|
1097
|
+
});
|
|
1098
|
+
const { runPortableEvaluator } = await import("./portable-runtime-GBE3SHBZ.mjs");
|
|
1099
|
+
const cases = (_a = input.cases) != null ? _a : [];
|
|
1100
|
+
if (cases.length > 0 && (cases.length !== input.traces.length || cases.some(
|
|
1101
|
+
(entry, index) => {
|
|
1102
|
+
var _a2;
|
|
1103
|
+
return entry.candidate.trace.event.id !== ((_a2 = input.traces[index]) == null ? void 0 : _a2.event.id);
|
|
1104
|
+
}
|
|
1105
|
+
))) {
|
|
1106
|
+
throw new Error("Raindrop portable evaluator cases must match traces exactly, in slice order");
|
|
1107
|
+
}
|
|
1108
|
+
const result = await runPortableEvaluator(evaluator, { ...input, cases });
|
|
1109
|
+
validatePortableResult(artifact, input.traces, result);
|
|
1110
|
+
return result;
|
|
1111
|
+
}
|
|
1112
|
+
async function verifyPortableEvalArtifact(rawArtifact, options = {}) {
|
|
1113
|
+
const artifact = PortableEvalArtifactSchema.parse(rawArtifact);
|
|
1114
|
+
if (artifact.traceProjectionSha256 !== TRACE_PROJECTION_SHA256) {
|
|
1115
|
+
throw new Error(
|
|
1116
|
+
`Raindrop portable evaluator ${artifact.evaluator.slug} targets a different trace projection`
|
|
1117
|
+
);
|
|
1118
|
+
}
|
|
1119
|
+
const digest = await artifactDigest(artifact);
|
|
1120
|
+
if (digest !== artifact.sha256) {
|
|
1121
|
+
throw new Error(
|
|
1122
|
+
`Raindrop portable evaluator ${artifact.evaluator.slug} content digest is invalid`
|
|
1123
|
+
);
|
|
1124
|
+
}
|
|
1125
|
+
if (options.expectedSha256 && digest !== options.expectedSha256) {
|
|
1126
|
+
throw new Error(
|
|
1127
|
+
`Raindrop portable evaluator ${artifact.evaluator.slug} does not match expectedSha256`
|
|
1128
|
+
);
|
|
1129
|
+
}
|
|
1130
|
+
return artifact;
|
|
1131
|
+
}
|
|
1132
|
+
function validatePortableResult(artifact, traces, result) {
|
|
1133
|
+
if (result.stats.traceCount !== traces.length) {
|
|
1134
|
+
throw new Error("Raindrop portable evaluator returned an inconsistent trace count");
|
|
1135
|
+
}
|
|
1136
|
+
const expected = new Set(traces.map((trace) => trace.event.id));
|
|
1137
|
+
if (expected.size !== traces.length) {
|
|
1138
|
+
throw new Error("Raindrop portable evaluator input trace ids must be unique");
|
|
1139
|
+
}
|
|
1140
|
+
const returned = /* @__PURE__ */ new Set();
|
|
1141
|
+
for (const outcome of result.outcomes) {
|
|
1142
|
+
if (!expected.has(outcome.traceId)) {
|
|
1143
|
+
throw new Error(`Raindrop portable evaluator returned foreign trace ${outcome.traceId}`);
|
|
1144
|
+
}
|
|
1145
|
+
if (returned.has(outcome.traceId)) {
|
|
1146
|
+
throw new Error(`Raindrop portable evaluator repeated trace ${outcome.traceId}`);
|
|
1147
|
+
}
|
|
1148
|
+
returned.add(outcome.traceId);
|
|
1149
|
+
if (outcome.state !== "graded") continue;
|
|
1150
|
+
const valid = artifact.evaluator.outputType === "boolean" ? "pass" in outcome : artifact.evaluator.outputType === "score" ? "score" in outcome : "value" in outcome;
|
|
1151
|
+
if (!valid) {
|
|
1152
|
+
throw new Error(
|
|
1153
|
+
`Raindrop portable evaluator ${artifact.evaluator.slug} returned the wrong graded value`
|
|
1154
|
+
);
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
const missing = [...expected].find((traceId) => !returned.has(traceId));
|
|
1158
|
+
if (missing) throw new Error(`Raindrop portable evaluator omitted trace ${missing}`);
|
|
1159
|
+
}
|
|
1160
|
+
async function artifactDigest(artifact) {
|
|
1161
|
+
var _a;
|
|
1162
|
+
if (!((_a = globalThis.crypto) == null ? void 0 : _a.subtle)) {
|
|
1163
|
+
throw new Error("Raindrop portable evaluator requires Web Crypto SHA-256 support");
|
|
1164
|
+
}
|
|
1165
|
+
const { sha256: _digest, ...unsigned } = artifact;
|
|
1166
|
+
const encoded = new TextEncoder().encode(canonicalJson(unsigned));
|
|
1167
|
+
const digest = await globalThis.crypto.subtle.digest("SHA-256", encoded);
|
|
1168
|
+
return [...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
1169
|
+
}
|
|
1170
|
+
function canonicalJson(value) {
|
|
1171
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
1172
|
+
if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
|
|
1173
|
+
return `{${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => `${JSON.stringify(key)}:${canonicalJson(entry)}`).join(",")}}`;
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
export {
|
|
1177
|
+
EvalScoreSchema,
|
|
1178
|
+
defineDataset,
|
|
1179
|
+
isEvalDataset,
|
|
1180
|
+
BooleanThresholdSchema,
|
|
1181
|
+
NumericThresholdSchema,
|
|
1182
|
+
defineEvaluatorProgram,
|
|
1183
|
+
defineLocalEvaluator,
|
|
1184
|
+
defineEvalSuite,
|
|
1185
|
+
isEvalSuiteDefinition,
|
|
1186
|
+
evaluatorName,
|
|
1187
|
+
evaluatorOutput,
|
|
1188
|
+
validateEvaluatorOutput,
|
|
1189
|
+
TraceSchema,
|
|
1190
|
+
EvalDatasetCaseIdSchema,
|
|
1191
|
+
CapturedTraceSnapshotSchema,
|
|
1192
|
+
EvalCaseTracePairSchema,
|
|
1193
|
+
projectWorkshopTrace,
|
|
1194
|
+
projectCapturedEvent,
|
|
1195
|
+
traceOutput,
|
|
1196
|
+
traceToolCalls,
|
|
1197
|
+
parsePortableEvalResult,
|
|
1198
|
+
importPortableEvaluator,
|
|
1199
|
+
evaluatePortableEvaluator,
|
|
1200
|
+
verifyPortableEvalArtifact
|
|
1201
|
+
};
|