@camstack/addon-post-analysis 1.2.74 → 1.2.76
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.
- package/dist/{dist-Cy8lyywE.js → dist-BsBjSNIo.js} +429 -45
- package/dist/{dist-CvWsGsxP.mjs → dist-CYfG8ulU.mjs} +394 -46
- package/dist/embedding-encoder/index.js +1 -1
- package/dist/embedding-encoder/index.mjs +1 -1
- package/dist/pipeline-analytics/_stub.js +1 -1
- package/dist/pipeline-analytics/{_virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-1--pFIrH.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_pipeline_analytics_widgets-DCcRtqVf.mjs} +3 -3
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-DFckpC3K.mjs +26 -0
- package/dist/pipeline-analytics/{hostInit-DxmzfwkG.mjs → hostInit-sdxJJeWR.mjs} +3 -3
- package/dist/pipeline-analytics/index.js +4728 -1731
- package/dist/pipeline-analytics/index.mjs +4723 -1726
- package/dist/pipeline-analytics/remoteEntry.js +1 -1
- package/package.json +4 -1
- package/dist/pipeline-analytics/_virtual_mf___mfe_internal__addon_pipeline_analytics_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-DE456p1Q.mjs +0 -26
|
@@ -12700,6 +12700,17 @@ var LlmImageSchema = object({
|
|
|
12700
12700
|
bytes: _instanceof(Uint8Array),
|
|
12701
12701
|
mimeType: string()
|
|
12702
12702
|
});
|
|
12703
|
+
/**
|
|
12704
|
+
* Retry policy. `enabled: false` is NOT the same as `maxAttempts: 1` in intent —
|
|
12705
|
+
* the flag is what a consumer table flips, the count is what the operator tunes.
|
|
12706
|
+
* A retry doubles the wall time of a call, so the two gates that run inside a
|
|
12707
|
+
* notification's budget keep it off (see `CONSUMER_RETRY_POLICY` in addon-ai).
|
|
12708
|
+
*/
|
|
12709
|
+
var LlmRetryPolicySchema = object({
|
|
12710
|
+
enabled: boolean().default(false),
|
|
12711
|
+
/** Total attempts INCLUDING the first. 1 = no retry. */
|
|
12712
|
+
maxAttempts: number().int().min(1).max(5).default(1)
|
|
12713
|
+
});
|
|
12703
12714
|
var LlmGenerateBaseInputSchema = object({
|
|
12704
12715
|
/** Collection routing (the notification-output posture). */
|
|
12705
12716
|
addonId: string().optional(),
|
|
@@ -12714,7 +12725,28 @@ var LlmGenerateBaseInputSchema = object({
|
|
|
12714
12725
|
jsonSchema: record(string(), unknown()).optional(),
|
|
12715
12726
|
/** Per-call override of the profile default. */
|
|
12716
12727
|
maxTokens: number().int().positive().optional(),
|
|
12717
|
-
temperature: number().optional()
|
|
12728
|
+
temperature: number().optional(),
|
|
12729
|
+
/** Per-call override of the profile default (nucleus sampling). */
|
|
12730
|
+
topP: number().min(0).max(1).optional(),
|
|
12731
|
+
/** Per-call override of the profile default (top-k sampling). */
|
|
12732
|
+
topK: number().int().positive().optional(),
|
|
12733
|
+
/** Per-call override of `profile.timeoutMs` — the total generation bound. */
|
|
12734
|
+
timeoutMs: number().int().positive().optional(),
|
|
12735
|
+
/** Per-call override; beats both the consumer table and the profile. */
|
|
12736
|
+
retry: LlmRetryPolicySchema.optional(),
|
|
12737
|
+
/**
|
|
12738
|
+
* Caller-minted id that makes this generation CANCELLABLE.
|
|
12739
|
+
*
|
|
12740
|
+
* Without it a caller that stops waiting cannot stop the work: the gates race
|
|
12741
|
+
* the call against 8 s and free their own slot when the timer wins, while the
|
|
12742
|
+
* generation upstream keeps running to `profile.timeoutMs` — 60 s by default,
|
|
12743
|
+
* on a single-threaded local model. The per-camera bound then counts WAITS,
|
|
12744
|
+
* not generations, and the real load is unbounded.
|
|
12745
|
+
*
|
|
12746
|
+
* `AbortSignal` cannot cross a process boundary; an id can. Pass one here and
|
|
12747
|
+
* `llm.cancel({ requestId })` tears the socket down.
|
|
12748
|
+
*/
|
|
12749
|
+
requestId: string().optional()
|
|
12718
12750
|
});
|
|
12719
12751
|
/**
|
|
12720
12752
|
* `llm-runtime` — node-side managed llama.cpp executor (spec §4). Registered
|
|
@@ -12753,8 +12785,49 @@ var ManagedRuntimeConfigSchema = object({
|
|
|
12753
12785
|
gpuLayers: number().int().default(0),
|
|
12754
12786
|
/** Default: cpus-2, clamped ≥1 (resolved node-side). */
|
|
12755
12787
|
threads: number().int().optional(),
|
|
12756
|
-
/** Concurrent slots. */
|
|
12788
|
+
/** Concurrent slots (`--parallel`). */
|
|
12757
12789
|
parallel: number().int().default(1),
|
|
12790
|
+
/** Logical batch size (`-b`). Larger = faster prompt ingest, more RAM. */
|
|
12791
|
+
batchSize: number().int().positive().optional(),
|
|
12792
|
+
/** Physical batch / micro-batch (`-ub`). */
|
|
12793
|
+
ubatchSize: number().int().positive().optional(),
|
|
12794
|
+
/**
|
|
12795
|
+
* `--flash-attn`. Cuts KV-cache memory on the backends that implement it and
|
|
12796
|
+
* is a no-op elsewhere, so it is offered rather than assumed.
|
|
12797
|
+
*/
|
|
12798
|
+
flashAttention: boolean().default(false),
|
|
12799
|
+
/**
|
|
12800
|
+
* `--mlock`. Pins the weights in RAM so the OS cannot page them out mid
|
|
12801
|
+
* inference. Costs the full model size in resident memory — which is exactly
|
|
12802
|
+
* what the RAM budget is counting.
|
|
12803
|
+
*/
|
|
12804
|
+
mlock: boolean().default(false),
|
|
12805
|
+
/**
|
|
12806
|
+
* `--no-mmap`. Reads the whole GGUF up front instead of mapping it. Slower to
|
|
12807
|
+
* start, but avoids the page-fault stalls a network or spinning-disk model
|
|
12808
|
+
* store produces on every first token.
|
|
12809
|
+
*/
|
|
12810
|
+
noMmap: boolean().default(false),
|
|
12811
|
+
/** `--cache-type-k` / `--cache-type-v` — quantising the KV cache is the
|
|
12812
|
+
* cheapest way to fit a longer context in the same RAM. */
|
|
12813
|
+
cacheTypeK: _enum([
|
|
12814
|
+
"f32",
|
|
12815
|
+
"f16",
|
|
12816
|
+
"q8_0",
|
|
12817
|
+
"q5_1",
|
|
12818
|
+
"q5_0",
|
|
12819
|
+
"q4_1",
|
|
12820
|
+
"q4_0"
|
|
12821
|
+
]).optional(),
|
|
12822
|
+
cacheTypeV: _enum([
|
|
12823
|
+
"f32",
|
|
12824
|
+
"f16",
|
|
12825
|
+
"q8_0",
|
|
12826
|
+
"q5_1",
|
|
12827
|
+
"q5_0",
|
|
12828
|
+
"q4_1",
|
|
12829
|
+
"q4_0"
|
|
12830
|
+
]).optional(),
|
|
12758
12831
|
/** Else lazy: first generate boots it. */
|
|
12759
12832
|
autoStart: boolean().default(false),
|
|
12760
12833
|
/** 0 = never; frees RAM after quiet periods. */
|
|
@@ -12842,10 +12915,44 @@ var LlmProfileSchema = object({
|
|
|
12842
12915
|
baseUrl: string().optional(),
|
|
12843
12916
|
/** ConfigUISchema type:'password' — never round-trips (spec §5). */
|
|
12844
12917
|
apiKey: string().optional(),
|
|
12918
|
+
/** Vision on/off. A vision call against a `false` profile is REFUSED, never
|
|
12919
|
+
* degraded to text — that shipped once and produced a confident answer to a
|
|
12920
|
+
* question about a picture nobody sent. */
|
|
12845
12921
|
supportsVision: boolean(),
|
|
12846
12922
|
temperature: number().min(0).max(2).optional(),
|
|
12923
|
+
/** Nucleus sampling. Every wire we speak has it. */
|
|
12924
|
+
topP: number().min(0).max(1).optional(),
|
|
12925
|
+
/** Top-k sampling. Carried only by the wires that have it — NEITHER OpenAI
|
|
12926
|
+
* wire does, and the client drops it there (measured: the request body gets
|
|
12927
|
+
* `top_p` and no `top_k`). The profile editor hides the field wherever it
|
|
12928
|
+
* would change nothing; `KINDS_WITH_TOP_K` is the single owner of that list. */
|
|
12929
|
+
topK: number().int().positive().optional(),
|
|
12847
12930
|
maxTokens: number().int().positive().optional(),
|
|
12931
|
+
/** Prompt context window. Advisory for cloud kinds (they enforce their own);
|
|
12932
|
+
* for `managed-local` it is the llama.cpp `--ctx-size` the runtime starts
|
|
12933
|
+
* the model with, so it is the one field that changes a PROCESS. */
|
|
12934
|
+
contextLength: number().int().positive().optional(),
|
|
12935
|
+
/** Default system prompt. A caller's `system` REPLACES it (never appends —
|
|
12936
|
+
* two system prompts fighting is worse than either alone). */
|
|
12937
|
+
systemPrompt: string().optional(),
|
|
12938
|
+
/** Total generation bound — the only one a unary call has. */
|
|
12848
12939
|
timeoutMs: number().int().positive().default(6e4),
|
|
12940
|
+
/** Wait for response headers only. */
|
|
12941
|
+
connectTimeoutMs: number().int().positive().default(1e4),
|
|
12942
|
+
/** Accepted, but no output yet — a cold GPU load lives here. */
|
|
12943
|
+
firstTokenTimeoutMs: number().int().positive().default(12e4),
|
|
12944
|
+
/** Output started then stopped. */
|
|
12945
|
+
idleTimeoutMs: number().int().positive().default(6e4),
|
|
12946
|
+
/** Profile-level default. The per-consumer table and a per-call override
|
|
12947
|
+
* both beat it — see `resolveRetryPolicy`. */
|
|
12948
|
+
retry: LlmRetryPolicySchema.default({
|
|
12949
|
+
enabled: false,
|
|
12950
|
+
maxAttempts: 1
|
|
12951
|
+
}),
|
|
12952
|
+
/** Whether this profile may use tools. The tool-call plumbing rides the
|
|
12953
|
+
* library; the REGISTRY of callable tools is ours and is empty in v1, so a
|
|
12954
|
+
* `true` here buys the wiring, not behaviour, until tools are registered. */
|
|
12955
|
+
toolsEnabled: boolean().default(false),
|
|
12849
12956
|
extraHeaders: record(string(), string()).optional(),
|
|
12850
12957
|
/** kind === 'managed-local' only (spec §4). */
|
|
12851
12958
|
runtime: ManagedRuntimeConfigSchema.optional()
|
|
@@ -12907,7 +13014,10 @@ var ProfileRefInputSchema = object({
|
|
|
12907
13014
|
addonId: string(),
|
|
12908
13015
|
profileId: string()
|
|
12909
13016
|
});
|
|
12910
|
-
method(LlmGenerateBaseInputSchema, LlmGenerateResultSchema, { kind: "mutation" }), method(GenerateVisionInputSchema, LlmGenerateResultSchema, { kind: "mutation" }), method(object({
|
|
13017
|
+
method(LlmGenerateBaseInputSchema, LlmGenerateResultSchema, { kind: "mutation" }), method(GenerateVisionInputSchema, LlmGenerateResultSchema, { kind: "mutation" }), method(object({
|
|
13018
|
+
addonId: string().optional(),
|
|
13019
|
+
requestId: string()
|
|
13020
|
+
}), _void(), { kind: "mutation" }), method(object({}), array(LlmProfileKindDescriptorSchema)), method(object({}), array(LlmProfileSchema)), method(object({ profile: LlmProfileSchema }), LlmProfileSchema, {
|
|
12911
13021
|
kind: "mutation",
|
|
12912
13022
|
auth: "admin"
|
|
12913
13023
|
}), method(ProfileRefInputSchema, _void(), {
|
|
@@ -14749,28 +14859,36 @@ var NcOccupancyConditionSchema = object({
|
|
|
14749
14859
|
/**
|
|
14750
14860
|
* Audio condition (IMMEDIATE trigger) — a rule on SOUND, not on a picture.
|
|
14751
14861
|
*
|
|
14752
|
-
*
|
|
14753
|
-
*
|
|
14754
|
-
*
|
|
14755
|
-
*
|
|
14756
|
-
*
|
|
14757
|
-
*
|
|
14758
|
-
*
|
|
14759
|
-
*
|
|
14760
|
-
*
|
|
14761
|
-
*
|
|
14762
|
-
*
|
|
14763
|
-
*
|
|
14764
|
-
*
|
|
14765
|
-
*
|
|
14766
|
-
*
|
|
14767
|
-
*
|
|
14768
|
-
*
|
|
14769
|
-
*
|
|
14770
|
-
*
|
|
14771
|
-
*
|
|
14772
|
-
*
|
|
14773
|
-
* `
|
|
14862
|
+
* **TWO EXCLUSIVE MODES** (operator decision 2026-08-14, D157). Which one a
|
|
14863
|
+
* rule is in is not a stored field — it is WHICH FILTER the rule carries, so
|
|
14864
|
+
* there is no second switch that can disagree with the first and every rule
|
|
14865
|
+
* authored before the decision migrates for free (`audioModeOf`):
|
|
14866
|
+
*
|
|
14867
|
+
* - **LABEL mode — `labels` present.** The rule fires on the FIRST frame the
|
|
14868
|
+
* classifier labels with one of them. No window, no percentage:
|
|
14869
|
+
* `hitPercent` and `samplingSeconds` are ignored, and the rule's own
|
|
14870
|
+
* `throttle` cooldown is the only brake. The per-label confidence floor is
|
|
14871
|
+
* the analyzer's (`classificationMinScore`, per device) — a label only
|
|
14872
|
+
* reaches this condition if the classifier was already confident enough.
|
|
14873
|
+
* - **LEVEL mode — `dbThreshold` present, no labels.** The sampling window IS
|
|
14874
|
+
* the condition: at least `hitPercent`% of the samples over
|
|
14875
|
+
* `samplingSeconds` must be at or above `dbThreshold` dBFS (see
|
|
14876
|
+
* {@link NC_AUDIO_DBFS_FLOOR}: negative-going, `0` = full scale). The window
|
|
14877
|
+
* must be FULL before it can match — a window open for two of its ten
|
|
14878
|
+
* seconds is 100% of nothing.
|
|
14879
|
+
*
|
|
14880
|
+
* **Why label mode has no window.** It had one, and it never fired: the
|
|
14881
|
+
* analyzer emits ~1 audio frame per second but YAMNet only LABELS one to three
|
|
14882
|
+
* of them per episode, even through continuous crying. The measured maximum
|
|
14883
|
+
* `hitPercent` over the whole live history was 40 — under the shipped default
|
|
14884
|
+
* of 60, so a label rule could not fire at all, ever. A percentage of frames is
|
|
14885
|
+
* the wrong question to ask of a sparse classifier.
|
|
14886
|
+
*
|
|
14887
|
+
* **Fail-closed when NEITHER is given** — every sample would be a trivial hit
|
|
14888
|
+
* and the rule would fire on silence. The schema cannot express "exactly one
|
|
14889
|
+
* of" without becoming a ZodEffects the cap path would have to special-case, so
|
|
14890
|
+
* the exclusivity is enforced where every editor writes (`patchAudio`) and a
|
|
14891
|
+
* legacy rule carrying both resolves to LABEL (the mode that fires).
|
|
14774
14892
|
*
|
|
14775
14893
|
* Labels are the audio macro classes (`AUDIO_MACRO_LABELS` / the NC taxonomy's
|
|
14776
14894
|
* `audio-*` ids). Both spellings are accepted — the matcher normalizes the
|
|
@@ -14778,13 +14896,13 @@ var NcOccupancyConditionSchema = object({
|
|
|
14778
14896
|
* an operator who typed `dog` mean the same thing.
|
|
14779
14897
|
*/
|
|
14780
14898
|
var NcAudioConditionSchema = object({
|
|
14781
|
-
/**
|
|
14899
|
+
/** LABEL MODE: audio macro labels. Present ⇒ fires on the first labelled frame. */
|
|
14782
14900
|
labels: array(string().min(1)).min(1).optional(),
|
|
14783
|
-
/**
|
|
14901
|
+
/** LEVEL MODE: floor in dBFS (negative-going, `0` = full scale). */
|
|
14784
14902
|
dbThreshold: number().min(-96).max(0).optional(),
|
|
14785
|
-
/**
|
|
14903
|
+
/** LEVEL MODE ONLY: percentage of the window's samples that must be hits (1–100). */
|
|
14786
14904
|
hitPercent: number().int().min(1).max(100).default(60),
|
|
14787
|
-
/**
|
|
14905
|
+
/** LEVEL MODE ONLY: length of the sampling window in seconds. */
|
|
14788
14906
|
samplingSeconds: number().int().min(1).max(300).default(10)
|
|
14789
14907
|
});
|
|
14790
14908
|
/**
|
|
@@ -27499,14 +27617,55 @@ method(object({
|
|
|
27499
27617
|
* thing except the comparator: `similarity` (CLIP cosine at the same ROI coords
|
|
27500
27618
|
* vs condition-tagged references) and `llm` (vision-LLM judgment over the crop).
|
|
27501
27619
|
*
|
|
27502
|
-
*
|
|
27503
|
-
*
|
|
27504
|
-
*
|
|
27505
|
-
*
|
|
27506
|
-
|
|
27507
|
-
|
|
27508
|
-
*
|
|
27620
|
+
* **No `deviceConfig`, deliberately.** This shipped as the D14 widget archetype,
|
|
27621
|
+
* which put a "Scenes" tab on one camera's detail page. That is the wrong shape
|
|
27622
|
+
* for the thing: a scene is a standing question about the property ("is the bin
|
|
27623
|
+
* still out"), and the operator's question is "which of my scenes have tripped",
|
|
27624
|
+
* across every camera at once — not "what does camera 617 think". Buried one
|
|
27625
|
+
* camera deep it also could not be found. The surface is now a top-level admin
|
|
27626
|
+
* page (`/scenes`, `pages/Scenes.tsx`) that lists every scene on every camera and
|
|
27627
|
+
* picks the camera inside the create flow, the same shape Events and Faces have.
|
|
27628
|
+
*
|
|
27629
|
+
* The consequence to keep in mind: `host/scene-monitor-editor` is gone from
|
|
27630
|
+
* `HOST_WIDGETS` too. `scripts/check-host-widget-resolves.ts` asserts BOTH
|
|
27631
|
+
* directions, so a registration nobody declares fails exactly as loudly as a
|
|
27632
|
+
* declaration nobody registers. The editor is imported directly by the page.
|
|
27633
|
+
*
|
|
27634
|
+
* `status.kind:'push'` — the engine pushes on every hysteresis flip /
|
|
27635
|
+
* availability change; consumers never poll.
|
|
27636
|
+
*/
|
|
27637
|
+
/** Extensible condition tag. Seeded 'day' | 'ir' (the two variants the operator
|
|
27638
|
+
* captures) plus 'night' | 'dawn' | 'dusk' from the resolver's sun-times band.
|
|
27639
|
+
* Open by design so more can be added without a wire break.
|
|
27640
|
+
*
|
|
27641
|
+
* Matching does NOT fall back across conditions: cross-condition cosines are
|
|
27642
|
+
* not comparable, so "I have never seen this scene in this light" is reported
|
|
27643
|
+
* as `unknown`, never guessed. A day reference scored against an IR frame
|
|
27644
|
+
* collapses the cosine and would latch a false alarm every single night. */
|
|
27509
27645
|
var SceneConditionSchema = string();
|
|
27646
|
+
/** Reserved, engine-owned state id standing for "the region no longer looks
|
|
27647
|
+
* like ANY captured reference". Never authored by an operator, never stored in
|
|
27648
|
+
* `states[]` — it is the synthetic candidate that makes divergence a
|
|
27649
|
+
* first-class hysteresis input rather than a bare `return`. */
|
|
27650
|
+
var SCENE_DIVERGED = "__diverged__";
|
|
27651
|
+
/** `matched` = the baseline is what we see; `diverged` = it demonstrably is not;
|
|
27652
|
+
* `unknown` = we cannot judge (no reference for this condition, encoder model
|
|
27653
|
+
* changed, view shifted, no snapshot). `unknown` is a real value, not a null,
|
|
27654
|
+
* and never counts toward hysteresis in either direction. */
|
|
27655
|
+
var SceneVerdictSchema = _enum([
|
|
27656
|
+
"matched",
|
|
27657
|
+
"diverged",
|
|
27658
|
+
"unknown"
|
|
27659
|
+
]);
|
|
27660
|
+
/** Why a scene cannot judge. Named, because this feature's failure mode is
|
|
27661
|
+
* silence that reads as "nothing has happened". */
|
|
27662
|
+
var SceneUnavailableSchema = _enum([
|
|
27663
|
+
"no-reference-for-condition",
|
|
27664
|
+
"view-shifted",
|
|
27665
|
+
"no-vision-profile",
|
|
27666
|
+
"encoder-model-changed",
|
|
27667
|
+
"no-snapshot"
|
|
27668
|
+
]);
|
|
27510
27669
|
/** One captured reference — condition-tagged, model-version-gated. `embedding`
|
|
27511
27670
|
* is `number[]` (Float32Array does NOT survive MsgPack/UDS). */
|
|
27512
27671
|
var SceneReferenceSchema = object({
|
|
@@ -27514,7 +27673,14 @@ var SceneReferenceSchema = object({
|
|
|
27514
27673
|
modelId: string(),
|
|
27515
27674
|
condition: SceneConditionSchema,
|
|
27516
27675
|
capturedAt: number(),
|
|
27517
|
-
thumbnailMediaId: string().optional()
|
|
27676
|
+
thumbnailMediaId: string().optional(),
|
|
27677
|
+
/** Whole-frame (downscaled) embedding captured alongside the ROI crop. The
|
|
27678
|
+
* anti-view-shift anchor: a bumped camera, a PTZ preset or a re-aim makes the
|
|
27679
|
+
* normalized rect frame a different piece of world, and the scene would
|
|
27680
|
+
* diverge forever with a perfectly plausible cosine. Checked LAZILY, only
|
|
27681
|
+
* when hysteresis is about to flip — one extra encode per candidate
|
|
27682
|
+
* transition, not per poll. */
|
|
27683
|
+
anchorEmbedding: array(number()).optional()
|
|
27518
27684
|
});
|
|
27519
27685
|
var SceneMonitorStateSchema = object({
|
|
27520
27686
|
id: string(),
|
|
@@ -27536,6 +27702,26 @@ var SceneCheckSchema = discriminatedUnion("mode", [object({
|
|
|
27536
27702
|
profileId: string().optional(),
|
|
27537
27703
|
hysteresisCount: number().int().positive()
|
|
27538
27704
|
})]);
|
|
27705
|
+
var SCENE_DEFAULT_ANCHOR_THRESHOLD = .85;
|
|
27706
|
+
var SCENE_CONFIRM_DEFAULT_TIMEOUT_MS = 8e3;
|
|
27707
|
+
/**
|
|
27708
|
+
* Vision-model adjudication of a candidate flip. Field names deliberately
|
|
27709
|
+
* mirror `NcConfirmSchema` so an operator meets one vocabulary, not two.
|
|
27710
|
+
*
|
|
27711
|
+
* `onTimeout` defaults to **'hold'**, the OPPOSITE of `NcConfirmGate`'s
|
|
27712
|
+
* fail-open: a notification suppressed is the worse error there, but a vision
|
|
27713
|
+
* model that timed out has not told us the bin is gone, and a latch is a
|
|
27714
|
+
* stateful claim that costs the operator a trip to reset.
|
|
27715
|
+
*/
|
|
27716
|
+
var SceneConfirmSchema = object({
|
|
27717
|
+
enabled: boolean().default(false),
|
|
27718
|
+
prompt: string().min(1).max(1e3),
|
|
27719
|
+
profileId: string().optional(),
|
|
27720
|
+
timeoutMs: number().int().min(1e3).max(2e4).default(SCENE_CONFIRM_DEFAULT_TIMEOUT_MS),
|
|
27721
|
+
maxImagePx: number().int().min(64).max(2048).default(448),
|
|
27722
|
+
/** What a timeout / unavailable model means for the PENDING flip. */
|
|
27723
|
+
onTimeout: _enum(["flip", "hold"]).default("hold")
|
|
27724
|
+
});
|
|
27539
27725
|
var SceneMonitorSchema = object({
|
|
27540
27726
|
id: string(),
|
|
27541
27727
|
label: string(),
|
|
@@ -27554,7 +27740,41 @@ var SceneMonitorSchema = object({
|
|
|
27554
27740
|
lastConfidence: number().nullable(),
|
|
27555
27741
|
currentCondition: SceneConditionSchema.nullable(),
|
|
27556
27742
|
availability: _enum(["ok", "unavailable"]),
|
|
27557
|
-
unavailableReason: string().nullable()
|
|
27743
|
+
unavailableReason: string().nullable(),
|
|
27744
|
+
/** Which state is "the initial screen". `null` until the first capture. */
|
|
27745
|
+
baselineStateId: string().nullable(),
|
|
27746
|
+
/** Which boolean drives notification rules and any export. */
|
|
27747
|
+
emit: _enum(["latched", "live"]).default("latched"),
|
|
27748
|
+
/** Live: does the region match the baseline RIGHT NOW. */
|
|
27749
|
+
verdict: SceneVerdictSchema,
|
|
27750
|
+
/** Has it been `diverged` at least once since `armedAt` — the operator's boolean. */
|
|
27751
|
+
latched: boolean(),
|
|
27752
|
+
/** Last reset (or creation). */
|
|
27753
|
+
armedAt: number(),
|
|
27754
|
+
divergedAt: number().nullable(),
|
|
27755
|
+
restoredAt: number().nullable(),
|
|
27756
|
+
/** A check is only COUNTED when the device has been quiet this long. Motion
|
|
27757
|
+
* during the window DISCARDS the observation — a car pulling up in front of
|
|
27758
|
+
* the bin must not be able to spend hysteresis credit. */
|
|
27759
|
+
quietSeconds: number().int().min(0).max(3600).default(60),
|
|
27760
|
+
/** An observation only advances the pending count when it is at least this
|
|
27761
|
+
* far from the previously counted one, so N agreeing checks span real time
|
|
27762
|
+
* rather than N adjacent polls inside one occlusion. */
|
|
27763
|
+
minObservationSpacingSec: number().int().min(0).max(3600).default(120),
|
|
27764
|
+
/** Vision-model adjudication of a candidate flip. Similarity primary only. */
|
|
27765
|
+
confirm: SceneConfirmSchema.optional(),
|
|
27766
|
+
/** Whole-frame anchor cosine below which a flip is REFUSED as `view-shifted`. */
|
|
27767
|
+
anchorThreshold: number().min(0).max(1).default(SCENE_DEFAULT_ANCHOR_THRESHOLD),
|
|
27768
|
+
/** Clear the latch on its own when the scene matches again? Default false —
|
|
27769
|
+
* `restoredAt` and the `scene-restored` edge are recorded regardless, so an
|
|
27770
|
+
* automation can react to the bin coming back without the operator's own
|
|
27771
|
+
* alarm silently clearing itself. */
|
|
27772
|
+
autoRestore: boolean().default(false),
|
|
27773
|
+
/** Named cause when `verdict === 'unknown'`. */
|
|
27774
|
+
unavailable: SceneUnavailableSchema.nullable(),
|
|
27775
|
+
/** Conditions that have at least one comparable reference — the coverage line
|
|
27776
|
+
* ("day ✓ · ir ✓ · dusk ✗") that turns a silent fallback into a visible fact. */
|
|
27777
|
+
coveredConditions: array(SceneConditionSchema)
|
|
27558
27778
|
});
|
|
27559
27779
|
var SceneMonitorStatusSchema = object({
|
|
27560
27780
|
monitors: array(SceneMonitorSchema),
|
|
@@ -27567,12 +27787,6 @@ var sceneMonitorCapability = {
|
|
|
27567
27787
|
kind: "wrapper",
|
|
27568
27788
|
defaultActive: true,
|
|
27569
27789
|
deviceTypes: [DeviceType.Camera],
|
|
27570
|
-
deviceConfig: { ui: {
|
|
27571
|
-
kind: "widget",
|
|
27572
|
-
widgetId: "host/scene-monitor-editor",
|
|
27573
|
-
tab: "scenes",
|
|
27574
|
-
label: "Scenes"
|
|
27575
|
-
} },
|
|
27576
27790
|
methods: {
|
|
27577
27791
|
listScenes: method(object({ deviceId: number() }), SceneMonitorStatusSchema),
|
|
27578
27792
|
createScene: method(object({
|
|
@@ -27603,7 +27817,14 @@ var sceneMonitorCapability = {
|
|
|
27603
27817
|
"both"
|
|
27604
27818
|
]).optional(),
|
|
27605
27819
|
checkIntervalSec: number().optional(),
|
|
27606
|
-
check: SceneCheckSchema.optional()
|
|
27820
|
+
check: SceneCheckSchema.optional(),
|
|
27821
|
+
emit: _enum(["latched", "live"]).optional(),
|
|
27822
|
+
quietSeconds: number().int().min(0).max(3600).optional(),
|
|
27823
|
+
minObservationSpacingSec: number().int().min(0).max(3600).optional(),
|
|
27824
|
+
anchorThreshold: number().min(0).max(1).optional(),
|
|
27825
|
+
autoRestore: boolean().optional(),
|
|
27826
|
+
/** `null` clears the vision-model adjudicator. */
|
|
27827
|
+
confirm: SceneConfirmSchema.nullable().optional()
|
|
27607
27828
|
})
|
|
27608
27829
|
}), _void(), {
|
|
27609
27830
|
kind: "mutation",
|
|
@@ -27644,6 +27865,26 @@ var sceneMonitorCapability = {
|
|
|
27644
27865
|
}), _void(), {
|
|
27645
27866
|
kind: "mutation",
|
|
27646
27867
|
auth: "admin"
|
|
27868
|
+
}),
|
|
27869
|
+
/**
|
|
27870
|
+
* Clear the latch, re-arm, and — by default — RE-CAPTURE the baseline for
|
|
27871
|
+
* the CURRENT condition. The bin never goes back in exactly the same spot;
|
|
27872
|
+
* "reset" in the operator's head means *this is the new normal*, and
|
|
27873
|
+
* re-capture is what makes the feature self-healing against slow drift
|
|
27874
|
+
* instead of failing silently weeks later.
|
|
27875
|
+
*
|
|
27876
|
+
* Reachable from three surfaces on this one mutation: the scene card, a
|
|
27877
|
+
* notification button (an `onTrigger` sequence with a `kind:'cap'` step —
|
|
27878
|
+
* no new Notification-Center code at all), and tRPC for scripts.
|
|
27879
|
+
*/
|
|
27880
|
+
resetScene: method(object({
|
|
27881
|
+
deviceId: number(),
|
|
27882
|
+
monitorId: string(),
|
|
27883
|
+
/** Defaults to TRUE at the provider seam — see `SCENE_RESET_RECAPTURES`. */
|
|
27884
|
+
recapture: boolean().optional()
|
|
27885
|
+
}), _void(), {
|
|
27886
|
+
kind: "mutation",
|
|
27887
|
+
auth: "admin"
|
|
27647
27888
|
})
|
|
27648
27889
|
},
|
|
27649
27890
|
status: {
|
|
@@ -28134,12 +28375,64 @@ var NetworkAddressSchema = object({
|
|
|
28134
28375
|
family: string(),
|
|
28135
28376
|
internal: boolean()
|
|
28136
28377
|
});
|
|
28378
|
+
/**
|
|
28379
|
+
* Provenance of the site coordinates, and the whole reason this is not just two
|
|
28380
|
+
* numbers.
|
|
28381
|
+
*
|
|
28382
|
+
* - `operator-set` — a human typed it, or accepted a detection. Authoritative;
|
|
28383
|
+
* nothing overwrites it.
|
|
28384
|
+
* - `derived-from-ip` — the hub geolocated its own public IP once, because a
|
|
28385
|
+
* default that is right to a few kilometres beats the coarse UTC clock split
|
|
28386
|
+
* the sun-times consumers otherwise fall back to.
|
|
28387
|
+
*
|
|
28388
|
+
* The UI shows which one it is. An operator who cannot tell a guess from their
|
|
28389
|
+
* own input will eventually trust the guess.
|
|
28390
|
+
*/
|
|
28391
|
+
var SiteLocationSourceSchema = _enum(["operator-set", "derived-from-ip"]);
|
|
28392
|
+
/**
|
|
28393
|
+
* The read shape: the location plus the honest state of the one-shot derivation.
|
|
28394
|
+
*
|
|
28395
|
+
* `derivationAttemptedAt` is what makes the "one call, ever" contract
|
|
28396
|
+
* inspectable. When it is set and `location` is null, the geo-IP lookup ran and
|
|
28397
|
+
* failed; the hub will NOT try again on its own — the fallback is declared
|
|
28398
|
+
* (consumers degrade to their own last resort) and the operator either types the
|
|
28399
|
+
* coordinates or presses detect.
|
|
28400
|
+
*/
|
|
28401
|
+
var SiteLocationStatusSchema = object({
|
|
28402
|
+
location: object({
|
|
28403
|
+
/** WGS84 decimal degrees. */
|
|
28404
|
+
latitude: number().min(-90).max(90),
|
|
28405
|
+
longitude: number().min(-180).max(180),
|
|
28406
|
+
source: SiteLocationSourceSchema,
|
|
28407
|
+
/** Epoch ms the value was last written. */
|
|
28408
|
+
updatedAt: number(),
|
|
28409
|
+
/**
|
|
28410
|
+
* Human-readable place the geo-IP service reported ("Napoli, IT"). Display
|
|
28411
|
+
* only — never parsed, never matched on. Absent for an operator-typed value.
|
|
28412
|
+
*/
|
|
28413
|
+
label: string().optional()
|
|
28414
|
+
}).nullable(),
|
|
28415
|
+
derivationAttemptedAt: number().nullable(),
|
|
28416
|
+
/** Why the last derivation failed, for the UI to show instead of a shrug. */
|
|
28417
|
+
derivationError: string().nullable()
|
|
28418
|
+
});
|
|
28419
|
+
/** `null` clears the location and re-arms nothing — the derivation stays spent. */
|
|
28420
|
+
var SetSiteLocationInputSchema = object({
|
|
28421
|
+
latitude: number().min(-90).max(90),
|
|
28422
|
+
longitude: number().min(-180).max(180)
|
|
28423
|
+
}).nullable();
|
|
28137
28424
|
method(_void(), FeatureManifestSchema), method(_void(), HealthStatusSchema), method(_void(), FeatureManifestSchema), method(_void(), array(NetworkAddressSchema).readonly()), method(_void(), unknown().nullable(), { auth: "admin" }), method(record(string(), unknown()), _null(), {
|
|
28138
28425
|
kind: "mutation",
|
|
28139
28426
|
auth: "admin"
|
|
28140
28427
|
}), method(_void(), _void(), {
|
|
28141
28428
|
kind: "mutation",
|
|
28142
28429
|
auth: "admin"
|
|
28430
|
+
}), method(_void(), SiteLocationStatusSchema), method(SetSiteLocationInputSchema, SiteLocationStatusSchema, {
|
|
28431
|
+
kind: "mutation",
|
|
28432
|
+
auth: "admin"
|
|
28433
|
+
}), method(_void(), SiteLocationStatusSchema, {
|
|
28434
|
+
kind: "mutation",
|
|
28435
|
+
auth: "admin"
|
|
28143
28436
|
});
|
|
28144
28437
|
/**
|
|
28145
28438
|
* Tamper / case-open detection sensor. Drives Home Assistant
|
|
@@ -32328,6 +32621,12 @@ Object.freeze({
|
|
|
32328
32621
|
addonId: null,
|
|
32329
32622
|
access: "create"
|
|
32330
32623
|
},
|
|
32624
|
+
"llm.cancel": {
|
|
32625
|
+
capName: "llm",
|
|
32626
|
+
capScope: "system",
|
|
32627
|
+
addonId: null,
|
|
32628
|
+
access: "create"
|
|
32629
|
+
},
|
|
32331
32630
|
"llm.deleteModel": {
|
|
32332
32631
|
capName: "llm",
|
|
32333
32632
|
capScope: "system",
|
|
@@ -34578,6 +34877,12 @@ Object.freeze({
|
|
|
34578
34877
|
addonId: null,
|
|
34579
34878
|
access: "create"
|
|
34580
34879
|
},
|
|
34880
|
+
"sceneMonitor.resetScene": {
|
|
34881
|
+
capName: "scene-monitor",
|
|
34882
|
+
capScope: "device",
|
|
34883
|
+
addonId: null,
|
|
34884
|
+
access: "delete"
|
|
34885
|
+
},
|
|
34581
34886
|
"sceneMonitor.updateScene": {
|
|
34582
34887
|
capName: "scene-monitor",
|
|
34583
34888
|
capScope: "device",
|
|
@@ -35256,6 +35561,12 @@ Object.freeze({
|
|
|
35256
35561
|
addonId: null,
|
|
35257
35562
|
access: "create"
|
|
35258
35563
|
},
|
|
35564
|
+
"system.detectSiteLocation": {
|
|
35565
|
+
capName: "system",
|
|
35566
|
+
capScope: "system",
|
|
35567
|
+
addonId: null,
|
|
35568
|
+
access: "create"
|
|
35569
|
+
},
|
|
35259
35570
|
"system.featureFlags": {
|
|
35260
35571
|
capName: "system",
|
|
35261
35572
|
capScope: "system",
|
|
@@ -35274,6 +35585,12 @@ Object.freeze({
|
|
|
35274
35585
|
addonId: null,
|
|
35275
35586
|
access: "view"
|
|
35276
35587
|
},
|
|
35588
|
+
"system.getSiteLocation": {
|
|
35589
|
+
capName: "system",
|
|
35590
|
+
capScope: "system",
|
|
35591
|
+
addonId: null,
|
|
35592
|
+
access: "view"
|
|
35593
|
+
},
|
|
35277
35594
|
"system.health": {
|
|
35278
35595
|
capName: "system",
|
|
35279
35596
|
capScope: "system",
|
|
@@ -35298,6 +35615,12 @@ Object.freeze({
|
|
|
35298
35615
|
addonId: null,
|
|
35299
35616
|
access: "create"
|
|
35300
35617
|
},
|
|
35618
|
+
"system.setSiteLocation": {
|
|
35619
|
+
capName: "system",
|
|
35620
|
+
capScope: "system",
|
|
35621
|
+
addonId: null,
|
|
35622
|
+
access: "create"
|
|
35623
|
+
},
|
|
35301
35624
|
"terminalSession.adoptLegacyMonitor": {
|
|
35302
35625
|
capName: "terminal-session",
|
|
35303
35626
|
capScope: "system",
|
|
@@ -37260,6 +37583,11 @@ Object.freeze({
|
|
|
37260
37583
|
form: "single",
|
|
37261
37584
|
optional: false
|
|
37262
37585
|
}],
|
|
37586
|
+
"sceneMonitor.resetScene": [{
|
|
37587
|
+
name: "deviceId",
|
|
37588
|
+
form: "single",
|
|
37589
|
+
optional: false
|
|
37590
|
+
}],
|
|
37263
37591
|
"sceneMonitor.updateScene": [{
|
|
37264
37592
|
name: "deviceId",
|
|
37265
37593
|
form: "single",
|
|
@@ -37550,6 +37878,26 @@ Object.freeze({
|
|
|
37550
37878
|
"network-access": "ingress",
|
|
37551
37879
|
"smtp-provider": "email"
|
|
37552
37880
|
});
|
|
37881
|
+
/**
|
|
37882
|
+
* Which mode this condition is in — the ONE place that question is answered.
|
|
37883
|
+
*
|
|
37884
|
+
* The mode is NOT a stored field, deliberately. It is which filter the rule
|
|
37885
|
+
* carries, so every rule authored before the modes existed migrates for free
|
|
37886
|
+
* and there is no second switch that can disagree with the first (the failure
|
|
37887
|
+
* this repo has shipped twice). `null` = neither filter, which the engine
|
|
37888
|
+
* refuses (see {@link audioIsFailClosed}).
|
|
37889
|
+
*
|
|
37890
|
+
* A LEGACY rule carrying BOTH resolves to `label`: it is the mode that fires,
|
|
37891
|
+
* and the alternative is silently keeping a window the operator can no longer
|
|
37892
|
+
* see in the editor. Nothing new can reach this branch — {@link patchAudio}
|
|
37893
|
+
* clears the other filter on every write.
|
|
37894
|
+
*/
|
|
37895
|
+
function audioModeOf(value) {
|
|
37896
|
+
if (value === void 0) return null;
|
|
37897
|
+
if (value.labels !== void 0 && value.labels.length > 0) return "label";
|
|
37898
|
+
if (value.dbThreshold !== void 0) return "level";
|
|
37899
|
+
return null;
|
|
37900
|
+
}
|
|
37553
37901
|
new Map(AUDIO_MACRO_LABELS.flatMap((macro) => macro.icon === void 0 ? [] : [[macro.id, macro.icon]]));
|
|
37554
37902
|
new Set(["devices", "classes"]);
|
|
37555
37903
|
var WEEKDAY_TO_DAY = {
|
|
@@ -38286,6 +38634,30 @@ Object.defineProperty(exports, "RetrainStatusSchema", {
|
|
|
38286
38634
|
return RetrainStatusSchema;
|
|
38287
38635
|
}
|
|
38288
38636
|
});
|
|
38637
|
+
Object.defineProperty(exports, "SCENE_CONFIRM_DEFAULT_TIMEOUT_MS", {
|
|
38638
|
+
enumerable: true,
|
|
38639
|
+
get: function() {
|
|
38640
|
+
return SCENE_CONFIRM_DEFAULT_TIMEOUT_MS;
|
|
38641
|
+
}
|
|
38642
|
+
});
|
|
38643
|
+
Object.defineProperty(exports, "SCENE_DEFAULT_ANCHOR_THRESHOLD", {
|
|
38644
|
+
enumerable: true,
|
|
38645
|
+
get: function() {
|
|
38646
|
+
return SCENE_DEFAULT_ANCHOR_THRESHOLD;
|
|
38647
|
+
}
|
|
38648
|
+
});
|
|
38649
|
+
Object.defineProperty(exports, "SCENE_DIVERGED", {
|
|
38650
|
+
enumerable: true,
|
|
38651
|
+
get: function() {
|
|
38652
|
+
return SCENE_DIVERGED;
|
|
38653
|
+
}
|
|
38654
|
+
});
|
|
38655
|
+
Object.defineProperty(exports, "SceneMonitorSchema", {
|
|
38656
|
+
enumerable: true,
|
|
38657
|
+
get: function() {
|
|
38658
|
+
return SceneMonitorSchema;
|
|
38659
|
+
}
|
|
38660
|
+
});
|
|
38289
38661
|
Object.defineProperty(exports, "TIMELAPSE_DENSE_FLOOR_SEC", {
|
|
38290
38662
|
enumerable: true,
|
|
38291
38663
|
get: function() {
|
|
@@ -38364,6 +38736,12 @@ Object.defineProperty(exports, "audioMetricsCapability", {
|
|
|
38364
38736
|
return audioMetricsCapability;
|
|
38365
38737
|
}
|
|
38366
38738
|
});
|
|
38739
|
+
Object.defineProperty(exports, "audioModeOf", {
|
|
38740
|
+
enumerable: true,
|
|
38741
|
+
get: function() {
|
|
38742
|
+
return audioModeOf;
|
|
38743
|
+
}
|
|
38744
|
+
});
|
|
38367
38745
|
Object.defineProperty(exports, "boolean", {
|
|
38368
38746
|
enumerable: true,
|
|
38369
38747
|
get: function() {
|
|
@@ -38538,6 +38916,12 @@ Object.defineProperty(exports, "record", {
|
|
|
38538
38916
|
return record;
|
|
38539
38917
|
}
|
|
38540
38918
|
});
|
|
38919
|
+
Object.defineProperty(exports, "sceneMonitorCapability", {
|
|
38920
|
+
enumerable: true,
|
|
38921
|
+
get: function() {
|
|
38922
|
+
return sceneMonitorCapability;
|
|
38923
|
+
}
|
|
38924
|
+
});
|
|
38541
38925
|
Object.defineProperty(exports, "sleep", {
|
|
38542
38926
|
enumerable: true,
|
|
38543
38927
|
get: function() {
|