@camstack/addon-export-hap 1.2.37 → 1.2.38

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.
@@ -8740,6 +8740,15 @@ var LabelDefinitionSchema = object({
8740
8740
  description: string().optional(),
8741
8741
  icon: string().optional()
8742
8742
  });
8743
+ var ClassMapDefinitionSchema = object({
8744
+ mapping: record(string(), _enum([
8745
+ "person",
8746
+ "vehicle",
8747
+ "animal",
8748
+ "package"
8749
+ ])),
8750
+ preserveOriginal: boolean()
8751
+ });
8743
8752
  var MODEL_FORMATS = [
8744
8753
  "onnx",
8745
8754
  "coreml",
@@ -8918,7 +8927,13 @@ var ModelCatalogEntrySchema = object({
8918
8927
  * `id` stays the source of truth for resolution/download/persistence; grouping
8919
8928
  * is a presentation overlay resolved back to an `id`.
8920
8929
  */
8921
- group: ModelVariantGroupSchema.optional()
8930
+ group: ModelVariantGroupSchema.optional(),
8931
+ /**
8932
+ * Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
8933
+ * applies (Frigate / COCO public catalog). Set on a custom model whose raw
8934
+ * labels already ARE the CamStack macros (Scrypted identity map).
8935
+ */
8936
+ classMap: ClassMapDefinitionSchema.optional()
8922
8937
  });
8923
8938
  var ConvertTargetSchema = discriminatedUnion("format", [object({
8924
8939
  format: literal("openvino"),
@@ -8947,7 +8962,8 @@ var ModelConvertMetadataSchema = object({
8947
8962
  "ocr",
8948
8963
  "segmentation"
8949
8964
  ]),
8950
- faceAlignment: boolean().optional()
8965
+ faceAlignment: boolean().optional(),
8966
+ classMap: ClassMapDefinitionSchema.optional()
8951
8967
  });
8952
8968
  var ConvertResultSchema = object({
8953
8969
  entry: ModelCatalogEntrySchema,
@@ -18019,6 +18035,33 @@ var NativeCropRefSchema = object({
18019
18035
  h: number()
18020
18036
  })
18021
18037
  });
18038
+ object({
18039
+ crop: object({
18040
+ left: number(),
18041
+ top: number(),
18042
+ width: number().positive(),
18043
+ height: number().positive()
18044
+ }).optional(),
18045
+ content: object({
18046
+ width: number().int().positive(),
18047
+ height: number().int().positive()
18048
+ }),
18049
+ fit: _enum(["stretch", "contain"]),
18050
+ format: _enum([
18051
+ "rgb",
18052
+ "gray",
18053
+ "jpeg"
18054
+ ])
18055
+ });
18056
+ var FrameRefSchema = object({
18057
+ registryId: string().min(1),
18058
+ id: string().min(1),
18059
+ width: number().int().positive(),
18060
+ height: number().int().positive(),
18061
+ format: _enum(["rgb", "gray"]),
18062
+ timestamp: number(),
18063
+ capturedAt: number().optional()
18064
+ });
18022
18065
  var ModelFormatSchema$1 = _enum([
18023
18066
  "onnx",
18024
18067
  "coreml",
@@ -18263,6 +18306,12 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
18263
18306
  steps: array(PipelineStepInputSchema).min(1),
18264
18307
  frame: FrameInputSchema.optional(),
18265
18308
  /**
18309
+ * Process-local lazy frame. Valid only when caller and provider resolve
18310
+ * in the same execution-group process; split/cross-node callers use
18311
+ * `frame`/`image` inline compatibility instead.
18312
+ */
18313
+ frameRef: FrameRefSchema.optional(),
18314
+ /**
18266
18315
  * CB5 shm passthrough — a `FrameHandle` naming the same ring slot
18267
18316
  * the decoded pixels live in. One more member of the one-of
18268
18317
  * frame/frameHandle/image/imageBase64/referenceImage group.
@@ -18518,7 +18567,10 @@ var NativeCropResultSchema = object({
18518
18567
  * Which source served this crop, so a quality-sensitive consumer (the native
18519
18568
  * `keyFrame`) can reject a degraded fallback:
18520
18569
  * - `native` — cut from the decode worker's retained NATIVE surface (the
18521
- * quality path).
18570
+ * quality path). A subject-tile serve is also native-resolution and stays
18571
+ * `native` here: the public enum cannot name `tile` without a breaking cap
18572
+ * change. Runner telemetry distinguishes lease vs tile via `source` on the
18573
+ * internal crop result (`nativeHits` vs `tileHits`).
18522
18574
  * - `ram-fullframe` — the native surface MISSED but the request was full-frame,
18523
18575
  * so the ≤640 RAM `RetainedFrameStore` served it (honest lower-res; legit for
18524
18576
  * the blank-frame guard / 640-snapshot resolve, NOT for the clean keyFrame).
@@ -19009,12 +19061,41 @@ var RunnerLocalLoadSchema = object({
19009
19061
  * legacy `OrchestratorMetricsSchema` shape so existing dashboards keep
19010
19062
  * working unchanged when they switch to reading from the runner cap.
19011
19063
  */
19064
+ var FrameLazyCountersSchema = object({
19065
+ framesDecoded: number(),
19066
+ framesAdmitted: number(),
19067
+ framesDroppedPixelFree: number(),
19068
+ viewsMaterialized: number(),
19069
+ viewsSkipped: number(),
19070
+ workerToRunnerBytes: number(),
19071
+ runnerToPoolRawBytes: number(),
19072
+ runnerToPoolJpegBytes: number(),
19073
+ onDemandFullFrameRequests: number(),
19074
+ onDemandCropRequests: number(),
19075
+ nativeHits: number(),
19076
+ nativeMisses: number(),
19077
+ tileHits: number(),
19078
+ tileMisses: number(),
19079
+ fallbackHits: number(),
19080
+ fallbackMisses: number(),
19081
+ retainedWritesAvoided: number(),
19082
+ residentRefs: number(),
19083
+ residentBytes: number(),
19084
+ releases: number(),
19085
+ evictions: number(),
19086
+ staleMisses: number()
19087
+ });
19088
+ var FrameLazyMetricsSchema = object({
19089
+ node: FrameLazyCountersSchema,
19090
+ cameras: array(FrameLazyCountersSchema.extend({ deviceId: number() }))
19091
+ });
19012
19092
  var RunnerLocalMetricsSchema = object({
19013
19093
  nodeId: string(),
19014
19094
  activeCameras: number(),
19015
19095
  throttledCameras: number(),
19016
19096
  avgInferenceTimeMs: number(),
19017
- queueDepth: number()
19097
+ queueDepth: number(),
19098
+ frameLazy: FrameLazyMetricsSchema.optional()
19018
19099
  });
19019
19100
  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({
19020
19101
  handle: FrameHandleSchema,
@@ -20314,6 +20395,9 @@ method(_void(), ProviderInfoSchema), method(object({ config: record(string(), un
20314
20395
  location: StorageLocationSchema,
20315
20396
  relativePath: string()
20316
20397
  }), _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" });
20398
+ /** Profile-exported FormBuilder schema. Shape is ConfigUISchema at the UI. */
20399
+ var ProfileSettingsSchemaBridge = unknown().nullable();
20400
+ var ProfileSettingsBagSchema = record(string(), unknown());
20317
20401
  /**
20318
20402
  * A live terminal session hosted by the provider addon. Output and input do
20319
20403
  * NOT flow through the capability — they use the addon data plane
@@ -20343,7 +20427,14 @@ var TerminalSessionInfoSchema = object({
20343
20427
  var TerminalProfileInfoSchema = object({
20344
20428
  profileId: string(),
20345
20429
  label: string(),
20346
- description: string().optional()
20430
+ description: string().optional(),
20431
+ /** Spawn defaults the instance form copies on create. */
20432
+ executable: string().optional(),
20433
+ args: array(string()).readonly().optional(),
20434
+ cwd: string().optional(),
20435
+ environment: array(string()).readonly().optional(),
20436
+ /** ConfigUISchema for instance knobs, or null when the profile has none. */
20437
+ settingsSchema: ProfileSettingsSchemaBridge.optional()
20347
20438
  });
20348
20439
  /**
20349
20440
  * A durable operator-created Terminal instance. Profiles are templates; only
@@ -20356,7 +20447,12 @@ var TerminalInstanceInfoSchema = object({
20356
20447
  profileId: string(),
20357
20448
  profileLabel: string(),
20358
20449
  name: string(),
20359
- enabled: boolean()
20450
+ enabled: boolean(),
20451
+ executable: string(),
20452
+ args: array(string()).readonly(),
20453
+ cwd: string(),
20454
+ environment: array(string()).readonly(),
20455
+ profileSettings: ProfileSettingsBagSchema
20360
20456
  });
20361
20457
  var TerminalLegacyCameraSchema = object({
20362
20458
  stableId: string(),
@@ -20386,7 +20482,23 @@ var TerminalOutputBatchSchema = object({
20386
20482
  method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }), method(_void(), array(TerminalInstanceInfoSchema).readonly(), { auth: "admin" }), method(object({
20387
20483
  targetNodeId: string().min(1),
20388
20484
  profileId: string().min(1),
20389
- name: string().trim().min(1).max(160).optional()
20485
+ name: string().trim().min(1).max(160).optional(),
20486
+ executable: string().max(1024).optional(),
20487
+ args: array(string().max(2048)).max(64).optional(),
20488
+ cwd: string().max(1024).optional(),
20489
+ environment: array(string().max(4096)).max(64).optional(),
20490
+ profileSettings: ProfileSettingsBagSchema.optional()
20491
+ }), TerminalInstanceInfoSchema, {
20492
+ kind: "mutation",
20493
+ auth: "admin"
20494
+ }), method(object({
20495
+ instanceId: string().min(1),
20496
+ name: string().trim().min(1).max(160).optional(),
20497
+ executable: string().max(1024).optional(),
20498
+ args: array(string().max(2048)).max(64).optional(),
20499
+ cwd: string().max(1024).optional(),
20500
+ environment: array(string().max(4096)).max(64).optional(),
20501
+ profileSettings: ProfileSettingsBagSchema.optional()
20390
20502
  }), TerminalInstanceInfoSchema, {
20391
20503
  kind: "mutation",
20392
20504
  auth: "admin"
@@ -20408,7 +20520,11 @@ method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }),
20408
20520
  }), method(_void(), array(TerminalSessionInfoSchema).readonly(), { auth: "admin" }), method(object({
20409
20521
  profileId: string(),
20410
20522
  cols: number().int().positive(),
20411
- rows: number().int().positive()
20523
+ rows: number().int().positive(),
20524
+ executable: string().max(1024).optional(),
20525
+ args: array(string().max(2048)).max(64).optional(),
20526
+ cwd: string().max(1024).optional(),
20527
+ environment: array(string().max(4096)).max(64).optional()
20412
20528
  }), TerminalSessionInfoSchema, {
20413
20529
  kind: "mutation",
20414
20530
  auth: "admin"
@@ -23226,10 +23342,10 @@ DeviceType.LawnMower, method(object({ deviceId: number().int().nonnegative() }),
23226
23342
  *
23227
23343
  * • The SDK (mobile / web client) consumes `getConnectionEndpoints()`
23228
23344
  * to receive an ordered list of candidate base URLs it should race
23229
- * on connect — LAN IPv4 first (lowest latency when on same network),
23230
- * then public hostname (if a tunnel is up), then IPv6. The SDK can
23231
- * race them with short timeouts and stick with the winner for the
23232
- * session.
23345
+ * on connect — LAN IPv4 and stable LAN IPv6 first (lowest latency
23346
+ * when on the same network), then public hostname (if a tunnel is
23347
+ * up). The SDK can race them with short timeouts and stick with the
23348
+ * winner for the session.
23233
23349
  *
23234
23350
  * Why hub-only: agents are not directly addressable by the operator's
23235
23351
  * clients — they reverse-connect to the hub. Exposing their interfaces
@@ -23384,6 +23500,17 @@ var NotificationEndpointSchema = object({
23384
23500
  /** What the ranking currently resolves to (null when nothing is reachable). */
23385
23501
  resolved: string().nullable()
23386
23502
  });
23503
+ /**
23504
+ * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
23505
+ * AUTO (every LAN IPv4 + the public tunnel). `resolved` is what that choice
23506
+ * currently expands to, so the UI can show the effective set either way.
23507
+ */
23508
+ var ViewerEndpointsSchema = object({
23509
+ /** The operator's explicit race set, or empty for AUTO. */
23510
+ baseUrls: array(string()).readonly(),
23511
+ /** What the ranking currently resolves to (may be empty if nothing is up). */
23512
+ resolved: array(string()).readonly()
23513
+ });
23387
23514
  var AllowedAddressesSchema = object({
23388
23515
  /**
23389
23516
  * Allowlist of interface addresses operators have explicitly opted
@@ -23392,6 +23519,20 @@ var AllowedAddressesSchema = object({
23392
23519
  * Network Addresses admin page and persisted by the addon.
23393
23520
  */
23394
23521
  addresses: array(string()).readonly() });
23522
+ var TlsStatusSchema = object({
23523
+ mode: _enum([
23524
+ "generated",
23525
+ "uploaded",
23526
+ "disabled"
23527
+ ]),
23528
+ leafFingerprintSha256: string().nullable(),
23529
+ caFingerprintSha256: string().nullable(),
23530
+ validTo: string().nullable(),
23531
+ sans: array(string()),
23532
+ caCertPem: string().nullable(),
23533
+ reissueError: string().nullable(),
23534
+ restartRequired: boolean()
23535
+ });
23395
23536
  method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
23396
23537
  /**
23397
23538
  * LEGACY HINT — do not send from new code. Kept optional so clients
@@ -23401,17 +23542,31 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
23401
23542
  */
23402
23543
  port: number().int().min(1).max(65535).optional(),
23403
23544
  /** Include `http(s)://127.0.0.1:<port>` as the lowest-priority
23404
- * candidate. Default `true`. */
23545
+ * candidate. Default `false` — loopback is not a client route. */
23405
23546
  includeLoopback: boolean().optional(),
23406
- /** Skip IPv6 entries. Some legacy clients can't parse them.
23407
- * Default `false`. */
23547
+ /** Skip IPv6 entries. Default `false` the palette includes stable
23548
+ * LAN IPv6 (ICE/WebRTC uses dual-stack regardless). Pass `true` to
23549
+ * hide them. The viewer HTTP/WS race is `getViewerEndpoints`. */
23408
23550
  ipv4Only: boolean().optional(),
23409
23551
  /** Scheme to emit for LAN/loopback URLs. Default `'http'`.
23410
23552
  * Pass `'https'` when the caller is itself loaded over HTTPS
23411
23553
  * to avoid mixed-content blocks in the browser. The public
23412
23554
  * tunnel always emits `https://` regardless. */
23413
23555
  scheme: _enum(["http", "https"]).optional()
23414
- }), 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" });
23556
+ }), 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, {
23557
+ kind: "mutation",
23558
+ auth: "admin"
23559
+ }), method(object({
23560
+ certPem: string().min(1),
23561
+ keyPem: string().min(1),
23562
+ caPem: string().optional()
23563
+ }), TlsStatusSchema, {
23564
+ kind: "mutation",
23565
+ auth: "admin"
23566
+ }), method(_void(), object({ pem: string() })), method(_void(), TlsStatusSchema, {
23567
+ kind: "mutation",
23568
+ auth: "admin"
23569
+ });
23415
23570
  var LockControlStatusSchema = object({
23416
23571
  /** Lifecycle state of the lock. `jammed` means the motor reported
23417
23572
  * failure to reach the target — operator intervention required. */
@@ -29211,6 +29366,12 @@ Object.freeze({
29211
29366
  addonId: null,
29212
29367
  access: "create"
29213
29368
  },
29369
+ "localNetwork.downloadCa": {
29370
+ capName: "local-network",
29371
+ capScope: "system",
29372
+ addonId: null,
29373
+ access: "view"
29374
+ },
29214
29375
  "localNetwork.getAllowedAddresses": {
29215
29376
  capName: "local-network",
29216
29377
  capScope: "system",
@@ -29235,18 +29396,42 @@ Object.freeze({
29235
29396
  addonId: null,
29236
29397
  access: "view"
29237
29398
  },
29399
+ "localNetwork.getTlsStatus": {
29400
+ capName: "local-network",
29401
+ capScope: "system",
29402
+ addonId: null,
29403
+ access: "view"
29404
+ },
29405
+ "localNetwork.getViewerEndpoints": {
29406
+ capName: "local-network",
29407
+ capScope: "system",
29408
+ addonId: null,
29409
+ access: "view"
29410
+ },
29238
29411
  "localNetwork.list": {
29239
29412
  capName: "local-network",
29240
29413
  capScope: "system",
29241
29414
  addonId: null,
29242
29415
  access: "view"
29243
29416
  },
29417
+ "localNetwork.regenerateCertificate": {
29418
+ capName: "local-network",
29419
+ capScope: "system",
29420
+ addonId: null,
29421
+ access: "create"
29422
+ },
29244
29423
  "localNetwork.resetAllowlistToBestMatch": {
29245
29424
  capName: "local-network",
29246
29425
  capScope: "system",
29247
29426
  addonId: null,
29248
29427
  access: "delete"
29249
29428
  },
29429
+ "localNetwork.revertToGeneratedCertificate": {
29430
+ capName: "local-network",
29431
+ capScope: "system",
29432
+ addonId: null,
29433
+ access: "create"
29434
+ },
29250
29435
  "localNetwork.setAllowedAddresses": {
29251
29436
  capName: "local-network",
29252
29437
  capScope: "system",
@@ -29259,6 +29444,18 @@ Object.freeze({
29259
29444
  addonId: null,
29260
29445
  access: "create"
29261
29446
  },
29447
+ "localNetwork.setViewerEndpoints": {
29448
+ capName: "local-network",
29449
+ capScope: "system",
29450
+ addonId: null,
29451
+ access: "create"
29452
+ },
29453
+ "localNetwork.uploadCertificate": {
29454
+ capName: "local-network",
29455
+ capScope: "system",
29456
+ addonId: null,
29457
+ access: "create"
29458
+ },
29262
29459
  "lockControl.lock": {
29263
29460
  capName: "lock-control",
29264
29461
  capScope: "device",
@@ -32139,6 +32336,12 @@ Object.freeze({
32139
32336
  addonId: null,
32140
32337
  access: "create"
32141
32338
  },
32339
+ "terminalSession.updateInstance": {
32340
+ capName: "terminal-session",
32341
+ capScope: "system",
32342
+ addonId: null,
32343
+ access: "create"
32344
+ },
32142
32345
  "terminalSession.writeInput": {
32143
32346
  capName: "terminal-session",
32144
32347
  capScope: "system",
@@ -34626,6 +34829,35 @@ Object.freeze(Object.fromEntries([{
34626
34829
  }]
34627
34830
  }].map((s) => [s.stepId, s.defaultModelId])));
34628
34831
  string().min(1);
34832
+ var CLUSTER_STEP_SETTING_FIELDS = [{
34833
+ stepId: "face-embedding",
34834
+ key: "minLandmarkFaceSize",
34835
+ label: "Min face size for recognition (detection px)",
34836
+ 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.",
34837
+ type: "slider",
34838
+ min: 0,
34839
+ max: 64,
34840
+ step: 2,
34841
+ default: 24
34842
+ }];
34843
+ function clusterStepSettingKey(stepId, fieldKey) {
34844
+ return `clusterStepSetting:${stepId}:${fieldKey}`;
34845
+ }
34846
+ var ClusterSettingNumberSchema = number().finite();
34847
+ function readClusterStepSettings(config) {
34848
+ const out = {};
34849
+ for (const field of CLUSTER_STEP_SETTING_FIELDS) {
34850
+ const parsed = ClusterSettingNumberSchema.safeParse(config[clusterStepSettingKey(field.stepId, field.key)]);
34851
+ const value = parsed.success ? parsed.data : field.default;
34852
+ const existing = out[field.stepId] ?? {};
34853
+ out[field.stepId] = {
34854
+ ...existing,
34855
+ [field.key]: value
34856
+ };
34857
+ }
34858
+ return out;
34859
+ }
34860
+ readClusterStepSettings({});
34629
34861
  object({
34630
34862
  /**
34631
34863
  * Fraction of the box's own size added on EACH side before cutting.
@@ -8728,6 +8728,15 @@ var LabelDefinitionSchema = object({
8728
8728
  description: string().optional(),
8729
8729
  icon: string().optional()
8730
8730
  });
8731
+ var ClassMapDefinitionSchema = object({
8732
+ mapping: record(string(), _enum([
8733
+ "person",
8734
+ "vehicle",
8735
+ "animal",
8736
+ "package"
8737
+ ])),
8738
+ preserveOriginal: boolean()
8739
+ });
8731
8740
  var MODEL_FORMATS = [
8732
8741
  "onnx",
8733
8742
  "coreml",
@@ -8906,7 +8915,13 @@ var ModelCatalogEntrySchema = object({
8906
8915
  * `id` stays the source of truth for resolution/download/persistence; grouping
8907
8916
  * is a presentation overlay resolved back to an `id`.
8908
8917
  */
8909
- group: ModelVariantGroupSchema.optional()
8918
+ group: ModelVariantGroupSchema.optional(),
8919
+ /**
8920
+ * Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
8921
+ * applies (Frigate / COCO public catalog). Set on a custom model whose raw
8922
+ * labels already ARE the CamStack macros (Scrypted identity map).
8923
+ */
8924
+ classMap: ClassMapDefinitionSchema.optional()
8910
8925
  });
8911
8926
  var ConvertTargetSchema = discriminatedUnion("format", [object({
8912
8927
  format: literal("openvino"),
@@ -8935,7 +8950,8 @@ var ModelConvertMetadataSchema = object({
8935
8950
  "ocr",
8936
8951
  "segmentation"
8937
8952
  ]),
8938
- faceAlignment: boolean().optional()
8953
+ faceAlignment: boolean().optional(),
8954
+ classMap: ClassMapDefinitionSchema.optional()
8939
8955
  });
8940
8956
  var ConvertResultSchema = object({
8941
8957
  entry: ModelCatalogEntrySchema,
@@ -18007,6 +18023,33 @@ var NativeCropRefSchema = object({
18007
18023
  h: number()
18008
18024
  })
18009
18025
  });
18026
+ object({
18027
+ crop: object({
18028
+ left: number(),
18029
+ top: number(),
18030
+ width: number().positive(),
18031
+ height: number().positive()
18032
+ }).optional(),
18033
+ content: object({
18034
+ width: number().int().positive(),
18035
+ height: number().int().positive()
18036
+ }),
18037
+ fit: _enum(["stretch", "contain"]),
18038
+ format: _enum([
18039
+ "rgb",
18040
+ "gray",
18041
+ "jpeg"
18042
+ ])
18043
+ });
18044
+ var FrameRefSchema = object({
18045
+ registryId: string().min(1),
18046
+ id: string().min(1),
18047
+ width: number().int().positive(),
18048
+ height: number().int().positive(),
18049
+ format: _enum(["rgb", "gray"]),
18050
+ timestamp: number(),
18051
+ capturedAt: number().optional()
18052
+ });
18010
18053
  var ModelFormatSchema$1 = _enum([
18011
18054
  "onnx",
18012
18055
  "coreml",
@@ -18251,6 +18294,12 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
18251
18294
  steps: array(PipelineStepInputSchema).min(1),
18252
18295
  frame: FrameInputSchema.optional(),
18253
18296
  /**
18297
+ * Process-local lazy frame. Valid only when caller and provider resolve
18298
+ * in the same execution-group process; split/cross-node callers use
18299
+ * `frame`/`image` inline compatibility instead.
18300
+ */
18301
+ frameRef: FrameRefSchema.optional(),
18302
+ /**
18254
18303
  * CB5 shm passthrough — a `FrameHandle` naming the same ring slot
18255
18304
  * the decoded pixels live in. One more member of the one-of
18256
18305
  * frame/frameHandle/image/imageBase64/referenceImage group.
@@ -18506,7 +18555,10 @@ var NativeCropResultSchema = object({
18506
18555
  * Which source served this crop, so a quality-sensitive consumer (the native
18507
18556
  * `keyFrame`) can reject a degraded fallback:
18508
18557
  * - `native` — cut from the decode worker's retained NATIVE surface (the
18509
- * quality path).
18558
+ * quality path). A subject-tile serve is also native-resolution and stays
18559
+ * `native` here: the public enum cannot name `tile` without a breaking cap
18560
+ * change. Runner telemetry distinguishes lease vs tile via `source` on the
18561
+ * internal crop result (`nativeHits` vs `tileHits`).
18510
18562
  * - `ram-fullframe` — the native surface MISSED but the request was full-frame,
18511
18563
  * so the ≤640 RAM `RetainedFrameStore` served it (honest lower-res; legit for
18512
18564
  * the blank-frame guard / 640-snapshot resolve, NOT for the clean keyFrame).
@@ -18997,12 +19049,41 @@ var RunnerLocalLoadSchema = object({
18997
19049
  * legacy `OrchestratorMetricsSchema` shape so existing dashboards keep
18998
19050
  * working unchanged when they switch to reading from the runner cap.
18999
19051
  */
19052
+ var FrameLazyCountersSchema = object({
19053
+ framesDecoded: number(),
19054
+ framesAdmitted: number(),
19055
+ framesDroppedPixelFree: number(),
19056
+ viewsMaterialized: number(),
19057
+ viewsSkipped: number(),
19058
+ workerToRunnerBytes: number(),
19059
+ runnerToPoolRawBytes: number(),
19060
+ runnerToPoolJpegBytes: number(),
19061
+ onDemandFullFrameRequests: number(),
19062
+ onDemandCropRequests: number(),
19063
+ nativeHits: number(),
19064
+ nativeMisses: number(),
19065
+ tileHits: number(),
19066
+ tileMisses: number(),
19067
+ fallbackHits: number(),
19068
+ fallbackMisses: number(),
19069
+ retainedWritesAvoided: number(),
19070
+ residentRefs: number(),
19071
+ residentBytes: number(),
19072
+ releases: number(),
19073
+ evictions: number(),
19074
+ staleMisses: number()
19075
+ });
19076
+ var FrameLazyMetricsSchema = object({
19077
+ node: FrameLazyCountersSchema,
19078
+ cameras: array(FrameLazyCountersSchema.extend({ deviceId: number() }))
19079
+ });
19000
19080
  var RunnerLocalMetricsSchema = object({
19001
19081
  nodeId: string(),
19002
19082
  activeCameras: number(),
19003
19083
  throttledCameras: number(),
19004
19084
  avgInferenceTimeMs: number(),
19005
- queueDepth: number()
19085
+ queueDepth: number(),
19086
+ frameLazy: FrameLazyMetricsSchema.optional()
19006
19087
  });
19007
19088
  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({
19008
19089
  handle: FrameHandleSchema,
@@ -20302,6 +20383,9 @@ method(_void(), ProviderInfoSchema), method(object({ config: record(string(), un
20302
20383
  location: StorageLocationSchema,
20303
20384
  relativePath: string()
20304
20385
  }), _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" });
20386
+ /** Profile-exported FormBuilder schema. Shape is ConfigUISchema at the UI. */
20387
+ var ProfileSettingsSchemaBridge = unknown().nullable();
20388
+ var ProfileSettingsBagSchema = record(string(), unknown());
20305
20389
  /**
20306
20390
  * A live terminal session hosted by the provider addon. Output and input do
20307
20391
  * NOT flow through the capability — they use the addon data plane
@@ -20331,7 +20415,14 @@ var TerminalSessionInfoSchema = object({
20331
20415
  var TerminalProfileInfoSchema = object({
20332
20416
  profileId: string(),
20333
20417
  label: string(),
20334
- description: string().optional()
20418
+ description: string().optional(),
20419
+ /** Spawn defaults the instance form copies on create. */
20420
+ executable: string().optional(),
20421
+ args: array(string()).readonly().optional(),
20422
+ cwd: string().optional(),
20423
+ environment: array(string()).readonly().optional(),
20424
+ /** ConfigUISchema for instance knobs, or null when the profile has none. */
20425
+ settingsSchema: ProfileSettingsSchemaBridge.optional()
20335
20426
  });
20336
20427
  /**
20337
20428
  * A durable operator-created Terminal instance. Profiles are templates; only
@@ -20344,7 +20435,12 @@ var TerminalInstanceInfoSchema = object({
20344
20435
  profileId: string(),
20345
20436
  profileLabel: string(),
20346
20437
  name: string(),
20347
- enabled: boolean()
20438
+ enabled: boolean(),
20439
+ executable: string(),
20440
+ args: array(string()).readonly(),
20441
+ cwd: string(),
20442
+ environment: array(string()).readonly(),
20443
+ profileSettings: ProfileSettingsBagSchema
20348
20444
  });
20349
20445
  var TerminalLegacyCameraSchema = object({
20350
20446
  stableId: string(),
@@ -20374,7 +20470,23 @@ var TerminalOutputBatchSchema = object({
20374
20470
  method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }), method(_void(), array(TerminalInstanceInfoSchema).readonly(), { auth: "admin" }), method(object({
20375
20471
  targetNodeId: string().min(1),
20376
20472
  profileId: string().min(1),
20377
- name: string().trim().min(1).max(160).optional()
20473
+ name: string().trim().min(1).max(160).optional(),
20474
+ executable: string().max(1024).optional(),
20475
+ args: array(string().max(2048)).max(64).optional(),
20476
+ cwd: string().max(1024).optional(),
20477
+ environment: array(string().max(4096)).max(64).optional(),
20478
+ profileSettings: ProfileSettingsBagSchema.optional()
20479
+ }), TerminalInstanceInfoSchema, {
20480
+ kind: "mutation",
20481
+ auth: "admin"
20482
+ }), method(object({
20483
+ instanceId: string().min(1),
20484
+ name: string().trim().min(1).max(160).optional(),
20485
+ executable: string().max(1024).optional(),
20486
+ args: array(string().max(2048)).max(64).optional(),
20487
+ cwd: string().max(1024).optional(),
20488
+ environment: array(string().max(4096)).max(64).optional(),
20489
+ profileSettings: ProfileSettingsBagSchema.optional()
20378
20490
  }), TerminalInstanceInfoSchema, {
20379
20491
  kind: "mutation",
20380
20492
  auth: "admin"
@@ -20396,7 +20508,11 @@ method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }),
20396
20508
  }), method(_void(), array(TerminalSessionInfoSchema).readonly(), { auth: "admin" }), method(object({
20397
20509
  profileId: string(),
20398
20510
  cols: number().int().positive(),
20399
- rows: number().int().positive()
20511
+ rows: number().int().positive(),
20512
+ executable: string().max(1024).optional(),
20513
+ args: array(string().max(2048)).max(64).optional(),
20514
+ cwd: string().max(1024).optional(),
20515
+ environment: array(string().max(4096)).max(64).optional()
20400
20516
  }), TerminalSessionInfoSchema, {
20401
20517
  kind: "mutation",
20402
20518
  auth: "admin"
@@ -23214,10 +23330,10 @@ DeviceType.LawnMower, method(object({ deviceId: number().int().nonnegative() }),
23214
23330
  *
23215
23331
  * • The SDK (mobile / web client) consumes `getConnectionEndpoints()`
23216
23332
  * to receive an ordered list of candidate base URLs it should race
23217
- * on connect — LAN IPv4 first (lowest latency when on same network),
23218
- * then public hostname (if a tunnel is up), then IPv6. The SDK can
23219
- * race them with short timeouts and stick with the winner for the
23220
- * session.
23333
+ * on connect — LAN IPv4 and stable LAN IPv6 first (lowest latency
23334
+ * when on the same network), then public hostname (if a tunnel is
23335
+ * up). The SDK can race them with short timeouts and stick with the
23336
+ * winner for the session.
23221
23337
  *
23222
23338
  * Why hub-only: agents are not directly addressable by the operator's
23223
23339
  * clients — they reverse-connect to the hub. Exposing their interfaces
@@ -23372,6 +23488,17 @@ var NotificationEndpointSchema = object({
23372
23488
  /** What the ranking currently resolves to (null when nothing is reachable). */
23373
23489
  resolved: string().nullable()
23374
23490
  });
23491
+ /**
23492
+ * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
23493
+ * AUTO (every LAN IPv4 + the public tunnel). `resolved` is what that choice
23494
+ * currently expands to, so the UI can show the effective set either way.
23495
+ */
23496
+ var ViewerEndpointsSchema = object({
23497
+ /** The operator's explicit race set, or empty for AUTO. */
23498
+ baseUrls: array(string()).readonly(),
23499
+ /** What the ranking currently resolves to (may be empty if nothing is up). */
23500
+ resolved: array(string()).readonly()
23501
+ });
23375
23502
  var AllowedAddressesSchema = object({
23376
23503
  /**
23377
23504
  * Allowlist of interface addresses operators have explicitly opted
@@ -23380,6 +23507,20 @@ var AllowedAddressesSchema = object({
23380
23507
  * Network Addresses admin page and persisted by the addon.
23381
23508
  */
23382
23509
  addresses: array(string()).readonly() });
23510
+ var TlsStatusSchema = object({
23511
+ mode: _enum([
23512
+ "generated",
23513
+ "uploaded",
23514
+ "disabled"
23515
+ ]),
23516
+ leafFingerprintSha256: string().nullable(),
23517
+ caFingerprintSha256: string().nullable(),
23518
+ validTo: string().nullable(),
23519
+ sans: array(string()),
23520
+ caCertPem: string().nullable(),
23521
+ reissueError: string().nullable(),
23522
+ restartRequired: boolean()
23523
+ });
23383
23524
  method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
23384
23525
  /**
23385
23526
  * LEGACY HINT — do not send from new code. Kept optional so clients
@@ -23389,17 +23530,31 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
23389
23530
  */
23390
23531
  port: number().int().min(1).max(65535).optional(),
23391
23532
  /** Include `http(s)://127.0.0.1:<port>` as the lowest-priority
23392
- * candidate. Default `true`. */
23533
+ * candidate. Default `false` — loopback is not a client route. */
23393
23534
  includeLoopback: boolean().optional(),
23394
- /** Skip IPv6 entries. Some legacy clients can't parse them.
23395
- * Default `false`. */
23535
+ /** Skip IPv6 entries. Default `false` the palette includes stable
23536
+ * LAN IPv6 (ICE/WebRTC uses dual-stack regardless). Pass `true` to
23537
+ * hide them. The viewer HTTP/WS race is `getViewerEndpoints`. */
23396
23538
  ipv4Only: boolean().optional(),
23397
23539
  /** Scheme to emit for LAN/loopback URLs. Default `'http'`.
23398
23540
  * Pass `'https'` when the caller is itself loaded over HTTPS
23399
23541
  * to avoid mixed-content blocks in the browser. The public
23400
23542
  * tunnel always emits `https://` regardless. */
23401
23543
  scheme: _enum(["http", "https"]).optional()
23402
- }), 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" });
23544
+ }), 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, {
23545
+ kind: "mutation",
23546
+ auth: "admin"
23547
+ }), method(object({
23548
+ certPem: string().min(1),
23549
+ keyPem: string().min(1),
23550
+ caPem: string().optional()
23551
+ }), TlsStatusSchema, {
23552
+ kind: "mutation",
23553
+ auth: "admin"
23554
+ }), method(_void(), object({ pem: string() })), method(_void(), TlsStatusSchema, {
23555
+ kind: "mutation",
23556
+ auth: "admin"
23557
+ });
23403
23558
  var LockControlStatusSchema = object({
23404
23559
  /** Lifecycle state of the lock. `jammed` means the motor reported
23405
23560
  * failure to reach the target — operator intervention required. */
@@ -29199,6 +29354,12 @@ Object.freeze({
29199
29354
  addonId: null,
29200
29355
  access: "create"
29201
29356
  },
29357
+ "localNetwork.downloadCa": {
29358
+ capName: "local-network",
29359
+ capScope: "system",
29360
+ addonId: null,
29361
+ access: "view"
29362
+ },
29202
29363
  "localNetwork.getAllowedAddresses": {
29203
29364
  capName: "local-network",
29204
29365
  capScope: "system",
@@ -29223,18 +29384,42 @@ Object.freeze({
29223
29384
  addonId: null,
29224
29385
  access: "view"
29225
29386
  },
29387
+ "localNetwork.getTlsStatus": {
29388
+ capName: "local-network",
29389
+ capScope: "system",
29390
+ addonId: null,
29391
+ access: "view"
29392
+ },
29393
+ "localNetwork.getViewerEndpoints": {
29394
+ capName: "local-network",
29395
+ capScope: "system",
29396
+ addonId: null,
29397
+ access: "view"
29398
+ },
29226
29399
  "localNetwork.list": {
29227
29400
  capName: "local-network",
29228
29401
  capScope: "system",
29229
29402
  addonId: null,
29230
29403
  access: "view"
29231
29404
  },
29405
+ "localNetwork.regenerateCertificate": {
29406
+ capName: "local-network",
29407
+ capScope: "system",
29408
+ addonId: null,
29409
+ access: "create"
29410
+ },
29232
29411
  "localNetwork.resetAllowlistToBestMatch": {
29233
29412
  capName: "local-network",
29234
29413
  capScope: "system",
29235
29414
  addonId: null,
29236
29415
  access: "delete"
29237
29416
  },
29417
+ "localNetwork.revertToGeneratedCertificate": {
29418
+ capName: "local-network",
29419
+ capScope: "system",
29420
+ addonId: null,
29421
+ access: "create"
29422
+ },
29238
29423
  "localNetwork.setAllowedAddresses": {
29239
29424
  capName: "local-network",
29240
29425
  capScope: "system",
@@ -29247,6 +29432,18 @@ Object.freeze({
29247
29432
  addonId: null,
29248
29433
  access: "create"
29249
29434
  },
29435
+ "localNetwork.setViewerEndpoints": {
29436
+ capName: "local-network",
29437
+ capScope: "system",
29438
+ addonId: null,
29439
+ access: "create"
29440
+ },
29441
+ "localNetwork.uploadCertificate": {
29442
+ capName: "local-network",
29443
+ capScope: "system",
29444
+ addonId: null,
29445
+ access: "create"
29446
+ },
29250
29447
  "lockControl.lock": {
29251
29448
  capName: "lock-control",
29252
29449
  capScope: "device",
@@ -32127,6 +32324,12 @@ Object.freeze({
32127
32324
  addonId: null,
32128
32325
  access: "create"
32129
32326
  },
32327
+ "terminalSession.updateInstance": {
32328
+ capName: "terminal-session",
32329
+ capScope: "system",
32330
+ addonId: null,
32331
+ access: "create"
32332
+ },
32130
32333
  "terminalSession.writeInput": {
32131
32334
  capName: "terminal-session",
32132
32335
  capScope: "system",
@@ -34614,6 +34817,35 @@ Object.freeze(Object.fromEntries([{
34614
34817
  }]
34615
34818
  }].map((s) => [s.stepId, s.defaultModelId])));
34616
34819
  string().min(1);
34820
+ var CLUSTER_STEP_SETTING_FIELDS = [{
34821
+ stepId: "face-embedding",
34822
+ key: "minLandmarkFaceSize",
34823
+ label: "Min face size for recognition (detection px)",
34824
+ 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.",
34825
+ type: "slider",
34826
+ min: 0,
34827
+ max: 64,
34828
+ step: 2,
34829
+ default: 24
34830
+ }];
34831
+ function clusterStepSettingKey(stepId, fieldKey) {
34832
+ return `clusterStepSetting:${stepId}:${fieldKey}`;
34833
+ }
34834
+ var ClusterSettingNumberSchema = number().finite();
34835
+ function readClusterStepSettings(config) {
34836
+ const out = {};
34837
+ for (const field of CLUSTER_STEP_SETTING_FIELDS) {
34838
+ const parsed = ClusterSettingNumberSchema.safeParse(config[clusterStepSettingKey(field.stepId, field.key)]);
34839
+ const value = parsed.success ? parsed.data : field.default;
34840
+ const existing = out[field.stepId] ?? {};
34841
+ out[field.stepId] = {
34842
+ ...existing,
34843
+ [field.key]: value
34844
+ };
34845
+ }
34846
+ return out;
34847
+ }
34848
+ readClusterStepSettings({});
34617
34849
  object({
34618
34850
  /**
34619
34851
  * 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-export-hap",
3
- "version": "1.2.37",
3
+ "version": "1.2.38",
4
4
  "description": "HomeKit (HAP) exporter for CamStack devices. Publishes each exposed device as its own HomeKit accessory: cameras and doorbells with SRTP streaming, HomeKit Secure Video, motion, two-way audio, PTZ and battery; switches, lights, locks and sensors through a capability→service table.",
5
5
  "keywords": [
6
6
  "camstack",