calmlens 0.21.0 → 0.22.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.
data/sig/calmlens.rbs CHANGED
@@ -31,6 +31,7 @@ module CalmLens
31
31
  ?headers: Hash[String, String], ?request_id: String?) -> void
32
32
  # Whole seconds from the `Retry-After` header.
33
33
  def retry_after: () -> Integer?
34
+ def local?: () -> bool
34
35
  def not_found?: () -> bool
35
36
  def retryable?: () -> bool
36
37
  def self.build: (String code, ?String? message, ?status: Integer?, ?details: Hash[String, json_value]?,
@@ -122,6 +123,9 @@ module CalmLens
122
123
  attr_reader events: Events
123
124
  attr_reader cdn: CDN
124
125
  attr_reader lenses: Lenses
126
+ attr_reader upload_presets: UploadPresets
127
+ attr_reader project_settings: ProjectSettings
128
+ attr_reader metadata_fields: MetadataFields
125
129
  attr_reader project_id: String
126
130
  attr_reader base_url: String
127
131
  attr_reader cdn_base_url: String
@@ -237,6 +241,25 @@ module CalmLens
237
241
  def delete: (lens_id_options options) -> nil
238
242
  end
239
243
 
244
+ class UploadPresets < Resource
245
+ def list: (?list_upload_presets_options options) -> upload_preset_page
246
+ def each: (?list_upload_presets_options options) { (upload_preset) -> void } -> nil
247
+ | (?list_upload_presets_options options) -> Enumerator[upload_preset, nil]
248
+ def ensure: (ensure_upload_presets_options options) -> ensure_upload_presets_response
249
+ def delete: (upload_preset_id_options options) -> nil
250
+ end
251
+
252
+ class ProjectSettings < Resource
253
+ def get: (?request_only_options options) -> project_settings_resource
254
+ def update: (update_project_settings_options options) -> project_settings_resource
255
+ end
256
+
257
+ class MetadataFields < Resource
258
+ def list: (?request_only_options options) -> metadata_fields_resource
259
+ def ensure: (ensure_metadata_fields_options options) -> metadata_fields_resource
260
+ def delete: (delete_metadata_field_options options) -> nil
261
+ end
262
+
240
263
  class UploadTokens < Resource
241
264
  TOKEN_PREFIX: String
242
265
  SIGNING_CONTEXT: String
@@ -379,6 +402,8 @@ module CalmLens
379
402
  # The HTTP status the mock answered with; nil when the request failed without a response.
380
403
  attr_accessor status: Integer?
381
404
  def json: () -> json_value
405
+ # An upload form's `options` (parsed) and `file` (its bytes); nil for any other body.
406
+ def form: () -> { 'options' => Hash[String, json_value], 'file' => String }?
382
407
  end
383
408
 
384
409
  interface _Clock
data/sig/error_codes.rbs CHANGED
@@ -37,12 +37,14 @@ module CalmLens
37
37
  PERMISSION_DENIED: String
38
38
  UPLOAD_TOO_LARGE: String
39
39
  DOCUMENT_TOO_MANY_ITEMS: String
40
+ MEDIA_DURATION_LIMIT: String
40
41
  INVALID_IMAGE: String
41
42
  IMAGE_TOO_LARGE: String
42
43
  FREE_UPLOADS_EXHAUSTED: String
43
44
  UPLOADS_PAUSED: String
44
45
  UNSUPPORTED_UPLOAD_TYPE: String
45
46
  INVALID_UPLOAD_PAYLOAD: String
47
+ UPLOAD_OPTIONS_IN_QUERY: String
46
48
  USE_UPLOAD_PART: String
47
49
  UPLOAD_NOT_OPEN: String
48
50
  INVALID_UPLOAD_PART_NUMBER: String
@@ -99,6 +101,14 @@ module CalmLens
99
101
  UPLOAD_PRESET_DAILY_LIMIT_REACHED: String
100
102
  UPLOAD_PRESET_ORIGIN_NOT_ALLOWED: String
101
103
  UPLOAD_PRESET_FIELD_NOT_ALLOWED: String
104
+ UPLOAD_PRESET_REVISION_CONFLICT: String
105
+ UPLOAD_PRESET_KEY_TAKEN: String
106
+ UPLOAD_PRESET_DAILY_LIMIT_REQUIRED: String
107
+ UPLOAD_PRESET_INVALID_FOLDER: String
108
+ UPLOAD_PRESET_INVALID_POLICY: String
109
+ PROJECT_SETTINGS_REVISION_CONFLICT: String
110
+ SEARCH_ESTIMATE_CHANGED: String
111
+ METADATA_FIELD_NOT_FOUND: String
102
112
  UPLOAD_TOKEN_INVALID: String
103
113
  UPLOAD_TOKEN_EXPIRED: String
104
114
  UPLOAD_TOKEN_USED: String
data/sig/types.rbs CHANGED
@@ -103,6 +103,7 @@ module CalmLens
103
103
  # at the CDN's `hls` resource (`hls/index.m3u8`) and played by its `embed` resource. Renditions list
104
104
  # video from the largest down, then audio.
105
105
  type asset_hls = { "renditions" => Array[asset_hls_rendition] }
106
+ type asset_hls_status = { "status" => String, "reason" => String? }
106
107
  type asset_rendered_kind = "image" | "pdf" | "video" | "audio"
107
108
  # The asset's one displayable file, as the CDN's `rendered` resource serves it: an image, a PDF, or
108
109
  # browser-safe video or audio. `peaks` is an audio waveform's normalised peaks.
@@ -193,13 +194,32 @@ module CalmLens
193
194
  # What decided the automated status: the `policy`'s categories, the asset's `children`, a
194
195
  # `hash-list` match, a `mandatory-rule` or `link-safety`.
195
196
  type moderation_source = "policy" | "children" | "hash-list" | "mandatory-rule" | "link-safety"
197
+ # The policy that made a decision: its ID, its revision then and, for a policy from a preset, the
198
+ # preset release it used.
199
+ type decision_policy = {
200
+ "id" => String,
201
+ "revision" => Integer,
202
+ "preset" => { "id" => String, "version" => Integer }?
203
+ }
204
+ # A review the human review queue is waiting for: when the asset joined it (Unix milliseconds),
205
+ # why, and the categories that made the decision uncertain.
206
+ type asset_pending_review = {
207
+ "requestedAt" => Integer,
208
+ "reason" => "sampled" | "uncertain",
209
+ "uncertainCategories" => Array[String]
210
+ }
196
211
  # Every field but `status`, `manualReviews`, `flaggedCategories`, `regions` and `timeline` is `nil`
197
- # until moderation decides.
212
+ # until moderation decides; `pendingReview` is `nil` when no review is waiting.
198
213
  type asset_moderation = {
199
214
  "manualReviews" => Array[asset_review],
200
215
  "status" => asset_moderation_status,
201
216
  # The policy's original decision; a reviewer's decision can change `status` without changing it.
202
217
  "automatedStatus" => asset_moderation_decision?,
218
+ # The policy that made the automated decision, as it was then.
219
+ "policy" => decision_policy?,
220
+ # The review the human review queue is waiting for, set with the automated decision that
221
+ # joined the queue; `nil` when no review is waiting.
222
+ "pendingReview" => asset_pending_review?,
203
223
  "source" => moderation_source?,
204
224
  # The mandatory rule that decided, when `source` is `mandatory-rule`; otherwise `nil`.
205
225
  "rule" => String?,
@@ -242,6 +262,7 @@ module CalmLens
242
262
  # Preview. The adaptive stream once streaming has prepared one for audio or video; `nil` for
243
263
  # other assets, until then, once the content is removed and while the asset is held.
244
264
  "hls" => asset_hls?,
265
+ "hlsStatus" => asset_hls_status?,
245
266
  "preview" => asset_preview?
246
267
  }
247
268
 
@@ -249,6 +270,8 @@ module CalmLens
249
270
  "id" => String,
250
271
  "projectId" => String,
251
272
  ?"parentId" => String?,
273
+ # The pages of the parent document a child shows, from 1; empty when unknown or not a child.
274
+ ?"parentPages" => Array[Integer],
252
275
  ?"folderId" => String?,
253
276
  ?"uploadPresetId" => String?,
254
277
  "createdAt" => Integer,
@@ -276,6 +299,9 @@ module CalmLens
276
299
  type likelihood = "very-unlikely" | "unlikely" | "possible" | "likely" | "very-likely"
277
300
  # not-supported: this processing path cannot assess the signal; unavailable: assessment failed.
278
301
  type not_evaluated_reason = "not-supported" | "unavailable"
302
+ # A processing feature's reason, which adds in-children: a document's or website's images are each
303
+ # a child asset with its own result (`assets.list_children`).
304
+ type feature_not_evaluated_reason = not_evaluated_reason | "in-children"
279
305
  type classification_category = "sexual" | "violence" | "self-harm" | "harassment" | "hate" | "criminal-activity"
280
306
 
281
307
  # `status: "evaluated"` carries `someScore`, `likelihood` and optionally `allScore`;
@@ -324,13 +350,13 @@ module CalmLens
324
350
  type person_detection_result = {
325
351
  "status" => "evaluated" | "not-evaluated",
326
352
  ?"people" => Array[detected_person],
327
- ?"reason" => not_evaluated_reason
353
+ ?"reason" => feature_not_evaluated_reason
328
354
  }
329
355
  # `status: "evaluated"` carries `faces`; `"not-evaluated"` carries `reason`.
330
356
  type face_detection_result = {
331
357
  "status" => "evaluated" | "not-evaluated",
332
358
  ?"faces" => Array[detected_face],
333
- ?"reason" => not_evaluated_reason
359
+ ?"reason" => feature_not_evaluated_reason
334
360
  }
335
361
  type detected_qr_code = { "value" => String, "box" => bounding_box }
336
362
  # A web link found in a QR code or in the text OCR extracted.
@@ -340,7 +366,7 @@ module CalmLens
340
366
  "status" => "evaluated" | "not-evaluated",
341
367
  ?"qrCodes" => Array[detected_qr_code],
342
368
  ?"links" => Array[detected_link],
343
- ?"reason" => not_evaluated_reason
369
+ ?"reason" => feature_not_evaluated_reason
344
370
  }
