@camstack/addon-pipeline 1.2.78 → 1.2.80

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/dist/{addon-utils-C-XbUkiG.js → addon-utils-C4Cge0S0.js} +1 -1
  2. package/dist/audio-analyzer/index.js +2 -2
  3. package/dist/audio-analyzer/index.mjs +1 -1
  4. package/dist/detection-pipeline/index.js +4 -4
  5. package/dist/detection-pipeline/index.mjs +2 -2
  6. package/dist/{dist-CsP_DikG.mjs → dist-Bf1SE1Ew.mjs} +184 -5
  7. package/dist/{dist-BdVCXl5n.js → dist-ZSiUDGzf.js} +184 -5
  8. package/dist/{event-loop-stall-monitor-C3cvE_Xk.mjs → event-loop-stall-monitor-CjWfos2b.mjs} +1 -1
  9. package/dist/{event-loop-stall-monitor-BOu8lGee.js → event-loop-stall-monitor-VcDGoua3.js} +1 -1
  10. package/dist/{lazy-sharp-1LkmyWqV.js → lazy-sharp-CC4WNiKY.js} +1 -1
  11. package/dist/motion-wasm/index.js +2 -2
  12. package/dist/motion-wasm/index.mjs +1 -1
  13. package/dist/pipeline-runner/index.js +4 -4
  14. package/dist/pipeline-runner/index.mjs +3 -3
  15. package/dist/recorder/index.js +62 -5
  16. package/dist/recorder/index.mjs +61 -4
  17. package/dist/session-decode/decode-worker-child.js +2 -2
  18. package/dist/session-decode/decode-worker-child.mjs +1 -1
  19. package/dist/stream-broker/_stub.js +2 -2
  20. package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-DUi-lR4R.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-B1oVjQLS.mjs} +2 -2
  21. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-BjDv7QMq.mjs +26 -0
  22. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-DEps-9qh.mjs +26 -0
  23. package/dist/stream-broker/{hostInit-DEtsjgBO.mjs → hostInit-D_m-NYyr.mjs} +2 -2
  24. package/dist/stream-broker/index.js +252 -30
  25. package/dist/stream-broker/index.mjs +252 -30
  26. package/dist/stream-broker/remoteEntry.js +1 -1
  27. package/dist/{worker-protocol-B4fPjmXk.js → worker-protocol-KDfFzKgT.js} +1 -1
  28. package/dist/{worker-protocol-BRwzX3f_.mjs → worker-protocol-p66oO1xL.mjs} +1 -1
  29. package/package.json +1 -1
  30. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-1QMyGZMB.mjs +0 -26
  31. package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-Dg08SxUW.mjs +0 -26
@@ -1,4 +1,4 @@
1
- const require_dist = require("./dist-BdVCXl5n.js");
1
+ const require_dist = require("./dist-ZSiUDGzf.js");
2
2
  require("node:crypto");
3
3
  let node_path = require("node:path");
4
4
  node_path = require_dist.__toESM(node_path, 1);
@@ -2,9 +2,9 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_dist = require("../dist-BdVCXl5n.js");
5
+ const require_dist = require("../dist-ZSiUDGzf.js");
6
6
  const require_node_topology_platform = require("../node-topology-platform-CFZ7F4xW.js");
7
- const require_addon_utils = require("../addon-utils-C-XbUkiG.js");
7
+ const require_addon_utils = require("../addon-utils-C4Cge0S0.js");
8
8
  let node_path = require("node:path");
9
9
  node_path = require_dist.__toESM(node_path);
10
10
  let node_fs = require("node:fs");
@@ -1,5 +1,5 @@
1
1
  import { n as __require } from "../chunk-DnnnRqeS.mjs";
2
- import { B as mapAudioLabelToMacro, E as audioAnalyzerCapability, T as audioAnalysisCapability, ft as hydrateSchema, m as HF_BASE_URL, n as AUDIO_BACKEND_CHOICES, o as DEFAULT_AUDIO_ANALYZER_CONFIG, st as BaseAddon, tt as errMsg } from "../dist-CsP_DikG.mjs";
2
+ import { B as mapAudioLabelToMacro, E as audioAnalyzerCapability, T as audioAnalysisCapability, ft as hydrateSchema, m as HF_BASE_URL, n as AUDIO_BACKEND_CHOICES, o as DEFAULT_AUDIO_ANALYZER_CONFIG, st as BaseAddon, tt as errMsg } from "../dist-Bf1SE1Ew.mjs";
3
3
  import { t as pickNodePlatformArch } from "../node-topology-platform-BkR_k6WT.mjs";
4
4
  import { i as downloadFile } from "../addon-utils-A2S9D7pu.mjs";
5
5
  import * as path$1 from "node:path";
@@ -2,11 +2,11 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_dist = require("../dist-BdVCXl5n.js");
6
- const require_event_loop_stall_monitor = require("../event-loop-stall-monitor-BOu8lGee.js");
7
- const require_lazy_sharp = require("../lazy-sharp-1LkmyWqV.js");
5
+ const require_dist = require("../dist-ZSiUDGzf.js");
6
+ const require_event_loop_stall_monitor = require("../event-loop-stall-monitor-VcDGoua3.js");
7
+ const require_lazy_sharp = require("../lazy-sharp-CC4WNiKY.js");
8
8
  const require_node_topology_platform = require("../node-topology-platform-CFZ7F4xW.js");
9
- const require_addon_utils = require("../addon-utils-C-XbUkiG.js");
9
+ const require_addon_utils = require("../addon-utils-C4Cge0S0.js");
10
10
  let sharp = require("sharp");
11
11
  sharp = require_dist.__toESM(sharp);
12
12
  let node_child_process = require("node:child_process");
@@ -1,6 +1,6 @@
1
1
  import { n as __require } from "../chunk-DnnnRqeS.mjs";
