@camstack/addon-provider-hikvision 1.1.21 → 1.1.23

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
@@ -4635,7 +4635,7 @@ function _instanceof(cls, params = {}) {
4635
4635
  return inst;
4636
4636
  }
4637
4637
  //#endregion
4638
- //#region ../types/dist/sleep-DJaTV2D7.mjs
4638
+ //#region ../types/dist/sleep-Baang_XW.mjs
4639
4639
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4640
4640
  EventCategory["SystemBoot"] = "system.boot";
4641
4641
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -6739,6 +6739,18 @@ function method(input, output, options) {
6739
6739
  timeoutMs: options?.timeoutMs
6740
6740
  };
6741
6741
  }
6742
+ /**
6743
+ * A wrapper/system-only method: served exclusively by the cap's system-level
6744
+ * provider (`InferProvider`), and OPTIONAL on `InferNativeProvider` so per-device
6745
+ * driver natives don't stub out a wrapper concern (e.g. a cross-device cache
6746
+ * overview). The `systemOnly: true` literal is what `InferNativeProvider` keys on.
6747
+ */
6748
+ function systemMethod(input, output, options) {
6749
+ return {
6750
+ ...method(input, output, options),
6751
+ systemOnly: true
6752
+ };
6753
+ }
6742
6754
  /** Shorthand to define an event schema */
