@camstack/types 1.2.75 → 1.2.77
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.d.ts +19 -18
- package/dist/addon.js +59 -56
- package/dist/addon.mjs +59 -57
- package/dist/capabilities/alerts.cap.d.ts +5 -5
- package/dist/capabilities/battery.cap.d.ts +8 -4
- package/dist/capabilities/custom-model-registry.cap.d.ts +4 -4
- package/dist/capabilities/decoder.cap.d.ts +2 -2
- package/dist/capabilities/face-gallery.cap.d.ts +1 -1
- package/dist/capabilities/index.d.ts +3 -3
- package/dist/capabilities/lawn-mower-control.cap.d.ts +4 -4
- package/dist/capabilities/llm-runtime.cap.d.ts +121 -3
- package/dist/capabilities/llm.cap.d.ts +189 -4
- package/dist/capabilities/metrics-provider.cap.d.ts +2 -2
- package/dist/capabilities/model-convert.cap.d.ts +6 -6
- package/dist/capabilities/model-distributor.cap.d.ts +4 -4
- package/dist/capabilities/notification-output.cap.d.ts +9 -9
- package/dist/capabilities/notification-rules.cap.d.ts +11 -11
- package/dist/capabilities/oauth-integration.cap.d.ts +2 -2
- package/dist/capabilities/osd-manager.cap.d.ts +6 -6
- package/dist/capabilities/pipeline-analytics.cap.d.ts +39 -39
- package/dist/capabilities/pipeline-executor.cap.d.ts +7 -7
- package/dist/capabilities/pipeline-orchestrator.cap.d.ts +6 -6
- package/dist/capabilities/pipeline-runner.cap.d.ts +2 -0
- package/dist/capabilities/platform-probe.cap.d.ts +2 -2
- package/dist/capabilities/recording.cap.d.ts +3 -3
- package/dist/capabilities/sso-bridge.cap.d.ts +3 -3
- package/dist/capabilities/stream-broker.cap.d.ts +6 -6
- package/dist/capabilities/stream-catalog.cap.d.ts +93 -0
- package/dist/capabilities/user-management.cap.d.ts +20 -20
- package/dist/device/base-device-provider.d.ts +9 -0
- package/dist/device/battery-presence.d.ts +84 -0
- package/dist/encode-profile.d.ts +2 -2
- package/dist/generated/addon-api.d.ts +15 -8
- package/dist/generated/device-local-state.d.ts +3 -0
- package/dist/generated/device-proxy.d.ts +1 -0
- package/dist/generated/method-access-map.d.ts +1 -1
- package/dist/generated/runtime-state-durability.d.ts +1 -1
- package/dist/generated/system-proxy.d.ts +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +309 -9
- package/dist/index.mjs +303 -10
- package/dist/interfaces/recording-config.d.ts +2 -2
- package/dist/interfaces/stream-broker.d.ts +9 -1
- package/dist/{sleep-B-mRsuDp.js → sleep-CoL-9qhR.js} +43 -0
- package/dist/{sleep-CQayd2Su.mjs → sleep-DlC2kJYf.mjs} +38 -1
- package/dist/types/models.d.ts +7 -7
- package/dist/util/boot-recovery-backoff.d.ts +26 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_event_category = require("./event-category-D3gG7oil.js");
|
|
3
|
-
const require_sleep = require("./sleep-
|
|
3
|
+
const require_sleep = require("./sleep-CoL-9qhR.js");
|
|
4
4
|
const require_canonical_hash = require("./canonical-hash-DNV8S5ET.js");
|
|
5
5
|
const require_enums = require("./enums.js");
|
|
6
6
|
const require_err_msg = require("./err-msg-COpsHMw2.js");
|
|
@@ -9517,6 +9517,18 @@ var LlmGenerateBaseInputSchema = zod.z.object({
|
|
|
9517
9517
|
* Resource ceiling = llama-server flags + idleStopMinutes ONLY (no RSS
|
|
9518
9518
|
* watchdog — operator decision #3).
|
|
9519
9519
|
*/
|
|
9520
|
+
/**
|
|
9521
|
+
* A companion artifact that MUST land beside the main GGUF: the `mmproj`
|
|
9522
|
+
* projector of a vision model, or shards 2..N of a split GGUF. Carried on the
|
|
9523
|
+
* REF rather than looked up at install time, so what the operator approved in
|
|
9524
|
+
* the preview is exactly what the node downloads.
|
|
9525
|
+
*/
|
|
9526
|
+
var ManagedModelExtraFileSchema = zod.z.object({
|
|
9527
|
+
url: zod.z.string(),
|
|
9528
|
+
filename: zod.z.string(),
|
|
9529
|
+
sizeBytes: zod.z.number(),
|
|
9530
|
+
sha256: zod.z.string().optional()
|
|
9531
|
+
});
|
|
9520
9532
|
var ManagedModelRefSchema = zod.z.discriminatedUnion("kind", [
|
|
9521
9533
|
zod.z.object({
|
|
9522
9534
|
kind: zod.z.literal("catalog"),
|
|
@@ -9525,7 +9537,11 @@ var ManagedModelRefSchema = zod.z.discriminatedUnion("kind", [
|
|
|
9525
9537
|
zod.z.object({
|
|
9526
9538
|
kind: zod.z.literal("url"),
|
|
9527
9539
|
url: zod.z.string(),
|
|
9528
|
-
sha256: zod.z.string().optional()
|
|
9540
|
+
sha256: zod.z.string().optional(),
|
|
9541
|
+
/** Picker/status label; the file basename when absent. */
|
|
9542
|
+
label: zod.z.string().optional(),
|
|
9543
|
+
sizeBytes: zod.z.number().optional(),
|
|
9544
|
+
extraFiles: zod.z.array(ManagedModelExtraFileSchema).optional()
|
|
9529
9545
|
}),
|
|
9530
9546
|
zod.z.object({
|
|
9531
9547
|
kind: zod.z.literal("path"),
|
|
@@ -9586,11 +9602,39 @@ var ManagedRuntimeConfigSchema = zod.z.object({
|
|
|
9586
9602
|
"q4_1",
|
|
9587
9603
|
"q4_0"
|
|
9588
9604
|
]).optional(),
|
|
9605
|
+
/**
|
|
9606
|
+
* Escape hatch for llama-server flags this schema does NOT model — `--jinja`
|
|
9607
|
+
* (which most vision chat templates need and some language-only models
|
|
9608
|
+
* dislike), `--cont-batching`, `--rope-scaling`, …
|
|
9609
|
+
*
|
|
9610
|
+
* It is NOT a second place to set the flags above. A token that collides
|
|
9611
|
+
* with a typed field is REJECTED at start, naming the field that owns it
|
|
9612
|
+
* (`assertNoOwnedFlags`), because two knobs writing the same argv is exactly
|
|
9613
|
+
* the "two switches that disagree" failure this repo has already shipped
|
|
9614
|
+
* twice (D62).
|
|
9615
|
+
*/
|
|
9616
|
+
extraArgs: zod.z.array(zod.z.string()).default([]),
|
|
9589
9617
|
/** Else lazy: first generate boots it. */
|
|
9590
9618
|
autoStart: zod.z.boolean().default(false),
|
|
9591
9619
|
/** 0 = never; frees RAM after quiet periods. */
|
|
9592
9620
|
idleStopMinutes: zod.z.number().int().default(30)
|
|
9593
9621
|
});
|
|
9622
|
+
/**
|
|
9623
|
+
* Where a multi-GB install currently is. A single 0..1 fraction cannot answer
|
|
9624
|
+
* "is it stuck?" for an install that is three files (shards + mmproj) followed
|
|
9625
|
+
* by a sha256 pass over 22 GB — during which the fraction sat at 1.0 and the
|
|
9626
|
+
* node looked hung. Phase + file + bytes is the smallest shape that does.
|
|
9627
|
+
*/
|
|
9628
|
+
var LlmDownloadProgressSchema = zod.z.object({
|
|
9629
|
+
phase: zod.z.enum(["downloading", "verifying"]),
|
|
9630
|
+
/** The artifact currently moving, e.g. `mmproj-F16.gguf`. */
|
|
9631
|
+
file: zod.z.string(),
|
|
9632
|
+
fileIndex: zod.z.number().int(),
|
|
9633
|
+
fileCount: zod.z.number().int(),
|
|
9634
|
+
/** Across the WHOLE install, not the current file. */
|
|
9635
|
+
downloadedBytes: zod.z.number(),
|
|
9636
|
+
totalBytes: zod.z.number().optional()
|
|
9637
|
+
});
|
|
9594
9638
|
var LlmRuntimeStatusSchema = zod.z.object({
|
|
9595
9639
|
/** Status is ALWAYS node-qualified. */
|
|
9596
9640
|
nodeId: zod.z.string(),
|
|
@@ -9607,6 +9651,8 @@ var LlmRuntimeStatusSchema = zod.z.object({
|
|
|
9607
9651
|
modelPath: zod.z.string().optional(),
|
|
9608
9652
|
modelId: zod.z.string().optional(),
|
|
9609
9653
|
downloadProgress: zod.z.number().min(0).max(1).optional(),
|
|
9654
|
+
/** Detail behind `downloadProgress`; present for the same lifetime. */
|
|
9655
|
+
download: LlmDownloadProgressSchema.optional(),
|
|
9610
9656
|
lastError: zod.z.string().optional(),
|
|
9611
9657
|
crashesInWindow: zod.z.number(),
|
|
9612
9658
|
/** Child RSS (sampled best-effort). */
|
|
@@ -9617,7 +9663,14 @@ var LlmNodeModelSchema = zod.z.object({
|
|
|
9617
9663
|
file: zod.z.string(),
|
|
9618
9664
|
sizeBytes: zod.z.number(),
|
|
9619
9665
|
catalogId: zod.z.string().optional(),
|
|
9620
|
-
installedAt: zod.z.number().optional()
|
|
9666
|
+
installedAt: zod.z.number().optional(),
|
|
9667
|
+
/**
|
|
9668
|
+
* Absolute path on the node. Present so a file that is on disk but matches
|
|
9669
|
+
* no catalog entry — a custom Hugging Face install, or a GGUF the operator
|
|
9670
|
+
* copied in by hand — is still SELECTABLE, as a `{kind:'path'}` ref. Without
|
|
9671
|
+
* it the picker could list such a file and do nothing with it.
|
|
9672
|
+
*/
|
|
9673
|
+
path: zod.z.string().optional()
|
|
9621
9674
|
});
|
|
9622
9675
|
var LlmRuntimeDiskUsageSchema = zod.z.object({
|
|
9623
9676
|
nodeId: zod.z.string(),
|
|
@@ -9781,6 +9834,36 @@ var ManagedModelCatalogEntrySchema = zod.z.object({
|
|
|
9781
9834
|
/** Vision models: companion projector file. */
|
|
9782
9835
|
mmprojUrl: zod.z.string().optional()
|
|
9783
9836
|
});
|
|
9837
|
+
/**
|
|
9838
|
+
* The outcome of turning one operator-typed Hugging Face reference into a
|
|
9839
|
+
* download plan. A RESULT, never a throw: "this repo has 24 quantizations and
|
|
9840
|
+
* I will not pick for you" is a normal answer the UI has to render, not an
|
|
9841
|
+
* exception.
|
|
9842
|
+
*
|
|
9843
|
+
* `candidates` is the whole reason the refusal is usable — every string in it
|
|
9844
|
+
* is a tag that resolves when pasted back as `<org>/<repo>:<TAG>`.
|
|
9845
|
+
*/
|
|
9846
|
+
var HfModelResolutionSchema = zod.z.discriminatedUnion("ok", [zod.z.object({
|
|
9847
|
+
ok: zod.z.literal(true),
|
|
9848
|
+
/** Ready to hand to `installModel` unchanged. */
|
|
9849
|
+
model: ManagedModelRefSchema,
|
|
9850
|
+
label: zod.z.string(),
|
|
9851
|
+
repo: zod.z.string(),
|
|
9852
|
+
quantization: zod.z.string(),
|
|
9853
|
+
purpose: zod.z.enum(["text", "vision"]),
|
|
9854
|
+
totalBytes: zod.z.number(),
|
|
9855
|
+
/** mmproj + shards, for the preview: an operator approving 23 GB should
|
|
9856
|
+
* see that 0.9 GB of it is a projector they did not name. */
|
|
9857
|
+
extraFilenames: zod.z.array(zod.z.string())
|
|
9858
|
+
}), zod.z.object({
|
|
9859
|
+
ok: zod.z.literal(false),
|
|
9860
|
+
code: zod.z.string(),
|
|
9861
|
+
message: zod.z.string(),
|
|
9862
|
+
candidates: zod.z.array(zod.z.string()).optional(),
|
|
9863
|
+
/** Set when the refusal was only the ceiling: re-calling with
|
|
9864
|
+
* `maxBytes: requiredBytes` is the operator's explicit override. */
|
|
9865
|
+
requiredBytes: zod.z.number().optional()
|
|
9866
|
+
})]);
|
|
9784
9867
|
var LlmRuntimeNodeSchema = zod.z.object({
|
|
9785
9868
|
nodeId: zod.z.string(),
|
|
9786
9869
|
reachable: zod.z.boolean(),
|
|
@@ -9848,6 +9931,25 @@ var llmCapability = {
|
|
|
9848
9931
|
listModelCatalog: require_sleep.method(zod.z.object({}), zod.z.array(ManagedModelCatalogEntrySchema)),
|
|
9849
9932
|
listRuntimeNodes: require_sleep.method(zod.z.object({}), zod.z.array(LlmRuntimeNodeSchema)),
|
|
9850
9933
|
listNodeModels: require_sleep.method(zod.z.object({ nodeId: zod.z.string() }), zod.z.array(LlmNodeModelSchema)),
|
|
9934
|
+
/**
|
|
9935
|
+
* One typed Hugging Face reference → a pinned, verified `ManagedModelRef`.
|
|
9936
|
+
*
|
|
9937
|
+
* Runs on the HUB, not on the target node: resolution needs egress to
|
|
9938
|
+
* huggingface.co, and an agent that cannot reach it still installs fine
|
|
9939
|
+
* through the model-distributor relay. Nothing is downloaded here — this is
|
|
9940
|
+
* a tree read plus a HEAD, so the operator sees the size, the quantization
|
|
9941
|
+
* and the mmproj BEFORE approving a multi-GB pull.
|
|
9942
|
+
*/
|
|
9943
|
+
resolveModelRef: require_sleep.method(zod.z.object({
|
|
9944
|
+
/** `https://huggingface.co/<org>/<repo>/resolve/main/<f>.gguf`,
|
|
9945
|
+
* `<org>/<repo>/<f>.gguf`, `<org>/<repo>` or `<org>/<repo>:<QUANT>`. */
|
|
9946
|
+
ref: zod.z.string(),
|
|
9947
|
+
/** Explicit ceiling override, in bytes. Absent = the built-in ceiling. */
|
|
9948
|
+
maxBytes: zod.z.number().positive().optional()
|
|
9949
|
+
}), HfModelResolutionSchema, {
|
|
9950
|
+
kind: "mutation",
|
|
9951
|
+
auth: "admin"
|
|
9952
|
+
}),
|
|
9851
9953
|
installModel: require_sleep.method(zod.z.object({
|
|
9852
9954
|
nodeId: zod.z.string(),
|
|
9853
9955
|
model: ManagedModelRefSchema
|
|
@@ -16846,6 +16948,17 @@ var maxSessionHoldMsField = {
|
|
|
16846
16948
|
default: 12e4,
|
|
16847
16949
|
step: 5e3
|
|
16848
16950
|
};
|
|
16951
|
+
/**
|
|
16952
|
+
* Quiet period that closes an `audioMode: 'on-motion'` audio window. Floor of
|
|
16953
|
+
* 5s so a rearm can never degenerate into per-event stream churn; default 90s
|
|
16954
|
+
* comfortably outlives the gap between two PIR wakes on a battery camera.
|
|
16955
|
+
*/
|
|
16956
|
+
var audioMotionWindowMsField = {
|
|
16957
|
+
min: 5e3,
|
|
16958
|
+
max: 6e5,
|
|
16959
|
+
default: 9e4,
|
|
16960
|
+
step: 5e3
|
|
16961
|
+
};
|
|
16849
16962
|
var motionFpsField = {
|
|
16850
16963
|
min: 1,
|
|
16851
16964
|
max: 30,
|
|
@@ -17022,6 +17135,27 @@ var RunnerCameraConfigSchema = zod.z.object({
|
|
|
17022
17135
|
* resolved `CameraDetectionConfig`.
|
|
17023
17136
|
*/
|
|
17024
17137
|
maxSessionHoldMs: zod.z.number().min(maxSessionHoldMsField.min).max(maxSessionHoldMsField.max).optional(),
|
|
17138
|
+
/**
|
|
17139
|
+
* Orchestrator-side quiet period (ms) that closes an `audioMode:
|
|
17140
|
+
* 'on-motion'` audio window, measured from the LAST motion event.
|
|
17141
|
+
*
|
|
17142
|
+
* This exists because the falling edge cannot be relied on. Camera-native
|
|
17143
|
+
* providers emit motion as a RISING EDGE ONLY (Reolink's Baichuan push and
|
|
17144
|
+
* its email-push SMTP path both emit `detected: true` and never the
|
|
17145
|
+
* counterpart); only the frame-diff analyzer emits falls. So on an
|
|
17146
|
+
* onboard-only camera a window that closed only on `detected: false` never
|
|
17147
|
+
* closed at all, and `on-motion` silently behaved as `always-on` — on a
|
|
17148
|
+
* battery camera, the one failure mode the mode exists to prevent.
|
|
17149
|
+
*
|
|
17150
|
+
* Every motion event rearms this timer WITHOUT restarting the stream, so a
|
|
17151
|
+
* burst of re-fires costs nothing. A falling edge, when one does arrive,
|
|
17152
|
+
* still closes earlier via `motionCooldownMs` — whichever comes first wins.
|
|
17153
|
+
*
|
|
17154
|
+
* Not consumed by the runner: carried here so it shares the per-camera
|
|
17155
|
+
* device-settings surface with `motionCooldownMs`, exactly like
|
|
17156
|
+
* `maxSessionHoldMs`.
|
|
17157
|
+
*/
|
|
17158
|
+
audioMotionWindowMs: zod.z.number().min(audioMotionWindowMsField.min).max(audioMotionWindowMsField.max).optional(),
|
|
17025
17159
|
motionFps: zod.z.number().min(motionFpsField.min).max(motionFpsField.max).default(motionFpsField.default),
|
|
17026
17160
|
detectionFps: zod.z.number().min(detectionFpsField.min).max(detectionFpsField.max).default(detectionFpsField.default),
|
|
17027
17161
|
motionStreamId: zod.z.string(),
|
|
@@ -17206,6 +17340,25 @@ var RunnerCameraDeviceUIFields = [
|
|
|
17206
17340
|
nullable: true,
|
|
17207
17341
|
nullLabel: "Default"
|
|
17208
17342
|
},
|
|
17343
|
+
{
|
|
17344
|
+
key: "audioMotionWindowMs",
|
|
17345
|
+
type: "slider",
|
|
17346
|
+
label: "Audio window after motion",
|
|
17347
|
+
description: "How long audio keeps being analysed after the last motion event. Each new motion event extends the window without restarting the audio stream.",
|
|
17348
|
+
min: audioMotionWindowMsField.min,
|
|
17349
|
+
max: audioMotionWindowMsField.max,
|
|
17350
|
+
step: audioMotionWindowMsField.step,
|
|
17351
|
+
default: audioMotionWindowMsField.default,
|
|
17352
|
+
showValue: true,
|
|
17353
|
+
unit: "s",
|
|
17354
|
+
displayScale: 1e3,
|
|
17355
|
+
nullable: true,
|
|
17356
|
+
nullLabel: "Default",
|
|
17357
|
+
showWhen: {
|
|
17358
|
+
field: "audioMode",
|
|
17359
|
+
equals: "on-motion"
|
|
17360
|
+
}
|
|
17361
|
+
},
|
|
17209
17362
|
{
|
|
17210
17363
|
key: "onboardMotionDrivesAnalyzer",
|
|
17211
17364
|
type: "boolean",
|
|
@@ -21210,6 +21363,25 @@ var BatteryStatusSchema = zod.z.object({
|
|
|
21210
21363
|
/** Ms epoch of the last observation. Lets consumers reason about freshness. */
|
|
21211
21364
|
lastUpdated: zod.z.number(),
|
|
21212
21365
|
/**
|
|
21366
|
+
* Ms epoch of the last time the device PROVED it was reachable — a
|
|
21367
|
+
* completed firmware round-trip, an observed wake, or an inbound push
|
|
21368
|
+
* (firmware event, email). `0`/absent = never since this slice was born.
|
|
21369
|
+
*
|
|
21370
|
+
* This is the ONLY input that separates "asleep" from "gone", and it is
|
|
21371
|
+
* fed exclusively by PASSIVE signals: nothing may write it by reaching
|
|
21372
|
+
* for the radio, because a poll that confirms reachability is the same
|
|
21373
|
+
* poll that drains the battery. See {@link deriveBatteryPresence} — the
|
|
21374
|
+
* single derivation every consumer must use; no surface computes its own.
|
|
21375
|
+
*
|
|
21376
|
+
* It is deliberately NOT a clock in the
|
|
21377
|
+
* `scripts/check-runtime-state-durability.ts` sense: it is the
|
|
21378
|
+
* observation itself, and it is the only thing a 30-hour silence is
|
|
21379
|
+
* visible in. Writers quantise it (see `CONTACT_WRITE_QUANTUM_MS` in the
|
|
21380
|
+
* Reolink provider) so a value that means "recently" cannot cost a
|
|
21381
|
+
* SQLite commit per round-trip.
|
|
21382
|
+
*/
|
|
21383
|
+
lastContactAt: zod.z.number().optional(),
|
|
21384
|
+
/**
|
|
21213
21385
|
* True when the source is a BINARY low-battery indicator (HA
|
|
21214
21386
|
* `binary_sensor` device_class=battery / `LOW_BAT`) that has no real
|
|
21215
21387
|
* charge level — `percentage` is then a coarse stand-in (100 = normal,
|
|
@@ -28182,13 +28354,63 @@ var CamStreamDescriptorSchema = zod.z.object({
|
|
|
28182
28354
|
* set of stream descriptors it can offer for the device, synchronously, so the
|
|
28183
28355
|
* broker can reconcile its registry against the authoritative provider state.
|
|
28184
28356
|
*/
|
|
28357
|
+
/**
|
|
28358
|
+
* The catalog as a DURABLE fact rather than a live answer.
|
|
28359
|
+
*
|
|
28360
|
+
* A battery camera's descriptors are profile-stable — they change when the
|
|
28361
|
+
* operator rewrites an encoder profile, not minute to minute — but building
|
|
28362
|
+
* them costs a Baichuan login, which on a sleeping Argus IS a wake. So the
|
|
28363
|
+
* provider is allowed to build them exactly once per profile and must serve
|
|
28364
|
+
* every later pull from a cache.
|
|
28365
|
+
*
|
|
28366
|
+
* Holding that cache only in RAM is what turned a restart into an outage. The
|
|
28367
|
+
* runner comes back with the camera asleep, `buildStreamCatalogUncached`
|
|
28368
|
+
* correctly refuses to wake it, the pull answers `[]`, the broker has no
|
|
28369
|
+
* cam-stream entry to build a broker from, and `webrtcSession.handleOffer`
|
|
28370
|
+
* fails with a flat "No broker for stream" — for as long as the camera sleeps,
|
|
28371
|
+
* which on a battery cam is most of the day. The camera was fine. The stream
|
|
28372
|
+
* was unreachable because the process had forgotten what the camera offers.
|
|
28373
|
+
*
|
|
28374
|
+
* Declaring it here puts it in `device-runtime-state`, the kernel's canonical
|
|
28375
|
+
* declared collection, with the same `restored` durability `battery` uses for
|
|
28376
|
+
* the same reason: the last known value is the only value there is while the
|
|
28377
|
+
* device is asleep. The broker's brokers are therefore always DEFINABLE — it
|
|
28378
|
+
* is the DIAL that wakes a camera, never the catalog (D173).
|
|
28379
|
+
*/
|
|
28380
|
+
var StreamCatalogStateSchema = zod.z.object({
|
|
28381
|
+
/** The descriptors as last built from a real camera response. Never a guess:
|
|
28382
|
+
* a failed or refused build writes NOTHING, so a restored catalog is always
|
|
28383
|
+
* one the camera itself once produced. */
|
|
28384
|
+
descriptors: zod.z.array(CamStreamDescriptorSchema),
|
|
28385
|
+
/** Ms epoch of the build that produced {@link descriptors}. Lets the wake
|
|
28386
|
+
* path decide whether the camera's own awake window is worth spending on a
|
|
28387
|
+
* re-read. */
|
|
28388
|
+
lastFetchedAt: zod.z.number()
|
|
28389
|
+
});
|
|
28185
28390
|
var streamCatalogCapability = {
|
|
28186
28391
|
name: "stream-catalog",
|
|
28187
28392
|
scope: "device",
|
|
28188
28393
|
deviceNative: true,
|
|
28189
28394
|
mode: "singleton",
|
|
28190
28395
|
deviceTypes: [require_sleep.DeviceType.Camera],
|
|
28191
|
-
methods: { getCatalog: require_sleep.method(zod.z.object({ deviceId: zod.z.number().int().nonnegative() }), zod.z.array(CamStreamDescriptorSchema).readonly()) }
|
|
28396
|
+
methods: { getCatalog: require_sleep.method(zod.z.object({ deviceId: zod.z.number().int().nonnegative() }), zod.z.array(CamStreamDescriptorSchema).readonly()) },
|
|
28397
|
+
runtimeState: StreamCatalogStateSchema,
|
|
28398
|
+
/**
|
|
28399
|
+
* Runtime-state durability: **restored** — see the schema doc. A cold
|
|
28400
|
+
* catalog on a sleeping battery camera is not a slow first frame, it is a
|
|
28401
|
+
* camera that cannot be watched at all until it happens to wake.
|
|
28402
|
+
*
|
|
28403
|
+
* Churn is nil by construction: the slice is written only by a SUCCESSFUL
|
|
28404
|
+
* build, and a build only runs when there is no cached copy (or the copy is
|
|
28405
|
+
* a day old and the camera is awake anyway).
|
|
28406
|
+
*
|
|
28407
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
28408
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
28409
|
+
*/
|
|
28410
|
+
durability: "restored",
|
|
28411
|
+
/** Clock field: written, but excluded from the compare that decides whether
|
|
28412
|
+
* persisting is worth a SQLite commit — the descriptors are the value. */
|
|
28413
|
+
volatileStateFields: ["lastFetchedAt"]
|
|
28192
28414
|
};
|
|
28193
28415
|
//#endregion
|
|
28194
28416
|
//#region src/capabilities/stream-params.cap.ts
|
|
@@ -30419,6 +30641,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
30419
30641
|
sceneMonitor: sceneMonitorCapability,
|
|
30420
30642
|
scriptRunner: scriptRunnerCapability,
|
|
30421
30643
|
smoke: smokeCapability,
|
|
30644
|
+
streamCatalog: streamCatalogCapability,
|
|
30422
30645
|
streamParams: streamParamsCapability,
|
|
30423
30646
|
switch: switchCapability,
|
|
30424
30647
|
tamper: tamperCapability,
|
|
@@ -31076,6 +31299,15 @@ var BaseDeviceProvider = class extends require_sleep.BaseAddon {
|
|
|
31076
31299
|
labels: ["probe not implemented"]
|
|
31077
31300
|
};
|
|
31078
31301
|
}
|
|
31302
|
+
/**
|
|
31303
|
+
* Top-level devices restored at once in {@link onRestoreDevices}.
|
|
31304
|
+
*
|
|
31305
|
+
* Four covers the fleets this ships to without turning a boot into a burst a
|
|
31306
|
+
* camera NVR answers with a refusal. A provider whose upstream is a single
|
|
31307
|
+
* session with a serial command channel (a Baichuan hub, an NVR that
|
|
31308
|
+
* serialises ISAPI) should lower it; nothing needs to raise it.
|
|
31309
|
+
*/
|
|
31310
|
+
restoreConcurrency = 4;
|
|
31079
31311
|
async restoreDevices(savedDevices) {
|
|
31080
31312
|
await this.onRestoreDevices(savedDevices);
|
|
31081
31313
|
if (savedDevices.length > 0) this.ctx.logger.info(`Restored ${savedDevices.length} ${this.providerName} device(s)`);
|
|
@@ -31107,15 +31339,15 @@ var BaseDeviceProvider = class extends require_sleep.BaseAddon {
|
|
|
31107
31339
|
*/
|
|
31108
31340
|
async onRestoreDevices(savedDevices) {
|
|
31109
31341
|
const restored = /* @__PURE__ */ new Set();
|
|
31110
|
-
|
|
31111
|
-
|
|
31342
|
+
const topLevel = savedDevices.filter((saved) => saved.parentDeviceId === null);
|
|
31343
|
+
const restoreOne = async (saved) => {
|
|
31112
31344
|
const Class = this.deviceClasses[saved.type];
|
|
31113
31345
|
if (!Class) {
|
|
31114
31346
|
this.ctx.logger.warn("No device class registered for restored type — skipping", {
|
|
31115
31347
|
tags: { stableId: saved.stableId },
|
|
31116
31348
|
meta: { type: saved.type }
|
|
31117
31349
|
});
|
|
31118
|
-
|
|
31350
|
+
return;
|
|
31119
31351
|
}
|
|
31120
31352
|
try {
|
|
31121
31353
|
await this.ctx.kernel.devices.create(saved.stableId, Class, {});
|
|
@@ -31129,7 +31361,15 @@ var BaseDeviceProvider = class extends require_sleep.BaseAddon {
|
|
|
31129
31361
|
}
|
|
31130
31362
|
});
|
|
31131
31363
|
}
|
|
31132
|
-
}
|
|
31364
|
+
};
|
|
31365
|
+
let nextTopLevel = 0;
|
|
31366
|
+
await Promise.all(Array.from({ length: Math.min(Math.max(1, this.restoreConcurrency), topLevel.length) }, async () => {
|
|
31367
|
+
for (;;) {
|
|
31368
|
+
const saved = topLevel[nextTopLevel++];
|
|
31369
|
+
if (saved === void 0) return;
|
|
31370
|
+
await restoreOne(saved);
|
|
31371
|
+
}
|
|
31372
|
+
}));
|
|
31133
31373
|
const childRows = savedDevices.filter((s) => s.parentDeviceId !== null);
|
|
31134
31374
|
for (const saved of childRows) {
|
|
31135
31375
|
const Class = this.deviceClasses[saved.type];
|
|
@@ -31625,6 +31865,47 @@ function resolveDeviceProfile(features) {
|
|
|
31625
31865
|
return null;
|
|
31626
31866
|
}
|
|
31627
31867
|
//#endregion
|
|
31868
|
+
//#region src/device/battery-presence.ts
|
|
31869
|
+
/**
|
|
31870
|
+
* Default silence budget before a sleeping battery camera is called gone.
|
|
31871
|
+
*
|
|
31872
|
+
* Sized off the mechanism that produces contact, not off taste: a battery cam
|
|
31873
|
+
* on this deployment surfaces a firmware push (battery level, sleep/wake, or a
|
|
31874
|
+
* motion email) on the order of hours even with no visitors, and the snapshot
|
|
31875
|
+
* wrapper's own battery window is 1 hour. Six hours is therefore several
|
|
31876
|
+
* missed opportunities, not one — so a single quiet night does not raise a
|
|
31877
|
+
* fault, and a genuinely flat camera is named well inside a day.
|
|
31878
|
+
*/
|
|
31879
|
+
var BATTERY_UNREACHABLE_AFTER_MS = 360 * 6e4;
|
|
31880
|
+
/**
|
|
31881
|
+
* THE derivation. One crop rectangle, one presence verdict — see D52 for why
|
|
31882
|
+
* this repo insists a derived value has exactly one implementation.
|
|
31883
|
+
*
|
|
31884
|
+
* `undefined` status ⇒ `sleeping`. A device with no slice has made no claim,
|
|
31885
|
+
* and the caller decides separately whether it is even battery-operated
|
|
31886
|
+
* (`DeviceFeature.BatteryOperated`); this function never answers that
|
|
31887
|
+
* question, only what a battery device is doing.
|
|
31888
|
+
*/
|
|
31889
|
+
function deriveBatteryPresence(input) {
|
|
31890
|
+
const status = input.status;
|
|
31891
|
+
if (!status) return "sleeping";
|
|
31892
|
+
if (status.sleeping !== true) return "awake";
|
|
31893
|
+
const lastContactAt = status.lastContactAt;
|
|
31894
|
+
if (typeof lastContactAt !== "number" || lastContactAt <= 0) return "sleeping";
|
|
31895
|
+
const budget = input.unreachableAfterMs ?? 216e5;
|
|
31896
|
+
return input.nowMs - lastContactAt > budget ? "unreachable" : "sleeping";
|
|
31897
|
+
}
|
|
31898
|
+
/**
|
|
31899
|
+
* Is this presence a FAULT the operator should be told about?
|
|
31900
|
+
*
|
|
31901
|
+
* Exists so no surface has to re-decide it — the whole point of the third
|
|
31902
|
+
* state is that `sleeping` stops being rendered as breakage, and a caller that
|
|
31903
|
+
* writes `presence !== 'awake'` has silently undone that.
|
|
31904
|
+
*/
|
|
31905
|
+
function isBatteryPresenceFault(presence) {
|
|
31906
|
+
return presence === "unreachable";
|
|
31907
|
+
}
|
|
31908
|
+
//#endregion
|
|
31628
31909
|
//#region src/device/path-util.ts
|
|
31629
31910
|
/** Returns true when `x` is a non-null, non-array plain object. */
|
|
31630
31911
|
function isRecord(x) {
|
|
@@ -35809,6 +36090,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
35809
36090
|
addonId: null,
|
|
35810
36091
|
access: "view"
|
|
35811
36092
|
},
|
|
36093
|
+
"llm.resolveModelRef": {
|
|
36094
|
+
capName: "llm",
|
|
36095
|
+
capScope: "system",
|
|
36096
|
+
addonId: null,
|
|
36097
|
+
access: "create"
|
|
36098
|
+
},
|
|
35812
36099
|
"llm.setDefault": {
|
|
35813
36100
|
capName: "llm",
|
|
35814
36101
|
capScope: "system",
|
|
@@ -41386,7 +41673,7 @@ function getCapsByProviderKind(kind) {
|
|
|
41386
41673
|
//#region src/generated/runtime-state-durability.ts
|
|
41387
41674
|
/**
|
|
41388
41675
|
* Per-cap runtime-state policy, projected from every `*.cap.ts` that declares
|
|
41389
|
-
* `runtimeState`.
|
|
41676
|
+
* `runtimeState`. 64 caps: 34 `restored`, 30 `session`.
|
|
41390
41677
|
*
|
|
41391
41678
|
* A cap absent from this map has no runtime-state slice at all. A cap PRESENT
|
|
41392
41679
|
* with `durability: 'session'` has one and has decided not to keep it.
|
|
@@ -41592,6 +41879,10 @@ var RUNTIME_STATE_POLICY = {
|
|
|
41592
41879
|
durability: "restored",
|
|
41593
41880
|
volatileFields: ["lastChangedAt"]
|
|
41594
41881
|
},
|
|
41882
|
+
"stream-catalog": {
|
|
41883
|
+
durability: "restored",
|
|
41884
|
+
volatileFields: ["lastFetchedAt"]
|
|
41885
|
+
},
|
|
41595
41886
|
"stream-params": {
|
|
41596
41887
|
durability: "restored",
|
|
41597
41888
|
volatileFields: ["lastFetchedAt"]
|
|
@@ -41692,6 +41983,7 @@ var RESTORED_CAP_NAMES = [
|
|
|
41692
41983
|
"pressure-sensor",
|
|
41693
41984
|
"privacy-mask",
|
|
41694
41985
|
"smoke",
|
|
41986
|
+
"stream-catalog",
|
|
41695
41987
|
"stream-params",
|
|
41696
41988
|
"switch",
|
|
41697
41989
|
"tamper",
|
|
@@ -42052,6 +42344,7 @@ function createSystemProxy(api) {
|
|
|
42052
42344
|
listModelCatalog: (input) => dispatch("llm", "listModelCatalog", "query", input),
|
|
42053
42345
|
listRuntimeNodes: (input) => dispatch("llm", "listRuntimeNodes", "query", input),
|
|
42054
42346
|
listNodeModels: (input) => dispatch("llm", "listNodeModels", "query", input),
|
|
42347
|
+
resolveModelRef: (input) => dispatch("llm", "resolveModelRef", "mutation", input),
|
|
42055
42348
|
installModel: (input) => dispatch("llm", "installModel", "mutation", input),
|
|
42056
42349
|
deleteModel: (input) => dispatch("llm", "deleteModel", "mutation", input),
|
|
42057
42350
|
getRuntimeStatus: (input) => dispatch("llm", "getRuntimeStatus", "query", input),
|
|
@@ -45418,6 +45711,8 @@ exports.AvailableIntegrationTypeSchema = AvailableIntegrationTypeSchema;
|
|
|
45418
45711
|
exports.BACKEND_TO_FORMAT = BACKEND_TO_FORMAT;
|
|
45419
45712
|
exports.BASE_LIVE_EGRESS_PROFILE = BASE_LIVE_EGRESS_PROFILE;
|
|
45420
45713
|
exports.BATTERY_DEVICE_PROFILE = BATTERY_DEVICE_PROFILE;
|
|
45714
|
+
exports.BATTERY_UNREACHABLE_AFTER_MS = BATTERY_UNREACHABLE_AFTER_MS;
|
|
45715
|
+
exports.BOOT_RECOVERY_BACKOFF_MS = require_sleep.BOOT_RECOVERY_BACKOFF_MS;
|
|
45421
45716
|
exports.BacklightModeSchema = BacklightModeSchema;
|
|
45422
45717
|
exports.BackupDestinationInfoSchema = BackupDestinationInfoSchema;
|
|
45423
45718
|
exports.BackupEntrySchema = BackupEntrySchema;
|
|
@@ -45679,6 +45974,7 @@ exports.HF_BASE_URL = HF_BASE_URL;
|
|
|
45679
45974
|
exports.HF_REPO = HF_REPO;
|
|
45680
45975
|
exports.HWACCEL_OPTIONS = HWACCEL_OPTIONS;
|
|
45681
45976
|
exports.HealthStatusSchema = HealthStatusSchema;
|
|
45977
|
+
exports.HfModelResolutionSchema = HfModelResolutionSchema;
|
|
45682
45978
|
exports.HistoryPointSchema = HistoryPointSchema;
|
|
45683
45979
|
exports.HistoryResolutionEnum = HistoryResolutionEnum;
|
|
45684
45980
|
exports.HumidifierStatusSchema = HumidifierStatusSchema;
|
|
@@ -45709,6 +46005,7 @@ exports.LinkedDeviceSchema = LinkedDeviceSchema;
|
|
|
45709
46005
|
exports.LinkedDevicesModeSchema = LinkedDevicesModeSchema;
|
|
45710
46006
|
exports.LlmDefaultSchema = LlmDefaultSchema;
|
|
45711
46007
|
exports.LlmDefaultSelectorSchema = LlmDefaultSelectorSchema;
|
|
46008
|
+
exports.LlmDownloadProgressSchema = LlmDownloadProgressSchema;
|
|
45712
46009
|
exports.LlmErrorCodeSchema = LlmErrorCodeSchema;
|
|
45713
46010
|
exports.LlmGenerateBaseInputSchema = LlmGenerateBaseInputSchema;
|
|
45714
46011
|
exports.LlmGenerateErrSchema = LlmGenerateErrSchema;
|
|
@@ -45749,6 +46046,7 @@ exports.METHOD_DEVICE_SELECTORS = METHOD_DEVICE_SELECTORS;
|
|
|
45749
46046
|
exports.MODEL_FORMATS = MODEL_FORMATS;
|
|
45750
46047
|
exports.MOTION_TRIGGER_FEATURE = MOTION_TRIGGER_FEATURE;
|
|
45751
46048
|
exports.ManagedModelCatalogEntrySchema = ManagedModelCatalogEntrySchema;
|
|
46049
|
+
exports.ManagedModelExtraFileSchema = ManagedModelExtraFileSchema;
|
|
45752
46050
|
exports.ManagedModelRefSchema = ManagedModelRefSchema;
|
|
45753
46051
|
exports.ManagedRuntimeConfigSchema = ManagedRuntimeConfigSchema;
|
|
45754
46052
|
exports.MaskGridDimsSchema = MaskGridDimsSchema;
|
|
@@ -46341,6 +46639,7 @@ exports.decodeVectorBase64 = decodeVectorBase64;
|
|
|
46341
46639
|
exports.decoderCapability = decoderCapability;
|
|
46342
46640
|
exports.defaultDeviceFor = defaultDeviceFor;
|
|
46343
46641
|
exports.defineCustomActions = defineCustomActions;
|
|
46642
|
+
exports.deriveBatteryPresence = deriveBatteryPresence;
|
|
46344
46643
|
exports.deriveCameraSwitches = deriveCameraSwitches;
|
|
46345
46644
|
exports.deriveDetailCropRect = deriveDetailCropRect;
|
|
46346
46645
|
exports.deriveRecordingMode = deriveRecordingMode;
|
|
@@ -46410,6 +46709,7 @@ exports.isAgentOnlyPlacement = isAgentOnlyPlacement;
|
|
|
46410
46709
|
exports.isArrayOutputSchema = isArrayOutputSchema;
|
|
46411
46710
|
exports.isAudioLabelSelected = isAudioLabelSelected;
|
|
46412
46711
|
exports.isBaseConditionKey = isBaseConditionKey;
|
|
46712
|
+
exports.isBatteryPresenceFault = isBatteryPresenceFault;
|
|
46413
46713
|
exports.isCollectionArrayMethod = isCollectionArrayMethod;
|
|
46414
46714
|
exports.isDeployableToAgent = isDeployableToAgent;
|
|
46415
46715
|
exports.isDetectionMacroClass = isDetectionMacroClass;
|