@calmlens/sdk 0.15.0 → 0.16.2

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.
Files changed (38) hide show
  1. package/README.md +30 -10
  2. package/cjs/{CalmLensConnection-DoemramF.js → CalmLensConnection-5Hj3trGr.js} +2 -2
  3. package/cjs/{CalmLensUtils-Cv1Ylp9-.js → CalmLensUtils-BeIl1N6N.js} +7 -7
  4. package/cjs/{CalmLensVersion-CuxKdijk.js → CalmLensVersion-BGpB9t4-.js} +6 -1
  5. package/cjs/{CalmLensWebhooks-qrL-Zdu3.js → CalmLensWebhooks-CogUYk8-.js} +7 -7
  6. package/cjs/Classification-BNhgwGEm-DmA9VEuE.d.ts +4806 -0
  7. package/cjs/TestTriggers-CRKtulyp-vrzEq2wm.d.ts +44 -0
  8. package/cjs/{WebhookPayload-vy8HNMaK.d.ts → WebhookPayload-CJoIkGBD.d.ts} +1019 -5100
  9. package/cjs/app.d.ts +4 -3
  10. package/cjs/app.js +3 -3
  11. package/cjs/{index-Dz340UQ9.d.ts → index-C9Xw1aid.d.ts} +139 -141
  12. package/cjs/index.d.ts +4 -3
  13. package/cjs/index.js +1 -1
  14. package/cjs/server.d.ts +8 -7
  15. package/cjs/server.js +17 -22
  16. package/cjs/test-inputs.d.ts +2 -0
  17. package/cjs/test-inputs.js +265 -0
  18. package/cjs/testing.d.ts +5 -5
  19. package/cjs/testing.js +7943 -101
  20. package/esm/{CalmLensConnection-CQLoUoBd.js → CalmLensConnection-BAJdoZHy.js} +2 -2
  21. package/esm/{CalmLensUtils-B3S--hBG.js → CalmLensUtils-DqniTKJ8.js} +7 -7
  22. package/esm/{CalmLensVersion-N71PMJAz.js → CalmLensVersion-l_khh4nS.js} +6 -1
  23. package/esm/{CalmLensWebhooks-BxMSx1Vm.js → CalmLensWebhooks-BtrKKLvg.js} +7 -7
  24. package/esm/Classification-BNhgwGEm-DmA9VEuE.d.ts +4806 -0
  25. package/esm/TestTriggers-CRKtulyp-vrzEq2wm.d.ts +44 -0
  26. package/esm/{WebhookPayload-vy8HNMaK.d.ts → WebhookPayload-CJoIkGBD.d.ts} +1019 -5100
  27. package/esm/app.d.ts +4 -3
  28. package/esm/app.js +3 -3
  29. package/esm/{index-Dz340UQ9.d.ts → index-C9Xw1aid.d.ts} +139 -141
  30. package/esm/index.d.ts +4 -3
  31. package/esm/index.js +1 -1
  32. package/esm/server.d.ts +8 -7
  33. package/esm/server.js +17 -22
  34. package/esm/test-inputs.d.ts +2 -0
  35. package/esm/test-inputs.js +256 -0
  36. package/esm/testing.d.ts +5 -5
  37. package/esm/testing.js +7922 -80
  38. package/package.json +19 -7
