@camstack/addon-provider-velux 0.2.26 → 0.2.27

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
@@ -8020,6 +8020,15 @@ var LabelDefinitionSchema = object({
8020
8020
  description: string().optional(),
8021
8021
  icon: string().optional()
8022
8022
  });
8023
+ var ClassMapDefinitionSchema = object({
8024
+ mapping: record(string(), _enum([
8025
+ "person",
8026
+ "vehicle",
8027
+ "animal",
8028
+ "package"
8029
+ ])),
8030
+ preserveOriginal: boolean()
8031
+ });
8023
8032
  var MODEL_FORMATS = [
8024
8033
  "onnx",
8025
8034
  "coreml",
@@ -8198,7 +8207,13 @@ var ModelCatalogEntrySchema = object({
8198
8207
  * `id` stays the source of truth for resolution/download/persistence; grouping
8199
8208
  * is a presentation overlay resolved back to an `id`.
8200
8209
  */
8201
- 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()
8202
8217
  });
8203
8218
  var ConvertTargetSchema = discriminatedUnion("format", [object({
8204
8219
  format: literal("openvino"),
@@ -8227,7 +8242,8 @@ var ModelConvertMetadataSchema = object({
8227
8242
  "ocr",
8228
8243
  "segmentation"
8229
8244
  ]),
8230
- faceAlignment: boolean().optional()
8245
+ faceAlignment: boolean().optional(),
8246
+ classMap: ClassMapDefinitionSchema.optional()
8231
8247
  });
8232
8248
  var ConvertResultSchema = object({
8233
8249
  entry: ModelCatalogEntrySchema,
@@ -17520,6 +17536,33 @@ var NativeCropRefSchema = object({
17520
17536
  h: number()
17521
17537
  })
17522
17538
  });
17539
+ object({
17540
+ crop: object({
17541
+ left: number(),
17542
+ top: number(),
17543
+ width: number().positive(),
17544
+ height: number().positive()
17545
+ }).optional(),
17546
+ content: object({
17547
+ width: number().int().positive(),
17548
+ height: number().int().positive()
17549
+ }),
17550
+ fit: _enum(["stretch", "contain"]),
17551
+ format: _enum([
17552
+ "rgb",
17553
+ "gray",
17554
+ "jpeg"
17555
+ ])
17556
+ });
17557
+ var FrameRefSchema = object({
17558
+ registryId: string().min(1),
17559
+ id: string().min(1),
17560
+ width: number().int().positive(),
17561
+ height: number().int().positive(),
17562
+ format: _enum(["rgb", "gray"]),
17563
+ timestamp: number(),
17564
+ capturedAt: number().optional()
17565
+ });
17523
17566
  var ModelFormatSchema$1 = _enum([
17524
17567
  "onnx",
17525
17568
  "coreml",
@@ -17764,6 +17807,12 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
17764
17807
  steps: array(PipelineStepInputSchema).min(1),
17765
17808
  frame: FrameInputSchema.optional(),
17766
17809
  /**
17810
+ * Process-local lazy frame. Valid only when caller and provider resolve
17811
+ * in the same execution-group process; split/cross-node callers use
17812
+ * `frame`/`image` inline compatibility instead.
17813
+ */
17814
+ frameRef: FrameRefSchema.optional(),
17815
+ /**
17767
17816
  * CB5 shm passthrough — a `FrameHandle` naming the same ring slot
17768
17817
  * the decoded pixels live in. One more member of the one-of
17769
17818
  * frame/frameHandle/image/imageBase64/referenceImage group.
@@ -18059,7 +18108,10 @@ var NativeCropResultSchema = object({
18059
18108
  * Which source served this crop, so a quality-sensitive consumer (the native
18060
18109
  * `keyFrame`) can reject a degraded fallback:
18061
18110
  * - `native` — cut from the decode worker's retained NATIVE surface (the
18062
- * quality path).
18111
+ * quality path). A subject-tile serve is also native-resolution and stays
18112
+ * `native` here: the public enum cannot name `tile` without a breaking cap
18113
+ * change. Runner telemetry distinguishes lease vs tile via `source` on the
18114
+ * internal crop result (`nativeHits` vs `tileHits`).
18063
18115
  * - `ram-fullframe` — the native surface MISSED but the request was full-frame,
18064
18116
  * so the ≤640 RAM `RetainedFrameStore` served it (honest lower-res; legit for
18065
18117
  * the blank-frame guard / 640-snapshot resolve, NOT for the clean keyFrame).
@@ -18550,12 +18602,41 @@ var RunnerLocalLoadSchema = object({
18550
18602
  * legacy `OrchestratorMetricsSchema` shape so existing dashboards keep
18551
18603
  * working unchanged when they switch to reading from the runner cap.
18552
18604
  */
18605
+ var FrameLazyCountersSchema = object({
18606
+ framesDecoded: number(),
18607
+ framesAdmitted: number(),
18608
+ framesDroppedPixelFree: number(),
18609
+ viewsMaterialized: number(),
18610
+ viewsSkipped: number(),
18611
+ workerToRunnerBytes: number(),
18612
+ runnerToPoolRawBytes: number(),
18613
+ runnerToPoolJpegBytes: number(),
18614
+ onDemandFullFrameRequests: number(),
18615
+ onDemandCropRequests: number(),
18616
+ nativeHits: number(),
18617
+ nativeMisses: number(),
18618
+ tileHits: number(),
18619
+ tileMisses: number(),
18620
+ fallbackHits: number(),
18621
+ fallbackMisses: number(),
18622
+ retainedWritesAvoided: number(),
18623
+ residentRefs: number(),
18624
+ residentBytes: number(),
18625
+ releases: number(),
18626
+ evictions: number(),
18627
+ staleMisses: number()
18628
+ });
18629
+ var FrameLazyMetricsSchema = object({
18630
+ node: FrameLazyCountersSchema,
18631
+ cameras: array(FrameLazyCountersSchema.extend({ deviceId: number() }))
18632
+ });
18553
18633
  var RunnerLocalMetricsSchema = object({
18554
18634
  nodeId: string(),
18555
18635
  activeCameras: number(),
18556
18636
  throttledCameras: number(),
18557
18637
  avgInferenceTimeMs: number(),
18558
- queueDepth: number()
18638
+ queueDepth: number(),
18639
+ frameLazy: FrameLazyMetricsSchema.optional()
18559
18640
  });
18560
18641
  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({
18561
18642
  handle: FrameHandleSchema,
@@ -19855,6 +19936,9 @@ method(_void(), ProviderInfoSchema), method(object({ config: record(string(), un
19855
19936
  location: StorageLocationSchema,
19856
19937
  relativePath: string()
19857
19938
  }), _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" });
19939
+ /** Profile-exported FormBuilder schema. Shape is ConfigUISchema at the UI. */
19940
+ var ProfileSettingsSchemaBridge = unknown().nullable();
19941
+ var ProfileSettingsBagSchema = record(string(), unknown());
19858
19942
  /**
19859
19943
  * A live terminal session hosted by the provider addon. Output and input do
19860
19944
  * NOT flow through the capability — they use the addon data plane
@@ -19884,7 +19968,14 @@ var TerminalSessionInfoSchema = object({
19884
19968
  var TerminalProfileInfoSchema = object({
19885
19969
  profileId: string(),
19886
19970
  label: string(),
19887
- description: string().optional()
19971
+ description: string().optional(),
19972
+ /** Spawn defaults the instance form copies on create. */
19973
+ executable: string().optional(),
19974
+ args: array(string()).readonly().optional(),
19975
+ cwd: string().optional(),
19976
+ environment: array(string()).readonly().optional(),
19977
+ /** ConfigUISchema for instance knobs, or null when the profile has none. */
19978
+ settingsSchema: ProfileSettingsSchemaBridge.optional()
19888
19979
  });
19889
19980
  /**
19890
19981
  * A durable operator-created Terminal instance. Profiles are templates; only
@@ -19897,7 +19988,12 @@ var TerminalInstanceInfoSchema = object({
19897
19988
  profileId: string(),
19898
19989
  profileLabel: string(),
19899
19990
  name: string(),
19900
- enabled: boolean()
19991
+ enabled: boolean(),
19992
+ executable: string(),
19993
+ args: array(string()).readonly(),
19994
+ cwd: string(),
19995
+ environment: array(string()).readonly(),
19996
+ profileSettings: ProfileSettingsBagSchema
19901
19997
  });
19902
19998
  var TerminalLegacyCameraSchema = object({
19903
19999
  stableId: string(),
@@ -19927,7 +20023,23 @@ var TerminalOutputBatchSchema = object({
19927
20023
  method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }), method(_void(), array(TerminalInstanceInfoSchema).readonly(), { auth: "admin" }), method(object({
19928
20024
  targetNodeId: string().min(1),
19929
20025
  profileId: string().min(1),
19930
- name: string().trim().min(1).max(160).optional()
20026
+ name: string().trim().min(1).max(160).optional(),
20027
+ executable: string().max(1024).optional(),
20028
+ args: array(string().max(2048)).max(64).optional(),
20029
+ cwd: string().max(1024).optional(),
20030
+ environment: array(string().max(4096)).max(64).optional(),
20031
+ profileSettings: ProfileSettingsBagSchema.optional()
20032
+ }), TerminalInstanceInfoSchema, {
20033
+ kind: "mutation",
20034
+ auth: "admin"
20035
+ }), method(object({
20036
+ instanceId: string().min(1),
20037
+ name: string().trim().min(1).max(160).optional(),
20038
+ executable: string().max(1024).optional(),
20039
+ args: array(string().max(2048)).max(64).optional(),
20040
+ cwd: string().max(1024).optional(),
20041
+ environment: array(string().max(4096)).max(64).optional(),
20042
+ profileSettings: ProfileSettingsBagSchema.optional()
19931
20043
  }), TerminalInstanceInfoSchema, {
19932
20044
  kind: "mutation",
19933
20045
  auth: "admin"
@@ -19949,7 +20061,11 @@ method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }),
19949
20061
  }), method(_void(), array(TerminalSessionInfoSchema).readonly(), { auth: "admin" }), method(object({
19950
20062
  profileId: string(),
19951
20063
  cols: number().int().positive(),
19952
- rows: number().int().positive()
20064
+ rows: number().int().positive(),
20065
+ executable: string().max(1024).optional(),
20066
+ args: array(string().max(2048)).max(64).optional(),
20067
+ cwd: string().max(1024).optional(),
20068
+ environment: array(string().max(4096)).max(64).optional()
19953
20069
  }), TerminalSessionInfoSchema, {
19954
20070
  kind: "mutation",
19955
20071
  auth: "admin"
@@ -23824,10 +23940,10 @@ var lawnMowerControlCapability = {
23824
23940
  *
23825
23941
  * • The SDK (mobile / web client) consumes `getConnectionEndpoints()`
23826
23942
  * to receive an ordered list of candidate base URLs it should race
23827
- * on connect — LAN IPv4 first (lowest latency when on same network),
23828
- * then public hostname (if a tunnel is up), then IPv6. The SDK can
23829
- * race them with short timeouts and stick with the winner for the
23830
- * session.
23943
+ * on connect — LAN IPv4 and stable LAN IPv6 first (lowest latency
23944
+ * when on the same network), then public hostname (if a tunnel is
23945
+ * up). The SDK can race them with short timeouts and stick with the
23946
+ * winner for the session.
23831
23947
  *
23832
23948
  * Why hub-only: agents are not directly addressable by the operator's
23833
23949
  * clients — they reverse-connect to the hub. Exposing their interfaces
@@ -23982,6 +24098,17 @@ var NotificationEndpointSchema = object({
23982
24098
  /** What the ranking currently resolves to (null when nothing is reachable). */
23983
24099
  resolved: string().nullable()
23984
24100
  });
24101
+ /**
24102
+ * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
24103
+ * AUTO (every LAN IPv4 + the public tunnel). `resolved` is what that choice
24104
+ * currently expands to, so the UI can show the effective set either way.
24105
+ */
24106
+ var ViewerEndpointsSchema = object({
24107
+ /** The operator's explicit race set, or empty for AUTO. */
24108
+ baseUrls: array(string()).readonly(),
24109
+ /** What the ranking currently resolves to (may be empty if nothing is up). */
24110
+ resolved: array(string()).readonly()
24111
+ });
23985
24112
  var AllowedAddressesSchema = object({
23986
24113
  /**
23987
24114
  * Allowlist of interface addresses operators have explicitly opted
@@ -23990,6 +24117,20 @@ var AllowedAddressesSchema = object({
23990
24117
  * Network Addresses admin page and persisted by the addon.
23991
24118
  */
23992
24119
  addresses: array(string()).readonly() });
24120
+ var TlsStatusSchema = object({
24121
+ mode: _enum([
24122
+ "generated",
24123
+ "uploaded",
24124
+ "disabled"
24125
+ ]),
24126
+ leafFingerprintSha256: string().nullable(),
24127
+ caFingerprintSha256: string().nullable(),
24128
+ validTo: string().nullable(),
24129
+ sans: array(string()),
24130
+ caCertPem: string().nullable(),
24131
+ reissueError: string().nullable(),
24132
+ restartRequired: boolean()
24133
+ });
23993
24134
  method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
23994
24135
  /**
23995
24136
  * LEGACY HINT — do not send from new code. Kept optional so clients
@@ -23999,17 +24140,31 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
23999
24140
  */
24000
24141
  port: number().int().min(1).max(65535).optional(),
24001
24142
  /** Include `http(s)://127.0.0.1:<port>` as the lowest-priority
24002
- * candidate. Default `true`. */
24143
+ * candidate. Default `false` — loopback is not a client route. */
24003
24144
  includeLoopback: boolean().optional(),
24004
- /** Skip IPv6 entries. Some legacy clients can't parse them.
24005
- * Default `false`. */
24145
+ /** Skip IPv6 entries. Default `false` the palette includes stable
24146
+ * LAN IPv6 (ICE/WebRTC uses dual-stack regardless). Pass `true` to
24147
+ * hide them. The viewer HTTP/WS race is `getViewerEndpoints`. */
24006
24148
  ipv4Only: boolean().optional(),
24007
24149
  /** Scheme to emit for LAN/loopback URLs. Default `'http'`.
24008
24150
  * Pass `'https'` when the caller is itself loaded over HTTPS
24009
24151
  * to avoid mixed-content blocks in the browser. The public
24010
24152
  * tunnel always emits `https://` regardless. */
24011
24153
  scheme: _enum(["http", "https"]).optional()
24012
- }), 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" });
24154
+ }), 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, {
24155
+ kind: "mutation",
24156
+ auth: "admin"
24157
+ }), method(object({
24158
+ certPem: string().min(1),
24159
+ keyPem: string().min(1),
24160
+ caPem: string().optional()
24161
+ }), TlsStatusSchema, {
24162
+ kind: "mutation",
24163
+ auth: "admin"
24164
+ }), method(_void(), object({ pem: string() })), method(_void(), TlsStatusSchema, {
24165
+ kind: "mutation",
24166
+ auth: "admin"
24167
+ });
24013
24168
  var LockControlStatusSchema = object({
24014
24169
  /** Lifecycle state of the lock. `jammed` means the motor reported
24015
24170
  * failure to reach the target — operator intervention required. */
@@ -32036,6 +32191,12 @@ Object.freeze({
32036
32191
  addonId: null,
32037
32192
  access: "create"
32038
32193
  },
32194
+ "localNetwork.downloadCa": {
32195
+ capName: "local-network",
32196
+ capScope: "system",
32197
+ addonId: null,
32198
+ access: "view"
32199
+ },
32039
32200
  "localNetwork.getAllowedAddresses": {
32040
32201
  capName: "local-network",
32041
32202
  capScope: "system",
@@ -32060,18 +32221,42 @@ Object.freeze({
32060
32221
  addonId: null,
32061
32222
  access: "view"
32062
32223
  },
32224
+ "localNetwork.getTlsStatus": {
32225
+ capName: "local-network",
32226
+ capScope: "system",
32227
+ addonId: null,
32228
+ access: "view"
32229
+ },
32230
+ "localNetwork.getViewerEndpoints": {
32231
+ capName: "local-network",
32232
+ capScope: "system",
32233
+ addonId: null,
32234
+ access: "view"
32235
+ },
32063
32236
  "localNetwork.list": {
32064
32237
  capName: "local-network",
32065
32238
  capScope: "system",
32066
32239
  addonId: null,
32067
32240
  access: "view"
32068
32241
  },
32242
+ "localNetwork.regenerateCertificate": {
32243
+ capName: "local-network",
32244
+ capScope: "system",
32245
+ addonId: null,
32246
+ access: "create"
32247
+ },
32069
32248
  "localNetwork.resetAllowlistToBestMatch": {
32070
32249
  capName: "local-network",
32071
32250
  capScope: "system",
32072
32251
  addonId: null,
32073
32252
  access: "delete"
32074
32253
  },
32254
+ "localNetwork.revertToGeneratedCertificate": {
32255
+ capName: "local-network",
32256
+ capScope: "system",
32257
+ addonId: null,
32258
+ access: "create"
32259
+ },
32075
32260
  "localNetwork.setAllowedAddresses": {
32076
32261
  capName: "local-network",
32077
32262
  capScope: "system",
@@ -32084,6 +32269,18 @@ Object.freeze({
32084
32269
  addonId: null,
32085
32270
  access: "create"
32086
32271
  },
32272
+ "localNetwork.setViewerEndpoints": {
32273
+ capName: "local-network",
32274
+ capScope: "system",
32275
+ addonId: null,
32276
+ access: "create"
32277
+ },
32278
+ "localNetwork.uploadCertificate": {
32279
+ capName: "local-network",
32280
+ capScope: "system",
32281
+ addonId: null,
32282
+ access: "create"
32283
+ },
32087
32284
  "lockControl.lock": {
32088
32285
  capName: "lock-control",
32089
32286
  capScope: "device",
@@ -34964,6 +35161,12 @@ Object.freeze({
34964
35161
  addonId: null,
34965
35162
  access: "create"
34966
35163
  },
35164
+ "terminalSession.updateInstance": {
35165
+ capName: "terminal-session",
35166
+ capScope: "system",
35167
+ addonId: null,
35168
+ access: "create"
35169
+ },
34967
35170
  "terminalSession.writeInput": {
34968
35171
  capName: "terminal-session",
34969
35172
  capScope: "system",
@@ -37451,6 +37654,35 @@ Object.freeze(Object.fromEntries([{
37451
37654
  }]
37452
37655
  }].map((s) => [s.stepId, s.defaultModelId])));
37453
37656
  string().min(1);
37657
+ var CLUSTER_STEP_SETTING_FIELDS = [{
37658
+ stepId: "face-embedding",
37659
+ key: "minLandmarkFaceSize",
37660
+ label: "Min face size for recognition (detection px)",
37661
+ 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.",
37662
+ type: "slider",
37663
+ min: 0,
37664
+ max: 64,
37665
+ step: 2,
37666
+ default: 24
37667
+ }];
37668
+ function clusterStepSettingKey(stepId, fieldKey) {
37669
+ return `clusterStepSetting:${stepId}:${fieldKey}`;
37670
+ }
37671
+ var ClusterSettingNumberSchema = number().finite();
37672
+ function readClusterStepSettings(config) {
37673
+ const out = {};
37674
+ for (const field of CLUSTER_STEP_SETTING_FIELDS) {
37675
+ const parsed = ClusterSettingNumberSchema.safeParse(config[clusterStepSettingKey(field.stepId, field.key)]);
37676
+ const value = parsed.success ? parsed.data : field.default;
37677
+ const existing = out[field.stepId] ?? {};
37678
+ out[field.stepId] = {
37679
+ ...existing,
37680
+ [field.key]: value
37681
+ };
37682
+ }
37683
+ return out;
37684
+ }
37685
+ readClusterStepSettings({});
37454
37686
  object({
37455
37687
  /**
37456
37688
  * Fraction of the box's own size added on EACH side before cutting.
package/dist/addon.mjs CHANGED
@@ -8019,6 +8019,15 @@ var LabelDefinitionSchema = object({
8019
8019
  description: string().optional(),
8020
8020
  icon: string().optional()
8021
8021
  });
8022
+ var ClassMapDefinitionSchema = object({
8023
+ mapping: record(string(), _enum([
8024
+ "person",
8025
+ "vehicle",
8026
+ "animal",
8027
+ "package"
8028
+ ])),
8029
+ preserveOriginal: boolean()
8030
+ });
8022
8031
  var MODEL_FORMATS = [
8023
8032
  "onnx",
8024
8033
  "coreml",
@@ -8197,7 +8206,13 @@ var ModelCatalogEntrySchema = object({
8197
8206
  * `id` stays the source of truth for resolution/download/persistence; grouping
8198
8207
  * is a presentation overlay resolved back to an `id`.
8199
8208
  */
8200
- 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()
8201
8216
  });
8202
8217
  var ConvertTargetSchema = discriminatedUnion("format", [object({
8203
8218
  format: literal("openvino"),
@@ -8226,7 +8241,8 @@ var ModelConvertMetadataSchema = object({
8226
8241
  "ocr",
8227
8242
  "segmentation"
8228
8243
  ]),
8229
- faceAlignment: boolean().optional()
8244
+ faceAlignment: boolean().optional(),
8245
+ classMap: ClassMapDefinitionSchema.optional()
8230
8246
  });
8231
8247
  var ConvertResultSchema = object({
8232
8248
  entry: ModelCatalogEntrySchema,
@@ -17519,6 +17535,33 @@ var NativeCropRefSchema = object({
17519
17535
  h: number()
17520
17536
  })
17521
17537
  });
17538
+ object({
17539
+ crop: object({
17540
+ left: number(),
17541
+ top: number(),
17542
+ width: number().positive(),
17543
+ height: number().positive()
17544
+ }).optional(),
17545
+ content: object({
17546
+ width: number().int().positive(),
17547
+ height: number().int().positive()
17548
+ }),
17549
+ fit: _enum(["stretch", "contain"]),
17550
+ format: _enum([
17551
+ "rgb",
17552
+ "gray",
17553
+ "jpeg"
17554
+ ])
17555
+ });
17556
+ var FrameRefSchema = object({
17557
+ registryId: string().min(1),
17558
+ id: string().min(1),
17559
+ width: number().int().positive(),
17560
+ height: number().int().positive(),
17561
+ format: _enum(["rgb", "gray"]),
17562
+ timestamp: number(),
17563
+ capturedAt: number().optional()
17564
+ });
17522
17565
  var ModelFormatSchema$1 = _enum([
17523
17566
  "onnx",
17524
17567
  "coreml",
@@ -17763,6 +17806,12 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
17763
17806
  steps: array(PipelineStepInputSchema).min(1),
17764
17807
  frame: FrameInputSchema.optional(),
17765
17808
  /**
17809
+ * Process-local lazy frame. Valid only when caller and provider resolve
17810
+ * in the same execution-group process; split/cross-node callers use
17811
+ * `frame`/`image` inline compatibility instead.
17812
+ */
17813
+ frameRef: FrameRefSchema.optional(),
17814
+ /**
17766
17815
  * CB5 shm passthrough — a `FrameHandle` naming the same ring slot
17767
17816
  * the decoded pixels live in. One more member of the one-of
17768
17817
  * frame/frameHandle/image/imageBase64/referenceImage group.
@@ -18058,7 +18107,10 @@ var NativeCropResultSchema = object({
18058
18107
  * Which source served this crop, so a quality-sensitive consumer (the native
18059
18108
  * `keyFrame`) can reject a degraded fallback:
18060
18109
  * - `native` — cut from the decode worker's retained NATIVE surface (the
18061
- * quality path).
18110
+ * quality path). A subject-tile serve is also native-resolution and stays
18111
+ * `native` here: the public enum cannot name `tile` without a breaking cap
18112
+ * change. Runner telemetry distinguishes lease vs tile via `source` on the
18113
+ * internal crop result (`nativeHits` vs `tileHits`).
18062
18114
  * - `ram-fullframe` — the native surface MISSED but the request was full-frame,
18063
18115
  * so the ≤640 RAM `RetainedFrameStore` served it (honest lower-res; legit for
18064
18116
  * the blank-frame guard / 640-snapshot resolve, NOT for the clean keyFrame).
@@ -18549,12 +18601,41 @@ var RunnerLocalLoadSchema = object({
18549
18601
  * legacy `OrchestratorMetricsSchema` shape so existing dashboards keep
18550
18602
  * working unchanged when they switch to reading from the runner cap.
18551
18603
  */
18604
+ var FrameLazyCountersSchema = object({
18605
+ framesDecoded: number(),
18606
+ framesAdmitted: number(),
18607
+ framesDroppedPixelFree: number(),
18608
+ viewsMaterialized: number(),
18609
+ viewsSkipped: number(),
18610
+ workerToRunnerBytes: number(),
18611
+ runnerToPoolRawBytes: number(),
18612
+ runnerToPoolJpegBytes: number(),
18613
+ onDemandFullFrameRequests: number(),
18614
+ onDemandCropRequests: number(),
18615
+ nativeHits: number(),
18616
+ nativeMisses: number(),
18617
+ tileHits: number(),
18618
+ tileMisses: number(),
18619
+ fallbackHits: number(),
18620
+ fallbackMisses: number(),
18621
+ retainedWritesAvoided: number(),
18622
+ residentRefs: number(),
18623
+ residentBytes: number(),
18624
+ releases: number(),
18625
+ evictions: number(),
18626
+ staleMisses: number()
18627
+ });
18628
+ var FrameLazyMetricsSchema = object({
18629
+ node: FrameLazyCountersSchema,
18630
+ cameras: array(FrameLazyCountersSchema.extend({ deviceId: number() }))
18631
+ });
18552
18632
  var RunnerLocalMetricsSchema = object({
18553
18633
  nodeId: string(),
18554
18634
  activeCameras: number(),
18555
18635
  throttledCameras: number(),
18556
18636
  avgInferenceTimeMs: number(),
18557
- queueDepth: number()
18637
+ queueDepth: number(),
18638
+ frameLazy: FrameLazyMetricsSchema.optional()
18558
18639
  });
18559
18640
  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({
18560
18641
  handle: FrameHandleSchema,
@@ -19854,6 +19935,9 @@ method(_void(), ProviderInfoSchema), method(object({ config: record(string(), un
19854
19935
  location: StorageLocationSchema,
19855
19936
  relativePath: string()
19856
19937
  }), _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" });
19938
+ /** Profile-exported FormBuilder schema. Shape is ConfigUISchema at the UI. */
19939
+ var ProfileSettingsSchemaBridge = unknown().nullable();
19940
+ var ProfileSettingsBagSchema = record(string(), unknown());
19857
19941
  /**
19858
19942
  * A live terminal session hosted by the provider addon. Output and input do
19859
19943
  * NOT flow through the capability — they use the addon data plane
@@ -19883,7 +19967,14 @@ var TerminalSessionInfoSchema = object({
19883
19967
  var TerminalProfileInfoSchema = object({
19884
19968
  profileId: string(),
19885
19969
  label: string(),
19886
- description: string().optional()
19970
+ description: string().optional(),
19971
+ /** Spawn defaults the instance form copies on create. */
19972
+ executable: string().optional(),
19973
+ args: array(string()).readonly().optional(),
19974
+ cwd: string().optional(),
19975
+ environment: array(string()).readonly().optional(),
19976
+ /** ConfigUISchema for instance knobs, or null when the profile has none. */
19977
+ settingsSchema: ProfileSettingsSchemaBridge.optional()
19887
19978
  });
19888
19979
  /**
19889
19980
  * A durable operator-created Terminal instance. Profiles are templates; only
@@ -19896,7 +19987,12 @@ var TerminalInstanceInfoSchema = object({
19896
19987
  profileId: string(),
19897
19988
  profileLabel: string(),
19898
19989
  name: string(),
19899
- enabled: boolean()
19990
+ enabled: boolean(),
19991
+ executable: string(),
19992
+ args: array(string()).readonly(),
19993
+ cwd: string(),
19994
+ environment: array(string()).readonly(),
19995
+ profileSettings: ProfileSettingsBagSchema
19900
19996
  });
19901
19997
  var TerminalLegacyCameraSchema = object({
19902
19998
  stableId: string(),
@@ -19926,7 +20022,23 @@ var TerminalOutputBatchSchema = object({
19926
20022
  method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }), method(_void(), array(TerminalInstanceInfoSchema).readonly(), { auth: "admin" }), method(object({
19927
20023
  targetNodeId: string().min(1),
19928
20024
  profileId: string().min(1),
19929
- name: string().trim().min(1).max(160).optional()
20025
+ name: string().trim().min(1).max(160).optional(),
20026
+ executable: string().max(1024).optional(),
20027
+ args: array(string().max(2048)).max(64).optional(),
20028
+ cwd: string().max(1024).optional(),
20029
+ environment: array(string().max(4096)).max(64).optional(),
20030
+ profileSettings: ProfileSettingsBagSchema.optional()
20031
+ }), TerminalInstanceInfoSchema, {
20032
+ kind: "mutation",
20033
+ auth: "admin"
20034
+ }), method(object({
20035
+ instanceId: string().min(1),
20036
+ name: string().trim().min(1).max(160).optional(),
20037
+ executable: string().max(1024).optional(),
20038
+ args: array(string().max(2048)).max(64).optional(),
20039
+ cwd: string().max(1024).optional(),
20040
+ environment: array(string().max(4096)).max(64).optional(),
20041
+ profileSettings: ProfileSettingsBagSchema.optional()
19930
20042
  }), TerminalInstanceInfoSchema, {
19931
20043
  kind: "mutation",
19932
20044
  auth: "admin"
@@ -19948,7 +20060,11 @@ method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }),
19948
20060
  }), method(_void(), array(TerminalSessionInfoSchema).readonly(), { auth: "admin" }), method(object({
19949
20061
  profileId: string(),
19950
20062
  cols: number().int().positive(),
19951
- rows: number().int().positive()
20063
+ rows: number().int().positive(),
20064
+ executable: string().max(1024).optional(),
20065
+ args: array(string().max(2048)).max(64).optional(),
20066
+ cwd: string().max(1024).optional(),
20067
+ environment: array(string().max(4096)).max(64).optional()
19952
20068
  }), TerminalSessionInfoSchema, {
19953
20069
  kind: "mutation",
19954
20070
  auth: "admin"
@@ -23823,10 +23939,10 @@ var lawnMowerControlCapability = {
23823
23939
  *
23824
23940
  * • The SDK (mobile / web client) consumes `getConnectionEndpoints()`
23825
23941
  * to receive an ordered list of candidate base URLs it should race
23826
- * on connect — LAN IPv4 first (lowest latency when on same network),
23827
- * then public hostname (if a tunnel is up), then IPv6. The SDK can
23828
- * race them with short timeouts and stick with the winner for the
23829
- * session.
23942
+ * on connect — LAN IPv4 and stable LAN IPv6 first (lowest latency
23943
+ * when on the same network), then public hostname (if a tunnel is
23944
+ * up). The SDK can race them with short timeouts and stick with the
23945
+ * winner for the session.
23830
23946
  *
23831
23947
  * Why hub-only: agents are not directly addressable by the operator's
23832
23948
  * clients — they reverse-connect to the hub. Exposing their interfaces
@@ -23981,6 +24097,17 @@ var NotificationEndpointSchema = object({
23981
24097
  /** What the ranking currently resolves to (null when nothing is reachable). */
23982
24098
  resolved: string().nullable()
23983
24099
  });
24100
+ /**
24101
+ * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
24102
+ * AUTO (every LAN IPv4 + the public tunnel). `resolved` is what that choice
24103
+ * currently expands to, so the UI can show the effective set either way.
24104
+ */
24105
+ var ViewerEndpointsSchema = object({
24106
+ /** The operator's explicit race set, or empty for AUTO. */
24107
+ baseUrls: array(string()).readonly(),
24108
+ /** What the ranking currently resolves to (may be empty if nothing is up). */
24109
+ resolved: array(string()).readonly()
24110
+ });
23984
24111
  var AllowedAddressesSchema = object({
23985
24112
  /**
23986
24113
  * Allowlist of interface addresses operators have explicitly opted
@@ -23989,6 +24116,20 @@ var AllowedAddressesSchema = object({
23989
24116
  * Network Addresses admin page and persisted by the addon.
23990
24117
  */
23991
24118
  addresses: array(string()).readonly() });
24119
+ var TlsStatusSchema = object({
24120
+ mode: _enum([
24121
+ "generated",
24122
+ "uploaded",
24123
+ "disabled"
24124
+ ]),
24125
+ leafFingerprintSha256: string().nullable(),
24126
+ caFingerprintSha256: string().nullable(),
24127
+ validTo: string().nullable(),
24128
+ sans: array(string()),
24129
+ caCertPem: string().nullable(),
24130
+ reissueError: string().nullable(),
24131
+ restartRequired: boolean()
24132
+ });
23992
24133
  method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
23993
24134
  /**
23994
24135
  * LEGACY HINT — do not send from new code. Kept optional so clients
@@ -23998,17 +24139,31 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
23998
24139
  */
23999
24140
  port: number().int().min(1).max(65535).optional(),
24000
24141
  /** Include `http(s)://127.0.0.1:<port>` as the lowest-priority
24001
- * candidate. Default `true`. */
24142
+ * candidate. Default `false` — loopback is not a client route. */
24002
24143
  includeLoopback: boolean().optional(),
24003
- /** Skip IPv6 entries. Some legacy clients can't parse them.
24004
- * Default `false`. */
24144
+ /** Skip IPv6 entries. Default `false` the palette includes stable
24145
+ * LAN IPv6 (ICE/WebRTC uses dual-stack regardless). Pass `true` to
24146
+ * hide them. The viewer HTTP/WS race is `getViewerEndpoints`. */
24005
24147
  ipv4Only: boolean().optional(),
24006
24148
  /** Scheme to emit for LAN/loopback URLs. Default `'http'`.
24007
24149
  * Pass `'https'` when the caller is itself loaded over HTTPS
24008
24150
  * to avoid mixed-content blocks in the browser. The public
24009
24151
  * tunnel always emits `https://` regardless. */
24010
24152
  scheme: _enum(["http", "https"]).optional()
24011
- }), 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" });
24153
+ }), 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, {
24154
+ kind: "mutation",
24155
+ auth: "admin"
24156
+ }), method(object({
24157
+ certPem: string().min(1),
24158
+ keyPem: string().min(1),
24159
+ caPem: string().optional()
24160
+ }), TlsStatusSchema, {
24161
+ kind: "mutation",
24162
+ auth: "admin"
24163
+ }), method(_void(), object({ pem: string() })), method(_void(), TlsStatusSchema, {
24164
+ kind: "mutation",
24165
+ auth: "admin"
24166
+ });
24012
24167
  var LockControlStatusSchema = object({
24013
24168
  /** Lifecycle state of the lock. `jammed` means the motor reported
24014
24169
  * failure to reach the target — operator intervention required. */
@@ -32035,6 +32190,12 @@ Object.freeze({
32035
32190
  addonId: null,
32036
32191
  access: "create"
32037
32192
  },
32193
+ "localNetwork.downloadCa": {
32194
+ capName: "local-network",
32195
+ capScope: "system",
32196
+ addonId: null,
32197
+ access: "view"
32198
+ },
32038
32199
  "localNetwork.getAllowedAddresses": {
32039
32200
  capName: "local-network",
32040
32201
  capScope: "system",
@@ -32059,18 +32220,42 @@ Object.freeze({
32059
32220
  addonId: null,
32060
32221
  access: "view"
32061
32222
  },
32223
+ "localNetwork.getTlsStatus": {
32224
+ capName: "local-network",
32225
+ capScope: "system",
32226
+ addonId: null,
32227
+ access: "view"
32228
+ },
32229
+ "localNetwork.getViewerEndpoints": {
32230
+ capName: "local-network",
32231
+ capScope: "system",
32232
+ addonId: null,
32233
+ access: "view"
32234
+ },
32062
32235
  "localNetwork.list": {
32063
32236
  capName: "local-network",
32064
32237
  capScope: "system",
32065
32238
  addonId: null,
32066
32239
  access: "view"
32067
32240
  },
32241
+ "localNetwork.regenerateCertificate": {
32242
+ capName: "local-network",
32243
+ capScope: "system",
32244
+ addonId: null,
32245
+ access: "create"
32246
+ },
32068
32247
  "localNetwork.resetAllowlistToBestMatch": {
32069
32248
  capName: "local-network",
32070
32249
  capScope: "system",
32071
32250
  addonId: null,
32072
32251
  access: "delete"
32073
32252
  },
32253
+ "localNetwork.revertToGeneratedCertificate": {
32254
+ capName: "local-network",
32255
+ capScope: "system",
32256
+ addonId: null,
32257
+ access: "create"
32258
+ },
32074
32259
  "localNetwork.setAllowedAddresses": {
32075
32260
  capName: "local-network",
32076
32261
  capScope: "system",
@@ -32083,6 +32268,18 @@ Object.freeze({
32083
32268
  addonId: null,
32084
32269
  access: "create"
32085
32270
  },
32271
+ "localNetwork.setViewerEndpoints": {
32272
+ capName: "local-network",
32273
+ capScope: "system",
32274
+ addonId: null,
32275
+ access: "create"
32276
+ },
32277
+ "localNetwork.uploadCertificate": {
32278
+ capName: "local-network",
32279
+ capScope: "system",
32280
+ addonId: null,
32281
+ access: "create"
32282
+ },
32086
32283
  "lockControl.lock": {
32087
32284
  capName: "lock-control",
32088
32285
  capScope: "device",
@@ -34963,6 +35160,12 @@ Object.freeze({
34963
35160
  addonId: null,
34964
35161
  access: "create"
34965
35162
  },
35163
+ "terminalSession.updateInstance": {
35164
+ capName: "terminal-session",
35165
+ capScope: "system",
35166
+ addonId: null,
35167
+ access: "create"
35168
+ },
34966
35169
  "terminalSession.writeInput": {
34967
35170
  capName: "terminal-session",
34968
35171
  capScope: "system",
@@ -37450,6 +37653,35 @@ Object.freeze(Object.fromEntries([{
37450
37653
  }]
37451
37654
  }].map((s) => [s.stepId, s.defaultModelId])));
37452
37655
  string().min(1);
37656
+ var CLUSTER_STEP_SETTING_FIELDS = [{
37657
+ stepId: "face-embedding",
37658
+ key: "minLandmarkFaceSize",
37659
+ label: "Min face size for recognition (detection px)",
37660
+ 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.",
37661
+ type: "slider",
37662
+ min: 0,
37663
+ max: 64,
37664
+ step: 2,
37665
+ default: 24
37666
+ }];
37667
+ function clusterStepSettingKey(stepId, fieldKey) {
37668
+ return `clusterStepSetting:${stepId}:${fieldKey}`;
37669
+ }
37670
+ var ClusterSettingNumberSchema = number().finite();
37671
+ function readClusterStepSettings(config) {
37672
+ const out = {};
37673
+ for (const field of CLUSTER_STEP_SETTING_FIELDS) {
37674
+ const parsed = ClusterSettingNumberSchema.safeParse(config[clusterStepSettingKey(field.stepId, field.key)]);
37675
+ const value = parsed.success ? parsed.data : field.default;
37676
+ const existing = out[field.stepId] ?? {};
37677
+ out[field.stepId] = {
37678
+ ...existing,
37679
+ [field.key]: value
37680
+ };
37681
+ }
37682
+ return out;
37683
+ }
37684
+ readClusterStepSettings({});
37453
37685
  object({
37454
37686
  /**
37455
37687
  * 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-velux",
3
- "version": "0.2.26",
3
+ "version": "0.2.27",
4
4
  "description": "Velux KLF-200 device-provider addon for CamStack — local-gateway window + shutter covers (positional, no tilt)",
5
5
  "keywords": [
6
6
  "camstack",