@camstack/addon-provider-amcrest 0.1.7 → 0.1.9

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/dist/addon.js CHANGED
@@ -4633,7 +4633,7 @@ function _instanceof(cls, params = {}) {
4633
4633
  return inst;
4634
4634
  }
4635
4635
  //#endregion
4636
- //#region ../types/dist/sleep-DJaTV2D7.mjs
4636
+ //#region ../types/dist/sleep-Baang_XW.mjs
4637
4637
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4638
4638
  EventCategory["SystemBoot"] = "system.boot";
4639
4639
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -6737,6 +6737,18 @@ function method(input, output, options) {
6737
6737
  timeoutMs: options?.timeoutMs
6738
6738
  };
6739
6739
  }
6740
+ /**
6741
+ * A wrapper/system-only method: served exclusively by the cap's system-level
6742
+ * provider (`InferProvider`), and OPTIONAL on `InferNativeProvider` so per-device
6743
+ * driver natives don't stub out a wrapper concern (e.g. a cross-device cache
6744
+ * overview). The `systemOnly: true` literal is what `InferNativeProvider` keys on.
6745
+ */
6746
+ function systemMethod(input, output, options) {
6747
+ return {
6748
+ ...method(input, output, options),
6749
+ systemOnly: true
6750
+ };
6751
+ }
6740
6752
  /** Shorthand to define an event schema */
