@camstack/types 1.2.98 → 1.2.100

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 (33) hide show
  1. package/dist/capabilities/alerts.cap.d.ts +5 -5
  2. package/dist/capabilities/custom-model-registry.cap.d.ts +18 -0
  3. package/dist/capabilities/decoder.cap.d.ts +12 -12
  4. package/dist/capabilities/index.d.ts +1 -1
  5. package/dist/capabilities/local-network.cap.d.ts +38 -7
  6. package/dist/capabilities/model-convert.cap.d.ts +27 -0
  7. package/dist/capabilities/model-distributor.cap.d.ts +18 -0
  8. package/dist/capabilities/motion-detection.cap.d.ts +4 -4
  9. package/dist/capabilities/native-object-detection.cap.d.ts +15 -15
  10. package/dist/capabilities/notification-rules.cap.d.ts +35 -8
  11. package/dist/capabilities/osd-manager.cap.d.ts +13 -1
  12. package/dist/capabilities/pipeline-analytics.cap.d.ts +13 -10
  13. package/dist/capabilities/pipeline-executor.cap.d.ts +16 -12
  14. package/dist/capabilities/pipeline-runner.cap.d.ts +182 -5
  15. package/dist/capabilities/schemas/detection-shared.d.ts +4 -4
  16. package/dist/capabilities/schemas/streaming-shared.d.ts +6 -6
  17. package/dist/capabilities/stream-broker.cap.d.ts +3 -3
  18. package/dist/capabilities/zone-rules.cap.d.ts +3 -3
  19. package/dist/generated/addon-api.d.ts +14 -0
  20. package/dist/generated/method-access-map.d.ts +1 -1
  21. package/dist/generated/system-proxy.d.ts +1 -1
  22. package/dist/index.d.ts +2 -1
  23. package/dist/index.js +191 -25
  24. package/dist/index.mjs +182 -26
  25. package/dist/interfaces/pipeline-executor-capability.d.ts +3 -0
  26. package/dist/interfaces/pipeline-runner-capability.d.ts +31 -0
  27. package/dist/interfaces/stream-broker.d.ts +5 -2
  28. package/dist/notification/audio-condition.d.ts +19 -4
  29. package/dist/types/frame-view.d.ts +52 -0
  30. package/dist/types/io.d.ts +3 -0
  31. package/dist/types/labels.d.ts +11 -0
  32. package/dist/types/models.d.ts +27 -0
  33. package/package.json +1 -1
@@ -3592,6 +3592,20 @@ export type AppRouter = TrpcCoreRouter<{
3592
3592
  output: z.infer<typeof localNetworkCapability.methods.setNotificationEndpoint.output>;
3593
3593
  meta: object;
3594
3594
  }>;