345
371
  # Link safety (preview, LinkSafety.ts).
346
372
  # What a link's destination is: `safe` when every reputation check passed, `adult` or `gambling`
@@ -404,7 +430,7 @@ module CalmLens
404
430
  "status" => "evaluated" | "not-evaluated",
405
431
  ?"provenance" => "ai-generated" | "ai-edited" | "unknown",
406
432
  ?"signals" => Array[provenance_signal],
407
- ?"reason" => not_evaluated_reason
433
+ ?"reason" => feature_not_evaluated_reason
408
434
  }
409
435
  # Where OCR found text in an image, and whether it is personal information.
410
436
  type text_region = { "box" => bounding_box, "personalInformation" => bool }
@@ -413,7 +439,7 @@ module CalmLens
413
439
  type ocr_result = {
414
440
  "status" => "evaluated" | "not-evaluated",
415
441
  ?"textRegions" => Array[text_region],
416
- ?"reason" => not_evaluated_reason
442
+ ?"reason" => feature_not_evaluated_reason
417
443
  }
418
444
 
419
445
  # How strongly each assessed category meets the policy and what the policy does with it.
@@ -424,7 +450,7 @@ module CalmLens
424
450
  # What decided a category's action: its `default` action, a policy score `below-threshold`, or the
425
451
  # `allowance` or `restriction` rules listed by `indexes` (at least one, the decisive rule first).