2
- import { $ as supportedRuntimes$1, A as defaultDeviceFor$1, At as string, C as YAMNET_TO_MACRO, G as pipelineExecutorCapability, L as enumerateInferenceDevices, Mt as EventCategory, Ot as object, P as detectionPipelineCapability, R as evaluateZoneRules, St as array, X as runtimeDevices$1, _t as parseJsonUnknown, bt as sleep, dt as createEvent, ft as hydrateSchema, gt as nodePin, jt as union, st as BaseAddon, t as APPLE_SA_TO_MACRO, tt as errMsg, u as DEVICE_BACKEND_TO_FORMAT } from "../dist-CsP_DikG.mjs";
3
- import { a as getDefaultModelForFormat, c as getStepDefinition, i as ALL_STEPS, l as resolveModelForFormat, n as startEventLoopStallMonitor, o as getDefaultModelForFormatFromDef, r as ALL_PIPELINE_STEPS, s as getStep } from "../event-loop-stall-monitor-C3cvE_Xk.mjs";
2
+ import { $ as supportedRuntimes$1, A as defaultDeviceFor$1, At as string, C as YAMNET_TO_MACRO, G as pipelineExecutorCapability, L as enumerateInferenceDevices, Mt as EventCategory, Ot as object, P as detectionPipelineCapability, R as evaluateZoneRules, St as array, X as runtimeDevices$1, _t as parseJsonUnknown, bt as sleep, dt as createEvent, ft as hydrateSchema, gt as nodePin, jt as union, st as BaseAddon, t as APPLE_SA_TO_MACRO, tt as errMsg, u as DEVICE_BACKEND_TO_FORMAT } from "../dist-Bf1SE1Ew.mjs";
3
+ import { a as getDefaultModelForFormat, c as getStepDefinition, i as ALL_STEPS, l as resolveModelForFormat, n as startEventLoopStallMonitor, o as getDefaultModelForFormatFromDef, r as ALL_PIPELINE_STEPS, s as getStep } from "../event-loop-stall-monitor-CjWfos2b.mjs";
4
4
  import { t as getSharp } from "../lazy-sharp-6oymT_yf.mjs";
5
5
  import { t as pickNodePlatformArch } from "../node-topology-platform-BkR_k6WT.mjs";
6
6
  import { a as ensureModel, o as isModelDownloaded, r as deleteModelFromDisk } from "../addon-utils-A2S9D7pu.mjs";
