@camstack/addon-notifiers 1.2.30 → 1.2.31

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 +248 -16
  2. package/dist/addon.mjs +248 -16
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -8153,6 +8153,15 @@ var LabelDefinitionSchema = object({
8153
8153
  description: string().optional(),
8154
8154
  icon: string().optional()
8155
8155
  });
8156
+ var ClassMapDefinitionSchema = object({
8157
+ mapping: record(string(), _enum([
8158
+ "person",
8159
+ "vehicle",
8160
+ "animal",
8161
+ "package"
8162
+ ])),
8163
+ preserveOriginal: boolean()
8164
+ });
8156
8165
  var MODEL_FORMATS = [
8157
8166
  "onnx",
8158
8167
  "coreml",
@@ -8331,7 +8340,13 @@ var ModelCatalogEntrySchema = object({
8331
8340
  * `id` stays the source of truth for resolution/download/persistence; grouping
8332
8341
  * is a presentation overlay resolved back to an `id`.
8333
8342
  */
8334
- group: ModelVariantGroupSchema.optional()
8343
+ group: ModelVariantGroupSchema.optional(),
8344
+ /**
8345
+ * Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
8346
+ * applies (Frigate / COCO public catalog). Set on a custom model whose raw
8347
+ * labels already ARE the CamStack macros (Scrypted identity map).
8348
+ */
8349
+ classMap: ClassMapDefinitionSchema.optional()
8335
8350
  });
8336
8351
  var ConvertTargetSchema = discriminatedUnion("format", [object({
8337
8352
  format: literal("openvino"),
@@ -8360,7 +8375,8 @@ var ModelConvertMetadataSchema = object({
8360
8375
  "ocr",
8361
8376
  "segmentation"
8362
8377
  ]),
8363
- faceAlignment: boolean().optional()
8378
+ faceAlignment: boolean().optional(),
8379
+ classMap: ClassMapDefinitionSchema.optional()
8364
8380
  });
8365
8381
  var ConvertResultSchema = object({
8366
8382
  entry: ModelCatalogEntrySchema,
@@ -17406,6 +17422,33 @@ var NativeCropRefSchema = object({
17406
17422
  h: number()
17407
17423
  })
17408
17424
  });
17425
+ object({
17426
+ crop: object({
17427
+ left: number(),
17428
+ top: number(),
17429
+ width: number().positive(),
17430
+ height: number().positive()
17431
+ }).optional(),
17432
+ content: object({
17433
+ width: number().int().positive(),
17434
+ height: number().int().positive()
17435
+ }),
17436
+ fit: _enum(["stretch", "contain"]),
17437
+ format: _enum([
17438
+ "rgb",
17439
+ "gray",
17440
+ "jpeg"
17441
+ ])
17442
+ });
17443
+ var FrameRefSchema = object({
17444
+ registryId: string().min(1),
17445
+ id: string().min(1),
17446
+ width: number().int().positive(),
17447
+ height: number().int().positive(),
17448
+ format: _enum(["rgb", "gray"]),
17449
+ timestamp: number(),
17450
+ capturedAt: number().optional()
17451
+ });
17409
17452
  var ModelFormatSchema$1 = _enum([
17410
17453
  "onnx",
17411
17454
  "coreml",
@@ -17650,6 +17693,12 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
17650
17693
  steps: array(PipelineStepInputSchema).min(1),
17651
17694
  frame: FrameInputSchema.optional(),
17652
17695
  /**
17696
+ * Process-local lazy frame. Valid only when caller and provider resolve
17697
+ * in the same execution-group process; split/cross-node callers use
17698
+ * `frame`/`image` inline compatibility instead.
17699
+ */
17700
+ frameRef: FrameRefSchema.optional(),
17701
+ /**
17653
17702
  * CB5 shm passthrough — a `FrameHandle` naming the same ring slot
17654
17703
  * the decoded pixels live in. One more member of the one-of
17655
17704
  * frame/frameHandle/image/imageBase64/referenceImage group.
@@ -17905,7 +17954,10 @@ var NativeCropResultSchema = object({
17905
17954
  * Which source served this crop, so a quality-sensitive consumer (the native
17906
17955
  * `keyFrame`) can reject a degraded fallback:
17907
17956
  * - `native` — cut from the decode worker's retained NATIVE surface (the
17908
- * quality path).
17957
+ * quality path). A subject-tile serve is also native-resolution and stays
17958
+ * `native` here: the public enum cannot name `tile` without a breaking cap
17959
+ * change. Runner telemetry distinguishes lease vs tile via `source` on the
17960
+ * internal crop result (`nativeHits` vs `tileHits`).
17909
17961
  * - `ram-fullframe` — the native surface MISSED but the request was full-frame,
17910
17962
  * so the ≤640 RAM `RetainedFrameStore` served it (honest lower-res; legit for
17911
17963
  * the blank-frame guard / 640-snapshot resolve, NOT for the clean keyFrame).
@@ -18396,12 +18448,41 @@ var RunnerLocalLoadSchema = object({
18396
18448
  * legacy `OrchestratorMetricsSchema` shape so existing dashboards keep
18397
18449
  * working unchanged when they switch to reading from the runner cap.
18398
18450
  */
18451
+ var FrameLazyCountersSchema = object({
18452
+ framesDecoded: number(),
18453
+ framesAdmitted: number(),
18454
+ framesDroppedPixelFree: number(),
18455
+ viewsMaterialized: number(),
18456
+ viewsSkipped: number(),
18457
+ workerToRunnerBytes: number(),
18458
+ runnerToPoolRawBytes: number(),
18459
+ runnerToPoolJpegBytes: number(),
18460
+ onDemandFullFrameRequests: number(),
18461
+ onDemandCropRequests: number(),
18462
+ nativeHits: number(),
18463
+ nativeMisses: number(),
18464
+ tileHits: number(),
18465
+ tileMisses: number(),
18466
+ fallbackHits: number(),
18467
+ fallbackMisses: number(),
18468
+ retainedWritesAvoided: number(),
18469
+ residentRefs: number(),
18470
+ residentBytes: number(),
18471
+ releases: number(),
18472
+ evictions: number(),
18473
+ staleMisses: number()
18474
+ });
18475
+ var FrameLazyMetricsSchema = object({
18476
+ node: FrameLazyCountersSchema,
18477
+ cameras: array(FrameLazyCountersSchema.extend({ deviceId: number() }))
18478
+ });
18399
18479
  var RunnerLocalMetricsSchema = object({
18400
18480
  nodeId: string(),
18401
18481
  activeCameras: number(),
18402
18482
  throttledCameras: number(),
18403
18483
  avgInferenceTimeMs: number(),
18404
- queueDepth: number()
18484
+ queueDepth: number(),
18485
+ frameLazy: FrameLazyMetricsSchema.optional()
18405
18486
  });
18406
18487
  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({
18407
18488
  handle: FrameHandleSchema,
@@ -19701,6 +19782,9 @@ method(_void(), ProviderInfoSchema), method(object({ config: record(string(), un
19701
19782
  location: StorageLocationSchema,
19702
19783
  relativePath: string()
19703
19784
  }), _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" });
19785
+ /** Profile-exported FormBuilder schema. Shape is ConfigUISchema at the UI. */
19786
+ var ProfileSettingsSchemaBridge = unknown().nullable();
19787
+ var ProfileSettingsBagSchema = record(string(), unknown());
19704
19788
  /**
19705
19789
  * A live terminal session hosted by the provider addon. Output and input do
19706
19790
  * NOT flow through the capability — they use the addon data plane
@@ -19730,7 +19814,14 @@ var TerminalSessionInfoSchema = object({
19730
19814
  var TerminalProfileInfoSchema = object({
19731
19815
  profileId: string(),
19732
19816
  label: string(),
19733
- description: string().optional()
19817
+ description: string().optional(),
19818
+ /** Spawn defaults the instance form copies on create. */
19819
+ executable: string().optional(),
19820
+ args: array(string()).readonly().optional(),
19821
+ cwd: string().optional(),
19822
+ environment: array(string()).readonly().optional(),
19823
+ /** ConfigUISchema for instance knobs, or null when the profile has none. */
19824
+ settingsSchema: ProfileSettingsSchemaBridge.optional()
19734
19825
  });
19735
19826
  /**
19736
19827
  * A durable operator-created Terminal instance. Profiles are templates; only
@@ -19743,7 +19834,12 @@ var TerminalInstanceInfoSchema = object({
19743
19834
  profileId: string(),
19744
19835
  profileLabel: string(),
19745
19836
  name: string(),
19746
- enabled: boolean()
19837
+ enabled: boolean(),
19838
+ executable: string(),
19839
+ args: array(string()).readonly(),
19840
+ cwd: string(),
19841
+ environment: array(string()).readonly(),
19842
+ profileSettings: ProfileSettingsBagSchema
19747
19843
  });
19748
19844
  var TerminalLegacyCameraSchema = object({
19749
19845
  stableId: string(),
@@ -19773,7 +19869,23 @@ var TerminalOutputBatchSchema = object({
19773
19869
  method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }), method(_void(), array(TerminalInstanceInfoSchema).readonly(), { auth: "admin" }), method(object({
19774
19870
  targetNodeId: string().min(1),
19775
19871
  profileId: string().min(1),
19776
- name: string().trim().min(1).max(160).optional()
19872
+ name: string().trim().min(1).max(160).optional(),
19873
+ executable: string().max(1024).optional(),
19874
+ args: array(string().max(2048)).max(64).optional(),
19875
+ cwd: string().max(1024).optional(),
19876
+ environment: array(string().max(4096)).max(64).optional(),
19877
+ profileSettings: ProfileSettingsBagSchema.optional()
19878
+ }), TerminalInstanceInfoSchema, {
19879
+ kind: "mutation",
19880
+ auth: "admin"
19881
+ }), method(object({
19882
+ instanceId: string().min(1),
19883
+ name: string().trim().min(1).max(160).optional(),
19884
+ executable: string().max(1024).optional(),
19885
+ args: array(string().max(2048)).max(64).optional(),
19886
+ cwd: string().max(1024).optional(),
19887
+ environment: array(string().max(4096)).max(64).optional(),
19888
+ profileSettings: ProfileSettingsBagSchema.optional()
19777
19889
  }), TerminalInstanceInfoSchema, {
19778
19890
  kind: "mutation",
19779
19891
  auth: "admin"
@@ -19795,7 +19907,11 @@ method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }),
19795
19907
  }), method(_void(), array(TerminalSessionInfoSchema).readonly(), { auth: "admin" }), method(object({
19796
19908
  profileId: string(),
19797
19909
  cols: number().int().positive(),
19798
- rows: number().int().positive()
19910
+ rows: number().int().positive(),
19911
+ executable: string().max(1024).optional(),
19912
+ args: array(string().max(2048)).max(64).optional(),
19913
+ cwd: string().max(1024).optional(),
19914
+ environment: array(string().max(4096)).max(64).optional()
19799
19915
  }), TerminalSessionInfoSchema, {
19800
19916
  kind: "mutation",
19801
19917
  auth: "admin"
@@ -22577,10 +22693,10 @@ DeviceType.LawnMower, method(object({ deviceId: number().int().nonnegative() }),
22577
22693
  *
22578
22694
  * • The SDK (mobile / web client) consumes `getConnectionEndpoints()`
22579
22695
  * to receive an ordered list of candidate base URLs it should race
22580
- * on connect — LAN IPv4 first (lowest latency when on same network),
22581
- * then public hostname (if a tunnel is up), then IPv6. The SDK can
22582
- * race them with short timeouts and stick with the winner for the
22583
- * session.
22696
+ * on connect — LAN IPv4 and stable LAN IPv6 first (lowest latency
22697
+ * when on the same network), then public hostname (if a tunnel is
22698
+ * up). The SDK can race them with short timeouts and stick with the
22699
+ * winner for the session.
22584
22700
  *
22585
22701
  * Why hub-only: agents are not directly addressable by the operator's
22586
22702
  * clients — they reverse-connect to the hub. Exposing their interfaces
@@ -22735,6 +22851,17 @@ var NotificationEndpointSchema = object({
22735
22851
  /** What the ranking currently resolves to (null when nothing is reachable). */
22736
22852
  resolved: string().nullable()
22737
22853
  });
22854
+ /**
22855
+ * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
22856
+ * AUTO (every LAN IPv4 + the public tunnel). `resolved` is what that choice
22857
+ * currently expands to, so the UI can show the effective set either way.
22858
+ */
22859
+ var ViewerEndpointsSchema = object({
22860
+ /** The operator's explicit race set, or empty for AUTO. */
22861
+ baseUrls: array(string()).readonly(),
22862
+ /** What the ranking currently resolves to (may be empty if nothing is up). */
22863
+ resolved: array(string()).readonly()
22864
+ });
22738
22865
  var AllowedAddressesSchema = object({
22739
22866
  /**
22740
22867
  * Allowlist of interface addresses operators have explicitly opted
@@ -22743,6 +22870,20 @@ var AllowedAddressesSchema = object({
22743
22870
  * Network Addresses admin page and persisted by the addon.
22744
22871
  */
22745
22872
  addresses: array(string()).readonly() });
22873
+ var TlsStatusSchema = object({
22874
+ mode: _enum([
22875
+ "generated",
22876
+ "uploaded",
22877
+ "disabled"
22878
+ ]),
22879
+ leafFingerprintSha256: string().nullable(),
22880
+ caFingerprintSha256: string().nullable(),
22881
+ validTo: string().nullable(),
22882
+ sans: array(string()),
22883
+ caCertPem: string().nullable(),
22884
+ reissueError: string().nullable(),
22885
+ restartRequired: boolean()
22886
+ });
22746
22887
  method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
22747
22888
  /**
22748
22889
  * LEGACY HINT — do not send from new code. Kept optional so clients
@@ -22752,17 +22893,31 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
22752
22893
  */
22753
22894
  port: number().int().min(1).max(65535).optional(),
22754
22895
  /** Include `http(s)://127.0.0.1:<port>` as the lowest-priority
22755
- * candidate. Default `true`. */
22896
+ * candidate. Default `false` — loopback is not a client route. */
22756
22897
  includeLoopback: boolean().optional(),
22757
- /** Skip IPv6 entries. Some legacy clients can't parse them.
22758
- * Default `false`. */
22898
+ /** Skip IPv6 entries. Default `false` the palette includes stable
22899
+ * LAN IPv6 (ICE/WebRTC uses dual-stack regardless). Pass `true` to
22900
+ * hide them. The viewer HTTP/WS race is `getViewerEndpoints`. */
22759
22901
  ipv4Only: boolean().optional(),
22760
22902
  /** Scheme to emit for LAN/loopback URLs. Default `'http'`.
22761
22903
  * Pass `'https'` when the caller is itself loaded over HTTPS
22762
22904
  * to avoid mixed-content blocks in the browser. The public
22763
22905
  * tunnel always emits `https://` regardless. */
22764
22906
  scheme: _enum(["http", "https"]).optional()
22765
- }), 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" });
22907
+ }), 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, {
22908
+ kind: "mutation",
22909
+ auth: "admin"
22910
+ }), method(object({
22911
+ certPem: string().min(1),
22912
+ keyPem: string().min(1),
22913
+ caPem: string().optional()
22914
+ }), TlsStatusSchema, {
22915
+ kind: "mutation",
22916
+ auth: "admin"
22917
+ }), method(_void(), object({ pem: string() })), method(_void(), TlsStatusSchema, {
22918
+ kind: "mutation",
22919
+ auth: "admin"
22920
+ });
22766
22921
  object({
22767
22922
  /** Lifecycle state of the lock. `jammed` means the motor reported
22768
22923
  * failure to reach the target — operator intervention required. */
@@ -28525,6 +28680,12 @@ Object.freeze({
28525
28680
  addonId: null,
28526
28681
  access: "create"
28527
28682
  },
28683
+ "localNetwork.downloadCa": {
28684
+ capName: "local-network",
28685
+ capScope: "system",
28686
+ addonId: null,
28687
+ access: "view"
28688
+ },
28528
28689
  "localNetwork.getAllowedAddresses": {
28529
28690
  capName: "local-network",
28530
28691
  capScope: "system",
@@ -28549,18 +28710,42 @@ Object.freeze({
28549
28710
  addonId: null,
28550
28711
  access: "view"
28551
28712
  },
28713
+ "localNetwork.getTlsStatus": {
28714
+ capName: "local-network",
28715
+ capScope: "system",
28716
+ addonId: null,
28717
+ access: "view"
28718
+ },
28719
+ "localNetwork.getViewerEndpoints": {
28720
+ capName: "local-network",
28721
+ capScope: "system",
28722
+ addonId: null,
28723
+ access: "view"
28724
+ },
28552
28725
  "localNetwork.list": {
28553
28726
  capName: "local-network",
28554
28727
  capScope: "system",
28555
28728
  addonId: null,
28556
28729
  access: "view"
28557
28730
  },
28731
+ "localNetwork.regenerateCertificate": {
28732
+ capName: "local-network",
28733
+ capScope: "system",
28734
+ addonId: null,
28735
+ access: "create"
28736
+ },
28558
28737
  "localNetwork.resetAllowlistToBestMatch": {
28559
28738
  capName: "local-network",
28560
28739
  capScope: "system",
28561
28740
  addonId: null,
28562
28741
  access: "delete"
28563
28742
  },
28743
+ "localNetwork.revertToGeneratedCertificate": {
28744
+ capName: "local-network",
28745
+ capScope: "system",
28746
+ addonId: null,
28747
+ access: "create"
28748
+ },
28564
28749
  "localNetwork.setAllowedAddresses": {
28565
28750
  capName: "local-network",
28566
28751
  capScope: "system",
@@ -28573,6 +28758,18 @@ Object.freeze({
28573
28758
  addonId: null,
28574
28759
  access: "create"
28575
28760
  },
28761
+ "localNetwork.setViewerEndpoints": {
28762
+ capName: "local-network",
28763
+ capScope: "system",
28764
+ addonId: null,
28765
+ access: "create"
28766
+ },
28767
+ "localNetwork.uploadCertificate": {
28768
+ capName: "local-network",
28769
+ capScope: "system",
28770
+ addonId: null,
28771
+ access: "create"
28772
+ },
28576
28773
  "lockControl.lock": {
28577
28774
  capName: "lock-control",
28578
28775
  capScope: "device",
@@ -31453,6 +31650,12 @@ Object.freeze({
31453
31650
  addonId: null,
31454
31651
  access: "create"
31455
31652
  },
31653
+ "terminalSession.updateInstance": {
31654
+ capName: "terminal-session",
31655
+ capScope: "system",
31656
+ addonId: null,
31657
+ access: "create"
31658
+ },
31456
31659
  "terminalSession.writeInput": {
31457
31660
  capName: "terminal-session",
31458
31661
  capScope: "system",
@@ -34147,6 +34350,35 @@ Object.freeze(Object.fromEntries([{
34147
34350
  }]
34148
34351
  }].map((s) => [s.stepId, s.defaultModelId])));
34149
34352
  string().min(1);
34353
+ var CLUSTER_STEP_SETTING_FIELDS = [{
34354
+ stepId: "face-embedding",
34355
+ key: "minLandmarkFaceSize",
34356
+ label: "Min face size for recognition (detection px)",
34357
+ 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.",
34358
+ type: "slider",
34359
+ min: 0,
34360
+ max: 64,
34361
+ step: 2,
34362
+ default: 24
34363
+ }];
34364
+ function clusterStepSettingKey(stepId, fieldKey) {
34365
+ return `clusterStepSetting:${stepId}:${fieldKey}`;
34366
+ }
34367
+ var ClusterSettingNumberSchema = number().finite();
34368
+ function readClusterStepSettings(config) {
34369
+ const out = {};
34370
+ for (const field of CLUSTER_STEP_SETTING_FIELDS) {
34371
+ const parsed = ClusterSettingNumberSchema.safeParse(config[clusterStepSettingKey(field.stepId, field.key)]);
34372
+ const value = parsed.success ? parsed.data : field.default;
34373
+ const existing = out[field.stepId] ?? {};
34374
+ out[field.stepId] = {
34375
+ ...existing,
34376
+ [field.key]: value
34377
+ };
34378
+ }
34379
+ return out;
34380
+ }
34381
+ readClusterStepSettings({});
34150
34382
  object({
34151
34383
  /**
34152
34384
  * Fraction of the box's own size added on EACH side before cutting.
package/dist/addon.mjs CHANGED
@@ -8126,6 +8126,15 @@ var LabelDefinitionSchema = object({
8126
8126
  description: string().optional(),
8127
8127
  icon: string().optional()
8128
8128
  });
8129
+ var ClassMapDefinitionSchema = object({
8130
+ mapping: record(string(), _enum([
8131
+ "person",
8132
+ "vehicle",
8133
+ "animal",
8134
+ "package"
8135
+ ])),
8136
+ preserveOriginal: boolean()
8137
+ });
8129
8138
  var MODEL_FORMATS = [
8130
8139
  "onnx",
8131
8140
  "coreml",
@@ -8304,7 +8313,13 @@ var ModelCatalogEntrySchema = object({
8304
8313
  * `id` stays the source of truth for resolution/download/persistence; grouping
8305
8314
  * is a presentation overlay resolved back to an `id`.
8306
8315
  */
8307
- group: ModelVariantGroupSchema.optional()
8316
+ group: ModelVariantGroupSchema.optional(),
8317
+ /**
8318
+ * Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
8319
+ * applies (Frigate / COCO public catalog). Set on a custom model whose raw
8320
+ * labels already ARE the CamStack macros (Scrypted identity map).
8321
+ */
8322
+ classMap: ClassMapDefinitionSchema.optional()
8308
8323
  });
8309
8324
  var ConvertTargetSchema = discriminatedUnion("format", [object({
8310
8325
  format: literal("openvino"),
@@ -8333,7 +8348,8 @@ var ModelConvertMetadataSchema = object({
8333
8348
  "ocr",
8334
8349
  "segmentation"
8335
8350
  ]),
8336
- faceAlignment: boolean().optional()
8351
+ faceAlignment: boolean().optional(),
8352
+ classMap: ClassMapDefinitionSchema.optional()
8337
8353
  });
8338
8354
  var ConvertResultSchema = object({
8339
8355
  entry: ModelCatalogEntrySchema,
@@ -17379,6 +17395,33 @@ var NativeCropRefSchema = object({
17379
17395
  h: number()
17380
17396
  })
17381
17397
  });
17398
+ object({
17399
+ crop: object({
17400
+ left: number(),
17401
+ top: number(),
17402
+ width: number().positive(),
17403
+ height: number().positive()
17404
+ }).optional(),
17405
+ content: object({
17406
+ width: number().int().positive(),
17407
+ height: number().int().positive()
17408
+ }),
17409
+ fit: _enum(["stretch", "contain"]),
17410
+ format: _enum([
17411
+ "rgb",
17412
+ "gray",
17413
+ "jpeg"
17414
+ ])
17415
+ });
17416
+ var FrameRefSchema = object({
17417
+ registryId: string().min(1),
17418
+ id: string().min(1),
17419
+ width: number().int().positive(),
17420
+ height: number().int().positive(),
17421
+ format: _enum(["rgb", "gray"]),
17422
+ timestamp: number(),
17423
+ capturedAt: number().optional()
17424
+ });
17382
17425
  var ModelFormatSchema$1 = _enum([
17383
17426
  "onnx",
17384
17427
  "coreml",
@@ -17623,6 +17666,12 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
17623
17666
  steps: array(PipelineStepInputSchema).min(1),
17624
17667
  frame: FrameInputSchema.optional(),
17625
17668
  /**
17669
+ * Process-local lazy frame. Valid only when caller and provider resolve
17670
+ * in the same execution-group process; split/cross-node callers use
17671
+ * `frame`/`image` inline compatibility instead.
17672
+ */
17673
+ frameRef: FrameRefSchema.optional(),
17674
+ /**
17626
17675
  * CB5 shm passthrough — a `FrameHandle` naming the same ring slot
17627
17676
  * the decoded pixels live in. One more member of the one-of
17628
17677
  * frame/frameHandle/image/imageBase64/referenceImage group.
@@ -17878,7 +17927,10 @@ var NativeCropResultSchema = object({
17878
17927
  * Which source served this crop, so a quality-sensitive consumer (the native
17879
17928
  * `keyFrame`) can reject a degraded fallback:
17880
17929
  * - `native` — cut from the decode worker's retained NATIVE surface (the
17881
- * quality path).
17930
+ * quality path). A subject-tile serve is also native-resolution and stays
17931
+ * `native` here: the public enum cannot name `tile` without a breaking cap
17932
+ * change. Runner telemetry distinguishes lease vs tile via `source` on the
17933
+ * internal crop result (`nativeHits` vs `tileHits`).
17882
17934
  * - `ram-fullframe` — the native surface MISSED but the request was full-frame,
17883
17935
  * so the ≤640 RAM `RetainedFrameStore` served it (honest lower-res; legit for
17884
17936
  * the blank-frame guard / 640-snapshot resolve, NOT for the clean keyFrame).
@@ -18369,12 +18421,41 @@ var RunnerLocalLoadSchema = object({
18369
18421
  * legacy `OrchestratorMetricsSchema` shape so existing dashboards keep
18370
18422
  * working unchanged when they switch to reading from the runner cap.
18371
18423
  */
18424
+ var FrameLazyCountersSchema = object({
18425
+ framesDecoded: number(),
18426
+ framesAdmitted: number(),
18427
+ framesDroppedPixelFree: number(),
18428
+ viewsMaterialized: number(),
18429
+ viewsSkipped: number(),
18430
+ workerToRunnerBytes: number(),
18431
+ runnerToPoolRawBytes: number(),
18432
+ runnerToPoolJpegBytes: number(),
18433
+ onDemandFullFrameRequests: number(),
18434
+ onDemandCropRequests: number(),
18435
+ nativeHits: number(),
18436
+ nativeMisses: number(),
18437
+ tileHits: number(),
18438
+ tileMisses: number(),
18439
+ fallbackHits: number(),
18440
+ fallbackMisses: number(),
18441
+ retainedWritesAvoided: number(),
18442
+ residentRefs: number(),
18443
+ residentBytes: number(),
18444
+ releases: number(),
18445
+ evictions: number(),
18446
+ staleMisses: number()
18447
+ });
18448
+ var FrameLazyMetricsSchema = object({
18449
+ node: FrameLazyCountersSchema,
18450
+ cameras: array(FrameLazyCountersSchema.extend({ deviceId: number() }))
18451
+ });
18372
18452
  var RunnerLocalMetricsSchema = object({
18373
18453
  nodeId: string(),
18374
18454
  activeCameras: number(),
18375
18455
  throttledCameras: number(),
18376
18456
  avgInferenceTimeMs: number(),
18377
- queueDepth: number()
18457
+ queueDepth: number(),
18458
+ frameLazy: FrameLazyMetricsSchema.optional()
18378
18459
  });
18379
18460
  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({
18380
18461
  handle: FrameHandleSchema,
@@ -19674,6 +19755,9 @@ method(_void(), ProviderInfoSchema), method(object({ config: record(string(), un
19674
19755
  location: StorageLocationSchema,
19675
19756
  relativePath: string()
19676
19757
  }), _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" });
19758
+ /** Profile-exported FormBuilder schema. Shape is ConfigUISchema at the UI. */
19759
+ var ProfileSettingsSchemaBridge = unknown().nullable();
19760
+ var ProfileSettingsBagSchema = record(string(), unknown());
19677
19761
  /**
19678
19762
  * A live terminal session hosted by the provider addon. Output and input do
19679
19763
  * NOT flow through the capability — they use the addon data plane
@@ -19703,7 +19787,14 @@ var TerminalSessionInfoSchema = object({
19703
19787
  var TerminalProfileInfoSchema = object({
19704
19788
  profileId: string(),
19705
19789
  label: string(),
19706
- description: string().optional()
19790
+ description: string().optional(),
19791
+ /** Spawn defaults the instance form copies on create. */
19792
+ executable: string().optional(),
19793
+ args: array(string()).readonly().optional(),
19794
+ cwd: string().optional(),
19795
+ environment: array(string()).readonly().optional(),
19796
+ /** ConfigUISchema for instance knobs, or null when the profile has none. */
19797
+ settingsSchema: ProfileSettingsSchemaBridge.optional()
19707
19798
  });
19708
19799
  /**
19709
19800
  * A durable operator-created Terminal instance. Profiles are templates; only
@@ -19716,7 +19807,12 @@ var TerminalInstanceInfoSchema = object({
19716
19807
  profileId: string(),
19717
19808
  profileLabel: string(),
19718
19809
  name: string(),
19719
- enabled: boolean()
19810
+ enabled: boolean(),
19811
+ executable: string(),
19812
+ args: array(string()).readonly(),
19813
+ cwd: string(),
19814
+ environment: array(string()).readonly(),
19815
+ profileSettings: ProfileSettingsBagSchema
19720
19816
  });
19721
19817
  var TerminalLegacyCameraSchema = object({
19722
19818
  stableId: string(),
@@ -19746,7 +19842,23 @@ var TerminalOutputBatchSchema = object({
19746
19842
  method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }), method(_void(), array(TerminalInstanceInfoSchema).readonly(), { auth: "admin" }), method(object({
19747
19843
  targetNodeId: string().min(1),
19748
19844
  profileId: string().min(1),
19749
- name: string().trim().min(1).max(160).optional()
19845
+ name: string().trim().min(1).max(160).optional(),
19846
+ executable: string().max(1024).optional(),
19847
+ args: array(string().max(2048)).max(64).optional(),
19848
+ cwd: string().max(1024).optional(),
19849
+ environment: array(string().max(4096)).max(64).optional(),
19850
+ profileSettings: ProfileSettingsBagSchema.optional()
19851
+ }), TerminalInstanceInfoSchema, {
19852
+ kind: "mutation",
19853
+ auth: "admin"
19854
+ }), method(object({
19855
+ instanceId: string().min(1),
19856
+ name: string().trim().min(1).max(160).optional(),
19857
+ executable: string().max(1024).optional(),
19858
+ args: array(string().max(2048)).max(64).optional(),
19859
+ cwd: string().max(1024).optional(),
19860
+ environment: array(string().max(4096)).max(64).optional(),
19861
+ profileSettings: ProfileSettingsBagSchema.optional()
19750
19862
  }), TerminalInstanceInfoSchema, {
19751
19863
  kind: "mutation",
19752
19864
  auth: "admin"
@@ -19768,7 +19880,11 @@ method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }),
19768
19880
  }), method(_void(), array(TerminalSessionInfoSchema).readonly(), { auth: "admin" }), method(object({
19769
19881
  profileId: string(),
19770
19882
  cols: number().int().positive(),
19771
- rows: number().int().positive()
19883
+ rows: number().int().positive(),
19884
+ executable: string().max(1024).optional(),
19885
+ args: array(string().max(2048)).max(64).optional(),
19886
+ cwd: string().max(1024).optional(),
19887
+ environment: array(string().max(4096)).max(64).optional()
19772
19888
  }), TerminalSessionInfoSchema, {
19773
19889
  kind: "mutation",
19774
19890
  auth: "admin"
@@ -22550,10 +22666,10 @@ DeviceType.LawnMower, method(object({ deviceId: number().int().nonnegative() }),
22550
22666
  *
22551
22667
  * • The SDK (mobile / web client) consumes `getConnectionEndpoints()`
22552
22668
  * to receive an ordered list of candidate base URLs it should race
22553
- * on connect — LAN IPv4 first (lowest latency when on same network),
22554
- * then public hostname (if a tunnel is up), then IPv6. The SDK can
22555
- * race them with short timeouts and stick with the winner for the
22556
- * session.
22669
+ * on connect — LAN IPv4 and stable LAN IPv6 first (lowest latency
22670
+ * when on the same network), then public hostname (if a tunnel is
22671
+ * up). The SDK can race them with short timeouts and stick with the
22672
+ * winner for the session.
22557
22673
  *
22558
22674
  * Why hub-only: agents are not directly addressable by the operator's
22559
22675
  * clients — they reverse-connect to the hub. Exposing their interfaces
@@ -22708,6 +22824,17 @@ var NotificationEndpointSchema = object({
22708
22824
  /** What the ranking currently resolves to (null when nothing is reachable). */
22709
22825
  resolved: string().nullable()
22710
22826
  });
22827
+ /**
22828
+ * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
22829
+ * AUTO (every LAN IPv4 + the public tunnel). `resolved` is what that choice
22830
+ * currently expands to, so the UI can show the effective set either way.
22831
+ */
22832
+ var ViewerEndpointsSchema = object({
22833
+ /** The operator's explicit race set, or empty for AUTO. */
22834
+ baseUrls: array(string()).readonly(),
22835
+ /** What the ranking currently resolves to (may be empty if nothing is up). */
22836
+ resolved: array(string()).readonly()
22837
+ });
22711
22838
  var AllowedAddressesSchema = object({
22712
22839
  /**
22713
22840
  * Allowlist of interface addresses operators have explicitly opted
@@ -22716,6 +22843,20 @@ var AllowedAddressesSchema = object({
22716
22843
  * Network Addresses admin page and persisted by the addon.
22717
22844
  */
22718
22845
  addresses: array(string()).readonly() });
22846
+ var TlsStatusSchema = object({
22847
+ mode: _enum([
22848
+ "generated",
22849
+ "uploaded",
22850
+ "disabled"
22851
+ ]),
22852
+ leafFingerprintSha256: string().nullable(),
22853
+ caFingerprintSha256: string().nullable(),
22854
+ validTo: string().nullable(),
22855
+ sans: array(string()),
22856
+ caCertPem: string().nullable(),
22857
+ reissueError: string().nullable(),
22858
+ restartRequired: boolean()
22859
+ });
22719
22860
  method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
22720
22861
  /**
22721
22862
  * LEGACY HINT — do not send from new code. Kept optional so clients
@@ -22725,17 +22866,31 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
22725
22866
  */
22726
22867
  port: number().int().min(1).max(65535).optional(),
22727
22868
  /** Include `http(s)://127.0.0.1:<port>` as the lowest-priority
22728
- * candidate. Default `true`. */
22869
+ * candidate. Default `false` — loopback is not a client route. */
22729
22870
  includeLoopback: boolean().optional(),
22730
- /** Skip IPv6 entries. Some legacy clients can't parse them.
22731
- * Default `false`. */
22871
+ /** Skip IPv6 entries. Default `false` the palette includes stable
22872
+ * LAN IPv6 (ICE/WebRTC uses dual-stack regardless). Pass `true` to
22873
+ * hide them. The viewer HTTP/WS race is `getViewerEndpoints`. */
22732
22874
  ipv4Only: boolean().optional(),
22733
22875
  /** Scheme to emit for LAN/loopback URLs. Default `'http'`.
22734
22876
  * Pass `'https'` when the caller is itself loaded over HTTPS
22735
22877
  * to avoid mixed-content blocks in the browser. The public
22736
22878
  * tunnel always emits `https://` regardless. */
22737
22879
  scheme: _enum(["http", "https"]).optional()
22738
- }), 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" });
22880
+ }), 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, {
22881
+ kind: "mutation",
22882
+ auth: "admin"
22883
+ }), method(object({
22884
+ certPem: string().min(1),
22885
+ keyPem: string().min(1),
22886
+ caPem: string().optional()
22887
+ }), TlsStatusSchema, {
22888
+ kind: "mutation",
22889
+ auth: "admin"
22890
+ }), method(_void(), object({ pem: string() })), method(_void(), TlsStatusSchema, {
22891
+ kind: "mutation",
22892
+ auth: "admin"
22893
+ });
22739
22894
  object({
22740
22895
  /** Lifecycle state of the lock. `jammed` means the motor reported
22741
22896
  * failure to reach the target — operator intervention required. */
@@ -28498,6 +28653,12 @@ Object.freeze({
28498
28653
  addonId: null,
28499
28654
  access: "create"
28500
28655
  },
28656
+ "localNetwork.downloadCa": {
28657
+ capName: "local-network",
28658
+ capScope: "system",
28659
+ addonId: null,
28660
+ access: "view"
28661
+ },
28501
28662
  "localNetwork.getAllowedAddresses": {
28502
28663
  capName: "local-network",
28503
28664
  capScope: "system",
@@ -28522,18 +28683,42 @@ Object.freeze({
28522
28683
  addonId: null,
28523
28684
  access: "view"
28524
28685
  },
28686
+ "localNetwork.getTlsStatus": {
28687
+ capName: "local-network",
28688
+ capScope: "system",
28689
+ addonId: null,
28690
+ access: "view"
28691
+ },
28692
+ "localNetwork.getViewerEndpoints": {
28693
+ capName: "local-network",
28694
+ capScope: "system",
28695
+ addonId: null,
28696
+ access: "view"
28697
+ },
28525
28698
  "localNetwork.list": {
28526
28699
  capName: "local-network",
28527
28700
  capScope: "system",
28528
28701
  addonId: null,
28529
28702
  access: "view"
28530
28703
  },
28704
+ "localNetwork.regenerateCertificate": {
28705
+ capName: "local-network",
28706
+ capScope: "system",
28707
+ addonId: null,
28708
+ access: "create"
28709
+ },
28531
28710
  "localNetwork.resetAllowlistToBestMatch": {
28532
28711
  capName: "local-network",
28533
28712
  capScope: "system",
28534
28713
  addonId: null,
28535
28714
  access: "delete"
28536
28715
  },
28716
+ "localNetwork.revertToGeneratedCertificate": {
28717
+ capName: "local-network",
28718
+ capScope: "system",
28719
+ addonId: null,
28720
+ access: "create"
28721
+ },
28537
28722
  "localNetwork.setAllowedAddresses": {
28538
28723
  capName: "local-network",
28539
28724
  capScope: "system",
@@ -28546,6 +28731,18 @@ Object.freeze({
28546
28731
  addonId: null,
28547
28732
  access: "create"
28548
28733
  },
28734
+ "localNetwork.setViewerEndpoints": {
28735
+ capName: "local-network",
28736
+ capScope: "system",
28737
+ addonId: null,
28738
+ access: "create"
28739
+ },
28740
+ "localNetwork.uploadCertificate": {
28741
+ capName: "local-network",
28742
+ capScope: "system",
28743
+ addonId: null,
28744
+ access: "create"
28745
+ },
28549
28746
  "lockControl.lock": {
28550
28747
  capName: "lock-control",
28551
28748
  capScope: "device",
@@ -31426,6 +31623,12 @@ Object.freeze({
31426
31623
  addonId: null,
31427
31624
  access: "create"
31428
31625
  },
31626
+ "terminalSession.updateInstance": {
31627
+ capName: "terminal-session",
31628
+ capScope: "system",
31629
+ addonId: null,
31630
+ access: "create"
31631
+ },
31429
31632
  "terminalSession.writeInput": {
31430
31633
  capName: "terminal-session",
31431
31634
  capScope: "system",
@@ -34120,6 +34323,35 @@ Object.freeze(Object.fromEntries([{
34120
34323
  }]
34121
34324
  }].map((s) => [s.stepId, s.defaultModelId])));
34122
34325
  string().min(1);
34326
+ var CLUSTER_STEP_SETTING_FIELDS = [{
34327
+ stepId: "face-embedding",
34328
+ key: "minLandmarkFaceSize",
34329
+ label: "Min face size for recognition (detection px)",
34330
+ 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.",
34331
+ type: "slider",
34332
+ min: 0,
34333
+ max: 64,
34334
+ step: 2,
34335
+ default: 24
34336
+ }];
34337
+ function clusterStepSettingKey(stepId, fieldKey) {
34338
+ return `clusterStepSetting:${stepId}:${fieldKey}`;
34339
+ }
34340
+ var ClusterSettingNumberSchema = number().finite();
34341
+ function readClusterStepSettings(config) {
34342
+ const out = {};
34343
+ for (const field of CLUSTER_STEP_SETTING_FIELDS) {
34344
+ const parsed = ClusterSettingNumberSchema.safeParse(config[clusterStepSettingKey(field.stepId, field.key)]);
34345
+ const value = parsed.success ? parsed.data : field.default;
34346
+ const existing = out[field.stepId] ?? {};
34347
+ out[field.stepId] = {
34348
+ ...existing,
34349
+ [field.key]: value
34350
+ };
34351
+ }
34352
+ return out;
34353
+ }
34354
+ readClusterStepSettings({});
34123
34355
  object({
34124
34356
  /**
34125
34357
  * 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-notifiers",
3
- "version": "1.2.30",
3
+ "version": "1.2.31",
4
4
  "description": "System notifiers addon for CamStack — a `notification-output` collection provider hosting per-kind notifier adapters (ntfy, pushover, gotify, telegram, discord, webhook, zentik).",
5
5
  "keywords": [
6
6
  "camstack",