426
452
  type category_policy_source = { "kind" => "default" | "below-threshold" } |
427
- { "kind" => "allowance" | "restriction", "indexes" => Array[Integer] }
453
+ { "kind" => "allowance" | "restriction", "indexes" => Array[Integer], "conditionScore" => Float }
428
454
  type category_policy_settings_snapshot = {
429
455
  "action" => flagged_content_action,
430
456
  "allowances" => Array[policy_rule_snapshot], "restrictions" => Array[policy_rule_snapshot]
@@ -636,6 +662,81 @@ module CalmLens
636
662
  "nextCursor" => String?
637
663
  }
638
664
 
665
+ # ---- Configuration as data (UploadPreset.ts, ProjectConfiguration.ts) --------------------------
666
+
667
+ type upload_preset_access = "token" | "anyone"
668
+ # An upload preset's processing options, as the API returns them.
669
+ type upload_preset_processing_options = {
670
+ ?"keepContentAfterProcessing" => bool?,
671
+ ?"storeSensitiveMetadata" => bool?,
672
+ ?"features" => {
673
+ ?"ocr" => { "enabled" => bool }?,
674
+ ?"personDetection" => { "enabled" => bool }?,
675
+ ?"faceDetection" => { "enabled" => bool, ?"ageEstimation" => bool? }?,
676
+ ?"linkDetection" => { "enabled" => bool }?,
677
+ ?"streaming" => { "enabled" => bool }?
678
+ }?
679
+ }
680
+ # The rules for uploads made from browsers and apps. `key` is unique in its project; `revision`
681
+ # counts changes, starting at 1. Send it back with a change.
682
+ type upload_preset = {
683
+ "id" => String,
684
+ "projectId" => String,
685
+ ?"createdByUserId" => String?,
686
+ "key" => String,
687
+ "revision" => Integer,
688
+ "name" => String,
689
+ "access" => upload_preset_access,
690
+ "enabled" => bool,
691
+ ?"allowedContentTypes" => Array[String]?,
692
+ ?"maxSizeInBytes" => Integer?,
693
+ ?"folderId" => String?,
694
+ ?"policyId" => String?,
695
+ "visibility" => asset_visibility,
696
+ ?"processingOptions" => upload_preset_processing_options?,
697
+ "revealDecision" => bool,
698
+ ?"dailyUploadLimit" => Integer?,
699
+ ?"allowedOrigins" => Array[String]?,
700
+ "createdAt" => Integer,
701
+ "updatedAt" => Integer
702
+ }
703
+ type upload_preset_page = { "items" => Array[upload_preset], "hasMore" => bool, "nextCursor" => String? }
704
+ type ensure_upload_presets_response = { "uploadPresets" => Array[upload_preset] }
705
+
706
+ type remote_url_rule = { "mode" => "allow" | "deny", "domains" => Array[String] }
707
+ type human_review_settings = {
708
+ "allowedSamplePercent" => number,
709
+ "restrictedSamplePercent" => number,
710
+ "uncertaintyMarginPercent" => number,
711
+ "reviewMissingEvidence" => bool
712
+ }
713
+ type public_project_settings = {
714
+ "optOutJurisdictions" => Array[String],
715
+ "blockUnmoderatedAssets" => bool,
716
+ "storeSensitiveMetadata" => bool,
717
+ "streamingEnabled" => bool,
718
+ "aiMediaSearchEnabled" => bool,
719
+ "remoteUrlRule" => remote_url_rule?,
720
+ "websiteSubmissionsPerMinute" => Integer?,
721
+ "humanReview" => human_review_settings
722
+ }
723
+ # The project's settings, with defaults filled in. `revision` counts changes to the settings and
724
+ # metadata fields, starting at 1. Send it back with a change.
725
+ type project_settings_resource = { "projectId" => String, "revision" => Integer, "settings" => public_project_settings }
726
+
727
+ type metadata_field_type = "string" | "number" | "boolean" | "date" | "url"
728
+ type metadata_field_icon = "tag" | "hash" | "user" | "folder" | "layers" | "photo" | "link"
729
+ # A metadata field the portal shows and filters by. `color` is `#rrggbb`.
730
+ type metadata_field = {
731
+ "id" => String,
732
+ "title" => String,
733
+ ?"description" => String,
734
+ "type" => metadata_field_type,
735
+ "icon" => metadata_field_icon,
736
+ "color" => String
737
+ }
738
+ type metadata_fields_resource = { "projectId" => String, "revision" => Integer, "fields" => Array[metadata_field] }
739
+
639
740
  # ---- Folders (Folder.ts) --------------------------------------------------------------------
