@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.
- package/README.md +30 -10
- package/cjs/{CalmLensConnection-DoemramF.js → CalmLensConnection-5Hj3trGr.js} +2 -2
- package/cjs/{CalmLensUtils-Cv1Ylp9-.js → CalmLensUtils-BeIl1N6N.js} +7 -7
- package/cjs/{CalmLensVersion-CuxKdijk.js → CalmLensVersion-BGpB9t4-.js} +6 -1
- package/cjs/{CalmLensWebhooks-qrL-Zdu3.js → CalmLensWebhooks-CogUYk8-.js} +7 -7
- package/cjs/Classification-BNhgwGEm-DmA9VEuE.d.ts +4806 -0
- package/cjs/TestTriggers-CRKtulyp-vrzEq2wm.d.ts +44 -0
- package/cjs/{WebhookPayload-vy8HNMaK.d.ts → WebhookPayload-CJoIkGBD.d.ts} +1019 -5100
- package/cjs/app.d.ts +4 -3
- package/cjs/app.js +3 -3
- package/cjs/{index-Dz340UQ9.d.ts → index-C9Xw1aid.d.ts} +139 -141
- package/cjs/index.d.ts +4 -3
- package/cjs/index.js +1 -1
- package/cjs/server.d.ts +8 -7
- package/cjs/server.js +17 -22
- package/cjs/test-inputs.d.ts +2 -0
- package/cjs/test-inputs.js +265 -0
- package/cjs/testing.d.ts +5 -5
- package/cjs/testing.js +7943 -101
- package/esm/{CalmLensConnection-CQLoUoBd.js → CalmLensConnection-BAJdoZHy.js} +2 -2
- package/esm/{CalmLensUtils-B3S--hBG.js → CalmLensUtils-DqniTKJ8.js} +7 -7
- package/esm/{CalmLensVersion-N71PMJAz.js → CalmLensVersion-l_khh4nS.js} +6 -1
- package/esm/{CalmLensWebhooks-BxMSx1Vm.js → CalmLensWebhooks-BtrKKLvg.js} +7 -7
- package/esm/Classification-BNhgwGEm-DmA9VEuE.d.ts +4806 -0
- package/esm/TestTriggers-CRKtulyp-vrzEq2wm.d.ts +44 -0
- package/esm/{WebhookPayload-vy8HNMaK.d.ts → WebhookPayload-CJoIkGBD.d.ts} +1019 -5100
- package/esm/app.d.ts +4 -3
- package/esm/app.js +3 -3
- package/esm/{index-Dz340UQ9.d.ts → index-C9Xw1aid.d.ts} +139 -141
- package/esm/index.d.ts +4 -3
- package/esm/index.js +1 -1
- package/esm/server.d.ts +8 -7
- package/esm/server.js +17 -22
- package/esm/test-inputs.d.ts +2 -0
- package/esm/test-inputs.js +256 -0
- package/esm/testing.d.ts +5 -5
- package/esm/testing.js +7922 -80
- 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
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
//#
|
|
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;
|