@camstack/types 1.2.93 → 1.2.95

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.
@@ -79,8 +79,8 @@ export { type IOauthIntegrationProvider, type OauthIntegrationDescriptor, OauthI
79
79
  export { type AudioEvent, AudioEventSchema, type DetectionSource, DetectionSourceSchema, type EventKind, type EventKindCategory, EventKindCategorySchema, type EventKindDescriptor, EventKindDescriptorSchema, type EventKindIcon, EventKindIconSchema, EventKindSchema, type EventKindsForDevice, EventKindsForDeviceSchema, type EventPruneCounts, type EventStoreDeviceFootprint, type EventStoreFootprint, type IPipelineAnalyticsProvider, type KeyEvent, KeyEventSchema, type LabelAttribution, LabelAttributionSchema, type LabelTier, LabelTierSchema, type MediaFile, type MediaFileInfo, MediaFileInfoSchema, type MediaFileKind, MediaFileSchema, type MotionEvent, MotionEventSchema, type ObjectEvent, ObjectEventSchema, pipelineAnalyticsCapability, type RecentTracksPage, RecentTracksPageSchema, type RecentTracksQuery, RecentTracksQueryInput, type RetrainAnnotation, type RetrainAnnotationDraft, RetrainAnnotationDraftSchema, RetrainAnnotationKindSchema, RetrainAnnotationSchema, RetrainAnnotationSourceSchema, type RetrainAssistResult, RetrainAssistResultSchema, RetrainAssistSubjectSchema, RetrainCopyRefusalSchema, type RetrainFrame, type RetrainFrameCandidate, RetrainFrameCandidateSchema, type RetrainFrameList, RetrainFrameListSchema, RetrainFrameSchema, type RetrainFrameSelection, RetrainFrameSelectionSchema, type RetrainMacroClass, RetrainMacroClassSchema, type RetrainStatus, RetrainStatusSchema, type RetrainTrack, RetrainTrackSchema, type RetrainTransitionResult, RetrainTransitionResultSchema, type ScoredObjectEvent, ScoredObjectEventSchema, type SensorEvent, SensorEventSchema, type Track, type TrackCascadeCounts, TrackCascadeCountsSchema, type TrackEnvelope, TrackEnvelopeSchema, TrackedDetectionSchema, type TrackFlags, type TrackFlagsPatch, TrackFlagsPatchSchema, TrackFlagsSchema, type TrackProjection, TrackProjectionSchema, TrackSchema, type TrackSource, TrackSourceSchema, type TrackState, TrackStateSchema, type TrackZoneFilter, TrackZoneFilterSchema, type TrainingExportDeviceTotals, TrainingExportDeviceTotalsSchema, type TrainingExportSummary, TrainingExportSummarySchema, type ZoneCrossing, type ZoneCrossingDirection, ZoneCrossingDirectionSchema, ZoneCrossingSchema, } from './pipeline-analytics.cap.js';
80
80
  export type { NativeCropRef, PipelineStepInputOutput, PipelineValidationIssue, PipelineValidationResult, } from './pipeline-executor.cap.js';
81
81
  export { ModelSubstitutionSchema, NativeCropRefSchema, PipelineDefaultStepSchema, PipelineEngineChoiceSchema, PipelineRunResultBridge, PipelineStepInputSchema, PipelineValidationIssueSchema, PipelineValidationResultSchema, pipelineExecutorCapability, } from './pipeline-executor.cap.js';
82
- export type { CameraAssignmentStatus, CameraAudioStatus, CameraBrokerProfile, CameraBrokerStatus, CameraDecoderShm, CameraDecoderStatus, CameraDetectionPhase, CameraDetectionProvisioning, CameraDetectionProvisioningState, CameraDetectionStatus, CameraMotionStatus, CameraRecordingMode, CameraRecordingStatus, CameraSourceStatus, CameraSourceStream, CameraStatus, CameraStatusDegradation, CameraStatusDegradationReason, CameraStatusStage, DiskReconcileJob, IngestOwner, NodeInferenceDevice, NodeInferenceDevices, } from './pipeline-orchestrator.cap.js';
83
- export { AgentLoadSummarySchema, CameraAssignmentStatusSchema, CameraAudioStatusSchema, CameraBrokerProfileSchema, CameraBrokerStatusSchema, CameraDecoderShmSchema, CameraDecoderStatusSchema, CameraDetectionPhaseSchema, CameraDetectionProvisioningSchema, CameraDetectionProvisioningStateSchema, CameraDetectionStatusSchema, CameraMotionStatusSchema, CameraRecordingModeSchema, CameraRecordingStatusSchema, CameraSourceStatusSchema, CameraSourceStreamSchema, CameraStatusDegradationReasonSchema, CameraStatusDegradationSchema, CameraStatusSchema, CameraStatusStageSchema, CapabilityBindingsSchema, DiskReconcileJobSchema, GlobalMetricsSchema, IngestOwnerSchema, PipelineAssignmentSchema, pipelineOrchestratorCapability, } from './pipeline-orchestrator.cap.js';
82
+ export type { CameraAssignmentStatus, CameraAudioStatus, CameraBrokerProfile, CameraBrokerStatus, CameraDecoderShm, CameraDecoderStatus, CameraDetectionPhase, CameraDetectionProvisioning, CameraDetectionProvisioningState, CameraDetectionStatus, CameraMotionStatus, CameraRecordingMode, CameraRecordingStatus, CameraSourceStatus, CameraSourceStream, CameraStatus, CameraStatusDegradation, CameraStatusDegradationReason, CameraStatusStage, DiskReconcileJob, InferenceDeviceExclusionReason, IngestOwner, NodeInferenceDevice, NodeInferenceDevices, } from './pipeline-orchestrator.cap.js';
83
+ export { AgentLoadSummarySchema, CameraAssignmentStatusSchema, CameraAudioStatusSchema, CameraBrokerProfileSchema, CameraBrokerStatusSchema, CameraDecoderShmSchema, CameraDecoderStatusSchema, CameraDetectionPhaseSchema, CameraDetectionProvisioningSchema, CameraDetectionProvisioningStateSchema, CameraDetectionStatusSchema, CameraMotionStatusSchema, CameraRecordingModeSchema, CameraRecordingStatusSchema, CameraSourceStatusSchema, CameraSourceStreamSchema, CameraStatusDegradationReasonSchema, CameraStatusDegradationSchema, CameraStatusSchema, CameraStatusStageSchema, CapabilityBindingsSchema, DiskReconcileJobSchema, GlobalMetricsSchema, INFERENCE_DEVICE_EXCLUSION_REASONS, InferenceDeviceExclusionReasonSchema, IngestOwnerSchema, PipelineAssignmentSchema, pipelineOrchestratorCapability, } from './pipeline-orchestrator.cap.js';
84
84
  export type { DetailParent, DetailResult, MotionSource, MotionSources, ReportMotionInput, RunDetailSubtreeInput, RunDetailSubtreeResult, RunnerFrameSource, RunnerInferenceDevice, RunStatelessStepInput, RunStatelessStepResult, StatelessStepRefusal, } from './pipeline-runner.cap.js';
85
85
  export { MotionSourceEnum, MotionSourcesSchema, type NativeCropBbox, NativeCropBboxSchema, NativeCropResultSchema, pipelineRunnerCapability, ReportMotionInputSchema, RunnerCameraConfigSchema, RunnerCameraDeviceUIFields, RunnerFrameSourceSchema, RunnerInferenceDeviceSchema, RunnerLocalLoadSchema, RunnerLocalMetricsSchema, } from './pipeline-runner.cap.js';
86
86
  export { AudioChunkInputSchema, AudioClassificationLabelSchema, AudioLevelSchema, BoundingBoxSchema, FrameInputSchema, SpatialDetectionSchema, } from './schemas/detection-shared.js';
@@ -154,7 +154,7 @@ export { type BacklightMode, BacklightModeSchema, type ExposureMode, ExposureMod
154
154
  export { AvailableIntegrationTypeSchema, CreateIntegrationInputSchema, DeleteIntegrationResultSchema, type IIntegrationsProvider, IntegrationLiteSchema, type IntegrationTestConnectionResult, type IntegrationTestConnectionStatus, IntegrationWithStateSchema, integrationsCapability, TestConnectionResultSchema, TestConnectionStatusEnum, UpdateIntegrationInputSchema, } from './integrations.cap.js';
155
155
  export { type IIntercomProvider, type IntercomAbility, IntercomAbilitySchema, type IntercomStatus, IntercomStatusSchema, intercomCapability, } from './intercom.cap.js';
156
156
  export { type DeviceCodeSeverity, DeviceCodeSeveritySchema, type ILawnMowerControlProvider, type LawnMowerActivity, LawnMowerActivitySchema, type LawnMowerControlStatus, LawnMowerControlStatusSchema, lawnMowerControlCapability, } from './lawn-mower-control.cap.js';
157
- export { type ConnectionEndpoint, type ILocalNetworkProvider, type LocalInterface, localNetworkCapability, } from './local-network.cap.js';
157
+ export { type AdvertisedLocalPort, type ConnectionEndpoint, type ILocalNetworkProvider, type LocalInterface, localNetworkCapability, } from './local-network.cap.js';
158
158
  export { type ILockControlProvider, type LockControlStatus, LockControlStatusSchema, type LockState, LockStateSchema, lockControlCapability, } from './lock-control.cap.js';
159
159
  export { type MaskGridDims, MaskGridDimsSchema, type MaskGridShape, MaskGridShapeSchema, type MaskLineShape, MaskLineShapeSchema, type MaskPoint, MaskPointSchema, type MaskPolygonShape, MaskPolygonShapeSchema, type MaskPolygonVertices, MaskPolygonVerticesSchema, type MaskRectShape, MaskRectShapeSchema, type MaskShape, type MaskShapeKind, MaskShapeKindSchema, MaskShapeSchema, } from './mask-shape.js';
160
160
  export { type IMediaPlayerProvider, type MediaInfo, type MediaPlayerRepeat, MediaPlayerRepeatSchema, type MediaPlayerState, MediaPlayerStateSchema, type MediaPlayerStatus, MediaPlayerStatusSchema, mediaPlayerCapability, } from './media-player.cap.js';
@@ -74,6 +74,17 @@ declare const ConnectionEndpointSchema: z.ZodObject<{
74
74
  plausibleReason: z.ZodString;
75
75
  priority: z.ZodNumber;
76
76
  }, z.core.$strip>;
77
+ /** The port every LAN/loopback `baseUrl` in the same result was built with. */
78
+ declare const AdvertisedLocalPortSchema: z.ZodObject<{
79
+ port: z.ZodNumber;
80
+ source: z.ZodEnum<{
81
+ default: "default";
82
+ "server-config": "server-config";
83
+ "server-env": "server-env";
84
+ "caller-hint": "caller-hint";
85
+ }>;
86
+ }, z.core.$strip>;
87
+ export type AdvertisedLocalPort = z.infer<typeof AdvertisedLocalPortSchema>;
77
88
  /**
78
89
  * The chosen outbound endpoint for notification artifacts. `baseUrl: null` =
79
90
  * AUTO (resolved from the candidate ranking at send time); `resolved` reports
@@ -157,9 +168,29 @@ export declare const localNetworkCapability: {
157
168
  * Honours `getAllowedAddresses()` when set — addresses outside
158
169
  * the allowlist are dropped (the public tunnel + loopback are
159
170
  * always included as escape hatches).
171
+ *
172
+ * **The port is the hub's, not the caller's** (D62 — a function's fact
173
+ * belongs to whoever already owns it). This method used to take a `port`
174
+ * and echo it onto every LAN and loopback URL it advertised, which made
175
+ * every client a second authority on a socket only the hub binds. A viewer
176
+ * configured with a port-less public URL (`https://camstack.example.top`)
177
+ * infers 443 from the scheme, asks with 443, and was handed
178
+ * `https://192.168.1.9:443` for a hub listening on 4443. That candidate
179
+ * cannot ever answer, and losing its race reads in the log exactly like
180
+ * "the LAN was tried and it was slower" — so an operator sitting on his own
181
+ * WiFi stayed on the public tunnel for weeks, with the LAN candidate born
182
+ * dead on every single connect.
183
+ *
184
+ * The hub now resolves its own listen port and reports it as `localPort`,
185
+ * with the SOURCE of the number, so a client can tell a fact from an echo.
186
+ *
187
+ * Out of scope on purpose: a LAN URL that is not the hub's own socket (a
188
+ * reverse proxy in front of it on another port) is not this method's to
189
+ * invent either — pin it with `setNotificationEndpoint` / a configured
190
+ * origin, which is an operator statement rather than a guess.
160
191
  */
161
192
  readonly getConnectionEndpoints: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
162
- port: z.ZodNumber;
193
+ port: z.ZodOptional<z.ZodNumber>;
163
194
  includeLoopback: z.ZodOptional<z.ZodBoolean>;
164
195
  ipv4Only: z.ZodOptional<z.ZodBoolean>;
165
196
  scheme: z.ZodOptional<z.ZodEnum<{
@@ -189,6 +220,15 @@ export declare const localNetworkCapability: {
189
220
  plausibleReason: z.ZodString;
190
221
  priority: z.ZodNumber;
191
222
  }, z.core.$strip>>>;
223
+ localPort: z.ZodObject<{
224
+ port: z.ZodNumber;
225
+ source: z.ZodEnum<{
226
+ default: "default";
227
+ "server-config": "server-config";
228
+ "server-env": "server-env";
229
+ "caller-hint": "caller-hint";
230
+ }>;
231
+ }, z.core.$strip>;
192
232
  }, z.core.$strip>, import("./capability-definition.js").CapabilityMethodKind>;
193
233
  /**
194
234
  * The endpoint OUTBOUND artifacts must be addressed by — notification
@@ -202,7 +202,7 @@ export type TrackEnvelope = z.infer<typeof TrackEnvelopeSchema>;
202
202
  * `snapshots[]` references — megabytes across a page of tracks. `slim`
203
203
  * keeps every scalar the list surfaces actually render (ids, class(es),
204
204
  * label / audioLabels / importance enrichment, firstSeen/lastSeen, state,
205
- * zonesVisited, bestEventId, envelope, hasFace, hasRider) and returns `positions` /
205
+ * zonesVisited, bestEventId, envelope, hasFace, hasEmbeddedFace, hasRider) and returns `positions` /
206
206
  * `snapshots` as EMPTY arrays — detail views re-fetch the full row via
207
207
  * `getTrack`. Mirrors the event-store `projection` convention
208
208
  * (`getObjectEvents` et al.).
@@ -435,6 +435,7 @@ declare const TrackSchema: z.ZodObject<{
435
435
  maxY: z.ZodNumber;
436
436
  }, z.core.$strip>>;
437
437
  hasFace: z.ZodOptional<z.ZodBoolean>;
438
+ hasEmbeddedFace: z.ZodOptional<z.ZodBoolean>;
438
439
  hasRider: z.ZodOptional<z.ZodBoolean>;
439
440
  label: z.ZodOptional<z.ZodString>;
440
441
  labelScore: z.ZodOptional<z.ZodNumber>;
@@ -1087,6 +1088,7 @@ declare const RecentTracksPageSchema: z.ZodObject<{
1087
1088
  maxY: z.ZodNumber;
1088
1089
  }, z.core.$strip>>;
1089
1090
  hasFace: z.ZodOptional<z.ZodBoolean>;
1091
+ hasEmbeddedFace: z.ZodOptional<z.ZodBoolean>;
1090
1092
  hasRider: z.ZodOptional<z.ZodBoolean>;
1091
1093
  label: z.ZodOptional<z.ZodString>;
1092
1094
  labelScore: z.ZodOptional<z.ZodNumber>;
@@ -1348,6 +1350,7 @@ export declare const pipelineAnalyticsCapability: {
1348
1350
  maxY: z.ZodNumber;
1349
1351
  }, z.core.$strip>>;
1350
1352
  hasFace: z.ZodOptional<z.ZodBoolean>;
1353
+ hasEmbeddedFace: z.ZodOptional<z.ZodBoolean>;
1351
1354
  hasRider: z.ZodOptional<z.ZodBoolean>;
1352
1355
  label: z.ZodOptional<z.ZodString>;
1353
1356
  labelScore: z.ZodOptional<z.ZodNumber>;
@@ -1444,6 +1447,7 @@ export declare const pipelineAnalyticsCapability: {
1444
1447
  maxY: z.ZodNumber;
1445
1448
  }, z.core.$strip>>;
1446
1449
  hasFace: z.ZodOptional<z.ZodBoolean>;
1450
+ hasEmbeddedFace: z.ZodOptional<z.ZodBoolean>;
1447
1451
  hasRider: z.ZodOptional<z.ZodBoolean>;
1448
1452
  label: z.ZodOptional<z.ZodString>;
1449
1453
  labelScore: z.ZodOptional<z.ZodNumber>;
@@ -1563,6 +1567,7 @@ export declare const pipelineAnalyticsCapability: {
1563
1567
  maxY: z.ZodNumber;
1564
1568
  }, z.core.$strip>>;
1565
1569
  hasFace: z.ZodOptional<z.ZodBoolean>;
1570
+ hasEmbeddedFace: z.ZodOptional<z.ZodBoolean>;
1566
1571
  hasRider: z.ZodOptional<z.ZodBoolean>;
1567
1572
  label: z.ZodOptional<z.ZodString>;
1568
1573
  labelScore: z.ZodOptional<z.ZodNumber>;
@@ -1678,6 +1683,7 @@ export declare const pipelineAnalyticsCapability: {
1678
1683
  maxY: z.ZodNumber;
1679
1684
  }, z.core.$strip>>;
1680
1685
  hasFace: z.ZodOptional<z.ZodBoolean>;
1686
+ hasEmbeddedFace: z.ZodOptional<z.ZodBoolean>;
1681
1687
  hasRider: z.ZodOptional<z.ZodBoolean>;
1682
1688
  label: z.ZodOptional<z.ZodString>;
1683
1689
  labelScore: z.ZodOptional<z.ZodNumber>;
@@ -532,6 +532,24 @@ declare const CameraStatusSchema: z.ZodObject<{
532
532
  }, z.core.$strip>>>;
533
533
  fetchedAt: z.ZodNumber;
534
534
  }, z.core.$strip>;
535
+ /**
536
+ * Why the dispatcher does NOT consider a device the node HAS for the
537
+ * camera-root election. The list is the CONTRACT between the orchestrator's
538
+ * `resolveInferenceDeviceEligibility` (which computes it) and the admin UI
539
+ * (which renders it) — the orchestrator's `InferenceDeviceExclusionReason`
540
+ * derives from this tuple so the two can never drift.
541
+ *
542
+ * Every one of these drops used to be silent, and an accelerator that is
543
+ * enabled, available, and never chosen is indistinguishable from one that was
544
+ * never configured. The reason is the difference.
545
+ */
546
+ declare const INFERENCE_DEVICE_EXCLUSION_REASONS: readonly ["disabled", "unavailable", "cannot-host-camera-root", "accelerator-preferred"];
547
+ declare const InferenceDeviceExclusionReasonSchema: z.ZodEnum<{
548
+ disabled: "disabled";
549
+ unavailable: "unavailable";
550
+ "cannot-host-camera-root": "cannot-host-camera-root";
551
+ "accelerator-preferred": "accelerator-preferred";
552
+ }>;
535
553
  declare const NodeInferenceDeviceSchema: z.ZodObject<{
536
554
  key: z.ZodString;
537
555
  backend: z.ZodString;
@@ -554,6 +572,12 @@ declare const NodeInferenceDeviceSchema: z.ZodObject<{
554
572
  settings: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
555
573
  jumpDeviceKey: z.ZodOptional<z.ZodString>;
556
574
  }, z.core.$strip>>>;
575
+ exclusion: z.ZodNullable<z.ZodEnum<{
576
+ disabled: "disabled";
577
+ unavailable: "unavailable";
578
+ "cannot-host-camera-root": "cannot-host-camera-root";
579
+ "accelerator-preferred": "accelerator-preferred";
580
+ }>>;
557
581
  }, z.core.$strip>;
558
582
  declare const NodeInferenceDevicesSchema: z.ZodObject<{
559
583
  nodeId: z.ZodString;
@@ -580,6 +604,12 @@ declare const NodeInferenceDevicesSchema: z.ZodObject<{
580
604
  settings: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
581
605
  jumpDeviceKey: z.ZodOptional<z.ZodString>;
582
606
  }, z.core.$strip>>>;
607
+ exclusion: z.ZodNullable<z.ZodEnum<{
608
+ disabled: "disabled";
609
+ unavailable: "unavailable";
610
+ "cannot-host-camera-root": "cannot-host-camera-root";
611
+ "accelerator-preferred": "accelerator-preferred";
612
+ }>>;
583
613
  }, z.core.$strip>>>;
584
614
  }, z.core.$strip>;
585
615
  /**
@@ -1027,6 +1057,12 @@ export declare const pipelineOrchestratorCapability: {
1027
1057
  settings: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1028
1058
  jumpDeviceKey: z.ZodOptional<z.ZodString>;
1029
1059
  }, z.core.$strip>>>;
1060
+ exclusion: z.ZodNullable<z.ZodEnum<{
1061
+ disabled: "disabled";
1062
+ unavailable: "unavailable";
1063
+ "cannot-host-camera-root": "cannot-host-camera-root";
1064
+ "accelerator-preferred": "accelerator-preferred";
1065
+ }>>;
1030
1066
  }, z.core.$strip>>>;
1031
1067
  }, z.core.$strip>, import("./capability-definition.js").CapabilityMethodKind>;
1032
1068
  /**
@@ -1887,4 +1923,5 @@ export type CameraRecordingMode = z.infer<typeof CameraRecordingModeSchema>;
1887
1923
  export type IngestOwner = z.infer<typeof IngestOwnerSchema>;
1888
1924
  export type NodeInferenceDevice = z.infer<typeof NodeInferenceDeviceSchema>;
1889
1925
  export type NodeInferenceDevices = z.infer<typeof NodeInferenceDevicesSchema>;
1890
- export { AgentLoadSummarySchema, CameraAssignmentStatusSchema, CameraAudioStatusSchema, CameraBrokerProfileSchema, CameraBrokerStatusSchema, CameraDecoderShmSchema, CameraDecoderStatusSchema, CameraDetectionPhaseSchema, CameraDetectionProvisioningSchema, CameraDetectionProvisioningStateSchema, CameraDetectionStatusSchema, CameraMotionStatusSchema, CameraPipelineConfigSchema, CameraRecordingModeSchema, CameraRecordingStatusSchema, CameraSourceStatusSchema, CameraSourceStreamSchema, CameraStatusDegradationReasonSchema, CameraStatusDegradationSchema, CameraStatusSchema, CameraStatusStageSchema, CameraStepOverridePatchSchema, CapabilityBindingsSchema, DiskReconcileJobSchema, GlobalMetricsSchema, IngestOwnerSchema, PipelineAssignmentSchema, PipelineTemplateSchema as OrchestratorPipelineTemplateSchema, };
1926
+ export type InferenceDeviceExclusionReason = z.infer<typeof InferenceDeviceExclusionReasonSchema>;
1927
+ export { AgentLoadSummarySchema, CameraAssignmentStatusSchema, CameraAudioStatusSchema, CameraBrokerProfileSchema, CameraBrokerStatusSchema, CameraDecoderShmSchema, CameraDecoderStatusSchema, CameraDetectionPhaseSchema, CameraDetectionProvisioningSchema, CameraDetectionProvisioningStateSchema, CameraDetectionStatusSchema, CameraMotionStatusSchema, CameraPipelineConfigSchema, CameraRecordingModeSchema, CameraRecordingStatusSchema, CameraSourceStatusSchema, CameraSourceStreamSchema, CameraStatusDegradationReasonSchema, CameraStatusDegradationSchema, CameraStatusSchema, CameraStatusStageSchema, CameraStepOverridePatchSchema, CapabilityBindingsSchema, DiskReconcileJobSchema, GlobalMetricsSchema, INFERENCE_DEVICE_EXCLUSION_REASONS, InferenceDeviceExclusionReasonSchema, IngestOwnerSchema, PipelineAssignmentSchema, PipelineTemplateSchema as OrchestratorPipelineTemplateSchema, };
@@ -55,6 +55,7 @@ declare const DetailResultSchema: z.ZodObject<{
55
55
  }, z.core.$strip>>;
56
56
  embedding: z.ZodOptional<z.ZodString>;
57
57
  embeddingMagnitude: z.ZodOptional<z.ZodNumber>;
58
+ embeddingModelId: z.ZodOptional<z.ZodString>;
58
59
  label: z.ZodOptional<z.ZodString>;
59
60
  labelTier: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<1>, z.ZodLiteral<2>]>>;
60
61
  labelModelId: z.ZodOptional<z.ZodString>;
@@ -628,6 +629,7 @@ export declare const pipelineRunnerCapability: {
628
629
  }, z.core.$strip>>;
629
630
  embedding: z.ZodOptional<z.ZodString>;
630
631
  embeddingMagnitude: z.ZodOptional<z.ZodNumber>;
632
+ embeddingModelId: z.ZodOptional<z.ZodString>;
631
633
  label: z.ZodOptional<z.ZodString>;
632
634
  labelTier: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<1>, z.ZodLiteral<2>]>>;
633
635
  labelModelId: z.ZodOptional<z.ZodString>;
@@ -707,6 +709,7 @@ export declare const pipelineRunnerCapability: {
707
709
  }, z.core.$strip>>;
708
710
  embedding: z.ZodOptional<z.ZodString>;
709
711
  embeddingMagnitude: z.ZodOptional<z.ZodNumber>;
712
+ embeddingModelId: z.ZodOptional<z.ZodString>;
710
713
  label: z.ZodOptional<z.ZodString>;
711
714
  labelTier: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<1>, z.ZodLiteral<2>]>>;
712
715
  labelModelId: z.ZodOptional<z.ZodString>;
@@ -18,8 +18,8 @@ export type { IBatteryOperated, IDoorbellButton, INativeSnapshot, IPanTiltZoom,
18
18
  export { getByPath, setByPath } from './path-util.js';
19
19
  export type { ReachabilityPollHandle, ReachabilityPollLogger, ReachabilityPollOptions, } from './reachability-poll.js';
20
20
  export { REACHABILITY_FAILURES_TO_OFFLINE, REACHABILITY_POLL_INTERVAL_MS, REACHABILITY_PROBE_TIMEOUT_MS, startReachabilityPoll, } from './reachability-poll.js';
21
- export type { RuntimeStateBridge } from './runtime-state-helpers.js';
22
- export { createRuntimeStateBridge } from './runtime-state-helpers.js';
21
+ export type { RuntimeStateBridge, RuntimeStateStaleReadPolicy, } from './runtime-state-helpers.js';
22
+ export { createRuntimeStateBridge, OPERATOR_WRITTEN_STALE_MS, RUNTIME_STATE_REFRESH_MISS_COOLDOWN_MS, } from './runtime-state-helpers.js';
23
23
  export type { WireableField } from './schema-fields.js';
24
24
  export { enumerateItemArrayFields, enumerateSchemaFields } from './schema-fields.js';
25
25
  export type { DeviceConfigEntry } from './zod-to-config-ui.js';
@@ -13,6 +13,45 @@ import type { IDeviceRuntimeState } from './device-runtime-state.js';
13
13
  * coming back; per-read is enough to stall the viewer's first paint.
14
14
  */
15
15
  export declare const RUNTIME_STATE_REFRESH_MISS_COOLDOWN_MS = 60000;
16
+ /**
17
+ * The freshness window for a cap whose value changes ONLY when WE write it.
18
+ *
19
+ * The usual `staleMs: 10_000` is tuned for a reading that moves on its own — a
20
+ * battery level, a day/night state that flips at dusk. It is the wrong number
21
+ * for a cap like `privacy-mask`, whose two facts (is the video mask on, is the
22
+ * microphone on) change when an operator changes them, through a `setMask` /
23
+ * `setAudioEnabled` that **re-reads the camera and rewrites this very slice**.
24
+ * A write is therefore its own invalidation: the window never delays an
25
+ * operator's own change, however long it is.
26
+ *
27
+ * What the window really bounds is the ONE case we do not write: somebody
28
+ * changing the mask in the vendor app or the camera's web UI. Ten minutes is
29
+ * the trade — that change is visible within ten minutes, and a fleet of 29
30
+ * cameras behind a page that polls every 5s costs about 3 camera round trips a
31
+ * minute instead of 696
32
+ * ([D221](../../../../docs/decisions/adr-0221-a-polled-list-never-dials-a-camera.md)).
33
+ *
34
+ * Use it ONLY with {@link RuntimeStateStaleReadPolicy} `'serve-and-revalidate'`.
35
+ * On the awaiting default a window this long does not remove the stall, it
36
+ * merely makes it rarer and just as long.
37
+ */
38
+ export declare const OPERATOR_WRITTEN_STALE_MS: number;
39
+ /**
40
+ * What a read does when the slice it finds is STALE **and present**.
41
+ *
42
+ * - `'await-refresh'` (default) — the caller waits for the camera. Right for a
43
+ * reader that asked BECAUSE it wants the current value: an open settings
44
+ * form, a write path reading back what the firmware accepted.
45
+ * - `'serve-and-revalidate'` — the caller is answered from the slice
46
+ * immediately and the refresh runs behind it, for the next caller. Right for
47
+ * a POLLED reader, which by definition will ask again shortly and must never
48
+ * put a camera round trip on a request path (D49, D221).
49
+ *
50
+ * A COLD slice — one that was never fetched — awaits under both policies. The
51
+ * first render has to be a real answer rather than a flash of the `empty()`
52
+ * default, and a default is exactly what "the operator muted this" looks like.
53
+ */
54
+ export type RuntimeStateStaleReadPolicy = 'await-refresh' | 'serve-and-revalidate';
16
55
  /**
17
56
  * Minimal logger surface the bridge uses. Declared with METHOD syntax
18
57
  * (not a property arrow) so the parameter check is bivariant — a scoped
@@ -69,6 +108,23 @@ export interface RuntimeStateBridgeLogger {
69
108
  * helper stays thin so a single provider can host multiple cap-bridged
70
109
  * readers without fighting over a shared promise.
71
110
  *
111
+ * ## The freshness window belongs to the READER, not to the cap
112
+ *
113
+ * `staleMs` plus {@link RuntimeStateStaleReadPolicy} are what make this the
114
+ * ONLY cache in front of a cap. Before D221 they were not: `privacy-mask` kept
115
+ * the 10s window meant for a self-changing reading while a fleet-wide list
116
+ * polled it every 5s, so the slice was stale on nearly every read and the badge
117
+ * dialled 29 cameras twelve times a minute. The answer was a SECOND cache in
118
+ * the consumer — two authorities over one fact, and the write path that did not
119
+ * route through that consumer (the mask editor, which writes the cap directly)
120
+ * left it lying.
121
+ *
122
+ * So a cap whose value only an operator changes takes
123
+ * {@link OPERATOR_WRITTEN_STALE_MS} and `'serve-and-revalidate'`, here, once:
124
+ * the write path already re-reads the camera into this slice, which is a
125
+ * stronger invalidation than any downstream mirror can offer, and no consumer
126
+ * needs a cache of its own.
127
+ *
72
128
  * ## A refresh that does not LAND is a miss, and a miss costs the caller
73
129
  *
74
130
  * Providers swallow their own camera errors (they keep the last slice
@@ -91,8 +147,10 @@ export interface RuntimeStateBridgeLogger {
91
147
  */
92
148
  export interface RuntimeStateBridge<TStatus> {
93
149
  /** Run a stale-check; if the slice is missing or older than
94
- * `staleMs`, await `refresh()`. Idempotent within the freshness
95
- * window back-to-back calls touch zero camera I/O. */
150
+ * `staleMs`, refresh it awaiting the camera, or behind the caller
151
+ * when `staleRead` is `'serve-and-revalidate'` and a slice already
152
+ * exists. Idempotent within the freshness window — back-to-back calls
153
+ * touch zero camera I/O. */
96
154
  readonly ensureFresh: () => Promise<void>;
97
155
  /** Drop-in `getStatus` provider method. Includes the cross-device
98
156
  * guard + freshness check + status projection from the slice. */
@@ -113,6 +171,9 @@ export declare function createRuntimeStateBridge<TCap extends CapabilityDefiniti
113
171
  readonly empty: () => z.infer<TCap['status']['schema']>;
114
172
  /** Override the miss cooldown (tests, or a cap whose fetch is cheap). */
115
173
  readonly refreshMissCooldownMs?: number;
174
+ /** What a stale-but-present slice does. Defaults to `'await-refresh'`,
175
+ * which is what every caller did before the policy existed. */
176
+ readonly staleRead?: RuntimeStateStaleReadPolicy;
116
177
  /** Scoped logger so a refresh that never lands is visible per-device. */
117
178
  readonly logger?: RuntimeStateBridgeLogger;
118
179
  }): RuntimeStateBridge<z.infer<TCap['status']['schema']>>;