@@ -0,0 +1,265 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region src/contract/TestTriggers-7yylawYV.js
3
+ const TEST_IMAGE_PALETTES = {
4
+ sexual: [
5
+ [
6
+ 255,
7
+ 20,
8
+ 147,
9
+ 255
10
+ ],
11
+ [
12
+ 255,
13
+ 105,
14
+ 180,
15
+ 255
16
+ ],
17
+ [
18
+ 199,
19
+ 21,
20
+ 133,
21
+ 255
22
+ ],
23
+ [
24
+ 255,
25
+ 69,
26
+ 0,
27
+ 255
28
+ ]
29
+ ],
30
+ violence: [
31
+ [
32
+ 139,
33
+ 0,
34
+ 0,
35
+ 255
36
+ ],
37
+ [
38
+ 220,
39
+ 20,
40
+ 60,
41
+ 255
42
+ ],
43
+ [
44
+ 178,
45
+ 34,
46
+ 34,
47
+ 255
48
+ ],
49
+ [
50
+ 255,
51
+ 0,
52
+ 0,
53
+ 255
54
+ ]
55
+ ],
56
+ harassment: [
57
+ [
58
+ 180,
59
+ 83,
60
+ 9,
61
+ 255
62
+ ],
63
+ [
64
+ 217,
65
+ 119,
66
+ 6,
67
+ 255
68
+ ],
69
+ [
70
+ 245,
71
+ 158,
72
+ 11,
73
+ 255
74
+ ],
75
+ [
76
+ 251,
77
+ 191,
78
+ 36,
79
+ 255
80
+ ]
81
+ ],
82
+ hate: [
83
+ [
84
+ 30,
85
+ 64,
86
+ 175,
87
+ 255
88
+ ],
89
+ [
90
+ 37,
91
+ 99,
92
+ 235,
93
+ 255
94
+ ],
95
+ [
96
+ 59,
97
+ 130,
98
+ 246,
99
+ 255
100
+ ],
101
+ [
102
+ 96,
103
+ 165,
104
+ 250,
105
+ 255
106
+ ]
107
+ ],
108
+ "criminal-activity": [
109
+ [
110
+ 6,
111
+ 95,
112
+ 70,
113
+ 255
114
+ ],
115
+ [
116
+ 5,
117
+ 150,
118
+ 105,
119
+ 255
120
+ ],
121
+ [
122
+ 16,
123
+ 185,
124
+ 129,
125
+ 255
126
+ ],
127
+ [
128
+ 52,
129
+ 211,
130
+ 153,
131
+ 255
132
+ ]
133
+ ],
134
+ "self-harm": [
135
+ [
136
+ 75,
137
+ 0,
138
+ 130,
139
+ 255
140
+ ],
141
+ [
142
+ 138,
143
+ 43,
144
+ 226,
145
+ 255
146
+ ],
147
+ [
148
+ 72,
149
+ 61,
150
+ 139,
151
+ 255
152
+ ],
153
+ [
154
+ 147,
155
+ 112,
156
+ 219,
157
+ 255
158
+ ]
159
+ ]
160
+ };
161
+ /** A project's test input key: eight hexadecimal characters only its members can see. */
162
+ const TEST_INPUT_KEY_PATTERN = /^[a-f0-9]{8}$/;
163
+ const TEXT_CODE_SIGNALS = [
164
+ "harassment",
165
+ "hate",
166
+ "criminal-activity",
167
+ "sexual.involving-minors"
168
+ ];
169
+ /**
170
+ * The text code that CalmLens classifies as `category` for the project with this test input key.
171
+ * @returns The code, or an empty string for a category without a text code
172
+ */
173
+ const generateTestTextCode = (category, testInputKey) => TEXT_CODE_SIGNALS.includes(category) ? `<!calmlens-test ${testInputKey} ${category}>` : "";
174
+ const TEST_TRIGGER_PATTERN = /<!calmlens-test\s+([a-f0-9]{8})\s+(harassment|hate|criminal-activity|sexual\.involving-minors)\s*>/gi;
175
+ /**
176
+ * The test signals in `text` whose codes carry the project's test input key. Codes with another
177
+ * key are ignored, so a code can only be used by the project it belongs to.
178
+ */
179
+ const detectTestTrigger = (text, testInputKey) => {
180
+ const signals = [];
181
+ for (const [, key, signal] of text.matchAll(TEST_TRIGGER_PATTERN)) {
182
+ if (key.toLowerCase() !== testInputKey.toLowerCase()) continue;
183
+ const testSignal = signal.toLowerCase();
184
+ if (!signals.includes(testSignal)) signals.push(testSignal);
185
+ }
186
+ return {
187
+ isTestTrigger: signals.length > 0,
188
+ signals
189
+ };
190
+ };
191
+ /** Sixteen cells encode two bits each using the category's four existing colours. */
192
+ const getTestImageKeyCells = (width, height) => {
193
+ return Array.from({ length: 16 }, (_, index) => {
194
+ const column = index % 4;
195
+ const row = Math.floor(index / 4);
196
+ const x = Math.floor(column * width / 4);
197
+ const y = Math.floor(row * height / 4);
198
+ return {
199
+ x,
200
+ y,
201
+ width: Math.floor((column + 1) * width / 4) - x,
202
+ height: Math.floor((row + 1) * height / 4) - y
203
+ };
204
+ });
205
+ };
206
+ const getTestImageKeyColors = (signal, testInputKey) => {
207
+ const colors = TEST_IMAGE_PALETTES[signal];
208
+ if (!colors || !TEST_INPUT_KEY_PATTERN.test(testInputKey)) throw new Error("Invalid image test signal or key");
209
+ return [...testInputKey].flatMap((character) => {
210
+ const value = Number.parseInt(character, 16);
211
+ return [colors[value >> 2], colors[value & 3]];
212
+ });
213
+ };
214
+ /**
215
+ * Gets all test trigger categories that support images
216
+ */
217
+ const getImageTestCategories = () => {
218
+ return Object.keys(TEST_IMAGE_PALETTES);
219
+ };
220
+ /** Paint a full-image 4×4 grid as RGBA pixels; callers choose their image encoder. */
221
+ const paintTestImage = (signal, testInputKey, width = 512, height = width) => {
222
+ if (!Number.isSafeInteger(width) || !Number.isSafeInteger(height) || width < 24 || height < 24) throw new RangeError("Test image dimensions must be integers of at least 24 pixels");
223
+ const colors = getTestImageKeyColors(signal, testInputKey);
224
+ const rgba = new Uint8Array(width * height * 4);
225
+ getTestImageKeyCells(width, height).forEach((cell, index) => {
226
+ for (let y = cell.y; y < cell.y + cell.height; y++) for (let x = cell.x; x < cell.x + cell.width; x++) rgba.set(colors[index], (y * width + x) * 4);
227
+ });
228
+ return rgba;
229
+ };
230
+ /** Decode the project key from pixels, tolerating resizing and lossy compression. */
231
+ const detectTestImage = (image, testInputKey) => {
232
+ const { width, height, rgba } = image;
233
+ if (!Number.isSafeInteger(width) || !Number.isSafeInteger(height) || width < 24 || height < 24 || rgba.length !== width * height * 4 || !TEST_INPUT_KEY_PATTERN.test(testInputKey)) return void 0;
234
+ const cells = getTestImageKeyCells(width, height);
235
+ for (const category of getImageTestCategories()) {
236
+ const colors = getTestImageKeyColors(category, testInputKey);
237
+ if (cells.every((cell, index) => {
238
+ const sample = [
239
+ 0,
240
+ 0,
241
+ 0
242
+ ];
243
+ let count = 0;
244
+ for (let y = cell.y + Math.ceil(cell.height / 4); y < cell.y + cell.height * 3 / 4; y++) for (let x = cell.x + Math.ceil(cell.width / 4); x < cell.x + cell.width * 3 / 4; x++) {
245
+ const offset = (y * width + x) * 4;
246
+ if (rgba[offset + 3] < 250) return false;
247
+ for (let c = 0; c < 3; c++) sample[c] += rgba[offset + c];
248
+ count++;
249
+ }
250
+ const distances = TEST_IMAGE_PALETTES[category].map((color) => sample.reduce((sum, value, c) => sum + (value / count - color[c]) ** 2, 0));
251
+ const nearest = distances.indexOf(Math.min(...distances));
252
+ return distances[nearest] <= 900 && TEST_IMAGE_PALETTES[category][nearest] === colors[index];
253
+ })) return category;
254
+ }
255
+ };
256
+ //#endregion
257
+ exports.TEST_IMAGE_PALETTES = TEST_IMAGE_PALETTES;
258
+ exports.TEST_INPUT_KEY_PATTERN = TEST_INPUT_KEY_PATTERN;
259
+ exports.detectTestImage = detectTestImage;
260
+ exports.detectTestTrigger = detectTestTrigger;
261
+ exports.generateTestTextCode = generateTestTextCode;
262
+ exports.getImageTestCategories = getImageTestCategories;
263
+ exports.getTestImageKeyCells = getTestImageKeyCells;
264
+ exports.getTestImageKeyColors = getTestImageKeyColors;
265
+ exports.paintTestImage = paintTestImage;
package/cjs/testing.d.ts CHANGED
@@ -1,12 +1,12 @@
1
- import { $ as ModerateTextOptions, A as CalmLensServerClientOptions, B as EnsureLensOptions, Ct as Event, F as CreateAssetSignedUrlOptions, H as FolderIdOptions, I as CreateFolderOptions, J as Lens, K as IterateAssetChildrenOptions, M as CdnServeOptions, Mt as PermissionGrant, Nt as Folder, Q as ListEventsOptions, R as DeleteAssetContentOptions, St as PostAssetSignedUrlResponse, T as AssetSearchResponse, Tt as TypedEvent, V as EnsureLensesOptions, X as ListAssetChildrenOptions, Z as ListAssetsOptions, at as RetrieveAssetOptions, ct as SignUploadTokenOptions, d as Asset, dt as SubmitAssetOptions, et as MoveAssetOptions, ft as UpdateAssetOptions, j as CdnAssetUrlOptions, lt as SignedUploadToken, mt as UploadAssetPartOptions, ot as RetryAssetOptions, p as AssetChildrenPage, pt as UpdateFolderOptions, q as IterateAssetsOptions, r as ClassificationCategory, st as SearchAssetsOptions, t as WebhookEventPayload, tt as MoveFolderOptions, vt as WaitForAssetDecisionOptions, x as AssetPage, xt as GetEventsResponse, z as DeleteAssetOptions, zt as AssetBinaryPayloadInput } from "./WebhookPayload-vy8HNMaK.js";
2
- //#region ../shared/src/TestTriggers.d.ts
3
- type ClassificationTestSignal = ClassificationCategory | "sexual.involving-minors" | "violence.graphic";
4
- //#endregion
5
- //#region ../shared/src/MediaTestTriggers.d.ts
1
+ import { $ as SearchAssetsOptions, A as DeleteAssetContentOptions, B as Lens, C as CdnAssetUrlOptions, D as CreateAssetSignedUrlOptions, G as ModerateTextOptions, H as ListAssetChildrenOptions, K as MoveAssetOptions, M as EnsureLensOptions, N as EnsureLensesOptions, O as CreateFolderOptions, P as FolderIdOptions, Q as RetryAssetOptions, R as IterateAssetChildrenOptions, S as CalmLensServerClientOptions, Tt as Folder, U as ListAssetsOptions, W as ListEventsOptions, Z as RetrieveAssetOptions, _ as AssetSearchResponse, _t as TypedEvent, a as AssetChildrenPage, at as UpdateFolderOptions, et as SignUploadTokenOptions, ht as Event, it as UpdateAssetOptions, j as DeleteAssetOptions, jt as AssetBinaryPayloadInput, mt as PostAssetSignedUrlResponse, n as WebhookEventPayload, ot as UploadAssetPartOptions, p as AssetPage, pt as GetEventsResponse, q as MoveFolderOptions, r as Asset, rt as SubmitAssetOptions, tt as SignedUploadToken, ut as WaitForAssetDecisionOptions, w as CdnServeOptions, wt as PermissionGrant, z as IterateAssetsOptions } from "./WebhookPayload-CJoIkGBD.js";
2
+ import { t as ClassificationTestSignal } from "./TestTriggers-CRKtulyp-vrzEq2wm.js";
3
+ //#region src/contract/MediaTestTriggers.d.ts
4
+ //#region packages/shared/src/MediaTestTriggers.d.ts
6
5
  export declare const MEDIA_TEST_SIGNALS: readonly ["sexual", "violence", "self-harm", "harassment", "hate", "criminal-activity", "violence.graphic"];
7
6
  /** Read this aloud, or render it as large, high-contrast text in a video frame. */
8
7
  export declare function generateMediaTestCode(signal: ClassificationTestSignal, testInputKey: string): string;
9
8
  //#endregion
9
+ //#endregion
10
10
  //#region src/testing/MockApiKey.d.ts
11
11
  export declare const MOCK_API_KEY_PREFIX = "sk_test_";
12
12
  export declare const createMockApiKey: (grants?: PermissionGrant[]) => string;