@camstack/system 1.2.91 → 1.2.92
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-runner.js +1 -1
- package/dist/addon-runner.mjs +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
- package/dist/builtins/alerts/alerts.addon.js +1 -1
- package/dist/builtins/alerts/alerts.addon.mjs +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
- package/dist/builtins/console-logging/index.js +1 -1
- package/dist/builtins/console-logging/index.mjs +1 -1
- package/dist/builtins/core-blocks/blocks-integration.d.ts +34 -1
- package/dist/builtins/core-blocks/core-blocks.addon.js +69 -22
- package/dist/builtins/core-blocks/core-blocks.addon.mjs +69 -22
- package/dist/builtins/device-manager/device-manager.addon.js +1 -1
- package/dist/builtins/device-manager/device-manager.addon.mjs +1 -1
- package/dist/builtins/doorbell/virtual-doorbell.addon.js +1 -1
- package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -1
- package/dist/builtins/hub-forwarder/index.js +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
- package/dist/builtins/local-auth/local-auth.addon.js +1 -1
- package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
- package/dist/builtins/local-network/local-network.addon.js +1 -1
- package/dist/builtins/local-network/local-network.addon.mjs +1 -1
- package/dist/builtins/loki-logging/index.js +1 -1
- package/dist/builtins/loki-logging/index.mjs +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
- package/dist/builtins/platform-probe/index.js +1 -1
- package/dist/builtins/platform-probe/index.mjs +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
- package/dist/builtins/snapshot/index.js +1 -1
- package/dist/builtins/snapshot/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +1 -1
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +1 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
- package/dist/builtins/system-config/system-config.addon.js +1 -1
- package/dist/builtins/system-config/system-config.addon.mjs +1 -1
- package/dist/builtins/winston-logging/index.js +1 -1
- package/dist/builtins/winston-logging/index.mjs +1 -1
- package/dist/{dist-9Gfk4KOk.js → dist-BH2tZ9ZN.js} +252 -5
- package/dist/{dist-DhrTd8LL.mjs → dist-DXDvrBi0.mjs} +252 -5
- package/dist/index.js +41 -6
- package/dist/index.mjs +41 -6
- package/dist/kernel/addon-health-monitor.d.ts +10 -1
- package/dist/logging/log-manager.d.ts +28 -0
- package/dist/{manifest-python-deps-C0zkl1Ae.js → manifest-python-deps-BZO_eMn-.js} +1 -7
- package/dist/{manifest-python-deps-fWzdEasI.mjs → manifest-python-deps-D3hP9W8D.mjs} +2 -8
- package/package.json +1 -1
|
@@ -10158,6 +10158,18 @@ var LlmGenerateBaseInputSchema = z.object({
|
|
|
10158
10158
|
* Resource ceiling = llama-server flags + idleStopMinutes ONLY (no RSS
|
|
10159
10159
|
* watchdog — operator decision #3).
|
|
10160
10160
|
*/
|
|
10161
|
+
/**
|
|
10162
|
+
* A companion artifact that MUST land beside the main GGUF: the `mmproj`
|
|
10163
|
+
* projector of a vision model, or shards 2..N of a split GGUF. Carried on the
|
|
10164
|
+
* REF rather than looked up at install time, so what the operator approved in
|
|
10165
|
+
* the preview is exactly what the node downloads.
|
|
10166
|
+
*/
|
|
10167
|
+
var ManagedModelExtraFileSchema = z.object({
|
|
10168
|
+
url: z.string(),
|
|
10169
|
+
filename: z.string(),
|
|
10170
|
+
sizeBytes: z.number(),
|
|
10171
|
+
sha256: z.string().optional()
|
|
10172
|
+
});
|
|
10161
10173
|
var ManagedModelRefSchema = z.discriminatedUnion("kind", [
|
|
10162
10174
|
z.object({
|
|
10163
10175
|
kind: z.literal("catalog"),
|
|
@@ -10166,7 +10178,11 @@ var ManagedModelRefSchema = z.discriminatedUnion("kind", [
|
|
|
10166
10178
|
z.object({
|
|
10167
10179
|
kind: z.literal("url"),
|
|
10168
10180
|
url: z.string(),
|
|
10169
|
-
sha256: z.string().optional()
|
|
10181
|
+
sha256: z.string().optional(),
|
|
10182
|
+
/** Picker/status label; the file basename when absent. */
|
|
10183
|
+
label: z.string().optional(),
|
|
10184
|
+
sizeBytes: z.number().optional(),
|
|
10185
|
+
extraFiles: z.array(ManagedModelExtraFileSchema).optional()
|
|
10170
10186
|
}),
|
|
10171
10187
|
z.object({
|
|
10172
10188
|
kind: z.literal("path"),
|
|
@@ -10227,11 +10243,39 @@ var ManagedRuntimeConfigSchema = z.object({
|
|
|
10227
10243
|
"q4_1",
|
|
10228
10244
|
"q4_0"
|
|
10229
10245
|
]).optional(),
|
|
10246
|
+
/**
|
|
10247
|
+
* Escape hatch for llama-server flags this schema does NOT model — `--jinja`
|
|
10248
|
+
* (which most vision chat templates need and some language-only models
|
|
10249
|
+
* dislike), `--cont-batching`, `--rope-scaling`, …
|
|
10250
|
+
*
|
|
10251
|
+
* It is NOT a second place to set the flags above. A token that collides
|
|
10252
|
+
* with a typed field is REJECTED at start, naming the field that owns it
|
|
10253
|
+
* (`assertNoOwnedFlags`), because two knobs writing the same argv is exactly
|
|
10254
|
+
* the "two switches that disagree" failure this repo has already shipped
|
|
10255
|
+
* twice (D62).
|
|
10256
|
+
*/
|
|
10257
|
+
extraArgs: z.array(z.string()).default([]),
|
|
10230
10258
|
/** Else lazy: first generate boots it. */
|
|
10231
10259
|
autoStart: z.boolean().default(false),
|
|
10232
10260
|
/** 0 = never; frees RAM after quiet periods. */
|
|
10233
10261
|
idleStopMinutes: z.number().int().default(30)
|
|
10234
10262
|
});
|
|
10263
|
+
/**
|
|
10264
|
+
* Where a multi-GB install currently is. A single 0..1 fraction cannot answer
|
|
10265
|
+
* "is it stuck?" for an install that is three files (shards + mmproj) followed
|
|
10266
|
+
* by a sha256 pass over 22 GB — during which the fraction sat at 1.0 and the
|
|
10267
|
+
* node looked hung. Phase + file + bytes is the smallest shape that does.
|
|
10268
|
+
*/
|
|
10269
|
+
var LlmDownloadProgressSchema = z.object({
|
|
10270
|
+
phase: z.enum(["downloading", "verifying"]),
|
|
10271
|
+
/** The artifact currently moving, e.g. `mmproj-F16.gguf`. */
|
|
10272
|
+
file: z.string(),
|
|
10273
|
+
fileIndex: z.number().int(),
|
|
10274
|
+
fileCount: z.number().int(),
|
|
10275
|
+
/** Across the WHOLE install, not the current file. */
|
|
10276
|
+
downloadedBytes: z.number(),
|
|
10277
|
+
totalBytes: z.number().optional()
|
|
10278
|
+
});
|
|
10235
10279
|
var LlmRuntimeStatusSchema = z.object({
|
|
10236
10280
|
/** Status is ALWAYS node-qualified. */
|
|
10237
10281
|
nodeId: z.string(),
|
|
@@ -10248,6 +10292,8 @@ var LlmRuntimeStatusSchema = z.object({
|
|
|
10248
10292
|
modelPath: z.string().optional(),
|
|
10249
10293
|
modelId: z.string().optional(),
|
|
10250
10294
|
downloadProgress: z.number().min(0).max(1).optional(),
|
|
10295
|
+
/** Detail behind `downloadProgress`; present for the same lifetime. */
|
|
10296
|
+
download: LlmDownloadProgressSchema.optional(),
|
|
10251
10297
|
lastError: z.string().optional(),
|
|
10252
10298
|
crashesInWindow: z.number(),
|
|
10253
10299
|
/** Child RSS (sampled best-effort). */
|
|
@@ -10258,7 +10304,14 @@ var LlmNodeModelSchema = z.object({
|
|
|
10258
10304
|
file: z.string(),
|
|
10259
10305
|
sizeBytes: z.number(),
|
|
10260
10306
|
catalogId: z.string().optional(),
|
|
10261
|
-
installedAt: z.number().optional()
|
|
10307
|
+
installedAt: z.number().optional(),
|
|
10308
|
+
/**
|
|
10309
|
+
* Absolute path on the node. Present so a file that is on disk but matches
|
|
10310
|
+
* no catalog entry — a custom Hugging Face install, or a GGUF the operator
|
|
10311
|
+
* copied in by hand — is still SELECTABLE, as a `{kind:'path'}` ref. Without
|
|
10312
|
+
* it the picker could list such a file and do nothing with it.
|
|
10313
|
+
*/
|
|
10314
|
+
path: z.string().optional()
|
|
10262
10315
|
});
|
|
10263
10316
|
var LlmRuntimeDiskUsageSchema = z.object({
|
|
10264
10317
|
nodeId: z.string(),
|
|
@@ -10351,9 +10404,12 @@ var LlmProfileSchema = z.object({
|
|
|
10351
10404
|
systemPrompt: z.string().optional(),
|
|
10352
10405
|
/** Total generation bound — the only one a unary call has. */
|
|
10353
10406
|
timeoutMs: z.number().int().positive().default(6e4),
|
|
10354
|
-
/**
|
|
10407
|
+
/** The TCP handshake only — "is the port even open". NOT the wait for
|
|
10408
|
+
* response headers: on the LM Studio / llama-server wire those are written
|
|
10409
|
+
* once the model has finished loading, so they belong to the bound below. */
|
|
10355
10410
|
connectTimeoutMs: z.number().int().positive().default(1e4),
|
|
10356
|
-
/** Accepted, but no output yet —
|
|
10411
|
+
/** Accepted, but no output yet — response headers included, because a cold
|
|
10412
|
+
* GPU load is exactly what happens before them. */
|
|
10357
10413
|
firstTokenTimeoutMs: z.number().int().positive().default(12e4),
|
|
10358
10414
|
/** Output started then stopped. */
|
|
10359
10415
|
idleTimeoutMs: z.number().int().positive().default(6e4),
|
|
@@ -10416,6 +10472,36 @@ var ManagedModelCatalogEntrySchema = z.object({
|
|
|
10416
10472
|
/** Vision models: companion projector file. */
|
|
10417
10473
|
mmprojUrl: z.string().optional()
|
|
10418
10474
|
});
|
|
10475
|
+
/**
|
|
10476
|
+
* The outcome of turning one operator-typed Hugging Face reference into a
|
|
10477
|
+
* download plan. A RESULT, never a throw: "this repo has 24 quantizations and
|
|
10478
|
+
* I will not pick for you" is a normal answer the UI has to render, not an
|
|
10479
|
+
* exception.
|
|
10480
|
+
*
|
|
10481
|
+
* `candidates` is the whole reason the refusal is usable — every string in it
|
|
10482
|
+
* is a tag that resolves when pasted back as `<org>/<repo>:<TAG>`.
|
|
10483
|
+
*/
|
|
10484
|
+
var HfModelResolutionSchema = z.discriminatedUnion("ok", [z.object({
|
|
10485
|
+
ok: z.literal(true),
|
|
10486
|
+
/** Ready to hand to `installModel` unchanged. */
|
|
10487
|
+
model: ManagedModelRefSchema,
|
|
10488
|
+
label: z.string(),
|
|
10489
|
+
repo: z.string(),
|
|
10490
|
+
quantization: z.string(),
|
|
10491
|
+
purpose: z.enum(["text", "vision"]),
|
|
10492
|
+
totalBytes: z.number(),
|
|
10493
|
+
/** mmproj + shards, for the preview: an operator approving 23 GB should
|
|
10494
|
+
* see that 0.9 GB of it is a projector they did not name. */
|
|
10495
|
+
extraFilenames: z.array(z.string())
|
|
10496
|
+
}), z.object({
|
|
10497
|
+
ok: z.literal(false),
|
|
10498
|
+
code: z.string(),
|
|
10499
|
+
message: z.string(),
|
|
10500
|
+
candidates: z.array(z.string()).optional(),
|
|
10501
|
+
/** Set when the refusal was only the ceiling: re-calling with
|
|
10502
|
+
* `maxBytes: requiredBytes` is the operator's explicit override. */
|
|
10503
|
+
requiredBytes: z.number().optional()
|
|
10504
|
+
})]);
|
|
10419
10505
|
var LlmRuntimeNodeSchema = z.object({
|
|
10420
10506
|
nodeId: z.string(),
|
|
10421
10507
|
reachable: z.boolean(),
|
|
@@ -10483,6 +10569,25 @@ var llmCapability = {
|
|
|
10483
10569
|
listModelCatalog: method(z.object({}), z.array(ManagedModelCatalogEntrySchema)),
|
|
10484
10570
|
listRuntimeNodes: method(z.object({}), z.array(LlmRuntimeNodeSchema)),
|
|
10485
10571
|
listNodeModels: method(z.object({ nodeId: z.string() }), z.array(LlmNodeModelSchema)),
|
|
10572
|
+
/**
|
|
10573
|
+
* One typed Hugging Face reference → a pinned, verified `ManagedModelRef`.
|
|
10574
|
+
*
|
|
10575
|
+
* Runs on the HUB, not on the target node: resolution needs egress to
|
|
10576
|
+
* huggingface.co, and an agent that cannot reach it still installs fine
|
|
10577
|
+
* through the model-distributor relay. Nothing is downloaded here — this is
|
|
10578
|
+
* a tree read plus a HEAD, so the operator sees the size, the quantization
|
|
10579
|
+
* and the mmproj BEFORE approving a multi-GB pull.
|
|
10580
|
+
*/
|
|
10581
|
+
resolveModelRef: method(z.object({
|
|
10582
|
+
/** `https://huggingface.co/<org>/<repo>/resolve/main/<f>.gguf`,
|
|
10583
|
+
* `<org>/<repo>/<f>.gguf`, `<org>/<repo>` or `<org>/<repo>:<QUANT>`. */
|
|
10584
|
+
ref: z.string(),
|
|
10585
|
+
/** Explicit ceiling override, in bytes. Absent = the built-in ceiling. */
|
|
10586
|
+
maxBytes: z.number().positive().optional()
|
|
10587
|
+
}), HfModelResolutionSchema, {
|
|
10588
|
+
kind: "mutation",
|
|
10589
|
+
auth: "admin"
|
|
10590
|
+
}),
|
|
10486
10591
|
installModel: method(z.object({
|
|
10487
10592
|
nodeId: z.string(),
|
|
10488
10593
|
model: ManagedModelRefSchema
|
|
@@ -12620,9 +12725,66 @@ var NcDeviceStateConditionSchema = z.object({
|
|
|
12620
12725
|
/** Any of these matches. */
|
|
12621
12726
|
states: z.array(z.string().min(1)).min(1)
|
|
12622
12727
|
});
|
|
12728
|
+
/**
|
|
12729
|
+
* "This rule applies only while scene `sceneId` is `matched` / `diverged`."
|
|
12730
|
+
*
|
|
12731
|
+
* A GATE, not a trigger. `occupancy` and `audio` each DISCRIMINATE their rule —
|
|
12732
|
+
* carrying one makes the rule fire on that subject and nothing else. Scene is
|
|
12733
|
+
* the other shape entirely, the `deviceState` shape: it narrows a rule that
|
|
12734
|
+
* already has a trigger ("tell me about a person at the front door, but only
|
|
12735
|
+
* while the bin is still out"). That is why it composes with every delivery
|
|
12736
|
+
* instead of owning one, and why no new `NcDelivery` member and no new subject
|
|
12737
|
+
* kind exist for it — see D159.
|
|
12738
|
+
*
|
|
12739
|
+
* ── Identity ───────────────────────────────────────────────────────────────
|
|
12740
|
+
* `sceneId` is `SceneMonitor.id`, a `randomUUID()` minted by `createScene` —
|
|
12741
|
+
* globally unique, so it needs no device to disambiguate it. `deviceId` is
|
|
12742
|
+
* carried as a HINT for the editor and for the log line, never as part of the
|
|
12743
|
+
* lookup key: a rule whose hint drifted must still gate correctly.
|
|
12744
|
+
*
|
|
12745
|
+
* ── Which boolean ──────────────────────────────────────────────────────────
|
|
12746
|
+
* `latched` ABSENT means "whatever the scene itself says" — `SceneMonitor.emit`
|
|
12747
|
+
* already declares which boolean drives notification rules, and a second knob
|
|
12748
|
+
* that could disagree with it is exactly the D62 failure. Set it only to
|
|
12749
|
+
* override one rule against the scene's own default.
|
|
12750
|
+
*
|
|
12751
|
+
* - LIVE reading (`emit`/`latched` resolve to live): passes iff
|
|
12752
|
+
* `verdict === requiredState`. `unknown` — no reference for this light, view
|
|
12753
|
+
* shifted, no snapshot — passes NEITHER. A scene that cannot judge is not
|
|
12754
|
+
* evidence, in either direction.
|
|
12755
|
+
* - LATCHED reading: passes iff `latched === (requiredState === 'diverged')`.
|
|
12756
|
+
* The latch is a durable fact about the past ("it has diverged since I armed
|
|
12757
|
+
* it"), so a camera that has gone dark does not clear it — that is the whole
|
|
12758
|
+
* reason the operator asked for a latch.
|
|
12759
|
+
*
|
|
12760
|
+
* The gate reads an in-memory mirror (`NcSceneStateCache`) refreshed OFF the
|
|
12761
|
+
* event path, never the cap: D49. A mirror that has never loaded, or a scene it
|
|
12762
|
+
* does not carry, reads absent and the rule does NOT fire — fail closed, and
|
|
12763
|
+
* said out loud in the log rather than dropped in silence.
|
|
12764
|
+
*/
|
|
12765
|
+
var NcSceneConditionSchema = z.object({
|
|
12766
|
+
/** `SceneMonitor.id` — the uuid the cap mints. The whole lookup key. */
|
|
12767
|
+
sceneId: z.string().min(1),
|
|
12768
|
+
/** The camera the scene lives on. A hint for the editor and the log line. */
|
|
12769
|
+
deviceId: z.number().int().optional(),
|
|
12770
|
+
/** The state the scene must be in for the rule to fire. */
|
|
12771
|
+
requiredState: z.enum(["matched", "diverged"]),
|
|
12772
|
+
/**
|
|
12773
|
+
* Read the LATCH (`true`) or the LIVE verdict (`false`). Absent = follow the
|
|
12774
|
+
* scene's own `emit` field, which is the only place that decision belongs.
|
|
12775
|
+
*/
|
|
12776
|
+
latched: z.boolean().optional()
|
|
12777
|
+
});
|
|
12623
12778
|
var NcConditionsSchema = z.object({
|
|
12624
12779
|
/** Gate on ANOTHER device's current state (the alarm armed, a switch on). */
|
|
12625
12780
|
deviceState: NcDeviceStateConditionSchema.optional(),
|
|
12781
|
+
/**
|
|
12782
|
+
* Gate on a SCENE's state — "only while the bin is still out". Composes with
|
|
12783
|
+
* every trigger (detection, occupancy, audio, sensor, package, track-end);
|
|
12784
|
+
* unlike `occupancy`/`audio` it discriminates nothing. See
|
|
12785
|
+
* {@link NcSceneCondition} and D159.
|
|
12786
|
+
*/
|
|
12787
|
+
scene: NcSceneConditionSchema.optional(),
|
|
12626
12788
|
/** Device scope — absent = all devices. */
|
|
12627
12789
|
devices: z.array(z.number()).optional(),
|
|
12628
12790
|
/** Detector class names (any overlap with the record's class set). */
|
|
@@ -13260,6 +13422,7 @@ var NcConditionDescriptorSchema = z.object({
|
|
|
13260
13422
|
"occupancy",
|
|
13261
13423
|
"audio",
|
|
13262
13424
|
"deviceState",
|
|
13425
|
+
"scene",
|
|
13263
13426
|
"systemEvent"
|
|
13264
13427
|
]),
|
|
13265
13428
|
operator: z.enum([
|
|
@@ -16485,6 +16648,17 @@ var maxSessionHoldMsField = {
|
|
|
16485
16648
|
default: 12e4,
|
|
16486
16649
|
step: 5e3
|
|
16487
16650
|
};
|
|
16651
|
+
/**
|
|
16652
|
+
* Quiet period that closes an `audioMode: 'on-motion'` audio window. Floor of
|
|
16653
|
+
* 5s so a rearm can never degenerate into per-event stream churn; default 90s
|
|
16654
|
+
* comfortably outlives the gap between two PIR wakes on a battery camera.
|
|
16655
|
+
*/
|
|
16656
|
+
var audioMotionWindowMsField = {
|
|
16657
|
+
min: 5e3,
|
|
16658
|
+
max: 6e5,
|
|
16659
|
+
default: 9e4,
|
|
16660
|
+
step: 5e3
|
|
16661
|
+
};
|
|
16488
16662
|
var motionFpsField = {
|
|
16489
16663
|
min: 1,
|
|
16490
16664
|
max: 30,
|
|
@@ -16661,6 +16835,27 @@ var RunnerCameraConfigSchema = z.object({
|
|
|
16661
16835
|
* resolved `CameraDetectionConfig`.
|
|
16662
16836
|
*/
|
|
16663
16837
|
maxSessionHoldMs: z.number().min(maxSessionHoldMsField.min).max(maxSessionHoldMsField.max).optional(),
|
|
16838
|
+
/**
|
|
16839
|
+
* Orchestrator-side quiet period (ms) that closes an `audioMode:
|
|
16840
|
+
* 'on-motion'` audio window, measured from the LAST motion event.
|
|
16841
|
+
*
|
|
16842
|
+
* This exists because the falling edge cannot be relied on. Camera-native
|
|
16843
|
+
* providers emit motion as a RISING EDGE ONLY (Reolink's Baichuan push and
|
|
16844
|
+
* its email-push SMTP path both emit `detected: true` and never the
|
|
16845
|
+
* counterpart); only the frame-diff analyzer emits falls. So on an
|
|
16846
|
+
* onboard-only camera a window that closed only on `detected: false` never
|
|
16847
|
+
* closed at all, and `on-motion` silently behaved as `always-on` — on a
|
|
16848
|
+
* battery camera, the one failure mode the mode exists to prevent.
|
|
16849
|
+
*
|
|
16850
|
+
* Every motion event rearms this timer WITHOUT restarting the stream, so a
|
|
16851
|
+
* burst of re-fires costs nothing. A falling edge, when one does arrive,
|
|
16852
|
+
* still closes earlier via `motionCooldownMs` — whichever comes first wins.
|
|
16853
|
+
*
|
|
16854
|
+
* Not consumed by the runner: carried here so it shares the per-camera
|
|
16855
|
+
* device-settings surface with `motionCooldownMs`, exactly like
|
|
16856
|
+
* `maxSessionHoldMs`.
|
|
16857
|
+
*/
|
|
16858
|
+
audioMotionWindowMs: z.number().min(audioMotionWindowMsField.min).max(audioMotionWindowMsField.max).optional(),
|
|
16664
16859
|
motionFps: z.number().min(motionFpsField.min).max(motionFpsField.max).default(motionFpsField.default),
|
|
16665
16860
|
detectionFps: z.number().min(detectionFpsField.min).max(detectionFpsField.max).default(detectionFpsField.default),
|
|
16666
16861
|
motionStreamId: z.string(),
|
|
@@ -16756,7 +16951,7 @@ var RunnerCameraConfigSchema = z.object({
|
|
|
16756
16951
|
*/
|
|
16757
16952
|
inferenceDevices: z.array(RunnerInferenceDeviceSchema).readonly().optional()
|
|
16758
16953
|
});
|
|
16759
|
-
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;
|
|
16954
|
+
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;
|
|
16760
16955
|
/**
|
|
16761
16956
|
* Runtime load summary returned by `getLocalLoad`. Used by the orchestrator's
|
|
16762
16957
|
* load-balancing levels (L2 capacity-based, L3 hardware-aware) to decide
|
|
@@ -26788,6 +26983,33 @@ var recordingExportCapability = {
|
|
|
26788
26983
|
* as `unknown`, never guessed. A day reference scored against an IR frame
|
|
26789
26984
|
* collapses the cosine and would latch a false alarm every single night. */
|
|
26790
26985
|
var SceneConditionSchema = z.string();
|
|
26986
|
+
/**
|
|
26987
|
+
* What a scene does when the CURRENT light has no reference of its own.
|
|
26988
|
+
*
|
|
26989
|
+
* The lighting variants are not equally likely to exist. Almost every operator
|
|
26990
|
+
* captures daylight and then never stands outside at 22:00 to capture IR, and a
|
|
26991
|
+
* scene that is only ever going to be asked about a daytime question ("is the
|
|
26992
|
+
* bin still on the kerb at 08:00") does not need a night reference at all. The
|
|
26993
|
+
* night half must therefore be OPTIONAL, and optional means the scene keeps
|
|
26994
|
+
* working without it rather than degrading into a permanent complaint.
|
|
26995
|
+
*
|
|
26996
|
+
* - `skip` (default) — the check in that light is not made. Not a verdict, not
|
|
26997
|
+
* an alarm, not even an `unknown`: the live state simply stays whatever the
|
|
26998
|
+
* last covered light left it at, the latch is untouched, and the hysteresis
|
|
26999
|
+
* run is neither spent nor cleared. The scene resumes by itself at first
|
|
27000
|
+
* light. This is the only behaviour under which "I never captured IR" is a
|
|
27001
|
+
* configuration choice instead of a nightly fault.
|
|
27002
|
+
* - `judge-anyway` — score against the OTHER conditions' references. Available
|
|
27003
|
+
* for cameras whose IR frame is close enough to daylight (a floodlit
|
|
27004
|
+
* driveway, an always-white-light doorbell), and wrong for everything else:
|
|
27005
|
+
* cross-condition cosines are not comparable, so a day reference against a
|
|
27006
|
+
* true IR frame collapses and the scene reports a theft at 21:40.
|
|
27007
|
+
*
|
|
27008
|
+
* Never applies when the scene has NO comparable reference at all — that is
|
|
27009
|
+
* "not armed yet", it is reported as `no-reference-for-condition`, and silence
|
|
27010
|
+
* there would hide a scene the operator never finished setting up.
|
|
27011
|
+
*/
|
|
27012
|
+
var SceneUncoveredPolicySchema = z.enum(["skip", "judge-anyway"]);
|
|
26791
27013
|
/** `matched` = the baseline is what we see; `diverged` = it demonstrably is not;
|
|
26792
27014
|
* `unknown` = we cannot judge (no reference for this condition, encoder model
|
|
26793
27015
|
* changed, view shifted, no snapshot). `unknown` is a real value, not a null,
|
|
@@ -26843,6 +27065,9 @@ var SceneCheckSchema = z.discriminatedUnion("mode", [z.object({
|
|
|
26843
27065
|
hysteresisCount: z.number().int().positive()
|
|
26844
27066
|
})]);
|
|
26845
27067
|
var SCENE_DEFAULT_ANCHOR_THRESHOLD = .85;
|
|
27068
|
+
/** Night is OPTIONAL. A scene with only a daylight reference sits the IR hours
|
|
27069
|
+
* out in silence rather than reporting a fault every night. */
|
|
27070
|
+
var SCENE_DEFAULT_UNCOVERED_POLICY = "skip";
|
|
26846
27071
|
/**
|
|
26847
27072
|
* Vision-model adjudication of a candidate flip. Field names deliberately
|
|
26848
27073
|
* mirror `NcConfirmSchema` so an operator meets one vocabulary, not two.
|
|
@@ -26909,6 +27134,21 @@ var SceneMonitorSchema = z.object({
|
|
|
26909
27134
|
* automation can react to the bin coming back without the operator's own
|
|
26910
27135
|
* alarm silently clearing itself. */
|
|
26911
27136
|
autoRestore: z.boolean().default(false),
|
|
27137
|
+
/** What to do when the current light has no reference of its own. See
|
|
27138
|
+
* {@link SceneUncoveredPolicySchema} — the default makes night OPTIONAL. */
|
|
27139
|
+
onUncoveredCondition: SceneUncoveredPolicySchema.default(SCENE_DEFAULT_UNCOVERED_POLICY),
|
|
27140
|
+
/**
|
|
27141
|
+
* The light whose checks are currently being SAT OUT under
|
|
27142
|
+
* `onUncoveredCondition: 'skip'` — `null` when the scene is checking normally.
|
|
27143
|
+
*
|
|
27144
|
+
* Engine-reported and advisory only: it moves no verdict, no latch and no
|
|
27145
|
+
* hysteresis. It exists so the card can say *"night (IR) — checks paused,
|
|
27146
|
+
* nothing captured in this light"* in the same calm voice as the coverage
|
|
27147
|
+
* line, because the alternative is a scene that silently stops answering
|
|
27148
|
+
* after sunset with nothing anywhere saying why. A skipped check must never
|
|
27149
|
+
* read as a broken one.
|
|
27150
|
+
*/
|
|
27151
|
+
suspendedCondition: SceneConditionSchema.nullable().default(null),
|
|
26912
27152
|
/** Named cause when `verdict === 'unknown'`. */
|
|
26913
27153
|
unavailable: SceneUnavailableSchema.nullable(),
|
|
26914
27154
|
/** Conditions that have at least one comparable reference — the coverage line
|
|
@@ -26962,6 +27202,7 @@ var sceneMonitorCapability = {
|
|
|
26962
27202
|
minObservationSpacingSec: z.number().int().min(0).max(3600).optional(),
|
|
26963
27203
|
anchorThreshold: z.number().min(0).max(1).optional(),
|
|
26964
27204
|
autoRestore: z.boolean().optional(),
|
|
27205
|
+
onUncoveredCondition: SceneUncoveredPolicySchema.optional(),
|
|
26965
27206
|
/** `null` clears the vision-model adjudicator. */
|
|
26966
27207
|
confirm: SceneConfirmSchema.nullable().optional()
|
|
26967
27208
|
})
|
|
@@ -31707,6 +31948,12 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
31707
31948
|
addonId: null,
|
|
31708
31949
|
access: "view"
|
|
31709
31950
|
},
|
|
31951
|
+
"llm.resolveModelRef": {
|
|
31952
|
+
capName: "llm",
|
|
31953
|
+
capScope: "system",
|
|
31954
|
+
addonId: null,
|
|
31955
|
+
access: "create"
|
|
31956
|
+
},
|
|
31710
31957
|
"llm.setDefault": {
|
|
31711
31958
|
capName: "llm",
|
|
31712
31959
|
capScope: "system",
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_chunk = require("./chunk-Cek0wNdY.js");
|
|
3
|
-
const require_dist = require("./dist-
|
|
3
|
+
const require_dist = require("./dist-BH2tZ9ZN.js");
|
|
4
4
|
const require_builtins_alerts_alerts_addon = require("./builtins/alerts/alerts.addon.js");
|
|
5
5
|
require("./builtins/alerts/index.js");
|
|
6
6
|
const require_formatter = require("./formatter-DqAKDlvN.js");
|
|
@@ -25,7 +25,7 @@ const require_builtins_system_config_system_config_addon = require("./builtins/s
|
|
|
25
25
|
require("./builtins/system-config/index.js");
|
|
26
26
|
const require_builtins_winston_logging_index = require("./builtins/winston-logging/index.js");
|
|
27
27
|
const require_file_data_plane = require("./file-data-plane-DUHPHa-Y.js");
|
|
28
|
-
const require_manifest_python_deps = require("./manifest-python-deps-
|
|
28
|
+
const require_manifest_python_deps = require("./manifest-python-deps-BZO_eMn-.js");
|
|
29
29
|
const require_resource_monitor = require("./resource-monitor-CdnzxBLP.js");
|
|
30
30
|
const require_custom_action_registry = require("./custom-action-registry-jY0NOZK8.js");
|
|
31
31
|
let zod = require("zod");
|
|
@@ -1181,6 +1181,11 @@ var LogManager = class {
|
|
|
1181
1181
|
subscribers = /* @__PURE__ */ new Map();
|
|
1182
1182
|
deviceNameLookup = null;
|
|
1183
1183
|
/**
|
|
1184
|
+
* The bootstrap stdout sink, while one is attached. Detached — and its
|
|
1185
|
+
* replay suppressed — when {@link STDOUT_DESTINATION_ADDON_ID} registers.
|
|
1186
|
+
*/
|
|
1187
|
+
bootstrapConsole = null;
|
|
1188
|
+
/**
|
|
1184
1189
|
* `perAddonCapacity` bounds EACH addon's bucket, not the total — a chatty addon
|
|
1185
1190
|
* evicts only its own lines, so quiet addons keep their sparse history.
|
|
1186
1191
|
*
|
|
@@ -1282,13 +1287,34 @@ var LogManager = class {
|
|
|
1282
1287
|
setDestinationEnabledCheck(check) {
|
|
1283
1288
|
this.isDestinationEnabled = check ?? void 0;
|
|
1284
1289
|
}
|
|
1290
|
+
/**
|
|
1291
|
+
* Attach a minimal console sink that carries the boot log until the real
|
|
1292
|
+
* `console-logging` builtin registers — see {@link STDOUT_DESTINATION_ADDON_ID}.
|
|
1293
|
+
*
|
|
1294
|
+
* Registered WITHOUT an `addonId` on purpose: the per-destination toggle
|
|
1295
|
+
* could otherwise hide the one window an operator cannot read any other way
|
|
1296
|
+
* (a hub that dies before pass 3 would emit nothing at all). It is detached
|
|
1297
|
+
* the moment the stdout owner arrives, so stdout never carries two copies.
|
|
1298
|
+
*
|
|
1299
|
+
* Idempotent: a second call while one is attached is a no-op.
|
|
1300
|
+
*/
|
|
1301
|
+
attachBootstrapConsole(dest) {
|
|
1302
|
+
if (this.bootstrapConsole !== null) return;
|
|
1303
|
+
this.bootstrapConsole = dest;
|
|
1304
|
+
this.destinations.push({ dest });
|
|
1305
|
+
}
|
|
1285
1306
|
addDestination(dest, opts = {}) {
|
|
1286
|
-
const
|
|
1307
|
+
const supersedesBootstrap = this.bootstrapConsole !== null && opts.addonId === "console-logging";
|
|
1308
|
+
if (supersedesBootstrap && this.bootstrapConsole !== null) {
|
|
1309
|
+
this.removeDestination(this.bootstrapConsole);
|
|
1310
|
+
this.bootstrapConsole = null;
|
|
1311
|
+
}
|
|
1312
|
+
const replay = opts.replay ?? !supersedesBootstrap;
|
|
1287
1313
|
this.destinations.push(opts.addonId === void 0 ? { dest } : {
|
|
1288
1314
|
dest,
|
|
1289
1315
|
addonId: opts.addonId
|
|
1290
1316
|
});
|
|
1291
|
-
if (replay) for (const entry of this.ringBuffer.query({})) try {
|
|
1317
|
+
if (replay) for (const entry of [...this.ringBuffer.query({})].reverse()) try {
|
|
1292
1318
|
dest.write(entry);
|
|
1293
1319
|
} catch {}
|
|
1294
1320
|
}
|
|
@@ -93941,9 +93967,18 @@ function createStreamProbeBrokerService(deps) {
|
|
|
93941
93967
|
*/
|
|
93942
93968
|
var HEALTH_MONITOR_TICK_MS = 3e4;
|
|
93943
93969
|
var HEALTH_MONITOR_GRACE_PERIOD_MS = 5 * 6e4;
|
|
93944
|
-
/**
|
|
93970
|
+
/**
|
|
93971
|
+
* Retry intervals after each failure (capped — never stops).
|
|
93972
|
+
*
|
|
93973
|
+
* The FIRST interval must not exceed {@link HEALTH_MONITOR_TICK_MS}: retries can
|
|
93974
|
+
* only fire on a tick, so anything larger just adds latency on top of a wait the
|
|
93975
|
+
* tick already imposes. It used to be 60 s, which meant an addon that failed to
|
|
93976
|
+
* load because the boot was still moving files around stayed down for 60–90 s
|
|
93977
|
+
* — a schedule that presumed a healthy hub (docs/design/boot-to-usable-camera.md,
|
|
93978
|
+
* item E). Pinned by `addon-health-monitor.spec.ts`.
|
|
93979
|
+
*/
|
|
93945
93980
|
var HEALTH_MONITOR_RETRY_INTERVALS_MS = [
|
|
93946
|
-
|
|
93981
|
+
3e4,
|
|
93947
93982
|
12e4,
|
|
93948
93983
|
3e5
|
|
93949
93984
|
];
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as __toCommonJS, i as __require, n as __esmMin, o as __toESM$1, r as __exportAll, t as __commonJSMin$1 } from "./chunk-CNf5ZN-e.mjs";
|
|
2
|
-
import { $ as objectInputDeclaresAddonId, At as createEvent, B as isArrayOutputSchema, Bt as resolveCapMount, Dt as asJsonObject$1, G as kebabToCamel, H as isObjectInput, K as lifecycleJobSchema, Lt as parseJsonObject, Nt as expandCapMethods, Ot as asNumber, R as extractNestedAddonId, Rt as parseJsonUnknown$1, Tt as ReadinessTimeoutError, Ut as EventCategory$1, V as isCollectionArrayMethod, Vt as scopeKey, W as isVoidInput, X as looseSchema, Y as logLevelAtMost, at as scopesAllowDeviceCap, bt as DEVICE_STATUS_METHOD, d as METHOD_ACCESS_MAP, f as RUNTIME_DEFAULTS, gt as errMsg$1, it as scopesAllowAddon, jt as emitDownForOwnedCaps, kt as asString$1, nt as procedureAuthKey, t as ALL_CAPABILITY_DEFINITIONS, vt as DATAPLANE_SECRET_HEADER$1, wt as ReadinessRegistry, y as addonSettingsCapability, yt as DEVICE_SETTINGS_CONTRIBUTION_METHODS, zt as readinessKey } from "./dist-
|
|
2
|
+
import { $ as objectInputDeclaresAddonId, At as createEvent, B as isArrayOutputSchema, Bt as resolveCapMount, Dt as asJsonObject$1, G as kebabToCamel, H as isObjectInput, K as lifecycleJobSchema, Lt as parseJsonObject, Nt as expandCapMethods, Ot as asNumber, R as extractNestedAddonId, Rt as parseJsonUnknown$1, Tt as ReadinessTimeoutError, Ut as EventCategory$1, V as isCollectionArrayMethod, Vt as scopeKey, W as isVoidInput, X as looseSchema, Y as logLevelAtMost, at as scopesAllowDeviceCap, bt as DEVICE_STATUS_METHOD, d as METHOD_ACCESS_MAP, f as RUNTIME_DEFAULTS, gt as errMsg$1, it as scopesAllowAddon, jt as emitDownForOwnedCaps, kt as asString$1, nt as procedureAuthKey, t as ALL_CAPABILITY_DEFINITIONS, vt as DATAPLANE_SECRET_HEADER$1, wt as ReadinessRegistry, y as addonSettingsCapability, yt as DEVICE_SETTINGS_CONTRIBUTION_METHODS, zt as readinessKey } from "./dist-DXDvrBi0.mjs";
|
|
3
3
|
import { AlertCenterAddon } from "./builtins/alerts/alerts.addon.mjs";
|
|
4
4
|
import "./builtins/alerts/index.mjs";
|
|
5
5
|
import { t as formatLogLine } from "./formatter-B7qW8bPJ.mjs";
|
|
@@ -24,7 +24,7 @@ import { SystemConfigAddon } from "./builtins/system-config/system-config.addon.
|
|
|
24
24
|
import "./builtins/system-config/index.mjs";
|
|
25
25
|
import { WinstonDestination, WinstonLoggingAddon } from "./builtins/winston-logging/index.mjs";
|
|
26
26
|
import { a as parseTokenizedUrl, c as collectModelFiles, d as downloadModel, f as ensureModel, h as isModelDownloaded, i as parseRangeHeader, l as deleteModelFromDisk, m as getModelFilePath, n as contentTypeFor, o as resolveFilePath, p as fetchJson, r as createAuthenticatedFileServer, s as ModelDownloadService, t as createFileDataPlaneHandler, u as downloadFile } from "./file-data-plane-CuE_hBli.mjs";
|
|
27
|
-
import { $ as buildNativeCapProxy, A as createHubCapForwardService, B as AGENT_CAP_FWD_ACTION, C as brokerTransportLink, Ct as runNpm, D as localProviderLink, E as ipcParentLink, F as createUdsLogger, G as callWithServiceDiscovery, H as CapRouteResolver, I as createUdsLoggerWithControl, J as UdsLocalTransportServer, K as createLocalTransport, L as LocalChildClient, M as createUdsEventBridge, N as createUdsEventBus, O as HUB_CAP_FWD_ACTION, P as udsChildLogToWorkerEntry, Q as encodeFrame, R as LocalChildRegistry, S as brokerCallForCap, St as resolveNpmInvocation, T as ipcChildLink, U as CapRouteError, V as AGENT_CAP_FWD_SERVICE, W as classifyCapRoute, X as localEndpointPath, Y as SocketChannel, Z as FrameDecoder, _ as createKernelHwAccel, _t as CapabilityHandle, a as getWorkerDeviceRegistry, b as __resetCapUsageRegistryForTests, bt as installManifestNativeDeps, c as setHubConnected, ct as NATIVE_PROVIDER_SERVICE_INFIX, d as getBrokerEventBus, dt as capBareAction, et as buildUdsNativeCapProxy, f as getMoleculerEventStats, ft as capServiceName, g as AddonDepsManager, gt as DeviceRegistry, h as subscribePassthrough, ht as serializeTypedArrays, i as createUdsAddonContext, it as mountNativeCapService, j as createParentUnownedCallHandler, k as HUB_CAP_FWD_SERVICE, l as EVENT_TOPIC_PREFIX, lt as capActionName, m as setNodeEventInterest, mt as deserializeTypedArrays, n as adaptBrokerToCluster, o as getOrInitReadinessRegistry, ot as createAddonService, p as registerEventBusService, pt as parseCapAction, q as UdsLocalTransportClient, r as createAddonContext, s as getOrInitReadinessRegistryForClient, st as validateProviderRegistrations, t as installManifestPythonDeps, tt as createBrokerDeviceManagerApi, u as clusterEventTopic, ut as capActionSuffix, v as resolveHwAccel, vt as CapabilityUnavailableError, w as buildLinkChain, wt as createAddonDataPlaneFacility, x as getCapUsageRegistry, xt as resolveAddonClass, y as CapUsageRegistry, yt as copyBundledNativeModules, z as UDS_NO_ROUTE_PREFIX } from "./manifest-python-deps-
|
|
27
|
+
import { $ as buildNativeCapProxy, A as createHubCapForwardService, B as AGENT_CAP_FWD_ACTION, C as brokerTransportLink, Ct as runNpm, D as localProviderLink, E as ipcParentLink, F as createUdsLogger, G as callWithServiceDiscovery, H as CapRouteResolver, I as createUdsLoggerWithControl, J as UdsLocalTransportServer, K as createLocalTransport, L as LocalChildClient, M as createUdsEventBridge, N as createUdsEventBus, O as HUB_CAP_FWD_ACTION, P as udsChildLogToWorkerEntry, Q as encodeFrame, R as LocalChildRegistry, S as brokerCallForCap, St as resolveNpmInvocation, T as ipcChildLink, U as CapRouteError, V as AGENT_CAP_FWD_SERVICE, W as classifyCapRoute, X as localEndpointPath, Y as SocketChannel, Z as FrameDecoder, _ as createKernelHwAccel, _t as CapabilityHandle, a as getWorkerDeviceRegistry, b as __resetCapUsageRegistryForTests, bt as installManifestNativeDeps, c as setHubConnected, ct as NATIVE_PROVIDER_SERVICE_INFIX, d as getBrokerEventBus, dt as capBareAction, et as buildUdsNativeCapProxy, f as getMoleculerEventStats, ft as capServiceName, g as AddonDepsManager, gt as DeviceRegistry, h as subscribePassthrough, ht as serializeTypedArrays, i as createUdsAddonContext, it as mountNativeCapService, j as createParentUnownedCallHandler, k as HUB_CAP_FWD_SERVICE, l as EVENT_TOPIC_PREFIX, lt as capActionName, m as setNodeEventInterest, mt as deserializeTypedArrays, n as adaptBrokerToCluster, o as getOrInitReadinessRegistry, ot as createAddonService, p as registerEventBusService, pt as parseCapAction, q as UdsLocalTransportClient, r as createAddonContext, s as getOrInitReadinessRegistryForClient, st as validateProviderRegistrations, t as installManifestPythonDeps, tt as createBrokerDeviceManagerApi, u as clusterEventTopic, ut as capActionSuffix, v as resolveHwAccel, vt as CapabilityUnavailableError, w as buildLinkChain, wt as createAddonDataPlaneFacility, x as getCapUsageRegistry, xt as resolveAddonClass, y as CapUsageRegistry, yt as copyBundledNativeModules, z as UDS_NO_ROUTE_PREFIX } from "./manifest-python-deps-D3hP9W8D.mjs";
|
|
28
28
|
import { n as getSinglePidStats, t as getPidStats } from "./resource-monitor-BWmQ5i-o.mjs";
|
|
29
29
|
import { t as CustomActionRegistry } from "./custom-action-registry-F__gp_VX.mjs";
|
|
30
30
|
import { z } from "zod";
|
|
@@ -1173,6 +1173,11 @@ var LogManager = class {
|
|
|
1173
1173
|
subscribers = /* @__PURE__ */ new Map();
|
|
1174
1174
|
deviceNameLookup = null;
|
|
1175
1175
|
/**
|
|
1176
|
+
* The bootstrap stdout sink, while one is attached. Detached — and its
|
|
1177
|
+
* replay suppressed — when {@link STDOUT_DESTINATION_ADDON_ID} registers.
|
|
1178
|
+
*/
|
|
1179
|
+
bootstrapConsole = null;
|
|
1180
|
+
/**
|
|
1176
1181
|
* `perAddonCapacity` bounds EACH addon's bucket, not the total — a chatty addon
|
|
1177
1182
|
* evicts only its own lines, so quiet addons keep their sparse history.
|
|
1178
1183
|
*
|
|
@@ -1274,13 +1279,34 @@ var LogManager = class {
|
|
|
1274
1279
|
setDestinationEnabledCheck(check) {
|
|
1275
1280
|
this.isDestinationEnabled = check ?? void 0;
|
|
1276
1281
|
}
|
|
1282
|
+
/**
|
|
1283
|
+
* Attach a minimal console sink that carries the boot log until the real
|
|
1284
|
+
* `console-logging` builtin registers — see {@link STDOUT_DESTINATION_ADDON_ID}.
|
|
1285
|
+
*
|
|
1286
|
+
* Registered WITHOUT an `addonId` on purpose: the per-destination toggle
|
|
1287
|
+
* could otherwise hide the one window an operator cannot read any other way
|
|
1288
|
+
* (a hub that dies before pass 3 would emit nothing at all). It is detached
|
|
1289
|
+
* the moment the stdout owner arrives, so stdout never carries two copies.
|
|
1290
|
+
*
|
|
1291
|
+
* Idempotent: a second call while one is attached is a no-op.
|
|
1292
|
+
*/
|
|
1293
|
+
attachBootstrapConsole(dest) {
|
|
1294
|
+
if (this.bootstrapConsole !== null) return;
|
|
1295
|
+
this.bootstrapConsole = dest;
|
|
1296
|
+
this.destinations.push({ dest });
|
|
1297
|
+
}
|
|
1277
1298
|
addDestination(dest, opts = {}) {
|
|
1278
|
-
const
|
|
1299
|
+
const supersedesBootstrap = this.bootstrapConsole !== null && opts.addonId === "console-logging";
|
|
1300
|
+
if (supersedesBootstrap && this.bootstrapConsole !== null) {
|
|
1301
|
+
this.removeDestination(this.bootstrapConsole);
|
|
1302
|
+
this.bootstrapConsole = null;
|
|
1303
|
+
}
|
|
1304
|
+
const replay = opts.replay ?? !supersedesBootstrap;
|
|
1279
1305
|
this.destinations.push(opts.addonId === void 0 ? { dest } : {
|
|
1280
1306
|
dest,
|
|
1281
1307
|
addonId: opts.addonId
|
|
1282
1308
|
});
|
|
1283
|
-
if (replay) for (const entry of this.ringBuffer.query({})) try {
|
|
1309
|
+
if (replay) for (const entry of [...this.ringBuffer.query({})].reverse()) try {
|
|
1284
1310
|
dest.write(entry);
|
|
1285
1311
|
} catch {}
|
|
1286
1312
|
}
|
|
@@ -93933,9 +93959,18 @@ function createStreamProbeBrokerService(deps) {
|
|
|
93933
93959
|
*/
|
|
93934
93960
|
var HEALTH_MONITOR_TICK_MS = 3e4;
|
|
93935
93961
|
var HEALTH_MONITOR_GRACE_PERIOD_MS = 5 * 6e4;
|
|
93936
|
-
/**
|
|
93962
|
+
/**
|
|
93963
|
+
* Retry intervals after each failure (capped — never stops).
|
|
93964
|
+
*
|
|
93965
|
+
* The FIRST interval must not exceed {@link HEALTH_MONITOR_TICK_MS}: retries can
|
|
93966
|
+
* only fire on a tick, so anything larger just adds latency on top of a wait the
|
|
93967
|
+
* tick already imposes. It used to be 60 s, which meant an addon that failed to
|
|
93968
|
+
* load because the boot was still moving files around stayed down for 60–90 s
|
|
93969
|
+
* — a schedule that presumed a healthy hub (docs/design/boot-to-usable-camera.md,
|
|
93970
|
+
* item E). Pinned by `addon-health-monitor.spec.ts`.
|
|
93971
|
+
*/
|
|
93937
93972
|
var HEALTH_MONITOR_RETRY_INTERVALS_MS = [
|
|
93938
|
-
|
|
93973
|
+
3e4,
|
|
93939
93974
|
12e4,
|
|
93940
93975
|
3e5
|
|
93941
93976
|
];
|
|
@@ -35,7 +35,16 @@ import { IEventBus, IScopedLogger } from '@camstack/types';
|
|
|
35
35
|
*/
|
|
36
36
|
export declare const HEALTH_MONITOR_TICK_MS = 30000;
|
|
37
37
|
export declare const HEALTH_MONITOR_GRACE_PERIOD_MS: number;
|
|
38
|
-
/**
|
|
38
|
+
/**
|
|
39
|
+
* Retry intervals after each failure (capped — never stops).
|
|
40
|
+
*
|
|
41
|
+
* The FIRST interval must not exceed {@link HEALTH_MONITOR_TICK_MS}: retries can
|
|
42
|
+
* only fire on a tick, so anything larger just adds latency on top of a wait the
|
|
43
|
+
* tick already imposes. It used to be 60 s, which meant an addon that failed to
|
|
44
|
+
* load because the boot was still moving files around stayed down for 60–90 s
|
|
45
|
+
* — a schedule that presumed a healthy hub (docs/design/boot-to-usable-camera.md,
|
|
46
|
+
* item E). Pinned by `addon-health-monitor.spec.ts`.
|
|
47
|
+
*/
|
|
39
48
|
export declare const HEALTH_MONITOR_RETRY_INTERVALS_MS: readonly number[];
|
|
40
49
|
export type AddonHealthPhase = 'pending' | 'healthy' | 'failed';
|
|
41
50
|
export interface AddonHealthState {
|
|
@@ -14,6 +14,17 @@ export interface ILogDestination {
|
|
|
14
14
|
* SAME orchestrator toggle as every other destination.
|
|
15
15
|
*/
|
|
16
16
|
export declare const LOG_BUFFER_DESTINATION_ID = "log-buffer";
|
|
17
|
+
/**
|
|
18
|
+
* The addon that OWNS stdout. Every other shipped destination writes somewhere
|
|
19
|
+
* else (winston is file-only, loki is remote), so this is the single id whose
|
|
20
|
+
* arrival means "the real console is up now".
|
|
21
|
+
*
|
|
22
|
+
* It exists because the console destination is a core builtin that boots after
|
|
23
|
+
* the whole runner plan: a measured hub boot produced no stdout for ~40 s and
|
|
24
|
+
* then flushed the backlog newest-first. {@link LogManager.attachBootstrapConsole}
|
|
25
|
+
* covers that window, and this constant is how the handover is recognised.
|
|
26
|
+
*/
|
|
27
|
+
export declare const STDOUT_DESTINATION_ADDON_ID = "console-logging";
|
|
17
28
|
export declare class LogManager {
|
|
18
29
|
private readonly ringBuffer;
|
|
19
30
|
/**
|
|
@@ -34,6 +45,11 @@ export declare class LogManager {
|
|
|
34
45
|
private isDestinationEnabled?;
|
|
35
46
|
private readonly subscribers;
|
|
36
47
|
private deviceNameLookup;
|
|
48
|
+
/**
|
|
49
|
+
* The bootstrap stdout sink, while one is attached. Detached — and its
|
|
50
|
+
* replay suppressed — when {@link STDOUT_DESTINATION_ADDON_ID} registers.
|
|
51
|
+
*/
|
|
52
|
+
private bootstrapConsole;
|
|
37
53
|
/**
|
|
38
54
|
* `perAddonCapacity` bounds EACH addon's bucket, not the total — a chatty addon
|
|
39
55
|
* evicts only its own lines, so quiet addons keep their sparse history.
|
|
@@ -78,6 +94,18 @@ export declare class LogManager {
|
|
|
78
94
|
}): void;
|
|
79
95
|
/** Set the per-destination enablement check (see {@link isDestinationEnabled}). */
|
|
80
96
|
setDestinationEnabledCheck(check: ((addonId: string) => boolean) | null): void;
|
|
97
|
+
/**
|
|
98
|
+
* Attach a minimal console sink that carries the boot log until the real
|
|
99
|
+
* `console-logging` builtin registers — see {@link STDOUT_DESTINATION_ADDON_ID}.
|
|
100
|
+
*
|
|
101
|
+
* Registered WITHOUT an `addonId` on purpose: the per-destination toggle
|
|
102
|
+
* could otherwise hide the one window an operator cannot read any other way
|
|
103
|
+
* (a hub that dies before pass 3 would emit nothing at all). It is detached
|
|
104
|
+
* the moment the stdout owner arrives, so stdout never carries two copies.
|
|
105
|
+
*
|
|
106
|
+
* Idempotent: a second call while one is attached is a no-op.
|
|
107
|
+
*/
|
|
108
|
+
attachBootstrapConsole(dest: ILogDestination): void;
|
|
81
109
|
addDestination(dest: ILogDestination, opts?: {
|
|
82
110
|
replay?: boolean;
|
|
83
111
|
addonId?: string;
|
|
@@ -1678,13 +1678,7 @@ function createBrokerDeviceManagerApi(opts) {
|
|
|
1678
1678
|
});
|
|
1679
1679
|
return child;
|
|
1680
1680
|
};
|
|
1681
|
-
const PROBE_RETRY_BACKOFF_MS =
|
|
1682
|
-
5 * 6e4,
|
|
1683
|
-
15 * 6e4,
|
|
1684
|
-
30 * 6e4,
|
|
1685
|
-
60 * 6e4,
|
|
1686
|
-
60 * 6e4
|
|
1687
|
-
];
|
|
1681
|
+
const PROBE_RETRY_BACKOFF_MS = _camstack_types_addon.BOOT_RECOVERY_BACKOFF_MS;
|
|
1688
1682
|
const probeRetryTimers = /* @__PURE__ */ new Map();
|
|
1689
1683
|
const cancelProbeRetry = (deviceId) => {
|
|
1690
1684
|
const timer = probeRetryTimers.get(deviceId);
|