package/dist/index.d.ts CHANGED
@@ -153,8 +153,8 @@ export type { IBatteryOperated, IDoorbellButton, INativeSnapshot, IPanTiltZoom,
153
153
  export { getByPath, setByPath } from './device/path-util.js';
154
154
  export type { ReachabilityPollHandle, ReachabilityPollLogger, ReachabilityPollOptions, } from './device/reachability-poll.js';
155
155
  export { REACHABILITY_FAILURES_TO_OFFLINE, REACHABILITY_POLL_INTERVAL_MS, REACHABILITY_PROBE_TIMEOUT_MS, startReachabilityPoll, } from './device/reachability-poll.js';
156
- export type { RuntimeStateBridge } from './device/runtime-state-helpers.js';
157
- export { createRuntimeStateBridge } from './device/runtime-state-helpers.js';
156
+ export type { RuntimeStateBridge, RuntimeStateStaleReadPolicy, } from './device/runtime-state-helpers.js';
157
+ export { createRuntimeStateBridge, OPERATOR_WRITTEN_STALE_MS, RUNTIME_STATE_REFRESH_MISS_COOLDOWN_MS, } from './device/runtime-state-helpers.js';
158
158
  export type { WireableField } from './device/schema-fields.js';
159
159
  export { enumerateItemArrayFields, enumerateSchemaFields } from './device/schema-fields.js';
160
160
  export type { SourceInfo } from './device/source-info.js';
@@ -199,7 +199,8 @@ export { isScheduleActive } from './notification/schedule.js';
199
199
  export { NC_SYSTEM_EVENT_FILTER_KEYS, type NcSystemEventFilterKey, systemEventFilterApplies, systemEventFilterAppliesToAnyKind, } from './notification/system-event-filters.js';
200
200
  export type { TimelapseCadencePair, TimelapsePreviewMode, TimelapseRule, TimelapseRuleInput, TimelapseRulePatch, TimelapseTemplate, } from './notification/timelapse-rule.js';
201
201
  export { assertTimelapseCadences, DEFAULT_TIMELAPSE_PREVIEW_TEXT, readTimelapseGeneratedAt, TIMELAPSE_DENSE_FLOOR_SEC, TimelapseRuleInputSchema, TimelapseRulePatchSchema, TimelapseRuleSchema, TimelapseTemplateSchema, } from './notification/timelapse-rule.js';
202
- export { DEFAULT_DETAIL_CROP_CONVENTION, DETAIL_CROP_PADDING_FIELD, DETAIL_CROP_PADDING_KEY, DETAIL_CROP_SECTION_ID, DETAIL_CROP_SQUARE_KEY, type DetailCropConvention, DetailCropConventionSchema, type DetailCropRect, deriveDetailCropRect, type HydratedSettingsSection, type HydratedSettingsView, pickDetailCropConvention, readDetailCropConvention, } from './pipeline/detail-crop.js';
202
+ export { CLUSTER_MODEL_SCOPED_STEPS, CLUSTER_MODEL_SECTION_ID, type ClusterModelScopedStep, type ClusterStepModels, clusterModelSettingKey, DEFAULT_CLUSTER_STEP_MODELS, type HydratedClusterSection, type HydratedClusterView, isClusterScopedStep, pickClusterStepModels, readClusterStepModels, resolveClusterStepModelId, type StepModelScope, } from './pipeline/cluster-model-scope.js';
203
+ export { DEFAULT_DETAIL_CROP_CONVENTION, DETAIL_CROP_PADDING_FIELD, DETAIL_CROP_PADDING_KEY, DETAIL_CROP_SECTION_ID, DETAIL_CROP_SQUARE_KEY, FULL_IMAGE_BBOX, type DetailCropConvention, DetailCropConventionSchema, type DetailCropRect, deriveDetailCropRect, type HydratedSettingsSection, type HydratedSettingsView, pickDetailCropConvention, readDetailCropConvention, } from './pipeline/detail-crop.js';
203
204
  export { DEFAULT_NATIVE_LEASE_SETTINGS, NATIVE_LEASE_ACTIVITY_FIELD, NATIVE_LEASE_ACTIVITY_KEY, NATIVE_LEASE_ADMISSION_FIELD, NATIVE_LEASE_ADMISSION_KEY, NATIVE_LEASE_BUDGET_FIELD, NATIVE_LEASE_BUDGET_KEY, NATIVE_LEASE_HOLD_FIELD, NATIVE_LEASE_HOLD_KEY, NATIVE_LEASE_SECTION_ID, NATIVE_LEASE_TILE_BUDGET_FIELD, NATIVE_LEASE_TILE_BUDGET_KEY, type NativeLeaseAdmission, NativeLeaseAdmissionSchema, type NativeLeaseKnob, type NativeLeaseNumberKnob, type NativeLeaseSettings, type NativeLeaseSettingsOverride, NativeLeaseSettingsSchema, pickNativeLeaseOverride, readNativeLeaseOverride, } from './pipeline/native-lease.js';
204
205
  export { ACCESS_ROLES, type AccessRoleAssignment, type AccessRoleId, type AccessRoleSpec, buildRoleScopes, detectAccessRole, roleSpec, } from './schemas/access-roles.js';
205
206
  export { type ApiKeyRecord, ApiKeyRecordSchema, type CapScope, CapScopeSchema, type DeviceSelector, DeviceSelectorSchema, type DeviceTokenScope, type MethodAccess, MethodAccessSchema, type ScopedToken, ScopedTokenSchema, type TokenScope, TokenScopeSchema, type UserRecord, UserRecordSchema, } from './schemas/auth-records.js';