@camstack/addon-osd-manager 0.1.137 → 0.1.139

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (18) hide show
  1. package/dist/{MotionZonesSettings-B4onRgUN.mjs → MotionZonesSettings-CG1jsdMo.mjs} +2 -2
  2. package/dist/{PrivacyMaskSettings-15mTDT2b.mjs → PrivacyMaskSettings-mBWMKyY2.mjs} +4 -4
  3. package/dist/{SceneMonitorEditor-DFU0p0mQ.mjs → SceneMonitorEditor-C_L1sFhf.mjs} +3 -3
  4. package/dist/_stub.js +10 -10
  5. package/dist/{_virtual_mf-localSharedImportMap___mfe_internal__addon_osd_manager_page-CGBPavbq.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_osd_manager_page-COPuIhJm.mjs} +3 -3
  6. package/dist/_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-B8-UPDOD.mjs +26 -0
  7. package/dist/{hostInit-jIJC0_ID.mjs → hostInit-CtlLZppQ.mjs} +2 -2
  8. package/dist/index.js +442 -19
  9. package/dist/index.mjs +442 -19
  10. package/dist/{player-overlays-B_ERqzqj.mjs → player-overlays-Cxv7i44p.mjs} +1 -1
  11. package/dist/remoteEntry.js +1 -1
  12. package/dist/{responsive-BOpuh3Lr.mjs → responsive-BpLjT1Jf.mjs} +1 -1
  13. package/dist/{scene-monitor-copy-D5o6-VNM.mjs → scene-monitor-copy-CglGNTA4.mjs} +1 -1
  14. package/dist/{square-oUeZZbza.mjs → square-CeQEcUQK.mjs} +1 -1
  15. package/dist/{trash-2-BrFLAkuW.mjs → trash-2-D4OQxTrz.mjs} +1 -1
  16. package/dist/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_osd_manager_page__remoteEntry_js-C-OUB_74.mjs → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_osd_manager_page__remoteEntry_js-CJGlrZlS.mjs} +1 -1
  17. package/package.json +1 -1
  18. package/dist/_virtual_mf___mfe_internal__addon_osd_manager_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-CVM3jGoe.mjs +0 -26
