camstack 1.2.46 → 1.2.48

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.
@@ -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",
@@ -29834,7 +29872,7 @@ var lifecycleJobSchema = external_exports.object({
29834
29872
  state: lifecycleJobStateSchema,
29835
29873
  schemaVersion: external_exports.literal(1)
29836
29874
  });
29837
- var LogLevelSchema$1 = external_exports.enum([
29875
+ var LogLevelSchema$2 = external_exports.enum([
29838
29876
  "debug",
29839
29877
  "info",
29840
29878
  "warn",
@@ -30034,7 +30072,7 @@ var addonsCapability = {
30034
30072
  getLogs: method(external_exports.object({
30035
30073
  addonId: external_exports.string(),
30036
30074
  limit: external_exports.number().min(1).max(500).default(100),
30037
- level: LogLevelSchema$1.optional()
30075
+ level: LogLevelSchema$2.optional()
30038
30076
  }), external_exports.array(LogQueryEntrySchema)),
30039
30077
  listPackages: method(external_exports.void(), external_exports.array(InstalledPackageSchema).readonly()),
30040
30078
  installPackage: method(external_exports.object({
@@ -30272,7 +30310,7 @@ var addonsCapability = {
30272
30310
  }),
30273
30311
  onAddonLogs: method(external_exports.object({
30274
30312
  addonId: external_exports.string(),
30275
- level: LogLevelSchema$1.optional()
30313
+ level: LogLevelSchema$2.optional()
30276
30314
  }), LogStreamEntrySchema, { kind: "subscription" })
30277
30315
  },
30278
30316
  /** BIG PLAN 2: declarative mount hint — read by `@camstack/system` `buildCapRouters`. */
@@ -31731,6 +31769,14 @@ var FaceFilterEnum = external_exports.enum([
31731
31769
  "identified",
31732
31770
  "all"
31733
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
+ });
31734
31780
  var MediaFileLiteSchema$1 = external_exports.object({
31735
31781
  key: external_exports.string(),
31736
31782
  kind: external_exports.string(),
@@ -31789,24 +31835,72 @@ var faceGalleryCapability = {
31789
31835
  auth: "admin"
31790
31836
  }),
31791
31837
  listRecentFaces: method(external_exports.object({
31792
- /** 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
+ */
31793
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(),
31794
31862
  limit: external_exports.number().int().positive().optional(),
31795
31863
  filter: FaceFilterEnum.optional(),
31796
31864
  /**
31797
- * Inline the base64 crop on every row. Default `true` — the existing
31798
- * 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.
31799
31878
  *
31800
- * Set `false` once the caller renders {@link FaceInfo.cropUrl}: that
31801
- * drops ~2.87 MiB per 500-row page to a few KiB of metadata and lets
31802
- * the browser cache the images.
31879
+ * See {@link FaceSortFieldEnum} for what a row with no suggestion
31880
+ * does under `'suggestionConfidence'`.
31803
31881
  *
31804
- * **This is an INPUT field, so it does not reach the addon until the
31805
- * next train.** The hub router validates cap inputs against its own
31806
- * compiled Zod, which strips a key it does not know verified today
31807
- * on the OUTPUT side, where an additive field DOES arrive immediately
31808
- * (`Track.hasFace`). Until the train ships, sending `false` is
31809
- * 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.
31810
31904
  */
31811
31905
  includeCrops: external_exports.boolean().optional()
31812
31906
  }).optional(), external_exports.array(FaceInfoSchema).readonly()),
@@ -31855,13 +31949,39 @@ var faceGalleryCapability = {
31855
31949
  suggestFaceClusters: method(external_exports.object({
31856
31950
  threshold: external_exports.number().min(0).max(1).optional(),
31857
31951
  minClusterSize: external_exports.number().int().min(2).optional(),
31858
- limit: external_exports.number().int().positive().optional()
31859
- }).optional(), external_exports.array(external_exports.object({
31860
- faceIds: external_exports.array(external_exports.string()).readonly(),
31861
- representativeFaceId: external_exports.string(),
31862
- size: external_exports.number().int(),
31863
- cohesion: external_exports.number()
31864
- })).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())
31865
31985
  }
31866
31986
  };
31867
31987
  var FanDirectionSchema = external_exports.enum(["forward", "reverse"]);
@@ -36461,6 +36581,174 @@ var SetSiteLocationInputSchema = external_exports.object({
36461
36581
  latitude: external_exports.number().min(-90).max(90),
36462
36582
  longitude: external_exports.number().min(-180).max(180)
36463
36583
  }).nullable();
36584
+ var TransportPlaneSchema = external_exports.enum([
36585
+ "http",
36586
+ "ws",
36587
+ "mesh",
36588
+ "unknown"
36589
+ ]);
36590
+ var TransportPlaneCountsSchema = external_exports.object({
36591
+ http: external_exports.number(),
36592
+ ws: external_exports.number(),
36593
+ mesh: external_exports.number(),
36594
+ unknown: external_exports.number()
36595
+ });
36596
+ var RequestCensusGroupSchema = external_exports.object({
36597
+ plane: TransportPlaneSchema,
36598
+ procedure: external_exports.string(),
36599
+ userAgent: external_exports.string(),
36600
+ ip: external_exports.string(),
36601
+ principal: external_exports.string(),
36602
+ calls: external_exports.number(),
36603
+ subscriptions: external_exports.number(),
36604
+ perMin: external_exports.number()
36605
+ });
36606
+ var RequestCensusProcedureSchema = external_exports.object({
36607
+ procedure: external_exports.string(),
36608
+ calls: external_exports.number(),
36609
+ /**
36610
+ * The same total, split by transport. THIS is the row that answers the
36611
+ * question the census exists for: one look at `deviceManager.listAll` says
36612
+ * which plane carried the 4 960, without joining two log lines by eye.
36613
+ */
36614
+ planes: TransportPlaneCountsSchema,
36615
+ /** Subscription STARTS on this procedure. Never folded into `calls`. */
36616
+ subscriptions: external_exports.number(),
36617
+ perMin: external_exports.number()
36618
+ });
36619
+ var RequestCensusSnapshotSchema = external_exports.object({
36620
+ armed: external_exports.boolean(),
36621
+ /** How long the current - or just-closed - window collected, in ms. */
36622
+ elapsedMs: external_exports.number(),
36623
+ /** The window actually armed, after the server clamped the request. */
36624
+ windowMs: external_exports.number(),
36625
+ /** Epoch ms the window closes at. 0 when disarmed. */
36626
+ armedUntilMs: external_exports.number(),
36627
+ httpRequests: external_exports.number(),
36628
+ batchedRequests: external_exports.number(),
36629
+ /**
36630
+ * Procedure invocations. Higher than `httpRequests` whenever tRPC batching
36631
+ * is in play (`?batch=1` carries several procedures in one request); this is
36632
+ * the number comparable with a store-side call count.
36633
+ */
36634
+ procedureCalls: external_exports.number(),
36635
+ /**
36636
+ * `procedureCalls` split by transport. The four keys sum to
36637
+ * `procedureCalls` by construction - {@link RequestCensusSnapshotSchema}'s
36638
+ * `planesExplainTotal` is that identity, checked rather than assumed.
36639
+ */
36640
+ planes: TransportPlaneCountsSchema,
36641
+ /**
36642
+ * True iff `planes` sums to `procedureCalls`. False means a call was counted
36643
+ * on no plane at all - which is a RESULT (a plane is missing from the
36644
+ * instrument), not a failure, and it has to be visible to be read as one.
36645
+ */
36646
+ planesExplainTotal: external_exports.boolean(),
36647
+ /**
36648
+ * tRPC WebSocket connections opened during the window. NOT calls - the WS
36649
+ * adapter resolves one context per connection - kept because a plane's call
36650
+ * count of zero against 37 open connections says something different from a
36651
+ * plane with no connections at all.
36652
+ */
36653
+ wsConnections: external_exports.number(),
36654
+ /**
36655
+ * Client frames the WS plane looked at. `wsMessages` far above
36656
+ * `planes.ws + subscriptions` means most traffic is not operations
36657
+ * (keepalives, connection params) - which is itself an answer.
36658
+ */
36659
+ wsMessages: external_exports.number(),
36660
+ /**
36661
+ * Subscription STARTS across every plane, excluded from `procedureCalls` on
36662
+ * purpose: one live-events stream opened at boot and held for six hours is
36663
+ * one subscription, and counting it as a call would let a quiet plane
36664
+ * masquerade as the storm.
36665
+ */
36666
+ subscriptions: external_exports.number(),
36667
+ /** `subscription.stop` frames. Starts minus stops is what is still open. */
36668
+ subscriptionStops: external_exports.number(),
36669
+ distinctGroups: external_exports.number(),
36670
+ /**
36671
+ * Operations counted in the totals whose CALLER attribution was shed at the
36672
+ * cardinality bound. Unrelated to the `unknown` PLANE: these calls know
36673
+ * which transport they arrived on, they just lost their group row.
36674
+ */
36675
+ unattributedCalls: external_exports.number(),
36676
+ procedures: external_exports.array(RequestCensusProcedureSchema).readonly(),
36677
+ groups: external_exports.array(RequestCensusGroupSchema).readonly()
36678
+ });
36679
+ var RequestCensusStatusSchema = RequestCensusSnapshotSchema.extend({ persisted: external_exports.boolean() });
36680
+ var LogLevelSchema$1 = external_exports.enum([
36681
+ "debug",
36682
+ "info",
36683
+ "warn",
36684
+ "error"
36685
+ ]);
36686
+ var DiagnosticIdSchema = external_exports.enum(["request-census"]);
36687
+ var LoggingScopeKindSchema = external_exports.enum([
36688
+ "cluster",
36689
+ "node",
36690
+ "component"
36691
+ ]);
36692
+ var LoggingLevelSourceSchema = external_exports.enum([
36693
+ "default",
36694
+ "cluster",
36695
+ "node",
36696
+ "component"
36697
+ ]);
36698
+ var LoggingLevelLayerSchema = external_exports.object({
36699
+ scope: LoggingScopeKindSchema,
36700
+ /** The node this layer speaks for; `null` on the cluster layer. */
36701
+ nodeId: external_exports.string().nullable(),
36702
+ /** Explicitly set here, or `null` when this layer inherits. */
36703
+ level: LogLevelSchema$1.nullable()
36704
+ });
36705
+ var LoggingEffectiveSchema = external_exports.object({
36706
+ level: LogLevelSchema$1,
36707
+ levelSource: LoggingLevelSourceSchema
36708
+ });
36709
+ var LoggingExplicitSchema = external_exports.object({ layers: external_exports.array(LoggingLevelLayerSchema).readonly() });
36710
+ var DiagnosticWindowSchema = external_exports.object({
36711
+ id: DiagnosticIdSchema,
36712
+ armed: external_exports.boolean(),
36713
+ /** Epoch ms the window closes at. 0 when disarmed. */
36714
+ armedUntilMs: external_exports.number(),
36715
+ /** Ms left before it expires on its own. 0 when disarmed. */
36716
+ remainingMs: external_exports.number(),
36717
+ /** Whether the stored deadline is the one the live diagnostic is running —
36718
+ * i.e. whether this window would survive a restart. */
36719
+ persisted: external_exports.boolean()
36720
+ });
36721
+ var DiagnosticWindowPatchSchema = external_exports.object({
36722
+ id: DiagnosticIdSchema,
36723
+ armMs: external_exports.number().int().min(0),
36724
+ /** Cadence of the diagnostic's aggregated report line. Clamped by the server. */
36725
+ reportEveryMs: external_exports.number().int().positive().optional()
36726
+ });
36727
+ var LoggingSettingsPatchSchema = external_exports.object({
36728
+ /**
36729
+ * Absent leaves the level untouched. `null` CLEARS the explicit value at the
36730
+ * addressed scope so it inherits again. A value sets it.
36731
+ */
36732
+ level: LogLevelSchema$1.nullable().optional(),
36733
+ /**
36734
+ * Only the diagnostics NAMED here change. An armed window that is not listed
36735
+ * keeps running — a patch is never a full replacement.
36736
+ */
36737
+ diagnostics: external_exports.array(DiagnosticWindowPatchSchema).readonly().optional()
36738
+ });
36739
+ var GetLoggingSettingsInputSchema = external_exports.object({ scopeNodeId: external_exports.string().optional() });
36740
+ var SetLoggingSettingsInputSchema = external_exports.object({
36741
+ scopeNodeId: external_exports.string().optional(),
36742
+ patch: LoggingSettingsPatchSchema
36743
+ });
36744
+ var LoggingSettingsStateSchema = external_exports.object({
36745
+ /** The layer this document was read at. `null` = the cluster layer. */
36746
+ scopeNodeId: external_exports.string().nullable(),
36747
+ effective: LoggingEffectiveSchema,
36748
+ explicit: LoggingExplicitSchema,
36749
+ activeWindows: external_exports.array(DiagnosticWindowSchema).readonly(),
36750
+ persisted: external_exports.boolean()
36751
+ });
36464
36752
  var systemCapability = {
36465
36753
  name: "system",
36466
36754
  scope: "system",
@@ -36504,6 +36792,38 @@ var systemCapability = {
36504
36792
  detectSiteLocation: method(external_exports.void(), SiteLocationStatusSchema, {
36505
36793
  kind: "mutation",
36506
36794
  auth: "admin"
36795
+ }),
36796
+ /**
36797
+ * Read the HTTP request census - which caller, from which address, with
36798
+ * which user-agent, invoked which tRPC procedure, and how often.
36799
+ *
36800
+ * Reading NEVER re-arms: re-arming clears the counts, which would throw
36801
+ * away exactly the numbers being asked for. A closed window may be read as
36802
+ * many times as the operator likes and always describes the same window.
36803
+ *
36804
+ * Admin-only: the rows carry source addresses and principal names.
36805
+ */
36806
+ getRequestCensus: method(external_exports.void(), RequestCensusStatusSchema, { auth: "admin" }),
36807
+ /**
36808
+ * The logging settings document — levels and armed diagnostics — resolved
36809
+ * for `nodeId`, or for the cluster when `nodeId` is absent.
36810
+ *
36811
+ * Returns BOTH `effective` and `explicit`. See
36812
+ * {@link LoggingLevelLayerSchema} for why collapsing them is the defect.
36813
+ */
36814
+ getLoggingSettings: method(GetLoggingSettingsInputSchema, LoggingSettingsStateSchema, { auth: "admin" }),
36815
+ /**
36816
+ * Write the logging settings document. The ONLY write authority over log
36817
+ * levels and diagnostic windows — arming the request census went through
36818
+ * `system.setRequestCensus` until 2026-08-27 and no longer does, because
36819
+ * two writes that disagree about the same window is exactly the defect
36820
+ * this document exists to remove (D245).
36821
+ *
36822
+ * The patch MERGES: see {@link LoggingSettingsPatchSchema}.
36823
+ */
36824
+ setLoggingSettings: method(SetLoggingSettingsInputSchema, LoggingSettingsStateSchema, {
36825
+ kind: "mutation",
36826
+ auth: "admin"
36507
36827
  })
36508
36828
  },
36509
36829
  /** BIG PLAN 2: declarative mount hint — read by `@camstack/system` `buildCapRouters`. */
@@ -37367,6 +37687,19 @@ var PIPELINE_OWNER_CAPABILITY_NAMES = [
37367
37687
  "pipeline-orchestrator",
37368
37688
  "pipeline-runner"
37369
37689
  ];
37690
+ var SOURCE_CAP_ACTIVE_FIELD = {
37691
+ contact: "entryOpen",
37692
+ binary: "on",
37693
+ switch: "on",
37694
+ motion: "detected",
37695
+ flood: "flooded",
37696
+ gas: "detected",
37697
+ smoke: "detected",
37698
+ "carbon-monoxide": "detected",
37699
+ vibration: "detected",
37700
+ tamper: "tampered"
37701
+ };
37702
+ var SOURCE_CAPS = Object.keys(SOURCE_CAP_ACTIVE_FIELD);
37370
37703
  var HF_REPO = "camstack/camstack-models";
37371
37704
  var HF_BASE_URL = `https://huggingface.co/${HF_REPO}/resolve/main`;
37372
37705
  var AccessoryKind = {
@@ -37389,6 +37722,7 @@ var ACCESSORY_LABEL = {
37389
37722
  [AccessoryKind.Nightvision]: "Night Vision",
37390
37723
  [AccessoryKind.PrivacyMask]: "Privacy Mask"
37391
37724
  };
37725
+ var BATTERY_UNREACHABLE_AFTER_MS = 360 * 6e4;
37392
37726
  var DEVICE_TYPE_CONTROL_KIND = {
37393
37727
  [DeviceType.Cover]: "cover",
37394
37728
  [DeviceType.Valve]: "valve",
@@ -37433,7 +37767,6 @@ var BATTERY_DEVICE_PROFILE = {
37433
37767
  },
37434
37768
  settings: {}
37435
37769
  };
37436
- var BATTERY_UNREACHABLE_AFTER_MS = 360 * 6e4;
37437
37770
  var OPERATOR_WRITTEN_STALE_MS = 10 * 6e4;
37438
37771
  var METHOD_ACCESS_MAP = Object.freeze({
37439
37772
  "accessories.setChildHidden": {
@@ -42596,6 +42929,18 @@ var METHOD_ACCESS_MAP = Object.freeze({
42596
42929
  addonId: null,
42597
42930
  access: "create"
42598
42931
  },
42932
+ "system.getLoggingSettings": {
42933
+ capName: "system",
42934
+ capScope: "system",
42935
+ addonId: null,
42936
+ access: "view"
42937
+ },
42938
+ "system.getRequestCensus": {
42939
+ capName: "system",
42940
+ capScope: "system",
42941
+ addonId: null,
42942
+ access: "view"
42943
+ },
42599
42944
  "system.getRetentionConfig": {
42600
42945
  capName: "system",
42601
42946
  capScope: "system",
@@ -42626,6 +42971,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
42626
42971
  addonId: null,
42627
42972
  access: "view"
42628
42973
  },
42974
+ "system.setLoggingSettings": {
42975
+ capName: "system",
42976
+ capScope: "system",
42977
+ addonId: null,
42978
+ access: "create"
42979
+ },
42629
42980
  "system.setRetentionConfig": {
42630
42981
  capName: "system",
42631
42982
  capScope: "system",
@@ -43781,6 +44132,10 @@ var METHOD_DEVICE_SELECTORS = Object.freeze({
43781
44132
  name: "deviceId",
43782
44133
  form: "single",
43783
44134
  optional: true
44135
+ }, {
44136
+ name: "deviceIds",
44137
+ form: "array",
44138
+ optional: true
43784
44139
  }],
43785
44140
  "fanControl.setDirection": [{
43786
44141
  name: "deviceId",
@@ -45258,13 +45613,45 @@ var NativeLeaseSettingsSchema = external_exports.object({
45258
45613
  * fallback — i.e. the pre-2026-08-13 miss profile. Set it there only to
45259
45614
  * reproduce that.
45260
45615
  */
45261
- tileBudgetMb: external_exports.number().int().min(0).max(1024)
45616
+ tileBudgetMb: external_exports.number().int().min(0).max(1024),
45617
+ /**
45618
+ * RAM ceiling per decode worker, in MB, for the SCENE TILES — one
45619
+ * JPEG-encoded copy of the WHOLE native frame, cut in the same instant as the
45620
+ * subject tiles, on frames that detected something.
45621
+ *
45622
+ * It exists because a subject tile cannot answer a FULL-FRAME request:
45623
+ * containment is strict by design, so the native `keyFrame`, the detail
45624
+ * plane's `frameJpeg` rung and the display-crop fallback had no rung at all
45625
+ * below the hold. Measured on the live cluster: 23.3% of key-frame captures
45626
+ * missed, 95.7% of them with `worker-lease-gone` — the raster released one
45627
+ * frame-time after delivery, with the request only p50 367 ms behind it.
45628
+ *
45629
+ * Sizing, and why this is a budget and not a duration: a scene tile is
45630
+ * ~1.5-2.5 MB at 4K (against ~23.75 MB for the raster it was cut from and
45631
+ * ~60-120 KB for a subject tile), and it is cut ~0.4 times a second per busy
45632
+ * camera — only detection-bearing frames get one. 48 MB is therefore ~20-30
45633
+ * frames, i.e. the store's 30 s TTL binds at the steady state and the budget
45634
+ * binds only through a detection burst, where it still covers well past the
45635
+ * measured p90 ask age of 4.3 s. Holding the RASTERS for the same window
45636
+ * would be ~498 MB per camera and ~6 GB at peak concurrency — the OOM this
45637
+ * whole shape exists to avoid.
45638
+ *
45639
+ * A SEPARATE ceiling from `tileBudgetMb` on purpose: a scene tile is ~20× a
45640
+ * subject tile, so one shared budget would let a busy camera's key frames
45641
+ * evict the face/plate tiles the recognisers depend on. Two budgets make that
45642
+ * impossible rather than unlikely. `0` DISABLES scene tiles and restores the
45643
+ * pre-existing behaviour, where a late full-frame request had nothing but the
45644
+ * ≤640 RAM raster — which the `keyFrame` gate rejects, so in practice it had
45645
+ * nothing.
45646
+ */
45647
+ sceneBudgetMb: external_exports.number().int().min(0).max(1024)
45262
45648
  });
45263
45649
  var DEFAULT_NATIVE_LEASE_SETTINGS = {
45264
45650
  holdFrames: 8,
45265
45651
  budgetMb: 1024,
45266
45652
  activityMs: 15e3,
45267
45653
  tileBudgetMb: 64,
45654
+ sceneBudgetMb: 48,
45268
45655
  admission: "inferred"
45269
45656
  };
45270
45657
  var NATIVE_LEASE_HOLD_FIELD = {
@@ -45291,6 +45678,12 @@ var NATIVE_LEASE_TILE_BUDGET_FIELD = {
45291
45678
  step: 16,
45292
45679
  default: DEFAULT_NATIVE_LEASE_SETTINGS.tileBudgetMb
45293
45680
  };
45681
+ var NATIVE_LEASE_SCENE_BUDGET_FIELD = {
45682
+ min: 0,
45683
+ max: 1024,
45684
+ step: 16,
45685
+ default: DEFAULT_NATIVE_LEASE_SETTINGS.sceneBudgetMb
45686
+ };
45294
45687
  var NATIVE_LEASE_ADMISSION_FIELD = {
45295
45688
  options: [{
45296
45689
  value: "all",
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runDiscover
4
- } from "./chunk-HAO7UL6U.js";
4
+ } from "./chunk-4E6GZ4AC.js";
5
5
  import "./chunk-LMMQX4CK.js";
6
6
 
7
7
  // src/cli.ts
@@ -38,7 +38,7 @@ async function runServe(args) {
38
38
  ...typeof values.data === "string" ? { data: values.data } : {}
39
39
  };
40
40
  Object.assign(process.env, buildServeEnv(opts));
41
- await import("./launcher-Y5I6QU24.js");
41
+ await import("./launcher-MNOEQWRN.js");
42
42
  }
43
43
 
44
44
  // src/commands/agent.ts
@@ -83,7 +83,7 @@ async function runAgent(args) {
83
83
  ...typeof values.port === "string" ? { port: values.port } : {}
84
84
  };
85
85
  Object.assign(process.env, buildAgentEnv(opts));
86
- await import("./launcher-Y5I6QU24.js");
86
+ await import("./launcher-MNOEQWRN.js");
87
87
  }
88
88
 
89
89
  // src/commands/setup.ts
@@ -1130,7 +1130,7 @@ function isUnknown(_value) {
1130
1130
  return true;
1131
1131
  }
1132
1132
  async function resolveServerInteractive(presetNamespace) {
1133
- const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-27QPK6P7.js");
1133
+ const { discoverNodes, resolveHubFromDiscovered, filterHubNodes, DEFAULT_HUB_HTTPS_PORT } = await import("./discover-LCFU2BSJ.js");
1134
1134
  if (presetNamespace) {
1135
1135
  const spinner4 = clack.spinner();
1136
1136
  spinner4.start(`Discovering hub on LAN (namespace "${presetNamespace}")`);
@@ -5,7 +5,7 @@ import {
5
5
  filterHubNodes,
6
6
  resolveHubFromDiscovered,
7
7
  runDiscover
8
- } from "./chunk-HAO7UL6U.js";
8
+ } from "./chunk-4E6GZ4AC.js";
9
9
  import "./chunk-LMMQX4CK.js";
10
10
  export {
11
11
  DEFAULT_HUB_HTTPS_PORT,