6741
6753
  function event(data) {
6742
6754
  return { data };
@@ -11830,6 +11842,7 @@ var PipelineAddonSchemaSchema = object({
11830
11842
  defaultModelId: string(),
11831
11843
  defaultModelIdByFormat: record(string(), string()).optional(),
11832
11844
  enabledByDefault: boolean().optional(),
11845
+ backfillIntoExistingOverrides: boolean().optional(),
11833
11846
  defaultConfidence: number(),
11834
11847
  group: string().optional(),
11835
11848
  configSchema: array(ConfigFieldBridge).readonly().optional()
@@ -12011,7 +12024,15 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
12011
12024
  image: _instanceof(Uint8Array).optional(),
12012
12025
  referenceImage: string().optional(),
12013
12026
  deviceId: number().optional(),
12014
- sessionId: string().optional()
12027
+ sessionId: string().optional(),
12028
+ /**
12029
+ * Execution plane. 'full' (default) runs the whole tree — benchmark,
12030
+ * reference-image, and detail-subtree calls. 'frame' is the live
12031
+ * per-frame dispatch: ONLY root-plane steps run; crop children
12032
+ * (inputClasses ≠ null) are skipped and served per-track via
12033
+ * pipelineRunner.runDetailSubtree (two-plane design).
12034
+ */
12035
+ plane: _enum(["full", "frame"]).optional()
12015
12036
  }), PipelineRunResultBridge, { kind: "mutation" }), method(object({
12016
12037
  engine: PipelineEngineChoiceSchema.optional(),
12017
12038
  steps: array(PipelineStepInputSchema).min(1),
@@ -12169,6 +12190,47 @@ var zonesCapability = {
12169
12190
  runtimeState: object({ zones: array(ZoneSchema).readonly() })
12170
12191
  };
12171
12192
  /**
12193
+ * A bounding box in NORMALIZED [0,1] frame coordinates for `getNativeCrop`. The
12194
+ * decode worker resolves it against the RETAINED native frame's real pixel dims,
12195
+ * so the caller supplies only the detection-res bbox divided by the detection
12196
+ * dims — no native resolution to plumb.
12197
+ */
12198
+ var NativeCropBboxSchema = object({
12199
+ x: number(),
12200
+ y: number(),
12201
+ w: number(),
12202
+ h: number()
12203
+ });
12204
+ /** Result of a best-effort native-resolution crop (`getNativeCrop`). */
12205
+ var NativeCropResultSchema = object({
12206
+ /** Packed rgb (24-bit) pixels of the crop. */
12207
+ bytes: _instanceof(Uint8Array),
12208
+ width: number().int().positive(),
12209
+ height: number().int().positive()
12210
+ });
12211
+ /** Parent detection context passed to `runDetailSubtree` — the crop's
12212
+ * originating detection, in FRAME-space coordinates. Reuses
12213
+ * `NativeCropBboxSchema`'s `{x,y,w,h}` shape (same numeric fields; here
12214
+ * the coordinates are frame-space rather than getNativeCrop's
12215
+ * normalized [0,1] convention). */
12216
+ var DetailParentSchema = object({
12217
+ bbox: NativeCropBboxSchema,
12218
+ className: string()
12219
+ });
12220
+ /** One child-step result from `runDetailSubtree` — an embedding, label,
12221
+ * or refined detection produced by running the crop-subtree on a
12222
+ * single tracked detection. */
12223
+ var DetailResultSchema = object({
12224
+ stepId: string(),
12225
+ className: string(),
12226
+ score: number(),
12227
+ /** FRAME-space bbox (already mapped back from crop space). */
12228
+ bbox: NativeCropBboxSchema.optional(),
12229
+ embedding: string().optional(),
12230
+ label: string().optional(),
12231
+ alignedCropJpeg: string().optional()
12232
+ });
12233
+ /**
12172
12234
  * Per-camera tunable ranges + defaults. Single source of truth used
12173
12235
  * by both the Zod data schema (validation + default fallback) and
12174
12236
  * the device settings UI (slider min/max/step). Touch one place and
@@ -12424,7 +12486,17 @@ var RunnerLocalMetricsSchema = object({
12424
12486
  avgInferenceTimeMs: number(),
12425
12487
  queueDepth: number()
12426
12488
  });
12427
- method(RunnerCameraConfigSchema, object({ success: literal(true) }), { kind: "mutation" }), method(object({ deviceId: number() }), object({ success: literal(true) }), { kind: "mutation" }), method(ReportMotionInputSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), RunnerLocalLoadSchema), method(_void(), RunnerLocalMetricsSchema), method(object({ deviceId: number() }), CameraMetricsSchema.nullable()), method(_void(), array(CameraMetricsWithDeviceIdSchema).readonly()), method(_void(), array(number()).readonly());
12489
+ method(RunnerCameraConfigSchema, object({ success: literal(true) }), { kind: "mutation" }), method(object({ deviceId: number() }), object({ success: literal(true) }), { kind: "mutation" }), method(ReportMotionInputSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), RunnerLocalLoadSchema), method(_void(), RunnerLocalMetricsSchema), method(object({ deviceId: number() }), CameraMetricsSchema.nullable()), method(_void(), array(CameraMetricsWithDeviceIdSchema).readonly()), method(_void(), array(number()).readonly()), method(object({
12490
+ handle: FrameHandleSchema,
12491
+ bbox: NativeCropBboxSchema,
12492
+ maxWidth: number().int().positive().optional()
12493
+ }), NativeCropResultSchema.nullable()), method(object({
12494
+ deviceId: number(),
12495
+ frameHandle: FrameHandleSchema.optional(),
12496
+ cropJpeg: string().optional(),
12497
+ parent: DetailParentSchema,
12498
+ steps: array(string()).optional()
12499
+ }), object({ details: array(DetailResultSchema) }).nullable(), { kind: "mutation" });
12428
12500
  /**
12429
12501
  * Hardware / firmware motion sensor cap — binary detected state plus
12430
12502
  * a timestamp of the last observation. Distinct from
@@ -18099,7 +18171,17 @@ var TrackSchema = object({
18099
18171
  /** Cumulative normalized distance travelled (0..1 units = full frame width). */
18100
18172
  totalDistance: number(),
18101
18173
  state: TrackStateSchema,
18102
- active: boolean()
18174
+ active: boolean(),
18175
+ /** Deterministic key-event importance score in [0,1] (server-computed at
18176
+ * track expiry, recomputed on late label). Absent on legacy rows written
18177
+ * before scoring shipped — consumers degrade to absence / compute-on-read. */
18178
+ importance: number().optional(),
18179
+ /** Id of the track's highest-confidence ObjectEvent (its representative
18180
+ * "best" frame). Absent when the track produced no object events. */
18181
+ bestEventId: string().optional(),
18182
+ /** Tag of the importance sub-signal that dominated the score
18183
+ * (identity|dwell|proximity|class|confidence|travel|zone). */
18184
+ importanceReason: string().optional()
18103
18185
  });
18104
18186
  var BaseEventFields = {
18105
18187
  id: string(),
@@ -18164,8 +18246,18 @@ var ObjectEventSchema = object({
18164
18246
  frameHeight: number().optional(),
18165
18247
  /** MediaStore key for the crop attached to this event (if any). */
18166
18248
  mediaKey: string().optional(),
18249
+ /** Design B: MediaStore key of the track's native-resolution key frame (the
18250
+ * best-detection full frame). Resolve via the event-media data-plane
18251
+ * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`) for a detail view that
18252
+ * draws `bbox` over the native frame. Absent on legacy rows / non-decoded
18253
+ * sources — consumers fall back to `mediaKey` (the tight crop). */
18254
+ keyFrameMediaKey: string().optional(),
18167
18255
  /** Populated by B5 (recording playback URL for this event). */
18168
- mediaUrl: string().optional()
18256
+ mediaUrl: string().optional(),
18257
+ /** The parent track's key-event importance [0,1], propagated to every object
18258
+ * event of the track (so an event row can be sorted by importance without a
18259
+ * track join). Absent on legacy rows / before the track was scored. */
18260
+ importance: number().optional()
18169
18261
  });
18170
18262
  var AudioEventSchema = object({
18171
18263
  ...BaseEventFields,
@@ -18189,7 +18281,8 @@ var MediaFileKindEnum = _enum([
18189
18281
  "fullFrame",
18190
18282
  "fullFrameBoxed",
18191
18283
  "faceCrop",
18192
- "plateCrop"
18284
+ "plateCrop",
18285
+ "keyFrame"
18193
18286
  ]);
18194
18287
  var MediaFileSchema = object({
18195
18288
  key: string(),
@@ -18210,6 +18303,32 @@ var DeviceEventQueryInput = object({
18210
18303
  projection: _enum(["full", "slim"]).optional()
18211
18304
  });
18212
18305
  var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
18306
+ var KeyEventQueryInput = object({
18307
+ deviceId: number(),
18308
+ /** Window lower bound (track firstSeen ≥ since). */
18309
+ since: number(),
18310
+ /** Window upper bound (track firstSeen ≤ until). */
18311
+ until: number(),
18312
+ limit: number().int().min(1).max(200).default(50),
18313
+ /** Drop tracks scoring below this importance. */
18314
+ minImportance: number().min(0).max(1).optional(),
18315
+ /** Restrict to a single class (e.g. 'person'). */
18316
+ classFilter: string().optional()
18317
+ });
18318
+ var KeyEventSchema = object({
18319
+ /** The representative event id (the track's best ObjectEvent, else its trackId). */
18320
+ id: string(),
18321
+ trackId: string(),
18322
+ /** Track start time (firstSeen). */
18323
+ timestamp: number(),
18324
+ className: string(),
18325
+ label: string().optional(),
18326
+ importance: number(),
18327
+ /** Highest-confidence ObjectEvent id for the track (empty when none). */
18328
+ bestEventId: string(),
18329
+ /** Track lifetime in ms (lastSeen - firstSeen). */
18330
+ windowMs: number().optional()
18331
+ });
18213
18332
  var TrackedDetectionSchema = object({
18214
18333
  trackId: string(),
18215
18334
  className: string(),
@@ -18239,7 +18358,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
18239
18358
  }), array(TrackSchema).readonly()), method(object({ deviceId: number() }), _void(), {
18240
18359
  kind: "mutation",
18241
18360
  auth: "admin"
18242
- }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({
18361
+ }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
18243
18362
  deviceId: number(),
18244
18363
  since: number(),
18245
18364
  until: number(),
@@ -19043,7 +19162,20 @@ var snapshotCapability = {
19043
19162
  invalidateCache: method(object({ deviceId: number() }), _void(), {
19044
19163
  kind: "mutation",
19045
19164
  auth: "admin"
19046
- })
19165
+ }),
19166
+ /**
19167
+ * Cache-only batch overview — answers from the wrapper's in-memory cache in
19168
+ * O(n) and NEVER triggers a capture. Lets a grid skip requesting images for
19169
+ * devices that never produced a frame, and gives it an ETag per device for
19170
+ * conditional (304-able) image fetches. `lastCapturedAt`/`cacheAgeMs`/`etag`
19171
+ * are null for a device with no cached frame.
19172
+ */
19173
+ getSnapshotOverview: systemMethod(object({ deviceIds: array(number()).min(1).max(200) }), array(object({
19174
+ deviceId: number(),
19175
+ lastCapturedAt: number().nullable(),
19176
+ cacheAgeMs: number().nullable(),
19177
+ etag: string().nullable()
19178
+ })))
19047
19179
  },
19048
19180
  status: {
19049
19181
  schema: SnapshotStatusSchema,
@@ -19300,10 +19432,32 @@ method(_void(), array(TurnServerSchema).readonly());
19300
19432
  * b. `finishAuthentication({userId, response})` → server verifies
19301
19433
  * the assertion, bumps the credential counter, returns ok.
19302
19434
  *
19435
+ * 2b. Usernameless (discoverable-credential) authentication — the
19436
+ * passkey IS the primary factor, no password leg:
19437
+ * a. `beginDiscoverableAuthentication({})` → assertion options with
19438
+ * EMPTY `allowCredentials` (the browser offers every resident
19439
+ * passkey it holds for this RP) + `userVerification: 'required'`
19440
+ * (the passkey replaces both factors, so UV is mandatory).
19441
+ * The challenge is stored server-side, NOT bound to any user.
19442
+ * b. `finishDiscoverableAuthentication({response})` → the provider
19443
+ * resolves the credential by the response's credential id,
19444
+ * verifies the assertion against the stored challenge + that
19445
+ * credential's public key/counter, and returns the OWNING
19446
+ * `userId` — the caller (core auth router) mints the session.
19447
+ *
19303
19448
  * 3. Management:
19304
19449
  * - `listPasskeys({userId})` — enumerate user's enrolled credentials.
19305
19450
  * - `removePasskey({userId, credentialId})` — revoke one credential.
19306
19451
  *
19452
+ * 4. Second-factor preference (opt-in, default OFF):
19453
+ * Enrolling a passkey only enables passkey-FIRST sign-in. It is
19454
+ * demanded as a second factor after a password login ONLY when the
19455
+ * user explicitly opts in via `setSecondFactorPreference`.
19456
+ * - `getSecondFactorPreference({userId})` → `{ enabled }` (missing
19457
+ * row ⇒ `enabled: false`).
19458
+ * - `setSecondFactorPreference({userId, enabled})` — persisted by
19459
+ * the providing addon beside its credentials.
19460
+ *
19307
19461
  * Challenges are short-lived (5 min, in-memory). The cap is internal —
19308
19462
  * the admin-ui composes the begin/finish round-trip and never exposes
19309
19463
  * the cap to non-admins.
@@ -19346,6 +19500,17 @@ method(object({
19346
19500
  }), object({ verified: boolean() }), {
19347
19501
  kind: "mutation",
19348
19502
  access: "view"
19503
+ }), method(object({}), object({ optionsJSON: record(string(), unknown()) }), {
19504
+ kind: "mutation",
19505
+ access: "view"
19506
+ }), method(object({
19507
+ /** AuthenticationResponseJSON from the browser. */
19508
+ response: record(string(), unknown()) }), object({
19509
+ verified: boolean(),
19510
+ userId: string().nullable()
19511
+ }), {
19512
+ kind: "mutation",
19513
+ access: "view"
19349
19514
  }), method(object({ userId: string() }), array(PasskeySummarySchema), { auth: "admin" }), method(object({
19350
19515
  userId: string(),
19351
19516
  credentialId: string()
@@ -19353,6 +19518,13 @@ method(object({
19353
19518
  kind: "mutation",
19354
19519
  auth: "admin",
19355
19520
  access: "delete"
19521
+ }), method(object({ userId: string() }), object({ enabled: boolean() }), { auth: "admin" }), method(object({
19522
+ userId: string(),
19523
+ enabled: boolean()
19524
+ }), object({ success: literal(true) }), {
19525
+ kind: "mutation",
19526
+ auth: "admin",
19527
+ access: "create"
19356
19528
  });
19357
19529
  /**
19358
19530
  * `videoclips` — the unified, navigable-clip surface for a camera.
@@ -20154,7 +20326,17 @@ var FaceInfoSchema = object({
20154
20326
  recognizedIdentityId: string().optional(),
20155
20327
  identityName: string().optional(),
20156
20328
  assigned: boolean(),
20157
- base64: string().optional()
20329
+ base64: string().optional(),
20330
+ /** Design B: the face bbox (pixel space) on the key frame — lets a detail
20331
+ * view draw the box over the native `keyFrameMediaKey` frame. Absent on
20332
+ * legacy rows written before design B. */
20333
+ faceBbox: BoundingBoxSchema.optional(),
20334
+ /** Design B: MediaStore key of the track's native-resolution key frame.
20335
+ * Fetch the native JPEG via the event-media data-plane
20336
+ * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`). Absent when the
20337
+ * track produced no key frame (e.g. native/onboard source) — the UI falls
20338
+ * back to the inline `base64` face crop. */
20339
+ keyFrameMediaKey: string().optional()
20158
20340
  });
20159
20341
  var FaceFilterEnum = _enum([
20160
20342
  "unassigned",
@@ -24572,6 +24754,12 @@ Object.freeze({
24572
24754
  addonId: null,
24573
24755
  access: "view"
24574
24756
  },
24757
+ "pipelineAnalytics.getKeyEvents": {
24758
+ capName: "pipeline-analytics",
24759
+ capScope: "device",
24760
+ addonId: null,
24761
+ access: "view"
24762
+ },
24575
24763
  "pipelineAnalytics.getMotionEvents": {
24576
24764
  capName: "pipeline-analytics",
24577
24765
  capScope: "device",
@@ -25100,12 +25288,24 @@ Object.freeze({
25100
25288
  addonId: null,
25101
25289
  access: "view"
25102
25290
  },
25291
+ "pipelineRunner.getNativeCrop": {
25292
+ capName: "pipeline-runner",
25293
+ capScope: "system",
25294
+ addonId: null,
25295
+ access: "view"
25296
+ },
25103
25297
  "pipelineRunner.reportMotion": {
25104
25298
  capName: "pipeline-runner",
25105
25299
  capScope: "system",
25106
25300
  addonId: null,
25107
25301
  access: "create"
25108
25302
  },
25303
+ "pipelineRunner.runDetailSubtree": {
25304
+ capName: "pipeline-runner",
25305
+ capScope: "system",
25306
+ addonId: null,
25307
+ access: "create"
25308
+ },
25109
25309
  "plateGallery.correctPlateText": {
25110
25310
  capName: "plate-gallery",
25111
25311
  capScope: "system",
@@ -25466,6 +25666,12 @@ Object.freeze({
25466
25666
  addonId: null,
25467
25667
  access: "view"
25468
25668
  },
25669
+ "snapshot.getSnapshotOverview": {
25670
+ capName: "snapshot",
25671
+ capScope: "device",
25672
+ addonId: null,
25673
+ access: "view"
25674
+ },
25469
25675
  "snapshot.invalidateCache": {
25470
25676
  capName: "snapshot",
25471
25677
  capScope: "device",
@@ -26144,6 +26350,12 @@ Object.freeze({
26144
26350
  addonId: null,
26145
26351
  access: "view"
26146
26352
  },
26353
+ "userPasskeys.beginDiscoverableAuthentication": {
26354
+ capName: "user-passkeys",
26355
+ capScope: "system",
26356
+ addonId: null,
26357
+ access: "view"
26358
+ },
26147
26359
  "userPasskeys.beginRegistration": {
26148
26360
  capName: "user-passkeys",
26149
26361
  capScope: "system",
@@ -26156,12 +26368,24 @@ Object.freeze({
26156
26368
  addonId: null,
26157
26369
  access: "view"
26158
26370
  },
26371
+ "userPasskeys.finishDiscoverableAuthentication": {
26372
+ capName: "user-passkeys",
26373
+ capScope: "system",
26374
+ addonId: null,
26375
+ access: "view"
26376
+ },
26159
26377
  "userPasskeys.finishRegistration": {
26160
26378
  capName: "user-passkeys",
26161
26379
  capScope: "system",
26162
26380
  addonId: null,
26163
26381
  access: "create"
26164
26382
  },
26383
+ "userPasskeys.getSecondFactorPreference": {
26384
+ capName: "user-passkeys",
26385
+ capScope: "system",
26386
+ addonId: null,
26387
+ access: "view"
26388
+ },
26165
26389
  "userPasskeys.listPasskeys": {
26166
26390
  capName: "user-passkeys",
26167
26391
  capScope: "system",
@@ -26174,6 +26398,12 @@ Object.freeze({
26174
26398
  addonId: null,
26175
26399
  access: "delete"
26176
26400
  },
26401
+ "userPasskeys.setSecondFactorPreference": {
26402
+ capName: "user-passkeys",
26403
+ capScope: "system",
26404
+ addonId: null,
26405
+ access: "create"
26406
+ },
26177
26407
  "vacuumControl.locate": {
26178
26408
  capName: "vacuum-control",
26179
26409
  capScope: "device",
package/dist/addon.mjs CHANGED
@@ -4634,7 +4634,7 @@ function _instanceof(cls, params = {}) {
4634
4634
  return inst;
4635
4635
  }
4636
4636
  //#endregion
4637
- //#region ../types/dist/sleep-DJaTV2D7.mjs
4637
+ //#region ../types/dist/sleep-Baang_XW.mjs
4638
4638
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4639
4639
  EventCategory["SystemBoot"] = "system.boot";
4640
4640
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -6738,6 +6738,18 @@ function method(input, output, options) {
6738
6738
  timeoutMs: options?.timeoutMs
6739
6739
  };
6740
6740
  }
6741
+ /**
6742
+ * A wrapper/system-only method: served exclusively by the cap's system-level
6743
+ * provider (`InferProvider`), and OPTIONAL on `InferNativeProvider` so per-device
6744
+ * driver natives don't stub out a wrapper concern (e.g. a cross-device cache
6745
+ * overview). The `systemOnly: true` literal is what `InferNativeProvider` keys on.
6746
+ */
6747
+ function systemMethod(input, output, options) {
6748
+ return {
6749
+ ...method(input, output, options),
6750
+ systemOnly: true
6751
+ };
6752
+ }
6741
6753
  /** Shorthand to define an event schema */
6742
6754
  function event(data) {
6743
6755
  return { data };
@@ -11831,6 +11843,7 @@ var PipelineAddonSchemaSchema = object({
11831
11843
  defaultModelId: string(),
11832
11844
  defaultModelIdByFormat: record(string(), string()).optional(),
11833
11845
  enabledByDefault: boolean().optional(),
11846
+ backfillIntoExistingOverrides: boolean().optional(),
11834
11847
  defaultConfidence: number(),
11835
11848
  group: string().optional(),
11836
11849
  configSchema: array(ConfigFieldBridge).readonly().optional()
@@ -12012,7 +12025,15 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
12012
12025
  image: _instanceof(Uint8Array).optional(),
12013
12026
  referenceImage: string().optional(),
12014
12027
  deviceId: number().optional(),
12015
- sessionId: string().optional()
12028
+ sessionId: string().optional(),
12029
+ /**
12030
+ * Execution plane. 'full' (default) runs the whole tree — benchmark,
12031
+ * reference-image, and detail-subtree calls. 'frame' is the live
12032
+ * per-frame dispatch: ONLY root-plane steps run; crop children
12033
+ * (inputClasses ≠ null) are skipped and served per-track via
12034
+ * pipelineRunner.runDetailSubtree (two-plane design).
12035
+ */
12036
+ plane: _enum(["full", "frame"]).optional()
12016
12037
  }), PipelineRunResultBridge, { kind: "mutation" }), method(object({
12017
12038
  engine: PipelineEngineChoiceSchema.optional(),
12018
12039
  steps: array(PipelineStepInputSchema).min(1),
@@ -12170,6 +12191,47 @@ var zonesCapability = {
12170
12191
  runtimeState: object({ zones: array(ZoneSchema).readonly() })
12171
12192
  };
12172
12193
  /**
12194
+ * A bounding box in NORMALIZED [0,1] frame coordinates for `getNativeCrop`. The
12195
+ * decode worker resolves it against the RETAINED native frame's real pixel dims,
12196
+ * so the caller supplies only the detection-res bbox divided by the detection
12197
+ * dims — no native resolution to plumb.
12198
+ */
12199
+ var NativeCropBboxSchema = object({
12200
+ x: number(),
12201
+ y: number(),
12202
+ w: number(),
12203
+ h: number()
12204
+ });
12205
+ /** Result of a best-effort native-resolution crop (`getNativeCrop`). */
12206
+ var NativeCropResultSchema = object({
12207
+ /** Packed rgb (24-bit) pixels of the crop. */
12208
+ bytes: _instanceof(Uint8Array),
12209
+ width: number().int().positive(),
12210
+ height: number().int().positive()
12211
+ });
12212
+ /** Parent detection context passed to `runDetailSubtree` — the crop's
12213
+ * originating detection, in FRAME-space coordinates. Reuses
12214
+ * `NativeCropBboxSchema`'s `{x,y,w,h}` shape (same numeric fields; here
12215
+ * the coordinates are frame-space rather than getNativeCrop's
12216
+ * normalized [0,1] convention). */
12217
+ var DetailParentSchema = object({
12218
+ bbox: NativeCropBboxSchema,
12219
+ className: string()
12220
+ });
12221
+ /** One child-step result from `runDetailSubtree` — an embedding, label,
12222
+ * or refined detection produced by running the crop-subtree on a
12223
+ * single tracked detection. */
12224
+ var DetailResultSchema = object({
12225
+ stepId: string(),
12226
+ className: string(),
12227
+ score: number(),
12228
+ /** FRAME-space bbox (already mapped back from crop space). */
12229
+ bbox: NativeCropBboxSchema.optional(),
12230
+ embedding: string().optional(),
12231
+ label: string().optional(),
12232
+ alignedCropJpeg: string().optional()
12233
+ });
12234
+ /**
12173
12235
  * Per-camera tunable ranges + defaults. Single source of truth used
12174
12236
  * by both the Zod data schema (validation + default fallback) and
12175
12237
  * the device settings UI (slider min/max/step). Touch one place and
@@ -12425,7 +12487,17 @@ var RunnerLocalMetricsSchema = object({
12425
12487
  avgInferenceTimeMs: number(),
12426
12488
  queueDepth: number()
12427
12489
  });
12428
- method(RunnerCameraConfigSchema, object({ success: literal(true) }), { kind: "mutation" }), method(object({ deviceId: number() }), object({ success: literal(true) }), { kind: "mutation" }), method(ReportMotionInputSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), RunnerLocalLoadSchema), method(_void(), RunnerLocalMetricsSchema), method(object({ deviceId: number() }), CameraMetricsSchema.nullable()), method(_void(), array(CameraMetricsWithDeviceIdSchema).readonly()), method(_void(), array(number()).readonly());
12490
+ method(RunnerCameraConfigSchema, object({ success: literal(true) }), { kind: "mutation" }), method(object({ deviceId: number() }), object({ success: literal(true) }), { kind: "mutation" }), method(ReportMotionInputSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), RunnerLocalLoadSchema), method(_void(), RunnerLocalMetricsSchema), method(object({ deviceId: number() }), CameraMetricsSchema.nullable()), method(_void(), array(CameraMetricsWithDeviceIdSchema).readonly()), method(_void(), array(number()).readonly()), method(object({
12491
+ handle: FrameHandleSchema,
12492
+ bbox: NativeCropBboxSchema,
12493
+ maxWidth: number().int().positive().optional()
12494
+ }), NativeCropResultSchema.nullable()), method(object({
12495
+ deviceId: number(),
12496
+ frameHandle: FrameHandleSchema.optional(),
12497
+ cropJpeg: string().optional(),
12498
+ parent: DetailParentSchema,
12499
+ steps: array(string()).optional()
12500
+ }), object({ details: array(DetailResultSchema) }).nullable(), { kind: "mutation" });
12429
12501
  /**
12430
12502
  * Hardware / firmware motion sensor cap — binary detected state plus
12431
12503
  * a timestamp of the last observation. Distinct from
@@ -18100,7 +18172,17 @@ var TrackSchema = object({
18100
18172
  /** Cumulative normalized distance travelled (0..1 units = full frame width). */
18101
18173
  totalDistance: number(),
18102
18174
  state: TrackStateSchema,
18103
- active: boolean()
18175
+ active: boolean(),
18176
+ /** Deterministic key-event importance score in [0,1] (server-computed at
18177
+ * track expiry, recomputed on late label). Absent on legacy rows written
18178
+ * before scoring shipped — consumers degrade to absence / compute-on-read. */
18179
+ importance: number().optional(),
18180
+ /** Id of the track's highest-confidence ObjectEvent (its representative
18181
+ * "best" frame). Absent when the track produced no object events. */
18182
+ bestEventId: string().optional(),
18183
+ /** Tag of the importance sub-signal that dominated the score
18184
+ * (identity|dwell|proximity|class|confidence|travel|zone). */
18185
+ importanceReason: string().optional()
18104
18186
  });
18105
18187
  var BaseEventFields = {
18106
18188
  id: string(),
@@ -18165,8 +18247,18 @@ var ObjectEventSchema = object({
18165
18247
  frameHeight: number().optional(),
18166
18248
  /** MediaStore key for the crop attached to this event (if any). */
18167
18249
  mediaKey: string().optional(),
18250
+ /** Design B: MediaStore key of the track's native-resolution key frame (the
18251
+ * best-detection full frame). Resolve via the event-media data-plane
18252
+ * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`) for a detail view that
18253
+ * draws `bbox` over the native frame. Absent on legacy rows / non-decoded
18254
+ * sources — consumers fall back to `mediaKey` (the tight crop). */
18255
+ keyFrameMediaKey: string().optional(),
18168
18256
  /** Populated by B5 (recording playback URL for this event). */
18169
- mediaUrl: string().optional()
18257
+ mediaUrl: string().optional(),
18258
+ /** The parent track's key-event importance [0,1], propagated to every object
18259
+ * event of the track (so an event row can be sorted by importance without a
18260
+ * track join). Absent on legacy rows / before the track was scored. */
18261
+ importance: number().optional()
18170
18262
  });
18171
18263
  var AudioEventSchema = object({
18172
18264
  ...BaseEventFields,
@@ -18190,7 +18282,8 @@ var MediaFileKindEnum = _enum([
18190
18282
  "fullFrame",
18191
18283
  "fullFrameBoxed",
18192
18284
  "faceCrop",
18193
- "plateCrop"
18285
+ "plateCrop",
18286
+ "keyFrame"
18194
18287
  ]);
18195
18288
  var MediaFileSchema = object({
18196
18289
  key: string(),
@@ -18211,6 +18304,32 @@ var DeviceEventQueryInput = object({
18211
18304
  projection: _enum(["full", "slim"]).optional()
18212
18305
  });
18213
18306
  var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
18307
+ var KeyEventQueryInput = object({
18308
+ deviceId: number(),
18309
+ /** Window lower bound (track firstSeen ≥ since). */
18310
+ since: number(),
18311
+ /** Window upper bound (track firstSeen ≤ until). */
18312
+ until: number(),
18313
+ limit: number().int().min(1).max(200).default(50),
18314
+ /** Drop tracks scoring below this importance. */
18315
+ minImportance: number().min(0).max(1).optional(),
18316
+ /** Restrict to a single class (e.g. 'person'). */
18317
+ classFilter: string().optional()
18318
+ });
18319
+ var KeyEventSchema = object({
18320
+ /** The representative event id (the track's best ObjectEvent, else its trackId). */
18321
+ id: string(),
18322
+ trackId: string(),
18323
+ /** Track start time (firstSeen). */
18324
+ timestamp: number(),
18325
+ className: string(),
18326
+ label: string().optional(),
18327
+ importance: number(),
18328
+ /** Highest-confidence ObjectEvent id for the track (empty when none). */
18329
+ bestEventId: string(),
18330
+ /** Track lifetime in ms (lastSeen - firstSeen). */
18331
+ windowMs: number().optional()
18332
+ });
18214
18333
  var TrackedDetectionSchema = object({
18215
18334
  trackId: string(),
18216
18335
  className: string(),
@@ -18240,7 +18359,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
18240
18359
  }), array(TrackSchema).readonly()), method(object({ deviceId: number() }), _void(), {
18241
18360
  kind: "mutation",
18242
18361
  auth: "admin"
18243
- }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({
18362
+ }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
18244
18363
  deviceId: number(),
18245
18364
  since: number(),
18246
18365
  until: number(),
@@ -19044,7 +19163,20 @@ var snapshotCapability = {
19044
19163
  invalidateCache: method(object({ deviceId: number() }), _void(), {
19045
19164
  kind: "mutation",
19046
19165
  auth: "admin"
19047
- })
19166
+ }),
19167
+ /**
19168
+ * Cache-only batch overview — answers from the wrapper's in-memory cache in
19169
+ * O(n) and NEVER triggers a capture. Lets a grid skip requesting images for
19170
+ * devices that never produced a frame, and gives it an ETag per device for
19171
+ * conditional (304-able) image fetches. `lastCapturedAt`/`cacheAgeMs`/`etag`
19172
+ * are null for a device with no cached frame.
19173
+ */
19174
+ getSnapshotOverview: systemMethod(object({ deviceIds: array(number()).min(1).max(200) }), array(object({
19175
+ deviceId: number(),
19176
+ lastCapturedAt: number().nullable(),
19177
+ cacheAgeMs: number().nullable(),
19178
+ etag: string().nullable()
19179
+ })))
19048
19180
  },
19049
19181
  status: {
19050
19182
  schema: SnapshotStatusSchema,
@@ -19301,10 +19433,32 @@ method(_void(), array(TurnServerSchema).readonly());
19301
19433
  * b. `finishAuthentication({userId, response})` → server verifies
19302
19434
  * the assertion, bumps the credential counter, returns ok.
19303
19435
  *
19436
+ * 2b. Usernameless (discoverable-credential) authentication — the
19437
+ * passkey IS the primary factor, no password leg:
19438
+ * a. `beginDiscoverableAuthentication({})` → assertion options with
19439
+ * EMPTY `allowCredentials` (the browser offers every resident
19440
+ * passkey it holds for this RP) + `userVerification: 'required'`
19441
+ * (the passkey replaces both factors, so UV is mandatory).
19442
+ * The challenge is stored server-side, NOT bound to any user.
19443
+ * b. `finishDiscoverableAuthentication({response})` → the provider
19444
+ * resolves the credential by the response's credential id,
19445
+ * verifies the assertion against the stored challenge + that
19446
+ * credential's public key/counter, and returns the OWNING
19447
+ * `userId` — the caller (core auth router) mints the session.
19448
+ *
19304
19449
  * 3. Management:
19305
19450
  * - `listPasskeys({userId})` — enumerate user's enrolled credentials.
19306
19451
  * - `removePasskey({userId, credentialId})` — revoke one credential.
19307
19452
  *
19453
+ * 4. Second-factor preference (opt-in, default OFF):
19454
+ * Enrolling a passkey only enables passkey-FIRST sign-in. It is
19455
+ * demanded as a second factor after a password login ONLY when the
19456
+ * user explicitly opts in via `setSecondFactorPreference`.
19457
+ * - `getSecondFactorPreference({userId})` → `{ enabled }` (missing
19458
+ * row ⇒ `enabled: false`).
19459
+ * - `setSecondFactorPreference({userId, enabled})` — persisted by
19460
+ * the providing addon beside its credentials.
19461
+ *
19308
19462
  * Challenges are short-lived (5 min, in-memory). The cap is internal —
19309
19463
  * the admin-ui composes the begin/finish round-trip and never exposes
19310
19464
  * the cap to non-admins.
@@ -19347,6 +19501,17 @@ method(object({
19347
19501
  }), object({ verified: boolean() }), {
19348
19502
  kind: "mutation",
19349
19503
  access: "view"
19504
+ }), method(object({}), object({ optionsJSON: record(string(), unknown()) }), {
19505
+ kind: "mutation",
19506
+ access: "view"
19507
+ }), method(object({
19508
+ /** AuthenticationResponseJSON from the browser. */
19509
+ response: record(string(), unknown()) }), object({
19510
+ verified: boolean(),
19511
+ userId: string().nullable()
19512
+ }), {
19513
+ kind: "mutation",
19514
+ access: "view"
19350
19515
  }), method(object({ userId: string() }), array(PasskeySummarySchema), { auth: "admin" }), method(object({
19351
19516
  userId: string(),
19352
19517
  credentialId: string()
@@ -19354,6 +19519,13 @@ method(object({
19354
19519
  kind: "mutation",
19355
19520
  auth: "admin",
19356
19521
  access: "delete"
19522
+ }), method(object({ userId: string() }), object({ enabled: boolean() }), { auth: "admin" }), method(object({
19523
+ userId: string(),
19524
+ enabled: boolean()
19525
+ }), object({ success: literal(true) }), {
19526
+ kind: "mutation",
19527
+ auth: "admin",
19528
+ access: "create"
19357
19529
  });
19358
19530
  /**
19359
19531
  * `videoclips` — the unified, navigable-clip surface for a camera.
@@ -20155,7 +20327,17 @@ var FaceInfoSchema = object({
20155
20327
  recognizedIdentityId: string().optional(),
20156
20328
  identityName: string().optional(),
20157
20329
  assigned: boolean(),
20158
- base64: string().optional()
20330
+ base64: string().optional(),
20331
+ /** Design B: the face bbox (pixel space) on the key frame — lets a detail
20332
+ * view draw the box over the native `keyFrameMediaKey` frame. Absent on
20333
+ * legacy rows written before design B. */
20334
+ faceBbox: BoundingBoxSchema.optional(),
20335
+ /** Design B: MediaStore key of the track's native-resolution key frame.
20336
+ * Fetch the native JPEG via the event-media data-plane
20337
+ * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`). Absent when the
20338
+ * track produced no key frame (e.g. native/onboard source) — the UI falls
20339
+ * back to the inline `base64` face crop. */
20340
+ keyFrameMediaKey: string().optional()
20159
20341
  });
20160
20342
  var FaceFilterEnum = _enum([
20161
20343
  "unassigned",
@@ -24573,6 +24755,12 @@ Object.freeze({
24573
24755
  addonId: null,
24574
24756
  access: "view"
24575
24757
  },
24758
+ "pipelineAnalytics.getKeyEvents": {
24759
+ capName: "pipeline-analytics",
24760
+ capScope: "device",
24761
+ addonId: null,
24762
+ access: "view"
24763
+ },
24576
24764
  "pipelineAnalytics.getMotionEvents": {
24577
24765
  capName: "pipeline-analytics",
24578
24766
  capScope: "device",
@@ -25101,12 +25289,24 @@ Object.freeze({
25101
25289
  addonId: null,
25102
25290
  access: "view"
25103
25291
  },
25292
+ "pipelineRunner.getNativeCrop": {
25293
+ capName: "pipeline-runner",
25294
+ capScope: "system",
25295
+ addonId: null,
25296
+ access: "view"
25297
+ },
25104
25298
  "pipelineRunner.reportMotion": {
25105
25299
  capName: "pipeline-runner",
25106
25300
  capScope: "system",
25107
25301
  addonId: null,
25108
25302
  access: "create"
25109
25303
  },
25304
+ "pipelineRunner.runDetailSubtree": {
25305
+ capName: "pipeline-runner",
25306
+ capScope: "system",
25307
+ addonId: null,
25308
+ access: "create"
25309
+ },
25110
25310
  "plateGallery.correctPlateText": {
25111
25311
  capName: "plate-gallery",
25112
25312
  capScope: "system",
@@ -25467,6 +25667,12 @@ Object.freeze({
25467
25667
  addonId: null,
25468
25668
  access: "view"
25469
25669
  },
25670
+ "snapshot.getSnapshotOverview": {
25671
+ capName: "snapshot",
25672
+ capScope: "device",
25673
+ addonId: null,
25674
+ access: "view"
25675
+ },
25470
25676
  "snapshot.invalidateCache": {
25471
25677
  capName: "snapshot",
25472
25678
  capScope: "device",
@@ -26145,6 +26351,12 @@ Object.freeze({
26145
26351
  addonId: null,
26146
26352
  access: "view"
26147
26353
  },
26354
+ "userPasskeys.beginDiscoverableAuthentication": {
26355
+ capName: "user-passkeys",
26356
+ capScope: "system",
26357
+ addonId: null,
26358
+ access: "view"
26359
+ },
26148
26360
  "userPasskeys.beginRegistration": {
26149
26361
  capName: "user-passkeys",
26150
26362
  capScope: "system",
@@ -26157,12 +26369,24 @@ Object.freeze({
26157
26369
  addonId: null,
26158
26370
  access: "view"
26159
26371
  },
26372
+ "userPasskeys.finishDiscoverableAuthentication": {
26373
+ capName: "user-passkeys",
26374
+ capScope: "system",
26375
+ addonId: null,
26376
+ access: "view"
26377
+ },
26160
26378
  "userPasskeys.finishRegistration": {
26161
26379
  capName: "user-passkeys",
26162
26380
  capScope: "system",
26163
26381
  addonId: null,
26164
26382
  access: "create"
26165
26383
  },
26384
+ "userPasskeys.getSecondFactorPreference": {
26385
+ capName: "user-passkeys",
26386
+ capScope: "system",
26387
+ addonId: null,
26388
+ access: "view"
26389
+ },
26166
26390
  "userPasskeys.listPasskeys": {
26167
26391
  capName: "user-passkeys",
26168
26392
  capScope: "system",
@@ -26175,6 +26399,12 @@ Object.freeze({
26175
26399
  addonId: null,
26176
26400
  access: "delete"
26177
26401
  },
26402
+ "userPasskeys.setSecondFactorPreference": {
26403
+ capName: "user-passkeys",
26404
+ capScope: "system",
26405
+ addonId: null,
26406
+ access: "create"
26407
+ },
26178
26408
  "vacuumControl.locate": {
26179
26409
  capName: "vacuum-control",
26180
26410
  capScope: "device",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-amcrest",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
4
4
  "description": "Amcrest/Dahua camera device provider addon for CamStack — Dahua CGI over HTTP(S) with digest auth (snapshot, RTSP catalog, PTZ, image/day-night config)",
5
5
  "keywords": [
6
6
  "camstack",