camstack 1.2.45 → 1.2.47

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.
@@ -14522,7 +14522,7 @@ function date4(params) {
14522
14522
  // ../../node_modules/zod/v4/classic/external.js
14523
14523
  config(en_default());
14524
14524
 
14525
- // ../types/dist/sleep-DJlqY62B.mjs
14525
+ // ../types/dist/sleep-CdbM8ge4.mjs
14526
14526
  var WELL_KNOWN_TABS = [
14527
14527
  {
14528
14528
  id: "overview",
@@ -15603,6 +15603,28 @@ var OpsLogQueryInputSchema = external_exports.object({
15603
15603
  /** Max rows returned, newest-first. */
15604
15604
  limit: external_exports.number().int().min(1).max(1e3).optional()
15605
15605
  });
15606
+ var LabelDefinitionSchema = external_exports.object({
15607
+ id: external_exports.string(),
15608
+ name: external_exports.string(),
15609
+ category: external_exports.string().optional(),
15610
+ description: external_exports.string().optional(),
15611
+ icon: external_exports.string().optional()
15612
+ });
15613
+ var CLASS_MAP_MACRO_TARGETS = [
15614
+ "person",
15615
+ "vehicle",
15616
+ "animal",
15617
+ "package"
15618
+ ];
15619
+ var FIRST_LEVEL_MACRO_CLASSES = [
15620
+ "person",
15621
+ "vehicle",
15622
+ "animal"
15623
+ ];
15624
+ var DetectionCatalogClassMapSchema = external_exports.object({
15625
+ mapping: external_exports.record(external_exports.string(), external_exports.enum(CLASS_MAP_MACRO_TARGETS)),
15626
+ preserveOriginal: external_exports.boolean()
15627
+ });
15606
15628
  var RecordingWeekdaySchema = external_exports.number().int().min(0).max(6);
15607
15629
  var HHMM = /^([01]\d|2[0-3]):[0-5]\d$/;
15608
15630
  var RecordingStorageModeSchema = external_exports.enum([
@@ -15610,9 +15632,42 @@ var RecordingStorageModeSchema = external_exports.enum([
15610
15632
  "events",
15611
15633
  "continuous"
15612
15634
  ]);
15635
+ var RecordingObjectTriggerClassSchema = external_exports.enum(FIRST_LEVEL_MACRO_CLASSES);
15636
+ var noDuplicates = (values) => new Set(values).size === values.length;
15613
15637
  var RecordingTriggersSchema = external_exports.object({
15614
15638
  motion: external_exports.boolean().optional(),
15615
- audioThresholdDbfs: external_exports.number().optional()
15639
+ audioThresholdDbfs: external_exports.number().optional(),
15640
+ /**
15641
+ * Le macro classi la cui detection apre una finestra. ASSENTE = la sorgente
15642
+ * non è ascoltata; un array VUOTO è rifiutato, perché "banda events, trigger
15643
+ * object acceso, nessuna classe" è la stessa forma "abilitata e non registra
15644
+ * nulla, per sempre" contro cui è scritto `eventsBandCanEverDemand`.
15645
+ *
15646
+ * Il segnale letto è GIÀ FILTRATO: solo detection `source: 'pipeline'`, cioè
15647
+ * quelle che hanno attraversato `enabledMacroClasses`, i
15648
+ * `minConfidence<Macro>` e il full-frame guard. L'AI a bordo camera
15649
+ * (`source: 'onboard'`) non attraversa nessuno di quei gate e NON apre
15650
+ * finestre — vedi `recorder/object-trigger.ts`.
15651
+ */
15652
+ objectClasses: external_exports.array(RecordingObjectTriggerClassSchema).min(1).refine(noDuplicates, { message: "objectClasses must not repeat a class" }).optional(),
15653
+ /**
15654
+ * I device LINKED il cui FRONTE ALTO apre una finestra. Assente = la sorgente
15655
+ * non è ascoltata; un array vuoto è rifiutato per la stessa ragione di
15656
+ * `objectClasses`.
15657
+ *
15658
+ * Sono id di device SORGENTE, non camere: la banda li nomina, quindi il
15659
+ * percorso caldo (`DeviceStateChanged`, a ritmo di bus su tutta la flotta)
15660
+ * non fa RPC. L'OFFERTA da cui l'operatore li sceglie è un'altra domanda, e
15661
+ * si risolve con `deviceManager.getLinkedDevices` + `getBindingsBatch` per
15662
+ * device (D12) — mai un elenco globale di cap.
15663
+ *
15664
+ * Cosa vuol dire "alto" dipende dal TIPO di device e non è deciso qui:
15665
+ * `SOURCE_CAP_ACTIVE_FIELD` (`catalogs/sensor-active-state.ts`) è LA tabella,
15666
+ * la stessa che il virtual-doorbell usa dal 2026-08-05. Ed è il FRONTE, non
15667
+ * il livello: un contatto trovato già aperto al riavvio del runner non fa
15668
+ * registrare.
15669
+ */
15670
+ sensorDeviceIds: external_exports.array(external_exports.number().int().positive()).min(1).max(16).refine(noDuplicates, { message: "sensorDeviceIds must not repeat a device" }).optional()
15616
15671
  });
15617
15672
  var RecordingBandModeSchema = external_exports.enum(["continuous", "events"]);
15618
15673
  var RecordingBandTriggersSchema = RecordingTriggersSchema;
@@ -15929,23 +15984,6 @@ var DecoderSessionConfigSchema = external_exports.object({
15929
15984
  */
15930
15985
  debug: external_exports.boolean().optional()
15931
15986
  });
15932
- var LabelDefinitionSchema = external_exports.object({
15933
- id: external_exports.string(),
15934
- name: external_exports.string(),
15935
- category: external_exports.string().optional(),
15936
- description: external_exports.string().optional(),
15937
- icon: external_exports.string().optional()
15938
- });
15939
- var CLASS_MAP_MACRO_TARGETS = [
15940
- "person",
15941
- "vehicle",
15942
- "animal",
15943
- "package"
15944
- ];
15945
- var DetectionCatalogClassMapSchema = external_exports.object({
15946
- mapping: external_exports.record(external_exports.string(), external_exports.enum(CLASS_MAP_MACRO_TARGETS)),
15947
- preserveOriginal: external_exports.boolean()
15948
- });
15949
15987
  var MODEL_FORMATS = [
15950
15988
  "onnx",
15951
15989
  "coreml",
@@ -23694,7 +23732,23 @@ var NcHistoryEntrySchema = external_exports.object({
23694
23732
  updatedAt: external_exports.number(),
23695
23733
  /** Failure detail — present on a `dead` row. */
23696
23734
  error: external_exports.string().optional(),
23697
- subject: NcHistorySubjectSchema
23735
+ subject: NcHistorySubjectSchema,
23736
+ /**
23737
+ * Ids of the artefacts (still, then gif, then clip) this row's successful
23738
+ * delivery indexed in the artefact library — a REFERENCE, never the bytes
23739
+ * (an artefact is often megabytes; this row is durable JSON rewritten on
23740
+ * every delivery attempt). Absent on a row still pending/dead, a row
23741
+ * delivered before this field shipped, or a wiring with no artefact index.
23742
+ *
23743
+ * Resolve one to a fetchable URL with `resolveArtifactUrl` — an id
23744
+ * outlives any one URL's TTL, so a caller mints a fresh link on demand
23745
+ * rather than trusting one frozen at delivery time. `resolveArtifactUrl`
23746
+ * also answers `null` for an id whose artefact has since expired past the
23747
+ * retained shelf's own age bound — the degrade a caller (the Home
23748
+ * Assistant export) must render as "no image right now", never as a
23749
+ * broken link.
23750
+ */
23751
+ artifactIds: external_exports.array(external_exports.string().min(1)).optional()
23698
23752
  });
23699
23753
  var NcHistoryFilterSchema = external_exports.object({
23700
23754
  ruleId: external_exports.string().optional(),
@@ -23940,6 +23994,20 @@ var notificationRulesCapability = {
23940
23994
  */
23941
23995
  getHistory: method(external_exports.object({ filter: NcHistoryFilterSchema.default({ limit: 100 }) }), external_exports.object({ entries: external_exports.array(NcHistoryEntrySchema) }), { auth: "admin" }),
23942
23996
  /**
23997
+ * Mint a fresh, externally-reachable URL for one artefact a history row
23998
+ * named in {@link NcHistoryEntrySchema.shape.artifactIds} — the SAME
23999
+ * signed-link mechanism the dispatcher uses to attach media to an
24000
+ * outgoing notification (one derivation; this never re-implements it).
24001
+ *
24002
+ * `url: null` on THREE causes a caller must treat identically ("no image
24003
+ * right now", never a broken link): the id is unknown, its artefact has
24004
+ * expired past the retained shelf's own age bound, or this install has no
24005
+ * externally-reachable base URL. A caller that received a URL on a
24006
+ * previous call and now gets `null` must stop showing it — a link that
24007
+ * worked five minutes ago is not proof it works now.
24008
+ */
24009
+ resolveArtifactUrl: method(external_exports.object({ artifactId: external_exports.string().min(1) }), external_exports.object({ url: external_exports.string().nullable() }), { auth: "admin" }),
24010
+ /**
23943
24011
  * Snooze windows currently in effect, plus any whose digest has not yet
23944
24012
  * gone out. `caller: 'required'`: a user sees their OWN windows and the
23945
24013
  * global ones that silence them, never another person's private silence.
@@ -29804,7 +29872,7 @@ var lifecycleJobSchema = external_exports.object({
29804
29872
  state: lifecycleJobStateSchema,
29805
29873
  schemaVersion: external_exports.literal(1)
29806
29874
  });
29807
- var LogLevelSchema$1 = external_exports.enum([
29875
+ var LogLevelSchema$2 = external_exports.enum([
29808
29876
  "debug",
29809
29877
  "info",
29810
29878
  "warn",
@@ -30004,7 +30072,7 @@ var addonsCapability = {
30004
30072
  getLogs: method(external_exports.object({
30005
30073
  addonId: external_exports.string(),
30006
30074
  limit: external_exports.number().min(1).max(500).default(100),
30007
- level: LogLevelSchema$1.optional()
30075
+ level: LogLevelSchema$2.optional()
30008
30076
  }), external_exports.array(LogQueryEntrySchema)),
30009
30077
  listPackages: method(external_exports.void(), external_exports.array(InstalledPackageSchema).readonly()),
30010
30078
  installPackage: method(external_exports.object({
@@ -30242,7 +30310,7 @@ var addonsCapability = {
30242
30310
  }),
30243
30311
  onAddonLogs: method(external_exports.object({
30244
30312
  addonId: external_exports.string(),
30245
- level: LogLevelSchema$1.optional()
30313
+ level: LogLevelSchema$2.optional()
30246
30314
  }), LogStreamEntrySchema, { kind: "subscription" })
30247
30315
  },
30248
30316
  /** BIG PLAN 2: declarative mount hint — read by `@camstack/system` `buildCapRouters`. */
@@ -31701,6 +31769,14 @@ var FaceFilterEnum = external_exports.enum([
31701
31769
  "identified",
31702
31770
  "all"
31703
31771
  ]);
31772
+ var FaceSortFieldEnum = external_exports.enum(["timestamp", "suggestionConfidence"]);
31773
+ var FaceSortDirectionEnum = external_exports.enum(["asc", "desc"]);
31774
+ var FaceClusterSchema = external_exports.object({
31775
+ faceIds: external_exports.array(external_exports.string()).readonly(),
31776
+ representativeFaceId: external_exports.string(),
31777
+ size: external_exports.number().int(),
31778
+ cohesion: external_exports.number()
31779
+ });
31704
31780
  var MediaFileLiteSchema$1 = external_exports.object({
31705
31781
  key: external_exports.string(),
31706
31782
  kind: external_exports.string(),
@@ -31759,24 +31835,72 @@ var faceGalleryCapability = {
31759
31835
  auth: "admin"
31760
31836
  }),
31761
31837
  listRecentFaces: method(external_exports.object({
31762
- /** Restrict to one camera. Absent keeps the cluster-wide gallery view. */
31838
+ /**
31839
+ * Restrict to ONE camera. Absent keeps the cluster-wide gallery view.
31840
+ *
31841
+ * The legacy single-camera form, kept verbatim for every caller that
31842
+ * already sends it. A caller that wants a SET sends {@link deviceIds}
31843
+ * instead — never both: `deviceIds` is the authority whenever it is
31844
+ * present, and this field is then ignored rather than unioned, so
31845
+ * there is exactly one answer to "which cameras did I ask for".
31846
+ */
31763
31847
  deviceId: external_exports.number().int().optional(),
31848
+ /**
31849
+ * Restrict to a SET of cameras — the review UI's camera filter, which
31850
+ * until now had to fetch the cluster-wide page and drop rows in the
31851
+ * client (so the `limit` it asked for was spent on cameras it was
31852
+ * about to discard).
31853
+ *
31854
+ * An **empty array reads NOTHING** — `[]` is an empty page, never
31855
+ * "every camera". A request for no devices is a request, not an
31856
+ * omission; same contract as `deviceManager.listFleet` and
31857
+ * `pipelineAnalytics.listRecentTracks`.
31858
+ *
31859
+ * Absent (`undefined`) is the omission, and keeps the cluster-wide view.
31860
+ */
31861
+ deviceIds: external_exports.array(external_exports.number().int()).optional(),
31764
31862
  limit: external_exports.number().int().positive().optional(),
31765
31863
  filter: FaceFilterEnum.optional(),
31766
31864
  /**
31767
- * Inline the base64 crop on every row. Default `true` — the existing
31768
- * behaviour, kept so no caller breaks.
31865
+ * Window lower bound on {@link FaceInfo.timestamp}, INCLUSIVE.
31866
+ * Absent means no lower bound.
31867
+ */
31868
+ since: external_exports.number().int().optional(),
31869
+ /**
31870
+ * Window upper bound on {@link FaceInfo.timestamp}, INCLUSIVE.
31871
+ * Absent means no upper bound.
31872
+ */
31873
+ until: external_exports.number().int().optional(),
31874
+ /**
31875
+ * Order the page by time or by suggestion certainty. Default
31876
+ * `'timestamp'` — the historical order, unchanged for every caller
31877
+ * that does not ask.
31769
31878
  *
31770
- * Set `false` once the caller renders {@link FaceInfo.cropUrl}: that
31771
- * drops ~2.87 MiB per 500-row page to a few KiB of metadata and lets
31772
- * the browser cache the images.
31879
+ * See {@link FaceSortFieldEnum} for what a row with no suggestion
31880
+ * does under `'suggestionConfidence'`.
31773
31881
  *
31774
- * **This is an INPUT field, so it does not reach the addon until the
31775
- * next train.** The hub router validates cap inputs against its own
31776
- * compiled Zod, which strips a key it does not know verified today
31777
- * on the OUTPUT side, where an additive field DOES arrive immediately
31778
- * (`Track.hasFace`). Until the train ships, sending `false` is
31779
- * harmless and simply keeps the crops inline.
31882
+ * Cost note: `'timestamp'` is served by the `(deviceId, timestamp)`
31883
+ * index and stops reading as soon as `limit` rows have PASSED the
31884
+ * filter. `'suggestionConfidence'` cannot stop earlythe most
31885
+ * certain row may be the oldest so it walks the window. Narrow it
31886
+ * with {@link since} / {@link until}.
31887
+ */
31888
+ sortBy: FaceSortFieldEnum.optional(),
31889
+ /** Sort direction for {@link sortBy}. Default `'desc'`. */
31890
+ sortDirection: FaceSortDirectionEnum.optional(),
31891
+ /**
31892
+ * Inline the base64 crop on every row.
31893
+ *
31894
+ * Default `false` since the 2026-08-25 inversion — see
31895
+ * `include-crops-default.ts`, which is the ONE place that resolves
31896
+ * this for every gallery, and which records why the inline shape had
31897
+ * to become the one you ASK for (60 457 ms → UDS timeout at 500 rows).
31898
+ * The doc here used to still say `true`; it was wrong, and a leftover
31899
+ * that describes the old design reads as permission to rely on it.
31900
+ *
31901
+ * Nothing loses its image: the row carries {@link FaceInfo.cropUrl},
31902
+ * which the browser fetches off the `event-media` plane in parallel,
31903
+ * cached and ETagged.
31780
31904
  */
31781
31905
  includeCrops: external_exports.boolean().optional()
31782
31906
  }).optional(), external_exports.array(FaceInfoSchema).readonly()),
@@ -31825,13 +31949,39 @@ var faceGalleryCapability = {
31825
31949
  suggestFaceClusters: method(external_exports.object({
31826
31950
  threshold: external_exports.number().min(0).max(1).optional(),
31827
31951
  minClusterSize: external_exports.number().int().min(2).optional(),
31828
- limit: external_exports.number().int().positive().optional()
31829
- }).optional(), external_exports.array(external_exports.object({
31830
- faceIds: external_exports.array(external_exports.string()).readonly(),
31831
- representativeFaceId: external_exports.string(),
31832
- size: external_exports.number().int(),
31833
- cohesion: external_exports.number()
31834
- })).readonly())
31952
+ /**
31953
+ * Cap on the number of CLUSTERS returned. Renamed from `limit`,
31954
+ * which read as though it bounded the work — it never did.
31955
+ *
31956
+ * Wins over {@link limit} when both are sent.
31957
+ */
31958
+ maxClusters: external_exports.number().int().positive().optional(),
31959
+ /**
31960
+ * @deprecated Ambiguous name for {@link maxClusters} — it cuts the
31961
+ * RESULT, not the scan. Kept so existing callers keep working; send
31962
+ * `maxClusters` (and, if you care about cost, {@link maxFacesScanned}).
31963
+ */
31964
+ limit: external_exports.number().int().positive().optional(),
31965
+ /**
31966
+ * Cap on the number of unassigned faces READ AND CLUSTERED — the
31967
+ * POOL, not the result.
31968
+ *
31969
+ * This is the knob {@link maxClusters} was mistaken for. Clustering
31970
+ * used to read every unassigned face on the hub no matter what the
31971
+ * caller asked for, because the only bound cut the finished clusters
31972
+ * afterwards; a UI showing a window of 100 paid for a scan of the
31973
+ * whole corpus, on an addon whose disk is under contention.
31974
+ *
31975
+ * The pool is the NEWEST matching faces first — the same order the
31976
+ * gallery shows — so a bound here shortens the horizon, it does not
31977
+ * sample it randomly.
31978
+ *
31979
+ * Default: 1 000 (`FACE_SWEEP_PAGE`, exactly one store page). Chosen
31980
+ * so the live corpus — 372 face rows — is unaffected while the
31981
+ * unbounded scan can never come back as the table grows.
31982
+ */
31983
+ maxFacesScanned: external_exports.number().int().positive().optional()
31984
+ }).optional(), external_exports.array(FaceClusterSchema).readonly())
31835
31985
  }
31836
31986
  };
31837
31987
  var FanDirectionSchema = external_exports.enum(["forward", "reverse"]);
@@ -35381,6 +35531,23 @@ var ReadGopBytesResultSchema = external_exports.object({
35381
35531
  /** Media ms the returned fragment covers. */
35382
35532
  gopDurMs: external_exports.number()
35383
35533
  });
35534
+ var ReadWindowBytesResultSchema = external_exports.discriminatedUnion("kind", [external_exports.object({
35535
+ kind: external_exports.literal("ok"),
35536
+ data: external_exports.instanceof(Uint8Array),
35537
+ /** Absolute epoch ms of the returned bytes' first sample — at or before
35538
+ * the requested `fromMs` (anchored on the nearest keyframe). */
35539
+ gopStartMs: external_exports.number(),
35540
+ /** Media ms the returned bytes cover, from `gopStartMs`. */
35541
+ gopDurMs: external_exports.number(),
35542
+ /** `false` ⇒ the safety byte cap cut the read short before it reached
35543
+ * the requested `toMs`; the caller got fewer frames than asked for. */
35544
+ reachesRequestedEnd: external_exports.boolean()
35545
+ }), external_exports.object({
35546
+ kind: external_exports.literal("spans-multiple-segments"),
35547
+ /** Where the covering segment's own footage runs out — informational,
35548
+ * not a retry hint (retrying the same window would refuse again). */
35549
+ segmentEndMs: external_exports.number()
35550
+ })]);
35384
35551
  var recordingCapability = {
35385
35552
  name: "recording",
35386
35553
  scope: "system",
@@ -35460,6 +35627,21 @@ var recordingCapability = {
35460
35627
  kind: "query",
35461
35628
  auth: "admin"
35462
35629
  }),
35630
+ /** Read a WINDOW `[fromMs, toMs)` of segment `startMs`, by mfra byte
35631
+ * range — the multi-GOP twin of `readGopBytes`. Refuses (does not
35632
+ * degrade) when the window runs past the covering segment. Used by the
35633
+ * replay clip's `recording` source to fetch several seconds of native
35634
+ * footage for its single ffmpeg decode pass. */
35635
+ readWindowBytes: method(external_exports.object({
35636
+ deviceId: external_exports.number(),
35637
+ profile: external_exports.string(),
35638
+ startMs: external_exports.number(),
35639
+ fromMs: external_exports.number(),
35640
+ toMs: external_exports.number()
35641
+ }), ReadWindowBytesResultSchema, {
35642
+ kind: "query",
35643
+ auth: "admin"
35644
+ }),
35463
35645
  setDeviceConfig: method(external_exports.object({
35464
35646
  deviceId: external_exports.number(),
35465
35647
  config: RecordingConfigSchema
@@ -36399,6 +36581,121 @@ var SetSiteLocationInputSchema = external_exports.object({
36399
36581
  latitude: external_exports.number().min(-90).max(90),
36400
36582
  longitude: external_exports.number().min(-180).max(180)
36401
36583
  }).nullable();
36584
+ var RequestCensusGroupSchema = external_exports.object({
36585
+ procedure: external_exports.string(),
36586
+ userAgent: external_exports.string(),
36587
+ ip: external_exports.string(),
36588
+ principal: external_exports.string(),
36589
+ calls: external_exports.number(),
36590
+ perMin: external_exports.number()
36591
+ });
36592
+ var RequestCensusProcedureSchema = external_exports.object({
36593
+ procedure: external_exports.string(),
36594
+ calls: external_exports.number(),
36595
+ perMin: external_exports.number()
36596
+ });
36597
+ var RequestCensusSnapshotSchema = external_exports.object({
36598
+ armed: external_exports.boolean(),
36599
+ /** How long the current - or just-closed - window collected, in ms. */
36600
+ elapsedMs: external_exports.number(),
36601
+ /** The window actually armed, after the server clamped the request. */
36602
+ windowMs: external_exports.number(),
36603
+ /** Epoch ms the window closes at. 0 when disarmed. */
36604
+ armedUntilMs: external_exports.number(),
36605
+ httpRequests: external_exports.number(),
36606
+ batchedRequests: external_exports.number(),
36607
+ /**
36608
+ * Procedure invocations. Higher than `httpRequests` whenever tRPC batching
36609
+ * is in play (`?batch=1` carries several procedures in one request); this is
36610
+ * the number comparable with a store-side call count.
36611
+ */
36612
+ procedureCalls: external_exports.number(),
36613
+ /**
36614
+ * tRPC WebSocket connections opened during the window. NOT calls - the WS
36615
+ * transport resolves one context per connection - but the number that says
36616
+ * whether a plane this census cannot see was busy while HTTP was quiet.
36617
+ */
36618
+ wsConnections: external_exports.number(),
36619
+ distinctGroups: external_exports.number(),
36620
+ /** Calls counted in the totals whose group attribution was shed at the
36621
+ * cardinality bound. */
36622
+ unattributedCalls: external_exports.number(),
36623
+ procedures: external_exports.array(RequestCensusProcedureSchema).readonly(),
36624
+ groups: external_exports.array(RequestCensusGroupSchema).readonly()
36625
+ });
36626
+ var RequestCensusStatusSchema = RequestCensusSnapshotSchema.extend({ persisted: external_exports.boolean() });
36627
+ var LogLevelSchema$1 = external_exports.enum([
36628
+ "debug",
36629
+ "info",
36630
+ "warn",
36631
+ "error"
36632
+ ]);
36633
+ var DiagnosticIdSchema = external_exports.enum(["request-census"]);
36634
+ var LoggingScopeKindSchema = external_exports.enum([
36635
+ "cluster",
36636
+ "node",
36637
+ "component"
36638
+ ]);
36639
+ var LoggingLevelSourceSchema = external_exports.enum([
36640
+ "default",
36641
+ "cluster",
36642
+ "node",
36643
+ "component"
36644
+ ]);
36645
+ var LoggingLevelLayerSchema = external_exports.object({
36646
+ scope: LoggingScopeKindSchema,
36647
+ /** The node this layer speaks for; `null` on the cluster layer. */
36648
+ nodeId: external_exports.string().nullable(),
36649
+ /** Explicitly set here, or `null` when this layer inherits. */
36650
+ level: LogLevelSchema$1.nullable()
36651
+ });
36652
+ var LoggingEffectiveSchema = external_exports.object({
36653
+ level: LogLevelSchema$1,
36654
+ levelSource: LoggingLevelSourceSchema
36655
+ });
36656
+ var LoggingExplicitSchema = external_exports.object({ layers: external_exports.array(LoggingLevelLayerSchema).readonly() });
36657
+ var DiagnosticWindowSchema = external_exports.object({
36658
+ id: DiagnosticIdSchema,
36659
+ armed: external_exports.boolean(),
36660
+ /** Epoch ms the window closes at. 0 when disarmed. */
36661
+ armedUntilMs: external_exports.number(),
36662
+ /** Ms left before it expires on its own. 0 when disarmed. */
36663
+ remainingMs: external_exports.number(),
36664
+ /** Whether the stored deadline is the one the live diagnostic is running —
36665
+ * i.e. whether this window would survive a restart. */
36666
+ persisted: external_exports.boolean()
36667
+ });
36668
+ var DiagnosticWindowPatchSchema = external_exports.object({
36669
+ id: DiagnosticIdSchema,
36670
+ armMs: external_exports.number().int().min(0),
36671
+ /** Cadence of the diagnostic's aggregated report line. Clamped by the server. */
36672
+ reportEveryMs: external_exports.number().int().positive().optional()
36673
+ });
36674
+ var LoggingSettingsPatchSchema = external_exports.object({
36675
+ /**
36676
+ * Absent leaves the level untouched. `null` CLEARS the explicit value at the
36677
+ * addressed scope so it inherits again. A value sets it.
36678
+ */
36679
+ level: LogLevelSchema$1.nullable().optional(),
36680
+ /**
36681
+ * Only the diagnostics NAMED here change. An armed window that is not listed
36682
+ * keeps running — a patch is never a full replacement.
36683
+ */
36684
+ diagnostics: external_exports.array(DiagnosticWindowPatchSchema).readonly().optional()
36685
+ });
36686
+ var GetLoggingSettingsInputSchema = external_exports.object({ scopeNodeId: external_exports.string().optional() });
36687
+ var SetLoggingSettingsInputSchema = external_exports.object({
36688
+ scopeNodeId: external_exports.string().optional(),
36689
+ patch: LoggingSettingsPatchSchema
36690
+ });
36691
+ var LoggingSettingsStateSchema = external_exports.object({
36692
+ /** The layer this document was read at. `null` = the cluster layer. */
36693
+ scopeNodeId: external_exports.string().nullable(),
36694
+ effective: LoggingEffectiveSchema,
36695
+ explicit: LoggingExplicitSchema,
36696
+ activeWindows: external_exports.array(DiagnosticWindowSchema).readonly(),
36697
+ persisted: external_exports.boolean()
36698
+ });
36402
36699
  var systemCapability = {
36403
36700
  name: "system",
36404
36701
  scope: "system",
@@ -36442,6 +36739,38 @@ var systemCapability = {
36442
36739
  detectSiteLocation: method(external_exports.void(), SiteLocationStatusSchema, {
36443
36740
  kind: "mutation",
36444
36741
  auth: "admin"
36742
+ }),
36743
+ /**
36744
+ * Read the HTTP request census - which caller, from which address, with
36745
+ * which user-agent, invoked which tRPC procedure, and how often.
36746
+ *
36747
+ * Reading NEVER re-arms: re-arming clears the counts, which would throw
36748
+ * away exactly the numbers being asked for. A closed window may be read as
36749
+ * many times as the operator likes and always describes the same window.
36750
+ *
36751
+ * Admin-only: the rows carry source addresses and principal names.
36752
+ */
36753
+ getRequestCensus: method(external_exports.void(), RequestCensusStatusSchema, { auth: "admin" }),
36754
+ /**
36755
+ * The logging settings document — levels and armed diagnostics — resolved
36756
+ * for `nodeId`, or for the cluster when `nodeId` is absent.
36757
+ *
36758
+ * Returns BOTH `effective` and `explicit`. See
36759
+ * {@link LoggingLevelLayerSchema} for why collapsing them is the defect.
36760
+ */
36761
+ getLoggingSettings: method(GetLoggingSettingsInputSchema, LoggingSettingsStateSchema, { auth: "admin" }),
36762
+ /**
36763
+ * Write the logging settings document. The ONLY write authority over log
36764
+ * levels and diagnostic windows — arming the request census went through
36765
+ * `system.setRequestCensus` until 2026-08-27 and no longer does, because
36766
+ * two writes that disagree about the same window is exactly the defect
36767
+ * this document exists to remove (D245).
36768
+ *
36769
+ * The patch MERGES: see {@link LoggingSettingsPatchSchema}.
36770
+ */
36771
+ setLoggingSettings: method(SetLoggingSettingsInputSchema, LoggingSettingsStateSchema, {
36772
+ kind: "mutation",
36773
+ auth: "admin"
36445
36774
  })
36446
36775
  },
36447
36776
  /** BIG PLAN 2: declarative mount hint — read by `@camstack/system` `buildCapRouters`. */
@@ -37305,6 +37634,19 @@ var PIPELINE_OWNER_CAPABILITY_NAMES = [
37305
37634
  "pipeline-orchestrator",
37306
37635
  "pipeline-runner"
37307
37636
  ];
37637
+ var SOURCE_CAP_ACTIVE_FIELD = {
37638
+ contact: "entryOpen",
37639
+ binary: "on",
37640
+ switch: "on",
37641
+ motion: "detected",
37642
+ flood: "flooded",
37643
+ gas: "detected",
37644
+ smoke: "detected",
37645
+ "carbon-monoxide": "detected",
37646
+ vibration: "detected",
37647
+ tamper: "tampered"
37648
+ };
37649
+ var SOURCE_CAPS = Object.keys(SOURCE_CAP_ACTIVE_FIELD);
37308
37650
  var HF_REPO = "camstack/camstack-models";
37309
37651
  var HF_BASE_URL = `https://huggingface.co/${HF_REPO}/resolve/main`;
37310
37652
  var AccessoryKind = {
@@ -37327,6 +37669,7 @@ var ACCESSORY_LABEL = {
37327
37669
  [AccessoryKind.Nightvision]: "Night Vision",
37328
37670
  [AccessoryKind.PrivacyMask]: "Privacy Mask"
37329
37671
  };
37672
+ var BATTERY_UNREACHABLE_AFTER_MS = 360 * 6e4;
37330
37673
  var DEVICE_TYPE_CONTROL_KIND = {
37331
37674
  [DeviceType.Cover]: "cover",
37332
37675
  [DeviceType.Valve]: "valve",
@@ -37371,7 +37714,6 @@ var BATTERY_DEVICE_PROFILE = {
37371
37714
  },
37372
37715
  settings: {}
37373
37716
  };
37374
- var BATTERY_UNREACHABLE_AFTER_MS = 360 * 6e4;
37375
37717
  var OPERATOR_WRITTEN_STALE_MS = 10 * 6e4;
37376
37718
  var METHOD_ACCESS_MAP = Object.freeze({
37377
37719
  "accessories.setChildHidden": {
@@ -40278,6 +40620,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
40278
40620
  addonId: null,
40279
40621
  access: "view"
40280
40622
  },
40623
+ "notificationRules.resolveArtifactUrl": {
40624
+ capName: "notification-rules",
40625
+ capScope: "system",
40626
+ addonId: null,
40627
+ access: "view"
40628
+ },
40281
40629
  "notificationRules.setAlarmConfig": {
40282
40630
  capName: "notification-rules",
40283
40631
  capScope: "system",
@@ -41682,6 +42030,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
41682
42030
  addonId: null,
41683
42031
  access: "view"
41684
42032
  },
42033
+ "recording.readWindowBytes": {
42034
+ capName: "recording",
42035
+ capScope: "system",
42036
+ addonId: null,
42037
+ access: "view"
42038
+ },
41685
42039
  "recording.refreshStorageLocationsForMigration": {
41686
42040
  capName: "recording",
41687
42041
  capScope: "system",
@@ -42522,6 +42876,18 @@ var METHOD_ACCESS_MAP = Object.freeze({
42522
42876
  addonId: null,
42523
42877
  access: "create"
42524
42878
  },
42879
+ "system.getLoggingSettings": {
42880
+ capName: "system",
42881
+ capScope: "system",
42882
+ addonId: null,
42883
+ access: "view"
42884
+ },
42885
+ "system.getRequestCensus": {
42886
+ capName: "system",
42887
+ capScope: "system",
42888
+ addonId: null,
42889
+ access: "view"
42890
+ },
42525
42891
  "system.getRetentionConfig": {
42526
42892
  capName: "system",
42527
42893
  capScope: "system",
@@ -42552,6 +42918,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
42552
42918
  addonId: null,
42553
42919
  access: "view"
42554
42920
  },
42921
+ "system.setLoggingSettings": {
42922
+ capName: "system",
42923
+ capScope: "system",
42924
+ addonId: null,
42925
+ access: "create"
42926
+ },
42555
42927
  "system.setRetentionConfig": {
42556
42928
  capName: "system",
42557
42929
  capScope: "system",
@@ -43707,6 +44079,10 @@ var METHOD_DEVICE_SELECTORS = Object.freeze({
43707
44079
  name: "deviceId",
43708
44080
  form: "single",
43709
44081
  optional: true
44082
+ }, {
44083
+ name: "deviceIds",
44084
+ form: "array",
44085
+ optional: true
43710
44086
  }],
43711
44087
  "fanControl.setDirection": [{
43712
44088
  name: "deviceId",
@@ -44512,6 +44888,11 @@ var METHOD_DEVICE_SELECTORS = Object.freeze({
44512
44888
  form: "single",
44513
44889
  optional: false
44514
44890
  }],
44891
+ "recording.readWindowBytes": [{
44892
+ name: "deviceId",
44893
+ form: "single",
44894
+ optional: false
44895
+ }],
44515
44896
  "recording.relocateFootage": [{
44516
44897
  name: "deviceId",
44517
44898
  form: "single",
@@ -45179,13 +45560,45 @@ var NativeLeaseSettingsSchema = external_exports.object({
45179
45560
  * fallback — i.e. the pre-2026-08-13 miss profile. Set it there only to
45180
45561
  * reproduce that.
45181
45562
  */
45182
- tileBudgetMb: external_exports.number().int().min(0).max(1024)
45563
+ tileBudgetMb: external_exports.number().int().min(0).max(1024),
45564
+ /**
45565
+ * RAM ceiling per decode worker, in MB, for the SCENE TILES — one
45566
+ * JPEG-encoded copy of the WHOLE native frame, cut in the same instant as the
45567
+ * subject tiles, on frames that detected something.
45568
+ *
45569
+ * It exists because a subject tile cannot answer a FULL-FRAME request:
45570
+ * containment is strict by design, so the native `keyFrame`, the detail
45571
+ * plane's `frameJpeg` rung and the display-crop fallback had no rung at all
45572
+ * below the hold. Measured on the live cluster: 23.3% of key-frame captures
45573
+ * missed, 95.7% of them with `worker-lease-gone` — the raster released one
45574
+ * frame-time after delivery, with the request only p50 367 ms behind it.
45575
+ *
45576
+ * Sizing, and why this is a budget and not a duration: a scene tile is
45577
+ * ~1.5-2.5 MB at 4K (against ~23.75 MB for the raster it was cut from and
45578
+ * ~60-120 KB for a subject tile), and it is cut ~0.4 times a second per busy
45579
+ * camera — only detection-bearing frames get one. 48 MB is therefore ~20-30
45580
+ * frames, i.e. the store's 30 s TTL binds at the steady state and the budget
45581
+ * binds only through a detection burst, where it still covers well past the
45582
+ * measured p90 ask age of 4.3 s. Holding the RASTERS for the same window
45583
+ * would be ~498 MB per camera and ~6 GB at peak concurrency — the OOM this
45584
+ * whole shape exists to avoid.
45585
+ *
45586
+ * A SEPARATE ceiling from `tileBudgetMb` on purpose: a scene tile is ~20× a
45587
+ * subject tile, so one shared budget would let a busy camera's key frames
45588
+ * evict the face/plate tiles the recognisers depend on. Two budgets make that
45589
+ * impossible rather than unlikely. `0` DISABLES scene tiles and restores the
45590
+ * pre-existing behaviour, where a late full-frame request had nothing but the
45591
+ * ≤640 RAM raster — which the `keyFrame` gate rejects, so in practice it had
45592
+ * nothing.
45593
+ */
45594
+ sceneBudgetMb: external_exports.number().int().min(0).max(1024)
45183
45595
  });
45184
45596
  var DEFAULT_NATIVE_LEASE_SETTINGS = {
45185
45597
  holdFrames: 8,
45186
45598
  budgetMb: 1024,
45187
45599
  activityMs: 15e3,
45188
45600
  tileBudgetMb: 64,
45601
+ sceneBudgetMb: 48,
45189
45602
  admission: "inferred"
45190
45603
  };
45191
45604
  var NATIVE_LEASE_HOLD_FIELD = {
@@ -45212,6 +45625,12 @@ var NATIVE_LEASE_TILE_BUDGET_FIELD = {
45212
45625
  step: 16,
45213
45626
  default: DEFAULT_NATIVE_LEASE_SETTINGS.tileBudgetMb
45214
45627
  };
45628
+ var NATIVE_LEASE_SCENE_BUDGET_FIELD = {
45629
+ min: 0,
45630
+ max: 1024,
45631
+ step: 16,
45632
+ default: DEFAULT_NATIVE_LEASE_SETTINGS.sceneBudgetMb
45633
+ };
45215
45634
  var NATIVE_LEASE_ADMISSION_FIELD = {
45216
45635
  options: [{
45217
45636
  value: "all",