@camstack/addon-post-analysis 1.2.90 → 1.2.92

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.
@@ -21487,20 +21487,6 @@ var VectorStatsResultSchema = object({
21487
21487
  exact: boolean()
21488
21488
  });
21489
21489
  method(VectorDeclareIndexInputSchema, _void(), { kind: "mutation" }), method(VectorUpsertInputSchema, VectorUpsertResultSchema, { kind: "mutation" }), method(VectorQueryInputSchema, VectorQueryResultSchema), method(VectorGetInputSchema, VectorGetResultSchema), method(VectorDeleteInputSchema, VectorDeleteResultSchema, { kind: "mutation" }), method(VectorDeleteByFilterInputSchema, VectorDeleteResultSchema, { kind: "mutation" }), method(VectorStatsInputSchema, VectorStatsResultSchema);
21490
- /**
21491
- * `videoclips` — the unified, navigable-clip surface for a camera.
21492
- *
21493
- * A device-scoped WRAPPER cap (like `pipeline-analytics`): exactly one active
21494
- * provider per device, substitutable. The DEFAULT provider (registered by
21495
- * `addon-post-analysis`, `defaultActive: true`) composes the analytics event
21496
- * log (markers + thumbnails) with the recorder's `getPlaybackManifest` — a clip
21497
- * is a time-WINDOW over existing footage, never a separate file. A camera that
21498
- * exposes NATIVE onboard clips (Reolink/Hikvision NVR) can later substitute the
21499
- * wrapper provider for its device and serve its own clip catalog + URLs.
21500
- *
21501
- * A `Clip` is purely time-based (subtree-blind): playback resolves segments by
21502
- * temporal overlap, so the API never decides `continuous` vs `events`.
21503
- */
21504
21490
  var ClipSchema = object({
21505
21491
  /** Opaque, provider-namespaced id. The default provider encodes the time
21506
21492
  * window so `getClipPlayback` is self-contained (no event re-query). */
@@ -21526,12 +21512,41 @@ var ClipSchema = object({
21526
21512
  * of the event that owns `kind` (object > motion > audio). Do not extract
21527
21513
  * a keyframe from the recorded segments. Other providers (onboard, HKSV)
21528
21514
  * mint their own stills.
21515
+ *
21516
+ * **VOUCHED, never fabricated.** A provider emits this only for an event it
21517
+ * has CONFIRMED owns at least one media row (its own, or its owning track's).
21518
+ * Absent is meaningful — "this visit has no event still" — never "we did not
21519
+ * look". Stamping it from a URL template made 35% of one camera's clips point
21520
+ * at a 404 (device 3836, 2026-08-17: 64 of 179 clips dead, 63 of them motion).
21521
+ * A read that FAILS drops the claim; it never invents it.
21529
21522
  */
21530
21523
  thumbnail: string().optional(),
21531
- /** Analytics event ids that overlap this visit. Empty on footage-only clips.
21532
- * The default provider's visit grain puts many motion heartbeats on one clip
21533
- * instead of minting one clip per marker. */
21524
+ /**
21525
+ * An instant INSIDE this visit's footage, hole-safe, where a recorded still
21526
+ * can be decoded. Present whenever the visit came from recorded availability;
21527
+ * absent on a per-event padded window (there is no footage to promise).
21528
+ *
21529
+ * This is not a thumbnail and not a second byte path: it is the argument to
21530
+ * the recorder's existing still route. The surface — never the provider —
21531
+ * decides whether to use it. It is the midpoint of the visit's LONGEST
21532
+ * contiguous range, not of the visit: a visit spans its holes by
21533
+ * construction, so a naive midpoint lands in dead air.
21534
+ */
21535
+ stillAtMs: number().optional(),
21536
+ /**
21537
+ * Analytics event ids that overlap this visit — a BOUNDED sample, newest
21538
+ * first within kind (object → motion → audio), capped at
21539
+ * {@link MAX_CLIP_EVENT_IDS}. Empty on footage-only clips.
21540
+ *
21541
+ * Bounded because it is not a payload the surface pages through: one visit on
21542
+ * device 615 carried 2 345 ids, and `eventIds` was 99% of a 153 KB
21543
+ * camera-day. Read {@link eventCount} for the true total.
21544
+ */
21534
21545
  eventIds: array(string()).optional(),
21546
+ /** How many analytics events actually overlap this visit. Differs from
21547
+ * `eventIds.length` exactly when the sample was capped — so a truncated
21548
+ * list is never mistaken for a quiet visit. */
21549
+ eventCount: number().int().nonnegative().optional(),
21535
21550
  /** Intra-visit footage holes (GOP rolls, discarded segments) still shorter
21536
21551
  * than `VISIT_MERGE_GAP_MS`. Playback concatenates around them; the timeline
21537
21552
  * bar keeps showing them via `recording.getAvailability`. */
@@ -22016,7 +22031,14 @@ var SearchResultSchema = object({
22016
22031
  });
22017
22032
  var AutoUpdateSettingsSchema = object({
22018
22033
  channel: ChannelSchema,
22019
- intervalSeconds: number()
22034
+ intervalSeconds: number(),
22035
+ /**
22036
+ * Cadence of the "an update exists" POLLER, in seconds. Independent of
22037
+ * `channel`: the poller runs while auto-apply is `off`, because being told
22038
+ * about a publish and installing it are different decisions. Clamped
22039
+ * server-side to 900 s … 604800 s; defaults to 21600 s (6 h).
22040
+ */
22041
+ updateCheckIntervalSeconds: number()
22020
22042
  });
22021
22043
  var AddonAutoUpdateSchema = ChannelWithInheritSchema;
22022
22044
  var RestartAddonResultSchema = unknown();
@@ -22157,7 +22179,9 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
22157
22179
  auth: "admin"
22158
22180
  }), method(_void(), AutoUpdateSettingsSchema, { auth: "admin" }), method(object({
22159
22181
  channel: ChannelSchema,
22160
- intervalSeconds: number().min(300).max(86400).optional()
22182
+ intervalSeconds: number().min(300).max(86400).optional(),
22183
+ /** Availability-poll cadence; see AutoUpdateSettingsSchema. */
22184
+ updateCheckIntervalSeconds: number().min(900).max(604800).optional()
22161
22185
  }), unknown(), {
22162
22186
  kind: "mutation",
22163
22187
  auth: "admin"
@@ -38535,6 +38559,20 @@ function isScheduleActive(schedule, atMs) {
38535
38559
  return schedule.invert === true ? !inside : inside;
38536
38560
  }
38537
38561
  /**
38562
+ * Does `filter` say anything about `kind`?
38563
+ *
38564
+ * `false` means the filter is not part of this kind's vocabulary: the engine
38565
+ * ignores it and an editor hides its input. It never means "excluded".
38566
+ */
38567
+ function systemEventFilterApplies(kind, filter) {
38568
+ switch (filter) {
38569
+ case "deviceIds": return kind.startsWith("device-") || kind.startsWith("stream-") || kind === "detection-blind" || kind === "alarm-triggered" || kind === "export-completed";
38570
+ case "deviceTypes": return kind.startsWith("device-") || kind === "detection-blind";
38571
+ case "nodeIds": return kind.startsWith("node-") || kind === "addon-update-available" || kind === "addon-updated" || kind === "server-update-available" || kind === "server-updated";
38572
+ case "packageNames": return kind.endsWith("update-available") || kind === "addon-updated" || kind === "server-updated";
38573
+ }
38574
+ }
38575
+ /**
38538
38576
  * TimelapseRule — the STANDALONE scheduled timelapse producer's rule model.
38539
38577
  *
38540
38578
  * Spec: `docs/superpowers/specs/2026-07-24-nc-occupancy-timelapse-design.md`
@@ -39526,6 +39564,12 @@ Object.defineProperty(exports, "subKindsOf", {
39526
39564
  return subKindsOf;
39527
39565
  }
39528
39566
  });
39567
+ Object.defineProperty(exports, "systemEventFilterApplies", {
39568
+ enumerable: true,
39569
+ get: function() {
39570
+ return systemEventFilterApplies;
39571
+ }
39572
+ });
39529
39573
  Object.defineProperty(exports, "unknown", {
39530
39574
  enumerable: true,
39531
39575
  get: function() {
@@ -21456,20 +21456,6 @@ var VectorStatsResultSchema = object({
21456
21456
  exact: boolean()
21457
21457
  });
21458
21458
  method(VectorDeclareIndexInputSchema, _void(), { kind: "mutation" }), method(VectorUpsertInputSchema, VectorUpsertResultSchema, { kind: "mutation" }), method(VectorQueryInputSchema, VectorQueryResultSchema), method(VectorGetInputSchema, VectorGetResultSchema), method(VectorDeleteInputSchema, VectorDeleteResultSchema, { kind: "mutation" }), method(VectorDeleteByFilterInputSchema, VectorDeleteResultSchema, { kind: "mutation" }), method(VectorStatsInputSchema, VectorStatsResultSchema);
21459
- /**
21460
- * `videoclips` — the unified, navigable-clip surface for a camera.
21461
- *
21462
- * A device-scoped WRAPPER cap (like `pipeline-analytics`): exactly one active
21463
- * provider per device, substitutable. The DEFAULT provider (registered by
21464
- * `addon-post-analysis`, `defaultActive: true`) composes the analytics event
21465
- * log (markers + thumbnails) with the recorder's `getPlaybackManifest` — a clip
21466
- * is a time-WINDOW over existing footage, never a separate file. A camera that
21467
- * exposes NATIVE onboard clips (Reolink/Hikvision NVR) can later substitute the
21468
- * wrapper provider for its device and serve its own clip catalog + URLs.
21469
- *
21470
- * A `Clip` is purely time-based (subtree-blind): playback resolves segments by
21471
- * temporal overlap, so the API never decides `continuous` vs `events`.
21472
- */
21473
21459
  var ClipSchema = object({
21474
21460
  /** Opaque, provider-namespaced id. The default provider encodes the time
21475
21461
  * window so `getClipPlayback` is self-contained (no event re-query). */
@@ -21495,12 +21481,41 @@ var ClipSchema = object({
21495
21481
  * of the event that owns `kind` (object > motion > audio). Do not extract
21496
21482
  * a keyframe from the recorded segments. Other providers (onboard, HKSV)
21497
21483
  * mint their own stills.
21484
+ *
21485
+ * **VOUCHED, never fabricated.** A provider emits this only for an event it
21486
+ * has CONFIRMED owns at least one media row (its own, or its owning track's).
21487
+ * Absent is meaningful — "this visit has no event still" — never "we did not
21488
+ * look". Stamping it from a URL template made 35% of one camera's clips point
21489
+ * at a 404 (device 3836, 2026-08-17: 64 of 179 clips dead, 63 of them motion).
21490
+ * A read that FAILS drops the claim; it never invents it.
21498
21491
  */
21499
21492
  thumbnail: string().optional(),
21500
- /** Analytics event ids that overlap this visit. Empty on footage-only clips.
21501
- * The default provider's visit grain puts many motion heartbeats on one clip
21502
- * instead of minting one clip per marker. */
21493
+ /**
21494
+ * An instant INSIDE this visit's footage, hole-safe, where a recorded still
21495
+ * can be decoded. Present whenever the visit came from recorded availability;
21496
+ * absent on a per-event padded window (there is no footage to promise).
21497
+ *
21498
+ * This is not a thumbnail and not a second byte path: it is the argument to
21499
+ * the recorder's existing still route. The surface — never the provider —
21500
+ * decides whether to use it. It is the midpoint of the visit's LONGEST
21501
+ * contiguous range, not of the visit: a visit spans its holes by
21502
+ * construction, so a naive midpoint lands in dead air.
21503
+ */
21504
+ stillAtMs: number().optional(),
21505
+ /**
21506
+ * Analytics event ids that overlap this visit — a BOUNDED sample, newest
21507
+ * first within kind (object → motion → audio), capped at
21508
+ * {@link MAX_CLIP_EVENT_IDS}. Empty on footage-only clips.
21509
+ *
21510
+ * Bounded because it is not a payload the surface pages through: one visit on
21511
+ * device 615 carried 2 345 ids, and `eventIds` was 99% of a 153 KB
21512
+ * camera-day. Read {@link eventCount} for the true total.
21513
+ */
21503
21514
  eventIds: array(string()).optional(),
21515
+ /** How many analytics events actually overlap this visit. Differs from
21516
+ * `eventIds.length` exactly when the sample was capped — so a truncated
21517
+ * list is never mistaken for a quiet visit. */
21518
+ eventCount: number().int().nonnegative().optional(),
21504
21519
  /** Intra-visit footage holes (GOP rolls, discarded segments) still shorter
21505
21520
  * than `VISIT_MERGE_GAP_MS`. Playback concatenates around them; the timeline
21506
21521
  * bar keeps showing them via `recording.getAvailability`. */
@@ -21985,7 +22000,14 @@ var SearchResultSchema = object({
21985
22000
  });
21986
22001
  var AutoUpdateSettingsSchema = object({
21987
22002
  channel: ChannelSchema,
21988
- intervalSeconds: number()
22003
+ intervalSeconds: number(),
22004
+ /**
22005
+ * Cadence of the "an update exists" POLLER, in seconds. Independent of
22006
+ * `channel`: the poller runs while auto-apply is `off`, because being told
22007
+ * about a publish and installing it are different decisions. Clamped
22008
+ * server-side to 900 s … 604800 s; defaults to 21600 s (6 h).
22009
+ */
22010
+ updateCheckIntervalSeconds: number()
21989
22011
  });
21990
22012
  var AddonAutoUpdateSchema = ChannelWithInheritSchema;
21991
22013
  var RestartAddonResultSchema = unknown();
@@ -22126,7 +22148,9 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
22126
22148
  auth: "admin"
22127
22149
  }), method(_void(), AutoUpdateSettingsSchema, { auth: "admin" }), method(object({
22128
22150
  channel: ChannelSchema,
22129
- intervalSeconds: number().min(300).max(86400).optional()
22151
+ intervalSeconds: number().min(300).max(86400).optional(),
22152
+ /** Availability-poll cadence; see AutoUpdateSettingsSchema. */
22153
+ updateCheckIntervalSeconds: number().min(900).max(604800).optional()
22130
22154
  }), unknown(), {
22131
22155
  kind: "mutation",
22132
22156
  auth: "admin"
@@ -38504,6 +38528,20 @@ function isScheduleActive(schedule, atMs) {
38504
38528
  return schedule.invert === true ? !inside : inside;
38505
38529
  }
38506
38530
  /**
38531
+ * Does `filter` say anything about `kind`?
38532
+ *
38533
+ * `false` means the filter is not part of this kind's vocabulary: the engine
38534
+ * ignores it and an editor hides its input. It never means "excluded".
38535
+ */
38536
+ function systemEventFilterApplies(kind, filter) {
38537
+ switch (filter) {
38538
+ case "deviceIds": return kind.startsWith("device-") || kind.startsWith("stream-") || kind === "detection-blind" || kind === "alarm-triggered" || kind === "export-completed";
38539
+ case "deviceTypes": return kind.startsWith("device-") || kind === "detection-blind";
38540
+ case "nodeIds": return kind.startsWith("node-") || kind === "addon-update-available" || kind === "addon-updated" || kind === "server-update-available" || kind === "server-updated";
38541
+ case "packageNames": return kind.endsWith("update-available") || kind === "addon-updated" || kind === "server-updated";
38542
+ }
38543
+ }
38544
+ /**
38507
38545
  * TimelapseRule — the STANDALONE scheduled timelapse producer's rule model.
38508
38546
  *
38509
38547
  * Spec: `docs/superpowers/specs/2026-07-24-nc-occupancy-timelapse-design.md`
@@ -38985,4 +39023,4 @@ function vectorDimFromBase64(encoded) {
38985
39023
  return Math.floor(Buffer.from(encoded, "base64").byteLength / 4);
38986
39024
  }
38987
39025
  //#endregion
38988
- export { faceGalleryCapability as $, SCENE_CONFIRM_DEFAULT_TIMEOUT_MS as A, record as At, VISIT_MERGE_GAP_MS as B, NcSnoozeSchema as C, array as Ct, OpsLogEntrySchema as D, number as Dt, NcTaxonomySchema as E, literal as Et, TIMELAPSE_DENSE_FLOOR_SEC as F, audioModeOf as G, alarmPanelCapability as H, TimelapseRuleInputSchema as I, customAction as J, buildEventKindDescriptor as K, TimelapseRulePatchSchema as L, SCENE_DEFAULT_UNCOVERED_POLICY as M, unknown as Mt, SCENE_DIVERGED as N, EventCategory as Nt, RECORDING_EXPORT_MAX_READ_BYTES as O, object as Ot, SceneMonitorSchema as P, encodeVectorBase64 as Q, TimelapseRuleSchema as R, NcSnoozeInputSchema as S, _enum as St, NcSystemEventKindSchema as T, discriminatedUnion as Tt, assertTimelapseCadences as U, addonWidgetsSourceCapability as V, audioMetricsCapability as W, deriveRecordingMode as X, defineCustomActions as Y, embeddingEncoderCapability as Z, NcRuleInputSchema as _, createEvent as _t, DETECTION_PIPELINE_CAP_NAME as a, pipelineAnalyticsCapability as at, NcRuleTargetSchema as b, nodePin as bt, EVENT_PAD_MS as c, readTimelapseGeneratedAt as ct, NC_ALARM_SYSTEM_EVENT_KINDS as d, vectorDimFromBase64 as dt, hfModelUrl as et, NC_CONDITION_CATALOG as f, videoclipsCapability as ft, NcConditionDescriptorSchema as g, DeviceType as gt, NC_TAXONOMY as h, BaseAddon as ht, DETECTION_MACRO_CLASSES as i, notificationRulesCapability as it, SCENE_DEFAULT_ANCHOR_THRESHOLD as j, string as jt, RetrainStatusSchema as k, partialRecord as kt, LabelAttributionSchema as l, sceneMonitorCapability as lt, NC_SNOOZE_MAX_MINUTES as m, errMsg as mt, DEFAULT_EVENT_COLOR as n, isScheduleActive as nt, DeclaredDevices as o, plateGalleryCapability as ot, NC_DEFAULT_SNOOZE_MINUTES as p, zoneAnalyticsCapability as pt, cosineSimilarity as q, DEFAULT_TIMELAPSE_PREVIEW_TEXT as r, kebabToCamel as rt, EVENT_KIND_BY_CAP as s, readDeviceStateFrom as st, BaseDevice as t, isDetectionMacroClass as tt, MACRO_LABELS as u, subKindsOf as ut, NcRulePatchSchema as v, hydrateSchema as vt, NcSnoozeSuppressedSchema as w, boolean as wt, NcScheduleSchema as x, sleep as xt, NcRuleSchema as y, isDeviceScopedCap as yt, TrackSourceSchema as z };
39026
+ export { faceGalleryCapability as $, SCENE_CONFIRM_DEFAULT_TIMEOUT_MS as A, partialRecord as At, VISIT_MERGE_GAP_MS as B, NcSnoozeSchema as C, _enum as Ct, OpsLogEntrySchema as D, literal as Dt, NcTaxonomySchema as E, discriminatedUnion as Et, TIMELAPSE_DENSE_FLOOR_SEC as F, audioModeOf as G, alarmPanelCapability as H, TimelapseRuleInputSchema as I, customAction as J, buildEventKindDescriptor as K, TimelapseRulePatchSchema as L, SCENE_DEFAULT_UNCOVERED_POLICY as M, string as Mt, SCENE_DIVERGED as N, unknown as Nt, RECORDING_EXPORT_MAX_READ_BYTES as O, number as Ot, SceneMonitorSchema as P, EventCategory as Pt, encodeVectorBase64 as Q, TimelapseRuleSchema as R, NcSnoozeInputSchema as S, sleep as St, NcSystemEventKindSchema as T, boolean as Tt, assertTimelapseCadences as U, addonWidgetsSourceCapability as V, audioMetricsCapability as W, deriveRecordingMode as X, defineCustomActions as Y, embeddingEncoderCapability as Z, NcRuleInputSchema as _, DeviceType as _t, DETECTION_PIPELINE_CAP_NAME as a, pipelineAnalyticsCapability as at, NcRuleTargetSchema as b, isDeviceScopedCap as bt, EVENT_PAD_MS as c, readTimelapseGeneratedAt as ct, NC_ALARM_SYSTEM_EVENT_KINDS as d, systemEventFilterApplies as dt, hfModelUrl as et, NC_CONDITION_CATALOG as f, vectorDimFromBase64 as ft, NcConditionDescriptorSchema as g, BaseAddon as gt, NC_TAXONOMY as h, errMsg as ht, DETECTION_MACRO_CLASSES as i, notificationRulesCapability as it, SCENE_DEFAULT_ANCHOR_THRESHOLD as j, record as jt, RetrainStatusSchema as k, object as kt, LabelAttributionSchema as l, sceneMonitorCapability as lt, NC_SNOOZE_MAX_MINUTES as m, zoneAnalyticsCapability as mt, DEFAULT_EVENT_COLOR as n, isScheduleActive as nt, DeclaredDevices as o, plateGalleryCapability as ot, NC_DEFAULT_SNOOZE_MINUTES as p, videoclipsCapability as pt, cosineSimilarity as q, DEFAULT_TIMELAPSE_PREVIEW_TEXT as r, kebabToCamel as rt, EVENT_KIND_BY_CAP as s, readDeviceStateFrom as st, BaseDevice as t, isDetectionMacroClass as tt, MACRO_LABELS as u, subKindsOf as ut, NcRulePatchSchema as v, createEvent as vt, NcSnoozeSuppressedSchema as w, array as wt, NcScheduleSchema as x, nodePin as xt, NcRuleSchema as y, hydrateSchema as yt, TrackSourceSchema as z };
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_dist = require("../dist-BBIhkNDY.js");
5
+ const require_dist = require("../dist-BfrtqGyh.js");
6
6
  let node_fs = require("node:fs");
7
7
  let node_fs$1 = require_dist.__toESM(node_fs, 1);
8
8
  node_fs = require_dist.__toESM(node_fs);
@@ -1,4 +1,4 @@
1
- import { Z as embeddingEncoderCapability, et as hfModelUrl, ht as BaseAddon } from "../dist-Bac7ww1C.mjs";
1
+ import { Z as embeddingEncoderCapability, et as hfModelUrl, gt as BaseAddon } from "../dist-VnaTfwAL.mjs";
2
2
  import { createRequire } from "node:module";
3
3
  import * as fs from "node:fs";
4
4
  import "node:fs";
@@ -18,7 +18,7 @@ var e = {
18
18
  },
19
19
  "@camstack/types": {
20
20
  name: "@camstack/types",
21
- version: "1.2.84",
21
+ version: "1.2.86",
22
22
  scope: ["default"],
23
23
  loaded: !1,
24
24
  from: "addon_pipeline_analytics_widgets",
@@ -36,7 +36,7 @@ async function r() {
36
36
  }
37
37
  },
38
38
  "@camstack/types": {
39
- version: "1.2.84",
39
+ version: "1.2.86",
40
40
  scope: "default",
41
41
  shareConfig: {
42
42
  singleton: !0,