3595
+ getViewerEndpoints: TRPCQueryProcedure<{
3596
+ input: {
3597
+ nodeId?: string | undefined;
3598
+ } | undefined;
3599
+ output: z.infer<typeof localNetworkCapability.methods.getViewerEndpoints.output>;
3600
+ meta: object;
3601
+ }>;
3602
+ setViewerEndpoints: TRPCMutationProcedure<{
3603
+ input: {
3604
+ [x: string]: unknown;
3605
+ } & z.input<typeof localNetworkCapability.methods.setViewerEndpoints.input>;
3606
+ output: z.infer<typeof localNetworkCapability.methods.setViewerEndpoints.output>;
3607
+ meta: object;
3608
+ }>;
3595
3609
  getAllowedAddresses: TRPCQueryProcedure<{
3596
3610
  input: {
3597
3611
  nodeId?: string | undefined;
@@ -6,7 +6,7 @@
6
6
  * scope+access check inside `protectedProcedure` (see
7
7
  * `server/backend/src/api/trpc/trpc.middleware.ts`).
8
8
  *
9
- * Coverage: 949 method paths across 123 capabilities.
9
+ * Coverage: 951 method paths across 123 capabilities.
10
10
  */
11
11
  import type { CapabilityMethodAccess } from '../capabilities/capability-definition.js';
12
12
  export interface MethodAccessRecord {
@@ -74,7 +74,7 @@ export interface SystemProxy {
74
74
  readonly faceGallery: Pick<InferProvider<typeof faceGalleryCapability>, 'listIdentities' | 'createIdentity' | 'renameIdentity' | 'deleteIdentity' | 'listIdentitySamples' | 'removeSample' | 'getFaceMedia' | 'assignFace' | 'unassignFace' | 'deleteFace' | 'assignFaces' | 'unassignFaces' | 'suggestFaceClusters'>;
75
75
  readonly integrations: Pick<InferProvider<typeof integrationsCapability>, 'list' | 'get' | 'getByAddonId' | 'create' | 'update' | 'delete' | 'getSettings' | 'setSettings' | 'getAvailableTypes' | 'testConnection'>;
76
76
  readonly llm: Pick<InferProvider<typeof llmCapability>, 'generate' | 'generateVision' | 'cancel' | 'listProfileKinds' | 'listProfiles' | 'upsertProfile' | 'deleteProfile' | 'testProfile' | 'listModels' | 'getDefaults' | 'setDefault' | 'getUsage' | 'listModelCatalog' | 'listRuntimeNodes' | 'listNodeModels' | 'resolveModelRef' | 'installModel' | 'deleteModel' | 'getRuntimeStatus' | 'startRuntime' | 'stopRuntime'>;
77
- readonly localNetwork: Pick<InferProvider<typeof localNetworkCapability>, 'list' | 'getPreferred' | 'getConnectionEndpoints' | 'getNotificationEndpoint' | 'setNotificationEndpoint' | 'getAllowedAddresses' | 'setAllowedAddresses' | 'resetAllowlistToBestMatch' | 'getTlsStatus' | 'regenerateCertificate' | 'uploadCertificate' | 'downloadCa' | 'revertToGeneratedCertificate'>;
77
+ readonly localNetwork: Pick<InferProvider<typeof localNetworkCapability>, 'list' | 'getPreferred' | 'getConnectionEndpoints' | 'getNotificationEndpoint' | 'setNotificationEndpoint' | 'getViewerEndpoints' | 'setViewerEndpoints' | 'getAllowedAddresses' | 'setAllowedAddresses' | 'resetAllowlistToBestMatch' | 'getTlsStatus' | 'regenerateCertificate' | 'uploadCertificate' | 'downloadCa' | 'revertToGeneratedCertificate'>;
78
78
  readonly meshNetwork: Pick<InferProvider<typeof meshNetworkCapability>, 'getStatus' | 'join' | 'startLogin' | 'leave' | 'logout' | 'listPeers' | 'testConnection'>;
79
79
  readonly metricsProvider: Pick<InferProvider<typeof metricsProviderCapability>, 'collectSnapshot' | 'getCached' | 'getCurrent' | 'getDiskSpace' | 'getGpuInfo' | 'getCpuTemperature' | 'getProcessStats' | 'listAddonInstances' | 'getAddonStats' | 'listNodeProcesses' | 'killProcess' | 'dumpHeapSnapshot'>;
80
80
  readonly mqttBroker: Pick<InferProvider<typeof mqttBrokerCapability>, 'listBrokers' | 'getBrokerConfig' | 'addBroker' | 'removeBroker' | 'testConnection' | 'startEmbeddedBroker' | 'stopEmbeddedBroker' | 'getStatus'>;
package/dist/index.d.ts CHANGED
@@ -104,6 +104,7 @@ export * from './types/detection.js';
104
104
  export type { EngineOutput } from './types/engine-output.js';
105
105
  export * from './types/entities.js';
106
106
  export * from './types/events.js';
107
+ export type * from './types/frame-view.js';
107
108
  export * from './types/io.js';
108
109
  export * from './types/labels.js';
109
110
  export * from './types/live-state.js';
@@ -190,7 +191,7 @@ export type { AudioCodecInfo, AudioDecodeSessionConfig, AudioEncodedChunk, Audio
190
191
  export type { StreamQuality } from './interfaces/device-capabilities/camera.js';
191
192
  export { STREAM_QUALITY_LABELS, streamQualityLabel, } from './interfaces/device-capabilities/camera.js';
192
193
  export * from './lifecycle/index.js';
193
- export { audioIsFailClosed, audioKindId, audioLabelChoices, audioModeOf, audioOrDefaults, isAudioLabelSelected, NC_AUDIO_DB_MAX, NC_AUDIO_DB_MIN, NC_AUDIO_DB_OFFERED, NC_AUDIO_DB_STEP, NC_AUDIO_DEFAULTS, NC_AUDIO_HIT_PERCENT_MAX, NC_AUDIO_HIT_PERCENT_MIN, NC_AUDIO_SAMPLING_MAX_SEC, NC_AUDIO_SAMPLING_MIN_SEC, type NcAudioLabelChoice, type NcAudioMode, type NcAudioPatch, normalizeAudioLabel, patchAudio, toggleAudioLabel, } from './notification/audio-condition.js';
194
+ export { audioIsFailClosed, audioKindId, audioLabelChoices, audioModeOf, audioOrDefaults, isAudioLabelSelected, NC_AUDIO_DB_MAX, NC_AUDIO_DB_MIN, NC_AUDIO_DB_OFFERED, NC_AUDIO_DB_STEP, NC_AUDIO_CONFIRM_HITS_DEFAULT, NC_AUDIO_CONFIRM_HITS_MAX, NC_AUDIO_CONFIRM_HITS_MIN, NC_AUDIO_CONFIRM_WINDOW_MAX_SEC, NC_AUDIO_CONFIRM_WINDOW_MIN_SEC, NC_AUDIO_CONFIRM_WINDOW_SEC_DEFAULT, NC_AUDIO_DEFAULTS, NC_AUDIO_HIT_PERCENT_MAX, NC_AUDIO_HIT_PERCENT_MIN, NC_AUDIO_SAMPLING_MAX_SEC, NC_AUDIO_SAMPLING_MIN_SEC, type NcAudioLabelChoice, type NcAudioMode, type NcAudioPatch, normalizeAudioLabel, patchAudio, toggleAudioLabel, } from './notification/audio-condition.js';
194
195
  export { isBaseConditionKey, knownValues, NC_BASE_CONDITION_KEYS, type NcBaseConditionKey, pickerForCondition, type TaxonomyGroup, type TaxonomyOption, type TaxonomyPicker, } from './notification/condition-taxonomy.js';
195
196
  export { type PreparedAction, type PreparedAttachment, type PreparedNotification, prepareNotification, type ResolvedLevel, } from './notification/degrade-engine.js';
196
197
  export { htmlToText, markdownToHtmlLite, markdownToText, type NotificationFormat as NotificationBodyFormat, resolveFormat, textToHtml, transcodeBody, } from './notification/format-transcode.js';
package/dist/index.js CHANGED
@@ -2359,6 +2359,17 @@ var LabelDefinitionSchema = zod.z.object({
2359
2359
  description: zod.z.string().optional(),
2360
2360
  icon: zod.z.string().optional()
2361
2361
  });
2362
+ /** Detection-macro targets a catalog `classMap` may resolve to. */
2363
+ var CLASS_MAP_MACRO_TARGETS = [
2364
+ "person",
2365
+ "vehicle",
2366
+ "animal",
2367
+ "package"
2368
+ ];
2369
+ var ClassMapDefinitionSchema = zod.z.object({
2370
+ mapping: zod.z.record(zod.z.string(), zod.z.enum(CLASS_MAP_MACRO_TARGETS)),
2371
+ preserveOriginal: zod.z.boolean()
2372
+ });
2362
2373
  //#endregion
2363
2374
  //#region src/types/model-variant-groups.ts
2364
2375
  var FORMAT_KEYS = [
@@ -2689,7 +2700,13 @@ var ModelCatalogEntrySchema = zod.z.object({
2689
2700
  * `id` stays the source of truth for resolution/download/persistence; grouping
2690
2701
  * is a presentation overlay resolved back to an `id`.
2691
2702
  */
2692
- group: ModelVariantGroupSchema.optional()
2703
+ group: ModelVariantGroupSchema.optional(),
2704
+ /**
2705
+ * Per-MODEL class map override. Absent ⇒ the step's `StepDefinition.classMap`
2706
+ * applies (Frigate / COCO public catalog). Set on a custom model whose raw
2707
+ * labels already ARE the CamStack macros (Scrypted identity map).
2708
+ */
2709
+ classMap: ClassMapDefinitionSchema.optional()
2693
2710
  });
2694
2711
  var ConvertTargetSchema = zod.z.discriminatedUnion("format", [zod.z.object({
2695
2712
  format: zod.z.literal("openvino"),
@@ -2718,7 +2735,8 @@ var ModelConvertMetadataSchema = zod.z.object({
2718
2735
  "ocr",
2719
2736
  "segmentation"
2720
2737
  ]),
2721
- faceAlignment: zod.z.boolean().optional()
2738
+ faceAlignment: zod.z.boolean().optional(),
2739
+ classMap: ClassMapDefinitionSchema.optional()
2722
2740
  });
2723
2741
  var ConvertArtifactSchema = zod.z.object({
2724
2742
  format: zod.z.enum(MODEL_FORMATS),
@@ -12435,12 +12453,15 @@ var NC_AUDIO_DBFS_FLOOR = -96;
12435
12453
  * there is no second switch that can disagree with the first and every rule
12436
12454
  * authored before the decision migrates for free (`audioModeOf`):
12437
12455
  *
12438
- * - **LABEL mode — `labels` present.** The rule fires on the FIRST frame the
12439
- * classifier labels with one of them. No window, no percentage:
12440
- * `hitPercent` and `samplingSeconds` are ignored, and the rule's own
12441
- * `throttle` cooldown is the only brake. The per-label confidence floor is
12442
- * the analyzer's (`classificationMinScore`, per device) a label only
12443
- * reaches this condition if the classifier was already confident enough.
12456
+ * - **LABEL mode — `labels` present.** The rule fires when `confirmHits`
12457
+ * labelled frames land inside `confirmWindowSec` (default 2 in 5 s).
12458
+ * `hitPercent` and `samplingSeconds` are still ignored a percentage of
12459
+ * frames is the wrong question for a classifier that labels 1–3 frames
12460
+ * per episode. The count window is the brake that drops a single-frame
12461
+ * false positive; the rule's own `throttle` cooldown is the other. The
12462
+ * per-label confidence floor is the analyzer's (`classificationMinScore`,
12463
+ * per device) — a label only reaches this condition if the classifier was
12464
+ * already confident enough. `confirmHits: 1` restores first-frame fire.
12444
12465
  * - **LEVEL mode — `dbThreshold` present, no labels.** The sampling window IS
12445
12466
  * the condition: at least `hitPercent`% of the samples over
12446
12467
  * `samplingSeconds` must be at or above `dbThreshold` dBFS (see
@@ -12467,14 +12488,22 @@ var NC_AUDIO_DBFS_FLOOR = -96;
12467
12488
  * an operator who typed `dog` mean the same thing.
12468
12489
  */
12469
12490
  var NcAudioConditionSchema = zod.z.object({
12470
- /** LABEL MODE: audio macro labels. Present ⇒ fires on the first labelled frame. */
12491
+ /** LABEL MODE: audio macro labels. Present ⇒ count-in-window confirm. */
12471
12492
  labels: zod.z.array(zod.z.string().min(1)).min(1).optional(),
12472
12493
  /** LEVEL MODE: floor in dBFS (negative-going, `0` = full scale). */
12473
12494
  dbThreshold: zod.z.number().min(-96).max(0).optional(),
12474
12495
  /** LEVEL MODE ONLY: percentage of the window's samples that must be hits (1–100). */
12475
12496
  hitPercent: zod.z.number().int().min(1).max(100).default(60),
12476
12497
  /** LEVEL MODE ONLY: length of the sampling window in seconds. */
12477
- samplingSeconds: zod.z.number().int().min(1).max(300).default(10)
12498
+ samplingSeconds: zod.z.number().int().min(1).max(300).default(10),
12499
+ /**
12500
+ * LABEL MODE: how many labelled frames must land inside
12501
+ * {@link NcAudioConditionSchema.shape.confirmWindowSec} before dispatch.
12502
+ * Absent ⇒ 2 (the matcher default). `1` is first-frame fire.
12503
+ */
12504
+ confirmHits: zod.z.number().int().min(1).max(20).optional(),
12505
+ /** LABEL MODE: the window those frames must share, in seconds. Absent ⇒ 5. */
12506
+ confirmWindowSec: zod.z.number().int().min(1).max(60).optional()
12478
12507
  });
12479
12508
  /**
12480
12509
  * Which zone-crossing DIRECTION a rule accepts (`ObjectEvent.zoneCrossing`).
@@ -15509,7 +15538,9 @@ var TrackCascadeCountsSchema = zod.z.object({
15509
15538
  /** Unassigned plate reads removed (best-effort; plate leg deferred to plate-intelligence). */
15510
15539
  plates: zod.z.number().int(),
15511
15540
  /** Per-track CLIP search vectors removed (best-effort). */
15512
- embeddings: zod.z.number().int()
15541
+ embeddings: zod.z.number().int(),
15542
+ /** Group membership + group rows removed with their last member (best-effort). */
15543
+ groups: zod.z.number().int()
15513
15544
  });
15514
15545
  /** Disk-wins reconcile: media rows whose blobs are gone, then empty tracks. */
15515
15546
  var DiskReconcileCountsSchema = zod.z.object({
@@ -16276,6 +16307,33 @@ var NativeCropRefSchema = zod.z.object({
16276
16307
  h: zod.z.number()
16277
16308
  })
16278
16309
  });
16310
+ zod.z.object({
16311
+ crop: zod.z.object({
16312
+ left: zod.z.number(),
16313
+ top: zod.z.number(),
16314
+ width: zod.z.number().positive(),
16315
+ height: zod.z.number().positive()
16316
+ }).optional(),
16317
+ content: zod.z.object({
16318
+ width: zod.z.number().int().positive(),
16319
+ height: zod.z.number().int().positive()
16320
+ }),
16321
+ fit: zod.z.enum(["stretch", "contain"]),
16322
+ format: zod.z.enum([
16323
+ "rgb",
16324
+ "gray",
16325
+ "jpeg"
16326
+ ])
16327
+ });
16328
+ var FrameRefSchema = zod.z.object({
16329
+ registryId: zod.z.string().min(1),
16330
+ id: zod.z.string().min(1),
16331
+ width: zod.z.number().int().positive(),
16332
+ height: zod.z.number().int().positive(),
16333
+ format: zod.z.enum(["rgb", "gray"]),
16334
+ timestamp: zod.z.number(),
16335
+ capturedAt: zod.z.number().optional()
16336
+ });
16279
16337
  var ModelFormatSchema$1 = zod.z.enum([
16280
16338
  "onnx",
16281
16339
  "coreml",
@@ -16597,7 +16655,7 @@ var pipelineExecutorCapability = {
16597
16655
  * legacy call shape used by existing benchmark code; once all
16598
16656
  * callers pass it explicitly we make it required.
16599
16657
  *
16600
- * Exactly one of `frame`, `frameHandle`, `imageBase64`,
16658
+ * Exactly one of `frame`, `frameRef`, `frameHandle`, `imageBase64`,
16601
16659
  * `referenceImage` must be provided:
16602
16660
  * - `frame`: runtime dispatch path (runner → decoded broker frame).
16603
16661
  * Carries the raw buffer, dimensions, and format; the executor
@@ -16619,6 +16677,12 @@ var pipelineExecutorCapability = {
16619
16677
  steps: zod.z.array(PipelineStepInputSchema).min(1),
16620
16678
  frame: FrameInputSchema.optional(),
16621
16679
  /**
16680
+ * Process-local lazy frame. Valid only when caller and provider resolve
16681
+ * in the same execution-group process; split/cross-node callers use
16682
+ * `frame`/`image` inline compatibility instead.
16683
+ */
16684
+ frameRef: FrameRefSchema.optional(),
16685
+ /**
16622
16686
  * CB5 shm passthrough — a `FrameHandle` naming the same ring slot
16623
16687
  * the decoded pixels live in. One more member of the one-of
16624
16688
  * frame/frameHandle/image/imageBase64/referenceImage group.
@@ -16975,7 +17039,10 @@ var NativeCropResultSchema = zod.z.object({
16975
17039
  * Which source served this crop, so a quality-sensitive consumer (the native
16976
17040
  * `keyFrame`) can reject a degraded fallback:
16977
17041
  * - `native` — cut from the decode worker's retained NATIVE surface (the
16978
- * quality path).
17042
+ * quality path). A subject-tile serve is also native-resolution and stays
17043
+ * `native` here: the public enum cannot name `tile` without a breaking cap
17044
+ * change. Runner telemetry distinguishes lease vs tile via `source` on the
17045
+ * internal crop result (`nativeHits` vs `tileHits`).
16979
17046
  * - `ram-fullframe` — the native surface MISSED but the request was full-frame,
16980
17047
  * so the ≤640 RAM `RetainedFrameStore` served it (honest lower-res; legit for
16981
17048
  * the blank-frame guard / 640-snapshot resolve, NOT for the clean keyFrame).
@@ -17624,12 +17691,41 @@ var RunnerLocalLoadSchema = zod.z.object({
17624
17691
  * legacy `OrchestratorMetricsSchema` shape so existing dashboards keep
17625
17692
  * working unchanged when they switch to reading from the runner cap.
17626
17693
  */
17694
+ var FrameLazyCountersSchema = zod.z.object({
17695
+ framesDecoded: zod.z.number(),
17696
+ framesAdmitted: zod.z.number(),
17697
+ framesDroppedPixelFree: zod.z.number(),
17698
+ viewsMaterialized: zod.z.number(),
17699
+ viewsSkipped: zod.z.number(),
17700
+ workerToRunnerBytes: zod.z.number(),
17701
+ runnerToPoolRawBytes: zod.z.number(),
17702
+ runnerToPoolJpegBytes: zod.z.number(),
17703
+ onDemandFullFrameRequests: zod.z.number(),
17704
+ onDemandCropRequests: zod.z.number(),
17705
+ nativeHits: zod.z.number(),
17706
+ nativeMisses: zod.z.number(),
17707
+ tileHits: zod.z.number(),
17708
+ tileMisses: zod.z.number(),
17709
+ fallbackHits: zod.z.number(),
17710
+ fallbackMisses: zod.z.number(),
17711
+ retainedWritesAvoided: zod.z.number(),
17712
+ residentRefs: zod.z.number(),
17713
+ residentBytes: zod.z.number(),
17714
+ releases: zod.z.number(),
17715
+ evictions: zod.z.number(),
17716
+ staleMisses: zod.z.number()
17717
+ });
17718
+ var FrameLazyMetricsSchema = zod.z.object({
17719
+ node: FrameLazyCountersSchema,
17720
+ cameras: zod.z.array(FrameLazyCountersSchema.extend({ deviceId: zod.z.number() }))
17721
+ });
17627
17722
  var RunnerLocalMetricsSchema = zod.z.object({
17628
17723
  nodeId: zod.z.string(),
17629
17724
  activeCameras: zod.z.number(),
17630
17725
  throttledCameras: zod.z.number(),
17631
17726
  avgInferenceTimeMs: zod.z.number(),
17632
- queueDepth: zod.z.number()
17727
+ queueDepth: zod.z.number(),
17728
+ frameLazy: FrameLazyMetricsSchema.optional()
17633
17729
  });
17634
17730
  /**
17635
17731
  * Pipeline Runner capability — runtime detection workhorse.
@@ -24696,6 +24792,17 @@ var NotificationEndpointSchema = zod.z.object({
24696
24792
  /** What the ranking currently resolves to (null when nothing is reachable). */
24697
24793
  resolved: zod.z.string().nullable()
24698
24794
  });
24795
+ /**
24796
+ * The URLs the SDK / viewer should race for API access. `baseUrls` empty =
24797
+ * AUTO (every LAN IPv4 + the public tunnel). `resolved` is what that choice
24798
+ * currently expands to, so the UI can show the effective set either way.
24799
+ */
24800
+ var ViewerEndpointsSchema = zod.z.object({
24801
+ /** The operator's explicit race set, or empty for AUTO. */
24802
+ baseUrls: zod.z.array(zod.z.string()).readonly(),
24803
+ /** What the ranking currently resolves to (may be empty if nothing is up). */
24804
+ resolved: zod.z.array(zod.z.string()).readonly()
24805
+ });
24699
24806
  var AllowedAddressesSchema = zod.z.object({
24700
24807
  /**
24701
24808
  * Allowlist of interface addresses operators have explicitly opted
@@ -24737,13 +24844,13 @@ var localNetworkCapability = {
24737
24844
  */
24738
24845
  getPreferred: require_sleep.method(zod.z.void(), PreferredSchema),
24739
24846
  /**
24740
- * Ordered candidate base URLs the SDK should try on connect.
24741
- * Includes LAN IPs (one per non-internal interface), the public
24742
- * tunnel hostname (when active), and loopback as a last-resort
24743
- * fallback. Filterable by `includeLoopback` / `ipv4Only`.
24744
- * Honours `getAllowedAddresses()` when set addresses outside
24745
- * the allowlist are dropped (the public tunnel + loopback are
24746
- * always included as escape hatches).
24847
+ * Ordered candidate base URLs (the palette the Network tab shows).
24848
+ * Includes LAN IPv4, stable LAN IPv6, the public tunnel, and mesh when
24849
+ * joined. Loopback is off by default. The SDK races the subset from
24850
+ * `getViewerEndpoints`, not this full list — IPv6 stays here because
24851
+ * WebRTC ICE gathers dual-stack regardless of the HTTP race. Honours
24852
+ * `getAllowedAddresses()` when set addresses outside the allowlist
24853
+ * are dropped (the public tunnel is still included as an escape hatch).
24747
24854
  *
24748
24855
  * **The port is the hub's, not the caller's** (D62 — a function's fact
24749
24856
  * belongs to whoever already owns it). This method used to take a `port`
@@ -24774,10 +24881,11 @@ var localNetworkCapability = {
24774
24881
  */
24775
24882
  port: zod.z.number().int().min(1).max(65535).optional(),
24776
24883
  /** Include `http(s)://127.0.0.1:<port>` as the lowest-priority
24777
- * candidate. Default `true`. */
24884
+ * candidate. Default `false` — loopback is not a client route. */
24778
24885
  includeLoopback: zod.z.boolean().optional(),
24779
- /** Skip IPv6 entries. Some legacy clients can't parse them.
24780
- * Default `false`. */
24886
+ /** Skip IPv6 entries. Default `false` the palette includes stable
24887
+ * LAN IPv6 (ICE/WebRTC uses dual-stack regardless). Pass `true` to
24888
+ * hide them. The viewer HTTP/WS race is `getViewerEndpoints`. */
24781
24889
  ipv4Only: zod.z.boolean().optional(),
24782
24890
  /** Scheme to emit for LAN/loopback URLs. Default `'http'`.
24783
24891
  * Pass `'https'` when the caller is itself loaded over HTTPS
@@ -24806,6 +24914,19 @@ var localNetworkCapability = {
24806
24914
  */
24807
24915
  setNotificationEndpoint: require_sleep.method(zod.z.object({ baseUrl: zod.z.string().nullable() }), NotificationEndpointSchema, { kind: "mutation" }),
24808
24916
  /**
24917
+ * The endpoints the SDK / viewer races for API access. Empty `baseUrls`
24918
+ * means AUTO: every LAN IPv4 address plus the public tunnel, never IPv6,
24919
+ * never mesh, never loopback. `resolved` is that set (or the operator's
24920
+ * explicit subset) as it stands right now.
24921
+ */
24922
+ getViewerEndpoints: require_sleep.method(zod.z.void(), ViewerEndpointsSchema),
24923
+ /**
24924
+ * Replace the viewer race set. Empty `baseUrls` restores AUTO. Stored
24925
+ * verbatim (not indices) so a temporarily-down tunnel is not silently
24926
+ * dropped from the operator's choice.
24927
+ */
24928
+ setViewerEndpoints: require_sleep.method(zod.z.object({ baseUrls: zod.z.array(zod.z.string()).readonly() }), ViewerEndpointsSchema, { kind: "mutation" }),
24929
+ /**
24809
24930
  * Read the operator's allowlist. Empty = "auto" (no filter). Used
24810
24931
  * by the admin UI's address selector to seed its checkbox state.
24811
24932
  */
@@ -36817,6 +36938,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
36817
36938
  addonId: null,
36818
36939
  access: "view"
36819
36940
  },
36941
+ "localNetwork.getViewerEndpoints": {
36942
+ capName: "local-network",
36943
+ capScope: "system",
36944
+ addonId: null,
36945
+ access: "view"
36946
+ },
36820
36947
  "localNetwork.list": {
36821
36948
  capName: "local-network",
36822
36949
  capScope: "system",
@@ -36853,6 +36980,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
36853
36980
  addonId: null,
36854
36981
  access: "create"
36855
36982
  },
36983
+ "localNetwork.setViewerEndpoints": {
36984
+ capName: "local-network",
36985
+ capScope: "system",
36986
+ addonId: null,
36987
+ access: "create"
36988
+ },
36856
36989
  "localNetwork.uploadCertificate": {
36857
36990
  capName: "local-network",
36858
36991
  capScope: "system",
@@ -43055,6 +43188,8 @@ function createSystemProxy(api) {
43055
43188
  getConnectionEndpoints: (input) => dispatch("localNetwork", "getConnectionEndpoints", "query", input),
43056
43189
  getNotificationEndpoint: (input) => dispatch("localNetwork", "getNotificationEndpoint", "query", input),
43057
43190
  setNotificationEndpoint: (input) => dispatch("localNetwork", "setNotificationEndpoint", "mutation", input),
43191
+ getViewerEndpoints: (input) => dispatch("localNetwork", "getViewerEndpoints", "query", input),
43192
+ setViewerEndpoints: (input) => dispatch("localNetwork", "setViewerEndpoints", "mutation", input),
43058
43193
  getAllowedAddresses: (input) => dispatch("localNetwork", "getAllowedAddresses", "query", input),
43059
43194
  setAllowedAddresses: (input) => dispatch("localNetwork", "setAllowedAddresses", "mutation", input),
43060
43195
  resetAllowlistToBestMatch: (input) => dispatch("localNetwork", "resetAllowlistToBestMatch", "mutation", input),
@@ -43468,6 +43603,19 @@ var NC_AUDIO_HIT_PERCENT_MIN = 1;
43468
43603
  var NC_AUDIO_HIT_PERCENT_MAX = 100;
43469
43604
  var NC_AUDIO_SAMPLING_MIN_SEC = 1;
43470
43605
  var NC_AUDIO_SAMPLING_MAX_SEC = 300;
43606
+ /**
43607
+ * LABEL-mode confirm-count defaults. Chosen against the live "Pianti" rule
43608
+ * (2026-08-23): 15 notifies in 12 h, each a single YAMNet `crying` frame,
43609
+ * nobody actually crying. Two labelled frames in 5 s drops the single-frame
43610
+ * false positives and still catches a real episode (YAMNet labels 2–3
43611
+ * frames of a genuine cry).
43612
+ */
43613
+ var NC_AUDIO_CONFIRM_HITS_DEFAULT = 2;
43614
+ var NC_AUDIO_CONFIRM_WINDOW_SEC_DEFAULT = 5;
43615
+ var NC_AUDIO_CONFIRM_HITS_MIN = 1;
43616
+ var NC_AUDIO_CONFIRM_HITS_MAX = 20;
43617
+ var NC_AUDIO_CONFIRM_WINDOW_MIN_SEC = 1;
43618
+ var NC_AUDIO_CONFIRM_WINDOW_MAX_SEC = 60;
43471
43619
  /** Schema defaults — an untouched sub-field must author exactly these. */
43472
43620
  var NC_AUDIO_DEFAULTS = {
43473
43621
  hitPercent: 60,
@@ -43547,7 +43695,15 @@ function patchAudio(current, patch) {
43547
43695
  ...labels !== void 0 ? { labels: [...labels] } : {},
43548
43696
  ...dbThreshold !== void 0 ? { dbThreshold: clampInt(dbThreshold, NC_AUDIO_DB_MIN, 0) } : {},
43549
43697
  hitPercent: clampInt(patch.hitPercent ?? base.hitPercent, 1, 100),
43550
- samplingSeconds: clampInt(patch.samplingSeconds ?? base.samplingSeconds, 1, 300)
43698
+ samplingSeconds: clampInt(patch.samplingSeconds ?? base.samplingSeconds, 1, 300),
43699
+ ...(() => {
43700
+ const hits = has(patch, "confirmHits") ? patch.confirmHits : base.confirmHits;
43701
+ const windowSec = has(patch, "confirmWindowSec") ? patch.confirmWindowSec : base.confirmWindowSec;
43702
+ return {
43703
+ ...hits !== void 0 ? { confirmHits: clampInt(hits, 1, 20) } : {},
43704
+ ...windowSec !== void 0 ? { confirmWindowSec: clampInt(windowSec, 1, 60) } : {}
43705
+ };
43706
+ })()
43551
43707
  };
43552
43708
  }
43553
43709
  /**
@@ -47382,6 +47538,7 @@ exports.CAPABILITY_ROUTER_KEYS = CAPABILITY_ROUTER_KEYS;
47382
47538
  exports.CAP_NAMES_WITH_STATUS = CAP_NAMES_WITH_STATUS;
47383
47539
  exports.CAP_NODE_PIN_CONTEXT_KEY = require_sleep.CAP_NODE_PIN_CONTEXT_KEY;
47384
47540
  exports.CAP_PROVIDER_KIND_MAP = CAP_PROVIDER_KIND_MAP;
47541
+ exports.CLASS_MAP_MACRO_TARGETS = CLASS_MAP_MACRO_TARGETS;
47385
47542
  exports.CLUSTER_MODEL_SCOPED_STEPS = CLUSTER_MODEL_SCOPED_STEPS;
47386
47543
  exports.CLUSTER_MODEL_SECTION_ID = CLUSTER_MODEL_SECTION_ID;
47387
47544
  exports.CLUSTER_STEP_SETTING_FIELDS = CLUSTER_STEP_SETTING_FIELDS;
@@ -47428,6 +47585,7 @@ exports.CapScopeSchema = CapScopeSchema;
47428
47585
  exports.CapabilityBindingsSchema = CapabilityBindingsSchema;
47429
47586
  exports.CarbonMonoxideStatusSchema = CarbonMonoxideStatusSchema;
47430
47587
  exports.ChargingStatus = require_sleep.ChargingStatus;
47588
+ exports.ClassMapDefinitionSchema = ClassMapDefinitionSchema;
47431
47589
  exports.ClientNetworkStatsSchema = ClientNetworkStatsSchema;
47432
47590
  exports.ClimateControlStatusSchema = ClimateControlStatusSchema;
47433
47591
  exports.ClipPlaybackSchema = ClipPlaybackSchema;
@@ -47603,6 +47761,8 @@ exports.Fmp4BoxSplitter = require_canonical_hash.Fmp4BoxSplitter;
47603
47761
  exports.FrameHandleFormatSchema = require_sleep.FrameHandleFormatSchema;
47604
47762
  exports.FrameHandleSchema = require_sleep.FrameHandleSchema;
47605
47763
  exports.FrameInputSchema = FrameInputSchema;
47764
+ exports.FrameLazyCountersSchema = FrameLazyCountersSchema;
47765
+ exports.FrameLazyMetricsSchema = FrameLazyMetricsSchema;
47606
47766
  exports.GasStatusSchema = GasStatusSchema;
47607
47767
  exports.GetStreamWithCodecInputSchema = GetStreamWithCodecInputSchema;
47608
47768
  exports.GlobalMetricsSchema = GlobalMetricsSchema;
@@ -47747,6 +47907,12 @@ exports.NATIVE_LEASE_SECTION_ID = NATIVE_LEASE_SECTION_ID;
47747
47907
  exports.NATIVE_LEASE_TILE_BUDGET_FIELD = NATIVE_LEASE_TILE_BUDGET_FIELD;
47748
47908
  exports.NATIVE_LEASE_TILE_BUDGET_KEY = NATIVE_LEASE_TILE_BUDGET_KEY;
47749
47909
  exports.NC_ALARM_SYSTEM_EVENT_KINDS = NC_ALARM_SYSTEM_EVENT_KINDS;
47910
+ exports.NC_AUDIO_CONFIRM_HITS_DEFAULT = NC_AUDIO_CONFIRM_HITS_DEFAULT;
47911
+ exports.NC_AUDIO_CONFIRM_HITS_MAX = NC_AUDIO_CONFIRM_HITS_MAX;
47912
+ exports.NC_AUDIO_CONFIRM_HITS_MIN = NC_AUDIO_CONFIRM_HITS_MIN;
47913
+ exports.NC_AUDIO_CONFIRM_WINDOW_MAX_SEC = NC_AUDIO_CONFIRM_WINDOW_MAX_SEC;
47914
+ exports.NC_AUDIO_CONFIRM_WINDOW_MIN_SEC = NC_AUDIO_CONFIRM_WINDOW_MIN_SEC;
47915
+ exports.NC_AUDIO_CONFIRM_WINDOW_SEC_DEFAULT = NC_AUDIO_CONFIRM_WINDOW_SEC_DEFAULT;
47750
47916
  exports.NC_AUDIO_DBFS_FLOOR = NC_AUDIO_DBFS_FLOOR;
47751
47917
  exports.NC_AUDIO_DB_MAX = NC_AUDIO_DB_MAX;
47752
47918
  exports.NC_AUDIO_DB_MIN = NC_AUDIO_DB_MIN;