repzo 1.0.291 → 1.0.293

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 (34) hide show
  1. package/changelog.md +28 -0
  2. package/lib/index.d.ts +244 -2
  3. package/lib/index.js +541 -0
  4. package/lib/types/index.d.ts +4533 -1
  5. package/package.json +1 -1
  6. package/src/index.ts +1270 -0
  7. package/src/oas/activity-ai-object-detection-session-frame.yaml +600 -0
  8. package/src/oas/ai-object-detection-assigned-missions.yaml +283 -0
  9. package/src/oas/ai-object-detection-assignment-rule.yaml +357 -0
  10. package/src/oas/ai-object-detection-category.yaml +338 -0
  11. package/src/oas/ai-object-detection-dataset.yaml +342 -0
  12. package/src/oas/ai-object-detection-detection-settings.yaml +410 -0
  13. package/src/oas/ai-object-detection-inference.yaml +818 -0
  14. package/src/oas/ai-object-detection-label-group.yaml +265 -0
  15. package/src/oas/ai-object-detection-label-report.yaml +366 -0
  16. package/src/oas/ai-object-detection-label.yaml +395 -0
  17. package/src/oas/ai-object-detection-metric-result.yaml +734 -0
  18. package/src/oas/ai-object-detection-metric.yaml +559 -0
  19. package/src/oas/ai-object-detection-mission-results.yaml +370 -0
  20. package/src/oas/ai-object-detection-mission-set.yaml +250 -0
  21. package/src/oas/ai-object-detection-mission.yaml +349 -0
  22. package/src/oas/ai-object-detection-model-version-epoch.yaml +214 -0
  23. package/src/oas/ai-object-detection-model-version-train-agent.yaml +88 -0
  24. package/src/oas/ai-object-detection-model-version.yaml +567 -0
  25. package/src/oas/ai-object-detection-model.yaml +369 -0
  26. package/src/oas/ai-object-detection-segment.yaml +301 -0
  27. package/src/oas/ai-object-detection-session-analysis.yaml +1306 -0
  28. package/src/oas/ai-object-detection-session-election.yaml +193 -0
  29. package/src/oas/ai-object-detection-session-insight.yaml +418 -0
  30. package/src/oas/ai-object-detection-session.yaml +840 -0
  31. package/src/oas/ai-object-detection-settings.yaml +249 -0
  32. package/src/oas/ai-object-detection-task.yaml +1007 -0
  33. package/src/oas/object-detection-analytics-report.yaml +674 -0
  34. package/src/types/index.ts +5159 -1
