@camstack/addon-static-turn 1.2.24 → 1.2.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- //#region ../types/dist/event-category-XfKNtfCc.mjs
2
+ //#region ../types/dist/event-category-CIa_iT6b.mjs
3
3
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4
4
  EventCategory["SystemBoot"] = "system.boot";
5
5
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -15,6 +15,15 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
15
15
  */
16
16
  EventCategory["SystemRestartCompleted"] = "system.restart-completed";
17
17
  /**
18
+ * The hub reissued its own TLS certificate at boot (`ensureTlsCert`).
19
+ * Emitted only when the material on disk actually changed, so an
20
+ * operator who trusted the old certificate by hand is told rather than
21
+ * discovering it as a browser error. Payload `TlsCertChangedPayload`.
22
+ *
23
+ * Rule: docs/decisions/adr-0227-*.md
24
+ */
25
+ EventCategory["SystemTlsCertChanged"] = "system.tls-cert-changed";
26
+ /**
18
27
  * A newer addon or server-root package version was found by the
19
28
  * authoritative registry check. Emitted once when any observed
20
29
  * `latestVersion` changes (or a package/node first appears behind);
@@ -7995,6 +8004,15 @@ var LabelDefinitionSchema = object({
7995
8004
  description: string().optional(),
7996
8005
  icon: string().optional()
7997
8006
  });
8007
+ var ClassMapDefinitionSchema = object({
8008
+ mapping: record(string(), _enum([
8009
+ "person",
8010
+ "vehicle",
8011
+ "animal",
8012
+ "package"
8013
+ ])),
8014
+ preserveOriginal: boolean()
8015
+ });
7998
8016
  var MODEL_FORMATS = [
7999
8017
  "onnx",
8000
8018
  "coreml",
@@ -8173,7 +8191,13 @@ var ModelCatalogEntrySchema = object({
8173
8191
  * `id` stays the source of truth for resolution/download/persistence; grouping
8174
8192
  * is a presentation overlay resolved back to an `id`.
8175
8193
  */
8176
- group: ModelVariantGroupSchema.optional()
8194
+ group: ModelVariantGroupSchema.optional(),
8195
+ /**
8196
+ * Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
8197
+ * applies (Frigate / COCO public catalog). Set on a custom model whose raw
8198
+ * labels already ARE the CamStack macros (Scrypted identity map).
8199
+ */
8200
+ classMap: ClassMapDefinitionSchema.optional()
8177
8201
  });