6743
6755
  function event(data) {
6744
6756
  return { data };
@@ -12022,6 +12034,7 @@ var PipelineAddonSchemaSchema = object({
12022
12034
  defaultModelId: string(),
12023
12035
  defaultModelIdByFormat: record(string(), string()).optional(),
12024
12036
  enabledByDefault: boolean().optional(),
12037
+ backfillIntoExistingOverrides: boolean().optional(),
12025
12038
  defaultConfidence: number(),
12026
12039
  group: string().optional(),
12027
12040
  configSchema: array(ConfigFieldBridge).readonly().optional()
@@ -12203,7 +12216,15 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
12203
12216
  image: _instanceof(Uint8Array).optional(),
12204
12217
  referenceImage: string().optional(),
12205
12218
  deviceId: number().optional(),
12206
- sessionId: string().optional()
12219
+ sessionId: string().optional(),
12220
+ /**
12221
+ * Execution plane. 'full' (default) runs the whole tree — benchmark,
12222
+ * reference-image, and detail-subtree calls. 'frame' is the live
12223
+ * per-frame dispatch: ONLY root-plane steps run; crop children
12224
+ * (inputClasses ≠ null) are skipped and served per-track via
12225
+ * pipelineRunner.runDetailSubtree (two-plane design).
12226
+ */
12227
+ plane: _enum(["full", "frame"]).optional()
12207
12228
  }), PipelineRunResultBridge, { kind: "mutation" }), method(object({
12208
12229
  engine: PipelineEngineChoiceSchema.optional(),
12209
12230
  steps: array(PipelineStepInputSchema).min(1),
@@ -12361,6 +12382,47 @@ var zonesCapability = {
12361
12382
  runtimeState: object({ zones: array(ZoneSchema).readonly() })
12362
12383
  };
12363
12384
  /**
12385
+ * A bounding box in NORMALIZED [0,1] frame coordinates for `getNativeCrop`. The
12386
+ * decode worker resolves it against the RETAINED native frame's real pixel dims,
12387
+ * so the caller supplies only the detection-res bbox divided by the detection
12388
+ * dims — no native resolution to plumb.
12389
+ */
12390
+ var NativeCropBboxSchema = object({
12391
+ x: number(),
12392
+ y: number(),
12393
+ w: number(),
12394
+ h: number()
12395
+ });
12396
+ /** Result of a best-effort native-resolution crop (`getNativeCrop`). */
12397
+ var NativeCropResultSchema = object({
12398
+ /** Packed rgb (24-bit) pixels of the crop. */
12399
+ bytes: _instanceof(Uint8Array),
12400
+ width: number().int().positive(),
12401
+ height: number().int().positive()
12402
+ });
12403
+ /** Parent detection context passed to `runDetailSubtree` — the crop's
12404
+ * originating detection, in FRAME-space coordinates. Reuses
12405
+ * `NativeCropBboxSchema`'s `{x,y,w,h}` shape (same numeric fields; here
12406
+ * the coordinates are frame-space rather than getNativeCrop's
12407
+ * normalized [0,1] convention). */
12408
+ var DetailParentSchema = object({
12409
+ bbox: NativeCropBboxSchema,
12410
+ className: string()
12411
+ });
12412
+ /** One child-step result from `runDetailSubtree` — an embedding, label,
12413
+ * or refined detection produced by running the crop-subtree on a
12414
+ * single tracked detection. */
12415
+ var DetailResultSchema = object({
12416
+ stepId: string(),
12417
+ className: string(),
12418
+ score: number(),
12419
+ /** FRAME-space bbox (already mapped back from crop space). */
12420
+ bbox: NativeCropBboxSchema.optional(),
12421
+ embedding: string().optional(),
12422
+ label: string().optional(),
12423
+ alignedCropJpeg: string().optional()
12424
+ });
12425
+ /**
12364
12426
  * Per-camera tunable ranges + defaults. Single source of truth used
12365
12427
  * by both the Zod data schema (validation + default fallback) and
12366
12428
  * the device settings UI (slider min/max/step). Touch one place and
@@ -12616,7 +12678,17 @@ var RunnerLocalMetricsSchema = object({
12616
12678
  avgInferenceTimeMs: number(),
12617
12679
  queueDepth: number()
12618
12680
  });
12619
- 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());
12681
+ 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({
12682
+ handle: FrameHandleSchema,
12683
+ bbox: NativeCropBboxSchema,
12684
+ maxWidth: number().int().positive().optional()
12685
+ }), NativeCropResultSchema.nullable()), method(object({
12686
+ deviceId: number(),
12687
+ frameHandle: FrameHandleSchema.optional(),
12688
+ cropJpeg: string().optional(),
12689
+ parent: DetailParentSchema,
12690
+ steps: array(string()).optional()
12691
+ }), object({ details: array(DetailResultSchema) }).nullable(), { kind: "mutation" });
12620
12692
  /**
12621
12693
  * Hardware / firmware motion sensor cap — binary detected state plus
12622
12694
  * a timestamp of the last observation. Distinct from
@@ -18303,7 +18375,17 @@ var TrackSchema = object({
18303
18375
  /** Cumulative normalized distance travelled (0..1 units = full frame width). */
18304
18376
  totalDistance: number(),
18305
18377
  state: TrackStateSchema,
18306
- active: boolean()
18378
+ active: boolean(),
18379
+ /** Deterministic key-event importance score in [0,1] (server-computed at
18380
+ * track expiry, recomputed on late label). Absent on legacy rows written
18381
+ * before scoring shipped — consumers degrade to absence / compute-on-read. */
18382
+ importance: number().optional(),
18383
+ /** Id of the track's highest-confidence ObjectEvent (its representative
18384
+ * "best" frame). Absent when the track produced no object events. */
18385
+ bestEventId: string().optional(),
18386
+ /** Tag of the importance sub-signal that dominated the score
18387
+ * (identity|dwell|proximity|class|confidence|travel|zone). */
18388
+ importanceReason: string().optional()
18307
18389
  });
18308
18390
  var BaseEventFields = {
18309
18391
  id: string(),
@@ -18368,8 +18450,18 @@ var ObjectEventSchema = object({
18368
18450
  frameHeight: number().optional(),
18369
18451
  /** MediaStore key for the crop attached to this event (if any). */
18370
18452
  mediaKey: string().optional(),
18453
+ /** Design B: MediaStore key of the track's native-resolution key frame (the
18454
+ * best-detection full frame). Resolve via the event-media data-plane
18455
+ * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`) for a detail view that
18456
+ * draws `bbox` over the native frame. Absent on legacy rows / non-decoded
18457
+ * sources — consumers fall back to `mediaKey` (the tight crop). */
18458
+ keyFrameMediaKey: string().optional(),
18371
18459
  /** Populated by B5 (recording playback URL for this event). */
18372
- mediaUrl: string().optional()
18460
+ mediaUrl: string().optional(),
18461
+ /** The parent track's key-event importance [0,1], propagated to every object
18462
+ * event of the track (so an event row can be sorted by importance without a
18463
+ * track join). Absent on legacy rows / before the track was scored. */
18464
+ importance: number().optional()
18373
18465
  });
18374
18466
  var AudioEventSchema = object({
18375
18467
  ...BaseEventFields,
@@ -18393,7 +18485,8 @@ var MediaFileKindEnum = _enum([
18393
18485
  "fullFrame",
18394
18486
  "fullFrameBoxed",
18395
18487
  "faceCrop",
18396
- "plateCrop"
18488
+ "plateCrop",
18489
+ "keyFrame"
18397
18490
  ]);
18398
18491
  var MediaFileSchema = object({
18399
18492
  key: string(),
@@ -18414,6 +18507,32 @@ var DeviceEventQueryInput = object({
18414
18507
  projection: _enum(["full", "slim"]).optional()
18415
18508
  });
18416
18509
  var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
18510
+ var KeyEventQueryInput = object({
18511
+ deviceId: number(),
18512
+ /** Window lower bound (track firstSeen ≥ since). */
18513
+ since: number(),
18514
+ /** Window upper bound (track firstSeen ≤ until). */
18515
+ until: number(),
18516
+ limit: number().int().min(1).max(200).default(50),
18517
+ /** Drop tracks scoring below this importance. */
18518
+ minImportance: number().min(0).max(1).optional(),
18519
+ /** Restrict to a single class (e.g. 'person'). */
18520
+ classFilter: string().optional()
18521
+ });
18522
+ var KeyEventSchema = object({
18523
+ /** The representative event id (the track's best ObjectEvent, else its trackId). */
18524
+ id: string(),
18525
+ trackId: string(),
18526
+ /** Track start time (firstSeen). */
18527
+ timestamp: number(),
18528
+ className: string(),
18529
+ label: string().optional(),
18530
+ importance: number(),
18531
+ /** Highest-confidence ObjectEvent id for the track (empty when none). */
18532
+ bestEventId: string(),
18533
+ /** Track lifetime in ms (lastSeen - firstSeen). */
18534
+ windowMs: number().optional()
18535
+ });
18417
18536
  var TrackedDetectionSchema = object({
18418
18537
  trackId: string(),
18419
18538
  className: string(),
@@ -18443,7 +18562,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
18443
18562
  }), array(TrackSchema).readonly()), method(object({ deviceId: number() }), _void(), {
18444
18563
  kind: "mutation",
18445
18564
  auth: "admin"
18446
- }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({
18565
+ }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
18447
18566
  deviceId: number(),
18448
18567
  since: number(),
18449
18568
  until: number(),
@@ -19247,7 +19366,20 @@ var snapshotCapability = {
19247
19366
  invalidateCache: method(object({ deviceId: number() }), _void(), {
19248
19367
  kind: "mutation",
19249
19368
  auth: "admin"
19250
- })
19369
+ }),
19370
+ /**
19371
+ * Cache-only batch overview — answers from the wrapper's in-memory cache in
19372
+ * O(n) and NEVER triggers a capture. Lets a grid skip requesting images for
19373
+ * devices that never produced a frame, and gives it an ETag per device for
19374
+ * conditional (304-able) image fetches. `lastCapturedAt`/`cacheAgeMs`/`etag`
19375
+ * are null for a device with no cached frame.
19376
+ */
19377
+ getSnapshotOverview: systemMethod(object({ deviceIds: array(number()).min(1).max(200) }), array(object({
19378
+ deviceId: number(),
19379
+ lastCapturedAt: number().nullable(),
19380
+ cacheAgeMs: number().nullable(),
19381
+ etag: string().nullable()
19382
+ })))
19251
19383
  },
19252
19384
  status: {
19253
19385
  schema: SnapshotStatusSchema,
@@ -19504,10 +19636,32 @@ method(_void(), array(TurnServerSchema).readonly());
19504
19636
  * b. `finishAuthentication({userId, response})` → server verifies
19505
19637
  * the assertion, bumps the credential counter, returns ok.
19506
19638
  *
19639
+ * 2b. Usernameless (discoverable-credential) authentication — the
19640
+ * passkey IS the primary factor, no password leg:
19641
+ * a. `beginDiscoverableAuthentication({})` → assertion options with
19642
+ * EMPTY `allowCredentials` (the browser offers every resident
19643
+ * passkey it holds for this RP) + `userVerification: 'required'`
19644
+ * (the passkey replaces both factors, so UV is mandatory).
19645
+ * The challenge is stored server-side, NOT bound to any user.
19646
+ * b. `finishDiscoverableAuthentication({response})` → the provider
19647
+ * resolves the credential by the response's credential id,
19648
+ * verifies the assertion against the stored challenge + that
19649
+ * credential's public key/counter, and returns the OWNING
19650
+ * `userId` — the caller (core auth router) mints the session.
19651
+ *
19507
19652
  * 3. Management:
19508
19653
  * - `listPasskeys({userId})` — enumerate user's enrolled credentials.
19509
19654
  * - `removePasskey({userId, credentialId})` — revoke one credential.
19510
19655
  *
19656
+ * 4. Second-factor preference (opt-in, default OFF):
19657
+ * Enrolling a passkey only enables passkey-FIRST sign-in. It is
19658
+ * demanded as a second factor after a password login ONLY when the
19659
+ * user explicitly opts in via `setSecondFactorPreference`.
19660
+ * - `getSecondFactorPreference({userId})` → `{ enabled }` (missing
19661
+ * row ⇒ `enabled: false`).
19662
+ * - `setSecondFactorPreference({userId, enabled})` — persisted by
19663
+ * the providing addon beside its credentials.
19664
+ *
19511
19665
  * Challenges are short-lived (5 min, in-memory). The cap is internal —
19512
19666
  * the admin-ui composes the begin/finish round-trip and never exposes
19513
19667
  * the cap to non-admins.
@@ -19550,6 +19704,17 @@ method(object({
19550
19704
  }), object({ verified: boolean() }), {
19551
19705
  kind: "mutation",
19552
19706
  access: "view"
19707
+ }), method(object({}), object({ optionsJSON: record(string(), unknown()) }), {
19708
+ kind: "mutation",
19709
+ access: "view"
19710
+ }), method(object({
19711
+ /** AuthenticationResponseJSON from the browser. */
19712
+ response: record(string(), unknown()) }), object({
19713
+ verified: boolean(),
19714
+ userId: string().nullable()
19715
+ }), {
19716
+ kind: "mutation",
19717
+ access: "view"
19553
19718
  }), method(object({ userId: string() }), array(PasskeySummarySchema), { auth: "admin" }), method(object({
19554
19719
  userId: string(),
19555
19720
  credentialId: string()
@@ -19557,6 +19722,13 @@ method(object({
19557
19722
  kind: "mutation",
19558
19723
  auth: "admin",
19559
19724
  access: "delete"
19725
+ }), method(object({ userId: string() }), object({ enabled: boolean() }), { auth: "admin" }), method(object({
19726
+ userId: string(),
19727
+ enabled: boolean()
19728
+ }), object({ success: literal(true) }), {
19729
+ kind: "mutation",
19730
+ auth: "admin",
19731
+ access: "create"
19560
19732
  });
19561
19733
  /**
19562
19734
  * `videoclips` — the unified, navigable-clip surface for a camera.
@@ -20358,7 +20530,17 @@ var FaceInfoSchema = object({
20358
20530
  recognizedIdentityId: string().optional(),
20359
20531
  identityName: string().optional(),
20360
20532
  assigned: boolean(),
20361
- base64: string().optional()
20533
+ base64: string().optional(),
20534
+ /** Design B: the face bbox (pixel space) on the key frame — lets a detail
20535
+ * view draw the box over the native `keyFrameMediaKey` frame. Absent on
20536
+ * legacy rows written before design B. */
20537
+ faceBbox: BoundingBoxSchema.optional(),
20538
+ /** Design B: MediaStore key of the track's native-resolution key frame.
20539
+ * Fetch the native JPEG via the event-media data-plane
20540
+ * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`). Absent when the
20541
+ * track produced no key frame (e.g. native/onboard source) — the UI falls
20542
+ * back to the inline `base64` face crop. */
20543
+ keyFrameMediaKey: string().optional()
20362
20544
  });
20363
20545
  var FaceFilterEnum = _enum([
20364
20546
  "unassigned",
@@ -24852,6 +25034,12 @@ Object.freeze({
24852
25034
  addonId: null,
24853
25035
  access: "view"
24854
25036
  },
25037
+ "pipelineAnalytics.getKeyEvents": {
25038
+ capName: "pipeline-analytics",
25039
+ capScope: "device",
25040
+ addonId: null,
25041
+ access: "view"
25042
+ },
24855
25043
  "pipelineAnalytics.getMotionEvents": {
24856
25044
  capName: "pipeline-analytics",
24857
25045
  capScope: "device",
@@ -25380,12 +25568,24 @@ Object.freeze({
25380
25568
  addonId: null,
25381
25569
  access: "view"
25382
25570
  },
25571
+ "pipelineRunner.getNativeCrop": {
25572
+ capName: "pipeline-runner",
25573
+ capScope: "system",
25574
+ addonId: null,
25575
+ access: "view"
25576
+ },
25383
25577
  "pipelineRunner.reportMotion": {
25384
25578
  capName: "pipeline-runner",
25385
25579
  capScope: "system",
25386
25580
  addonId: null,
25387
25581
  access: "create"
25388
25582
  },
25583
+ "pipelineRunner.runDetailSubtree": {
25584
+ capName: "pipeline-runner",
25585
+ capScope: "system",
25586
+ addonId: null,
25587
+ access: "create"
25588
+ },
25389
25589
  "plateGallery.correctPlateText": {
25390
25590
  capName: "plate-gallery",
25391
25591
  capScope: "system",
@@ -25746,6 +25946,12 @@ Object.freeze({
25746
25946
  addonId: null,
25747
25947
  access: "view"
25748
25948
  },
25949
+ "snapshot.getSnapshotOverview": {
25950
+ capName: "snapshot",
25951
+ capScope: "device",
25952
+ addonId: null,
25953
+ access: "view"
25954
+ },
25749
25955
  "snapshot.invalidateCache": {
25750
25956
  capName: "snapshot",
25751
25957
  capScope: "device",
@@ -26424,6 +26630,12 @@ Object.freeze({
26424
26630
  addonId: null,
26425
26631
  access: "view"
26426
26632
  },
26633
+ "userPasskeys.beginDiscoverableAuthentication": {
26634
+ capName: "user-passkeys",
26635
+ capScope: "system",
26636
+ addonId: null,
26637
+ access: "view"
26638
+ },
26427
26639
  "userPasskeys.beginRegistration": {
26428
26640
  capName: "user-passkeys",
26429
26641
  capScope: "system",
@@ -26436,12 +26648,24 @@ Object.freeze({
26436
26648
  addonId: null,
26437
26649
  access: "view"
26438
26650
  },
26651
+ "userPasskeys.finishDiscoverableAuthentication": {
26652
+ capName: "user-passkeys",
26653
+ capScope: "system",
26654
+ addonId: null,
26655
+ access: "view"
26656
+ },
26439
26657
  "userPasskeys.finishRegistration": {
26440
26658
  capName: "user-passkeys",
26441
26659
  capScope: "system",
26442
26660
  addonId: null,
26443
26661
  access: "create"
26444
26662
  },
26663
+ "userPasskeys.getSecondFactorPreference": {
26664
+ capName: "user-passkeys",
26665
+ capScope: "system",
26666
+ addonId: null,
26667
+ access: "view"
26668
+ },
26445
26669
  "userPasskeys.listPasskeys": {
26446
26670
  capName: "user-passkeys",
26447
26671
  capScope: "system",
@@ -26454,6 +26678,12 @@ Object.freeze({
26454
26678
  addonId: null,
26455
26679
  access: "delete"
26456
26680
  },
26681
+ "userPasskeys.setSecondFactorPreference": {
26682
+ capName: "user-passkeys",
26683
+ capScope: "system",
26684
+ addonId: null,
26685
+ access: "create"
26686
+ },
26457
26687
  "vacuumControl.locate": {
26458
26688
  capName: "vacuum-control",
26459
26689
  capScope: "device",
package/dist/addon.mjs CHANGED
@@ -4636,7 +4636,7 @@ function _instanceof(cls, params = {}) {
4636
4636
  return inst;
4637
4637
  }
4638
4638
  //#endregion
4639
- //#region ../types/dist/sleep-DJaTV2D7.mjs
4639
+ //#region ../types/dist/sleep-Baang_XW.mjs
4640
4640
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4641
4641
  EventCategory["SystemBoot"] = "system.boot";
4642
4642
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -6740,6 +6740,18 @@ function method(input, output, options) {
6740
6740
  timeoutMs: options?.timeoutMs
6741
6741
  };
6742
6742
  }
6743
+ /**
6744
+ * A wrapper/system-only method: served exclusively by the cap's system-level
6745
+ * provider (`InferProvider`), and OPTIONAL on `InferNativeProvider` so per-device
6746
+ * driver natives don't stub out a wrapper concern (e.g. a cross-device cache
6747
+ * overview). The `systemOnly: true` literal is what `InferNativeProvider` keys on.
6748
+ */
6749
+ function systemMethod(input, output, options) {
6750
+ return {
6751
+ ...method(input, output, options),
6752
+ systemOnly: true
6753
+ };
6754
+ }
6743
6755
  /** Shorthand to define an event schema */
6744
6756
  function event(data) {
6745
6757
  return { data };
@@ -12023,6 +12035,7 @@ var PipelineAddonSchemaSchema = object({
12023
12035
  defaultModelId: string(),
12024
12036
  defaultModelIdByFormat: record(string(), string()).optional(),
12025
12037
  enabledByDefault: boolean().optional(),
12038
+ backfillIntoExistingOverrides: boolean().optional(),
12026
12039
  defaultConfidence: number(),
12027
12040
  group: string().optional(),
12028
12041
  configSchema: array(ConfigFieldBridge).readonly().optional()
@@ -12204,7 +12217,15 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
12204
12217
  image: _instanceof(Uint8Array).optional(),
12205
12218
  referenceImage: string().optional(),
12206
12219
  deviceId: number().optional(),
12207
- sessionId: string().optional()
12220
+ sessionId: string().optional(),
12221
+ /**
12222
+ * Execution plane. 'full' (default) runs the whole tree — benchmark,
12223
+ * reference-image, and detail-subtree calls. 'frame' is the live
12224
+ * per-frame dispatch: ONLY root-plane steps run; crop children
12225
+ * (inputClasses ≠ null) are skipped and served per-track via
12226
+ * pipelineRunner.runDetailSubtree (two-plane design).
12227
+ */
12228
+ plane: _enum(["full", "frame"]).optional()
12208
12229
  }), PipelineRunResultBridge, { kind: "mutation" }), method(object({
12209
12230
  engine: PipelineEngineChoiceSchema.optional(),
12210
12231
  steps: array(PipelineStepInputSchema).min(1),
@@ -12362,6 +12383,47 @@ var zonesCapability = {
12362
12383
  runtimeState: object({ zones: array(ZoneSchema).readonly() })
12363
12384
  };
12364
12385
  /**
12386
+ * A bounding box in NORMALIZED [0,1] frame coordinates for `getNativeCrop`. The
12387
+ * decode worker resolves it against the RETAINED native frame's real pixel dims,
12388
+ * so the caller supplies only the detection-res bbox divided by the detection
12389
+ * dims — no native resolution to plumb.
12390
+ */
12391
+ var NativeCropBboxSchema = object({
12392
+ x: number(),
12393
+ y: number(),
12394
+ w: number(),
12395
+ h: number()
12396
+ });
12397
+ /** Result of a best-effort native-resolution crop (`getNativeCrop`). */
12398
+ var NativeCropResultSchema = object({
12399
+ /** Packed rgb (24-bit) pixels of the crop. */
12400
+ bytes: _instanceof(Uint8Array),
12401
+ width: number().int().positive(),
12402
+ height: number().int().positive()
12403
+ });
12404
+ /** Parent detection context passed to `runDetailSubtree` — the crop's
12405
+ * originating detection, in FRAME-space coordinates. Reuses
12406
+ * `NativeCropBboxSchema`'s `{x,y,w,h}` shape (same numeric fields; here
12407
+ * the coordinates are frame-space rather than getNativeCrop's
12408
+ * normalized [0,1] convention). */
12409
+ var DetailParentSchema = object({
12410
+ bbox: NativeCropBboxSchema,
12411
+ className: string()
12412
+ });
12413
+ /** One child-step result from `runDetailSubtree` — an embedding, label,
12414
+ * or refined detection produced by running the crop-subtree on a
12415
+ * single tracked detection. */
12416
+ var DetailResultSchema = object({
12417
+ stepId: string(),
12418
+ className: string(),
12419
+ score: number(),
12420
+ /** FRAME-space bbox (already mapped back from crop space). */
12421
+ bbox: NativeCropBboxSchema.optional(),
12422
+ embedding: string().optional(),
12423
+ label: string().optional(),
12424
+ alignedCropJpeg: string().optional()
12425
+ });
12426
+ /**
12365
12427
  * Per-camera tunable ranges + defaults. Single source of truth used
12366
12428
  * by both the Zod data schema (validation + default fallback) and
12367
12429
  * the device settings UI (slider min/max/step). Touch one place and
@@ -12617,7 +12679,17 @@ var RunnerLocalMetricsSchema = object({
12617
12679
  avgInferenceTimeMs: number(),
12618
12680
  queueDepth: number()
12619
12681
  });
12620
- 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());
12682
+ 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({
12683
+ handle: FrameHandleSchema,
12684
+ bbox: NativeCropBboxSchema,
12685
+ maxWidth: number().int().positive().optional()
12686
+ }), NativeCropResultSchema.nullable()), method(object({
12687
+ deviceId: number(),
12688
+ frameHandle: FrameHandleSchema.optional(),
12689
+ cropJpeg: string().optional(),
12690
+ parent: DetailParentSchema,
12691
+ steps: array(string()).optional()
12692
+ }), object({ details: array(DetailResultSchema) }).nullable(), { kind: "mutation" });
12621
12693
  /**
12622
12694
  * Hardware / firmware motion sensor cap — binary detected state plus
12623
12695
  * a timestamp of the last observation. Distinct from
@@ -18304,7 +18376,17 @@ var TrackSchema = object({
18304
18376
  /** Cumulative normalized distance travelled (0..1 units = full frame width). */
18305
18377
  totalDistance: number(),
18306
18378
  state: TrackStateSchema,
18307
- active: boolean()
18379
+ active: boolean(),
18380
+ /** Deterministic key-event importance score in [0,1] (server-computed at
18381
+ * track expiry, recomputed on late label). Absent on legacy rows written
18382
+ * before scoring shipped — consumers degrade to absence / compute-on-read. */
18383
+ importance: number().optional(),
18384
+ /** Id of the track's highest-confidence ObjectEvent (its representative
18385
+ * "best" frame). Absent when the track produced no object events. */
18386
+ bestEventId: string().optional(),
18387
+ /** Tag of the importance sub-signal that dominated the score
18388
+ * (identity|dwell|proximity|class|confidence|travel|zone). */
18389
+ importanceReason: string().optional()
18308
18390
  });
18309
18391
  var BaseEventFields = {
18310
18392
  id: string(),
@@ -18369,8 +18451,18 @@ var ObjectEventSchema = object({
18369
18451
  frameHeight: number().optional(),
18370
18452
  /** MediaStore key for the crop attached to this event (if any). */
18371
18453
  mediaKey: string().optional(),
18454
+ /** Design B: MediaStore key of the track's native-resolution key frame (the
18455
+ * best-detection full frame). Resolve via the event-media data-plane
18456
+ * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`) for a detail view that
18457
+ * draws `bbox` over the native frame. Absent on legacy rows / non-decoded
18458
+ * sources — consumers fall back to `mediaKey` (the tight crop). */
18459
+ keyFrameMediaKey: string().optional(),
18372
18460
  /** Populated by B5 (recording playback URL for this event). */
18373
- mediaUrl: string().optional()
18461
+ mediaUrl: string().optional(),
18462
+ /** The parent track's key-event importance [0,1], propagated to every object
18463
+ * event of the track (so an event row can be sorted by importance without a
18464
+ * track join). Absent on legacy rows / before the track was scored. */
18465
+ importance: number().optional()
18374
18466
  });
18375
18467
  var AudioEventSchema = object({
18376
18468
  ...BaseEventFields,
@@ -18394,7 +18486,8 @@ var MediaFileKindEnum = _enum([
18394
18486
  "fullFrame",
18395
18487
  "fullFrameBoxed",
18396
18488
  "faceCrop",
18397
- "plateCrop"
18489
+ "plateCrop",
18490
+ "keyFrame"
18398
18491
  ]);
18399
18492
  var MediaFileSchema = object({
18400
18493
  key: string(),
@@ -18415,6 +18508,32 @@ var DeviceEventQueryInput = object({
18415
18508
  projection: _enum(["full", "slim"]).optional()
18416
18509
  });
18417
18510
  var ObjectEventQueryInput = DeviceEventQueryInput.extend({ classFilter: string().optional() });
18511
+ var KeyEventQueryInput = object({
18512
+ deviceId: number(),
18513
+ /** Window lower bound (track firstSeen ≥ since). */
18514
+ since: number(),
18515
+ /** Window upper bound (track firstSeen ≤ until). */
18516
+ until: number(),
18517
+ limit: number().int().min(1).max(200).default(50),
18518
+ /** Drop tracks scoring below this importance. */
18519
+ minImportance: number().min(0).max(1).optional(),
18520
+ /** Restrict to a single class (e.g. 'person'). */
18521
+ classFilter: string().optional()
18522
+ });
18523
+ var KeyEventSchema = object({
18524
+ /** The representative event id (the track's best ObjectEvent, else its trackId). */
18525
+ id: string(),
18526
+ trackId: string(),
18527
+ /** Track start time (firstSeen). */
18528
+ timestamp: number(),
18529
+ className: string(),
18530
+ label: string().optional(),
18531
+ importance: number(),
18532
+ /** Highest-confidence ObjectEvent id for the track (empty when none). */
18533
+ bestEventId: string(),
18534
+ /** Track lifetime in ms (lastSeen - firstSeen). */
18535
+ windowMs: number().optional()
18536
+ });
18418
18537
  var TrackedDetectionSchema = object({
18419
18538
  trackId: string(),
18420
18539
  className: string(),
@@ -18444,7 +18563,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
18444
18563
  }), array(TrackSchema).readonly()), method(object({ deviceId: number() }), _void(), {
18445
18564
  kind: "mutation",
18446
18565
  auth: "admin"
18447
- }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({
18566
+ }), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(KeyEventQueryInput, array(KeyEventSchema).readonly()), method(object({
18448
18567
  deviceId: number(),
18449
18568
  since: number(),
18450
18569
  until: number(),
@@ -19248,7 +19367,20 @@ var snapshotCapability = {
19248
19367
  invalidateCache: method(object({ deviceId: number() }), _void(), {
19249
19368
  kind: "mutation",
19250
19369
  auth: "admin"
19251
- })
19370
+ }),
19371
+ /**
19372
+ * Cache-only batch overview — answers from the wrapper's in-memory cache in
19373
+ * O(n) and NEVER triggers a capture. Lets a grid skip requesting images for
19374
+ * devices that never produced a frame, and gives it an ETag per device for
19375
+ * conditional (304-able) image fetches. `lastCapturedAt`/`cacheAgeMs`/`etag`
19376
+ * are null for a device with no cached frame.
19377
+ */
19378
+ getSnapshotOverview: systemMethod(object({ deviceIds: array(number()).min(1).max(200) }), array(object({
19379
+ deviceId: number(),
19380
+ lastCapturedAt: number().nullable(),
19381
+ cacheAgeMs: number().nullable(),
19382
+ etag: string().nullable()
19383
+ })))
19252
19384
  },
19253
19385
  status: {
19254
19386
  schema: SnapshotStatusSchema,
@@ -19505,10 +19637,32 @@ method(_void(), array(TurnServerSchema).readonly());
19505
19637
  * b. `finishAuthentication({userId, response})` → server verifies
19506
19638
  * the assertion, bumps the credential counter, returns ok.
19507
19639
  *
19640
+ * 2b. Usernameless (discoverable-credential) authentication — the
19641
+ * passkey IS the primary factor, no password leg:
19642
+ * a. `beginDiscoverableAuthentication({})` → assertion options with
19643
+ * EMPTY `allowCredentials` (the browser offers every resident
19644
+ * passkey it holds for this RP) + `userVerification: 'required'`
19645
+ * (the passkey replaces both factors, so UV is mandatory).
19646
+ * The challenge is stored server-side, NOT bound to any user.
19647
+ * b. `finishDiscoverableAuthentication({response})` → the provider
19648
+ * resolves the credential by the response's credential id,
19649
+ * verifies the assertion against the stored challenge + that
19650
+ * credential's public key/counter, and returns the OWNING
19651
+ * `userId` — the caller (core auth router) mints the session.
19652
+ *
19508
19653
  * 3. Management:
19509
19654
  * - `listPasskeys({userId})` — enumerate user's enrolled credentials.
19510
19655
  * - `removePasskey({userId, credentialId})` — revoke one credential.
19511
19656
  *
19657
+ * 4. Second-factor preference (opt-in, default OFF):
19658
+ * Enrolling a passkey only enables passkey-FIRST sign-in. It is
19659
+ * demanded as a second factor after a password login ONLY when the
19660
+ * user explicitly opts in via `setSecondFactorPreference`.
19661
+ * - `getSecondFactorPreference({userId})` → `{ enabled }` (missing
19662
+ * row ⇒ `enabled: false`).
19663
+ * - `setSecondFactorPreference({userId, enabled})` — persisted by
19664
+ * the providing addon beside its credentials.
19665
+ *
19512
19666
  * Challenges are short-lived (5 min, in-memory). The cap is internal —
19513
19667
  * the admin-ui composes the begin/finish round-trip and never exposes
19514
19668
  * the cap to non-admins.
@@ -19551,6 +19705,17 @@ method(object({
19551
19705
  }), object({ verified: boolean() }), {
19552
19706
  kind: "mutation",
19553
19707
  access: "view"
19708
+ }), method(object({}), object({ optionsJSON: record(string(), unknown()) }), {
19709
+ kind: "mutation",
19710
+ access: "view"
19711
+ }), method(object({
19712
+ /** AuthenticationResponseJSON from the browser. */
19713
+ response: record(string(), unknown()) }), object({
19714
+ verified: boolean(),
19715
+ userId: string().nullable()
19716
+ }), {
19717
+ kind: "mutation",
19718
+ access: "view"
19554
19719
  }), method(object({ userId: string() }), array(PasskeySummarySchema), { auth: "admin" }), method(object({
19555
19720
  userId: string(),
19556
19721
  credentialId: string()
@@ -19558,6 +19723,13 @@ method(object({
19558
19723
  kind: "mutation",
19559
19724
  auth: "admin",
19560
19725
  access: "delete"
19726
+ }), method(object({ userId: string() }), object({ enabled: boolean() }), { auth: "admin" }), method(object({
19727
+ userId: string(),
19728
+ enabled: boolean()
19729
+ }), object({ success: literal(true) }), {
19730
+ kind: "mutation",
19731
+ auth: "admin",
19732
+ access: "create"
19561
19733
  });
19562
19734
  /**
19563
19735
  * `videoclips` — the unified, navigable-clip surface for a camera.
@@ -20359,7 +20531,17 @@ var FaceInfoSchema = object({
20359
20531
  recognizedIdentityId: string().optional(),
20360
20532
  identityName: string().optional(),
20361
20533
  assigned: boolean(),
20362
- base64: string().optional()
20534
+ base64: string().optional(),
20535
+ /** Design B: the face bbox (pixel space) on the key frame — lets a detail
20536
+ * view draw the box over the native `keyFrameMediaKey` frame. Absent on
20537
+ * legacy rows written before design B. */
20538
+ faceBbox: BoundingBoxSchema.optional(),
20539
+ /** Design B: MediaStore key of the track's native-resolution key frame.
20540
+ * Fetch the native JPEG via the event-media data-plane
20541
+ * (`/addon/<addonId>/event-media/<keyFrameMediaKey>`). Absent when the
20542
+ * track produced no key frame (e.g. native/onboard source) — the UI falls
20543
+ * back to the inline `base64` face crop. */
20544
+ keyFrameMediaKey: string().optional()
20363
20545
  });
20364
20546
  var FaceFilterEnum = _enum([
20365
20547
  "unassigned",
@@ -24853,6 +25035,12 @@ Object.freeze({
24853
25035
  addonId: null,
24854
25036
  access: "view"
24855
25037
  },
25038
+ "pipelineAnalytics.getKeyEvents": {
25039
+ capName: "pipeline-analytics",
25040
+ capScope: "device",
25041
+ addonId: null,
25042
+ access: "view"
25043
+ },
24856
25044
  "pipelineAnalytics.getMotionEvents": {
24857
25045
  capName: "pipeline-analytics",
24858
25046
  capScope: "device",
@@ -25381,12 +25569,24 @@ Object.freeze({
25381
25569
  addonId: null,
25382
25570
  access: "view"
25383
25571
  },
25572
+ "pipelineRunner.getNativeCrop": {
25573
+ capName: "pipeline-runner",
25574
+ capScope: "system",
25575
+ addonId: null,
25576
+ access: "view"
25577
+ },
25384
25578
  "pipelineRunner.reportMotion": {
25385
25579
  capName: "pipeline-runner",
25386
25580
  capScope: "system",
25387
25581
  addonId: null,
25388
25582
  access: "create"
25389
25583
  },
25584
+ "pipelineRunner.runDetailSubtree": {
25585
+ capName: "pipeline-runner",
25586
+ capScope: "system",
25587
+ addonId: null,
25588
+ access: "create"
25589
+ },
25390
25590
  "plateGallery.correctPlateText": {
25391
25591
  capName: "plate-gallery",
25392
25592
  capScope: "system",
@@ -25747,6 +25947,12 @@ Object.freeze({
25747
25947
  addonId: null,
25748
25948
  access: "view"
25749
25949
  },
25950
+ "snapshot.getSnapshotOverview": {
25951
+ capName: "snapshot",
25952
+ capScope: "device",
25953
+ addonId: null,
25954
+ access: "view"
25955
+ },
25750
25956
  "snapshot.invalidateCache": {
25751
25957
  capName: "snapshot",
25752
25958
  capScope: "device",
@@ -26425,6 +26631,12 @@ Object.freeze({
26425
26631
  addonId: null,
26426
26632
  access: "view"
26427
26633
  },
26634
+ "userPasskeys.beginDiscoverableAuthentication": {
26635
+ capName: "user-passkeys",
26636
+ capScope: "system",
26637
+ addonId: null,
26638
+ access: "view"
26639
+ },
26428
26640
  "userPasskeys.beginRegistration": {
26429
26641
  capName: "user-passkeys",
26430
26642
  capScope: "system",
@@ -26437,12 +26649,24 @@ Object.freeze({
26437
26649
  addonId: null,
26438
26650
  access: "view"
26439
26651
  },
26652
+ "userPasskeys.finishDiscoverableAuthentication": {
26653
+ capName: "user-passkeys",
26654
+ capScope: "system",
26655
+ addonId: null,
26656
+ access: "view"
26657
+ },
26440
26658
  "userPasskeys.finishRegistration": {
26441
26659
  capName: "user-passkeys",
26442
26660
  capScope: "system",
26443
26661
  addonId: null,
26444
26662
  access: "create"
26445
26663
  },
26664
+ "userPasskeys.getSecondFactorPreference": {
26665
+ capName: "user-passkeys",
26666
+ capScope: "system",
26667
+ addonId: null,
26668
+ access: "view"
26669
+ },
26446
26670
  "userPasskeys.listPasskeys": {
26447
26671
  capName: "user-passkeys",
26448
26672
  capScope: "system",
@@ -26455,6 +26679,12 @@ Object.freeze({
26455
26679
  addonId: null,
26456
26680
  access: "delete"
26457
26681
  },
26682
+ "userPasskeys.setSecondFactorPreference": {
26683
+ capName: "user-passkeys",
26684
+ capScope: "system",
26685
+ addonId: null,
26686
+ access: "create"
26687
+ },
26458
26688
  "vacuumControl.locate": {
26459
26689
  capName: "vacuum-control",
26460
26690
  capScope: "device",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-hikvision",
3
- "version": "1.1.21",
3
+ "version": "1.1.23",
4
4
  "description": "Hikvision camera device provider addon for CamStack — ISAPI over HTTP(S) with digest auth (snapshot, alarm stream, RTSP discovery)",
5
5
  "keywords": [
6
6
  "camstack",