@@ -0,0 +1,559 @@
1
+ openapi: 3.0.3
2
+ info:
3
+ title: Repzo API - AI Object Detection Metric
4
+ version: 1.0.0
5
+ description: |
6
+ **Metrics** are schema-strict planogram checks — the business layer on top
7
+ of Object Detection session analyses. A metric behaves like a typed
8
+ function: its `type` picks an implementation from the engine registry and
9
+ its `args` are validated against that type's declared argument schema
10
+ (required/optional fields, bounds). There are NO user formulas, flow
11
+ charts or scripts — every use case is a dedicated, well-tested type, and
12
+ adding one is a registry entry. Persistence is equally strict: `args` is a
13
+ Mongoose embedded DISCRIMINATOR keyed by the metric type (the promotions
14
+ model pattern), so unknown keys never reach the database.
15
+
16
+ **Output families.** Every type belongs to one family, which fixes what
17
+ the result's `answer` means and where its `score` 0..1 comes from:
18
+ - `compatibility` — `answer` is a boolean verdict; score = answer ? 1 : 0.
19
+ Mission points = score × the mission's weight.
20
+ - `numerical` — `answer` is a collected VALUE (data capture). Types may
21
+ accept an optional `target_answer`: score = answer ÷ target_answer
22
+ (clamped to 1). Without a target (and no evaluator-supplied factor) a
23
+ NON-ZERO answer earns full score (1); a missing or zero answer scores
24
+ 0.
25
+ - `share_of_shelf` — `answer` is the MAIN SEGMENT's measured quantity
26
+ (Σ cm of facing widths, Σ cm² of front-face area, or facing count);
27
+ `total` is the CONSIDERED CATEGORY — the same measure over facings
28
+ whose label belongs to ANY of the metric's segments (facings outside
29
+ every segment never dilute the share); `ratio` = answer / total;
30
+ `target_answer` = target_ratio × total; score =
31
+ min(1, ratio / target_ratio). Every segment row is reported as a
32
+ SegmentOutput in `computed.segments[]`; only the main row carries the
33
+ target and a score.
34
+
35
+ **Types.**
36
+ - `adjacent_block` (compatibility) — "these labels must stand together":
37
+ the stacks holding ANY of `labels` must form contiguous blocks (no
38
+ outside label cutting between them on a shelf) and the total facing
39
+ count must lie in `[from, to]`.
40
+ - `facings_count` (numerical) — data collection: how many facings of the
41
+ given labels does the shopper see (front row unless disabled)? An
42
+ optional `target_answer` ("I demand ≥ N facings") turns it into a
43
+ scored check: score = counted ÷ target, capped at 1.
44
+ - `on_shelf_availability` (numerical) — OSA: how much of what SHOULD be
45
+ on the shelf actually is? A selected label is AVAILABLE when ≥ 1
46
+ facing of it stands anywhere on a shelf (any depth row by default —
47
+ `front_row_only: true` narrows to the front). `answer` = available
48
+ count and `total` = selected count. An optional `target_answer` ("at
49
+ least N of these available", never above the label count) switches
50
+ scoring to answer ÷ target; without it the evaluator returns its own
51
+ factor `ratio` = answer ÷ total, so mission points = weight ×
52
+ availability. `missing` lists the out-of-stock labels with names.
53
+ - `share_of_shelf` (share_of_shelf) — references SEGMENTS
54
+ (`/ai-object-detection-segment`, reusable named label sets); each row
55
+ references exactly ONE segment (and a segment may appear in only one
56
+ row) and may override its labels for this metric only (empty override
57
+ = the segment's own). Exactly ONE row is the MAIN segment (`main:
58
+ true`; the first row when none is flagged) — `target_ratio` is the
59
+ goal FOR THAT SEGMENT; the other rows are context (competitors, the
60
+ category) measured for comparison, never scored. `measure` picks
61
+ linear width (`width_cm`), front-face area (`area_cm2`) or facing
62
+ count (`facings` — no physical sizes needed).
63
+
64
+ **Evaluation.** Every ENABLED metric a MISSION assigns to the session is
65
+ evaluated automatically against each successful session analysis (and
66
+ re-evaluated after a compose-only shelf recompute), producing one
67
+ `ai-object-detection-metric-result` per (analysis, metric).
68
+
69
+ **Registry introspection.** `GET ?registry=true` returns the type
70
+ declarations (args schema, output family, overwritable keys) so generic
71
+ clients can render forms without hardcoding.
72
+
73
+ **Multi-tenancy & lifecycle.** Scoped by `company_namespace` (injected
74
+ from the caller's token; SDK callers may pass an explicit override on
75
+ create), soft-deleted via `disabled: true`. `enabled` pauses evaluation
76
+ without losing the definition. Args are re-validated on every write
77
+ (`PUT` is a full re-definition — `type` and `args` are required);
78
+ invalid definitions are rejected with the full violation list;
79
+ share-of-shelf rows must reference LIVE segments. `PATCH` is not
80
+ supported (400 — use `PUT`). Admin-facing.
81
+ servers:
82
+ - url: https://sv.api.repzo.me
83
+ security:
84
+ - ApiKeyAuth: []
85
+ - JwtAuth: []
86
+ paths:
87
+ /ai-object-detection-metric:
88
+ get:
89
+ summary: List metrics (or the type registry)
90
+ operationId: findAiObjectDetectionMetric
91
+ parameters:
92
+ - in: query
93
+ name: registry
94
+ description: "`true` returns the metric TYPE declarations (args schema, output family, overwritable keys) instead of documents."
95
+ schema: { type: boolean }
96
+ - in: query
97
+ name: _id
98
+ description: "Filter by `_id`. Pass once or as `?_id[]=...` for multiple."
99
+ schema:
100
+ oneOf:
101
+ - type: string
102
+ - type: array
103
+ items: { type: string }
104
+ - in: query
105
+ name: name
106
+ description: Filter by exact name.
107
+ schema:
108
+ oneOf:
109
+ - type: string
110
+ - type: array
111
+ items: { type: string }
112
+ - in: query
113
+ name: search
114
+ description: Case-insensitive substring search on `name`.
115
+ schema: { type: string }
116
+ - in: query
117
+ name: type
118
+ description: Filter by metric type (registry key).
119
+ schema:
120
+ type: string
121
+ enum:
122
+ [
123
+ adjacent_block,
124
+ facings_count,
125
+ on_shelf_availability,
126
+ share_of_shelf,
127
+ ]
128
+ - in: query
129
+ name: enabled
130
+ schema: { type: boolean }
131
+ - in: query
132
+ name: disabled
133
+ description: "Include soft-deleted metrics (`true`) or only live ones (`false`). Omitted = no filter on the flag."
134
+ schema: { type: boolean }
135
+ - in: query
136
+ name: from_updatedAt
137
+ description: Lower bound on `updatedAt` (Unix ms).
138
+ schema: { type: number }
139
+ - in: query
140
+ name: to_updatedAt
141
+ description: Upper bound on `updatedAt` (Unix ms).
142
+ schema: { type: number }
143
+ - in: query
144
+ name: from_createdAt
145
+ description: Lower bound on `createdAt` (Unix ms).
146
+ schema: { type: number }
147
+ - in: query
148
+ name: to_createdAt
149
+ description: Upper bound on `createdAt` (Unix ms).
150
+ schema: { type: number }
151
+ - in: query
152
+ name: per_page
153
+ description: Page size. Defaults to the server's configured pagination limit.
154
+ schema: { type: integer, minimum: 1 }
155
+ - in: query
156
+ name: page
157
+ description: 1-indexed page number.
158
+ schema: { type: integer, minimum: 1 }
159
+ responses:
160
+ "200":
161
+ description: "Paginated metric documents (newest `_id` first), or the registry when `registry=true`."
162
+ content:
163
+ application/json:
164
+ schema:
165
+ oneOf:
166
+ - $ref: "#/components/schemas/MetricFindResult"
167
+ - $ref: "#/components/schemas/MetricRegistry"
168
+ post:
169
+ summary: Create a metric
170
+ operationId: createAiObjectDetectionMetric
171
+ requestBody:
172
+ required: true
173
+ content:
174
+ application/json:
175
+ schema:
176
+ $ref: "#/components/schemas/MetricCreateBody"
177
+ responses:
178
+ "201":
179
+ description: The created metric.
180
+ content:
181
+ application/json:
182
+ schema:
183
+ $ref: "#/components/schemas/Metric"
184
+ "400":
185
+ description: "Validation failed — the message lists EVERY args violation (e.g. `segments needs at least 1 segment(s); target_ratio must be ≤ 1`), or names unknown/deleted segments."
186
+ /ai-object-detection-metric/{id}:
187
+ get:
188
+ summary: Get a metric
189
+ operationId: getAiObjectDetectionMetric
190
+ parameters:
191
+ - in: path
192
+ name: id
193
+ required: true
194
+ schema: { type: string }
195
+ responses:
196
+ "200":
197
+ description: The metric document.
198
+ content:
199
+ application/json:
200
+ schema:
201
+ $ref: "#/components/schemas/Metric"
202
+ "400":
203
+ description: No metric with that id in the caller's namespace.
204
+ put:
205
+ summary: Update a metric (args re-validated)
206
+ description: |
207
+ A full re-definition: `type` and `args` are REQUIRED and re-validated
208
+ (the stored args discriminator is re-cast to the new type). `name`,
209
+ `description`, `enabled` and `disabled` are optional. `_id`,
210
+ `company_namespace` and `creator` in the body are ignored; `editor`
211
+ is stamped from the token.
212
+ operationId: updateAiObjectDetectionMetric
213
+ parameters:
214
+ - in: path
215
+ name: id
216
+ required: true
217
+ schema: { type: string }
218
+ requestBody:
219
+ required: true
220
+ content:
221
+ application/json:
222
+ schema:
223
+ $ref: "#/components/schemas/MetricUpdateBody"
224
+ responses:
225
+ "200":
226
+ description: The updated metric.
227
+ content:
228
+ application/json:
229
+ schema:
230
+ $ref: "#/components/schemas/Metric"
231
+ "400":
232
+ description: Validation failed — every violation listed.
233
+ "404":
234
+ description: Metric not found.
235
+ delete:
236
+ summary: Soft-delete a metric
237
+ description: "Sets `disabled: true` and stamps `editor`. Existing results keep their snapshots."
238
+ operationId: removeAiObjectDetectionMetric
239
+ parameters:
240
+ - in: path
241
+ name: id
242
+ required: true
243
+ schema: { type: string }
244
+ responses:
245
+ "200":
246
+ description: The disabled metric.
247
+ content:
248
+ application/json:
249
+ schema:
250
+ $ref: "#/components/schemas/Metric"
251
+ "404":
252
+ description: Metric not found.
253
+ components:
254
+ securitySchemes:
255
+ ApiKeyAuth:
256
+ type: apiKey
257
+ in: header
258
+ name: api-key
259
+ JwtAuth:
260
+ type: apiKey
261
+ in: header
262
+ name: Authorization
263
+ schemas:
264
+ AdjacentBlockArgs:
265
+ type: object
266
+ description: "Args for `type: adjacent_block` (compatibility family)."
267
+ required: [labels, from, to]
268
+ properties:
269
+ labels:
270
+ type: array
271
+ minItems: 1
272
+ items: { type: string }
273
+ description: Label ids that form the block.
274
+ from:
275
+ type: integer
276
+ minimum: 0
277
+ description: Minimum member facing count (inclusive).
278
+ to:
279
+ type: integer
280
+ minimum: 0
281
+ description: "Maximum member facing count (inclusive, from ≤ to)."
282
+ front_row_only:
283
+ type: boolean
284
+ default: true
285
+ description: Judge only the shopper-visible front row.
286
+ FacingsCountArgs:
287
+ type: object
288
+ description: "Args for `type: facings_count` (numerical family)."
289
+ required: [labels]
290
+ properties:
291
+ labels:
292
+ type: array
293
+ minItems: 1
294
+ items: { type: string }
295
+ description: Label ids to count.
296
+ target_answer:
297
+ type: integer
298
+ minimum: 1
299
+ description: "Optional demanded count — score = answer ÷ target_answer (clamped to 1). Absent: a non-zero count earns full score, zero earns 0."
300
+ front_row_only:
301
+ type: boolean
302
+ default: true
303
+ description: Count only the shopper-visible front row.
304
+ OnShelfAvailabilityArgs:
305
+ type: object
306
+ description: "Args for `type: on_shelf_availability` (numerical family)."
307
+ required: [labels]
308
+ properties:
309
+ labels:
310
+ type: array
311
+ minItems: 1
312
+ items: { type: string }
313
+ description: The label ids that SHOULD be on the shelf.
314
+ target_answer:
315
+ type: integer
316
+ minimum: 1
317
+ description: "Optional demanded count of AVAILABLE labels — score = answer ÷ target_answer (clamped to 1). Absent: score is the availability ratio (answer ÷ total). Rejected when it exceeds the number of labels selected, since that target could never be met."
318
+ front_row_only:
319
+ type: boolean
320
+ default: false
321
+ description: "Default false — a product in a back row is still available. true narrows availability to the shopper-visible front row."
322
+ ShareOfShelfArgs:
323
+ type: object
324
+ description: "Args for `type: share_of_shelf` (share family)."
325
+ required: [segments, target_ratio]
326
+ properties:
327
+ segments:
328
+ type: array
329
+ minItems: 1
330
+ description: |
331
+ Segment rows. Each row references exactly ONE segment
332
+ (`/ai-object-detection-segment`, a single ObjectId — never an
333
+ array) and a segment may appear in only one row (duplicates are
334
+ rejected: the same segment twice would double-count its share in
335
+ segment-level reporting). A row may override its segment's labels
336
+ FOR THIS METRIC ONLY — an empty/absent override means the
337
+ segment's own labels apply (and follow later segment edits
338
+ automatically).
339
+ Exactly ONE row must be the MAIN segment (`main: true`) — the one
340
+ `target_ratio` is defined for. Flagging none makes the FIRST row
341
+ main; flagging more than one is rejected. The other rows are
342
+ context (competitors, the category): measured and reported, never
343
+ scored.
344
+ items:
345
+ type: object
346
+ required: [segment]
347
+ properties:
348
+ segment:
349
+ type: string
350
+ description: Segment id (must exist and not be deleted).
351
+ labels:
352
+ type: array
353
+ items: { type: string }
354
+ description: Optional per-metric label override.
355
+ main:
356
+ type: boolean
357
+ default: false
358
+ description: "The row the metric's target is defined for — exactly one per metric."
359
+ target_ratio:
360
+ type: number
361
+ minimum: 0.001
362
+ maximum: 1
363
+ description: "The share the MAIN segment must reach — score = min(1, main_ratio / target_ratio)."
364
+ measure:
365
+ type: string
366
+ enum: [width_cm, area_cm2, facings]
367
+ default: width_cm
368
+ description: "width_cm = occupied shelf length (linear share; see first_in_stack), area_cm2 = front-face areas, facings = unit count."
369
+ front_row_only:
370
+ type: boolean
371
+ default: true
372
+ description: Measure only the shopper-visible front row.
373
+ first_in_stack:
374
+ type: boolean
375
+ default: true
376
+ description: "width_cm only: count each vertical pile ONCE — the BOTTOM (first-in-stack) object books the shelf distance, so stacked units don't inflate the linear share beyond the occupied shelf length. false = the legacy per-unit width sum. Ignored by area_cm2 / facings."
377
+ MetricArgs:
378
+ description: |
379
+ Arguments matching the type's schema — validated and NORMALIZED
380
+ server-side (unknown keys dropped, defaults applied, every
381
+ violation listed). The server stamps `args.type` internally for
382
+ the persistence discriminator; clients never send it.
383
+ oneOf:
384
+ - $ref: "#/components/schemas/AdjacentBlockArgs"
385
+ - $ref: "#/components/schemas/FacingsCountArgs"
386
+ - $ref: "#/components/schemas/OnShelfAvailabilityArgs"
387
+ - $ref: "#/components/schemas/ShareOfShelfArgs"
388
+ MetricCreateBody:
389
+ type: object
390
+ description: |
391
+ Body for creating a metric. The tenant key (`company_namespace`) is
392
+ optional for SDK callers and is otherwise injected from the caller's
393
+ session.
394
+ required: [name, type, args]
395
+ properties:
396
+ name: { type: string }
397
+ description: { type: string }
398
+ type:
399
+ type: string
400
+ description: Engine registry key — selects the args schema.
401
+ enum:
402
+ [
403
+ adjacent_block,
404
+ facings_count,
405
+ on_shelf_availability,
406
+ share_of_shelf,
407
+ ]
408
+ args:
409
+ $ref: "#/components/schemas/MetricArgs"
410
+ enabled:
411
+ type: boolean
412
+ default: true
413
+ description: OFF pauses evaluation without losing the definition.
414
+ company_namespace:
415
+ type: array
416
+ items: { type: string }
417
+ description: Optional tenant namespace override for SDK callers.
418
+ MetricUpdateBody:
419
+ type: object
420
+ description: |
421
+ Body for `PUT` — a full re-definition. `type` and `args` are required
422
+ and re-validated; the other fields are optional. Set `disabled: true`
423
+ to soft-delete. `company_namespace` is derived from the session — do
424
+ not send it.
425
+ required: [type, args]
426
+ properties:
427
+ name: { type: string }
428
+ description: { type: string }
429
+ type:
430
+ type: string
431
+ enum:
432
+ [
433
+ adjacent_block,
434
+ facings_count,
435
+ on_shelf_availability,
436
+ share_of_shelf,
437
+ ]
438
+ args:
439
+ $ref: "#/components/schemas/MetricArgs"
440
+ enabled: { type: boolean }
441
+ disabled:
442
+ type: boolean
443
+ description: Soft-delete flag.
444
+ Metric:
445
+ type: object
446
+ properties:
447
+ _id: { type: string }
448
+ disabled: { type: boolean }
449
+ name: { type: string }
450
+ description: { type: string }
451
+ type:
452
+ type: string
453
+ enum:
454
+ [
455
+ adjacent_block,
456
+ facings_count,
457
+ on_shelf_availability,
458
+ share_of_shelf,
459
+ ]
460
+ args:
461
+ description: "Stored args (strict per-type shape; includes the internal discriminator mirror `args.type`)."
462
+ oneOf:
463
+ - $ref: "#/components/schemas/AdjacentBlockArgs"
464
+ - $ref: "#/components/schemas/FacingsCountArgs"
465
+ - $ref: "#/components/schemas/OnShelfAvailabilityArgs"
466
+ - $ref: "#/components/schemas/ShareOfShelfArgs"
467
+ enabled: { type: boolean }
468
+ creator:
469
+ $ref: "#/components/schemas/UserStamp"
470
+ editor:
471
+ $ref: "#/components/schemas/UserStamp"
472
+ company_namespace:
473
+ type: array
474
+ items: { type: string }
475
+ createdAt: { type: string, format: date-time }
476
+ updatedAt: { type: string, format: date-time }
477
+ UserStamp:
478
+ type: object
479
+ description: "Who created / last edited the document (server-stamped from the token)."
480
+ properties:
481
+ _id: { type: string }
482
+ name: { type: string }
483
+ type:
484
+ type: string
485
+ enum: [admin, rep, client, tenant]
486
+ admin: { type: string }
487
+ rep: { type: string }
488
+ client: { type: string }
489
+ tenant: { type: string }
490
+ MetricArgField:
491
+ type: object
492
+ description: One argument declaration of a metric type (drives generic forms and server validation).
493
+ properties:
494
+ key: { type: string }
495
+ type:
496
+ type: string
497
+ enum: [labels, number, integer, boolean, enum, segments]
498
+ required: { type: boolean }
499
+ min: { type: number }
500
+ max: { type: number }
501
+ default:
502
+ description: Default applied when an optional arg is absent.
503
+ min_items:
504
+ type: integer
505
+ description: "labels / segments: minimum item count."
506
+ options:
507
+ type: array
508
+ items: { type: string }
509
+ description: "enum: the allowed values."
510
+ MetricRegistry:
511
+ type: object
512
+ description: "Response of `GET ?registry=true` — the metric type declarations."
513
+ properties:
514
+ engine_version:
515
+ type: integer
516
+ description: Bumped whenever a type's semantics change; results carry the version they were computed with.
517
+ types:
518
+ type: array
519
+ items:
520
+ type: object
521
+ properties:
522
+ type:
523
+ type: string
524
+ enum:
525
+ [
526
+ adjacent_block,
527
+ facings_count,
528
+ on_shelf_availability,
529
+ share_of_shelf,
530
+ ]
531
+ output:
532
+ type: string
533
+ enum: [compatibility, numerical, share_of_shelf]
534
+ args:
535
+ type: array
536
+ items:
537
+ $ref: "#/components/schemas/MetricArgField"
538
+ overwritable:
539
+ type: array
540
+ items: { type: string }
541
+ description: "Result output keys a human may override (`score` / `ratio` are always derived)."
542
+ MetricFindResult:
543
+ type: object
544
+ description: Standard paginated result envelope.
545
+ properties:
546
+ data:
547
+ type: array
548
+ items:
549
+ $ref: "#/components/schemas/Metric"
550
+ total_result: { type: number }
551
+ current_count: { type: number }
552
+ total_pages: { type: number }
553
+ current_page: { type: number }
554
+ per_page: { type: number }
555
+ first_page_url: { type: string }
556
+ last_page_url: { type: string }
557
+ next_page_url: { type: string, nullable: true }
558
+ prev_page_url: { type: string, nullable: true }
559
+ path: { type: string }