package/dist/index.js CHANGED
@@ -5363,7 +5363,7 @@ var ZodIssueCode = {
5363
5363
  var ZodFirstPartyTypeKind;
5364
5364
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5365
5365
  //#endregion
5366
- //#region ../types/dist/sleep-D_4W7xuQ.mjs
5366
+ //#region ../types/dist/sleep-DU7mu4wb.mjs
5367
5367
  /**
5368
5368
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5369
5369
  * window to float samples (D455).
@@ -16742,18 +16742,30 @@ var LlmErrorCodeSchema = _enum([
16742
16742
  "budget-exceeded",
16743
16743
  "adapter-error"
16744
16744
  ]);
16745
- var LlmGenerateResultSchema = discriminatedUnion("ok", [object({
16745
+ var LlmGenerateOkSchema = object({
16746
16746
  ok: literal(true),
16747
16747
  text: string(),
16748
16748
  model: string(),
16749
16749
  usage: LlmUsageSchema,
16750
16750
  truncated: boolean(),
16751
16751
  latencyMs: number()
16752
- }), object({
16752
+ });
16753
+ /**
16754
+ * WHO refused, on a `refusal`. `guardrail` = a safety filter in front of the
16755
+ * model rejected the request before it answered (Apple Foundation Models
16756
+ * refuses surveillance-framed prompts in 0.1 s); `model` = the model itself
16757
+ * declined. They are different faults: a guardrail refusal is a property of
16758
+ * the BACKEND, so the provider falls back to the next profile; a model refusal
16759
+ * is an answer. Absent on every other code, and on a refusal a wire cannot
16760
+ * attribute.
16761
+ */
16762
+ var LlmRefusalSourceSchema = _enum(["guardrail", "model"]);
16763
+ var LlmGenerateResultSchema = discriminatedUnion("ok", [LlmGenerateOkSchema, object({
16753
16764
  ok: literal(false),
16754
16765
  code: LlmErrorCodeSchema,
16755
16766
  message: string(),
16756
- retryAfterMs: number().optional()
16767
+ retryAfterMs: number().optional(),
16768
+ refusalSource: LlmRefusalSourceSchema.optional()
16757
16769
  })]);
16758
16770
  /**
16759
16771
  * `Uint8Array` is the sanctioned binary convention — superjson + the UDS
@@ -16983,6 +16995,77 @@ var LlmRuntimeDiskUsageSchema = object({
16983
16995
  modelsBytes: number(),
16984
16996
  freeBytes: number().optional()
16985
16997
  });
16998
+ var LlmRuntimeCompleteInputSchema = LlmGenerateBaseInputSchema.extend({
16999
+ images: array(LlmImageSchema).optional(),
17000
+ runtime: ManagedRuntimeConfigSchema,
17001
+ /** The managed profile's timeout, threaded by the hub provider. */
17002
+ timeoutMs: number().int().positive().optional()
17003
+ });
17004
+ /**
17005
+ * Why Apple Foundation Models cannot run on a node that has it in principle.
17006
+ * The first three are Apple's own `UnavailableReason`s, verbatim; the rest are
17007
+ * ours: the OS predates the framework (macOS < 26), the helper binary is not
17008
+ * in the installed addon, or it crashed past the respawn bound.
17009
+ */
17010
+ var AppleFmUnavailableReasonSchema = _enum([
17011
+ "deviceNotEligible",
17012
+ "appleIntelligenceNotEnabled",
17013
+ "modelNotReady",
17014
+ "osTooOld",
17015
+ "helperMissing",
17016
+ "helperCrashed"
17017
+ ]);
17018
+ /**
17019
+ * Apple Foundation Models on ONE node — four states, never a boolean (D315).
17020
+ *
17021
+ * - `available` — the helper probed it; what it CAN do is reported
17022
+ * here (`imageInput`, `contextSize`, languages),
17023
+ * never typed by an operator.
17024
+ * - `unavailable` — a known absence, with the reason to act on.
17025
+ * - `unsupported-platform` — not a Mac; there is nothing to enable.
17026
+ * - `unknown` — the probe did not answer (not yet run, timed
17027
+ * out, helper crashed mid-probe). A failed
17028
+ * measurement is NEVER `unavailable` (D393).
17029
+ */
17030
+ var AppleFmAvailabilitySchema = discriminatedUnion("state", [
17031
+ object({
17032
+ state: literal("available"),
17033
+ osVersion: string(),
17034
+ /** Tokens, as the framework reports it. Read at runtime, never assumed. */
17035
+ contextSize: number().int().positive(),
17036
+ /** BCP-47-ish tags (`it-IT`) of the languages the model supports. */
17037
+ languages: array(string()),
17038
+ /** Whether prompts may carry images. `false` on a macOS 26 build. */
17039
+ imageInput: boolean()
17040
+ }),
17041
+ object({
17042
+ state: literal("unavailable"),
17043
+ reason: AppleFmUnavailableReasonSchema,
17044
+ osVersion: string().nullable(),
17045
+ detail: string()
17046
+ }),
17047
+ object({
17048
+ state: literal("unsupported-platform"),
17049
+ platform: string()
17050
+ }),
17051
+ object({
17052
+ state: literal("unknown"),
17053
+ error: string()
17054
+ })
17055
+ ]);
17056
+ /**
17057
+ * A generation on the node's Apple Foundation Models helper. A separate verb
17058
+ * from `complete`, whose `runtime` is a llama.cpp config: overloading it would
17059
+ * drag a GGUF model reference into a backend that has none. `images` is part
17060
+ * of the contract so vision needs no cap change later; a node whose model has
17061
+ * no image input REFUSES them (`unavailable`), never drops them.
17062
+ */
17063
+ var LlmRuntimeAppleCompleteInputSchema = LlmGenerateBaseInputSchema.extend({
17064
+ images: array(LlmImageSchema).optional(),
17065
+ /** The profile's timeout, threaded by the hub provider. */
17066
+ timeoutMs: number().int().positive().optional()
17067
+ });
17068
+ var LlmRuntimeCancelInputSchema = object({ requestId: string() });
16986
17069
  var llmRuntimeCapability = {
16987
17070
  name: "llm-runtime",
16988
17071
  scope: "system",
@@ -17002,12 +17085,7 @@ var llmRuntimeCapability = {
17002
17085
  * nothing; the public `llm` cap (which end users and non-admin sessions
17003
17086
  * legitimately call for chat/generation) is untouched.
17004
17087
  */
17005
- complete: method(LlmGenerateBaseInputSchema.extend({
17006
- images: array(LlmImageSchema).optional(),
17007
- runtime: ManagedRuntimeConfigSchema,
17008
- /** The managed profile's timeout, threaded by the hub provider. */
17009
- timeoutMs: number().int().positive().optional()
17010
- }), LlmGenerateResultSchema, {
17088
+ complete: method(LlmRuntimeCompleteInputSchema, LlmGenerateResultSchema, {
17011
17089
  kind: "mutation",
17012
17090
  auth: "admin",
17013
17091
  timeoutMs: AI_CAP_TRANSPORT_TIMEOUT_MS
@@ -17032,7 +17110,28 @@ var llmRuntimeCapability = {
17032
17110
  auth: "admin"
17033
17111
  }),
17034
17112
  listLocalModels: method(object({}), array(LlmNodeModelSchema), { auth: "admin" }),
17035
- getDiskUsage: method(object({}), LlmRuntimeDiskUsageSchema, { auth: "admin" })
17113
+ getDiskUsage: method(object({}), LlmRuntimeDiskUsageSchema, { auth: "admin" }),
17114
+ /**
17115
+ * Stop a node-side generation started with a `requestId` — `complete` or
17116
+ * `completeApple`. The hub's `llm.cancel` forwards here with the same
17117
+ * nodePin the generation took; before this existed a cancelled
17118
+ * managed-local generation kept running on the node to its own timeout.
17119
+ * Idempotent: an unknown or finished id is a no-op.
17120
+ */
17121
+ cancel: method(LlmRuntimeCancelInputSchema, _void(), {
17122
+ kind: "mutation",
17123
+ auth: "admin"
17124
+ }),
17125
+ /**
17126
+ * This node's Apple Foundation Models state, answered from a mirror the
17127
+ * node refreshes in the background — it never waits on a probe.
17128
+ */
17129
+ appleAvailability: method(object({}), AppleFmAvailabilitySchema, { auth: "admin" }),
17130
+ completeApple: method(LlmRuntimeAppleCompleteInputSchema, LlmGenerateResultSchema, {
17131
+ kind: "mutation",
17132
+ auth: "admin",
17133
+ timeoutMs: AI_CAP_TRANSPORT_TIMEOUT_MS
17134
+ })
17036
17135
  }
17037
17136
  };
17038
17137
  /**
@@ -17051,7 +17150,8 @@ var LlmProfileKindSchema = _enum([
17051
17150
  "openai",
17052
17151
  "anthropic",
17053
17152
  "google",
17054
- "managed-local"
17153
+ "managed-local",
17154
+ "apple-foundation"
17055
17155
  ]);
17056
17156
  var LlmProfileSchema = object({
17057
17157
  id: string(),
@@ -17109,7 +17209,14 @@ var LlmProfileSchema = object({
17109
17209
  toolsEnabled: boolean().default(false),
17110
17210
  extraHeaders: record(string(), string()).optional(),
17111
17211
  /** kind === 'managed-local' only (spec §4). */
17112
- runtime: ManagedRuntimeConfigSchema.optional()
17212
+ runtime: ManagedRuntimeConfigSchema.optional(),
17213
+ /**
17214
+ * kind === 'apple-foundation' only: WHERE it runs — the only thing there is
17215
+ * to configure (no key, no URL, no download; `model` is `apple-system`).
17216
+ * `supportsVision` on such a row is stamped by the provider from the node's
17217
+ * reported `imageInput`, never taken from the operator (D62).
17218
+ */
17219
+ appleFoundation: object({ nodeId: string() }).optional()
17113
17220
  });
17114
17221
  /** ConfigUISchema tree passed through untyped on the wire (the
17115
17222
  * notification-output `ConfigSchemaPassthrough` precedent at
@@ -17191,7 +17298,9 @@ var LlmRuntimeNodeSchema = object({
17191
17298
  reachable: boolean(),
17192
17299
  status: LlmRuntimeStatusSchema.optional(),
17193
17300
  disk: LlmRuntimeDiskUsageSchema.optional(),
17194
- error: string().optional()
17301
+ error: string().optional(),
17302
+ /** Absent = the node did not answer the question (render as unknown). */
17303
+ apple: AppleFmAvailabilitySchema.optional()
17195
17304
  });
