@camstack/addon-provider-wyze 0.2.23 → 0.2.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/addon.js +128 -22
  2. package/dist/addon.mjs +128 -22
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -31,7 +31,7 @@ let net = require("net");
31
31
  net = __toESM(net, 1);
32
32
  let node_child_process = require("node:child_process");
33
33
  let node_tls = require("node:tls");
34
- //#region ../types/dist/event-category-C0lyLd5U.mjs
34
+ //#region ../types/dist/event-category-XfKNtfCc.mjs
35
35
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
36
36
  EventCategory["SystemBoot"] = "system.boot";
37
37
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -70,6 +70,22 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
70
70
  EventCategory["AddonInstalled"] = "addon.installed";
71
71
  EventCategory["AddonUninstalled"] = "addon.uninstalled";
72
72
  EventCategory["AddonCrashed"] = "addon.crashed";
73
+ /**
74
+ * A RUNNER the D6 crash circuit-breaker gave up on — terminal.
75
+ *
76
+ * `AddonCrashed` is the routine, self-healing fact ("it crashed; it is being
77
+ * respawned"); this is the one that never resolves itself. Emitted exactly
78
+ * once per trip, by `process-service.ts`, carrying the node, the runner, the
79
+ * addons it hosted and the crash count that tripped the breaker.
80
+ *
81
+ * It exists because a runner marked terminally `failed` used to be SILENT:
82
+ * on 2026-08-18 the `recorder` runner died of three unhandled ffmpeg spawn
83
+ * errors, the breaker stopped respawning it (correctly), `/health` kept
84
+ * returning 200, and fleet-wide recording was gone for 3h15 before the
85
+ * operator's phone told him. The Notification Center's system-event intake
86
+ * consumes this category and maps it to the `addon-crash-loop` kind.
87
+ */
88
+ EventCategory["AddonRunnerFailed"] = "addon.runner-failed";
73
89
  EventCategory["AddonError"] = "addon.error";
74
90
  EventCategory["AddonPageReady"] = "addon.page-ready";
75
91
  EventCategory["AddonWidgetReady"] = "addon.widget-ready";
@@ -7632,6 +7648,12 @@ var RecordingConfigSchema = object({
7632
7648
  /** DERIVED summary of `bands`, stamped by the recorder on every save.
7633
7649
  * Authoring it has no effect — see {@link RecordingStorageModeSchema}. */
7634
7650
  mode: RecordingStorageModeSchema.optional(),
7651
+ /**
7652
+ * Which assigned broker slots to record. Absent / empty = {@link
7653
+ * DEFAULT_RECORDING_PROFILES} (`high`+`low`) intersected with the
7654
+ * camera's currently assigned slots — never `mid` unless the operator
7655
+ * picks it, and never a slot the broker has not assigned.
7656
+ */
7635
7657
  profiles: array(CamProfileSchema).optional(),
7636
7658
  segmentSeconds: number().int().positive().optional(),
7637
7659
  /**
@@ -7712,7 +7734,11 @@ var RelocateFootageInputSchema = object({
7712
7734
  profiles: array(string()).optional(),
7713
7735
  /** Copy throttle in MB/s (default 40) — the drain is a background chore,
7714
7736
  * never allowed to starve live writers. */
7715
- throttleMbps: number().min(1).max(1e3).optional()
7737
+ throttleMbps: number().min(1).max(1e3).optional(),
7738
+ /** Move only segments whose startMs is >= this. Absent = the whole source
7739
+ * pile. Used when a full drain is too expensive and the operator only
7740
+ * wants the recent window on the new disk. */
7741
+ sinceMs: number().int().optional()
7716
7742
  });
7717
7743
  /** Internal, lease-scoped participant operation. It is intentionally separate
7718
7744
  * from persistent recording settings: a migration never changes
@@ -14594,6 +14620,7 @@ var NcSystemEventKindSchema = _enum([
14594
14620
  "node-offline",
14595
14621
  "node-inference-unavailable",
14596
14622
  "detection-blind",
14623
+ "addon-crash-loop",
14597
14624
  "addon-update-available",
14598
14625
  "server-update-available",
14599
14626
  "alarm-triggered",
@@ -17167,6 +17194,12 @@ var TrackCascadeCountsSchema = object({
17167
17194
  /** Per-track CLIP search vectors removed (best-effort). */