@@ -13704,6 +13704,18 @@ var LlmGenerateBaseInputSchema = object({
13704
13704
  * Resource ceiling = llama-server flags + idleStopMinutes ONLY (no RSS
13705
13705
  * watchdog — operator decision #3).
13706
13706
  */
13707
+ /**
13708
+ * A companion artifact that MUST land beside the main GGUF: the `mmproj`
13709
+ * projector of a vision model, or shards 2..N of a split GGUF. Carried on the
13710
+ * REF rather than looked up at install time, so what the operator approved in
13711
+ * the preview is exactly what the node downloads.
13712
+ */
13713
+ var ManagedModelExtraFileSchema = object({
13714
+ url: string(),
13715
+ filename: string(),
13716
+ sizeBytes: number(),
13717
+ sha256: string().optional()
13718
+ });
13707
13719
  var ManagedModelRefSchema = discriminatedUnion("kind", [
13708
13720
  object({
13709
13721
  kind: literal("catalog"),
@@ -13712,7 +13724,11 @@ var ManagedModelRefSchema = discriminatedUnion("kind", [
13712
13724
  object({
13713
13725
  kind: literal("url"),
13714
13726
  url: string(),
13715
- sha256: string().optional()
13727
+ sha256: string().optional(),
13728
+ /** Picker/status label; the file basename when absent. */
13729
+ label: string().optional(),
13730
+ sizeBytes: number().optional(),
13731
+ extraFiles: array(ManagedModelExtraFileSchema).optional()
13716
13732
  }),
13717
13733
  object({
13718
13734
  kind: literal("path"),
@@ -13773,11 +13789,39 @@ var ManagedRuntimeConfigSchema = object({
13773
13789
  "q4_1",
13774
13790
  "q4_0"
13775
13791
  ]).optional(),
13792
+ /**
13793
+ * Escape hatch for llama-server flags this schema does NOT model — `--jinja`
13794
+ * (which most vision chat templates need and some language-only models
13795
+ * dislike), `--cont-batching`, `--rope-scaling`, …
13796
+ *
13797
+ * It is NOT a second place to set the flags above. A token that collides
13798
+ * with a typed field is REJECTED at start, naming the field that owns it
13799
+ * (`assertNoOwnedFlags`), because two knobs writing the same argv is exactly
13800
+ * the "two switches that disagree" failure this repo has already shipped
13801
+ * twice (D62).
13802
+ */
13803
+ extraArgs: array(string()).default([]),
13776
13804
  /** Else lazy: first generate boots it. */
13777
13805
  autoStart: boolean().default(false),
13778
13806
  /** 0 = never; frees RAM after quiet periods. */
13779
13807
  idleStopMinutes: number().int().default(30)
13780
13808
  });
13809
+ /**
13810
+ * Where a multi-GB install currently is. A single 0..1 fraction cannot answer
13811
+ * "is it stuck?" for an install that is three files (shards + mmproj) followed
13812
+ * by a sha256 pass over 22 GB — during which the fraction sat at 1.0 and the
13813
+ * node looked hung. Phase + file + bytes is the smallest shape that does.
13814
+ */
13815
+ var LlmDownloadProgressSchema = object({
13816
+ phase: _enum(["downloading", "verifying"]),
13817
+ /** The artifact currently moving, e.g. `mmproj-F16.gguf`. */
13818
+ file: string(),
13819
+ fileIndex: number().int(),
13820
+ fileCount: number().int(),
13821
+ /** Across the WHOLE install, not the current file. */
13822
+ downloadedBytes: number(),
13823
+ totalBytes: number().optional()
13824
+ });
13781
13825
  var LlmRuntimeStatusSchema = object({
13782
13826
  /** Status is ALWAYS node-qualified. */
13783
13827
  nodeId: string(),
@@ -13794,6 +13838,8 @@ var LlmRuntimeStatusSchema = object({
13794
13838
  modelPath: string().optional(),
13795
13839
  modelId: string().optional(),
13796
13840
  downloadProgress: number().min(0).max(1).optional(),
13841
+ /** Detail behind `downloadProgress`; present for the same lifetime. */
13842
+ download: LlmDownloadProgressSchema.optional(),
13797
13843
  lastError: string().optional(),
13798
13844
  crashesInWindow: number(),
13799
13845
  /** Child RSS (sampled best-effort). */
@@ -13804,7 +13850,14 @@ var LlmNodeModelSchema = object({
13804
13850
  file: string(),
13805
13851
  sizeBytes: number(),
13806
13852
  catalogId: string().optional(),
13807
- installedAt: number().optional()
13853
+ installedAt: number().optional(),
13854
+ /**
13855
+ * Absolute path on the node. Present so a file that is on disk but matches
13856
+ * no catalog entry — a custom Hugging Face install, or a GGUF the operator
13857
+ * copied in by hand — is still SELECTABLE, as a `{kind:'path'}` ref. Without
13858
+ * it the picker could list such a file and do nothing with it.
13859
+ */
13860
+ path: string().optional()
13808
13861
  });
13809
13862
  var LlmRuntimeDiskUsageSchema = object({
13810
13863
  nodeId: string(),
@@ -13882,9 +13935,12 @@ var LlmProfileSchema = object({
13882
13935
  systemPrompt: string().optional(),
13883
13936
  /** Total generation bound — the only one a unary call has. */
13884
13937
  timeoutMs: number().int().positive().default(6e4),
13885
- /** Wait for response headers only. */
13938
+ /** The TCP handshake only — "is the port even open". NOT the wait for
13939
+ * response headers: on the LM Studio / llama-server wire those are written
13940
+ * once the model has finished loading, so they belong to the bound below. */
13886
13941
  connectTimeoutMs: number().int().positive().default(1e4),
13887
- /** Accepted, but no output yet — a cold GPU load lives here. */
13942
+ /** Accepted, but no output yet — response headers included, because a cold
13943
+ * GPU load is exactly what happens before them. */
13888
13944
  firstTokenTimeoutMs: number().int().positive().default(12e4),
13889
13945
  /** Output started then stopped. */
13890
13946
  idleTimeoutMs: number().int().positive().default(6e4),
@@ -13947,6 +14003,36 @@ var ManagedModelCatalogEntrySchema = object({
13947
14003
  /** Vision models: companion projector file. */
13948
14004
  mmprojUrl: string().optional()
13949
14005
  });
14006
+ /**
14007
+ * The outcome of turning one operator-typed Hugging Face reference into a
14008
+ * download plan. A RESULT, never a throw: "this repo has 24 quantizations and
14009
+ * I will not pick for you" is a normal answer the UI has to render, not an
14010
+ * exception.
14011
+ *
14012
+ * `candidates` is the whole reason the refusal is usable — every string in it
14013
+ * is a tag that resolves when pasted back as `<org>/<repo>:<TAG>`.
14014
+ */
14015
+ var HfModelResolutionSchema = discriminatedUnion("ok", [object({
14016
+ ok: literal(true),
14017
+ /** Ready to hand to `installModel` unchanged. */
14018
+ model: ManagedModelRefSchema,
14019
+ label: string(),
14020
+ repo: string(),
14021
+ quantization: string(),
14022
+ purpose: _enum(["text", "vision"]),
14023
+ totalBytes: number(),
14024
+ /** mmproj + shards, for the preview: an operator approving 23 GB should
14025
+ * see that 0.9 GB of it is a projector they did not name. */
14026
+ extraFilenames: array(string())
14027
+ }), object({
14028
+ ok: literal(false),
14029
+ code: string(),
14030
+ message: string(),
14031
+ candidates: array(string()).optional(),
14032
+ /** Set when the refusal was only the ceiling: re-calling with
14033
+ * `maxBytes: requiredBytes` is the operator's explicit override. */
14034
+ requiredBytes: number().optional()
14035
+ })]);
13950
14036
  var LlmRuntimeNodeSchema = object({
13951
14037
  nodeId: string(),
13952
14038
  reachable: boolean(),
@@ -13983,6 +14069,15 @@ method(LlmGenerateBaseInputSchema, LlmGenerateResultSchema, { kind: "mutation" }
13983
14069
  consumer: string().optional(),
13984
14070
  profileId: string().optional()
13985
14071
  }), array(LlmUsageRollupSchema)), method(object({}), array(ManagedModelCatalogEntrySchema)), method(object({}), array(LlmRuntimeNodeSchema)), method(object({ nodeId: string() }), array(LlmNodeModelSchema)), method(object({
14072
+ /** `https://huggingface.co/<org>/<repo>/resolve/main/<f>.gguf`,
14073
+ * `<org>/<repo>/<f>.gguf`, `<org>/<repo>` or `<org>/<repo>:<QUANT>`. */
14074
+ ref: string(),
14075
+ /** Explicit ceiling override, in bytes. Absent = the built-in ceiling. */
14076
+ maxBytes: number().positive().optional()
14077
+ }), HfModelResolutionSchema, {
14078
+ kind: "mutation",
14079
+ auth: "admin"
14080
+ }), method(object({
13986
14081
  nodeId: string(),
13987
14082
  model: ManagedModelRefSchema
13988
14083
  }), _void(), {
@@ -19610,6 +19705,17 @@ var maxSessionHoldMsField = {
19610
19705
  default: 12e4,
19611
19706
  step: 5e3
19612
19707
  };
19708
+ /**
19709
+ * Quiet period that closes an `audioMode: 'on-motion'` audio window. Floor of
19710
+ * 5s so a rearm can never degenerate into per-event stream churn; default 90s
19711
+ * comfortably outlives the gap between two PIR wakes on a battery camera.
19712
+ */
19713
+ var audioMotionWindowMsField = {
19714
+ min: 5e3,
19715
+ max: 6e5,
19716
+ default: 9e4,
19717
+ step: 5e3
19718
+ };
19613
19719
  var motionFpsField = {
19614
19720
  min: 1,
19615
19721
  max: 30,
@@ -19786,6 +19892,27 @@ var RunnerCameraConfigSchema = object({
19786
19892
  * resolved `CameraDetectionConfig`.
19787
19893
  */
19788
19894
  maxSessionHoldMs: number().min(maxSessionHoldMsField.min).max(maxSessionHoldMsField.max).optional(),
19895
+ /**
19896
+ * Orchestrator-side quiet period (ms) that closes an `audioMode:
19897
+ * 'on-motion'` audio window, measured from the LAST motion event.
19898
+ *
19899
+ * This exists because the falling edge cannot be relied on. Camera-native
19900
+ * providers emit motion as a RISING EDGE ONLY (Reolink's Baichuan push and
19901
+ * its email-push SMTP path both emit `detected: true` and never the
19902
+ * counterpart); only the frame-diff analyzer emits falls. So on an
19903
+ * onboard-only camera a window that closed only on `detected: false` never
19904
+ * closed at all, and `on-motion` silently behaved as `always-on` — on a
19905
+ * battery camera, the one failure mode the mode exists to prevent.
19906
+ *
19907
+ * Every motion event rearms this timer WITHOUT restarting the stream, so a
19908
+ * burst of re-fires costs nothing. A falling edge, when one does arrive,
19909
+ * still closes earlier via `motionCooldownMs` — whichever comes first wins.
19910
+ *
19911
+ * Not consumed by the runner: carried here so it shares the per-camera
19912
+ * device-settings surface with `motionCooldownMs`, exactly like
19913
+ * `maxSessionHoldMs`.
19914
+ */
19915
+ audioMotionWindowMs: number().min(audioMotionWindowMsField.min).max(audioMotionWindowMsField.max).optional(),
19789
19916
  motionFps: number().min(motionFpsField.min).max(motionFpsField.max).default(motionFpsField.default),
19790
19917
  detectionFps: number().min(detectionFpsField.min).max(detectionFpsField.max).default(detectionFpsField.default),
19791
19918
  motionStreamId: string(),
@@ -19881,7 +20008,7 @@ var RunnerCameraConfigSchema = object({
19881
20008
  */
19882
20009
  inferenceDevices: array(RunnerInferenceDeviceSchema).readonly().optional()
19883
20010
  });
19884
- motionFpsField.min, motionFpsField.max, motionFpsField.step, motionFpsField.default, detectionFpsField.min, detectionFpsField.max, detectionFpsField.step, detectionFpsField.default, motionCooldownMsField.min, motionCooldownMsField.max, motionCooldownMsField.step, motionCooldownMsField.default, maxSessionHoldMsField.min, maxSessionHoldMsField.max, maxSessionHoldMsField.step, maxSessionHoldMsField.default, occupancyRecheckSecField.min, occupancyRecheckSecField.max, occupancyRecheckSecField.step, occupancyRecheckSecField.default, occupancyRecheckFramesField.min, occupancyRecheckFramesField.max, occupancyRecheckFramesField.step, occupancyRecheckFramesField.default;
20011
+ motionFpsField.min, motionFpsField.max, motionFpsField.step, motionFpsField.default, detectionFpsField.min, detectionFpsField.max, detectionFpsField.step, detectionFpsField.default, motionCooldownMsField.min, motionCooldownMsField.max, motionCooldownMsField.step, motionCooldownMsField.default, maxSessionHoldMsField.min, maxSessionHoldMsField.max, maxSessionHoldMsField.step, maxSessionHoldMsField.default, audioMotionWindowMsField.min, audioMotionWindowMsField.max, audioMotionWindowMsField.step, audioMotionWindowMsField.default, occupancyRecheckSecField.min, occupancyRecheckSecField.max, occupancyRecheckSecField.step, occupancyRecheckSecField.default, occupancyRecheckFramesField.min, occupancyRecheckFramesField.max, occupancyRecheckFramesField.step, occupancyRecheckFramesField.default;
19885
20012
  /**
19886
20013
  * Runtime load summary returned by `getLocalLoad`. Used by the orchestrator's
19887
20014
  * load-balancing levels (L2 capacity-based, L3 hardware-aware) to decide
@@ -26676,6 +26803,33 @@ var recordingExportCapability = {
26676
26803
  * as `unknown`, never guessed. A day reference scored against an IR frame
26677
26804
  * collapses the cosine and would latch a false alarm every single night. */
26678
26805
  var SceneConditionSchema = string();
26806
+ /**
26807
+ * What a scene does when the CURRENT light has no reference of its own.
26808
+ *
26809
+ * The lighting variants are not equally likely to exist. Almost every operator
26810
+ * captures daylight and then never stands outside at 22:00 to capture IR, and a
26811
+ * scene that is only ever going to be asked about a daytime question ("is the
26812
+ * bin still on the kerb at 08:00") does not need a night reference at all. The
26813
+ * night half must therefore be OPTIONAL, and optional means the scene keeps
26814
+ * working without it rather than degrading into a permanent complaint.
26815
+ *
26816
+ * - `skip` (default) — the check in that light is not made. Not a verdict, not
26817
+ * an alarm, not even an `unknown`: the live state simply stays whatever the
26818
+ * last covered light left it at, the latch is untouched, and the hysteresis
26819
+ * run is neither spent nor cleared. The scene resumes by itself at first
26820
+ * light. This is the only behaviour under which "I never captured IR" is a
26821
+ * configuration choice instead of a nightly fault.
26822
+ * - `judge-anyway` — score against the OTHER conditions' references. Available
26823
+ * for cameras whose IR frame is close enough to daylight (a floodlit
26824
+ * driveway, an always-white-light doorbell), and wrong for everything else:
26825
+ * cross-condition cosines are not comparable, so a day reference against a
26826
+ * true IR frame collapses and the scene reports a theft at 21:40.
26827
+ *
26828
+ * Never applies when the scene has NO comparable reference at all — that is
26829
+ * "not armed yet", it is reported as `no-reference-for-condition`, and silence
26830
+ * there would hide a scene the operator never finished setting up.
26831
+ */
26832
+ var SceneUncoveredPolicySchema = _enum(["skip", "judge-anyway"]);
26679
26833
  /** `matched` = the baseline is what we see; `diverged` = it demonstrably is not;
26680
26834
  * `unknown` = we cannot judge (no reference for this condition, encoder model
26681
26835
  * changed, view shifted, no snapshot). `unknown` is a real value, not a null,
@@ -26731,6 +26885,9 @@ var SceneCheckSchema = discriminatedUnion("mode", [object({
26731
26885
  hysteresisCount: number().int().positive()
26732
26886
  })]);
26733
26887
  var SCENE_DEFAULT_ANCHOR_THRESHOLD = .85;
26888
+ /** Night is OPTIONAL. A scene with only a daylight reference sits the IR hours
26889
+ * out in silence rather than reporting a fault every night. */
26890
+ var SCENE_DEFAULT_UNCOVERED_POLICY = "skip";
26734
26891
  /**
26735
26892
  * Vision-model adjudication of a candidate flip. Field names deliberately
26736
26893
  * mirror `NcConfirmSchema` so an operator meets one vocabulary, not two.
@@ -26797,6 +26954,21 @@ var SceneMonitorSchema = object({
26797
26954
  * automation can react to the bin coming back without the operator's own
26798
26955
  * alarm silently clearing itself. */
26799
26956
  autoRestore: boolean().default(false),
26957
+ /** What to do when the current light has no reference of its own. See
26958
+ * {@link SceneUncoveredPolicySchema} — the default makes night OPTIONAL. */
26959
+ onUncoveredCondition: SceneUncoveredPolicySchema.default(SCENE_DEFAULT_UNCOVERED_POLICY),
26960
+ /**
26961
+ * The light whose checks are currently being SAT OUT under
26962
+ * `onUncoveredCondition: 'skip'` — `null` when the scene is checking normally.
26963
+ *
26964
+ * Engine-reported and advisory only: it moves no verdict, no latch and no
26965
+ * hysteresis. It exists so the card can say *"night (IR) — checks paused,
26966
+ * nothing captured in this light"* in the same calm voice as the coverage
26967
+ * line, because the alternative is a scene that silently stops answering
26968
+ * after sunset with nothing anywhere saying why. A skipped check must never
26969
+ * read as a broken one.
26970
+ */
26971
+ suspendedCondition: SceneConditionSchema.nullable().default(null),
26800
26972
  /** Named cause when `verdict === 'unknown'`. */
26801
26973
  unavailable: SceneUnavailableSchema.nullable(),
26802
26974
  /** Conditions that have at least one comparable reference — the coverage line
@@ -26840,6 +27012,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), SceneMonitorStatusSche
26840
27012
  minObservationSpacingSec: number().int().min(0).max(3600).optional(),
26841
27013
  anchorThreshold: number().min(0).max(1).optional(),
26842
27014
  autoRestore: boolean().optional(),
27015
+ onUncoveredCondition: SceneUncoveredPolicySchema.optional(),
26843
27016
  /** `null` clears the vision-model adjudicator. */
26844
27017
  confirm: SceneConfirmSchema.nullable().optional()
26845
27018
  })
@@ -30072,6 +30245,12 @@ Object.freeze({
30072
30245
  addonId: null,
30073
30246
  access: "view"
30074
30247
  },
30248
+ "llm.resolveModelRef": {
30249
+ capName: "llm",
30250
+ capScope: "system",
30251
+ addonId: null,
30252
+ access: "create"
30253
+ },
30075
30254
  "llm.setDefault": {
30076
30255
  capName: "llm",
30077
30256
  capScope: "system",
@@ -13727,6 +13727,18 @@ var LlmGenerateBaseInputSchema = object({
13727
13727
  * Resource ceiling = llama-server flags + idleStopMinutes ONLY (no RSS
13728
13728
  * watchdog — operator decision #3).
13729
13729
  */
13730
+ /**
13731
+ * A companion artifact that MUST land beside the main GGUF: the `mmproj`
13732
+ * projector of a vision model, or shards 2..N of a split GGUF. Carried on the
13733
+ * REF rather than looked up at install time, so what the operator approved in
13734
+ * the preview is exactly what the node downloads.
13735
+ */
13736
+ var ManagedModelExtraFileSchema = object({
13737
+ url: string(),
13738
+ filename: string(),
13739
+ sizeBytes: number(),
13740
+ sha256: string().optional()
13741
+ });
13730
13742
  var ManagedModelRefSchema = discriminatedUnion("kind", [
13731
13743
  object({
13732
13744
  kind: literal("catalog"),
@@ -13735,7 +13747,11 @@ var ManagedModelRefSchema = discriminatedUnion("kind", [
13735
13747
  object({
13736
13748
  kind: literal("url"),
13737
13749
  url: string(),
13738
- sha256: string().optional()
13750
+ sha256: string().optional(),
13751
+ /** Picker/status label; the file basename when absent. */
13752
+ label: string().optional(),
13753
+ sizeBytes: number().optional(),
13754
+ extraFiles: array(ManagedModelExtraFileSchema).optional()
13739
13755
  }),
13740
13756
  object({
13741
13757
  kind: literal("path"),
@@ -13796,11 +13812,39 @@ var ManagedRuntimeConfigSchema = object({
13796
13812
  "q4_1",
13797
13813
  "q4_0"
13798
13814
  ]).optional(),
13815
+ /**
13816
+ * Escape hatch for llama-server flags this schema does NOT model — `--jinja`
13817
+ * (which most vision chat templates need and some language-only models
13818
+ * dislike), `--cont-batching`, `--rope-scaling`, …
13819
+ *
13820
+ * It is NOT a second place to set the flags above. A token that collides
13821
+ * with a typed field is REJECTED at start, naming the field that owns it
13822
+ * (`assertNoOwnedFlags`), because two knobs writing the same argv is exactly
13823
+ * the "two switches that disagree" failure this repo has already shipped
13824
+ * twice (D62).
13825
+ */
13826
+ extraArgs: array(string()).default([]),
13799
13827
  /** Else lazy: first generate boots it. */
13800
13828
  autoStart: boolean().default(false),
13801
13829
  /** 0 = never; frees RAM after quiet periods. */
13802
13830
  idleStopMinutes: number().int().default(30)
13803
13831
  });
13832
+ /**
13833
+ * Where a multi-GB install currently is. A single 0..1 fraction cannot answer
13834
+ * "is it stuck?" for an install that is three files (shards + mmproj) followed
13835
+ * by a sha256 pass over 22 GB — during which the fraction sat at 1.0 and the
13836
+ * node looked hung. Phase + file + bytes is the smallest shape that does.
13837
+ */
13838
+ var LlmDownloadProgressSchema = object({
13839
+ phase: _enum(["downloading", "verifying"]),
13840
+ /** The artifact currently moving, e.g. `mmproj-F16.gguf`. */
13841
+ file: string(),
13842
+ fileIndex: number().int(),
13843
+ fileCount: number().int(),
13844
+ /** Across the WHOLE install, not the current file. */
13845
+ downloadedBytes: number(),
13846
+ totalBytes: number().optional()
13847
+ });
13804
13848
  var LlmRuntimeStatusSchema = object({
13805
13849
  /** Status is ALWAYS node-qualified. */
13806
13850
  nodeId: string(),
@@ -13817,6 +13861,8 @@ var LlmRuntimeStatusSchema = object({
13817
13861
  modelPath: string().optional(),
13818
13862
  modelId: string().optional(),
13819
13863
  downloadProgress: number().min(0).max(1).optional(),
13864
+ /** Detail behind `downloadProgress`; present for the same lifetime. */
13865
+ download: LlmDownloadProgressSchema.optional(),
13820
13866
  lastError: string().optional(),
13821
13867
  crashesInWindow: number(),
13822
13868
  /** Child RSS (sampled best-effort). */
@@ -13827,7 +13873,14 @@ var LlmNodeModelSchema = object({
13827
13873
  file: string(),
13828
13874
  sizeBytes: number(),
13829
13875
  catalogId: string().optional(),
13830
- installedAt: number().optional()
13876
+ installedAt: number().optional(),
13877
+ /**
13878
+ * Absolute path on the node. Present so a file that is on disk but matches
13879
+ * no catalog entry — a custom Hugging Face install, or a GGUF the operator
13880
+ * copied in by hand — is still SELECTABLE, as a `{kind:'path'}` ref. Without
13881
+ * it the picker could list such a file and do nothing with it.
13882
+ */
13883
+ path: string().optional()
13831
13884
  });
13832
13885
  var LlmRuntimeDiskUsageSchema = object({
13833
13886
  nodeId: string(),
@@ -13905,9 +13958,12 @@ var LlmProfileSchema = object({
13905
13958
  systemPrompt: string().optional(),
13906
13959
  /** Total generation bound — the only one a unary call has. */
13907
13960
  timeoutMs: number().int().positive().default(6e4),
13908
- /** Wait for response headers only. */
13961
+ /** The TCP handshake only — "is the port even open". NOT the wait for
13962
+ * response headers: on the LM Studio / llama-server wire those are written
13963
+ * once the model has finished loading, so they belong to the bound below. */
13909
13964
  connectTimeoutMs: number().int().positive().default(1e4),
13910
- /** Accepted, but no output yet — a cold GPU load lives here. */
13965
+ /** Accepted, but no output yet — response headers included, because a cold
13966
+ * GPU load is exactly what happens before them. */
13911
13967
  firstTokenTimeoutMs: number().int().positive().default(12e4),
13912
13968
  /** Output started then stopped. */
13913
13969
  idleTimeoutMs: number().int().positive().default(6e4),
@@ -13970,6 +14026,36 @@ var ManagedModelCatalogEntrySchema = object({
13970
14026
  /** Vision models: companion projector file. */
13971
14027
  mmprojUrl: string().optional()
13972
14028
  });
14029
+ /**
14030
+ * The outcome of turning one operator-typed Hugging Face reference into a
14031
+ * download plan. A RESULT, never a throw: "this repo has 24 quantizations and
14032
+ * I will not pick for you" is a normal answer the UI has to render, not an
14033
+ * exception.
14034
+ *
14035
+ * `candidates` is the whole reason the refusal is usable — every string in it
14036
+ * is a tag that resolves when pasted back as `<org>/<repo>:<TAG>`.
14037
+ */
14038
+ var HfModelResolutionSchema = discriminatedUnion("ok", [object({
14039
+ ok: literal(true),
14040
+ /** Ready to hand to `installModel` unchanged. */
14041
+ model: ManagedModelRefSchema,
14042
+ label: string(),
14043
+ repo: string(),
14044
+ quantization: string(),
14045
+ purpose: _enum(["text", "vision"]),
14046
+ totalBytes: number(),
14047
+ /** mmproj + shards, for the preview: an operator approving 23 GB should
14048
+ * see that 0.9 GB of it is a projector they did not name. */
14049
+ extraFilenames: array(string())
14050
+ }), object({
14051
+ ok: literal(false),
14052
+ code: string(),
14053
+ message: string(),
14054
+ candidates: array(string()).optional(),
14055
+ /** Set when the refusal was only the ceiling: re-calling with
14056
+ * `maxBytes: requiredBytes` is the operator's explicit override. */
14057
+ requiredBytes: number().optional()
14058
+ })]);
13973
14059
  var LlmRuntimeNodeSchema = object({
13974
14060
  nodeId: string(),
13975
14061
  reachable: boolean(),
@@ -14006,6 +14092,15 @@ method(LlmGenerateBaseInputSchema, LlmGenerateResultSchema, { kind: "mutation" }
14006
14092
  consumer: string().optional(),
14007
14093
  profileId: string().optional()
14008
14094
  }), array(LlmUsageRollupSchema)), method(object({}), array(ManagedModelCatalogEntrySchema)), method(object({}), array(LlmRuntimeNodeSchema)), method(object({ nodeId: string() }), array(LlmNodeModelSchema)), method(object({
14095
+ /** `https://huggingface.co/<org>/<repo>/resolve/main/<f>.gguf`,
14096
+ * `<org>/<repo>/<f>.gguf`, `<org>/<repo>` or `<org>/<repo>:<QUANT>`. */
14097
+ ref: string(),
14098
+ /** Explicit ceiling override, in bytes. Absent = the built-in ceiling. */
14099
+ maxBytes: number().positive().optional()
14100
+ }), HfModelResolutionSchema, {
14101
+ kind: "mutation",
14102
+ auth: "admin"
14103
+ }), method(object({
14009
14104
  nodeId: string(),
14010
14105
  model: ManagedModelRefSchema
14011
14106
  }), _void(), {
@@ -19633,6 +19728,17 @@ var maxSessionHoldMsField = {
19633
19728
  default: 12e4,
19634
19729
  step: 5e3
19635
19730
  };
19731
+ /**
19732
+ * Quiet period that closes an `audioMode: 'on-motion'` audio window. Floor of
19733
+ * 5s so a rearm can never degenerate into per-event stream churn; default 90s
19734
+ * comfortably outlives the gap between two PIR wakes on a battery camera.
19735
+ */
19736
+ var audioMotionWindowMsField = {
19737
+ min: 5e3,
19738
+ max: 6e5,
19739
+ default: 9e4,
19740
+ step: 5e3
19741
+ };
19636
19742
  var motionFpsField = {
19637
19743
  min: 1,
19638
19744
  max: 30,
@@ -19809,6 +19915,27 @@ var RunnerCameraConfigSchema = object({
19809
19915
  * resolved `CameraDetectionConfig`.
19810
19916
  */
19811
19917
  maxSessionHoldMs: number().min(maxSessionHoldMsField.min).max(maxSessionHoldMsField.max).optional(),
19918
+ /**
19919
+ * Orchestrator-side quiet period (ms) that closes an `audioMode:
19920
+ * 'on-motion'` audio window, measured from the LAST motion event.
19921
+ *
19922
+ * This exists because the falling edge cannot be relied on. Camera-native
19923
+ * providers emit motion as a RISING EDGE ONLY (Reolink's Baichuan push and
19924
+ * its email-push SMTP path both emit `detected: true` and never the
19925
+ * counterpart); only the frame-diff analyzer emits falls. So on an
19926
+ * onboard-only camera a window that closed only on `detected: false` never
19927
+ * closed at all, and `on-motion` silently behaved as `always-on` — on a
19928
+ * battery camera, the one failure mode the mode exists to prevent.
19929
+ *
19930
+ * Every motion event rearms this timer WITHOUT restarting the stream, so a
19931
+ * burst of re-fires costs nothing. A falling edge, when one does arrive,
19932
+ * still closes earlier via `motionCooldownMs` — whichever comes first wins.
19933
+ *
19934
+ * Not consumed by the runner: carried here so it shares the per-camera
19935
+ * device-settings surface with `motionCooldownMs`, exactly like
19936
+ * `maxSessionHoldMs`.
19937
+ */
19938
+ audioMotionWindowMs: number().min(audioMotionWindowMsField.min).max(audioMotionWindowMsField.max).optional(),
19812
19939
  motionFps: number().min(motionFpsField.min).max(motionFpsField.max).default(motionFpsField.default),
19813
19940
  detectionFps: number().min(detectionFpsField.min).max(detectionFpsField.max).default(detectionFpsField.default),
19814
19941
  motionStreamId: string(),
@@ -19904,7 +20031,7 @@ var RunnerCameraConfigSchema = object({
19904
20031
  */
19905
20032
  inferenceDevices: array(RunnerInferenceDeviceSchema).readonly().optional()
19906
20033
  });
19907
- motionFpsField.min, motionFpsField.max, motionFpsField.step, motionFpsField.default, detectionFpsField.min, detectionFpsField.max, detectionFpsField.step, detectionFpsField.default, motionCooldownMsField.min, motionCooldownMsField.max, motionCooldownMsField.step, motionCooldownMsField.default, maxSessionHoldMsField.min, maxSessionHoldMsField.max, maxSessionHoldMsField.step, maxSessionHoldMsField.default, occupancyRecheckSecField.min, occupancyRecheckSecField.max, occupancyRecheckSecField.step, occupancyRecheckSecField.default, occupancyRecheckFramesField.min, occupancyRecheckFramesField.max, occupancyRecheckFramesField.step, occupancyRecheckFramesField.default;
20034
+ motionFpsField.min, motionFpsField.max, motionFpsField.step, motionFpsField.default, detectionFpsField.min, detectionFpsField.max, detectionFpsField.step, detectionFpsField.default, motionCooldownMsField.min, motionCooldownMsField.max, motionCooldownMsField.step, motionCooldownMsField.default, maxSessionHoldMsField.min, maxSessionHoldMsField.max, maxSessionHoldMsField.step, maxSessionHoldMsField.default, audioMotionWindowMsField.min, audioMotionWindowMsField.max, audioMotionWindowMsField.step, audioMotionWindowMsField.default, occupancyRecheckSecField.min, occupancyRecheckSecField.max, occupancyRecheckSecField.step, occupancyRecheckSecField.default, occupancyRecheckFramesField.min, occupancyRecheckFramesField.max, occupancyRecheckFramesField.step, occupancyRecheckFramesField.default;
19908
20035
  /**
19909
20036
  * Runtime load summary returned by `getLocalLoad`. Used by the orchestrator's
19910
20037
  * load-balancing levels (L2 capacity-based, L3 hardware-aware) to decide
@@ -26699,6 +26826,33 @@ var recordingExportCapability = {
26699
26826
  * as `unknown`, never guessed. A day reference scored against an IR frame
26700
26827
  * collapses the cosine and would latch a false alarm every single night. */
26701
26828
  var SceneConditionSchema = string();
26829
+ /**
26830
+ * What a scene does when the CURRENT light has no reference of its own.
26831
+ *
26832
+ * The lighting variants are not equally likely to exist. Almost every operator
26833
+ * captures daylight and then never stands outside at 22:00 to capture IR, and a
26834
+ * scene that is only ever going to be asked about a daytime question ("is the
26835
+ * bin still on the kerb at 08:00") does not need a night reference at all. The
26836
+ * night half must therefore be OPTIONAL, and optional means the scene keeps
26837
+ * working without it rather than degrading into a permanent complaint.
26838
+ *
26839
+ * - `skip` (default) — the check in that light is not made. Not a verdict, not
26840
+ * an alarm, not even an `unknown`: the live state simply stays whatever the
26841
+ * last covered light left it at, the latch is untouched, and the hysteresis
26842
+ * run is neither spent nor cleared. The scene resumes by itself at first
26843
+ * light. This is the only behaviour under which "I never captured IR" is a
26844
+ * configuration choice instead of a nightly fault.
26845
+ * - `judge-anyway` — score against the OTHER conditions' references. Available
26846
+ * for cameras whose IR frame is close enough to daylight (a floodlit
26847
+ * driveway, an always-white-light doorbell), and wrong for everything else:
26848
+ * cross-condition cosines are not comparable, so a day reference against a
26849
+ * true IR frame collapses and the scene reports a theft at 21:40.
26850
+ *
26851
+ * Never applies when the scene has NO comparable reference at all — that is
26852
+ * "not armed yet", it is reported as `no-reference-for-condition`, and silence
26853
+ * there would hide a scene the operator never finished setting up.
26854
+ */
26855
+ var SceneUncoveredPolicySchema = _enum(["skip", "judge-anyway"]);
26702
26856
  /** `matched` = the baseline is what we see; `diverged` = it demonstrably is not;
26703
26857
  * `unknown` = we cannot judge (no reference for this condition, encoder model
26704
26858
  * changed, view shifted, no snapshot). `unknown` is a real value, not a null,
@@ -26754,6 +26908,9 @@ var SceneCheckSchema = discriminatedUnion("mode", [object({
26754
26908
  hysteresisCount: number().int().positive()
26755
26909
  })]);
26756
26910
  var SCENE_DEFAULT_ANCHOR_THRESHOLD = .85;
26911
+ /** Night is OPTIONAL. A scene with only a daylight reference sits the IR hours
26912
+ * out in silence rather than reporting a fault every night. */
26913
+ var SCENE_DEFAULT_UNCOVERED_POLICY = "skip";
26757
26914
  /**
26758
26915
  * Vision-model adjudication of a candidate flip. Field names deliberately
26759
26916
  * mirror `NcConfirmSchema` so an operator meets one vocabulary, not two.
@@ -26820,6 +26977,21 @@ var SceneMonitorSchema = object({
26820
26977
  * automation can react to the bin coming back without the operator's own
26821
26978
  * alarm silently clearing itself. */
26822
26979
  autoRestore: boolean().default(false),
26980
+ /** What to do when the current light has no reference of its own. See
26981
+ * {@link SceneUncoveredPolicySchema} — the default makes night OPTIONAL. */
26982
+ onUncoveredCondition: SceneUncoveredPolicySchema.default(SCENE_DEFAULT_UNCOVERED_POLICY),
26983
+ /**
26984
+ * The light whose checks are currently being SAT OUT under
26985
+ * `onUncoveredCondition: 'skip'` — `null` when the scene is checking normally.
26986
+ *
26987
+ * Engine-reported and advisory only: it moves no verdict, no latch and no
26988
+ * hysteresis. It exists so the card can say *"night (IR) — checks paused,
26989
+ * nothing captured in this light"* in the same calm voice as the coverage
26990
+ * line, because the alternative is a scene that silently stops answering
26991
+ * after sunset with nothing anywhere saying why. A skipped check must never
26992
+ * read as a broken one.
26993
+ */
26994
+ suspendedCondition: SceneConditionSchema.nullable().default(null),
26823
26995
  /** Named cause when `verdict === 'unknown'`. */
26824
26996
  unavailable: SceneUnavailableSchema.nullable(),
26825
26997
  /** Conditions that have at least one comparable reference — the coverage line
@@ -26863,6 +27035,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), SceneMonitorStatusSche
26863
27035
  minObservationSpacingSec: number().int().min(0).max(3600).optional(),
26864
27036
  anchorThreshold: number().min(0).max(1).optional(),
26865
27037
  autoRestore: boolean().optional(),
27038
+ onUncoveredCondition: SceneUncoveredPolicySchema.optional(),
26866
27039
  /** `null` clears the vision-model adjudicator. */
26867
27040
  confirm: SceneConfirmSchema.nullable().optional()
26868
27041
  })
@@ -30095,6 +30268,12 @@ Object.freeze({
30095
30268
  addonId: null,
30096
30269
  access: "view"
30097
30270
  },
30271
+ "llm.resolveModelRef": {
30272
+ capName: "llm",
30273
+ capScope: "system",
30274
+ addonId: null,
30275
+ access: "create"
30276
+ },
30098
30277
  "llm.setDefault": {
30099
30278
  capName: "llm",
30100
30279
  capScope: "system",