17196
17305
  var GenerateVisionInputSchema = LlmGenerateBaseInputSchema.extend({ images: array(LlmImageSchema).min(1) });
17197
17306
  var ProfileRefInputSchema = object({
@@ -19635,6 +19744,16 @@ var NcCrossingSchema = _enum([
19635
19744
  "exit",
19636
19745
  "any"
19637
19746
  ]);
19747
+ /**
19748
+ * Which edge of a BOOLEAN sensor fires a device-event rule (D640).
19749
+ * - `raised` — the sensor went high: water detected, smoke, open, tampered.
19750
+ * - `cleared` — it went back: dry, clear, closed.
19751
+ * - absent — both edges, which is what every rule authored before this did.
19752
+ *
19753
+ * There is no third member for "both": absence already says it, and a value
19754
+ * that means the same as absence is a second way to write one rule.
19755
+ */
19756
+ var NcSensorTransitionSchema = _enum(["raised", "cleared"]);
19638
19757
  /** Admin-zone membership condition (zone IDs as stamped by the ZoneEngine). */
19639
19758
  var NcZoneConditionSchema = object({
19640
19759
  ids: array(string().min(1)).min(1),
@@ -19824,6 +19943,20 @@ var NcConditionsSchema = object({
19824
19943
  scene: NcSceneConditionSchema.optional(),
19825
19944
  /** Device scope — absent = all devices. */
19826
19945
  devices: array(number()).optional(),
19946
+ /**
19947
+ * Device EXCLUSION (D641) — "every device except these". Judged on the SAME
19948
+ * subject ids {@link devices} is judged on (the camera, the sensor that
19949
+ * fired, a linked set's sensor and row cameras), so a sensor fanned out per
19950
+ * linked camera is excluded exactly where an include would have tested it.
19951
+ * `min(1)`: an empty exclusion excludes nothing and is written as absent.
19952
+ *
19953
+ * Not for `system-event` rules — those carry their own
19954
+ * `systemEvent.excludeDeviceIds` (D636), and the hub refuses this key there.
19955
+ * Editors present the two lists as ONE field (All | Only these | All except
19956
+ * these); the engine evaluates each independently, so a legacy rule
19957
+ * carrying both still means "these, minus those".
19958
+ */
19959
+ devicesExclude: array(number()).min(1).optional(),
19827
19960
  /** Detector class names (any overlap with the record's class set). */
19828
19961
  classes: array(string().min(1)).optional(),
19829
19962
  /** Veto classes — any overlap fails the rule. */
@@ -19957,6 +20090,16 @@ var NcConditionsSchema = object({
19957
20090
  */
19958
20091
  sensorKinds: array(string().min(1)).optional(),
19959
20092
  /**
20093
+ * DEVICE-EVENT only (D640). Fire on one edge of a boolean sensor —
20094
+ * {@link NcSensorTransitionSchema}. Which field of the slice means "raised"
20095
+ * is `@camstack/types` → `notification/sensor-raised.ts`. A reading the
20096
+ * engine cannot place (a kind with no raise, an unreadable slice) PASSES:
20097
+ * the condition fails open towards notifying, never towards silence. Editors
20098
+ * offer it only when every chosen {@link sensorKinds} member has a raise
20099
+ * (`sensorTransitionOffered`), and the hub refuses it on any other delivery.
20100
+ */
20101
+ sensorTransition: NcSensorTransitionSchema.optional(),
20102
+ /**
19960
20103
  * PACKAGE-EVENT only. Which package phase fires the rule — `delivered`
19961
20104
  * (a parked parcel appeared), `picked-up` (it departed), or `both`. Fails
19962
20105
  * when the subject's phase does not match (a subject always carries a phase
@@ -20456,9 +20599,29 @@ var NcTestResultSchema = object({
20456
20599
  className: string().optional(),
20457
20600
  label: string().optional()
20458
20601
  });
20459
- /** The five rule kinds, as data. `NcRuleKind` in `notification/rule-kinds.ts`
20460
- * is the same union; the template-vars spec pins the two together. */
20602
+ /** The rule kinds, as data. `NcRuleKind` in `notification/rule-kinds.ts` is the
20603
+ * same union; the template-vars spec pins the two together. `mixed` is DERIVED
20604
+ * (a stored system rule whose kinds span families, D637) and never authored. */
20461
20605
  var NcRuleKindSchema = _enum([
20606
+ "detection",
20607
+ "sensor",
20608
+ "occupancy",
20609
+ "sound",
20610
+ "device-events",
20611
+ "system",
20612
+ "alarm",
20613
+ "mixed"
20614
+ ]);
20615
+ /**
20616
+ * The kinds a SERVED template-variable descriptor may name: the five that
20617
+ * existed before D637, frozen. `getTemplateCatalog` ships `kinds` to every
20618
+ * installed viewer, and a viewer at `@camstack/types` 1.2.25x parses them with a
20619
+ * strict five-member enum — one `device-events` in one descriptor fails the
20620
+ * whole catalog parse. So the WIRE says `system`, and the MATCH widens it:
20621
+ * `templateVarKindApplies` reads a `system` descriptor as applying to every
20622
+ * system rule kind (`device-events`, `system`, `alarm`, `mixed`).
20623
+ */
20624
+ var NcTemplateVarKindSchema = _enum([
20462
20625
  "detection",
20463
20626
  "sensor",
20464
20627
  "occupancy",
@@ -20496,7 +20659,7 @@ var NcTemplateVarGroupSchema = _enum([
20496
20659
  *
20497
20660
  * `families` / `fields` / `kinds` / `deliveries` / `systemEventKinds` say WHERE
20498
20661
  * it has a value; absent = no restriction on that axis. `systemEventKinds` is
20499
- * read only for a `system` rule. `dynamic` declares a FAMILY of names
20662
+ * read only for a system-event rule (any family, or `mixed`). `dynamic` declares a FAMILY of names
20500
20663
  * (`count_<class>`): the descriptor's `name` is the example member.
20501
20664
  */
20502
20665
  var NcTemplateVarDescriptorSchema = object({
@@ -20507,7 +20670,7 @@ var NcTemplateVarDescriptorSchema = object({
20507
20670
  group: NcTemplateVarGroupSchema,
20508
20671
  families: array(NcTemplateFamilySchema).min(1),
20509
20672
  fields: array(NcTemplateFieldSchema).optional(),
20510
- kinds: array(NcRuleKindSchema).optional(),
20673
+ kinds: array(NcTemplateVarKindSchema).optional(),
20511
20674
  deliveries: array(NcDeliverySchema).optional(),
20512
20675
  systemEventKinds: array(NcSystemEventKindSchema).optional(),
20513
20676
  dynamic: object({
@@ -20555,6 +20718,7 @@ var NcConditionDescriptorSchema = object({
20555
20718
  /** Editor widget the UI renders — never hardcode per-condition forms. */
20556
20719
  valueType: _enum([
20557
20720
  "deviceIdList",
20721
+ "deviceIdExcludeList",
20558
20722
  "stringList",
20559
20723
  "number01",
20560
20724
  "number",
@@ -20565,6 +20729,7 @@ var NcConditionDescriptorSchema = object({
20565
20729
  "plateMatcher",
20566
20730
  "packagePhase",
20567
20731
  "crossingSelect",
20732
+ "sensorTransition",
20568
20733
  "polygonDraw",
20569
20734
  "occupancy",
20570
20735
  "audio",
@@ -20763,6 +20928,21 @@ var NC_CONDITION_CATALOG = [
20763
20928
  phase: "P1",
20764
20929
  description: "Restrict the rule to these devices; absent = all devices. A sensor event matches either the SENSOR that fired or the camera it is attributed to, so a rule may name either one."
20765
20930
  },
20931
+ {
20932
+ id: "devicesExclude",
20933
+ group: "scope",
20934
+ label: "Excluded devices",
20935
+ valueType: "deviceIdExcludeList",
20936
+ operator: "notIn",
20937
+ appliesTo: [
20938
+ "immediate",
20939
+ "track-end",
20940
+ "device-event",
20941
+ "package-event"
20942
+ ],
20943
+ phase: "P1",
20944
+ description: "Every device except these. Judged on the same device ids as Devices: a sensor event is excluded by the SENSOR that fired or by the camera it is attributed to."
20945
+ },
20766
20946
  {
20767
20947
  id: "classes",
20768
20948
  group: "class",
@@ -21019,6 +21199,33 @@ var NC_CONDITION_CATALOG = [
21019
21199
  phase: "P1",
21020
21200
  description: "Raw device event-type tokens (e.g. doorbell press / press_long) from the event-emitter slice; absent on doorbell-pulse / passive sensors."
21021
21201
  },
21202
+ {
21203
+ id: "sensorTransition",
21204
+ group: "device",
21205
+ label: "Notify when",
21206
+ valueType: "sensorTransition",
21207
+ options: [
21208
+ {
21209
+ value: "",
21210
+ label: "It triggers and when it clears",
21211
+ hint: "Every change: water detected, and back to dry."
21212
+ },
21213
+ {
21214
+ value: "raised",
21215
+ label: "Only when it triggers",
21216
+ hint: "Water detected, smoke, a contact opening — never the return to normal."
21217
+ },
21218
+ {
21219
+ value: "cleared",
21220
+ label: "Only when it clears",
21221
+ hint: "Back to dry, smoke gone, a contact closing — never the alert itself."
21222
+ }
21223
+ ],
21224
+ operator: "in",
21225
+ appliesTo: ["device-event"],
21226
+ phase: "P2",
21227
+ description: "Fire on one edge of a boolean sensor. Offered only when every chosen sensor kind raises and clears; a reading that cannot be placed still notifies."
21228
+ },
21022
21229
  {
21023
21230
  id: "packagePhase",
21024
21231
  group: "package",
@@ -21202,6 +21409,28 @@ var NcHistoryFilterSchema = object({
21202
21409
  limit: number().int().min(1).max(500).default(100)
21203
21410
  });
21204
21411
  /**
21412
+ * Every rule's last run, in one answer.
21413
+ *
21414
+ * A rule ABSENT from `runs` produced no delivery inside `horizonMs` — how far
21415
+ * back this answer looked, in ms before the hub's now. It is the outbox prune
21416
+ * window (7 days by default, operator-configurable), NARROWED when the read hit
21417
+ * its row bound: the answer never claims a window it did not read. `null` means
21418
+ * the operator keeps the outbox forever AND the read reached its end, so absent
21419
+ * means "never on record". A UI derives its "not in the last N days" from this
21420
+ * value, never from a constant — and only when the call ANSWERED (D315).
21421
+ */
21422
+ var NcRuleLastRunsSchema = object({
21423
+ runs: array(object({
21424
+ ruleId: string(),
21425
+ /** Fire time of the newest row (`createdAt`, epoch ms). */
21426
+ lastAt: number(),
21427
+ status: NcHistoryStatusSchema,
21428
+ /** The camera/device of that row (a digest row files under its first camera). */
21429
+ deviceId: number()
21430
+ })),
21431
+ horizonMs: number().nonnegative().nullable()
21432
+ });
21433
+ /**
21205
21434
  * What a snooze covers. Broader scopes win when several overlap, so one window
21206
21435
  * leaves ONE digest rather than a rule snooze and a whole-feed snooze both
21207
21436
  * summarising the same silence.
@@ -21382,6 +21611,14 @@ var NcAlarmModeCoverageSchema = object({
21382
21611
  /** Ids named by the covering rules. A SUBSET when `allDevices` is true. */
21383
21612
  deviceIds: array(number().int()),
21384
21613
  /**
21614
+ * D641: the ids NOT covered although `allDevices` is true — every unscoped
21615
+ * covering rule EXCLUDES them (`conditions.devicesExclude`) and no named rule
21616
+ * covers them. Always `[]` when `allDevices` is false. Excluded by the rules,
21617
+ * which is not the same as skipped by a switch: never in `skippedDevices`.
21618
+ * Defaulted so an answer computed before this field parses as "none".
21619
+ */
21620
+ allDevicesExcept: array(number().int()).default([]),
21621
+ /**
21385
21622
  * Devices this mode NAMES but cannot actually arm, each with the switch that
21386
21623
  * excludes it.
21387
21624
  *
@@ -21605,6 +21842,15 @@ var notificationRulesCapability = {
21605
21842
  */
21606
21843
  getHistory: method(object({ filter: NcHistoryFilterSchema.default({ limit: 100 }) }), object({ entries: array(NcHistoryEntrySchema) }), { auth: "admin" }),
21607
21844
  /**
21845
+ * The newest delivery of every rule, in ONE bounded read of the outbox —
21846
+ * the "Last run" column. Never a `getHistory` per rule. A rule with no
21847
+ * delivery inside `horizonMs` is absent from `runs`; see
21848
+ * {@link NcRuleLastRunsSchema} for what absent means. A store that cannot
21849
+ * answer FAILS the call rather than answering "nothing ran". Admin-only,
21850
+ * like `getHistory`, of which it is a projection.
21851
+ */
21852
+ getRuleLastRuns: method(object({}), NcRuleLastRunsSchema, { auth: "admin" }),
21853
+ /**
21608
21854
  * Mint a fresh, externally-reachable URL for one artefact a history row
21609
21855
  * named in {@link NcHistoryEntrySchema.shape.artifactIds} — the SAME
21610
21856
  * signed-link mechanism the dispatcher uses to attach media to an
@@ -27533,7 +27779,11 @@ function buildDescriptor(capName, kind) {
27533
27779
  icon: legacyIcon(t.iconId)
27534
27780
  };
27535
27781
  }
27536
- Object.freeze(Object.fromEntries(Object.entries(CAP_TO_KIND).map(([capName, kind]) => [capName, buildDescriptor(capName, kind)])));
27782
+ /**
27783
+ * Sensor / control cap name → static event-kind descriptor. A linked device
27784
+ * contributes one entry per bound cap present in this map.
27785
+ */
27786
+ var EVENT_KIND_BY_CAP = Object.freeze(Object.fromEntries(Object.entries(CAP_TO_KIND).map(([capName, kind]) => [capName, buildDescriptor(capName, kind)])));
27537
27787
  /**
27538
27788
  * server-management — per-NODE singleton capability for a node's ROOT
27539
27789
  * package lifecycle (runtime-updatable node packages).
@@ -36553,6 +36803,29 @@ var RenameNodeResultSchema = object({
36553
36803
  name: string()
36554
36804
  });
36555
36805
  /**
36806
+ * The cheap node list. A consumer's rule for a STORED node id (a rule's
36807
+ * `nodeIds`) that is missing from `nodes`, whatever `complete` says: render it
36808
+ * as a removable chip labelled unknown, never drop it (D49). Even a complete
36809
+ * list omits a node that joined and left between two history captures, so a
36810
+ * missing id means "not known to the hub", never "removed". Only the operator
36811
+ * removes it.
36812
+ *
36813
+ * `complete` changes only the WORDING: `false` = no history read has ever
36814
+ * answered, so the list may be missing offline nodes the hub does know (D315).
36815
+ *
36816
+ * `name` is the history row's name (≤ 30 s behind a rename), or the id when
36817
+ * the history has none.
36818
+ */
36819
+ var NodeDirectorySchema = object({
36820
+ nodes: array(object({
36821
+ id: string(),
36822
+ name: string(),
36823
+ isHub: boolean(),
36824
+ isOnline: boolean()
36825
+ })).readonly(),
36826
+ complete: boolean()
36827
+ });
36828
+ /**
36556
36829
  * `nodes` is a **hub-centric** cluster-management cap: the hub hosts
36557
36830
  * the single provider and every per-node method (`getNodeAddons`,
36558
36831
  * `restartProcess`, `restartNode`, `undeployAddon`, …) takes `nodeId`
@@ -36571,6 +36844,12 @@ var nodesCapability = {
36571
36844
  nodeIdMode: "data",
36572
36845
  methods: {
36573
36846
  topology: method(_void(), array(TopologyNodeSchema).readonly(), { auth: "admin" }),
36847
+ /**
36848
+ * The cheap node list for pickers (D637): the hub's in-memory registry plus
36849
+ * the durable node history, no per-node RPC. `complete: false` when the
36850
+ * history could not be read.
36851
+ */
36852
+ directory: method(_void(), NodeDirectorySchema, { auth: "admin" }),
36574
36853
  deployAddon: method(NodeAddonInputSchema, SuccessSchema, {
36575
36854
  kind: "mutation",
36576
36855
  auth: "admin"
@@ -42865,6 +43144,42 @@ function readDeviceStateFrom(runtimeState) {
42865
43144
  }
42866
43145
  }
42867
43146
  /**
43147
+ * LA tabella "quale booleano di questo tipo di device conta come ALTO", e il
43148
+ * valutatore puro del suo FRONTE.
43149
+ *
43150
+ * Viveva dentro il builtin virtual-doorbell
43151
+ * (`@camstack/system` — `builtins/doorbell/trigger-engine.ts`) e i suoi
43152
+ * predicati erano privati al modulo. Il recorder ne ha bisogno per il trigger
43153
+ * `RecordingTriggers.sensorDeviceIds`: copiarla avrebbe creato la SECONDA
43154
+ * tabella, che diverge alla prima cap aggiunta e il cui sintomo — "il sensore
43155
+ * fa suonare il campanello ma non registra" — è esattamente D62. Quindi si
43156
+ * SPOSTA qui e il doorbell la ri-esporta.
43157
+ *
43158
+ * ⚠ NON è `DEVICE_STATE_READERS` (`catalogs/device-state-vocabulary.ts`), e le
43159
+ * due non vanno unificate: quella risponde a "qual è la PAROLA di stato per una
43160
+ * regola" (e include `presence`, `cover`, `alarm-panel`), questa a "qual è il
43161
+ * booleano il cui FRONTE conta". Vocabolari deliberatamente diversi.
43162
+ */
43163
+ /**
43164
+ * Known binary / switch source caps → the boolean slice field whose
43165
+ * false→true rise counts as ACTIVE. Every entry is "fire on active".
43166
+ * Sensors whose "active" reading is not a plain boolean (presence's string
43167
+ * state, connectivity's connected flag) are deliberately excluded — a
43168
+ * reconnect is not a doorbell press, and it is not a recording either.
43169
+ */
43170
+ var SOURCE_CAP_ACTIVE_FIELD = {
43171
+ contact: "entryOpen",
43172
+ binary: "on",
43173
+ switch: "on",
43174
+ motion: "detected",
43175
+ flood: "flooded",
43176
+ gas: "detected",
43177
+ smoke: "detected",
43178
+ "carbon-monoxide": "detected",
43179
+ vibration: "detected",
43180
+ tamper: "tampered"
43181
+ };
43182
+ /**
42868
43183
  * Accessory device helpers — shared across drivers.
42869
43184
  *
42870
43185
  * Many vendor-specific drivers register accessory child devices on
@@ -47071,12 +47386,30 @@ Object.freeze({
47071
47386
  addonId: null,
47072
47387
  access: "create"
47073
47388
  },
47389
+ "llmRuntime.appleAvailability": {
47390
+ capName: "llm-runtime",
47391
+ capScope: "system",
47392
+ addonId: null,
47393
+ access: "view"
47394
+ },
47395
+ "llmRuntime.cancel": {
47396
+ capName: "llm-runtime",
47397
+ capScope: "system",
47398
+ addonId: null,
47399
+ access: "create"
47400
+ },
47074
47401
  "llmRuntime.complete": {
47075
47402
  capName: "llm-runtime",
47076
47403
  capScope: "system",
47077
47404
  addonId: null,
47078
47405
  access: "create"
47079
47406
  },
47407
+ "llmRuntime.completeApple": {
47408
+ capName: "llm-runtime",
47409
+ capScope: "system",
47410
+ addonId: null,
47411
+ access: "create"
47412
+ },
47080
47413
  "llmRuntime.deleteModel": {
47081
47414
  capName: "llm-runtime",
47082
47415
  capScope: "system",
@@ -47749,6 +48082,12 @@ Object.freeze({
47749
48082
  addonId: null,
47750
48083
  access: "create"
47751
48084
  },
48085
+ "nodes.directory": {
48086
+ capName: "nodes",
48087
+ capScope: "system",
48088
+ addonId: null,
48089
+ access: "view"
48090
+ },
47752
48091
  "nodes.executeQuery": {
47753
48092
  capName: "nodes",
47754
48093
  capScope: "system",
@@ -47917,6 +48256,12 @@ Object.freeze({
47917
48256
  addonId: null,
47918
48257
  access: "view"
47919
48258
  },
48259
+ "notificationRules.getRuleLastRuns": {
48260
+ capName: "notification-rules",
48261
+ capScope: "system",
48262
+ addonId: null,
48263
+ access: "view"
48264
+ },
47920
48265
  "notificationRules.getTemplateCatalog": {
47921
48266
  capName: "notification-rules",
47922
48267
  capScope: "system",
@@ -53513,6 +53858,51 @@ var NC_AUDIO_DEFAULTS = {
53513
53858
  samplingSeconds: 10
53514
53859
  };
53515
53860
  new Set(["devices", "classes"]);
53861
+ /** Every filter, for the callers that must cover all four (guards, tests). */
53862
+ var NC_SYSTEM_EVENT_FILTER_KEYS = [
53863
+ "deviceIds",
53864
+ "deviceTypes",
53865
+ "nodeIds",
53866
+ "packageNames"
53867
+ ];
53868
+ new Map(Object.entries({
53869
+ "device-online": "device-events",
53870
+ "device-offline": "device-events",
53871
+ "device-disabled": "device-events",
53872
+ "device-enabled": "device-events",
53873
+ "device-battery-low": "device-events",
53874
+ "device-battery-normal": "device-events",
53875
+ "device-consumable-low": "device-events",
53876
+ "device-consumable-normal": "device-events",
53877
+ "stream-online": "device-events",
53878
+ "stream-offline": "device-events",
53879
+ "detection-blind": "device-events",
53880
+ "node-online": "system",
53881
+ "node-offline": "system",
53882
+ "node-inference-unavailable": "system",
53883
+ "addon-crash-loop": "system",
53884
+ "addon-update-available": "system",
53885
+ "addon-updated": "system",
53886
+ "server-update-available": "system",
53887
+ "server-updated": "system",
53888
+ "wrapper-update-available": "system",
53889
+ "backup-completed": "system",
53890
+ "export-completed": "system",
53891
+ "alarm-triggered": "alarm",
53892
+ "alarm-armed": "alarm",
53893
+ "alarm-disarmed": "alarm",
53894
+ "alarm-arming": "alarm",
53895
+ "alarm-arm-refused": "alarm",
53896
+ "alarm-pending": "alarm",
53897
+ "alarm-rearmed": "alarm",
53898
+ "alarm-sensor-bypass": "alarm",
53899
+ "alarm-check-failed": "alarm",
53900
+ "camera-online": null,
53901
+ "camera-offline": null,
53902
+ "camera-disabled": null,
53903
+ "camera-enabled": null
53904
+ }));
53905
+ [...NC_SYSTEM_EVENT_FILTER_KEYS];
53516
53906
  NC_AUDIO_DEFAULTS.hitPercent, NC_AUDIO_DEFAULTS.samplingSeconds;
53517
53907
  var WEEKDAY_TO_DAY = {
53518
53908
  Sun: 0,
@@ -53574,6 +53964,39 @@ function isScheduleActive(schedule, atMs) {
53574
53964
  }
53575
53965
  return schedule.invert === true ? !inside : inside;
53576
53966
  }
53967
+ /**
53968
+ * WHICH WAY A BOOLEAN SENSOR MOVED — read off the one slice a sensor event
53969
+ * persists (D640 "a sensor rule fires on the raise, the clear, or both").
53970
+ *
53971
+ * A device-event rule over a flood sensor notified on BOTH edges: water
53972
+ * detected, and back to dry. `NcConditions.sensorTransition` lets the rule
53973
+ * name one edge; this file answers, for one `SensorEvent`, which edge it is.
53974
+ *
53975
+ * NOT A SECOND TABLE. The "which boolean of this cap counts as HIGH" question
53976
+ * already has one answer, `SOURCE_CAP_ACTIVE_FIELD`
53977
+ * (`catalogs/sensor-active-state.ts`, the doorbell's and the recorder's edge
53978
+ * table), and a sensor event names its kind, not its cap. So the table here is
53979
+ * DERIVED: event kind → cap (`EVENT_KIND_BY_CAP`) → that cap's active field.
53980
+ * Only kinds whose taxonomy category is `sensor` take part — a switch has an
53981
+ * `on` boolean too, but "it triggers / it clears" is not a sentence about a
53982
+ * light, and offering it there would be a knob with a misleading label.
53983
+ * `presence` is a WORD (`home` / `not_home` / a zone), not a boolean, and is
53984
+ * absent from the source table, so it is absent here.
53985
+ *
53986
+ * `undefined` = never guessed: a kind with no raise (a doorbell press, a
53987
+ * button, a cover), or a slice whose field is missing or not a boolean. The
53988
+ * engine then does NOT filter — a flood alert must not go silent because one
53989
+ * read came back unreadable (the same stance as the alarm's `sensorEdgeOf`).
53990
+ *
53991
+ * Pure, RN-safe: the viewer imports the support rule from here.
53992
+ */
53993
+ /** Event kind → the boolean field of its cap slice that means "raised". */
53994
+ var NC_SENSOR_RAISED_FIELD_BY_KIND = Object.freeze(Object.fromEntries(Object.entries(EVENT_KIND_BY_CAP).flatMap(([capName, descriptor]) => {
53995
+ const field = SOURCE_CAP_ACTIVE_FIELD[capName];
53996
+ if (field === void 0 || descriptor.category !== "sensor") return [];
53997
+ return [[descriptor.kind, field]];
53998
+ })));
53999
+ Object.freeze(Object.keys(NC_SENSOR_RAISED_FIELD_BY_KIND));
53577
54000
  var RULE_BODY_ONLY = ["body"];
53578
54001
  var RULE_TEXT = ["title", "body"];
53579
54002
  var BATTERY = ["device-battery-low", "device-battery-normal"];