@camstack/addon-pipeline 1.2.79 → 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.
- package/dist/{addon-utils-BZQxAJ1G.js → addon-utils-C4Cge0S0.js} +1 -1
- package/dist/audio-analyzer/index.js +2 -2
- package/dist/audio-analyzer/index.mjs +1 -1
- package/dist/detection-pipeline/index.js +4 -4
- package/dist/detection-pipeline/index.mjs +2 -2
- package/dist/{dist-BfTf6doa.mjs → dist-Bf1SE1Ew.mjs} +133 -3
- package/dist/{dist-BUIpqu3E.js → dist-ZSiUDGzf.js} +133 -3
- package/dist/{event-loop-stall-monitor-CmrHj0i9.mjs → event-loop-stall-monitor-CjWfos2b.mjs} +1 -1
- package/dist/{event-loop-stall-monitor-CGLQP0by.js → event-loop-stall-monitor-VcDGoua3.js} +1 -1
- package/dist/{lazy-sharp-BZVhL9Lw.js → lazy-sharp-CC4WNiKY.js} +1 -1
- package/dist/motion-wasm/index.js +2 -2
- package/dist/motion-wasm/index.mjs +1 -1
- package/dist/pipeline-runner/index.js +4 -4
- package/dist/pipeline-runner/index.mjs +3 -3
- package/dist/recorder/index.js +62 -5
- package/dist/recorder/index.mjs +61 -4
- package/dist/session-decode/decode-worker-child.js +2 -2
- package/dist/session-decode/decode-worker-child.mjs +1 -1
- package/dist/stream-broker/_stub.js +2 -2
- package/dist/stream-broker/{_virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-BohtrVou.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_stream_broker_widgets-B1oVjQLS.mjs} +2 -2
- 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
- package/dist/stream-broker/{_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-Dxr14lIu.mjs → _virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_ui_mf_2_library__loadShare__.js-DEps-9qh.mjs} +1 -1
- package/dist/stream-broker/{hostInit-pDANS0x0.mjs → hostInit-D_m-NYyr.mjs} +2 -2
- package/dist/stream-broker/index.js +1 -1
- package/dist/stream-broker/index.mjs +1 -1
- package/dist/stream-broker/remoteEntry.js +1 -1
- package/dist/{worker-protocol-BaLcYcOo.js → worker-protocol-KDfFzKgT.js} +1 -1
- package/dist/{worker-protocol-BdOv9Ujl.mjs → worker-protocol-p66oO1xL.mjs} +1 -1
- package/package.json +1 -1
- package/dist/stream-broker/_virtual_mf___mfe_internal__addon_stream_broker_widgets__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-y8ehJPoY.mjs +0 -26
|
@@ -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-
|
|
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-
|
|
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-
|
|
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-
|
|
6
|
-
const require_event_loop_stall_monitor = require("../event-loop-stall-monitor-
|
|
7
|
-
const require_lazy_sharp = require("../lazy-sharp-
|
|
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-
|
|
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-
|
|
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-
|
|
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(),
|
|
@@ -13950,6 +14003,36 @@ var ManagedModelCatalogEntrySchema = object({
|
|
|
13950
14003
|
/** Vision models: companion projector file. */
|
|
13951
14004
|
mmprojUrl: string().optional()
|
|
13952
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
|
+
})]);
|
|
13953
14036
|
var LlmRuntimeNodeSchema = object({
|
|
13954
14037
|
nodeId: string(),
|
|
13955
14038
|
reachable: boolean(),
|
|
@@ -13986,6 +14069,15 @@ method(LlmGenerateBaseInputSchema, LlmGenerateResultSchema, { kind: "mutation" }
|
|
|
13986
14069
|
consumer: string().optional(),
|
|
13987
14070
|
profileId: string().optional()
|
|
13988
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({
|
|
13989
14081
|
nodeId: string(),
|
|
13990
14082
|
model: ManagedModelRefSchema
|
|
13991
14083
|
}), _void(), {
|
|
@@ -19613,6 +19705,17 @@ var maxSessionHoldMsField = {
|
|
|
19613
19705
|
default: 12e4,
|
|
19614
19706
|
step: 5e3
|
|
19615
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
|
+
};
|
|
19616
19719
|
var motionFpsField = {
|
|
19617
19720
|
min: 1,
|
|
19618
19721
|
max: 30,
|
|
@@ -19789,6 +19892,27 @@ var RunnerCameraConfigSchema = object({
|
|
|
19789
19892
|
* resolved `CameraDetectionConfig`.
|
|
19790
19893
|
*/
|
|
19791
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(),
|
|
19792
19916
|
motionFps: number().min(motionFpsField.min).max(motionFpsField.max).default(motionFpsField.default),
|
|
19793
19917
|
detectionFps: number().min(detectionFpsField.min).max(detectionFpsField.max).default(detectionFpsField.default),
|
|
19794
19918
|
motionStreamId: string(),
|
|
@@ -19884,7 +20008,7 @@ var RunnerCameraConfigSchema = object({
|
|
|
19884
20008
|
*/
|
|
19885
20009
|
inferenceDevices: array(RunnerInferenceDeviceSchema).readonly().optional()
|
|
19886
20010
|
});
|
|
19887
|
-
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;
|
|
19888
20012
|
/**
|
|
19889
20013
|
* Runtime load summary returned by `getLocalLoad`. Used by the orchestrator's
|
|
19890
20014
|
* load-balancing levels (L2 capacity-based, L3 hardware-aware) to decide
|
|
@@ -30121,6 +30245,12 @@ Object.freeze({
|
|
|
30121
30245
|
addonId: null,
|
|
30122
30246
|
access: "view"
|
|
30123
30247
|
},
|
|
30248
|
+
"llm.resolveModelRef": {
|
|
30249
|
+
capName: "llm",
|
|
30250
|
+
capScope: "system",
|
|
30251
|
+
addonId: null,
|
|
30252
|
+
access: "create"
|
|
30253
|
+
},
|
|
30124
30254
|
"llm.setDefault": {
|
|
30125
30255
|
capName: "llm",
|
|
30126
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(),
|
|
@@ -13973,6 +14026,36 @@ var ManagedModelCatalogEntrySchema = object({
|
|
|
13973
14026
|
/** Vision models: companion projector file. */
|
|
13974
14027
|
mmprojUrl: string().optional()
|
|
13975
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
|
+
})]);
|
|
13976
14059
|
var LlmRuntimeNodeSchema = object({
|
|
13977
14060
|
nodeId: string(),
|
|
13978
14061
|
reachable: boolean(),
|
|
@@ -14009,6 +14092,15 @@ method(LlmGenerateBaseInputSchema, LlmGenerateResultSchema, { kind: "mutation" }
|
|
|
14009
14092
|
consumer: string().optional(),
|
|
14010
14093
|
profileId: string().optional()
|
|
14011
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({
|
|
14012
14104
|
nodeId: string(),
|
|
14013
14105
|
model: ManagedModelRefSchema
|
|
14014
14106
|
}), _void(), {
|
|
@@ -19636,6 +19728,17 @@ var maxSessionHoldMsField = {
|
|
|
19636
19728
|
default: 12e4,
|
|
19637
19729
|
step: 5e3
|
|
19638
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
|
+
};
|
|
19639
19742
|
var motionFpsField = {
|
|
19640
19743
|
min: 1,
|
|
19641
19744
|
max: 30,
|
|
@@ -19812,6 +19915,27 @@ var RunnerCameraConfigSchema = object({
|
|
|
19812
19915
|
* resolved `CameraDetectionConfig`.
|
|
19813
19916
|
*/
|
|
19814
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(),
|
|
19815
19939
|
motionFps: number().min(motionFpsField.min).max(motionFpsField.max).default(motionFpsField.default),
|
|
19816
19940
|
detectionFps: number().min(detectionFpsField.min).max(detectionFpsField.max).default(detectionFpsField.default),
|
|
19817
19941
|
motionStreamId: string(),
|
|
@@ -19907,7 +20031,7 @@ var RunnerCameraConfigSchema = object({
|
|
|
19907
20031
|
*/
|
|
19908
20032
|
inferenceDevices: array(RunnerInferenceDeviceSchema).readonly().optional()
|
|
19909
20033
|
});
|
|
19910
|
-
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;
|
|
19911
20035
|
/**
|
|
19912
20036
|
* Runtime load summary returned by `getLocalLoad`. Used by the orchestrator's
|
|
19913
20037
|
* load-balancing levels (L2 capacity-based, L3 hardware-aware) to decide
|
|
@@ -30144,6 +30268,12 @@ Object.freeze({
|
|
|
30144
30268
|
addonId: null,
|
|
30145
30269
|
access: "view"
|
|
30146
30270
|
},
|
|
30271
|
+
"llm.resolveModelRef": {
|
|
30272
|
+
capName: "llm",
|
|
30273
|
+
capScope: "system",
|
|
30274
|
+
addonId: null,
|
|
30275
|
+
access: "create"
|
|
30276
|
+
},
|
|
30147
30277
|
"llm.setDefault": {
|
|
30148
30278
|
capName: "llm",
|
|
30149
30279
|
capScope: "system",
|
package/dist/{event-loop-stall-monitor-CmrHj0i9.mjs → event-loop-stall-monitor-CjWfos2b.mjs}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as COCO_TO_MACRO, i as COCO_80_LABELS, r as AUDIO_MACRO_LABELS, z as hfModelUrl } from "./dist-
|
|
1
|
+
import { a as COCO_TO_MACRO, i as COCO_80_LABELS, r as AUDIO_MACRO_LABELS, z as hfModelUrl } from "./dist-Bf1SE1Ew.mjs";
|
|
2
2
|
import { PerformanceObserver } from "node:perf_hooks";
|
|
3
3
|
//#region src/detection-pipeline/registry/model-catalogs.ts
|
|
4
4
|
var HF_REPO = "camstack/camstack-models";
|
|
@@ -2,8 +2,8 @@ Object.defineProperties(exports, {
|
|
|
2
2
|
__esModule: { value: true },
|
|
3
3
|
[Symbol.toStringTag]: { value: "Module" }
|
|
4
4
|
});
|
|
5
|
-
const require_dist = require("../dist-
|
|
6
|
-
const require_lazy_sharp = require("../lazy-sharp-
|
|
5
|
+
const require_dist = require("../dist-ZSiUDGzf.js");
|
|
6
|
+
const require_lazy_sharp = require("../lazy-sharp-CC4WNiKY.js");
|
|
7
7
|
let node_path = require("node:path");
|
|
8
8
|
let node_fs = require("node:fs");
|
|
9
9
|
//#region src/motion-wasm/wasm-motion-detector.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { H as motionDetectionCapability, R as evaluateZoneRules, ft as hydrateSchema, st as BaseAddon, ut as DeviceType } from "../dist-
|
|
1
|
+
import { H as motionDetectionCapability, R as evaluateZoneRules, ft as hydrateSchema, st as BaseAddon, ut as DeviceType } from "../dist-Bf1SE1Ew.mjs";
|
|
2
2
|
import { t as getSharp } from "../lazy-sharp-6oymT_yf.mjs";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { readFileSync } from "node:fs";
|
|
@@ -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-
|
|
6
|
-
const require_event_loop_stall_monitor = require("../event-loop-stall-monitor-
|
|
7
|
-
const require_worker_protocol = require("../worker-protocol-
|
|
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_worker_protocol = require("../worker-protocol-KDfFzKgT.js");
|
|
8
8
|
const require_hub_hostname = require("../hub-hostname-DAJXlOgV.js");
|
|
9
|
-
const require_lazy_sharp = require("../lazy-sharp-
|
|
9
|
+
const require_lazy_sharp = require("../lazy-sharp-CC4WNiKY.js");
|
|
10
10
|
const require_remote_restream = require("../remote-restream-BYbAsgUf.js");
|
|
11
11
|
let sharp = require("sharp");
|
|
12
12
|
sharp = require_dist.__toESM(sharp);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { At as string, Ct as boolean, Dt as number, Et as literal, K as pipelineRunnerCapability, M as deriveDetailCropRect, Mt as EventCategory, Ot as object, St as array, Tt as lazy, U as pickDetailCropConvention, W as pickNativeLeaseOverride, dt as createEvent, gt as nodePin, j as defineCustomActions, k as customAction, s as DEFAULT_DETAIL_CROP_CONVENTION, st as BaseAddon, tt as errMsg, u as DEVICE_BACKEND_TO_FORMAT, xt as _enum } from "../dist-
|
|
2
|
-
import { c as getStepDefinition, t as attributeStall } from "../event-loop-stall-monitor-
|
|
3
|
-
import { a as nativeLeaseSettingEnv, t as isWorkerReply } from "../worker-protocol-
|
|
1
|
+
import { At as string, Ct as boolean, Dt as number, Et as literal, K as pipelineRunnerCapability, M as deriveDetailCropRect, Mt as EventCategory, Ot as object, St as array, Tt as lazy, U as pickDetailCropConvention, W as pickNativeLeaseOverride, dt as createEvent, gt as nodePin, j as defineCustomActions, k as customAction, s as DEFAULT_DETAIL_CROP_CONVENTION, st as BaseAddon, tt as errMsg, u as DEVICE_BACKEND_TO_FORMAT, xt as _enum } from "../dist-Bf1SE1Ew.mjs";
|
|
2
|
+
import { c as getStepDefinition, t as attributeStall } from "../event-loop-stall-monitor-CjWfos2b.mjs";
|
|
3
|
+
import { a as nativeLeaseSettingEnv, t as isWorkerReply } from "../worker-protocol-p66oO1xL.mjs";
|
|
4
4
|
import { t as resolveHubHostname } from "../hub-hostname-cCknRYKj.mjs";
|
|
5
5
|
import { t as getSharp } from "../lazy-sharp-6oymT_yf.mjs";
|
|
6
6
|
import { i as withDetectionIntent, n as profileForStreamId, t as isRemoteRestream } from "../remote-restream-Ci7RXNGb.mjs";
|
package/dist/recorder/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
const require_dist = require("../dist-
|
|
1
|
+
const require_dist = require("../dist-ZSiUDGzf.js");
|
|
2
2
|
const require_hub_hostname = require("../hub-hostname-DAJXlOgV.js");
|
|
3
|
-
const require_addon_utils = require("../addon-utils-
|
|
3
|
+
const require_addon_utils = require("../addon-utils-C4Cge0S0.js");
|
|
4
4
|
let node_crypto = require("node:crypto");
|
|
5
5
|
let node_child_process = require("node:child_process");
|
|
6
6
|
let node_path = require("node:path");
|
|
@@ -3764,6 +3764,7 @@ async function buildPlaybackManifest(deps, codecCache, deviceId, fromMs, toMs) {
|
|
|
3764
3764
|
if (base === null) return noPlayback(deviceId);
|
|
3765
3765
|
const readPrefix = deps.readFilePrefix ?? readPrefixFromDisk;
|
|
3766
3766
|
const playbackDir = playbackDirFor(deps.dataDir, deviceId);
|
|
3767
|
+
if (deps.index.hydrationOf(deviceId, fromMs, toMs) !== "hydrated") await deps.hydrateWindow?.(deviceId, fromMs, toMs);
|
|
3767
3768
|
const profiles = [...new Set(deps.index.segments(deviceId).map((s) => s.profile))];
|
|
3768
3769
|
const variants = [];
|
|
3769
3770
|
for (const profile of profiles) {
|
|
@@ -5016,6 +5017,61 @@ async function hydrateDeviceFromStorage(_api, index, deviceId, locations, logger
|
|
|
5016
5017
|
}
|
|
5017
5018
|
/** Entries classified between yields in {@link hydrateDeviceFromStorage}. */
|
|
5018
5019
|
var HYDRATE_CHUNK = 2e4;
|
|
5020
|
+
/**
|
|
5021
|
+
* Device walks in flight at once in {@link hydrateDevicesFromStorage}.
|
|
5022
|
+
*
|
|
5023
|
+
* The walk is `readdir` latency on a network/FUSE share, not CPU: measured on
|
|
5024
|
+
* the live hub, 24 cold hour directories cost 31 s one at a time and 16.7 s
|
|
5025
|
+
* eight at a time. Four is the conservative point on that curve — enough to
|
|
5026
|
+
* hide most of the latency, few enough that the boot walk never becomes the
|
|
5027
|
+
* reason a live SegmentWriter waits. libuv's default threadpool is 4, so a
|
|
5028
|
+
* higher number here mostly queues.
|
|
5029
|
+
*/
|
|
5030
|
+
var HYDRATE_DEVICE_CONCURRENCY = 4;
|
|
5031
|
+
/**
|
|
5032
|
+
* Walk the archive for a whole fleet: bounded-parallel, and each camera becomes
|
|
5033
|
+
* authoritative the moment ITS OWN walk lands (D167).
|
|
5034
|
+
*
|
|
5035
|
+
* Two things this fixes, both measured on the live hub on 2026-08-15:
|
|
5036
|
+
*
|
|
5037
|
+
* - The caller was `for (const id of ids) await hydrateDeviceFromStorage(...)`,
|
|
5038
|
+
* so seven cameras' 357 s of `readdir` WAS the 362 s wall clock. Nothing in
|
|
5039
|
+
* the walk contends for CPU — it is share latency — so overlapping is free.
|
|
5040
|
+
* - `markHydratedAll` ran in a SECOND loop after every device. A camera whose
|
|
5041
|
+
* walk finished at minute 1 still reported `hydrationOf → 'unknown'` until
|
|
5042
|
+
* minute 6, and every read of it in that window paid for an on-demand walk
|
|
5043
|
+
* over rows already in the index, competing with the walk still running for
|
|
5044
|
+
* the others.
|
|
5045
|
+
*
|
|
5046
|
+
* A device whose walk throws is NOT marked: `unknown` is the honest answer, and
|
|
5047
|
+
* it is what keeps the read path walking that window on demand.
|
|
5048
|
+
*/
|
|
5049
|
+
async function hydrateDevicesFromStorage(api, index, deviceIds, locations, logger, options = {}) {
|
|
5050
|
+
const concurrency = Math.max(1, options.concurrency ?? HYDRATE_DEVICE_CONCURRENCY);
|
|
5051
|
+
const queue = [...deviceIds];
|
|
5052
|
+
const walkOptions = {
|
|
5053
|
+
...options.yieldBetween ? { yieldBetween: options.yieldBetween } : {},
|
|
5054
|
+
...options.chunkSize !== void 0 ? { chunkSize: options.chunkSize } : {}
|
|
5055
|
+
};
|
|
5056
|
+
const lane = async () => {
|
|
5057
|
+
for (;;) {
|
|
5058
|
+
const deviceId = queue.shift();
|
|
5059
|
+
if (deviceId === void 0) return;
|
|
5060
|
+
try {
|
|
5061
|
+
options.onDeviceStarted?.(deviceId);
|
|
5062
|
+
await hydrateDeviceFromStorage(api, index, deviceId, locations, logger, walkOptions);
|
|
5063
|
+
index.markHydratedAll(deviceId);
|
|
5064
|
+
options.onDeviceHydrated?.(deviceId);
|
|
5065
|
+
} catch (err) {
|
|
5066
|
+
logger.warn("recorder: device hydrate failed — window stays unknown, reads will walk it", {
|
|
5067
|
+
tags: { deviceId },
|
|
5068
|
+
meta: { error: require_dist.errMsg(err) }
|
|
5069
|
+
});
|
|
5070
|
+
}
|
|
5071
|
+
}
|
|
5072
|
+
};
|
|
5073
|
+
await Promise.all(Array.from({ length: Math.min(concurrency, queue.length) }, lane));
|
|
5074
|
+
}
|
|
5019
5075
|
var macrotask$1 = () => new Promise((resolve) => {
|
|
5020
5076
|
setImmediate(resolve);
|
|
5021
5077
|
});
|
|
@@ -8108,11 +8164,12 @@ var RecorderV2Addon = class extends require_dist.BaseAddon {
|
|
|
8108
8164
|
return;
|
|
8109
8165
|
}
|
|
8110
8166
|
this.warmToday([...configs.keys()]);
|
|
8111
|
-
|
|
8112
|
-
|
|
8167
|
+
const hydrateStartedMs = Date.now();
|
|
8168
|
+
await hydrateDevicesFromStorage(this.ctx.api, this.index, [...configs.keys()], this.resolvedLocations, this.ctx.logger);
|
|
8113
8169
|
this.ctx.logger.info("recorder: hydrated index from storage", { meta: {
|
|
8114
8170
|
deviceCount: configs.size,
|
|
8115
|
-
locationCount: this.resolvedLocations.length
|
|
8171
|
+
locationCount: this.resolvedLocations.length,
|
|
8172
|
+
ms: Date.now() - hydrateStartedMs
|
|
8116
8173
|
} });
|
|
8117
8174
|
const loggedDomains = /* @__PURE__ */ new Set();
|
|
8118
8175
|
for (const loc of this.resolvedLocations) {
|