640
741
 
641
742
  type folder = {
@@ -1087,6 +1188,64 @@ module CalmLens
1087
1188
  ?request_options: request_options
1088
1189
  }
1089
1190
 
1191
+ # `sort` is `createdAt` and `id`, `createdAt` (oldest first) by default.
1192
+ type list_upload_presets_options = { ?cursor: String, ?page_size: Integer, ?sort: sort, ?request_options: request_options }
1193
+ # One preset's whole definition, by `key`; fields left out take their defaults. Send the `revision`
1194
+ # you read (0 for a preset that must not exist yet) to refuse a change made since.
1195
+ type upload_preset_definition = {
1196
+ key: String,
1197
+ name: String,
1198
+ ?revision: Integer,
1199
+ ?access: upload_preset_access,
1200
+ ?enabled: bool,
1201
+ ?allowed_content_types: Array[String]?,
1202
+ ?max_size_in_bytes: Integer?,
1203
+ ?folder_id: String?,
1204
+ ?policy_id: String?,
1205
+ ?visibility: asset_visibility,
1206
+ ?processing_options: processing_options_input?,
1207
+ ?reveal_decision: bool,
1208
+ ?daily_upload_limit: Integer?,
1209
+ ?allowed_origins: Array[String]?
1210
+ }
1211
+ type ensure_upload_presets_options = { upload_presets: Array[upload_preset_definition], ?request_options: request_options }
1212
+ type upload_preset_id_options = { upload_preset_id: String, ?request_options: request_options }
1213
+ # The complete settings: those left out return to their defaults.
1214
+ type project_settings_input = {
1215
+ ?opt_out_jurisdictions: Array[String],
1216
+ ?block_unmoderated_assets: bool,
1217
+ ?store_sensitive_metadata: bool,
1218
+ ?streaming_enabled: bool,
1219
+ ?ai_media_search_enabled: bool,
1220
+ ?remote_url_rule: { mode: "allow" | "deny", domains: Array[String] }?,
1221
+ ?website_submissions_per_minute: Integer?,
1222
+ ?human_review: {
1223
+ ?allowed_sample_percent: number,
1224
+ ?restricted_sample_percent: number,
1225
+ ?uncertainty_margin_percent: number,
1226
+ ?review_missing_evidence: bool
1227
+ }
1228
+ }
1229
+ # Send the `revision` you read to refuse settings changed since. `search_indexing_budget_units` is
1230
+ # needed when turning on `ai_media_search_enabled`.
1231
+ type update_project_settings_options = {
1232
+ ?revision: Integer,
1233
+ settings: project_settings_input,
1234
+ ?search_indexing_budget_units: number,
1235
+ ?request_options: request_options
1236
+ }
1237
+ type metadata_field_input = {
1238
+ id: String,
1239
+ title: String,
1240
+ ?description: String,
1241
+ type: metadata_field_type,
1242
+ icon: metadata_field_icon,
1243
+ color: String
1244
+ }
1245
+ # Fields to create or replace by ID; other fields are kept.
1246
+ type ensure_metadata_fields_options = { ?revision: Integer, fields: Array[metadata_field_input], ?request_options: request_options }
1247
+ type delete_metadata_field_options = { field_id: String, ?revision: Integer, ?request_options: request_options }
1248
+
1090
1249
  type asset_url_options = {
1091
1250
  # Exactly one of `asset_id` and `external_id`.
1092
1251
  ?asset_id: String,
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: calmlens
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.21.0
4
+ version: 0.22.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - CalmLens
@@ -32,6 +32,7 @@ files:
32
32
  - lib/calmlens/moderation_context.rb
33
33
  - lib/calmlens/option_keys.rb
34
34
  - lib/calmlens/policies.rb
35
+ - lib/calmlens/project_configuration.rb
35
36
  - lib/calmlens/resource.rb
36
37
  - lib/calmlens/response.rb
37
38
  - lib/calmlens/server_client.rb