@camstack/addon-provider-onvif 1.2.24 → 1.2.26

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 +258 -17
  2. package/dist/addon.mjs +258 -17
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -2,7 +2,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  //#region \0rolldown/runtime.js
3
3
  var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
4
4
  //#endregion
5
- //#region ../types/dist/event-category-XfKNtfCc.mjs
5
+ //#region ../types/dist/event-category-CIa_iT6b.mjs
6
6
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
7
7
  EventCategory["SystemBoot"] = "system.boot";
8
8
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -18,6 +18,15 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
18
18
  */
19
19
  EventCategory["SystemRestartCompleted"] = "system.restart-completed";
20
20
  /**
21
+ * The hub reissued its own TLS certificate at boot (`ensureTlsCert`).
22
+ * Emitted only when the material on disk actually changed, so an
23
+ * operator who trusted the old certificate by hand is told rather than
24
+ * discovering it as a browser error. Payload `TlsCertChangedPayload`.
25
+ *
26
+ * Rule: docs/decisions/adr-0227-*.md
27
+ */
28
+ EventCategory["SystemTlsCertChanged"] = "system.tls-cert-changed";
29
+ /**
21
30
  * A newer addon or server-root package version was found by the
22
31
  * authoritative registry check. Emitted once when any observed
23
32
  * `latestVersion` changes (or a package/node first appears behind);
@@ -8010,6 +8019,15 @@ var LabelDefinitionSchema = object({
8010
8019
  description: string().optional(),
8011
8020
  icon: string().optional()
8012
8021
  });
8022
+ var ClassMapDefinitionSchema = object({
8023
+ mapping: record(string(), _enum([
8024
+ "person",
8025
+ "vehicle",
8026
+ "animal",
8027
+ "package"
8028
+ ])),
8029
+ preserveOriginal: boolean()
8030
+ });
8013
8031
  var MODEL_FORMATS = [
8014
8032
  "onnx",
8015
8033
  "coreml",
@@ -8188,7 +8206,13 @@ var ModelCatalogEntrySchema = object({
8188
8206
  * `id` stays the source of truth for resolution/download/persistence; grouping
8189
8207
  * is a presentation overlay resolved back to an `id`.
8190
8208
  */
8191
- group: ModelVariantGroupSchema.optional()
8209
+ group: ModelVariantGroupSchema.optional(),
8210
+ /**
8211
+ * Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
8212
+ * applies (Frigate / COCO public catalog). Set on a custom model whose raw
8213
+ * labels already ARE the CamStack macros (Scrypted identity map).
8214
+ */
8215
+ classMap: ClassMapDefinitionSchema.optional()
8192
8216
  });