8178
8202
  var ConvertTargetSchema = discriminatedUnion("format", [object({
8179
8203
  format: literal("openvino"),
@@ -8202,7 +8226,8 @@ var ModelConvertMetadataSchema = object({
8202
8226
  "ocr",
8203
8227
  "segmentation"
8204
8228
  ]),
8205
- faceAlignment: boolean().optional()
8229
+ faceAlignment: boolean().optional(),
8230
+ classMap: ClassMapDefinitionSchema.optional()
8206
8231
  });
8207
8232
  var ConvertResultSchema = object({
8208
8233
  entry: ModelCatalogEntrySchema,
@@ -17193,6 +17218,33 @@ var NativeCropRefSchema = object({
17193
17218
  h: number()
17194
17219
  })
17195
17220
  });
17221
+ object({
17222
+ crop: object({
17223
+ left: number(),
17224
+ top: number(),
17225
+ width: number().positive(),
17226
+ height: number().positive()
17227
+ }).optional(),
17228
+ content: object({
17229
+ width: number().int().positive(),
17230
+ height: number().int().positive()
17231
+ }),
17232
+ fit: _enum(["stretch", "contain"]),
17233
+ format: _enum([
17234
+ "rgb",
17235
+ "gray",
17236
+ "jpeg"
17237
+ ])
17238
+ });
17239
+ var FrameRefSchema = object({
17240
+ registryId: string().min(1),
17241
+ id: string().min(1),
17242
+ width: number().int().positive(),
17243
+ height: number().int().positive(),
17244
+ format: _enum(["rgb", "gray"]),
17245
+ timestamp: number(),
17246
+ capturedAt: number().optional()
17247
+ });
17196
17248
  var ModelFormatSchema$1 = _enum([
17197
17249
  "onnx",
17198
17250
  "coreml",
@@ -17437,6 +17489,12 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
17437
17489
  steps: array(PipelineStepInputSchema).min(1),
17438
17490
  frame: FrameInputSchema.optional(),
17439
17491
  /**
17492
+ * Process-local lazy frame. Valid only when caller and provider resolve
17493
+ * in the same execution-group process; split/cross-node callers use
17494
+ * `frame`/`image` inline compatibility instead.
17495
+ */
17496
+ frameRef: FrameRefSchema.optional(),
17497
+ /**
17440
17498
  * CB5 shm passthrough — a `FrameHandle` naming the same ring slot
17441
17499
  * the decoded pixels live in. One more member of the one-of
17442
17500
  * frame/frameHandle/image/imageBase64/referenceImage group.
@@ -17692,7 +17750,10 @@ var NativeCropResultSchema = object({
17692
17750
  * Which source served this crop, so a quality-sensitive consumer (the native
17693
17751
  * `keyFrame`) can reject a degraded fallback:
17694
17752
  * - `native` — cut from the decode worker's retained NATIVE surface (the
17695
- * quality path).
17753
+ * quality path). A subject-tile serve is also native-resolution and stays
17754
+ * `native` here: the public enum cannot name `tile` without a breaking cap
17755
+ * change. Runner telemetry distinguishes lease vs tile via `source` on the
17756
+ * internal crop result (`nativeHits` vs `tileHits`).
17696
17757
  * - `ram-fullframe` — the native surface MISSED but the request was full-frame,
17697
17758
  * so the ≤640 RAM `RetainedFrameStore` served it (honest lower-res; legit for
17698
17759
  * the blank-frame guard / 640-snapshot resolve, NOT for the clean keyFrame).
@@ -18183,12 +18244,41 @@ var RunnerLocalLoadSchema = object({
18183
18244
  * legacy `OrchestratorMetricsSchema` shape so existing dashboards keep
18184
18245
  * working unchanged when they switch to reading from the runner cap.
18185
18246
  */
18247
+ var FrameLazyCountersSchema = object({
18248
+ framesDecoded: number(),
18249
+ framesAdmitted: number(),
18250
+ framesDroppedPixelFree: number(),
18251
+ viewsMaterialized: number(),
18252
+ viewsSkipped: number(),
18253
+ workerToRunnerBytes: number(),
18254
+ runnerToPoolRawBytes: number(),
18255
+ runnerToPoolJpegBytes: number(),
18256
+ onDemandFullFrameRequests: number(),
18257
+ onDemandCropRequests: number(),
18258
+ nativeHits: number(),
18259
+ nativeMisses: number(),
18260
+ tileHits: number(),
18261
+ tileMisses: number(),
18262
+ fallbackHits: number(),
18263
+ fallbackMisses: number(),
18264
+ retainedWritesAvoided: number(),
18265
+ residentRefs: number(),
18266
+ residentBytes: number(),
18267
+ releases: number(),
18268
+ evictions: number(),
18269
+ staleMisses: number()
18270
+ });
18271
+ var FrameLazyMetricsSchema = object({
18272
+ node: FrameLazyCountersSchema,
18273
+ cameras: array(FrameLazyCountersSchema.extend({ deviceId: number() }))
18274
+ });
18186
18275
  var RunnerLocalMetricsSchema = object({
18187
18276
  nodeId: string(),
18188
18277
  activeCameras: number(),
18189
18278
  throttledCameras: number(),
18190
18279
  avgInferenceTimeMs: number(),
18191
- queueDepth: number()
18280
+ queueDepth: number(),
18281
+ frameLazy: FrameLazyMetricsSchema.optional()
18192
18282
  });
18193
18283
  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({
18194
18284
  handle: FrameHandleSchema,
@@ -19488,6 +19578,9 @@ method(_void(), ProviderInfoSchema), method(object({ config: record(string(), un
19488
19578
  location: StorageLocationSchema,
19489
19579
  relativePath: string()
19490
19580
  }), _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" });
19581
+ /** Profile-exported FormBuilder schema. Shape is ConfigUISchema at the UI. */
19582
+ var ProfileSettingsSchemaBridge = unknown().nullable();
19583
+ var ProfileSettingsBagSchema = record(string(), unknown());
19491
19584
  /**
19492
19585
  * A live terminal session hosted by the provider addon. Output and input do
19493
19586
  * NOT flow through the capability — they use the addon data plane
@@ -19517,7 +19610,14 @@ var TerminalSessionInfoSchema = object({
19517
19610
  var TerminalProfileInfoSchema = object({
19518
19611
  profileId: string(),
19519
19612
  label: string(),
19520
- description: string().optional()
19613
+ description: string().optional(),
19614
+ /** Spawn defaults the instance form copies on create. */
19615
+ executable: string().optional(),
19616
+ args: array(string()).readonly().optional(),
19617
+ cwd: string().optional(),
19618
+ environment: array(string()).readonly().optional(),
19619
+ /** ConfigUISchema for instance knobs, or null when the profile has none. */
19620
+ settingsSchema: ProfileSettingsSchemaBridge.optional()
19521
19621
  });
19522
19622
  /**
19523
19623
  * A durable operator-created Terminal instance. Profiles are templates; only
@@ -19530,7 +19630,12 @@ var TerminalInstanceInfoSchema = object({
19530
19630
  profileId: string(),
19531
19631
  profileLabel: string(),
19532
19632
  name: string(),
19533
- enabled: boolean()
19633
+ enabled: boolean(),
19634
+ executable: string(),
19635
+ args: array(string()).readonly(),
19636
+ cwd: string(),
19637
+ environment: array(string()).readonly(),
19638
+ profileSettings: ProfileSettingsBagSchema
19534
19639
  });
19535
19640
  var TerminalLegacyCameraSchema = object({
19536
19641
  stableId: string(),
@@ -19560,7 +19665,23 @@ var TerminalOutputBatchSchema = object({
19560
19665
  method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }), method(_void(), array(TerminalInstanceInfoSchema).readonly(), { auth: "admin" }), method(object({
19561
19666
  targetNodeId: string().min(1),
19562
19667
  profileId: string().min(1),
19563
- name: string().trim().min(1).max(160).optional()
19668
+ name: string().trim().min(1).max(160).optional(),
19669
+ executable: string().max(1024).optional(),
19670
+ args: array(string().max(2048)).max(64).optional(),
19671
+ cwd: string().max(1024).optional(),
19672
+ environment: array(string().max(4096)).max(64).optional(),
19673
+ profileSettings: ProfileSettingsBagSchema.optional()
19674
+ }), TerminalInstanceInfoSchema, {
19675
+ kind: "mutation",
19676
+ auth: "admin"
19677
+ }), method(object({
19678
+ instanceId: string().min(1),
19679
+ name: string().trim().min(1).max(160).optional(),
19680
+ executable: string().max(1024).optional(),
19681
+ args: array(string().max(2048)).max(64).optional(),
19682
+ cwd: string().max(1024).optional(),
19683
+ environment: array(string().max(4096)).max(64).optional(),
19684
+ profileSettings: ProfileSettingsBagSchema.optional()
19564
19685
  }), TerminalInstanceInfoSchema, {
19565
19686
  kind: "mutation",
19566
19687
  auth: "admin"
@@ -19582,7 +19703,11 @@ method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }),
19582
19703
  }), method(_void(), array(TerminalSessionInfoSchema).readonly(), { auth: "admin" }), method(object({
19583
19704
  profileId: string(),
19584
19705
  cols: number().int().positive(),
19585
- rows: number().int().positive()
19706
+ rows: number().int().positive(),
19707
+ executable: string().max(1024).optional(),
19708
+ args: array(string().max(2048)).max(64).optional(),
19709
+ cwd: string().max(1024).optional(),
19710
+ environment: array(string().max(4096)).max(64).optional()
19586
19711
  }), TerminalSessionInfoSchema, {
19587
19712
  kind: "mutation",
19588
19713
  auth: "admin"
@@ -22387,10 +22512,10 @@ DeviceType.LawnMower, method(object({ deviceId: number().int().nonnegative() }),
22387
22512
  *
22388
22513
  * • The SDK (mobile / web client) consumes `getConnectionEndpoints()`
22389
22514
  * to receive an ordered list of candidate base URLs it should race
22390
- * on connect — LAN IPv4 first (lowest latency when on same network),
22391
- * then public hostname (if a tunnel is up), then IPv6. The SDK can
22392
- * race them with short timeouts and stick with the winner for the
22393
- * session.
22515
+ * on connect — LAN IPv4 and stable LAN IPv6 first (lowest latency
22516
+ * when on the same network), then public hostname (if a tunnel is
22517
+ * up). The SDK can race them with short timeouts and stick with the
22518
+ * winner for the session.
22394
22519
  *
22395
22520
  * Why hub-only: agents are not directly addressable by the operator's
22396
22521
  * clients — they reverse-connect to the hub. Exposing their interfaces
@@ -22545,6 +22670,17 @@ var NotificationEndpointSchema = object({
22545
22670
  /** What the ranking currently resolves to (null when nothing is reachable). */
22546
22671
  resolved: string().nullable()
22547
22672
  });
22673
+ /**
22674
+ * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
22675
+ * AUTO (every LAN IPv4 + the public tunnel). `resolved` is what that choice
22676
+ * currently expands to, so the UI can show the effective set either way.
22677
+ */
22678
+ var ViewerEndpointsSchema = object({
22679
+ /** The operator's explicit race set, or empty for AUTO. */
22680
+ baseUrls: array(string()).readonly(),
22681
+ /** What the ranking currently resolves to (may be empty if nothing is up). */
22682
+ resolved: array(string()).readonly()
22683
+ });
22548
22684
  var AllowedAddressesSchema = object({
22549
22685
  /**
22550
22686
  * Allowlist of interface addresses operators have explicitly opted
@@ -22553,6 +22689,20 @@ var AllowedAddressesSchema = object({
22553
22689
  * Network Addresses admin page and persisted by the addon.
22554
22690
  */
22555
22691
  addresses: array(string()).readonly() });
22692
+ var TlsStatusSchema = object({
22693
+ mode: _enum([
22694
+ "generated",
22695
+ "uploaded",
22696
+ "disabled"
22697
+ ]),
22698
+ leafFingerprintSha256: string().nullable(),
22699
+ caFingerprintSha256: string().nullable(),
22700
+ validTo: string().nullable(),
22701
+ sans: array(string()),
22702
+ caCertPem: string().nullable(),
22703
+ reissueError: string().nullable(),
22704
+ restartRequired: boolean()
22705
+ });
22556
22706
  method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
22557
22707
  /**
22558
22708
  * LEGACY HINT — do not send from new code. Kept optional so clients
@@ -22562,17 +22712,31 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
22562
22712
  */
22563
22713
  port: number().int().min(1).max(65535).optional(),
22564
22714
  /** Include `http(s)://127.0.0.1:<port>` as the lowest-priority
22565
- * candidate. Default `true`. */
22715
+ * candidate. Default `false` — loopback is not a client route. */
22566
22716
  includeLoopback: boolean().optional(),
22567
- /** Skip IPv6 entries. Some legacy clients can't parse them.
22568
- * Default `false`. */
22717
+ /** Skip IPv6 entries. Default `false` the palette includes stable
22718
+ * LAN IPv6 (ICE/WebRTC uses dual-stack regardless). Pass `true` to
22719
+ * hide them. The viewer HTTP/WS race is `getViewerEndpoints`. */
22569
22720
  ipv4Only: boolean().optional(),
22570
22721
  /** Scheme to emit for LAN/loopback URLs. Default `'http'`.
22571
22722
  * Pass `'https'` when the caller is itself loaded over HTTPS
22572
22723
  * to avoid mixed-content blocks in the browser. The public
22573
22724
  * tunnel always emits `https://` regardless. */
22574
22725
  scheme: _enum(["http", "https"]).optional()
22575
- }), 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" });
22726
+ }), 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, {
22727
+ kind: "mutation",
22728
+ auth: "admin"
22729
+ }), method(object({
22730
+ certPem: string().min(1),
22731
+ keyPem: string().min(1),
22732
+ caPem: string().optional()
22733
+ }), TlsStatusSchema, {
22734
+ kind: "mutation",
22735
+ auth: "admin"
22736
+ }), method(_void(), object({ pem: string() })), method(_void(), TlsStatusSchema, {
22737
+ kind: "mutation",
22738
+ auth: "admin"
22739
+ });
22576
22740
  object({
22577
22741
  /** Lifecycle state of the lock. `jammed` means the motor reported
22578
22742
  * failure to reach the target — operator intervention required. */
@@ -28335,6 +28499,12 @@ Object.freeze({
28335
28499
  addonId: null,
28336
28500
  access: "create"
28337
28501
  },
28502
+ "localNetwork.downloadCa": {
28503
+ capName: "local-network",
28504
+ capScope: "system",
28505
+ addonId: null,
28506
+ access: "view"
28507
+ },
28338
28508
  "localNetwork.getAllowedAddresses": {
28339
28509
  capName: "local-network",
28340
28510
  capScope: "system",
@@ -28359,18 +28529,42 @@ Object.freeze({
28359
28529
  addonId: null,
28360
28530
  access: "view"
28361
28531
  },
28532
+ "localNetwork.getTlsStatus": {
28533
+ capName: "local-network",
28534
+ capScope: "system",
28535
+ addonId: null,
28536
+ access: "view"
28537
+ },
28538
+ "localNetwork.getViewerEndpoints": {
28539
+ capName: "local-network",
28540
+ capScope: "system",
28541
+ addonId: null,
28542
+ access: "view"
28543
+ },
28362
28544
  "localNetwork.list": {
28363
28545
  capName: "local-network",
28364
28546
  capScope: "system",
28365
28547
  addonId: null,
28366
28548
  access: "view"
28367
28549
  },
28550
+ "localNetwork.regenerateCertificate": {
28551
+ capName: "local-network",
28552
+ capScope: "system",
28553
+ addonId: null,
28554
+ access: "create"
28555
+ },
28368
28556
  "localNetwork.resetAllowlistToBestMatch": {
28369
28557
  capName: "local-network",
28370
28558
  capScope: "system",
28371
28559
  addonId: null,
28372
28560
  access: "delete"
28373
28561
  },
28562
+ "localNetwork.revertToGeneratedCertificate": {
28563
+ capName: "local-network",
28564
+ capScope: "system",
28565
+ addonId: null,
28566
+ access: "create"
28567
+ },
28374
28568
  "localNetwork.setAllowedAddresses": {
28375
28569
  capName: "local-network",
28376
28570
  capScope: "system",
@@ -28383,6 +28577,18 @@ Object.freeze({
28383
28577
  addonId: null,
28384
28578
  access: "create"
28385
28579
  },
28580
+ "localNetwork.setViewerEndpoints": {
28581
+ capName: "local-network",
28582
+ capScope: "system",
28583
+ addonId: null,
28584
+ access: "create"
28585
+ },
28586
+ "localNetwork.uploadCertificate": {
28587
+ capName: "local-network",
28588
+ capScope: "system",
28589
+ addonId: null,
28590
+ access: "create"
28591
+ },
28386
28592
  "lockControl.lock": {
28387
28593
  capName: "lock-control",
28388
28594
  capScope: "device",
@@ -31263,6 +31469,12 @@ Object.freeze({
31263
31469
  addonId: null,
31264
31470
  access: "create"
31265
31471
  },
31472
+ "terminalSession.updateInstance": {
31473
+ capName: "terminal-session",
31474
+ capScope: "system",
31475
+ addonId: null,
31476
+ access: "create"
31477
+ },
31266
31478
  "terminalSession.writeInput": {
31267
31479
  capName: "terminal-session",
31268
31480
  capScope: "system",
@@ -33750,6 +33962,35 @@ Object.freeze(Object.fromEntries([{
33750
33962
  }]
33751
33963
  }].map((s) => [s.stepId, s.defaultModelId])));
33752
33964
  string().min(1);
33965
+ var CLUSTER_STEP_SETTING_FIELDS = [{
33966
+ stepId: "face-embedding",
33967
+ key: "minLandmarkFaceSize",
33968
+ label: "Min face size for recognition (detection px)",
33969
+ 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.",
33970
+ type: "slider",
33971
+ min: 0,
33972
+ max: 64,
33973
+ step: 2,
33974
+ default: 24
33975
+ }];
33976
+ function clusterStepSettingKey(stepId, fieldKey) {
33977
+ return `clusterStepSetting:${stepId}:${fieldKey}`;
33978
+ }
33979
+ var ClusterSettingNumberSchema = number().finite();
33980
+ function readClusterStepSettings(config) {
33981
+ const out = {};
33982
+ for (const field of CLUSTER_STEP_SETTING_FIELDS) {
33983
+ const parsed = ClusterSettingNumberSchema.safeParse(config[clusterStepSettingKey(field.stepId, field.key)]);
33984
+ const value = parsed.success ? parsed.data : field.default;
33985
+ const existing = out[field.stepId] ?? {};
33986
+ out[field.stepId] = {
33987
+ ...existing,
33988
+ [field.key]: value
33989
+ };
33990
+ }
33991
+ return out;
33992
+ }
33993
+ readClusterStepSettings({});
33753
33994
  object({
33754
33995
  /**
33755
33996
  * Fraction of the box's own size added on EACH side before cutting.
@@ -1,4 +1,4 @@
1
- //#region ../types/dist/event-category-XfKNtfCc.mjs
1
+ //#region ../types/dist/event-category-CIa_iT6b.mjs
2
2
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
3
3
  EventCategory["SystemBoot"] = "system.boot";
4
4
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -14,6 +14,15 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
14
14
  */
15
15
  EventCategory["SystemRestartCompleted"] = "system.restart-completed";
16
16
  /**
17
+ * The hub reissued its own TLS certificate at boot (`ensureTlsCert`).
18
+ * Emitted only when the material on disk actually changed, so an
19
+ * operator who trusted the old certificate by hand is told rather than
20
+ * discovering it as a browser error. Payload `TlsCertChangedPayload`.
21
+ *
22
+ * Rule: docs/decisions/adr-0227-*.md
23
+ */
24
+ EventCategory["SystemTlsCertChanged"] = "system.tls-cert-changed";
25
+ /**
17
26
  * A newer addon or server-root package version was found by the
18
27
  * authoritative registry check. Emitted once when any observed
19
28
  * `latestVersion` changes (or a package/node first appears behind);
@@ -7994,6 +8003,15 @@ var LabelDefinitionSchema = object({
7994
8003
  description: string().optional(),
7995
8004
  icon: string().optional()
7996
8005
  });
8006
+ var ClassMapDefinitionSchema = object({
8007
+ mapping: record(string(), _enum([
8008
+ "person",
8009
+ "vehicle",
8010
+ "animal",
8011
+ "package"
8012
+ ])),
8013
+ preserveOriginal: boolean()
8014
+ });
7997
8015
  var MODEL_FORMATS = [
7998
8016
  "onnx",
7999
8017
  "coreml",
@@ -8172,7 +8190,13 @@ var ModelCatalogEntrySchema = object({
8172
8190
  * `id` stays the source of truth for resolution/download/persistence; grouping
8173
8191
  * is a presentation overlay resolved back to an `id`.
8174
8192
  */
8175
- group: ModelVariantGroupSchema.optional()
8193
+ group: ModelVariantGroupSchema.optional(),
8194
+ /**
8195
+ * Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
8196
+ * applies (Frigate / COCO public catalog). Set on a custom model whose raw
8197
+ * labels already ARE the CamStack macros (Scrypted identity map).
8198
+ */
8199
+ classMap: ClassMapDefinitionSchema.optional()
8176
8200
  });
8177
8201
  var ConvertTargetSchema = discriminatedUnion("format", [object({
8178
8202
  format: literal("openvino"),
@@ -8201,7 +8225,8 @@ var ModelConvertMetadataSchema = object({
8201
8225
  "ocr",
8202
8226
  "segmentation"
8203
8227
  ]),
8204
- faceAlignment: boolean().optional()
8228
+ faceAlignment: boolean().optional(),
8229
+ classMap: ClassMapDefinitionSchema.optional()
8205
8230
  });
8206
8231
  var ConvertResultSchema = object({
8207
8232
  entry: ModelCatalogEntrySchema,
@@ -17192,6 +17217,33 @@ var NativeCropRefSchema = object({
17192
17217
  h: number()
17193
17218
  })
17194
17219
  });
17220
+ object({
17221
+ crop: object({
17222
+ left: number(),
17223
+ top: number(),
17224
+ width: number().positive(),
17225
+ height: number().positive()
17226
+ }).optional(),
17227
+ content: object({
17228
+ width: number().int().positive(),
17229
+ height: number().int().positive()
17230
+ }),
17231
+ fit: _enum(["stretch", "contain"]),
17232
+ format: _enum([
17233
+ "rgb",
17234
+ "gray",
17235
+ "jpeg"
17236
+ ])
17237
+ });
17238
+ var FrameRefSchema = object({
17239
+ registryId: string().min(1),
17240
+ id: string().min(1),
17241
+ width: number().int().positive(),
17242
+ height: number().int().positive(),
17243
+ format: _enum(["rgb", "gray"]),
17244
+ timestamp: number(),
17245
+ capturedAt: number().optional()
17246
+ });
17195
17247
  var ModelFormatSchema$1 = _enum([
17196
17248
  "onnx",
17197
17249
  "coreml",
@@ -17436,6 +17488,12 @@ method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngi
17436
17488
  steps: array(PipelineStepInputSchema).min(1),
17437
17489
  frame: FrameInputSchema.optional(),
17438
17490
  /**
17491
+ * Process-local lazy frame. Valid only when caller and provider resolve
17492
+ * in the same execution-group process; split/cross-node callers use
17493
+ * `frame`/`image` inline compatibility instead.
17494
+ */
17495
+ frameRef: FrameRefSchema.optional(),
17496
+ /**
17439
17497
  * CB5 shm passthrough — a `FrameHandle` naming the same ring slot
17440
17498
  * the decoded pixels live in. One more member of the one-of
17441
17499
  * frame/frameHandle/image/imageBase64/referenceImage group.
@@ -17691,7 +17749,10 @@ var NativeCropResultSchema = object({
17691
17749
  * Which source served this crop, so a quality-sensitive consumer (the native
17692
17750
  * `keyFrame`) can reject a degraded fallback:
17693
17751
  * - `native` — cut from the decode worker's retained NATIVE surface (the
17694
- * quality path).
17752
+ * quality path). A subject-tile serve is also native-resolution and stays
17753
+ * `native` here: the public enum cannot name `tile` without a breaking cap
17754
+ * change. Runner telemetry distinguishes lease vs tile via `source` on the
17755
+ * internal crop result (`nativeHits` vs `tileHits`).
17695
17756
  * - `ram-fullframe` — the native surface MISSED but the request was full-frame,
17696
17757
  * so the ≤640 RAM `RetainedFrameStore` served it (honest lower-res; legit for
17697
17758
  * the blank-frame guard / 640-snapshot resolve, NOT for the clean keyFrame).
@@ -18182,12 +18243,41 @@ var RunnerLocalLoadSchema = object({
18182
18243
  * legacy `OrchestratorMetricsSchema` shape so existing dashboards keep
18183
18244
  * working unchanged when they switch to reading from the runner cap.
18184
18245
  */
18246
+ var FrameLazyCountersSchema = object({
18247
+ framesDecoded: number(),
18248
+ framesAdmitted: number(),
18249
+ framesDroppedPixelFree: number(),
18250
+ viewsMaterialized: number(),
18251
+ viewsSkipped: number(),
18252
+ workerToRunnerBytes: number(),
18253
+ runnerToPoolRawBytes: number(),
18254
+ runnerToPoolJpegBytes: number(),
18255
+ onDemandFullFrameRequests: number(),
18256
+ onDemandCropRequests: number(),
18257
+ nativeHits: number(),
18258
+ nativeMisses: number(),
18259
+ tileHits: number(),
18260
+ tileMisses: number(),
18261
+ fallbackHits: number(),
18262
+ fallbackMisses: number(),
18263
+ retainedWritesAvoided: number(),
18264
+ residentRefs: number(),
18265
+ residentBytes: number(),
18266
+ releases: number(),
18267
+ evictions: number(),
18268
+ staleMisses: number()
18269
+ });
18270
+ var FrameLazyMetricsSchema = object({
18271
+ node: FrameLazyCountersSchema,
18272
+ cameras: array(FrameLazyCountersSchema.extend({ deviceId: number() }))
18273
+ });
18185
18274
  var RunnerLocalMetricsSchema = object({
18186
18275
  nodeId: string(),
18187
18276
  activeCameras: number(),
18188
18277
  throttledCameras: number(),
18189
18278
  avgInferenceTimeMs: number(),
18190
- queueDepth: number()
18279
+ queueDepth: number(),
18280
+ frameLazy: FrameLazyMetricsSchema.optional()
18191
18281
  });
18192
18282
  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({
18193
18283
  handle: FrameHandleSchema,
@@ -19487,6 +19577,9 @@ method(_void(), ProviderInfoSchema), method(object({ config: record(string(), un
19487
19577
  location: StorageLocationSchema,
19488
19578
  relativePath: string()
19489
19579
  }), _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" });
19580
+ /** Profile-exported FormBuilder schema. Shape is ConfigUISchema at the UI. */
19581
+ var ProfileSettingsSchemaBridge = unknown().nullable();
19582
+ var ProfileSettingsBagSchema = record(string(), unknown());
19490
19583
  /**
19491
19584
  * A live terminal session hosted by the provider addon. Output and input do
19492
19585
  * NOT flow through the capability — they use the addon data plane
@@ -19516,7 +19609,14 @@ var TerminalSessionInfoSchema = object({
19516
19609
  var TerminalProfileInfoSchema = object({
19517
19610
  profileId: string(),
19518
19611
  label: string(),
19519
- description: string().optional()
19612
+ description: string().optional(),
19613
+ /** Spawn defaults the instance form copies on create. */
19614
+ executable: string().optional(),
19615
+ args: array(string()).readonly().optional(),
19616
+ cwd: string().optional(),
19617
+ environment: array(string()).readonly().optional(),
19618
+ /** ConfigUISchema for instance knobs, or null when the profile has none. */
19619
+ settingsSchema: ProfileSettingsSchemaBridge.optional()
19520
19620
  });
19521
19621
  /**
19522
19622
  * A durable operator-created Terminal instance. Profiles are templates; only
@@ -19529,7 +19629,12 @@ var TerminalInstanceInfoSchema = object({
19529
19629
  profileId: string(),
19530
19630
  profileLabel: string(),
19531
19631
  name: string(),
19532
- enabled: boolean()
19632
+ enabled: boolean(),
19633
+ executable: string(),
19634
+ args: array(string()).readonly(),
19635
+ cwd: string(),
19636
+ environment: array(string()).readonly(),
19637
+ profileSettings: ProfileSettingsBagSchema
19533
19638
  });
19534
19639
  var TerminalLegacyCameraSchema = object({
19535
19640
  stableId: string(),
@@ -19559,7 +19664,23 @@ var TerminalOutputBatchSchema = object({
19559
19664
  method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }), method(_void(), array(TerminalInstanceInfoSchema).readonly(), { auth: "admin" }), method(object({
19560
19665
  targetNodeId: string().min(1),
19561
19666
  profileId: string().min(1),
19562
- name: string().trim().min(1).max(160).optional()
19667
+ name: string().trim().min(1).max(160).optional(),
19668
+ executable: string().max(1024).optional(),
19669
+ args: array(string().max(2048)).max(64).optional(),
19670
+ cwd: string().max(1024).optional(),
19671
+ environment: array(string().max(4096)).max(64).optional(),
19672
+ profileSettings: ProfileSettingsBagSchema.optional()
19673
+ }), TerminalInstanceInfoSchema, {
19674
+ kind: "mutation",
19675
+ auth: "admin"
19676
+ }), method(object({
19677
+ instanceId: string().min(1),
19678
+ name: string().trim().min(1).max(160).optional(),
19679
+ executable: string().max(1024).optional(),
19680
+ args: array(string().max(2048)).max(64).optional(),
19681
+ cwd: string().max(1024).optional(),
19682
+ environment: array(string().max(4096)).max(64).optional(),
19683
+ profileSettings: ProfileSettingsBagSchema.optional()
19563
19684
  }), TerminalInstanceInfoSchema, {
19564
19685
  kind: "mutation",
19565
19686
  auth: "admin"
@@ -19581,7 +19702,11 @@ method(_void(), array(TerminalProfileInfoSchema).readonly(), { auth: "admin" }),
19581
19702
  }), method(_void(), array(TerminalSessionInfoSchema).readonly(), { auth: "admin" }), method(object({
19582
19703
  profileId: string(),
19583
19704
  cols: number().int().positive(),
19584
- rows: number().int().positive()
19705
+ rows: number().int().positive(),
19706
+ executable: string().max(1024).optional(),
19707
+ args: array(string().max(2048)).max(64).optional(),
19708
+ cwd: string().max(1024).optional(),
19709
+ environment: array(string().max(4096)).max(64).optional()
19585
19710
  }), TerminalSessionInfoSchema, {
19586
19711
  kind: "mutation",
19587
19712
  auth: "admin"
@@ -22386,10 +22511,10 @@ DeviceType.LawnMower, method(object({ deviceId: number().int().nonnegative() }),
22386
22511
  *
22387
22512
  * • The SDK (mobile / web client) consumes `getConnectionEndpoints()`
22388
22513
  * to receive an ordered list of candidate base URLs it should race
22389
- * on connect — LAN IPv4 first (lowest latency when on same network),
22390
- * then public hostname (if a tunnel is up), then IPv6. The SDK can
22391
- * race them with short timeouts and stick with the winner for the
22392
- * session.
22514
+ * on connect — LAN IPv4 and stable LAN IPv6 first (lowest latency
22515
+ * when on the same network), then public hostname (if a tunnel is
22516
+ * up). The SDK can race them with short timeouts and stick with the
22517
+ * winner for the session.
22393
22518
  *
22394
22519
  * Why hub-only: agents are not directly addressable by the operator's
22395
22520
  * clients — they reverse-connect to the hub. Exposing their interfaces
@@ -22544,6 +22669,17 @@ var NotificationEndpointSchema = object({
22544
22669
  /** What the ranking currently resolves to (null when nothing is reachable). */
22545
22670
  resolved: string().nullable()
22546
22671
  });
22672
+ /**
22673
+ * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
22674
+ * AUTO (every LAN IPv4 + the public tunnel). `resolved` is what that choice
22675
+ * currently expands to, so the UI can show the effective set either way.
22676
+ */
22677
+ var ViewerEndpointsSchema = object({
22678
+ /** The operator's explicit race set, or empty for AUTO. */
22679
+ baseUrls: array(string()).readonly(),
22680
+ /** What the ranking currently resolves to (may be empty if nothing is up). */
22681
+ resolved: array(string()).readonly()
22682
+ });
22547
22683
  var AllowedAddressesSchema = object({
22548
22684
  /**
22549
22685
  * Allowlist of interface addresses operators have explicitly opted
@@ -22552,6 +22688,20 @@ var AllowedAddressesSchema = object({
22552
22688
  * Network Addresses admin page and persisted by the addon.
22553
22689
  */
22554
22690
  addresses: array(string()).readonly() });
22691
+ var TlsStatusSchema = object({
22692
+ mode: _enum([
22693
+ "generated",
22694
+ "uploaded",
22695
+ "disabled"
22696
+ ]),
22697
+ leafFingerprintSha256: string().nullable(),
22698
+ caFingerprintSha256: string().nullable(),
22699
+ validTo: string().nullable(),
22700
+ sans: array(string()),
22701
+ caCertPem: string().nullable(),
22702
+ reissueError: string().nullable(),
22703
+ restartRequired: boolean()
22704
+ });
22555
22705
  method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(object({
22556
22706
  /**
22557
22707
  * LEGACY HINT — do not send from new code. Kept optional so clients
@@ -22561,17 +22711,31 @@ method(_void(), ListResultSchema), method(_void(), PreferredSchema), method(obje
22561
22711
  */
22562
22712
  port: number().int().min(1).max(65535).optional(),
22563
22713
  /** Include `http(s)://127.0.0.1:<port>` as the lowest-priority
22564
- * candidate. Default `true`. */
22714
+ * candidate. Default `false` — loopback is not a client route. */
22565
22715
  includeLoopback: boolean().optional(),
22566
- /** Skip IPv6 entries. Some legacy clients can't parse them.
22567
- * Default `false`. */
22716
+ /** Skip IPv6 entries. Default `false` the palette includes stable
22717
+ * LAN IPv6 (ICE/WebRTC uses dual-stack regardless). Pass `true` to
22718
+ * hide them. The viewer HTTP/WS race is `getViewerEndpoints`. */
22568
22719
  ipv4Only: boolean().optional(),
22569
22720
  /** Scheme to emit for LAN/loopback URLs. Default `'http'`.
22570
22721
  * Pass `'https'` when the caller is itself loaded over HTTPS
22571
22722
  * to avoid mixed-content blocks in the browser. The public
22572
22723
  * tunnel always emits `https://` regardless. */
22573
22724
  scheme: _enum(["http", "https"]).optional()
22574
- }), 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" });
22725
+ }), 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, {
22726
+ kind: "mutation",
22727
+ auth: "admin"
22728
+ }), method(object({
22729
+ certPem: string().min(1),
22730
+ keyPem: string().min(1),
22731
+ caPem: string().optional()
22732
+ }), TlsStatusSchema, {
22733
+ kind: "mutation",
22734
+ auth: "admin"
22735
+ }), method(_void(), object({ pem: string() })), method(_void(), TlsStatusSchema, {
22736
+ kind: "mutation",
22737
+ auth: "admin"
22738
+ });
22575
22739
  object({
22576
22740
  /** Lifecycle state of the lock. `jammed` means the motor reported
22577
22741
  * failure to reach the target — operator intervention required. */
@@ -28334,6 +28498,12 @@ Object.freeze({
28334
28498
  addonId: null,
28335
28499
  access: "create"
28336
28500
  },
28501
+ "localNetwork.downloadCa": {
28502
+ capName: "local-network",
28503
+ capScope: "system",
28504
+ addonId: null,
28505
+ access: "view"
28506
+ },
28337
28507
  "localNetwork.getAllowedAddresses": {
28338
28508
  capName: "local-network",
28339
28509
  capScope: "system",
@@ -28358,18 +28528,42 @@ Object.freeze({
28358
28528
  addonId: null,
28359
28529
  access: "view"
28360
28530
  },
28531
+ "localNetwork.getTlsStatus": {
28532
+ capName: "local-network",
28533
+ capScope: "system",
28534
+ addonId: null,
28535
+ access: "view"
28536
+ },
28537
+ "localNetwork.getViewerEndpoints": {
28538
+ capName: "local-network",
28539
+ capScope: "system",
28540
+ addonId: null,
28541
+ access: "view"
28542
+ },
28361
28543
  "localNetwork.list": {
28362
28544
  capName: "local-network",
28363
28545
  capScope: "system",
28364
28546
  addonId: null,
28365
28547
  access: "view"
28366
28548
  },
28549
+ "localNetwork.regenerateCertificate": {
28550
+ capName: "local-network",
28551
+ capScope: "system",
28552
+ addonId: null,
28553
+ access: "create"
28554
+ },
28367
28555
  "localNetwork.resetAllowlistToBestMatch": {
28368
28556
  capName: "local-network",
28369
28557
  capScope: "system",
28370
28558
  addonId: null,
28371
28559
  access: "delete"
28372
28560
  },
28561
+ "localNetwork.revertToGeneratedCertificate": {
28562
+ capName: "local-network",
28563
+ capScope: "system",
28564
+ addonId: null,
28565
+ access: "create"
28566
+ },
28373
28567
  "localNetwork.setAllowedAddresses": {
28374
28568
  capName: "local-network",
28375
28569
  capScope: "system",
@@ -28382,6 +28576,18 @@ Object.freeze({
28382
28576
  addonId: null,
28383
28577
  access: "create"
28384
28578
  },
28579
+ "localNetwork.setViewerEndpoints": {
28580
+ capName: "local-network",
28581
+ capScope: "system",
28582
+ addonId: null,
28583
+ access: "create"
28584
+ },
28585
+ "localNetwork.uploadCertificate": {
28586
+ capName: "local-network",
28587
+ capScope: "system",
28588
+ addonId: null,
28589
+ access: "create"
28590
+ },
28385
28591
  "lockControl.lock": {
28386
28592
  capName: "lock-control",
28387
28593
  capScope: "device",
@@ -31262,6 +31468,12 @@ Object.freeze({
31262
31468
  addonId: null,
31263
31469
  access: "create"
31264
31470
  },
31471
+ "terminalSession.updateInstance": {
31472
+ capName: "terminal-session",
31473
+ capScope: "system",
31474
+ addonId: null,
31475
+ access: "create"
31476
+ },
31265
31477
  "terminalSession.writeInput": {
31266
31478
  capName: "terminal-session",
31267
31479
  capScope: "system",
@@ -33749,6 +33961,35 @@ Object.freeze(Object.fromEntries([{
33749
33961
  }]
33750
33962
  }].map((s) => [s.stepId, s.defaultModelId])));
33751
33963
  string().min(1);
33964
+ var CLUSTER_STEP_SETTING_FIELDS = [{
33965
+ stepId: "face-embedding",
33966
+ key: "minLandmarkFaceSize",
33967
+ label: "Min face size for recognition (detection px)",
33968
+ 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.",
33969
+ type: "slider",
33970
+ min: 0,
33971
+ max: 64,
33972
+ step: 2,
33973
+ default: 24
33974
+ }];
33975
+ function clusterStepSettingKey(stepId, fieldKey) {
33976
+ return `clusterStepSetting:${stepId}:${fieldKey}`;
33977
+ }
33978
+ var ClusterSettingNumberSchema = number().finite();
33979
+ function readClusterStepSettings(config) {
33980
+ const out = {};
33981
+ for (const field of CLUSTER_STEP_SETTING_FIELDS) {
33982
+ const parsed = ClusterSettingNumberSchema.safeParse(config[clusterStepSettingKey(field.stepId, field.key)]);
33983
+ const value = parsed.success ? parsed.data : field.default;
33984
+ const existing = out[field.stepId] ?? {};
33985
+ out[field.stepId] = {
33986
+ ...existing,
33987
+ [field.key]: value
33988
+ };
33989
+ }
33990
+ return out;
33991
+ }
33992
+ readClusterStepSettings({});
33752
33993
  object({
33753
33994
  /**
33754
33995
  * 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-static-turn",
3
- "version": "1.2.24",
3
+ "version": "1.2.26",
4
4
  "description": "Static / self-hosted (coturn) TURN provider for CamStack",
5
5
  "keywords": [
6
6
  "camstack",