17168
17195
  embeddings: number().int()
17169
17196
  });
17197
+ /** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
17198
+ var DiskReconcileCountsSchema = object({
17199
+ mediaDropped: number().int(),
17200
+ tracks: number().int(),
17201
+ events: number().int()
17202
+ });
17170
17203
  /** Event-store footprint for one camera. */
17171
17204
  var EventStoreDeviceFootprintSchema = object({
17172
17205
  deviceId: number(),
@@ -17343,6 +17376,9 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
17343
17376
  }), method(object({ deviceId: number() }), TrackCascadeCountsSchema, {
17344
17377
  kind: "mutation",
17345
17378
  auth: "admin"
17379
+ }), method(object({ deviceId: number() }), DiskReconcileCountsSchema, {
17380
+ kind: "mutation",
17381
+ auth: "admin"
17346
17382
  }), method(object({
17347
17383
  deviceId: number(),
17348
17384
  trackIds: array(string()).min(1)
@@ -18893,6 +18929,24 @@ var CameraStatusDegradationSchema = object({
18893
18929
  *
18894
18930
  * See spec: `docs/superpowers/specs/2026-06-24-camera-status-aggregator-cap.md`
18895
18931
  */
18932
+ var DiskReconcileJobSchema = object({
18933
+ state: _enum([
18934
+ "idle",
18935
+ "running",
18936
+ "done",
18937
+ "error"
18938
+ ]),
18939
+ total: number().int().nonnegative(),
18940
+ completed: number().int().nonnegative(),
18941
+ currentDeviceId: number().int().nullable(),
18942
+ failed: array(number().int()).readonly(),
18943
+ mediaDropped: number().int().nonnegative(),
18944
+ tracks: number().int().nonnegative(),
18945
+ events: number().int().nonnegative(),
18946
+ startedAtMs: number().int().nullable(),
18947
+ finishedAtMs: number().int().nullable(),
18948
+ error: string().nullable()
18949
+ });
18896
18950
  var CameraStatusSchema = object({
18897
18951
  deviceId: number(),
18898
18952
  assignment: CameraAssignmentStatusSchema,
@@ -19124,7 +19178,10 @@ method(StorageMigrationLeaseInputSchema, object({ paused: literal(true) }), {
19124
19178
  }), CameraSwitchGroupSchema, {
19125
19179
  kind: "mutation",
19126
19180
  auth: "admin"
19127
- }), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
19181
+ }), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(_void(), DiskReconcileJobSchema, {
19182
+ kind: "mutation",
19183
+ auth: "admin"
19184
+ }), method(_void(), DiskReconcileJobSchema, { auth: "admin" }), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
19128
19185
  name: string(),
19129
19186
  description: string().optional(),
19130
19187
  config: CameraPipelineConfigSchema
@@ -20301,20 +20358,6 @@ var VectorStatsResultSchema = object({
20301
20358
  exact: boolean()
20302
20359
  });
20303
20360
  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);
20304
- /**
20305
- * `videoclips` — the unified, navigable-clip surface for a camera.
20306
- *
20307
- * A device-scoped WRAPPER cap (like `pipeline-analytics`): exactly one active
20308
- * provider per device, substitutable. The DEFAULT provider (registered by
20309
- * `addon-post-analysis`, `defaultActive: true`) composes the analytics event
20310
- * log (markers + thumbnails) with the recorder's `getPlaybackManifest` — a clip
20311
- * is a time-WINDOW over existing footage, never a separate file. A camera that
20312
- * exposes NATIVE onboard clips (Reolink/Hikvision NVR) can later substitute the
20313
- * wrapper provider for its device and serve its own clip catalog + URLs.
20314
- *
20315
- * A `Clip` is purely time-based (subtree-blind): playback resolves segments by
20316
- * temporal overlap, so the API never decides `continuous` vs `events`.
20317
- */
20318
20361
  var ClipSchema = object({
20319
20362
  /** Opaque, provider-namespaced id. The default provider encodes the time
20320
20363
  * window so `getClipPlayback` is self-contained (no event re-query). */
@@ -20340,12 +20383,41 @@ var ClipSchema = object({
20340
20383
  * of the event that owns `kind` (object > motion > audio). Do not extract
20341
20384
  * a keyframe from the recorded segments. Other providers (onboard, HKSV)
20342
20385
  * mint their own stills.
20386
+ *
20387
+ * **VOUCHED, never fabricated.** A provider emits this only for an event it
20388
+ * has CONFIRMED owns at least one media row (its own, or its owning track's).
20389
+ * Absent is meaningful — "this visit has no event still" — never "we did not
20390
+ * look". Stamping it from a URL template made 35% of one camera's clips point
20391
+ * at a 404 (device 3836, 2026-08-17: 64 of 179 clips dead, 63 of them motion).
20392
+ * A read that FAILS drops the claim; it never invents it.
20343
20393
  */
20344
20394
  thumbnail: string().optional(),
20345
- /** Analytics event ids that overlap this visit. Empty on footage-only clips.
20346
- * The default provider's visit grain puts many motion heartbeats on one clip
20347
- * instead of minting one clip per marker. */
20395
+ /**
20396
+ * An instant INSIDE this visit's footage, hole-safe, where a recorded still
20397
+ * can be decoded. Present whenever the visit came from recorded availability;
20398
+ * absent on a per-event padded window (there is no footage to promise).
20399
+ *
20400
+ * This is not a thumbnail and not a second byte path: it is the argument to
20401
+ * the recorder's existing still route. The surface — never the provider —
20402
+ * decides whether to use it. It is the midpoint of the visit's LONGEST
20403
+ * contiguous range, not of the visit: a visit spans its holes by
20404
+ * construction, so a naive midpoint lands in dead air.
20405
+ */
20406
+ stillAtMs: number().optional(),
20407
+ /**
20408
+ * Analytics event ids that overlap this visit — a BOUNDED sample, newest
20409
+ * first within kind (object → motion → audio), capped at
20410
+ * {@link MAX_CLIP_EVENT_IDS}. Empty on footage-only clips.
20411
+ *
20412
+ * Bounded because it is not a payload the surface pages through: one visit on
20413
+ * device 615 carried 2 345 ids, and `eventIds` was 99% of a 153 KB
20414
+ * camera-day. Read {@link eventCount} for the true total.
20415
+ */
20348
20416
  eventIds: array(string()).optional(),
20417
+ /** How many analytics events actually overlap this visit. Differs from
20418
+ * `eventIds.length` exactly when the sample was capped — so a truncated
20419
+ * list is never mistaken for a quiet visit. */
20420
+ eventCount: number().int().nonnegative().optional(),
20349
20421
  /** Intra-visit footage holes (GOP rolls, discarded segments) still shorter
20350
20422
  * than `VISIT_MERGE_GAP_MS`. Playback concatenates around them; the timeline
20351
20423
  * bar keeps showing them via `recording.getAvailability`. */
@@ -20816,7 +20888,14 @@ var SearchResultSchema = object({
20816
20888
  });
20817
20889
  var AutoUpdateSettingsSchema = object({
20818
20890
  channel: ChannelSchema,
20819
- intervalSeconds: number()
20891
+ intervalSeconds: number(),
20892
+ /**
20893
+ * Cadence of the "an update exists" POLLER, in seconds. Independent of
20894
+ * `channel`: the poller runs while auto-apply is `off`, because being told
20895
+ * about a publish and installing it are different decisions. Clamped
20896
+ * server-side to 900 s … 604800 s; defaults to 21600 s (6 h).
20897
+ */
20898
+ updateCheckIntervalSeconds: number()
20820
20899
  });
20821
20900
  var AddonAutoUpdateSchema = ChannelWithInheritSchema;
20822
20901
  var RestartAddonResultSchema = unknown();
@@ -20957,7 +21036,9 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
20957
21036
  auth: "admin"
20958
21037
  }), method(_void(), AutoUpdateSettingsSchema, { auth: "admin" }), method(object({
20959
21038
  channel: ChannelSchema,
20960
- intervalSeconds: number().min(300).max(86400).optional()
21039
+ intervalSeconds: number().min(300).max(86400).optional(),
21040
+ /** Availability-poll cadence; see AutoUpdateSettingsSchema. */
21041
+ updateCheckIntervalSeconds: number().min(900).max(604800).optional()
20961
21042
  }), unknown(), {
20962
21043
  kind: "mutation",
20963
21044
  auth: "admin"
@@ -32987,6 +33068,12 @@ Object.freeze({
32987
33068
  addonId: null,
32988
33069
  access: "create"
32989
33070
  },
33071
+ "pipelineAnalytics.reconcileFromDisk": {
33072
+ capName: "pipeline-analytics",
33073
+ capScope: "device",
33074
+ addonId: null,
33075
+ access: "create"
33076
+ },
32990
33077
  "pipelineAnalytics.refreshStorageLocationsForMigration": {
32991
33078
  capName: "pipeline-analytics",
32992
33079
  capScope: "device",
@@ -33389,6 +33476,12 @@ Object.freeze({
33389
33476
  addonId: null,
33390
33477
  access: "view"
33391
33478
  },
33479
+ "pipelineOrchestrator.getReconcileFromDiskStatus": {
33480
+ capName: "pipeline-orchestrator",
33481
+ capScope: "system",
33482
+ addonId: null,
33483
+ access: "view"
33484
+ },
33392
33485
  "pipelineOrchestrator.listAgentSettings": {
33393
33486
  capName: "pipeline-orchestrator",
33394
33487
  capScope: "system",
@@ -33413,6 +33506,12 @@ Object.freeze({
33413
33506
  addonId: null,
33414
33507
  access: "create"
33415
33508
  },
33509
+ "pipelineOrchestrator.reconcileFromDisk": {
33510
+ capName: "pipeline-orchestrator",
33511
+ capScope: "system",
33512
+ addonId: null,
33513
+ access: "create"
33514
+ },
33416
33515
  "pipelineOrchestrator.removeAgentSettings": {
33417
33516
  capName: "pipeline-orchestrator",
33418
33517
  capScope: "system",
@@ -36404,6 +36503,11 @@ Object.freeze({
36404
36503
  form: "single",
36405
36504
  optional: true
36406
36505
  }],
36506
+ "pipelineAnalytics.reconcileFromDisk": [{
36507
+ name: "deviceId",
36508
+ form: "single",
36509
+ optional: false
36510
+ }],
36407
36511
  "pipelineAnalytics.restageRetrainTrack": [{
36408
36512
  name: "deviceId",
36409
36513
  form: "single",
@@ -37469,6 +37573,8 @@ DEFAULT_NATIVE_LEASE_SETTINGS.budgetMb;
37469
37573
  DEFAULT_NATIVE_LEASE_SETTINGS.activityMs;
37470
37574
  DEFAULT_NATIVE_LEASE_SETTINGS.tileBudgetMb;
37471
37575
  DEFAULT_NATIVE_LEASE_SETTINGS.admission;
37576
+ var MB = 1024 * 1024;
37577
+ 1024 * MB, 3072 * MB;
37472
37578
  //#endregion
37473
37579
  //#region ../../node_modules/@apocaliss92/wyze-bridge-js/dist/index.js
37474
37580
  var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, { get: (a, b) => (typeof require !== "undefined" ? require : a)[b] }) : x)(function(x) {
package/dist/addon.mjs CHANGED
@@ -10,7 +10,7 @@ import { getCACertificates, setDefaultCACertificates } from "node:tls";
10
10
  //#region \0rolldown/runtime.js
11
11
  var __require$1 = /* @__PURE__ */ createRequire(import.meta.url);
12
12
  //#endregion
13
- //#region ../types/dist/event-category-C0lyLd5U.mjs
13
+ //#region ../types/dist/event-category-XfKNtfCc.mjs
14
14
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
15
15
  EventCategory["SystemBoot"] = "system.boot";
16
16
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -49,6 +49,22 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
49
49
  EventCategory["AddonInstalled"] = "addon.installed";
50
50
  EventCategory["AddonUninstalled"] = "addon.uninstalled";
51
51
  EventCategory["AddonCrashed"] = "addon.crashed";
52
+ /**
53
+ * A RUNNER the D6 crash circuit-breaker gave up on — terminal.
54
+ *
55
+ * `AddonCrashed` is the routine, self-healing fact ("it crashed; it is being
56
+ * respawned"); this is the one that never resolves itself. Emitted exactly
57
+ * once per trip, by `process-service.ts`, carrying the node, the runner, the
58
+ * addons it hosted and the crash count that tripped the breaker.
59
+ *
60
+ * It exists because a runner marked terminally `failed` used to be SILENT:
61
+ * on 2026-08-18 the `recorder` runner died of three unhandled ffmpeg spawn
62
+ * errors, the breaker stopped respawning it (correctly), `/health` kept
63
+ * returning 200, and fleet-wide recording was gone for 3h15 before the
64
+ * operator's phone told him. The Notification Center's system-event intake
65
+ * consumes this category and maps it to the `addon-crash-loop` kind.
66
+ */
67
+ EventCategory["AddonRunnerFailed"] = "addon.runner-failed";
52
68
  EventCategory["AddonError"] = "addon.error";
53
69
  EventCategory["AddonPageReady"] = "addon.page-ready";
54
70
  EventCategory["AddonWidgetReady"] = "addon.widget-ready";
@@ -7611,6 +7627,12 @@ var RecordingConfigSchema = object({
7611
7627
  /** DERIVED summary of `bands`, stamped by the recorder on every save.
7612
7628
  * Authoring it has no effect — see {@link RecordingStorageModeSchema}. */
7613
7629
  mode: RecordingStorageModeSchema.optional(),
7630
+ /**
7631
+ * Which assigned broker slots to record. Absent / empty = {@link
7632
+ * DEFAULT_RECORDING_PROFILES} (`high`+`low`) intersected with the
7633
+ * camera's currently assigned slots — never `mid` unless the operator
7634
+ * picks it, and never a slot the broker has not assigned.
7635
+ */
7614
7636
  profiles: array(CamProfileSchema).optional(),
7615
7637
  segmentSeconds: number().int().positive().optional(),
7616
7638
  /**
@@ -7691,7 +7713,11 @@ var RelocateFootageInputSchema = object({
7691
7713
  profiles: array(string()).optional(),
7692
7714
  /** Copy throttle in MB/s (default 40) — the drain is a background chore,
7693
7715
  * never allowed to starve live writers. */
7694
- throttleMbps: number().min(1).max(1e3).optional()
7716
+ throttleMbps: number().min(1).max(1e3).optional(),
7717
+ /** Move only segments whose startMs is >= this. Absent = the whole source
7718
+ * pile. Used when a full drain is too expensive and the operator only
7719
+ * wants the recent window on the new disk. */
7720
+ sinceMs: number().int().optional()
7695
7721
  });
7696
7722
  /** Internal, lease-scoped participant operation. It is intentionally separate
7697
7723
  * from persistent recording settings: a migration never changes
@@ -14573,6 +14599,7 @@ var NcSystemEventKindSchema = _enum([
14573
14599
  "node-offline",
14574
14600
  "node-inference-unavailable",
14575
14601
  "detection-blind",
14602
+ "addon-crash-loop",
14576
14603
  "addon-update-available",
14577
14604
  "server-update-available",
14578
14605
  "alarm-triggered",
@@ -17146,6 +17173,12 @@ var TrackCascadeCountsSchema = object({
17146
17173
  /** Per-track CLIP search vectors removed (best-effort). */
17147
17174
  embeddings: number().int()
17148
17175
  });
17176
+ /** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
17177
+ var DiskReconcileCountsSchema = object({
17178
+ mediaDropped: number().int(),
17179
+ tracks: number().int(),
17180
+ events: number().int()
17181
+ });
17149
17182
  /** Event-store footprint for one camera. */
17150
17183
  var EventStoreDeviceFootprintSchema = object({
17151
17184
  deviceId: number(),
@@ -17322,6 +17355,9 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
17322
17355
  }), method(object({ deviceId: number() }), TrackCascadeCountsSchema, {
17323
17356
  kind: "mutation",
17324
17357
  auth: "admin"
17358
+ }), method(object({ deviceId: number() }), DiskReconcileCountsSchema, {
17359
+ kind: "mutation",
17360
+ auth: "admin"
17325
17361
  }), method(object({
17326
17362
  deviceId: number(),
17327
17363
  trackIds: array(string()).min(1)
@@ -18872,6 +18908,24 @@ var CameraStatusDegradationSchema = object({
18872
18908
  *
18873
18909
  * See spec: `docs/superpowers/specs/2026-06-24-camera-status-aggregator-cap.md`
18874
18910
  */
18911
+ var DiskReconcileJobSchema = object({
18912
+ state: _enum([
18913
+ "idle",
18914
+ "running",
18915
+ "done",
18916
+ "error"
18917
+ ]),
18918
+ total: number().int().nonnegative(),
18919
+ completed: number().int().nonnegative(),
18920
+ currentDeviceId: number().int().nullable(),
18921
+ failed: array(number().int()).readonly(),
18922
+ mediaDropped: number().int().nonnegative(),
18923
+ tracks: number().int().nonnegative(),
18924
+ events: number().int().nonnegative(),
18925
+ startedAtMs: number().int().nullable(),
18926
+ finishedAtMs: number().int().nullable(),
18927
+ error: string().nullable()
18928
+ });
18875
18929
  var CameraStatusSchema = object({
18876
18930
  deviceId: number(),
18877
18931
  assignment: CameraAssignmentStatusSchema,
@@ -19103,7 +19157,10 @@ method(StorageMigrationLeaseInputSchema, object({ paused: literal(true) }), {
19103
19157
  }), CameraSwitchGroupSchema, {
19104
19158
  kind: "mutation",
19105
19159
  auth: "admin"
19106
- }), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
19160
+ }), method(object({ deviceId: number() }), CameraStatusSchema), method(object({ deviceIds: array(number()).optional() }), array(CameraStatusSchema).readonly()), method(_void(), DiskReconcileJobSchema, {
19161
+ kind: "mutation",
19162
+ auth: "admin"
19163
+ }), method(_void(), DiskReconcileJobSchema, { auth: "admin" }), method(_void(), array(PipelineTemplateSchema).readonly()), method(object({
19107
19164
  name: string(),
19108
19165
  description: string().optional(),
19109
19166
  config: CameraPipelineConfigSchema
@@ -20280,20 +20337,6 @@ var VectorStatsResultSchema = object({
20280
20337
  exact: boolean()
20281
20338
  });
20282
20339
  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);
20283
- /**
20284
- * `videoclips` — the unified, navigable-clip surface for a camera.
20285
- *
20286
- * A device-scoped WRAPPER cap (like `pipeline-analytics`): exactly one active
20287
- * provider per device, substitutable. The DEFAULT provider (registered by
20288
- * `addon-post-analysis`, `defaultActive: true`) composes the analytics event
20289
- * log (markers + thumbnails) with the recorder's `getPlaybackManifest` — a clip
20290
- * is a time-WINDOW over existing footage, never a separate file. A camera that
20291
- * exposes NATIVE onboard clips (Reolink/Hikvision NVR) can later substitute the
20292
- * wrapper provider for its device and serve its own clip catalog + URLs.
20293
- *
20294
- * A `Clip` is purely time-based (subtree-blind): playback resolves segments by
20295
- * temporal overlap, so the API never decides `continuous` vs `events`.
20296
- */
20297
20340
  var ClipSchema = object({
20298
20341
  /** Opaque, provider-namespaced id. The default provider encodes the time
20299
20342
  * window so `getClipPlayback` is self-contained (no event re-query). */
@@ -20319,12 +20362,41 @@ var ClipSchema = object({
20319
20362
  * of the event that owns `kind` (object > motion > audio). Do not extract
20320
20363
  * a keyframe from the recorded segments. Other providers (onboard, HKSV)
20321
20364
  * mint their own stills.
20365
+ *
20366
+ * **VOUCHED, never fabricated.** A provider emits this only for an event it
20367
+ * has CONFIRMED owns at least one media row (its own, or its owning track's).
20368
+ * Absent is meaningful — "this visit has no event still" — never "we did not
20369
+ * look". Stamping it from a URL template made 35% of one camera's clips point
20370
+ * at a 404 (device 3836, 2026-08-17: 64 of 179 clips dead, 63 of them motion).
20371
+ * A read that FAILS drops the claim; it never invents it.
20322
20372
  */
20323
20373
  thumbnail: string().optional(),
20324
- /** Analytics event ids that overlap this visit. Empty on footage-only clips.
20325
- * The default provider's visit grain puts many motion heartbeats on one clip
20326
- * instead of minting one clip per marker. */
20374
+ /**
20375
+ * An instant INSIDE this visit's footage, hole-safe, where a recorded still
20376
+ * can be decoded. Present whenever the visit came from recorded availability;
20377
+ * absent on a per-event padded window (there is no footage to promise).
20378
+ *
20379
+ * This is not a thumbnail and not a second byte path: it is the argument to
20380
+ * the recorder's existing still route. The surface — never the provider —
20381
+ * decides whether to use it. It is the midpoint of the visit's LONGEST
20382
+ * contiguous range, not of the visit: a visit spans its holes by
20383
+ * construction, so a naive midpoint lands in dead air.
20384
+ */
20385
+ stillAtMs: number().optional(),
20386
+ /**
20387
+ * Analytics event ids that overlap this visit — a BOUNDED sample, newest
20388
+ * first within kind (object → motion → audio), capped at
20389
+ * {@link MAX_CLIP_EVENT_IDS}. Empty on footage-only clips.
20390
+ *
20391
+ * Bounded because it is not a payload the surface pages through: one visit on
20392
+ * device 615 carried 2 345 ids, and `eventIds` was 99% of a 153 KB
20393
+ * camera-day. Read {@link eventCount} for the true total.
20394
+ */
20327
20395
  eventIds: array(string()).optional(),
20396
+ /** How many analytics events actually overlap this visit. Differs from
20397
+ * `eventIds.length` exactly when the sample was capped — so a truncated
20398
+ * list is never mistaken for a quiet visit. */
20399
+ eventCount: number().int().nonnegative().optional(),
20328
20400
  /** Intra-visit footage holes (GOP rolls, discarded segments) still shorter
20329
20401
  * than `VISIT_MERGE_GAP_MS`. Playback concatenates around them; the timeline
20330
20402
  * bar keeps showing them via `recording.getAvailability`. */
@@ -20795,7 +20867,14 @@ var SearchResultSchema = object({
20795
20867
  });
20796
20868
  var AutoUpdateSettingsSchema = object({
20797
20869
  channel: ChannelSchema,
20798
- intervalSeconds: number()
20870
+ intervalSeconds: number(),
20871
+ /**
20872
+ * Cadence of the "an update exists" POLLER, in seconds. Independent of
20873
+ * `channel`: the poller runs while auto-apply is `off`, because being told
20874
+ * about a publish and installing it are different decisions. Clamped
20875
+ * server-side to 900 s … 604800 s; defaults to 21600 s (6 h).
20876
+ */
20877
+ updateCheckIntervalSeconds: number()
20799
20878
  });
20800
20879
  var AddonAutoUpdateSchema = ChannelWithInheritSchema;
20801
20880
  var RestartAddonResultSchema = unknown();
@@ -20936,7 +21015,9 @@ method(_void(), array(AddonListItemSchema).readonly()), method(object({
20936
21015
  auth: "admin"
20937
21016
  }), method(_void(), AutoUpdateSettingsSchema, { auth: "admin" }), method(object({
20938
21017
  channel: ChannelSchema,
20939
- intervalSeconds: number().min(300).max(86400).optional()
21018
+ intervalSeconds: number().min(300).max(86400).optional(),
21019
+ /** Availability-poll cadence; see AutoUpdateSettingsSchema. */
21020
+ updateCheckIntervalSeconds: number().min(900).max(604800).optional()
20940
21021
  }), unknown(), {
20941
21022
  kind: "mutation",
20942
21023
  auth: "admin"
@@ -32966,6 +33047,12 @@ Object.freeze({
32966
33047
  addonId: null,
32967
33048
  access: "create"
32968
33049
  },
33050
+ "pipelineAnalytics.reconcileFromDisk": {
33051
+ capName: "pipeline-analytics",
33052
+ capScope: "device",
33053
+ addonId: null,
33054
+ access: "create"
33055
+ },
32969
33056
  "pipelineAnalytics.refreshStorageLocationsForMigration": {
32970
33057
  capName: "pipeline-analytics",
32971
33058
  capScope: "device",
@@ -33368,6 +33455,12 @@ Object.freeze({
33368
33455
  addonId: null,
33369
33456
  access: "view"
33370
33457
  },
33458
+ "pipelineOrchestrator.getReconcileFromDiskStatus": {
33459
+ capName: "pipeline-orchestrator",
33460
+ capScope: "system",
33461
+ addonId: null,
33462
+ access: "view"
33463
+ },
33371
33464
  "pipelineOrchestrator.listAgentSettings": {
33372
33465
  capName: "pipeline-orchestrator",
33373
33466
  capScope: "system",
@@ -33392,6 +33485,12 @@ Object.freeze({
33392
33485
  addonId: null,
33393
33486
  access: "create"
33394
33487
  },
33488
+ "pipelineOrchestrator.reconcileFromDisk": {
33489
+ capName: "pipeline-orchestrator",
33490
+ capScope: "system",
33491
+ addonId: null,
33492
+ access: "create"
33493
+ },
33395
33494
  "pipelineOrchestrator.removeAgentSettings": {
33396
33495
  capName: "pipeline-orchestrator",
33397
33496
  capScope: "system",
@@ -36383,6 +36482,11 @@ Object.freeze({
36383
36482
  form: "single",
36384
36483
  optional: true
36385
36484
  }],
36485
+ "pipelineAnalytics.reconcileFromDisk": [{
36486
+ name: "deviceId",
36487
+ form: "single",
36488
+ optional: false
36489
+ }],
36386
36490
  "pipelineAnalytics.restageRetrainTrack": [{
36387
36491
  name: "deviceId",
36388
36492
  form: "single",
@@ -37448,6 +37552,8 @@ DEFAULT_NATIVE_LEASE_SETTINGS.budgetMb;
37448
37552
  DEFAULT_NATIVE_LEASE_SETTINGS.activityMs;
37449
37553
  DEFAULT_NATIVE_LEASE_SETTINGS.tileBudgetMb;
37450
37554
  DEFAULT_NATIVE_LEASE_SETTINGS.admission;
37555
+ var MB = 1024 * 1024;
37556
+ 1024 * MB, 3072 * MB;
37451
37557
  //#endregion
37452
37558
  //#region ../../node_modules/@apocaliss92/wyze-bridge-js/dist/index.js
37453
37559
  var __require = /* @__PURE__ */ ((x) => typeof __require$1 !== "undefined" ? __require$1 : typeof Proxy !== "undefined" ? new Proxy(x, { get: (a, b) => (typeof __require$1 !== "undefined" ? __require$1 : a)[b] }) : x)(function(x) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-wyze",
3
- "version": "0.2.23",
3
+ "version": "0.2.24",
4
4
  "description": "Wyze camera device-provider addon for CamStack — wraps the @apocaliss92/wyze-bridge-js P2P/DTLS client, feeding the stream-broker via the pull-rfc4571 lazy-publish path (a structural twin of addon-provider-reolink)",
5
5
  "keywords": [
6
6
  "camstack",