8193
8217
  var ConvertTargetSchema = discriminatedUnion("format", [object({
8194
8218
  format: literal("openvino"),
@@ -8217,7 +8241,8 @@ var ModelConvertMetadataSchema = object({
8217
8241
  "ocr",
8218
8242
  "segmentation"
8219
8243
  ]),
8220
- faceAlignment: boolean().optional()
8244
+ faceAlignment: boolean().optional(),
8245
+ classMap: ClassMapDefinitionSchema.optional()
8221
8246
  });
8222
8247
  var ConvertResultSchema = object({
8223
8248
  entry: ModelCatalogEntrySchema,
@@ -17263,6 +17288,33 @@ var NativeCropRefSchema = object({
17263
17288
  h: number()
17264
17289
  })
17265
17290
  });
17291
+ object({
17292
+ crop: object({
17293
+ left: number(),
17294
+ top: number(),
17295
+ width: number().positive(),
17296
+ height: number().positive()
17297
+ }).optional(),
17298
+ content: object({
17299
+ width: number().int().positive(),
17300
+ height: number().int().positive()
17301
+ }),
17302
+ fit: _enum(["stretch", "contain"]),
17303
+ format: _enum([
17304
+ "rgb",
17305
+ "gray",
17306
+ "jpeg"
17307
+ ])
17308
+ });
17309
+ var FrameRefSchema = object({
17310
+ registryId: string().min(1),
17311
+ id: string().min(1),
17312
+ width: number().int().positive(),
17313
+ height: number().int().positive(),
17314
+ format: _enum(["rgb", "gray"]),
17315
+ timestamp: number(),
17316
+ capturedAt: number().optional()
17317
+ });
17266
17318
  var ModelFormatSchema$1 = _enum([
17267
17319
  "onnx",
17268
17320
  "coreml",
@@ -17507,6 +17559,12 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
17507
17559
  steps: array(PipelineStepInputSchema).min(1),
17508
17560
  frame: FrameInputSchema.optional(),
17509
17561
  /**
17562
+ * Process-local lazy frame. Valid only when caller and provider resolve
17563
+ * in the same execution-group process; split/cross-node callers use
17564
+ * `frame`/`image` inline compatibility instead.
17565
+ */
17566
+ frameRef: FrameRefSchema.optional(),
17567
+ /**
17510
17568
  * CB5 shm passthrough — a `FrameHandle` naming the same ring slot
17511
17569
  * the decoded pixels live in. One more member of the one-of
17512
17570
  * frame/frameHandle/image/imageBase64/referenceImage group.
@@ -17762,7 +17820,10 @@ var NativeCropResultSchema = object({
17762
17820
  * Which source served this crop, so a quality-sensitive consumer (the native
17763
17821
  * `keyFrame`) can reject a degraded fallback:
17764
17822
  * - `native` — cut from the decode worker's retained NATIVE surface (the
17765
- * quality path).
17823
+ * quality path). A subject-tile serve is also native-resolution and stays
17824
+ * `native` here: the public enum cannot name `tile` without a breaking cap
17825
+ * change. Runner telemetry distinguishes lease vs tile via `source` on the
17826
+ * internal crop result (`nativeHits` vs `tileHits`).
17766
17827
  * - `ram-fullframe` — the native surface MISSED but the request was full-frame,
17767
17828
  * so the ≤640 RAM `RetainedFrameStore` served it (honest lower-res; legit for
17768
17829
  * the blank-frame guard / 640-snapshot resolve, NOT for the clean keyFrame).
@@ -18253,12 +18314,41 @@ var RunnerLocalLoadSchema = object({
18253
18314
  * legacy `OrchestratorMetricsSchema` shape so existing dashboards keep
18254
18315
  * working unchanged when they switch to reading from the runner cap.
18255
18316
  */
18317
+ var FrameLazyCountersSchema = object({
18318
+ framesDecoded: number(),
18319
+ framesAdmitted: number(),
18320
+ framesDroppedPixelFree: number(),
18321
+ viewsMaterialized: number(),
18322
+ viewsSkipped: number(),
18323
+ workerToRunnerBytes: number(),
18324
+ runnerToPoolRawBytes: number(),
18325
+ runnerToPoolJpegBytes: number(),
18326
+ onDemandFullFrameRequests: number(),
18327
+ onDemandCropRequests: number(),
18328
+ nativeHits: number(),
18329
+ nativeMisses: number(),
18330
+ tileHits: number(),
18331
+ tileMisses: number(),
18332
+ fallbackHits: number(),
18333
+ fallbackMisses: number(),
18334
+ retainedWritesAvoided: number(),
18335
+ residentRefs: number(),
18336
+ residentBytes: number(),
18337
+ releases: number(),
18338
+ evictions: number(),
18339
+ staleMisses: number()
18340
+ });
18341
+ var FrameLazyMetricsSchema = object({
18342
+ node: FrameLazyCountersSchema,
18343
+ cameras: array(FrameLazyCountersSchema.extend({ deviceId: number() }))
18344
+ });
18256
18345
  var RunnerLocalMetricsSchema = object({
18257
18346
  nodeId: string(),
18258
18347
  activeCameras: number(),
18259
18348
  throttledCameras: number(),
18260
18349
  avgInferenceTimeMs: number(),
18261
- queueDepth: number()
18350
+ queueDepth: number(),
18351
+ frameLazy: FrameLazyMetricsSchema.optional()
18262
18352
  });
18263
18353
  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({
18264
18354
  handle: FrameHandleSchema,
@@ -19662,6 +19752,9 @@ method(_void(), ProviderInfoSchema), method(object({ config: record(string(), un
19662
19752
  location: StorageLocationSchema,
19663
19753
  relativePath: string()
19664
19754
  }), _void(), { kind: "mutation" }), method(object({ location: StorageLocationSchema }), number().nullable()), method(BeginUploadInputSchema, BeginUploadResultSchema, { kind: "mutation" }), method(WriteChunkInputSchema, _void(), { kind: "mutation" }), method(FinalizeUploadInputSchema, _void(), { kind: "mutation" }), method(AbortUploadInputSchema, _void(), { kind: "mutation" }), method(BeginDownloadInputSchema, BeginDownloadResultSchema, { kind: "mutation" }), method(ReadChunkInputSchema, _instanceof(Uint8Array)), method(EndDownloadInputSchema, _void(), { kind: "mutation" });
19755
+ /** Profile-exported FormBuilder schema. Shape is ConfigUISchema at the UI. */
19756
+ var ProfileSettingsSchemaBridge = unknown().nullable();
19757
+ var ProfileSettingsBagSchema = record(string(), unknown());
19665
19758
  /**
19666
19759
  * A live terminal session hosted by the provider addon. Output and input do
19667
19760
  * NOT flow through the capability — they use the addon data plane
@@ -19691,7 +19784,14 @@ var TerminalSessionInfoSchema = object({
19691
19784
  var TerminalProfileInfoSchema = object({
19692
19785
  profileId: string(),
19693
19786
  label: string(),
19694
- description: string().optional()
19787
+ description: string().optional(),
19788
+ /** Spawn defaults the instance form copies on create. */
19789
+ executable: string().optional(),
19790
+ args: array(string()).readonly().optional(),
19791
+ cwd: string().optional(),
19792
+ environment: array(string()).readonly().optional(),
19793
+ /** ConfigUISchema for instance knobs, or null when the profile has none. */
19794
+ settingsSchema: ProfileSettingsSchemaBridge.optional()
19695
19795
  });
19696
19796
  /**
19697
19797
  * A durable operator-created Terminal instance. Profiles are templates; only
@@ -19704,7 +19804,12 @@ var TerminalInstanceInfoSchema = object({
19704
19804
  profileId: string(),
19705
19805
  profileLabel: string(),
19706
19806
  name: string(),
19707
- enabled: boolean()
19807
+ enabled: boolean(),
19808
+ executable: string(),
19809
+ args: array(string()).readonly(),
19810
+ cwd: string(),
19811
+ environment: array(string()).readonly(),
19812
+ profileSettings: ProfileSettingsBagSchema
19708
19813
  });
19709
19814
  var TerminalLegacyCameraSchema = object({
19710
19815
  stableId: string(),
@@ -19734,7 +19839,23 @@ var TerminalOutputBatchSchema = object({
19734
19839
  method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }), method(_void(), array(TerminalInstanceInfoSchema).readonly(), { auth: "admin" }), method(object({
19735
19840
  targetNodeId: string().min(1),
19736
19841
  profileId: string().min(1),
19737
- name: string().trim().min(1).max(160).optional()
19842
+ name: string().trim().min(1).max(160).optional(),
19843
+ executable: string().max(1024).optional(),
19844
+ args: array(string().max(2048)).max(64).optional(),
19845
+ cwd: string().max(1024).optional(),
19846
+ environment: array(string().max(4096)).max(64).optional(),
19847
+ profileSettings: ProfileSettingsBagSchema.optional()
19848
+ }), TerminalInstanceInfoSchema, {
19849
+ kind: "mutation",
19850
+ auth: "admin"
19851
+ }), method(object({
19852
+ instanceId: string().min(1),
19853
+ name: string().trim().min(1).max(160).optional(),
19854
+ executable: string().max(1024).optional(),
19855
+ args: array(string().max(2048)).max(64).optional(),
19856
+ cwd: string().max(1024).optional(),
19857
+ environment: array(string().max(4096)).max(64).optional(),
19858
+ profileSettings: ProfileSettingsBagSchema.optional()
19738
19859
  }), TerminalInstanceInfoSchema, {
19739
19860
  kind: "mutation",
19740
19861
  auth: "admin"
@@ -19756,7 +19877,11 @@ method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }),
19756
19877
  }), method(_void(), array(TerminalSessionInfoSchema).readonly(), { auth: "admin" }), method(object({
19757
19878
  profileId: string(),
19758
19879
  cols: number().int().positive(),
19759
- rows: number().int().positive()
19880
+ rows: number().int().positive(),
19881
+ executable: string().max(1024).optional(),
19882
+ args: array(string().max(2048)).max(64).optional(),
19883
+ cwd: string().max(1024).optional(),
19884
+ environment: array(string().max(4096)).max(64).optional()
19760
19885
  }), TerminalSessionInfoSchema, {
19761
19886
  kind: "mutation",
19762
19887
  auth: "admin"
@@ -22538,10 +22663,10 @@ DeviceType.LawnMower, method(object({ deviceId: number().int().nonnegative() }),
22538
22663
  *
22539
22664
  * • The SDK (mobile / web client) consumes `getConnectionEndpoints()`
22540
22665
  * to receive an ordered list of candidate base URLs it should race
22541
- * on connect — LAN IPv4 first (lowest latency when on same network),
22542
- * then public hostname (if a tunnel is up), then IPv6. The SDK can
22543
- * race them with short timeouts and stick with the winner for the
22544
- * session.
22666
+ * on connect — LAN IPv4 and stable LAN IPv6 first (lowest latency
22667
+ * when on the same network), then public hostname (if a tunnel is
22668
+ * up). The SDK can race them with short timeouts and stick with the
22669
+ * winner for the session.
22545
22670
  *
22546
22671
  * Why hub-only: agents are not directly addressable by the operator's
22547
22672
  * clients — they reverse-connect to the hub. Exposing their interfaces
@@ -22696,6 +22821,17 @@ var NotificationEndpointSchema = object({
22696
22821
  /** What the ranking currently resolves to (null when nothing is reachable). */
22697
22822
  resolved: string().nullable()
22698
22823
  });
22824
+ /**
22825
+ * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
22826
+ * AUTO (every LAN IPv4 + the public tunnel). `resolved` is what that choice
22827
+ * currently expands to, so the UI can show the effective set either way.
22828
+ */
22829
+ var ViewerEndpointsSchema = object({
22830
+ /** The operator's explicit race set, or empty for AUTO. */
22831
+ baseUrls: array(string()).readonly(),
22832
+ /** What the ranking currently resolves to (may be empty if nothing is up). */
22833
+ resolved: array(string()).readonly()
22834
+ });
22699
22835
  var AllowedAddressesSchema = object({
22700
22836
  /**
22701
22837
  * Allowlist of interface addresses operators have explicitly opted
@@ -22704,6 +22840,20 @@ var AllowedAddressesSchema = object({
22704
22840
  * Network Addresses admin page and persisted by the addon.
22705
22841
  */
22706
22842
  addresses: array(string()).readonly() });
22843
+ var TlsStatusSchema = object({
22844
+ mode: _enum([
22845
+ "generated",
22846
+ "uploaded",
22847
+ "disabled"
22848
+ ]),
22849
+ leafFingerprintSha256: string().nullable(),
22850
+ caFingerprintSha256: string().nullable(),
22851
+ validTo: string().nullable(),
22852
+ sans: array(string()),
22853
+ caCertPem: string().nullable(),
22854
+ reissueError: string().nullable(),
22855
+ restartRequired: boolean()
22856
+ });
22707
22857
  method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
22708
22858
  /**
22709
22859
  * LEGACY HINT — do not send from new code. Kept optional so clients
@@ -22713,17 +22863,31 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
22713
22863
  */
22714
22864
  port: number().int().min(1).max(65535).optional(),
22715
22865
  /** Include `http(s)://127.0.0.1:<port>` as the lowest-priority
22716
- * candidate. Default `true`. */
22866
+ * candidate. Default `false` — loopback is not a client route. */
22717
22867
  includeLoopback: boolean().optional(),
22718
- /** Skip IPv6 entries. Some legacy clients can't parse them.
22719
- * Default `false`. */
22868
+ /** Skip IPv6 entries. Default `false` the palette includes stable
22869
+ * LAN IPv6 (ICE/WebRTC uses dual-stack regardless). Pass `true` to
22870
+ * hide them. The viewer HTTP/WS race is `getViewerEndpoints`. */
22720
22871
  ipv4Only: boolean().optional(),
22721
22872
  /** Scheme to emit for LAN/loopback URLs. Default `'http'`.
22722
22873
  * Pass `'https'` when the caller is itself loaded over HTTPS
22723
22874
  * to avoid mixed-content blocks in the browser. The public
22724
22875
  * tunnel always emits `https://` regardless. */
22725
22876
  scheme: _enum(["http", "https"]).optional()
22726
- }), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), AllowedAddressesSchema), method(AllowedAddressesSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), AllowedAddressesSchema, { kind: "mutation" });
22877
+ }), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), ViewerEndpointsSchema), method(object({ baseUrls: array(string()).readonly() }), ViewerEndpointsSchema, { kind: "mutation" }), method(_void(), AllowedAddressesSchema), method(AllowedAddressesSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), AllowedAddressesSchema, { kind: "mutation" }), method(_void(), TlsStatusSchema), method(object({ reason: string().optional() }), TlsStatusSchema, {
22878
+ kind: "mutation",
22879
+ auth: "admin"
22880
+ }), method(object({
22881
+ certPem: string().min(1),
22882
+ keyPem: string().min(1),
22883
+ caPem: string().optional()
22884
+ }), TlsStatusSchema, {
22885
+ kind: "mutation",
22886
+ auth: "admin"
22887
+ }), method(_void(), object({ pem: string() })), method(_void(), TlsStatusSchema, {
22888
+ kind: "mutation",
22889
+ auth: "admin"
22890
+ });
22727
22891
  object({
22728
22892
  /** Lifecycle state of the lock. `jammed` means the motor reported
22729
22893
  * failure to reach the target — operator intervention required. */
@@ -28938,6 +29102,12 @@ Object.freeze({
28938
29102
  addonId: null,
28939
29103
  access: "create"
28940
29104
  },
29105
+ "localNetwork.downloadCa": {
29106
+ capName: "local-network",
29107
+ capScope: "system",
29108
+ addonId: null,
29109
+ access: "view"
29110
+ },
28941
29111
  "localNetwork.getAllowedAddresses": {
28942
29112
  capName: "local-network",
28943
29113
  capScope: "system",
@@ -28962,18 +29132,42 @@ Object.freeze({
28962
29132
  addonId: null,
28963
29133
  access: "view"
28964
29134
  },
29135
+ "localNetwork.getTlsStatus": {
29136
+ capName: "local-network",
29137
+ capScope: "system",
29138
+ addonId: null,
29139
+ access: "view"
29140
+ },
29141
+ "localNetwork.getViewerEndpoints": {
29142
+ capName: "local-network",
29143
+ capScope: "system",
29144
+ addonId: null,
29145
+ access: "view"
29146
+ },
28965
29147
  "localNetwork.list": {
28966
29148
  capName: "local-network",
28967
29149
  capScope: "system",
28968
29150
  addonId: null,
28969
29151
  access: "view"
28970
29152
  },
29153
+ "localNetwork.regenerateCertificate": {
29154
+ capName: "local-network",
29155
+ capScope: "system",
29156
+ addonId: null,
29157
+ access: "create"
29158
+ },
28971
29159
  "localNetwork.resetAllowlistToBestMatch": {
28972
29160
  capName: "local-network",
28973
29161
  capScope: "system",
28974
29162
  addonId: null,
28975
29163
  access: "delete"
28976
29164
  },
29165
+ "localNetwork.revertToGeneratedCertificate": {
29166
+ capName: "local-network",
29167
+ capScope: "system",
29168
+ addonId: null,
29169
+ access: "create"
29170
+ },
28977
29171
  "localNetwork.setAllowedAddresses": {
28978
29172
  capName: "local-network",
28979
29173
  capScope: "system",
@@ -28986,6 +29180,18 @@ Object.freeze({
28986
29180
  addonId: null,
28987
29181
  access: "create"
28988
29182
  },
29183
+ "localNetwork.setViewerEndpoints": {
29184
+ capName: "local-network",
29185
+ capScope: "system",
29186
+ addonId: null,
29187
+ access: "create"
29188
+ },
29189
+ "localNetwork.uploadCertificate": {
29190
+ capName: "local-network",
29191
+ capScope: "system",
29192
+ addonId: null,
29193
+ access: "create"
29194
+ },
28989
29195
  "lockControl.lock": {
28990
29196
  capName: "lock-control",
28991
29197
  capScope: "device",
@@ -31866,6 +32072,12 @@ Object.freeze({
31866
32072
  addonId: null,
31867
32073
  access: "create"
31868
32074
  },
32075
+ "terminalSession.updateInstance": {
32076
+ capName: "terminal-session",
32077
+ capScope: "system",
32078
+ addonId: null,
32079
+ access: "create"
32080
+ },
31869
32081
  "terminalSession.writeInput": {
31870
32082
  capName: "terminal-session",
31871
32083
  capScope: "system",
@@ -34353,6 +34565,35 @@ Object.freeze(Object.fromEntries([{
34353
34565
  }]
34354
34566
  }].map((s) => [s.stepId, s.defaultModelId])));
34355
34567
  string().min(1);
34568
+ var CLUSTER_STEP_SETTING_FIELDS = [{
34569
+ stepId: "face-embedding",
34570
+ key: "minLandmarkFaceSize",
34571
+ label: "Min face size for recognition (detection px)",
34572
+ description: "Refuse to embed a face smaller than this IN THE DETECTION FRAME. Applies to every node — the enrolled gallery is one index, and two admission floors would fill it from two policies. 0 disables the gate.",
34573
+ type: "slider",
34574
+ min: 0,
34575
+ max: 64,
34576
+ step: 2,
34577
+ default: 24
34578
+ }];
34579
+ function clusterStepSettingKey(stepId, fieldKey) {
34580
+ return `clusterStepSetting:${stepId}:${fieldKey}`;
34581
+ }
34582
+ var ClusterSettingNumberSchema = number().finite();
34583
+ function readClusterStepSettings(config) {
34584
+ const out = {};
34585
+ for (const field of CLUSTER_STEP_SETTING_FIELDS) {
34586
+ const parsed = ClusterSettingNumberSchema.safeParse(config[clusterStepSettingKey(field.stepId, field.key)]);
34587
+ const value = parsed.success ? parsed.data : field.default;
34588
+ const existing = out[field.stepId] ?? {};
34589
+ out[field.stepId] = {
34590
+ ...existing,
34591
+ [field.key]: value
34592
+ };
34593
+ }
34594
+ return out;
34595
+ }
34596
+ readClusterStepSettings({});
34356
34597
  object({
34357
34598
  /**
34358
34599
  * Fraction of the box's own size added on EACH side before cutting.
package/dist/addon.mjs CHANGED
@@ -3,7 +3,7 @@ import { createRequire } from "node:module";
3
3
  var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
4
4
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
5
5
  //#endregion
6
- //#region ../types/dist/event-category-XfKNtfCc.mjs
6
+ //#region ../types/dist/event-category-CIa_iT6b.mjs
7
7
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
8
8
  EventCategory["SystemBoot"] = "system.boot";
9
9
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -19,6 +19,15 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
19
19
  */
20
20
  EventCategory["SystemRestartCompleted"] = "system.restart-completed";
21
21
  /**
22
+ * The hub reissued its own TLS certificate at boot (`ensureTlsCert`).
23
+ * Emitted only when the material on disk actually changed, so an
24
+ * operator who trusted the old certificate by hand is told rather than
25
+ * discovering it as a browser error. Payload `TlsCertChangedPayload`.
26
+ *
27
+ * Rule: docs/decisions/adr-0227-*.md
28
+ */
29
+ EventCategory["SystemTlsCertChanged"] = "system.tls-cert-changed";
30
+ /**
22
31
  * A newer addon or server-root package version was found by the
23
32
  * authoritative registry check. Emitted once when any observed
24
33
  * `latestVersion` changes (or a package/node first appears behind);
@@ -8011,6 +8020,15 @@ var LabelDefinitionSchema = object({
8011
8020
  description: string().optional(),
8012
8021
  icon: string().optional()
8013
8022
  });
8023
+ var ClassMapDefinitionSchema = object({
8024
+ mapping: record(string(), _enum([
8025
+ "person",
8026
+ "vehicle",
8027
+ "animal",
8028
+ "package"
8029
+ ])),
8030
+ preserveOriginal: boolean()
8031
+ });
8014
8032
  var MODEL_FORMATS = [
8015
8033
  "onnx",
8016
8034
  "coreml",
@@ -8189,7 +8207,13 @@ var ModelCatalogEntrySchema = object({
8189
8207
  * `id` stays the source of truth for resolution/download/persistence; grouping
8190
8208
  * is a presentation overlay resolved back to an `id`.
8191
8209
  */
8192
- group: ModelVariantGroupSchema.optional()
8210
+ group: ModelVariantGroupSchema.optional(),
8211
+ /**
8212
+ * Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
8213
+ * applies (Frigate / COCO public catalog). Set on a custom model whose raw
8214
+ * labels already ARE the CamStack macros (Scrypted identity map).
8215
+ */
8216
+ classMap: ClassMapDefinitionSchema.optional()
8193
8217
  });
8194
8218
  var ConvertTargetSchema = discriminatedUnion("format", [object({
8195
8219
  format: literal("openvino"),
@@ -8218,7 +8242,8 @@ var ModelConvertMetadataSchema = object({
8218
8242
  "ocr",
8219
8243
  "segmentation"
8220
8244
  ]),
8221
- faceAlignment: boolean().optional()
8245
+ faceAlignment: boolean().optional(),
8246
+ classMap: ClassMapDefinitionSchema.optional()
8222
8247
  });
8223
8248
  var ConvertResultSchema = object({
8224
8249
  entry: ModelCatalogEntrySchema,
@@ -17264,6 +17289,33 @@ var NativeCropRefSchema = object({
17264
17289
  h: number()
17265
17290
  })
17266
17291
  });
17292
+ object({
17293
+ crop: object({
17294
+ left: number(),
17295
+ top: number(),
17296
+ width: number().positive(),
17297
+ height: number().positive()
17298
+ }).optional(),
17299
+ content: object({
17300
+ width: number().int().positive(),
17301
+ height: number().int().positive()
17302
+ }),
17303
+ fit: _enum(["stretch", "contain"]),
17304
+ format: _enum([
17305
+ "rgb",
17306
+ "gray",
17307
+ "jpeg"
17308
+ ])
17309
+ });
17310
+ var FrameRefSchema = object({
17311
+ registryId: string().min(1),
17312
+ id: string().min(1),
17313
+ width: number().int().positive(),
17314
+ height: number().int().positive(),
17315
+ format: _enum(["rgb", "gray"]),
17316
+ timestamp: number(),
17317
+ capturedAt: number().optional()
17318
+ });
17267
17319
  var ModelFormatSchema$1 = _enum([
17268
17320
  "onnx",
17269
17321
  "coreml",
@@ -17508,6 +17560,12 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
17508
17560
  steps: array(PipelineStepInputSchema).min(1),
17509
17561
  frame: FrameInputSchema.optional(),
17510
17562
  /**
17563
+ * Process-local lazy frame. Valid only when caller and provider resolve
17564
+ * in the same execution-group process; split/cross-node callers use
17565
+ * `frame`/`image` inline compatibility instead.
17566
+ */
17567
+ frameRef: FrameRefSchema.optional(),
17568
+ /**
17511
17569
  * CB5 shm passthrough — a `FrameHandle` naming the same ring slot
17512
17570
  * the decoded pixels live in. One more member of the one-of
17513
17571
  * frame/frameHandle/image/imageBase64/referenceImage group.
@@ -17763,7 +17821,10 @@ var NativeCropResultSchema = object({
17763
17821
  * Which source served this crop, so a quality-sensitive consumer (the native
17764
17822
  * `keyFrame`) can reject a degraded fallback:
17765
17823
  * - `native` — cut from the decode worker's retained NATIVE surface (the
17766
- * quality path).
17824
+ * quality path). A subject-tile serve is also native-resolution and stays
17825
+ * `native` here: the public enum cannot name `tile` without a breaking cap
17826
+ * change. Runner telemetry distinguishes lease vs tile via `source` on the
17827
+ * internal crop result (`nativeHits` vs `tileHits`).
17767
17828
  * - `ram-fullframe` — the native surface MISSED but the request was full-frame,
17768
17829
  * so the ≤640 RAM `RetainedFrameStore` served it (honest lower-res; legit for
17769
17830
  * the blank-frame guard / 640-snapshot resolve, NOT for the clean keyFrame).
@@ -18254,12 +18315,41 @@ var RunnerLocalLoadSchema = object({
18254
18315
  * legacy `OrchestratorMetricsSchema` shape so existing dashboards keep
18255
18316
  * working unchanged when they switch to reading from the runner cap.
18256
18317
  */
18318
+ var FrameLazyCountersSchema = object({
18319
+ framesDecoded: number(),
18320
+ framesAdmitted: number(),
18321
+ framesDroppedPixelFree: number(),
18322
+ viewsMaterialized: number(),
18323
+ viewsSkipped: number(),
18324
+ workerToRunnerBytes: number(),
18325
+ runnerToPoolRawBytes: number(),
18326
+ runnerToPoolJpegBytes: number(),
18327
+ onDemandFullFrameRequests: number(),
18328
+ onDemandCropRequests: number(),
18329
+ nativeHits: number(),
18330
+ nativeMisses: number(),
18331
+ tileHits: number(),
18332
+ tileMisses: number(),
18333
+ fallbackHits: number(),
18334
+ fallbackMisses: number(),
18335
+ retainedWritesAvoided: number(),
18336
+ residentRefs: number(),
18337
+ residentBytes: number(),
18338
+ releases: number(),
18339
+ evictions: number(),
18340
+ staleMisses: number()
18341
+ });
18342
+ var FrameLazyMetricsSchema = object({
18343
+ node: FrameLazyCountersSchema,
18344
+ cameras: array(FrameLazyCountersSchema.extend({ deviceId: number() }))
18345
+ });
18257
18346
  var RunnerLocalMetricsSchema = object({
18258
18347
  nodeId: string(),
18259
18348
  activeCameras: number(),
18260
18349
  throttledCameras: number(),
18261
18350
  avgInferenceTimeMs: number(),
18262
- queueDepth: number()
18351
+ queueDepth: number(),
18352
+ frameLazy: FrameLazyMetricsSchema.optional()
18263
18353
  });
18264
18354
  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({
18265
18355
  handle: FrameHandleSchema,
@@ -19663,6 +19753,9 @@ method(_void(), ProviderInfoSchema), method(object({ config: record(string(), un
19663
19753
  location: StorageLocationSchema,
19664
19754
  relativePath: string()
19665
19755
  }), _void(), { kind: "mutation" }), method(object({ location: StorageLocationSchema }), number().nullable()), method(BeginUploadInputSchema, BeginUploadResultSchema, { kind: "mutation" }), method(WriteChunkInputSchema, _void(), { kind: "mutation" }), method(FinalizeUploadInputSchema, _void(), { kind: "mutation" }), method(AbortUploadInputSchema, _void(), { kind: "mutation" }), method(BeginDownloadInputSchema, BeginDownloadResultSchema, { kind: "mutation" }), method(ReadChunkInputSchema, _instanceof(Uint8Array)), method(EndDownloadInputSchema, _void(), { kind: "mutation" });
19756
+ /** Profile-exported FormBuilder schema. Shape is ConfigUISchema at the UI. */
19757
+ var ProfileSettingsSchemaBridge = unknown().nullable();
19758
+ var ProfileSettingsBagSchema = record(string(), unknown());
19666
19759
  /**
19667
19760
  * A live terminal session hosted by the provider addon. Output and input do
19668
19761
  * NOT flow through the capability — they use the addon data plane
@@ -19692,7 +19785,14 @@ var TerminalSessionInfoSchema = object({
19692
19785
  var TerminalProfileInfoSchema = object({
19693
19786
  profileId: string(),
19694
19787
  label: string(),
19695
- description: string().optional()
19788
+ description: string().optional(),
19789
+ /** Spawn defaults the instance form copies on create. */
19790
+ executable: string().optional(),
19791
+ args: array(string()).readonly().optional(),
19792
+ cwd: string().optional(),
19793
+ environment: array(string()).readonly().optional(),
19794
+ /** ConfigUISchema for instance knobs, or null when the profile has none. */
19795
+ settingsSchema: ProfileSettingsSchemaBridge.optional()
19696
19796
  });
19697
19797
  /**
19698
19798
  * A durable operator-created Terminal instance. Profiles are templates; only
@@ -19705,7 +19805,12 @@ var TerminalInstanceInfoSchema = object({
19705
19805
  profileId: string(),
19706
19806
  profileLabel: string(),
19707
19807
  name: string(),
19708
- enabled: boolean()
19808
+ enabled: boolean(),
19809
+ executable: string(),
19810
+ args: array(string()).readonly(),
19811
+ cwd: string(),
19812
+ environment: array(string()).readonly(),
19813
+ profileSettings: ProfileSettingsBagSchema
19709
19814
  });
19710
19815
  var TerminalLegacyCameraSchema = object({
19711
19816
  stableId: string(),
@@ -19735,7 +19840,23 @@ var TerminalOutputBatchSchema = object({
19735
19840
  method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }), method(_void(), array(TerminalInstanceInfoSchema).readonly(), { auth: "admin" }), method(object({
19736
19841
  targetNodeId: string().min(1),
19737
19842
  profileId: string().min(1),
19738
- name: string().trim().min(1).max(160).optional()
19843
+ name: string().trim().min(1).max(160).optional(),
19844
+ executable: string().max(1024).optional(),
19845
+ args: array(string().max(2048)).max(64).optional(),
19846
+ cwd: string().max(1024).optional(),
19847
+ environment: array(string().max(4096)).max(64).optional(),
19848
+ profileSettings: ProfileSettingsBagSchema.optional()
19849
+ }), TerminalInstanceInfoSchema, {
19850
+ kind: "mutation",
19851
+ auth: "admin"
19852
+ }), method(object({
19853
+ instanceId: string().min(1),
19854
+ name: string().trim().min(1).max(160).optional(),
19855
+ executable: string().max(1024).optional(),
19856
+ args: array(string().max(2048)).max(64).optional(),
19857
+ cwd: string().max(1024).optional(),
19858
+ environment: array(string().max(4096)).max(64).optional(),
19859
+ profileSettings: ProfileSettingsBagSchema.optional()
19739
19860
  }), TerminalInstanceInfoSchema, {
19740
19861
  kind: "mutation",
19741
19862
  auth: "admin"
@@ -19757,7 +19878,11 @@ method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }),
19757
19878
  }), method(_void(), array(TerminalSessionInfoSchema).readonly(), { auth: "admin" }), method(object({
19758
19879
  profileId: string(),
19759
19880
  cols: number().int().positive(),
19760
- rows: number().int().positive()
19881
+ rows: number().int().positive(),
19882
+ executable: string().max(1024).optional(),
19883
+ args: array(string().max(2048)).max(64).optional(),
19884
+ cwd: string().max(1024).optional(),
19885
+ environment: array(string().max(4096)).max(64).optional()
19761
19886
  }), TerminalSessionInfoSchema, {
19762
19887
  kind: "mutation",
19763
19888
  auth: "admin"
@@ -22539,10 +22664,10 @@ DeviceType.LawnMower, method(object({ deviceId: number().int().nonnegative() }),
22539
22664
  *
22540
22665
  * • The SDK (mobile / web client) consumes `getConnectionEndpoints()`
22541
22666
  * to receive an ordered list of candidate base URLs it should race
22542
- * on connect — LAN IPv4 first (lowest latency when on same network),
22543
- * then public hostname (if a tunnel is up), then IPv6. The SDK can
22544
- * race them with short timeouts and stick with the winner for the
22545
- * session.
22667
+ * on connect — LAN IPv4 and stable LAN IPv6 first (lowest latency
22668
+ * when on the same network), then public hostname (if a tunnel is
22669
+ * up). The SDK can race them with short timeouts and stick with the
22670
+ * winner for the session.
22546
22671
  *
22547
22672
  * Why hub-only: agents are not directly addressable by the operator's
22548
22673
  * clients — they reverse-connect to the hub. Exposing their interfaces
@@ -22697,6 +22822,17 @@ var NotificationEndpointSchema = object({
22697
22822
  /** What the ranking currently resolves to (null when nothing is reachable). */
22698
22823
  resolved: string().nullable()
22699
22824
  });
22825
+ /**
22826
+ * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
22827
+ * AUTO (every LAN IPv4 + the public tunnel). `resolved` is what that choice
22828
+ * currently expands to, so the UI can show the effective set either way.
22829
+ */
22830
+ var ViewerEndpointsSchema = object({
22831
+ /** The operator's explicit race set, or empty for AUTO. */
22832
+ baseUrls: array(string()).readonly(),
22833
+ /** What the ranking currently resolves to (may be empty if nothing is up). */
22834
+ resolved: array(string()).readonly()
22835
+ });
22700
22836
  var AllowedAddressesSchema = object({
22701
22837
  /**
22702
22838
  * Allowlist of interface addresses operators have explicitly opted
@@ -22705,6 +22841,20 @@ var AllowedAddressesSchema = object({
22705
22841
  * Network Addresses admin page and persisted by the addon.
22706
22842
  */
22707
22843
  addresses: array(string()).readonly() });
22844
+ var TlsStatusSchema = object({
22845
+ mode: _enum([
22846
+ "generated",
22847
+ "uploaded",
22848
+ "disabled"
22849
+ ]),
22850
+ leafFingerprintSha256: string().nullable(),
22851
+ caFingerprintSha256: string().nullable(),
22852
+ validTo: string().nullable(),
22853
+ sans: array(string()),
22854
+ caCertPem: string().nullable(),
22855
+ reissueError: string().nullable(),
22856
+ restartRequired: boolean()
22857
+ });
22708
22858
  method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
22709
22859
  /**
22710
22860
  * LEGACY HINT — do not send from new code. Kept optional so clients
@@ -22714,17 +22864,31 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
22714
22864
  */
22715
22865
  port: number().int().min(1).max(65535).optional(),
22716
22866
  /** Include `http(s)://127.0.0.1:<port>` as the lowest-priority
22717
- * candidate. Default `true`. */
22867
+ * candidate. Default `false` — loopback is not a client route. */
22718
22868
  includeLoopback: boolean().optional(),
22719
- /** Skip IPv6 entries. Some legacy clients can't parse them.
22720
- * Default `false`. */
22869
+ /** Skip IPv6 entries. Default `false` the palette includes stable
22870
+ * LAN IPv6 (ICE/WebRTC uses dual-stack regardless). Pass `true` to
22871
+ * hide them. The viewer HTTP/WS race is `getViewerEndpoints`. */
22721
22872
  ipv4Only: boolean().optional(),
22722
22873
  /** Scheme to emit for LAN/loopback URLs. Default `'http'`.
22723
22874
  * Pass `'https'` when the caller is itself loaded over HTTPS
22724
22875
  * to avoid mixed-content blocks in the browser. The public
22725
22876
  * tunnel always emits `https://` regardless. */
22726
22877
  scheme: _enum(["http", "https"]).optional()
22727
- }), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), AllowedAddressesSchema), method(AllowedAddressesSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), AllowedAddressesSchema, { kind: "mutation" });
22878
+ }), GetConnectionEndpointsResultSchema), method(_void(), NotificationEndpointSchema), method(object({ baseUrl: string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }), method(_void(), ViewerEndpointsSchema), method(object({ baseUrls: array(string()).readonly() }), ViewerEndpointsSchema, { kind: "mutation" }), method(_void(), AllowedAddressesSchema), method(AllowedAddressesSchema, object({ success: literal(true) }), { kind: "mutation" }), method(_void(), AllowedAddressesSchema, { kind: "mutation" }), method(_void(), TlsStatusSchema), method(object({ reason: string().optional() }), TlsStatusSchema, {
22879
+ kind: "mutation",
22880
+ auth: "admin"
22881
+ }), method(object({
22882
+ certPem: string().min(1),
22883
+ keyPem: string().min(1),
22884
+ caPem: string().optional()
22885
+ }), TlsStatusSchema, {
22886
+ kind: "mutation",
22887
+ auth: "admin"
22888
+ }), method(_void(), object({ pem: string() })), method(_void(), TlsStatusSchema, {
22889
+ kind: "mutation",
22890
+ auth: "admin"
22891
+ });
22728
22892
  object({
22729
22893
  /** Lifecycle state of the lock. `jammed` means the motor reported
22730
22894
  * failure to reach the target — operator intervention required. */
@@ -28939,6 +29103,12 @@ Object.freeze({
28939
29103
  addonId: null,
28940
29104
  access: "create"
28941
29105
  },
29106
+ "localNetwork.downloadCa": {
29107
+ capName: "local-network",
29108
+ capScope: "system",
29109
+ addonId: null,
29110
+ access: "view"
29111
+ },
28942
29112
  "localNetwork.getAllowedAddresses": {
28943
29113
  capName: "local-network",
28944
29114
  capScope: "system",
@@ -28963,18 +29133,42 @@ Object.freeze({
28963
29133
  addonId: null,
28964
29134
  access: "view"
28965
29135
  },
29136
+ "localNetwork.getTlsStatus": {
29137
+ capName: "local-network",
29138
+ capScope: "system",
29139
+ addonId: null,
29140
+ access: "view"
29141
+ },
29142
+ "localNetwork.getViewerEndpoints": {
29143
+ capName: "local-network",
29144
+ capScope: "system",
29145
+ addonId: null,
29146
+ access: "view"
29147
+ },
28966
29148
  "localNetwork.list": {
28967
29149
  capName: "local-network",
28968
29150
  capScope: "system",
28969
29151
  addonId: null,
28970
29152
  access: "view"
28971
29153
  },
29154
+ "localNetwork.regenerateCertificate": {
29155
+ capName: "local-network",
29156
+ capScope: "system",
29157
+ addonId: null,
29158
+ access: "create"
29159
+ },
28972
29160
  "localNetwork.resetAllowlistToBestMatch": {
28973
29161
  capName: "local-network",
28974
29162
  capScope: "system",
28975
29163
  addonId: null,
28976
29164
  access: "delete"
28977
29165
  },
29166
+ "localNetwork.revertToGeneratedCertificate": {
29167
+ capName: "local-network",
29168
+ capScope: "system",
29169
+ addonId: null,
29170
+ access: "create"
29171
+ },
28978
29172
  "localNetwork.setAllowedAddresses": {
28979
29173
  capName: "local-network",
28980
29174
  capScope: "system",
@@ -28987,6 +29181,18 @@ Object.freeze({
28987
29181
  addonId: null,
28988
29182
  access: "create"
28989
29183
  },
29184
+ "localNetwork.setViewerEndpoints": {
29185
+ capName: "local-network",
29186
+ capScope: "system",
29187
+ addonId: null,
29188
+ access: "create"
29189
+ },
29190
+ "localNetwork.uploadCertificate": {
29191
+ capName: "local-network",
29192
+ capScope: "system",
29193
+ addonId: null,
29194
+ access: "create"
29195
+ },
28990
29196
  "lockControl.lock": {
28991
29197
  capName: "lock-control",
28992
29198
  capScope: "device",
@@ -31867,6 +32073,12 @@ Object.freeze({
31867
32073
  addonId: null,
31868
32074
  access: "create"
31869
32075
  },
32076
+ "terminalSession.updateInstance": {
32077
+ capName: "terminal-session",
32078
+ capScope: "system",
32079
+ addonId: null,
32080
+ access: "create"
32081
+ },
31870
32082
  "terminalSession.writeInput": {
31871
32083
  capName: "terminal-session",
31872
32084
  capScope: "system",
@@ -34354,6 +34566,35 @@ Object.freeze(Object.fromEntries([{
34354
34566
  }]
34355
34567
  }].map((s) => [s.stepId, s.defaultModelId])));
34356
34568
  string().min(1);
34569
+ var CLUSTER_STEP_SETTING_FIELDS = [{
34570
+ stepId: "face-embedding",
34571
+ key: "minLandmarkFaceSize",
34572
+ label: "Min face size for recognition (detection px)",
34573
+ description: "Refuse to embed a face smaller than this IN THE DETECTION FRAME. Applies to every node — the enrolled gallery is one index, and two admission floors would fill it from two policies. 0 disables the gate.",
34574
+ type: "slider",
34575
+ min: 0,
34576
+ max: 64,
34577
+ step: 2,
34578
+ default: 24
34579
+ }];
34580
+ function clusterStepSettingKey(stepId, fieldKey) {
34581
+ return `clusterStepSetting:${stepId}:${fieldKey}`;
34582
+ }
34583
+ var ClusterSettingNumberSchema = number().finite();
34584
+ function readClusterStepSettings(config) {
34585
+ const out = {};
34586
+ for (const field of CLUSTER_STEP_SETTING_FIELDS) {
34587
+ const parsed = ClusterSettingNumberSchema.safeParse(config[clusterStepSettingKey(field.stepId, field.key)]);
34588
+ const value = parsed.success ? parsed.data : field.default;
34589
+ const existing = out[field.stepId] ?? {};
34590
+ out[field.stepId] = {
34591
+ ...existing,
34592
+ [field.key]: value
34593
+ };
34594
+ }
34595
+ return out;
34596
+ }
34597
+ readClusterStepSettings({});
34357
34598
  object({
34358
34599
  /**
34359
34600
  * Fraction of the box's own size added on EACH side before cutting.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-onvif",
3
- "version": "1.2.24",
3
+ "version": "1.2.26",
4
4
  "description": "ONVIF camera device provider addon for CamStack",
5
5
  "keywords": [
6
6
  "camstack",