@verdict-ai/api 0.0.0-stage → 0.2.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/LICENSE +9 -0
- package/README.md +21 -2
- package/dist/app.d.ts +94 -0
- package/dist/app.js +120 -0
- package/dist/app.js.map +1 -0
- package/dist/github.d.ts +15 -0
- package/dist/github.js +40 -0
- package/dist/github.js.map +1 -0
- package/dist/hub-pages.d.ts +24 -0
- package/dist/hub-pages.js +119 -0
- package/dist/hub-pages.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/openapi.d.ts +463 -0
- package/dist/openapi.js +58 -0
- package/dist/openapi.js.map +1 -0
- package/dist/present.d.ts +110 -0
- package/dist/present.js +10 -0
- package/dist/present.js.map +1 -0
- package/dist/queue-cloudflare.d.ts +17 -0
- package/dist/queue-cloudflare.js +11 -0
- package/dist/queue-cloudflare.js.map +1 -0
- package/dist/rate-limit.d.ts +44 -0
- package/dist/rate-limit.js +40 -0
- package/dist/rate-limit.js.map +1 -0
- package/dist/routes/admin.d.ts +4 -0
- package/dist/routes/admin.js +81 -0
- package/dist/routes/admin.js.map +1 -0
- package/dist/routes/batches.d.ts +4 -0
- package/dist/routes/batches.js +27 -0
- package/dist/routes/batches.js.map +1 -0
- package/dist/routes/evaluations.d.ts +4 -0
- package/dist/routes/evaluations.js +104 -0
- package/dist/routes/evaluations.js.map +1 -0
- package/dist/routes/hub.d.ts +12 -0
- package/dist/routes/hub.js +66 -0
- package/dist/routes/hub.js.map +1 -0
- package/dist/routes/project-versions.d.ts +4 -0
- package/dist/routes/project-versions.js +56 -0
- package/dist/routes/project-versions.js.map +1 -0
- package/dist/routes/projects.d.ts +4 -0
- package/dist/routes/projects.js +91 -0
- package/dist/routes/projects.js.map +1 -0
- package/dist/routes/promotions.d.ts +4 -0
- package/dist/routes/promotions.js +72 -0
- package/dist/routes/promotions.js.map +1 -0
- package/dist/routes/public-hub.d.ts +41 -0
- package/dist/routes/public-hub.js +119 -0
- package/dist/routes/public-hub.js.map +1 -0
- package/dist/routes/publications.d.ts +4 -0
- package/dist/routes/publications.js +79 -0
- package/dist/routes/publications.js.map +1 -0
- package/dist/routes/reports.d.ts +4 -0
- package/dist/routes/reports.js +84 -0
- package/dist/routes/reports.js.map +1 -0
- package/dist/routes/rubrics.d.ts +4 -0
- package/dist/routes/rubrics.js +50 -0
- package/dist/routes/rubrics.js.map +1 -0
- package/dist/routes/shared.d.ts +42 -0
- package/dist/routes/shared.js +94 -0
- package/dist/routes/shared.js.map +1 -0
- package/dist/server.d.ts +19 -0
- package/dist/server.js +69 -0
- package/dist/server.js.map +1 -0
- package/dist/worker.d.ts +58 -0
- package/dist/worker.js +81 -0
- package/dist/worker.js.map +1 -0
- package/package.json +69 -3
- package/wrangler.example.toml +53 -0
|
@@ -0,0 +1,463 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Describes the public REST operations for API discovery.
|
|
3
|
+
* The published paths mirror route registration; runtime validation remains owned by request schemas.
|
|
4
|
+
*/
|
|
5
|
+
import type { RouteGroup } from "./app.js";
|
|
6
|
+
/** The document for an app that serves only some route groups: paths of the others are left out. */
|
|
7
|
+
export declare function openapiFor(groups: readonly RouteGroup[]): {
|
|
8
|
+
paths: {
|
|
9
|
+
[k: string]: {
|
|
10
|
+
post: {
|
|
11
|
+
summary: string;
|
|
12
|
+
};
|
|
13
|
+
get: {
|
|
14
|
+
summary: string;
|
|
15
|
+
};
|
|
16
|
+
} | {
|
|
17
|
+
post: {
|
|
18
|
+
summary: string;
|
|
19
|
+
};
|
|
20
|
+
} | {
|
|
21
|
+
get: {
|
|
22
|
+
summary: string;
|
|
23
|
+
};
|
|
24
|
+
put: {
|
|
25
|
+
summary: string;
|
|
26
|
+
};
|
|
27
|
+
delete: {
|
|
28
|
+
summary: string;
|
|
29
|
+
};
|
|
30
|
+
} | {
|
|
31
|
+
get: {
|
|
32
|
+
summary: string;
|
|
33
|
+
};
|
|
34
|
+
} | {
|
|
35
|
+
post: {
|
|
36
|
+
summary: string;
|
|
37
|
+
};
|
|
38
|
+
get: {
|
|
39
|
+
summary: string;
|
|
40
|
+
};
|
|
41
|
+
} | {
|
|
42
|
+
get: {
|
|
43
|
+
summary: string;
|
|
44
|
+
};
|
|
45
|
+
} | {
|
|
46
|
+
post: {
|
|
47
|
+
summary: string;
|
|
48
|
+
};
|
|
49
|
+
} | {
|
|
50
|
+
post: {
|
|
51
|
+
summary: string;
|
|
52
|
+
};
|
|
53
|
+
} | {
|
|
54
|
+
post: {
|
|
55
|
+
summary: string;
|
|
56
|
+
};
|
|
57
|
+
} | {
|
|
58
|
+
get: {
|
|
59
|
+
summary: string;
|
|
60
|
+
};
|
|
61
|
+
} | {
|
|
62
|
+
post: {
|
|
63
|
+
summary: string;
|
|
64
|
+
};
|
|
65
|
+
} | {
|
|
66
|
+
get: {
|
|
67
|
+
summary: string;
|
|
68
|
+
};
|
|
69
|
+
} | {
|
|
70
|
+
post: {
|
|
71
|
+
summary: string;
|
|
72
|
+
};
|
|
73
|
+
} | {
|
|
74
|
+
get: {
|
|
75
|
+
summary: string;
|
|
76
|
+
};
|
|
77
|
+
} | {
|
|
78
|
+
delete: {
|
|
79
|
+
summary: string;
|
|
80
|
+
};
|
|
81
|
+
} | {
|
|
82
|
+
get: {
|
|
83
|
+
summary: string;
|
|
84
|
+
security: never[];
|
|
85
|
+
};
|
|
86
|
+
} | {
|
|
87
|
+
get: {
|
|
88
|
+
summary: string;
|
|
89
|
+
security: never[];
|
|
90
|
+
};
|
|
91
|
+
} | {
|
|
92
|
+
get: {
|
|
93
|
+
summary: string;
|
|
94
|
+
security: never[];
|
|
95
|
+
};
|
|
96
|
+
} | {
|
|
97
|
+
post: {
|
|
98
|
+
summary: string;
|
|
99
|
+
};
|
|
100
|
+
get: {
|
|
101
|
+
summary: string;
|
|
102
|
+
};
|
|
103
|
+
} | {
|
|
104
|
+
post: {
|
|
105
|
+
summary: string;
|
|
106
|
+
};
|
|
107
|
+
} | {
|
|
108
|
+
delete: {
|
|
109
|
+
summary: string;
|
|
110
|
+
};
|
|
111
|
+
} | {
|
|
112
|
+
post: {
|
|
113
|
+
summary: string;
|
|
114
|
+
};
|
|
115
|
+
get: {
|
|
116
|
+
summary: string;
|
|
117
|
+
};
|
|
118
|
+
} | {
|
|
119
|
+
delete: {
|
|
120
|
+
summary: string;
|
|
121
|
+
};
|
|
122
|
+
} | {
|
|
123
|
+
post: {
|
|
124
|
+
summary: string;
|
|
125
|
+
};
|
|
126
|
+
get: {
|
|
127
|
+
summary: string;
|
|
128
|
+
};
|
|
129
|
+
} | {
|
|
130
|
+
get: {
|
|
131
|
+
summary: string;
|
|
132
|
+
};
|
|
133
|
+
delete: {
|
|
134
|
+
summary: string;
|
|
135
|
+
};
|
|
136
|
+
} | {
|
|
137
|
+
post: {
|
|
138
|
+
summary: string;
|
|
139
|
+
};
|
|
140
|
+
} | {
|
|
141
|
+
post: {
|
|
142
|
+
summary: string;
|
|
143
|
+
};
|
|
144
|
+
} | {
|
|
145
|
+
get: {
|
|
146
|
+
summary: string;
|
|
147
|
+
};
|
|
148
|
+
} | {
|
|
149
|
+
get: {
|
|
150
|
+
summary: string;
|
|
151
|
+
};
|
|
152
|
+
} | {
|
|
153
|
+
post: {
|
|
154
|
+
summary: string;
|
|
155
|
+
};
|
|
156
|
+
get: {
|
|
157
|
+
summary: string;
|
|
158
|
+
};
|
|
159
|
+
} | {
|
|
160
|
+
get: {
|
|
161
|
+
summary: string;
|
|
162
|
+
};
|
|
163
|
+
delete: {
|
|
164
|
+
summary: string;
|
|
165
|
+
};
|
|
166
|
+
} | {
|
|
167
|
+
post: {
|
|
168
|
+
summary: string;
|
|
169
|
+
};
|
|
170
|
+
get: {
|
|
171
|
+
summary: string;
|
|
172
|
+
};
|
|
173
|
+
} | {
|
|
174
|
+
get: {
|
|
175
|
+
summary: string;
|
|
176
|
+
};
|
|
177
|
+
} | {
|
|
178
|
+
post: {
|
|
179
|
+
summary: string;
|
|
180
|
+
};
|
|
181
|
+
get: {
|
|
182
|
+
summary: string;
|
|
183
|
+
};
|
|
184
|
+
} | {
|
|
185
|
+
post: {
|
|
186
|
+
summary: string;
|
|
187
|
+
};
|
|
188
|
+
get: {
|
|
189
|
+
summary: string;
|
|
190
|
+
};
|
|
191
|
+
} | {
|
|
192
|
+
delete: {
|
|
193
|
+
summary: string;
|
|
194
|
+
};
|
|
195
|
+
};
|
|
196
|
+
};
|
|
197
|
+
openapi: string;
|
|
198
|
+
info: {
|
|
199
|
+
title: string;
|
|
200
|
+
version: string;
|
|
201
|
+
description: string;
|
|
202
|
+
};
|
|
203
|
+
servers: {
|
|
204
|
+
url: string;
|
|
205
|
+
}[];
|
|
206
|
+
security: {
|
|
207
|
+
bearer: never[];
|
|
208
|
+
}[];
|
|
209
|
+
components: {
|
|
210
|
+
securitySchemes: {
|
|
211
|
+
bearer: {
|
|
212
|
+
type: string;
|
|
213
|
+
scheme: string;
|
|
214
|
+
};
|
|
215
|
+
};
|
|
216
|
+
};
|
|
217
|
+
};
|
|
218
|
+
export declare const openapi: {
|
|
219
|
+
openapi: string;
|
|
220
|
+
info: {
|
|
221
|
+
title: string;
|
|
222
|
+
version: string;
|
|
223
|
+
description: string;
|
|
224
|
+
};
|
|
225
|
+
servers: {
|
|
226
|
+
url: string;
|
|
227
|
+
}[];
|
|
228
|
+
security: {
|
|
229
|
+
bearer: never[];
|
|
230
|
+
}[];
|
|
231
|
+
components: {
|
|
232
|
+
securitySchemes: {
|
|
233
|
+
bearer: {
|
|
234
|
+
type: string;
|
|
235
|
+
scheme: string;
|
|
236
|
+
};
|
|
237
|
+
};
|
|
238
|
+
};
|
|
239
|
+
paths: {
|
|
240
|
+
"/v1/rubrics": {
|
|
241
|
+
post: {
|
|
242
|
+
summary: string;
|
|
243
|
+
};
|
|
244
|
+
get: {
|
|
245
|
+
summary: string;
|
|
246
|
+
};
|
|
247
|
+
};
|
|
248
|
+
"/v1/rubrics/validate": {
|
|
249
|
+
post: {
|
|
250
|
+
summary: string;
|
|
251
|
+
};
|
|
252
|
+
};
|
|
253
|
+
"/v1/rubrics/{id}": {
|
|
254
|
+
get: {
|
|
255
|
+
summary: string;
|
|
256
|
+
};
|
|
257
|
+
put: {
|
|
258
|
+
summary: string;
|
|
259
|
+
};
|
|
260
|
+
delete: {
|
|
261
|
+
summary: string;
|
|
262
|
+
};
|
|
263
|
+
};
|
|
264
|
+
"/v1/rubrics/{id}/calibration": {
|
|
265
|
+
get: {
|
|
266
|
+
summary: string;
|
|
267
|
+
};
|
|
268
|
+
};
|
|
269
|
+
"/v1/evaluations": {
|
|
270
|
+
post: {
|
|
271
|
+
summary: string;
|
|
272
|
+
};
|
|
273
|
+
get: {
|
|
274
|
+
summary: string;
|
|
275
|
+
};
|
|
276
|
+
};
|
|
277
|
+
"/v1/evaluations/{id}": {
|
|
278
|
+
get: {
|
|
279
|
+
summary: string;
|
|
280
|
+
};
|
|
281
|
+
};
|
|
282
|
+
"/v1/evaluations/{id}/retry": {
|
|
283
|
+
post: {
|
|
284
|
+
summary: string;
|
|
285
|
+
};
|
|
286
|
+
};
|
|
287
|
+
"/v1/evaluations/{id}/scores": {
|
|
288
|
+
post: {
|
|
289
|
+
summary: string;
|
|
290
|
+
};
|
|
291
|
+
};
|
|
292
|
+
"/v1/evaluations/{id}/aggregate": {
|
|
293
|
+
post: {
|
|
294
|
+
summary: string;
|
|
295
|
+
};
|
|
296
|
+
};
|
|
297
|
+
"/v1/tasks": {
|
|
298
|
+
get: {
|
|
299
|
+
summary: string;
|
|
300
|
+
};
|
|
301
|
+
};
|
|
302
|
+
"/v1/batches": {
|
|
303
|
+
post: {
|
|
304
|
+
summary: string;
|
|
305
|
+
};
|
|
306
|
+
};
|
|
307
|
+
"/v1/hub/config": {
|
|
308
|
+
get: {
|
|
309
|
+
summary: string;
|
|
310
|
+
};
|
|
311
|
+
};
|
|
312
|
+
"/v1/hub/login": {
|
|
313
|
+
post: {
|
|
314
|
+
summary: string;
|
|
315
|
+
};
|
|
316
|
+
};
|
|
317
|
+
"/v1/hub/me": {
|
|
318
|
+
get: {
|
|
319
|
+
summary: string;
|
|
320
|
+
};
|
|
321
|
+
};
|
|
322
|
+
"/v1/hub/keys/{id}": {
|
|
323
|
+
delete: {
|
|
324
|
+
summary: string;
|
|
325
|
+
};
|
|
326
|
+
};
|
|
327
|
+
"/v1/public/rubrics": {
|
|
328
|
+
get: {
|
|
329
|
+
summary: string;
|
|
330
|
+
security: never[];
|
|
331
|
+
};
|
|
332
|
+
};
|
|
333
|
+
"/v1/public/rubrics/{owner}/{slug}": {
|
|
334
|
+
get: {
|
|
335
|
+
summary: string;
|
|
336
|
+
security: never[];
|
|
337
|
+
};
|
|
338
|
+
};
|
|
339
|
+
"/v1/public/publications/{id}": {
|
|
340
|
+
get: {
|
|
341
|
+
summary: string;
|
|
342
|
+
security: never[];
|
|
343
|
+
};
|
|
344
|
+
};
|
|
345
|
+
"/v1/publications": {
|
|
346
|
+
post: {
|
|
347
|
+
summary: string;
|
|
348
|
+
};
|
|
349
|
+
get: {
|
|
350
|
+
summary: string;
|
|
351
|
+
};
|
|
352
|
+
};
|
|
353
|
+
"/v1/publications/preview": {
|
|
354
|
+
post: {
|
|
355
|
+
summary: string;
|
|
356
|
+
};
|
|
357
|
+
};
|
|
358
|
+
"/v1/publications/{id}": {
|
|
359
|
+
delete: {
|
|
360
|
+
summary: string;
|
|
361
|
+
};
|
|
362
|
+
};
|
|
363
|
+
"/v1/projects": {
|
|
364
|
+
post: {
|
|
365
|
+
summary: string;
|
|
366
|
+
};
|
|
367
|
+
get: {
|
|
368
|
+
summary: string;
|
|
369
|
+
};
|
|
370
|
+
};
|
|
371
|
+
"/v1/projects/{project}": {
|
|
372
|
+
delete: {
|
|
373
|
+
summary: string;
|
|
374
|
+
};
|
|
375
|
+
};
|
|
376
|
+
"/v1/projects/{project}/environments": {
|
|
377
|
+
post: {
|
|
378
|
+
summary: string;
|
|
379
|
+
};
|
|
380
|
+
get: {
|
|
381
|
+
summary: string;
|
|
382
|
+
};
|
|
383
|
+
};
|
|
384
|
+
"/v1/projects/{project}/environments/{environment}": {
|
|
385
|
+
get: {
|
|
386
|
+
summary: string;
|
|
387
|
+
};
|
|
388
|
+
delete: {
|
|
389
|
+
summary: string;
|
|
390
|
+
};
|
|
391
|
+
};
|
|
392
|
+
"/v1/projects/{project}/environments/{environment}/promotions": {
|
|
393
|
+
post: {
|
|
394
|
+
summary: string;
|
|
395
|
+
};
|
|
396
|
+
};
|
|
397
|
+
"/v1/projects/{project}/environments/{environment}/rollbacks": {
|
|
398
|
+
post: {
|
|
399
|
+
summary: string;
|
|
400
|
+
};
|
|
401
|
+
};
|
|
402
|
+
"/v1/projects/{project}/history": {
|
|
403
|
+
get: {
|
|
404
|
+
summary: string;
|
|
405
|
+
};
|
|
406
|
+
};
|
|
407
|
+
"/v1/projects/{project}/rubrics": {
|
|
408
|
+
get: {
|
|
409
|
+
summary: string;
|
|
410
|
+
};
|
|
411
|
+
};
|
|
412
|
+
"/v1/projects/{project}/rubrics/{name}/versions": {
|
|
413
|
+
post: {
|
|
414
|
+
summary: string;
|
|
415
|
+
};
|
|
416
|
+
get: {
|
|
417
|
+
summary: string;
|
|
418
|
+
};
|
|
419
|
+
};
|
|
420
|
+
"/v1/projects/{project}/rubrics/{name}/versions/{id}": {
|
|
421
|
+
get: {
|
|
422
|
+
summary: string;
|
|
423
|
+
};
|
|
424
|
+
delete: {
|
|
425
|
+
summary: string;
|
|
426
|
+
};
|
|
427
|
+
};
|
|
428
|
+
"/v1/projects/{project}/reports/runs": {
|
|
429
|
+
post: {
|
|
430
|
+
summary: string;
|
|
431
|
+
};
|
|
432
|
+
get: {
|
|
433
|
+
summary: string;
|
|
434
|
+
};
|
|
435
|
+
};
|
|
436
|
+
"/v1/projects/{project}/reports/runs/{runId}": {
|
|
437
|
+
get: {
|
|
438
|
+
summary: string;
|
|
439
|
+
};
|
|
440
|
+
};
|
|
441
|
+
"/v1/projects/{project}/reports/comparisons": {
|
|
442
|
+
post: {
|
|
443
|
+
summary: string;
|
|
444
|
+
};
|
|
445
|
+
get: {
|
|
446
|
+
summary: string;
|
|
447
|
+
};
|
|
448
|
+
};
|
|
449
|
+
"/v1/admin/keys": {
|
|
450
|
+
post: {
|
|
451
|
+
summary: string;
|
|
452
|
+
};
|
|
453
|
+
get: {
|
|
454
|
+
summary: string;
|
|
455
|
+
};
|
|
456
|
+
};
|
|
457
|
+
"/v1/admin/keys/{id}": {
|
|
458
|
+
delete: {
|
|
459
|
+
summary: string;
|
|
460
|
+
};
|
|
461
|
+
};
|
|
462
|
+
};
|
|
463
|
+
};
|
package/dist/openapi.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
const GROUP_PATHS = {
|
|
2
|
+
evaluations: ["/v1/evaluations", "/v1/tasks", "/v1/batches"],
|
|
3
|
+
rubrics: ["/v1/rubrics"],
|
|
4
|
+
hub: ["/v1/hub", "/v1/public", "/v1/publications"],
|
|
5
|
+
control: ["/v1/projects"],
|
|
6
|
+
};
|
|
7
|
+
/** The document for an app that serves only some route groups: paths of the others are left out. */
|
|
8
|
+
export function openapiFor(groups) {
|
|
9
|
+
const off = Object.keys(GROUP_PATHS).filter((g) => !groups.includes(g)).flatMap((g) => GROUP_PATHS[g]);
|
|
10
|
+
const served = (path) => !off.some((prefix) => path === prefix || path.startsWith(`${prefix}/`));
|
|
11
|
+
return { ...openapi, paths: Object.fromEntries(Object.entries(openapi.paths).filter(([path]) => served(path))) };
|
|
12
|
+
}
|
|
13
|
+
export const openapi = {
|
|
14
|
+
openapi: "3.1.0",
|
|
15
|
+
info: { title: "Verdict Evaluation API", version: "0.1.0", description: "Customizable rubrics, pluggable judges (LLM / human / benchmark), customizable aggregation." },
|
|
16
|
+
servers: [{ url: "/" }],
|
|
17
|
+
security: [{ bearer: [] }],
|
|
18
|
+
components: { securitySchemes: { bearer: { type: "http", scheme: "bearer" } } },
|
|
19
|
+
paths: {
|
|
20
|
+
"/v1/rubrics": { post: { summary: "Create rubric (JSON or YAML body)" }, get: { summary: "List rubrics" } },
|
|
21
|
+
"/v1/rubrics/validate": { post: { summary: "Validate a rubric without storing it" } },
|
|
22
|
+
"/v1/rubrics/{id}": { get: { summary: "Get rubric" }, put: { summary: "Replace rubric" }, delete: { summary: "Delete rubric" } },
|
|
23
|
+
"/v1/rubrics/{id}/calibration": { get: { summary: "Calibration report (`?target=0.8&buckets=5&limit=1000`)" } },
|
|
24
|
+
"/v1/evaluations": { post: { summary: "Evaluate a subject (sync; `async:true` for 202). Optional Idempotency-Key header (1–255 chars); replay 200, conflict 409, TTL 24h" }, get: { summary: "List evaluations" } },
|
|
25
|
+
"/v1/evaluations/{id}": { get: { summary: "Get evaluation (`?evidence=true` for full text)" } },
|
|
26
|
+
"/v1/evaluations/{id}/retry": { post: { summary: "Re-enqueue a failed evaluation (202; unknown 404; not failed 409)" } },
|
|
27
|
+
"/v1/evaluations/{id}/scores": { post: { summary: "Submit a human score for a pending criterion" } },
|
|
28
|
+
"/v1/evaluations/{id}/aggregate": { post: { summary: "Re-aggregate with a different aggregation config (no re-judging)" } },
|
|
29
|
+
"/v1/tasks": { get: { summary: "Pending human-rating tasks (`?rater=`)" } },
|
|
30
|
+
"/v1/batches": { post: { summary: "Evaluate many subjects against one rubric and rank them. Optional Idempotency-Key header (1–255 chars); replay 200, conflict 409, TTL 24h" } },
|
|
31
|
+
"/v1/hub/config": { get: { summary: "Public: the GitHub OAuth client id for sign-in (null when the server publishes under tenant ids), and `signIn` when the server runs CLI sign-in itself (browser approval)" } },
|
|
32
|
+
"/v1/hub/login": { post: { summary: "Public: trade a GitHub token from the device flow for a hub API key bound to that account (201 { apiKey, keyId, handle, tenantId })" } },
|
|
33
|
+
"/v1/hub/me": { get: { summary: "Who this key publishes as" } },
|
|
34
|
+
"/v1/hub/keys/{id}": { delete: { summary: "Revoke one of this account's hub keys (sign out)" } },
|
|
35
|
+
"/v1/public/rubrics": { get: { summary: "Public, no key: search published cards (q, domain, locale, type, owner, limit ≤ 50); one result per owner/slug at its newest live version", security: [] } },
|
|
36
|
+
"/v1/public/rubrics/{owner}/{slug}": { get: { summary: "Public, no key: a card at ?version= (default: newest live) with its version history; 410 when that version was withdrawn", security: [] } },
|
|
37
|
+
"/v1/public/publications/{id}": { get: { summary: "Public, no key: one publication by id; 410 when withdrawn", security: [] } },
|
|
38
|
+
"/v1/publications": { post: { summary: "Publish a rubric version, chosen public cases and run summaries to the hub (one criterion, licence, binary threshold; 400 with issues)" }, get: { summary: "List this tenant's publications, withdrawn included" } },
|
|
39
|
+
"/v1/publications/preview": { post: { summary: "Build the publication without storing it: { ok, issues, warnings, publication } — the exact document publish would store" } },
|
|
40
|
+
"/v1/publications/{id}": { delete: { summary: "Withdraw a publication (it stays readable by id, marked withdrawn, and leaves search)" } },
|
|
41
|
+
"/v1/projects": { post: { summary: "Create a project: { name } (201; 409 already_exists)" }, get: { summary: "List this tenant's projects" } },
|
|
42
|
+
"/v1/projects/{project}": { delete: { summary: "Delete a project and everything in it. Body { confirm: \"<name>\" }" } },
|
|
43
|
+
"/v1/projects/{project}/environments": { post: { summary: "Create an environment: { name } (201; 409 already_exists)" }, get: { summary: "List a project's environments" } },
|
|
44
|
+
"/v1/projects/{project}/environments/{environment}": { get: { summary: "An environment and its pointers: which version of each rubric it runs. `?include=rubrics` adds each rubric document (what services poll); answers carry an ETag, and If-None-Match gets 304 while nothing changed" }, delete: { summary: "Delete an environment and its pointers; its history stays. Body { confirm: \"<name>\" }" } },
|
|
45
|
+
"/v1/projects/{project}/environments/{environment}/promotions": { post: { summary: "Move pointers, all or none: { changes: [{ name, versionId | null, expected | null }], note? } (≤ 20 changes; null versionId removes the pointer; 409 pointer_conflict with the current versions when `expected` is stale)" } },
|
|
46
|
+
"/v1/projects/{project}/environments/{environment}/rollbacks": { post: { summary: "Undo a pointer's latest change: { name, expected, note? } (409 pointer_conflict / nothing_to_roll_back)" } },
|
|
47
|
+
"/v1/projects/{project}/history": { get: { summary: "Pointer changes, newest first (`?environment=&name=&limit=`)" } },
|
|
48
|
+
"/v1/projects/{project}/rubrics": { get: { summary: "Rubric names of a project, with version counts" } },
|
|
49
|
+
"/v1/projects/{project}/rubrics/{name}/versions": { post: { summary: "Upload an immutable rubric version: { id, rubric, parentVersionId?, fork? }. The server freezes the rubric again and refuses another id (201 new, 200 already there, 413 over 1 MB)" }, get: { summary: "List a rubric's versions, newest first, without the rubric documents" } },
|
|
50
|
+
"/v1/projects/{project}/rubrics/{name}/versions/{id}": { get: { summary: "One version with its rubric document" }, delete: { summary: "Delete a version no environment points at (409 in_use otherwise)" } },
|
|
51
|
+
"/v1/projects/{project}/reports/runs": { post: { summary: "Report a run's numbers: { name, run, report, datasetName?, source?, version? }. No case ids, inputs or outputs are read. `version` uploads the run's rubric version when the server lacks it (201 new, 200 already reported, 400 unknown_version)" }, get: { summary: "Run reports, newest run first (`?name=&versionId=&dataset=&limit=`)" } },
|
|
52
|
+
"/v1/projects/{project}/reports/runs/{runId}": { get: { summary: "One run report" } },
|
|
53
|
+
"/v1/projects/{project}/reports/comparisons": { post: { summary: "Report a comparison of two reported runs: { name, comparison, source? } — counts per criterion, no per-case rows (400 unknown_run)" }, get: { summary: "Comparison reports, newest first (`?name=&head=&limit=`)" } },
|
|
54
|
+
"/v1/admin/keys": { post: { summary: "Create an API key for a tenant (admin)" }, get: { summary: "List a tenant's keys (admin, `?tenant=`)" } },
|
|
55
|
+
"/v1/admin/keys/{id}": { delete: { summary: "Revoke a key (admin)" } },
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
//# sourceMappingURL=openapi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openapi.js","sourceRoot":"","sources":["../src/openapi.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Projects stored evaluations into public REST representations.
|
|
3
|
+
* Evidence text and rating details are included only when requested; frozen rubric policy remains visible.
|
|
4
|
+
*/
|
|
5
|
+
import type { Evaluation } from "@verdict-ai/core";
|
|
6
|
+
/** Public view of an evaluation: strip bulky evidence text unless asked. */
|
|
7
|
+
export declare function present(ev: Evaluation, { evidence, ratings }?: {
|
|
8
|
+
evidence?: boolean | undefined;
|
|
9
|
+
ratings?: boolean | undefined;
|
|
10
|
+
}): {
|
|
11
|
+
rubric: {
|
|
12
|
+
id: string | undefined;
|
|
13
|
+
name: string;
|
|
14
|
+
version: string;
|
|
15
|
+
aggregation: {
|
|
16
|
+
method: "min" | "max" | "formula" | "mean" | "median" | "weighted_mean" | "weighted_sum" | "geometric_mean";
|
|
17
|
+
rater: "min" | "max" | "mean" | "median" | "majority" | "trimmed_mean";
|
|
18
|
+
normalize: false | [number, number];
|
|
19
|
+
missing: "fail" | "exclude" | "zero";
|
|
20
|
+
gates: {
|
|
21
|
+
criterion: string;
|
|
22
|
+
min?: number | undefined;
|
|
23
|
+
max?: number | undefined;
|
|
24
|
+
message?: string | undefined;
|
|
25
|
+
}[];
|
|
26
|
+
precision: number;
|
|
27
|
+
formula?: string | undefined;
|
|
28
|
+
grades?: {
|
|
29
|
+
label: string;
|
|
30
|
+
min: number;
|
|
31
|
+
}[] | undefined;
|
|
32
|
+
passThreshold?: number | undefined;
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
evidence: import("@verdict-ai/core").Evidence[] | {
|
|
36
|
+
chars: number;
|
|
37
|
+
inputIndex: number;
|
|
38
|
+
kind: import("@verdict-ai/core").Input["type"];
|
|
39
|
+
label: string;
|
|
40
|
+
tags: string[];
|
|
41
|
+
json?: unknown;
|
|
42
|
+
source?: string;
|
|
43
|
+
truncated?: boolean;
|
|
44
|
+
images?: import("@verdict-ai/core").ImageMeta[];
|
|
45
|
+
stats: {
|
|
46
|
+
chars: number;
|
|
47
|
+
words: number;
|
|
48
|
+
lines: number;
|
|
49
|
+
};
|
|
50
|
+
warnings?: string[];
|
|
51
|
+
}[];
|
|
52
|
+
criteria: {
|
|
53
|
+
criterionId: string;
|
|
54
|
+
name: string;
|
|
55
|
+
weight: number;
|
|
56
|
+
group?: string;
|
|
57
|
+
status: "scored" | "pending" | "error" | "excluded";
|
|
58
|
+
choice?: string;
|
|
59
|
+
score?: number;
|
|
60
|
+
normalized?: number;
|
|
61
|
+
choices?: Record<string, number>;
|
|
62
|
+
pending: number;
|
|
63
|
+
gate?: {
|
|
64
|
+
passed: boolean;
|
|
65
|
+
message?: string;
|
|
66
|
+
};
|
|
67
|
+
}[];
|
|
68
|
+
job?: {
|
|
69
|
+
attempts: number;
|
|
70
|
+
maxAttempts: number;
|
|
71
|
+
lastError?: string;
|
|
72
|
+
nextAttemptAt?: string;
|
|
73
|
+
deadLettered?: boolean;
|
|
74
|
+
};
|
|
75
|
+
id: string;
|
|
76
|
+
tenantId?: string;
|
|
77
|
+
idempotencyKey?: string;
|
|
78
|
+
rubricId?: string;
|
|
79
|
+
subject: import("@verdict-ai/core").Subject;
|
|
80
|
+
status: import("@verdict-ai/core").EvaluationStatus;
|
|
81
|
+
aggregate: import("@verdict-ai/core").AggregateResult;
|
|
82
|
+
pendingTasks: Array<{
|
|
83
|
+
criterionId: string;
|
|
84
|
+
raterId?: string;
|
|
85
|
+
allowedRaters?: string[];
|
|
86
|
+
instructions?: string;
|
|
87
|
+
}>;
|
|
88
|
+
checks?: Array<{
|
|
89
|
+
id: string;
|
|
90
|
+
probability: number | null;
|
|
91
|
+
passed: boolean;
|
|
92
|
+
action: "abort" | "fail" | "flag";
|
|
93
|
+
message?: string;
|
|
94
|
+
error?: string;
|
|
95
|
+
}>;
|
|
96
|
+
error?: string;
|
|
97
|
+
inputErrors?: import("@verdict-ai/core").InputError[];
|
|
98
|
+
usage: {
|
|
99
|
+
decisionCalls: number;
|
|
100
|
+
llmCalls: number;
|
|
101
|
+
inputTokens: number;
|
|
102
|
+
outputTokens: number;
|
|
103
|
+
durationMs: number;
|
|
104
|
+
};
|
|
105
|
+
metadata?: Record<string, unknown>;
|
|
106
|
+
webhook?: string;
|
|
107
|
+
batchId?: string;
|
|
108
|
+
createdAt: string;
|
|
109
|
+
updatedAt: string;
|
|
110
|
+
};
|
package/dist/present.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Public view of an evaluation: strip bulky evidence text unless asked. */
|
|
2
|
+
export function present(ev, { evidence = false, ratings = true } = {}) {
|
|
3
|
+
return {
|
|
4
|
+
...ev,
|
|
5
|
+
rubric: { id: ev.rubric.id, name: ev.rubric.name, version: ev.rubric.version, aggregation: ev.rubric.aggregation },
|
|
6
|
+
evidence: evidence ? ev.evidence : ev.evidence.map(({ text, ...rest }) => ({ ...rest, chars: text.length })),
|
|
7
|
+
criteria: ratings ? ev.criteria : ev.criteria.map(({ ratings: _r, ...c }) => c),
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=present.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"present.js","sourceRoot":"","sources":["../src/present.ts"],"names":[],"mappings":"AAKA,4EAA4E;AAC5E,MAAM,UAAU,OAAO,CAAC,EAAc,EAAE,EAAE,QAAQ,GAAG,KAAK,EAAE,OAAO,GAAG,IAAI,EAAE,GAAG,EAAE;IAC/E,OAAO;QACL,GAAG,EAAE;QACL,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE;QAClH,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QAC5G,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;KAChF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapts serializable engine jobs to a Cloudflare queue binding.
|
|
3
|
+
* Messages carry request data only; the consumer owns execution and retry policy.
|
|
4
|
+
*/
|
|
5
|
+
import type { Job, Queue } from "@verdict-ai/core";
|
|
6
|
+
/** Sends jobs to the queue binding; enqueue rejects when the binding cannot accept a message. */
|
|
7
|
+
export declare class CloudflareQueue implements Queue {
|
|
8
|
+
private binding;
|
|
9
|
+
constructor(binding: {
|
|
10
|
+
send(body: Job, options?: {
|
|
11
|
+
delaySeconds?: number;
|
|
12
|
+
}): Promise<unknown>;
|
|
13
|
+
});
|
|
14
|
+
enqueue(job: Job, opts?: {
|
|
15
|
+
delayMs?: number;
|
|
16
|
+
}): Promise<void>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Sends jobs to the queue binding; enqueue rejects when the binding cannot accept a message. */
|
|
2
|
+
export class CloudflareQueue {
|
|
3
|
+
binding;
|
|
4
|
+
constructor(binding) {
|
|
5
|
+
this.binding = binding;
|
|
6
|
+
}
|
|
7
|
+
async enqueue(job, opts) {
|
|
8
|
+
await this.binding.send(job, { delaySeconds: Math.ceil((opts?.delayMs ?? 0) / 1000) });
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=queue-cloudflare.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queue-cloudflare.js","sourceRoot":"","sources":["../src/queue-cloudflare.ts"],"names":[],"mappings":"AAMA,iGAAiG;AACjG,MAAM,OAAO,eAAe;IACN;IAApB,YAAoB,OAAmF;QAAnF,YAAO,GAAP,OAAO,CAA4E;IAAG,CAAC;IAC3G,KAAK,CAAC,OAAO,CAAC,GAAQ,EAAE,IAA2B;QACjD,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,YAAY,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,OAAO,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC;IACzF,CAAC;CACF"}
|