@buildinternet/releases-api-types 0.52.0 → 0.52.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buildinternet/releases-api-types",
3
- "version": "0.52.0",
3
+ "version": "0.52.1",
4
4
  "description": "Wire protocol — request/response types for the Releases registry API. Shared by web, workers, and clients.",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/api-types.ts CHANGED
@@ -216,6 +216,11 @@ import type {
216
216
  FeedbackUpdateBodySchema,
217
217
  FeedbackDeleteResponseSchema,
218
218
  } from "./schemas/feedback.js";
219
+ import type {
220
+ ClassificationSummarySchema,
221
+ ClassificationRecentResponseSchema,
222
+ ClassificationRecentItemSchema,
223
+ } from "./schemas/classifications.js";
219
224
  import type {
220
225
  RecommendationNotifyAddedBodySchema,
221
226
  RecommendationNotifyAddedResultSchema,
@@ -551,6 +556,11 @@ export {
551
556
  FeedbackUpdateBodySchema,
552
557
  FeedbackDeleteResponseSchema,
553
558
  } from "./schemas/feedback.js";
559
+ export {
560
+ ClassificationSummarySchema,
561
+ ClassificationRecentResponseSchema,
562
+ ClassificationRecentItemSchema,
563
+ } from "./schemas/classifications.js";
554
564
  export {
555
565
  RecommendationNotifyAddedBodySchema,
556
566
  RecommendationNotifyAddedResultSchema,
@@ -1755,6 +1765,11 @@ export type FeedbackListResponse = z.infer<typeof FeedbackListResponseSchema>;
1755
1765
  export type FeedbackUpdateBody = z.infer<typeof FeedbackUpdateBodySchema>;
1756
1766
  export type FeedbackDeleteResponse = z.infer<typeof FeedbackDeleteResponseSchema>;
1757
1767
 
1768
+ // ── Classification analytics ──
1769
+ export type ClassificationSummary = z.infer<typeof ClassificationSummarySchema>;
1770
+ export type ClassificationRecentResponse = z.infer<typeof ClassificationRecentResponseSchema>;
1771
+ export type ClassificationRecentItem = z.infer<typeof ClassificationRecentItemSchema>;
1772
+
1758
1773
  // ── Recommendations ──
1759
1774
  export type RecommendationNotifyAddedBody = z.infer<typeof RecommendationNotifyAddedBodySchema>;
1760
1775
  export type RecommendationNotifyAddedResult = z.infer<typeof RecommendationNotifyAddedResultSchema>;
@@ -0,0 +1,105 @@
1
+ import { z } from "zod";
2
+
3
+ /**
4
+ * Admin classification analytics (`GET /v1/admin/classifications/summary`
5
+ * and `/recent`). Decisions live in Analytics Engine; these shapes are the
6
+ * hydrated read model, not the positional point schema.
7
+ */
8
+
9
+ const ClassificationOriginSchema = z.enum(["ingest", "manual", "eval"]);
10
+ const ClassificationOriginFilterSchema = z.enum(["ingest", "manual", "eval", "all"]);
11
+ const ClassificationDispositionSchema = z.enum(["kept", "suppressed", "failed", "skipped"]);
12
+
13
+ const ProbabilityBinSchema = z.object({
14
+ /** Inclusive. Width is 0.1. `0.8` is the start of the threshold bin. */
15
+ start: z.number(),
16
+ /** Exclusive, except the last bin (`0.9`–`1`) which includes `1`. */
17
+ end: z.number(),
18
+ count: z.number(),
19
+ });
20
+
21
+ const ProbabilityHistogramSchema = z.object({
22
+ bins: z.array(ProbabilityBinSchema),
23
+ /** Sampled rows whose double is `< 0` (the absent sentinel). */
24
+ missing: z.number(),
25
+ });
26
+
27
+ /** `GET /v1/admin/classifications/summary`. */
28
+ export const ClassificationSummarySchema = z.object({
29
+ after: z.string(),
30
+ before: z.string(),
31
+ bucket: z.enum(["hour", "day"]),
32
+ origin: ClassificationOriginFilterSchema,
33
+ totals: z.object({
34
+ classified: z.number(),
35
+ kept: z.number(),
36
+ suppressed: z.number(),
37
+ failed: z.number(),
38
+ skipped: z.number(),
39
+ costUsd: z.number(),
40
+ /** `suppressed / (kept + suppressed)`, or null when the denominator is 0. */
41
+ suppressionRate: z.number().nullable(),
42
+ }),
43
+ series: z.array(
44
+ z.object({
45
+ t: z.string(),
46
+ kept: z.number(),
47
+ suppressed: z.number(),
48
+ failed: z.number(),
49
+ skipped: z.number(),
50
+ }),
51
+ ),
52
+ choices: z.array(z.object({ choice: z.string(), count: z.number() })),
53
+ choiceSeries: z.array(
54
+ z.object({
55
+ t: z.string(),
56
+ choices: z.record(z.string(), z.number()),
57
+ }),
58
+ ),
59
+ models: z.array(
60
+ z.object({
61
+ provider: z.string(),
62
+ model: z.string(),
63
+ count: z.number(),
64
+ costUsd: z.number(),
65
+ }),
66
+ ),
67
+ probability: z.object({
68
+ threshold: z.literal(0.8),
69
+ selected: ProbabilityHistogramSchema,
70
+ confidence: ProbabilityHistogramSchema,
71
+ }),
72
+ meta: z.object({
73
+ dataset: z.string(),
74
+ retentionDays: z.literal(90),
75
+ sampled: z.literal(true),
76
+ }),
77
+ });
78
+
79
+ /** One sampled decision from `GET /v1/admin/classifications/recent`. */
80
+ export const ClassificationRecentItemSchema = z.object({
81
+ timestamp: z.string(),
82
+ origin: ClassificationOriginSchema,
83
+ sourceId: z.string().nullable(),
84
+ sourceName: z.string().nullable(),
85
+ sourceSlug: z.string().nullable(),
86
+ orgSlug: z.string().nullable(),
87
+ releaseId: z.string().nullable(),
88
+ releaseTitle: z.string().nullable(),
89
+ provider: z.string(),
90
+ model: z.string(),
91
+ choice: z.string(),
92
+ selectedChoiceProbability: z.number().nullable(),
93
+ providerConfidence: z.number().nullable(),
94
+ disposition: ClassificationDispositionSchema,
95
+ reason: z.string(),
96
+ failureCategory: z.string(),
97
+ costUsd: z.number().nullable(),
98
+ durationMs: z.number().nullable(),
99
+ });
100
+
101
+ /** `GET /v1/admin/classifications/recent` — newest sampled rows, not weighted. */
102
+ export const ClassificationRecentResponseSchema = z.object({
103
+ items: z.array(ClassificationRecentItemSchema),
104
+ nextCursor: z.string().nullable(),
105
+ });