@camstack/types 1.2.443 → 1.2.445
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/CHANGELOG.md +20 -0
- package/dist/addon.d.ts +5 -1
- package/dist/addon.js +21 -5
- package/dist/addon.mjs +17 -6
- package/dist/automation/export-entities.d.ts +98 -0
- package/dist/capabilities/capability-definition.d.ts +1 -1
- package/dist/capabilities/composer.cap.d.ts +34 -0
- package/dist/capabilities/consumables.cap.d.ts +4 -5
- package/dist/capabilities/core-blocks.cap.d.ts +244 -0
- package/dist/capabilities/device-export.cap.d.ts +111 -1
- package/dist/capabilities/index.d.ts +6 -4
- package/dist/capabilities/metrics-provider.cap.d.ts +16 -16
- package/dist/capabilities/nodes.cap.d.ts +2 -2
- package/dist/capabilities/pet-fountain.cap.d.ts +138 -0
- package/dist/capabilities/pipeline-executor.cap.d.ts +6 -22
- package/dist/capabilities/pipeline-orchestrator.cap.d.ts +2 -2
- package/dist/capabilities/pipeline-runner.cap.d.ts +2 -2
- package/dist/capabilities/pipeline-step-input.d.ts +33 -0
- package/dist/capabilities/server-management.cap.d.ts +28 -0
- package/dist/client.js +820 -799
- package/dist/client.mjs +820 -799
- package/dist/composition/composition-items.d.ts +3 -3
- package/dist/composition/composition-report.d.ts +17 -0
- package/dist/composition/composition.d.ts +68 -1
- package/dist/composition/index.d.ts +2 -0
- package/dist/composition/presets/pet-fountain.d.ts +36 -0
- package/dist/composition/validate-forward.d.ts +31 -0
- package/dist/{composition-C0dlyG9U.js → composition-CO6Sak-s.js} +49 -5
- package/dist/{composition-bIBW5_13.mjs → composition-kSuOifuG.mjs} +32 -6
- package/dist/device/cap-vocabulary/entries/appliances.d.ts +1 -1
- package/dist/device/device-control-resolution.d.ts +1 -1
- package/dist/device/device-type.d.ts +4 -0
- package/dist/{err-msg-BCdlR2Li.mjs → err-msg-DWXWc0Di.mjs} +4 -0
- package/dist/{err-msg-COHgq7Mb.js → err-msg-EJhsFHqa.js} +4 -0
- package/dist/generated/addon-api.d.ts +148 -32
- package/dist/generated/addon-cap-facts.d.ts +1 -1
- package/dist/generated/cap-status-types.d.ts +3 -1
- package/dist/generated/capability-router-map.d.ts +5 -2
- package/dist/generated/collection-array-methods.d.ts +2 -2
- package/dist/generated/customize-catalog.d.ts +1 -1
- package/dist/generated/device-local-state.d.ts +3 -0
- package/dist/generated/device-proxy.d.ts +3 -0
- package/dist/generated/device-scoped-caps.d.ts +1 -1
- package/dist/generated/history-catalog.d.ts +1 -1
- package/dist/generated/method-access-map.d.ts +1 -1
- package/dist/generated/method-device-selectors.d.ts +1 -1
- package/dist/generated/runtime-state-durability.d.ts +1 -1
- package/dist/generated/system-proxy.d.ts +2 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1465 -603
- package/dist/index.mjs +1433 -592
- package/dist/interfaces/agent.d.ts +6 -2
- package/dist/interfaces/event-bus.d.ts +1 -1
- package/dist/node.js +2 -2
- package/dist/node.mjs +2 -2
- package/dist/{sleep-C_u6cEAJ.mjs → sleep-6eG9C8Xl.mjs} +223 -72
- package/dist/{sleep-E7qAQwTE.js → sleep-UXDHn-oJ.js} +246 -71
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_sleep = require("./sleep-
|
|
2
|
+
const require_sleep = require("./sleep-UXDHn-oJ.js");
|
|
3
3
|
const require_event_category = require("./event-category-E17zaHjN.js");
|
|
4
|
-
const require_composition = require("./composition-
|
|
4
|
+
const require_composition = require("./composition-CO6Sak-s.js");
|
|
5
5
|
const require_node_color = require("./node-color.js");
|
|
6
|
-
const require_err_msg = require("./err-msg-
|
|
6
|
+
const require_err_msg = require("./err-msg-EJhsFHqa.js");
|
|
7
7
|
const require_enums = require("./enums.js");
|
|
8
8
|
let zod = require("zod");
|
|
9
9
|
//#region src/media/media-owner-key.ts
|
|
@@ -10705,6 +10705,593 @@ function buildActionSteps(steps, vars, deps) {
|
|
|
10705
10705
|
});
|
|
10706
10706
|
}
|
|
10707
10707
|
//#endregion
|
|
10708
|
+
//#region src/capabilities/notification-output.cap.ts
|
|
10709
|
+
/**
|
|
10710
|
+
* notification-output — canonical, capability-gated notification delivery.
|
|
10711
|
+
*
|
|
10712
|
+
* Apprise-derived model (see
|
|
10713
|
+
* `docs/superpowers/specs/2026-07-03-notification-output-notifier-matrix.md`):
|
|
10714
|
+
* callers emit ONE canonical `Notification`; each provider declares a
|
|
10715
|
+
* per-kind capability descriptor (`TargetKind`), and the pure degrade
|
|
10716
|
+
* engine (`@camstack/types` `prepareNotification`) transcodes / degrades the
|
|
10717
|
+
* message to what the kind supports — callers never special-case a service.
|
|
10718
|
+
*
|
|
10719
|
+
* DESIGN DECISIONS (locked):
|
|
10720
|
+
* - Target CRUD lives on THIS cap (`upsertTarget` / `deleteTarget` /
|
|
10721
|
+
* `setTargetEnabled`), each provider persisting via the `settings-store`
|
|
10722
|
+
* cap. Rationale: the admin UI needs one uniform surface across the
|
|
10723
|
+
* notifiers addon AND the HA addon; the addon-`globalSettingsSchema`-array
|
|
10724
|
+
* alternative would fork the UI per addon and cannot host the
|
|
10725
|
+
* discovery→adopt flow.
|
|
10726
|
+
* - `listTargetKinds` / `listTargets` / `discoverTargets` return arrays →
|
|
10727
|
+
* the generated cap-mount auto-`concatCollection`-fans them across every
|
|
10728
|
+
* registered provider (notifiers addon + HA addon) so one catalog is
|
|
10729
|
+
* routable. `send` / `testTarget` / CRUD route to ONE provider by the
|
|
10730
|
+
* `addonId` the generated collection router extracts from the call input.
|
|
10731
|
+
* - `Attachment.bytes` is `Uint8Array`. Transport-safe: superjson (the tRPC
|
|
10732
|
+
* transformer) + UDS MsgPack both round-trip typed arrays — already used by
|
|
10733
|
+
* `storage` / `storage-provider` / `recording` caps over the same path. No
|
|
10734
|
+
* base64 fallback needed.
|
|
10735
|
+
*
|
|
10736
|
+
* TODO (deferred, closed-set change — separate decision): add
|
|
10737
|
+
* `providerKind: 'notify'` so notification providers surface on the unified
|
|
10738
|
+
* admin "Integrations" page.
|
|
10739
|
+
*/
|
|
10740
|
+
/**
|
|
10741
|
+
* Zentik-derived typed-media enum — the superset across every kind. Each
|
|
10742
|
+
* adapter picks what it supports and the degrade engine filters the rest.
|
|
10743
|
+
*/
|
|
10744
|
+
var AttachmentMediaTypeSchema = zod.z.enum([
|
|
10745
|
+
"image",
|
|
10746
|
+
"video",
|
|
10747
|
+
"gif",
|
|
10748
|
+
"audio",
|
|
10749
|
+
"icon"
|
|
10750
|
+
]);
|
|
10751
|
+
/**
|
|
10752
|
+
* A single attachment. Exactly one of `url` (remote source, most adapters
|
|
10753
|
+
* prefer this) or `bytes` (inline source; required for Pushover-style
|
|
10754
|
+
* bytes-only kinds) MUST be present — the degrade engine expresses a
|
|
10755
|
+
* url→bytes fetch as a `needsFetch` directive the adapter executes.
|
|
10756
|
+
*/
|
|
10757
|
+
var AttachmentSchema = zod.z.object({
|
|
10758
|
+
mediaType: AttachmentMediaTypeSchema,
|
|
10759
|
+
url: zod.z.string().optional(),
|
|
10760
|
+
bytes: zod.z.instanceof(Uint8Array).optional(),
|
|
10761
|
+
mime: zod.z.string().optional(),
|
|
10762
|
+
name: zod.z.string().optional()
|
|
10763
|
+
}).refine((a) => a.url !== void 0 || a.bytes !== void 0, { message: "Attachment requires either `url` or `bytes`" });
|
|
10764
|
+
var NotificationFormatSchema = zod.z.enum([
|
|
10765
|
+
"text",
|
|
10766
|
+
"markdown",
|
|
10767
|
+
"html"
|
|
10768
|
+
]);
|
|
10769
|
+
/**
|
|
10770
|
+
* The CLOSED icon vocabulary an action button may use.
|
|
10771
|
+
*
|
|
10772
|
+
* A closed set, not a free string, and that is the whole point: an arbitrary
|
|
10773
|
+
* icon name is one that ntfy renders, zentik silently drops, and nobody
|
|
10774
|
+
* notices — the same class of gap as a zone vocabulary nothing produced
|
|
10775
|
+
* ([D35](../../../docs/decisions/adr-0035.md)). Every adapter maps this set or
|
|
10776
|
+
* declares `actionIcons: false` and the degrade engine strips the field.
|
|
10777
|
+
*
|
|
10778
|
+
* Named by INTENT, never by glyph. "check" would tie the vocabulary to one
|
|
10779
|
+
* renderer's icon set; "acknowledge" survives an adapter that draws it
|
|
10780
|
+
* differently.
|
|
10781
|
+
*
|
|
10782
|
+
* ── A TOKEN IS NOT A WIRE VALUE ─────────────────────────────────────
|
|
10783
|
+
*
|
|
10784
|
+
* These names are for US. **No adapter may forward one verbatim.** Each maps
|
|
10785
|
+
* the whole set onto its own renderer's vocabulary through a
|
|
10786
|
+
* `Record<NotificationActionIcon, string>` — a Record, never a lookup with a
|
|
10787
|
+
* fallback, so adding a member here fails every adapter's build until someone
|
|
10788
|
+
* decides its glyph, which is the only place that decision can be made
|
|
10789
|
+
* honestly.
|
|
10790
|
+
*
|
|
10791
|
+
* This paragraph is the bug. Zentik declared `actionIcons: true` and passed
|
|
10792
|
+
* `disarm` straight through; iOS feeds that string to
|
|
10793
|
+
* `UNNotificationActionIcon(systemImageName:)`, `disarm` is not an SF Symbol,
|
|
10794
|
+
* and every snooze and alarm button arrived BLANK. A pass-through is not a
|
|
10795
|
+
* mapping, and "the field is documented" is not "the value renders".
|
|
10796
|
+
*
|
|
10797
|
+
* Adding a member is TRAIN-BOUND. The enum lives in the published
|
|
10798
|
+
* `@camstack/server` closure and the cap seam validates against the HUB's copy,
|
|
10799
|
+
* so an addon that emits a token the running hub does not know does not lose an
|
|
10800
|
+
* icon — its whole `send` fails Zod validation and the notification never
|
|
10801
|
+
* arrives. Never emit a new token from an addon before the train carrying it.
|
|
10802
|
+
*/
|
|
10803
|
+
var NotificationActionIconSchema = zod.z.enum([
|
|
10804
|
+
"acknowledge",
|
|
10805
|
+
"dismiss",
|
|
10806
|
+
"silence",
|
|
10807
|
+
"snooze",
|
|
10808
|
+
"view",
|
|
10809
|
+
"play",
|
|
10810
|
+
"open",
|
|
10811
|
+
"close",
|
|
10812
|
+
"lock",
|
|
10813
|
+
"unlock",
|
|
10814
|
+
"arm",
|
|
10815
|
+
"arm-home",
|
|
10816
|
+
"arm-away",
|
|
10817
|
+
"arm-night",
|
|
10818
|
+
"disarm",
|
|
10819
|
+
"light",
|
|
10820
|
+
"alert",
|
|
10821
|
+
"camera"
|
|
10822
|
+
]);
|
|
10823
|
+
/** A single tap-through action button. */
|
|
10824
|
+
var NotificationActionSchema = zod.z.object({
|
|
10825
|
+
id: zod.z.string(),
|
|
10826
|
+
label: zod.z.string(),
|
|
10827
|
+
url: zod.z.string().optional(),
|
|
10828
|
+
/** Dropped by the degrade engine for a kind with `caps.actionIcons: false`. */
|
|
10829
|
+
icon: NotificationActionIconSchema.optional(),
|
|
10830
|
+
/**
|
|
10831
|
+
* Renders in a warning style where the notifier supports it.
|
|
10832
|
+
*
|
|
10833
|
+
* A HINT, never a gate. The callback's authority is its token and nothing
|
|
10834
|
+
* else — see `notification-center/action-token.ts` for what that does and
|
|
10835
|
+
* does not buy.
|
|
10836
|
+
*/
|
|
10837
|
+
destructive: zod.z.boolean().optional(),
|
|
10838
|
+
/**
|
|
10839
|
+
* How the tap should REACH the url.
|
|
10840
|
+
*
|
|
10841
|
+
* `navigate` (absent, and every button authored before this field) opens it:
|
|
10842
|
+
* the phone leaves the notification and shows whatever the callback returns.
|
|
10843
|
+
* That is right for a button whose answer the operator wants to read.
|
|
10844
|
+
*
|
|
10845
|
+
* `background` fires it as a POST and stays put. It exists for the buttons
|
|
10846
|
+
* whose whole point is not to interrupt — "silence this for 30 minutes" is
|
|
10847
|
+
* an answer to the notification, and being thrown into a browser tab to
|
|
10848
|
+
* confirm it costs more attention than the notification did. A backend that
|
|
10849
|
+
* cannot do a background call renders it as an ordinary link (the adapters
|
|
10850
|
+
* fall back rather than dropping the button), so this is a preference, never
|
|
10851
|
+
* a requirement.
|
|
10852
|
+
*/
|
|
10853
|
+
mode: zod.z.enum(["navigate", "background"]).optional()
|
|
10854
|
+
});
|
|
10855
|
+
/** A delivery parameter value: what a notifier declared it takes. */
|
|
10856
|
+
var DeliveryParamValueSchema = zod.z.union([
|
|
10857
|
+
zod.z.string(),
|
|
10858
|
+
zod.z.number(),
|
|
10859
|
+
zod.z.boolean()
|
|
10860
|
+
]);
|
|
10861
|
+
/**
|
|
10862
|
+
* One extra delivery parameter a notifier KIND declares (D938). A rule that
|
|
10863
|
+
* addresses a target of that kind may set it; a kind that declares nothing is
|
|
10864
|
+
* never handed one. The admin UI derives its control from this descriptor —
|
|
10865
|
+
* no editor knows a service by name.
|
|
10866
|
+
*
|
|
10867
|
+
* Optional fields are `.optional()`, never `.default()` (a Zod default does not
|
|
10868
|
+
* run on the addon cap path).
|
|
10869
|
+
*/
|
|
10870
|
+
var DeliveryParamSchema = zod.z.object({
|
|
10871
|
+
key: zod.z.string().min(1),
|
|
10872
|
+
label: zod.z.string(),
|
|
10873
|
+
/** i18n key of the label, resolved by the declaring addon's namespace. */
|
|
10874
|
+
labelKey: zod.z.string().optional(),
|
|
10875
|
+
type: zod.z.enum([
|
|
10876
|
+
"enum",
|
|
10877
|
+
"number",
|
|
10878
|
+
"boolean",
|
|
10879
|
+
"string"
|
|
10880
|
+
]),
|
|
10881
|
+
/** `enum` only: the closed set of accepted values. */
|
|
10882
|
+
options: zod.z.array(zod.z.object({
|
|
10883
|
+
value: zod.z.string(),
|
|
10884
|
+
label: zod.z.string()
|
|
10885
|
+
})).optional(),
|
|
10886
|
+
/** `number` only. */
|
|
10887
|
+
min: zod.z.number().optional(),
|
|
10888
|
+
max: zod.z.number().optional(),
|
|
10889
|
+
/** What the notifier does when the rule sets nothing; shown as the placeholder. */
|
|
10890
|
+
default: DeliveryParamValueSchema.optional()
|
|
10891
|
+
});
|
|
10892
|
+
/**
|
|
10893
|
+
* The canonical notification. `body` is the only hard field (Apprise model).
|
|
10894
|
+
* `priority` is a 5-level ORDINAL (1=lowest … 3=normal(default) … 5=urgent),
|
|
10895
|
+
* NOT a fixed severity enum — each kind declares its own `caps.levels` and
|
|
10896
|
+
* the adapter maps this ordinal onto its native level. `level?` is an
|
|
10897
|
+
* optional kind-native level id (`emergency`, `silent`, …) that overrides
|
|
10898
|
+
* `priority` for that one target.
|
|
10899
|
+
*/
|
|
10900
|
+
var NotificationSchema = zod.z.object({
|
|
10901
|
+
body: zod.z.string(),
|
|
10902
|
+
title: zod.z.string().optional(),
|
|
10903
|
+
format: NotificationFormatSchema.default("text"),
|
|
10904
|
+
priority: zod.z.number().int().min(1).max(5).default(3),
|
|
10905
|
+
level: zod.z.string().optional(),
|
|
10906
|
+
attachments: zod.z.array(AttachmentSchema).optional(),
|
|
10907
|
+
clickUrl: zod.z.string().optional(),
|
|
10908
|
+
actions: zod.z.array(NotificationActionSchema).optional(),
|
|
10909
|
+
sound: zod.z.string().optional(),
|
|
10910
|
+
ttl: zod.z.number().optional(),
|
|
10911
|
+
tag: zod.z.string().optional(),
|
|
10912
|
+
deviceId: zod.z.number().optional(),
|
|
10913
|
+
eventId: zod.z.string().optional(),
|
|
10914
|
+
metadata: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
|
|
10915
|
+
/**
|
|
10916
|
+
* Values for the parameters the target's kind DECLARES in
|
|
10917
|
+
* {@link TargetKindSchema} `deliveryParams`. Already validated against the
|
|
10918
|
+
* declaration by the sender; a notifier reads only the keys it declared.
|
|
10919
|
+
*/
|
|
10920
|
+
delivery: zod.z.record(zod.z.string(), DeliveryParamValueSchema).optional()
|
|
10921
|
+
});
|
|
10922
|
+
/** One declared native severity/priority level for a kind. */
|
|
10923
|
+
var TargetKindLevelSchema = zod.z.object({
|
|
10924
|
+
id: zod.z.string(),
|
|
10925
|
+
label: zod.z.string(),
|
|
10926
|
+
/** Which canonical priority (1..5) this level maps to. `null` = qualitative-only. */
|
|
10927
|
+
ordinal: zod.z.number().int().min(1).max(5).nullable(),
|
|
10928
|
+
flags: zod.z.object({
|
|
10929
|
+
critical: zod.z.boolean().optional(),
|
|
10930
|
+
silent: zod.z.boolean().optional(),
|
|
10931
|
+
noPush: zod.z.boolean().optional()
|
|
10932
|
+
}).optional(),
|
|
10933
|
+
/** e.g. Pushover `emergency` requires `retry` / `expire`. */
|
|
10934
|
+
requires: zod.z.array(zod.z.string()).optional(),
|
|
10935
|
+
description: zod.z.string().optional()
|
|
10936
|
+
});
|
|
10937
|
+
/** Attachment capabilities for a kind (drives the degrade engine + test panel). */
|
|
10938
|
+
var TargetKindAttachmentsCapsSchema = zod.z.object({
|
|
10939
|
+
mediaTypes: zod.z.array(AttachmentMediaTypeSchema),
|
|
10940
|
+
mode: zod.z.enum([
|
|
10941
|
+
"url",
|
|
10942
|
+
"bytes",
|
|
10943
|
+
"both"
|
|
10944
|
+
]),
|
|
10945
|
+
max: zod.z.number().int().nonnegative(),
|
|
10946
|
+
maxBytes: zod.z.number().int().positive().optional()
|
|
10947
|
+
});
|
|
10948
|
+
/** The full capability block consulted before dispatch. */
|
|
10949
|
+
var TargetKindCapsSchema = zod.z.object({
|
|
10950
|
+
attachments: TargetKindAttachmentsCapsSchema,
|
|
10951
|
+
/** Max action buttons (0 = none). */
|
|
10952
|
+
actions: zod.z.number().int().nonnegative(),
|
|
10953
|
+
/**
|
|
10954
|
+
* Whether this kind renders a per-action ICON.
|
|
10955
|
+
*
|
|
10956
|
+
* `.optional()`, deliberately NOT `.default(false)`: a Zod default does not
|
|
10957
|
+
* run on the addon cap path — three production failures in one day taught
|
|
10958
|
+
* this repo that once. Absent is read as false by the degrade engine, which
|
|
10959
|
+
* is the safe direction: an icon that is not rendered costs nothing, an icon
|
|
10960
|
+
* assumed and dropped costs the operator's trust in the field.
|
|
10961
|
+
*/
|
|
10962
|
+
actionIcons: zod.z.boolean().optional(),
|
|
10963
|
+
levels: zod.z.array(TargetKindLevelSchema),
|
|
10964
|
+
format: zod.z.array(NotificationFormatSchema),
|
|
10965
|
+
clickUrl: zod.z.boolean(),
|
|
10966
|
+
sound: zod.z.boolean(),
|
|
10967
|
+
ttl: zod.z.boolean(),
|
|
10968
|
+
bodyMaxLen: zod.z.number().int().positive()
|
|
10969
|
+
});
|
|
10970
|
+
/**
|
|
10971
|
+
* `configSchema` is a `ConfigUISchema` tree passed through to the admin
|
|
10972
|
+
* FormBuilder. Stored as `z.unknown()` at the cap seam (mirrors
|
|
10973
|
+
* `device-provider.getChildCreationSchema` `CreationSchemaOutputSchema`) —
|
|
10974
|
+
* the union is large and not meant for runtime validation here; the exported
|
|
10975
|
+
* `TargetKind` type re-tightens `configSchema` to `ConfigUISchema`.
|
|
10976
|
+
*/
|
|
10977
|
+
var ConfigSchemaPassthrough$3 = zod.z.unknown();
|
|
10978
|
+
var TargetKindSchema = zod.z.object({
|
|
10979
|
+
kind: zod.z.string(),
|
|
10980
|
+
label: zod.z.string(),
|
|
10981
|
+
icon: zod.z.string(),
|
|
10982
|
+
/** Stamped by each provider so the concat-fanned catalog stays routable. */
|
|
10983
|
+
addonId: zod.z.string(),
|
|
10984
|
+
/**
|
|
10985
|
+
* URL of the kind's bundled BRAND icon, served by the providing addon over
|
|
10986
|
+
* its own `addon-routes` surface (`/addon/<addonId>/icons/<kind>`). Absent
|
|
10987
|
+
* when the addon bundles no icon for that kind — the client then falls back
|
|
10988
|
+
* to a neutral glyph rather than rendering the raw `icon` NAME as text.
|
|
10989
|
+
*
|
|
10990
|
+
* Root-relative on purpose: it resolves against whatever origin serves a web
|
|
10991
|
+
* client, and a native client joins it onto its own hub base.
|
|
10992
|
+
*
|
|
10993
|
+
* DECLARED here deliberately. It used to travel as an undeclared passthrough
|
|
10994
|
+
* field that survived only because the runtime cap-router forwards provider
|
|
10995
|
+
* output verbatim — so every consumer had to re-declare it by hand to stop
|
|
10996
|
+
* its own Zod parse from stripping it, and the whole arrangement would have
|
|
10997
|
+
* broken silently the moment output validation was tightened anywhere.
|
|
10998
|
+
*/
|
|
10999
|
+
iconUrl: zod.z.string().optional(),
|
|
11000
|
+
/**
|
|
11001
|
+
* Media type of {@link iconUrl} (`image/svg+xml`, `image/png`, …).
|
|
11002
|
+
*
|
|
11003
|
+
* The server knows this and therefore says it, because the client cannot
|
|
11004
|
+
* safely guess: a React-Native client renders SVG and raster through two
|
|
11005
|
+
* DIFFERENT components (`react-native-svg` vs `expo-image` — expo-image does
|
|
11006
|
+
* not decode SVG on iOS/Android), so without this it silently fell back to a
|
|
11007
|
+
* placeholder glyph for every vector icon while the web build looked fine.
|
|
11008
|
+
*
|
|
11009
|
+
* Absent when {@link iconUrl} is absent, or for a legacy provider that has
|
|
11010
|
+
* not been updated — a client that cannot determine the type should prefer
|
|
11011
|
+
* its raster path, which is the safe default for an unknown image.
|
|
11012
|
+
*/
|
|
11013
|
+
iconMediaType: zod.z.string().optional(),
|
|
11014
|
+
configSchema: ConfigSchemaPassthrough$3,
|
|
11015
|
+
/**
|
|
11016
|
+
* The config keys that decide WHERE this kind's secrets are sent (server,
|
|
11017
|
+
* base URL, instance, chat, recipient). A save that changes any of them
|
|
11018
|
+
* while leaving a secret redacted is refused by the provider (D634), so an
|
|
11019
|
+
* editor uses this to ask for the secret on exactly those edits instead of
|
|
11020
|
+
* on every edit.
|
|
11021
|
+
*
|
|
11022
|
+
* Optional: absent from a provider that holds no secret (the Home Assistant
|
|
11023
|
+
* kinds) and from a provider older than this field — an editor that finds
|
|
11024
|
+
* it absent must assume ANY edit may need the secret.
|
|
11025
|
+
*/
|
|
11026
|
+
destinationKeys: zod.z.array(zod.z.string()).optional(),
|
|
11027
|
+
supportsDiscovery: zod.z.boolean(),
|
|
11028
|
+
/**
|
|
11029
|
+
* Extra delivery parameters a rule may set for a target of this kind (D938).
|
|
11030
|
+
* Absent = none; the rule editor then offers nothing.
|
|
11031
|
+
*/
|
|
11032
|
+
deliveryParams: zod.z.array(DeliveryParamSchema).optional(),
|
|
11033
|
+
caps: TargetKindCapsSchema
|
|
11034
|
+
});
|
|
11035
|
+
/**
|
|
11036
|
+
* A persisted target. `config` holds secrets; providers REDACT secret fields
|
|
11037
|
+
* (return a presence marker only) when serving `listTargets` — never
|
|
11038
|
+
* round-trip a stored secret to the UI.
|
|
11039
|
+
*/
|
|
11040
|
+
var TargetSchema = zod.z.object({
|
|
11041
|
+
id: zod.z.string(),
|
|
11042
|
+
name: zod.z.string(),
|
|
11043
|
+
kind: zod.z.string(),
|
|
11044
|
+
addonId: zod.z.string(),
|
|
11045
|
+
enabled: zod.z.boolean(),
|
|
11046
|
+
config: zod.z.record(zod.z.string(), zod.z.unknown())
|
|
11047
|
+
});
|
|
11048
|
+
/** A discovery-surfaced candidate (config is partial + non-secret). */
|
|
11049
|
+
var DiscoveredTargetSchema = zod.z.object({
|
|
11050
|
+
kind: zod.z.string(),
|
|
11051
|
+
suggestedName: zod.z.string(),
|
|
11052
|
+
config: zod.z.record(zod.z.string(), zod.z.unknown())
|
|
11053
|
+
});
|
|
11054
|
+
/** The degrade engine's report — what was resolved / dropped / degraded. */
|
|
11055
|
+
var RenderedAsSchema = zod.z.object({
|
|
11056
|
+
level: zod.z.string(),
|
|
11057
|
+
format: NotificationFormatSchema,
|
|
11058
|
+
attachmentsSent: zod.z.number().int().nonnegative(),
|
|
11059
|
+
actionsSent: zod.z.number().int().nonnegative(),
|
|
11060
|
+
truncated: zod.z.boolean(),
|
|
11061
|
+
dropped: zod.z.array(zod.z.string())
|
|
11062
|
+
});
|
|
11063
|
+
var SendResultSchema = zod.z.object({
|
|
11064
|
+
success: zod.z.boolean(),
|
|
11065
|
+
error: zod.z.string().optional(),
|
|
11066
|
+
renderedAs: RenderedAsSchema.optional()
|
|
11067
|
+
});
|
|
11068
|
+
/** Same shape as SendResult — kept as a distinct name for the test panel. */
|
|
11069
|
+
var TestResultSchema = SendResultSchema;
|
|
11070
|
+
/**
|
|
11071
|
+
* Pre-save credential probe against a partial (unsaved) target config.
|
|
11072
|
+
* `resolvedUrl` never includes secrets (token stripped from path).
|
|
11073
|
+
*/
|
|
11074
|
+
var ProbeTargetConfigResultSchema = zod.z.object({
|
|
11075
|
+
ok: zod.z.boolean(),
|
|
11076
|
+
resolvedUrl: zod.z.string(),
|
|
11077
|
+
httpStatus: zod.z.number().int().optional(),
|
|
11078
|
+
stateInstance: zod.z.string().optional(),
|
|
11079
|
+
error: zod.z.string().optional()
|
|
11080
|
+
});
|
|
11081
|
+
var notificationOutputCapability = {
|
|
11082
|
+
name: "notification-output",
|
|
11083
|
+
scope: "system",
|
|
11084
|
+
mode: "collection",
|
|
11085
|
+
methods: {
|
|
11086
|
+
listTargetKinds: require_sleep.method(zod.z.object({}), zod.z.array(TargetKindSchema)),
|
|
11087
|
+
listTargets: require_sleep.method(zod.z.object({}), zod.z.array(TargetSchema), { auth: "admin" }),
|
|
11088
|
+
/**
|
|
11089
|
+
* One target WITH secrets — admin edit / duplicate hydration only.
|
|
11090
|
+
* `listTargets` stays redacted; the editor loads this so password fields
|
|
11091
|
+
* are filled (masked in the input) and a save can round-trip the token
|
|
11092
|
+
* when a destination changes (Duplicate with a new chatId, etc.).
|
|
11093
|
+
*/
|
|
11094
|
+
getTarget: require_sleep.method(zod.z.object({ targetId: zod.z.string() }), TargetSchema, { auth: "admin" }),
|
|
11095
|
+
discoverTargets: require_sleep.method(zod.z.object({
|
|
11096
|
+
kind: zod.z.string(),
|
|
11097
|
+
config: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
|
|
11098
|
+
/**
|
|
11099
|
+
* When editing / duplicating, the blank password field never round-trips
|
|
11100
|
+
* the stored token. Pass the source target id so the provider can restore
|
|
11101
|
+
* secrets server-side before dialling (same merge as upsert).
|
|
11102
|
+
*/
|
|
11103
|
+
targetId: zod.z.string().optional()
|
|
11104
|
+
}), zod.z.array(DiscoveredTargetSchema), { auth: "admin" }),
|
|
11105
|
+
probeTargetConfig: require_sleep.method(zod.z.object({
|
|
11106
|
+
kind: zod.z.string(),
|
|
11107
|
+
config: zod.z.record(zod.z.string(), zod.z.unknown()),
|
|
11108
|
+
/** See `discoverTargets.targetId` — restore stored secrets for a blank password. */
|
|
11109
|
+
targetId: zod.z.string().optional()
|
|
11110
|
+
}), ProbeTargetConfigResultSchema, {
|
|
11111
|
+
kind: "mutation",
|
|
11112
|
+
auth: "admin"
|
|
11113
|
+
}),
|
|
11114
|
+
send: require_sleep.method(zod.z.object({
|
|
11115
|
+
targetId: zod.z.string(),
|
|
11116
|
+
notification: NotificationSchema
|
|
11117
|
+
}), SendResultSchema, {
|
|
11118
|
+
kind: "mutation",
|
|
11119
|
+
auth: "admin"
|
|
11120
|
+
}),
|
|
11121
|
+
testTarget: require_sleep.method(zod.z.object({
|
|
11122
|
+
targetId: zod.z.string(),
|
|
11123
|
+
sample: NotificationSchema.optional()
|
|
11124
|
+
}), TestResultSchema, {
|
|
11125
|
+
kind: "mutation",
|
|
11126
|
+
auth: "admin"
|
|
11127
|
+
}),
|
|
11128
|
+
upsertTarget: require_sleep.method(zod.z.object({
|
|
11129
|
+
target: TargetSchema,
|
|
11130
|
+
/**
|
|
11131
|
+
* Duplicate flow: create a NEW target id while copying secrets from an
|
|
11132
|
+
* existing row. The UI never holds the stored token; blank / redacted
|
|
11133
|
+
* password fields are restored from this source (D634 still applies if
|
|
11134
|
+
* destinations diverge without a re-typed secret).
|
|
11135
|
+
*/
|
|
11136
|
+
cloneSecretsFrom: zod.z.string().optional()
|
|
11137
|
+
}), TargetSchema, {
|
|
11138
|
+
kind: "mutation",
|
|
11139
|
+
auth: "admin"
|
|
11140
|
+
}),
|
|
11141
|
+
deleteTarget: require_sleep.method(zod.z.object({ targetId: zod.z.string() }), zod.z.void(), {
|
|
11142
|
+
kind: "mutation",
|
|
11143
|
+
auth: "admin"
|
|
11144
|
+
}),
|
|
11145
|
+
setTargetEnabled: require_sleep.method(zod.z.object({
|
|
11146
|
+
targetId: zod.z.string(),
|
|
11147
|
+
enabled: zod.z.boolean()
|
|
11148
|
+
}), zod.z.void(), {
|
|
11149
|
+
kind: "mutation",
|
|
11150
|
+
auth: "admin"
|
|
11151
|
+
})
|
|
11152
|
+
}
|
|
11153
|
+
};
|
|
11154
|
+
//#endregion
|
|
11155
|
+
//#region src/automation/export-entities.ts
|
|
11156
|
+
function errorText(err) {
|
|
11157
|
+
return err instanceof Error ? err.message : String(err);
|
|
11158
|
+
}
|
|
11159
|
+
/** `actions.run` flattens a refusal to `[code] text`; the code leads. */
|
|
11160
|
+
function refusalFromThrown(message) {
|
|
11161
|
+
if (message.startsWith("[busy]")) return "already-running";
|
|
11162
|
+
if (message.startsWith("[not-found]")) return "not-found";
|
|
11163
|
+
return null;
|
|
11164
|
+
}
|
|
11165
|
+
async function runExportedAction(api, log, input) {
|
|
11166
|
+
const { exporter, actionId } = input;
|
|
11167
|
+
const tags = { actionId };
|
|
11168
|
+
const refuse = (reason, detail) => {
|
|
11169
|
+
log.warn(`${exporter}: exported action not run — ${reason}`, {
|
|
11170
|
+
tags,
|
|
11171
|
+
meta: {
|
|
11172
|
+
reason,
|
|
11173
|
+
...detail ? { detail } : {}
|
|
11174
|
+
}
|
|
11175
|
+
});
|
|
11176
|
+
return {
|
|
11177
|
+
status: "refused",
|
|
11178
|
+
reason
|
|
11179
|
+
};
|
|
11180
|
+
};
|
|
11181
|
+
try {
|
|
11182
|
+
const result = await api.actions.run.mutate({ actionId });
|
|
11183
|
+
if (result.outcome === "skipped-overlap") return refuse("already-running", result.message);
|
|
11184
|
+
if (result.outcome === "skipped-cooldown") return refuse("cooldown", result.message);
|
|
11185
|
+
if (result.outcome === "failed" || result.outcome === "aborted") {
|
|
11186
|
+
const message = result.message ?? result.outcome;
|
|
11187
|
+
log.warn(`${exporter}: exported action failed`, {
|
|
11188
|
+
tags,
|
|
11189
|
+
meta: {
|
|
11190
|
+
outcome: result.outcome,
|
|
11191
|
+
message
|
|
11192
|
+
}
|
|
11193
|
+
});
|
|
11194
|
+
return {
|
|
11195
|
+
status: "failed",
|
|
11196
|
+
message
|
|
11197
|
+
};
|
|
11198
|
+
}
|
|
11199
|
+
log.info(`${exporter}: exported action ran`, {
|
|
11200
|
+
tags,
|
|
11201
|
+
meta: { outcome: result.outcome }
|
|
11202
|
+
});
|
|
11203
|
+
return { status: "started" };
|
|
11204
|
+
} catch (err) {
|
|
11205
|
+
const message = errorText(err);
|
|
11206
|
+
const reason = refusalFromThrown(message);
|
|
11207
|
+
if (reason !== null) return refuse(reason, message);
|
|
11208
|
+
log.warn(`${exporter}: exported action failed`, {
|
|
11209
|
+
tags,
|
|
11210
|
+
meta: { message }
|
|
11211
|
+
});
|
|
11212
|
+
return {
|
|
11213
|
+
status: "failed",
|
|
11214
|
+
message
|
|
11215
|
+
};
|
|
11216
|
+
}
|
|
11217
|
+
}
|
|
11218
|
+
/** Send through one CamStack notification target on behalf of an exporter. */
|
|
11219
|
+
async function sendToExportedTarget(api, log, input) {
|
|
11220
|
+
const { exporter, targetId } = input;
|
|
11221
|
+
const tags = { targetId };
|
|
11222
|
+
try {
|
|
11223
|
+
const target = (await api.notificationOutput.listTargets.query({})).find((t) => t.id === targetId);
|
|
11224
|
+
if (target === void 0) {
|
|
11225
|
+
log.warn(`${exporter}: exported notifier not used — target-gone`, {
|
|
11226
|
+
tags,
|
|
11227
|
+
meta: { reason: "target-gone" }
|
|
11228
|
+
});
|
|
11229
|
+
return {
|
|
11230
|
+
status: "refused",
|
|
11231
|
+
reason: "target-gone"
|
|
11232
|
+
};
|
|
11233
|
+
}
|
|
11234
|
+
if (!target.enabled) {
|
|
11235
|
+
log.warn(`${exporter}: exported notifier not used — target-disabled`, {
|
|
11236
|
+
tags,
|
|
11237
|
+
meta: { reason: "target-disabled" }
|
|
11238
|
+
});
|
|
11239
|
+
return {
|
|
11240
|
+
status: "refused",
|
|
11241
|
+
reason: "target-disabled"
|
|
11242
|
+
};
|
|
11243
|
+
}
|
|
11244
|
+
const result = await api.notificationOutput.send.mutate({
|
|
11245
|
+
targetId,
|
|
11246
|
+
addonId: target.addonId,
|
|
11247
|
+
notification: NotificationSchema.parse(input.notification)
|
|
11248
|
+
});
|
|
11249
|
+
if (!result.success) {
|
|
11250
|
+
const message = result.error ?? "send failed";
|
|
11251
|
+
log.warn(`${exporter}: exported notifier send failed`, {
|
|
11252
|
+
tags,
|
|
11253
|
+
meta: { message }
|
|
11254
|
+
});
|
|
11255
|
+
return {
|
|
11256
|
+
status: "failed",
|
|
11257
|
+
message
|
|
11258
|
+
};
|
|
11259
|
+
}
|
|
11260
|
+
return { status: "sent" };
|
|
11261
|
+
} catch (err) {
|
|
11262
|
+
const message = errorText(err);
|
|
11263
|
+
log.warn(`${exporter}: exported notifier send failed`, {
|
|
11264
|
+
tags,
|
|
11265
|
+
meta: { message }
|
|
11266
|
+
});
|
|
11267
|
+
return {
|
|
11268
|
+
status: "failed",
|
|
11269
|
+
message
|
|
11270
|
+
};
|
|
11271
|
+
}
|
|
11272
|
+
}
|
|
11273
|
+
/**
|
|
11274
|
+
* Split an exporter's selection into what still exists and what was deleted.
|
|
11275
|
+
* Devices are never judged here (their lifecycle is the tombstone, D865).
|
|
11276
|
+
* Callers pass ids from a query that ANSWERED — an unanswered list must not
|
|
11277
|
+
* reach this function (D49: a failed read changes nothing).
|
|
11278
|
+
*/
|
|
11279
|
+
function pruneDeletedEntities(selection, live, log, exporter) {
|
|
11280
|
+
const kept = [];
|
|
11281
|
+
const dropped = [];
|
|
11282
|
+
for (const ref of selection) if (ref.kind === "action" && !live.actionIds.has(ref.actionId)) {
|
|
11283
|
+
dropped.push(ref);
|
|
11284
|
+
log.warn(`${exporter}: exported action was deleted — dropped from the export`, { tags: { actionId: ref.actionId } });
|
|
11285
|
+
} else if (ref.kind === "notifier" && !live.targetIds.has(ref.targetId)) {
|
|
11286
|
+
dropped.push(ref);
|
|
11287
|
+
log.warn(`${exporter}: exported notifier target was deleted — dropped from the export`, { tags: { targetId: ref.targetId } });
|
|
11288
|
+
} else kept.push(ref);
|
|
11289
|
+
return {
|
|
11290
|
+
kept,
|
|
11291
|
+
dropped
|
|
11292
|
+
};
|
|
11293
|
+
}
|
|
11294
|
+
//#endregion
|
|
10708
11295
|
//#region src/capabilities/addon-pages.cap.ts
|
|
10709
11296
|
/**
|
|
10710
11297
|
* `addon-pages` — system-scoped singleton aggregator cap. Public-facing
|
|
@@ -10744,71 +11331,6 @@ var addonPagesCapability = {
|
|
|
10744
11331
|
methods: { listPages: require_sleep.method(zod.z.void(), zod.z.array(AddonPageInfoSchema).readonly()) }
|
|
10745
11332
|
};
|
|
10746
11333
|
//#endregion
|
|
10747
|
-
//#region src/capabilities/addon-pages-source.cap.ts
|
|
10748
|
-
/**
|
|
10749
|
-
* `addon-pages-source` — collection cap exposing per-provider raw page
|
|
10750
|
-
* declarations. Every addon that contributes a UI page registers a
|
|
10751
|
-
* provider here. The hub-side singleton aggregator (`addon-pages` cap,
|
|
10752
|
-
* see `addon-pages.cap.ts`) walks this collection, stamps versioned
|
|
10753
|
-
* `bundleUrl` values, and returns the enriched `AddonPageInfo[]` list
|
|
10754
|
-
* that admin-ui consumes.
|
|
10755
|
-
*
|
|
10756
|
-
* The split exists because the public listing has a different output
|
|
10757
|
-
* shape than the per-provider raw declarations, and we want both ends
|
|
10758
|
-
* to flow through codegen instead of relying on a hand-written wrapper.
|
|
10759
|
-
*/
|
|
10760
|
-
var AddonPageDeclarationSchema = zod.z.object({
|
|
10761
|
-
id: zod.z.string(),
|
|
10762
|
-
label: zod.z.string(),
|
|
10763
|
-
icon: zod.z.string(),
|
|
10764
|
-
path: zod.z.string(),
|
|
10765
|
-
/**
|
|
10766
|
-
* Module Federation remote name — must match the `name` field on the
|
|
10767
|
-
* page addon's `federation()` plugin config. Used by admin-ui's
|
|
10768
|
-
* `<AddonPageLoader>` to call `loadRemote('<remoteName>/page')`.
|
|
10769
|
-
* Conventionally `addon_<id>_page` (snake_case; MF names cannot
|
|
10770
|
-
* contain hyphens).
|
|
10771
|
-
*/
|
|
10772
|
-
remoteName: zod.z.string(),
|
|
10773
|
-
/**
|
|
10774
|
-
* Bundle filename inside the addon's `dist/` dir served at
|
|
10775
|
-
* `/api/addon-pages/<addonId>/<bundle>`. With Module Federation this
|
|
10776
|
-
* is always `'remoteEntry.js'`; the value is kept on the metadata so
|
|
10777
|
-
* the static-file route can compute an mtime-based cache-buster URL
|
|
10778
|
-
* without a separate filesystem stat.
|
|
10779
|
-
*/
|
|
10780
|
-
bundle: zod.z.string(),
|
|
10781
|
-
/**
|
|
10782
|
-
* Sidebar section this page docks into. Well-known ids: `'detection'`,
|
|
10783
|
-
* `'cluster'`, `'administration'` — the page renders inside that group.
|
|
10784
|
-
* Any OTHER string creates (or joins) a custom section rendered after
|
|
10785
|
-
* the built-in groups; its label comes from `sectionLabel` (first
|
|
10786
|
-
* declaration wins), falling back to the id. Absent → the legacy
|
|
10787
|
-
* "Addon Pages" group.
|
|
10788
|
-
*/
|
|
10789
|
-
section: zod.z.string().optional(),
|
|
10790
|
-
/** Display label for a CUSTOM `section` id (ignored for well-known ids). */
|
|
10791
|
-
sectionLabel: zod.z.string().optional()
|
|
10792
|
-
});
|
|
10793
|
-
var addonPagesSourceCapability = {
|
|
10794
|
-
name: "addon-pages-source",
|
|
10795
|
-
scope: "system",
|
|
10796
|
-
mode: "collection",
|
|
10797
|
-
internal: true,
|
|
10798
|
-
methods: {
|
|
10799
|
-
/**
|
|
10800
|
-
* `internal: true` did not gate the mount (see the 2026-08-26 note on
|
|
10801
|
-
* `data-store-provider`) — this was reachable on the AppRouter by ANY
|
|
10802
|
-
* authenticated session at the default `auth: 'protected'`. The only
|
|
10803
|
-
* consumer, the `addon-pages-aggregator` builtin, reads it via
|
|
10804
|
-
* `ctx.capabilities.getCollection('addon-pages-source')` — LOCAL-PROCESS
|
|
10805
|
-
* only, never tRPC (per `ctx.capabilities` seeing only the local
|
|
10806
|
-
* process). The public, enriched listing admin-ui actually consumes is
|
|
10807
|
-
* the separate `addon-pages` cap, unaffected by this change.
|
|
10808
|
-
*/
|
|
10809
|
-
listPages: require_sleep.method(zod.z.void(), zod.z.array(AddonPageDeclarationSchema).readonly(), { auth: "admin" }) }
|
|
10810
|
-
};
|
|
10811
|
-
//#endregion
|
|
10812
11334
|
//#region src/capabilities/addon-routes.cap.ts
|
|
10813
11335
|
var AddonHttpRouteSchema = zod.z.object({
|
|
10814
11336
|
method: zod.z.enum([
|
|
@@ -14915,7 +15437,11 @@ var CompositionProblemCodeSchema = zod.z.enum([
|
|
|
14915
15437
|
"mixed-quantity",
|
|
14916
15438
|
"helper-mismatch",
|
|
14917
15439
|
"member-constraint",
|
|
14918
|
-
"retention"
|
|
15440
|
+
"retention",
|
|
15441
|
+
"command-method-unknown",
|
|
15442
|
+
"command-source-unknown",
|
|
15443
|
+
"command-input-unknown",
|
|
15444
|
+
"command-input-missing"
|
|
14919
15445
|
]);
|
|
14920
15446
|
/** One refusal, named (D391). `path` points into the composition, e.g. `features[0].fields.temperature`. */
|
|
14921
15447
|
var CompositionProblemSchema = zod.z.object({
|
|
@@ -14957,7 +15483,9 @@ var CompositionFieldRoleSchema = zod.z.enum([
|
|
|
14957
15483
|
var CompositionFieldItemSchema = zod.z.object({
|
|
14958
15484
|
arrayPath: zod.z.string(),
|
|
14959
15485
|
key: zod.z.string(),
|
|
14960
|
-
label: zod.z.string()
|
|
15486
|
+
label: zod.z.string(),
|
|
15487
|
+
/** True when the item carries a `reset` forward: the composer writes `resettable` from this (D967). */
|
|
15488
|
+
resettable: zod.z.boolean().optional()
|
|
14961
15489
|
});
|
|
14962
15490
|
var CompositionFieldPlanSchema = zod.z.object({
|
|
14963
15491
|
cap: zod.z.string(),
|
|
@@ -15478,7 +16006,7 @@ function unavailableFor(tf, role, mode, cap, at) {
|
|
|
15478
16006
|
}
|
|
15479
16007
|
//#endregion
|
|
15480
16008
|
//#region src/composition/composition-items.ts
|
|
15481
|
-
/** Item fields the composer writes itself, with the value it writes. */
|
|
16009
|
+
/** Item fields the composer writes itself, with the value it writes. `resettable` is the default: an item with a `reset` forward writes `true` (D967). */
|
|
15482
16010
|
var COMPOSED_ITEM_FIXED_FIELDS = { resettable: false };
|
|
15483
16011
|
function reservedItemFields(itemArray) {
|
|
15484
16012
|
return new Set([
|
|
@@ -15521,7 +16049,8 @@ function planItemField(ctx, leaf) {
|
|
|
15521
16049
|
item: {
|
|
15522
16050
|
arrayPath: itemArray.path,
|
|
15523
16051
|
key,
|
|
15524
|
-
label
|
|
16052
|
+
label,
|
|
16053
|
+
...leaf.resettable ? { resettable: true } : {}
|
|
15525
16054
|
},
|
|
15526
16055
|
featureIndex,
|
|
15527
16056
|
kind: tf.kind,
|
|
@@ -15561,6 +16090,7 @@ function planItems(def, feature, featureIndex, lookupCap, mode = "new") {
|
|
|
15561
16090
|
}, ...Object.entries(item.fields).map(([path, source]) => planItemField(ctx, {
|
|
15562
16091
|
key,
|
|
15563
16092
|
label: item.label,
|
|
16093
|
+
resettable: item.reset !== void 0,
|
|
15564
16094
|
path,
|
|
15565
16095
|
source
|
|
15566
16096
|
}))]);
|
|
@@ -15572,12 +16102,163 @@ function planItems(def, feature, featureIndex, lookupCap, mode = "new") {
|
|
|
15572
16102
|
};
|
|
15573
16103
|
}
|
|
15574
16104
|
//#endregion
|
|
16105
|
+
//#region src/composition/validate-forward.ts
|
|
16106
|
+
/**
|
|
16107
|
+
* Save-time validation of `forward` commands (D659, amended by D967).
|
|
16108
|
+
*
|
|
16109
|
+
* A BUILT capability serves a method only through a command, so every method
|
|
16110
|
+
* the cap serves needs one. A forward is checked against the two input schemas
|
|
16111
|
+
* it joins: the BUILT method's (what the caller sends) and the SOURCE method's
|
|
16112
|
+
* (what is called). An input field in neither place is refused BY NAME, and so
|
|
16113
|
+
* is a required source input nothing provides. `deviceId` is the source's own
|
|
16114
|
+
* and is never an argument.
|
|
16115
|
+
*
|
|
16116
|
+
* Static: it needs only the capability definitions. That the source DEVICE
|
|
16117
|
+
* exists and binds the cap is `forwardSourceProblems`, with the sources read.
|
|
16118
|
+
*/
|
|
16119
|
+
var DEVICE_ID_FIELD = "deviceId";
|
|
16120
|
+
/** Every forward of a feature: the method commands, then each item's `reset`. */
|
|
16121
|
+
function featureForwards(feature, featureIndex) {
|
|
16122
|
+
const at = `features[${featureIndex}]`;
|
|
16123
|
+
const commands = Object.entries(feature.commands ?? {}).flatMap(([method, target]) => target.kind === "forward" ? [{
|
|
16124
|
+
at: `${at}.commands.${method}`,
|
|
16125
|
+
method,
|
|
16126
|
+
command: target
|
|
16127
|
+
}] : []);
|
|
16128
|
+
const resets = Object.entries(feature.items ?? {}).flatMap(([key, item]) => item.reset === void 0 ? [] : [{
|
|
16129
|
+
at: `${at}.items.${key}.reset`,
|
|
16130
|
+
method: "reset",
|
|
16131
|
+
itemKey: key,
|
|
16132
|
+
command: item.reset
|
|
16133
|
+
}]);
|
|
16134
|
+
return [...commands, ...resets];
|
|
16135
|
+
}
|
|
16136
|
+
/** Every source a forward of an enabled feature calls, once. */
|
|
16137
|
+
function forwardSourceRefs(composition) {
|
|
16138
|
+
const refs = composition.features.flatMap((feature, index) => feature.kind === "fields" && require_composition.compositionFeatureEnabled(feature) ? featureForwards(feature, index).map((forward) => forward.command.source) : []);
|
|
16139
|
+
return [...new Map(refs.map((ref) => [require_composition.compositionSourceKey(ref), ref])).values()];
|
|
16140
|
+
}
|
|
16141
|
+
/** The methods a BUILT cap must give a command: served, and not answered by the composer itself. */
|
|
16142
|
+
function commandedMethods(def) {
|
|
16143
|
+
return Object.entries(def.methods).filter(([name, m]) => m.systemOnly !== true && def.composedMethods?.[name] === void 0).map(([name]) => name);
|
|
16144
|
+
}
|
|
16145
|
+
var NO_INPUT = {
|
|
16146
|
+
all: /* @__PURE__ */ new Set(),
|
|
16147
|
+
required: /* @__PURE__ */ new Set()
|
|
16148
|
+
};
|
|
16149
|
+
/** The top-level input fields of a method, `deviceId` removed; null when the input is not an object. */
|
|
16150
|
+
function inputFields(def, method) {
|
|
16151
|
+
const input = def.methods[method]?.input;
|
|
16152
|
+
if (input === void 0) return null;
|
|
16153
|
+
const root = unwrapSchema(input);
|
|
16154
|
+
if (!(root instanceof zod.z.ZodObject)) return null;
|
|
16155
|
+
const entries = Object.entries(root.shape).filter(([name]) => name !== DEVICE_ID_FIELD);
|
|
16156
|
+
return {
|
|
16157
|
+
all: new Set(entries.map(([name]) => name)),
|
|
16158
|
+
required: new Set(entries.flatMap(([name, field]) => field instanceof zod.z.ZodType && !field.safeParse(void 0).success ? [name] : []))
|
|
16159
|
+
};
|
|
16160
|
+
}
|
|
16161
|
+
function inputRefs(arg) {
|
|
16162
|
+
if (typeof arg !== "object") return [];
|
|
16163
|
+
if (require_composition.isForwardInputRef(arg)) return [arg.$input];
|
|
16164
|
+
return Object.values(arg).flatMap(inputRefs);
|
|
16165
|
+
}
|
|
16166
|
+
function names(list) {
|
|
16167
|
+
return [...list].map((name) => `\`${name}\``).join(", ");
|
|
16168
|
+
}
|
|
16169
|
+
function sourceMethodOf(forward, lookupCap) {
|
|
16170
|
+
const { command, at } = forward;
|
|
16171
|
+
const def = lookupCap(command.cap);
|
|
16172
|
+
if (def === null) return {
|
|
16173
|
+
def: null,
|
|
16174
|
+
problems: [problem("command-source-unknown", `${at}.cap`, `no capability is named \`${command.cap}\``)]
|
|
16175
|
+
};
|
|
16176
|
+
const served = def.methods[command.method];
|
|
16177
|
+
if (served === void 0 || served.systemOnly === true) return {
|
|
16178
|
+
def: null,
|
|
16179
|
+
problems: [problem("command-source-unknown", `${at}.method`, `\`${command.cap}\` has no method \`${command.method}\` to forward to`)]
|
|
16180
|
+
};
|
|
16181
|
+
if (served.kind !== "mutation") return {
|
|
16182
|
+
def: null,
|
|
16183
|
+
problems: [problem("command-source-unknown", `${at}.method`, `\`${command.cap}.${command.method}\` is a query — a command calls a mutation of the source`)]
|
|
16184
|
+
};
|
|
16185
|
+
return {
|
|
16186
|
+
def,
|
|
16187
|
+
problems: []
|
|
16188
|
+
};
|
|
16189
|
+
}
|
|
16190
|
+
function mappedInputProblems(forward, built, source, args) {
|
|
16191
|
+
const { at, command } = forward;
|
|
16192
|
+
const where = `${command.cap}.${command.method}`;
|
|
16193
|
+
const problems = [];
|
|
16194
|
+
if ("deviceId" in args) problems.push(problem("command-input-unknown", `${at}.args.${DEVICE_ID_FIELD}`, `\`${DEVICE_ID_FIELD}\` is the source device's own — a forward never takes it as an argument`));
|
|
16195
|
+
if (source !== null) {
|
|
16196
|
+
for (const key of Object.keys(args).filter((k) => k !== "deviceId" && !source.all.has(k))) problems.push(problem("command-input-unknown", `${at}.args.${key}`, `\`${where}\` has no input field \`${key}\` (it takes ${names(source.all)})`));
|
|
16197
|
+
const missing = [...source.required].filter((k) => !(k in args));
|
|
16198
|
+
if (missing.length > 0) problems.push(problem("command-input-missing", `${at}.args`, `\`${where}\` needs ${names(missing)}, which \`args\` does not provide`));
|
|
16199
|
+
}
|
|
16200
|
+
const readable = forward.itemKey === void 0 ? built : NO_INPUT;
|
|
16201
|
+
if (readable !== null) for (const ref of Object.values(args).flatMap(inputRefs)) {
|
|
16202
|
+
if (readable.all.has(ref)) continue;
|
|
16203
|
+
problems.push(problem("command-input-unknown", `${at}.args`, readable === NO_INPUT ? `an item's \`reset\` takes no input — \`$input: ${ref}\` has nothing to read` : `\`$input: ${ref}\` is not a field of the \`${forward.method}\` input (it takes ${names(readable.all)})`));
|
|
16204
|
+
}
|
|
16205
|
+
return problems;
|
|
16206
|
+
}
|
|
16207
|
+
function passthroughInputProblems(forward, built, source) {
|
|
16208
|
+
const { at, command } = forward;
|
|
16209
|
+
const where = `${command.cap}.${command.method}`;
|
|
16210
|
+
const sent = forward.itemKey === void 0 ? built : NO_INPUT;
|
|
16211
|
+
if (sent === null || source === null) return [];
|
|
16212
|
+
const problems = [];
|
|
16213
|
+
for (const field of [...sent.all].filter((f) => !source.all.has(f))) problems.push(problem("command-input-unknown", `${at}.args`, `\`${forward.method}\` takes \`${field}\`, which \`${where}\` does not (it takes ${names(source.all)}) — add \`args\` to map it`));
|
|
16214
|
+
const missing = [...source.required].filter((k) => !sent.all.has(k));
|
|
16215
|
+
if (missing.length > 0) problems.push(problem("command-input-missing", `${at}.args`, `\`${where}\` needs ${names(missing)}, which \`${forward.method}\` does not take — add \`args\` to provide it`));
|
|
16216
|
+
return problems;
|
|
16217
|
+
}
|
|
16218
|
+
/** One forward against the built cap's method and the source cap's method. */
|
|
16219
|
+
function forwardProblems(built, forward, lookupCap) {
|
|
16220
|
+
const source = sourceMethodOf(forward, lookupCap);
|
|
16221
|
+
if (source.def === null) return source.problems;
|
|
16222
|
+
const builtFields = inputFields(built, forward.method);
|
|
16223
|
+
const sourceFields = inputFields(source.def, forward.command.method);
|
|
16224
|
+
const mapping = forward.command.args;
|
|
16225
|
+
return mapping === void 0 ? passthroughInputProblems(forward, builtFields, sourceFields) : mappedInputProblems(forward, builtFields, sourceFields, mapping);
|
|
16226
|
+
}
|
|
16227
|
+
/** A command must name a method the built cap serves and the composer does not answer itself. */
|
|
16228
|
+
function commandMethodProblems(built, feature, at) {
|
|
16229
|
+
const commanded = new Set(commandedMethods(built));
|
|
16230
|
+
return Object.keys(feature.commands ?? {}).flatMap((method) => {
|
|
16231
|
+
if (commanded.has(method)) return [];
|
|
16232
|
+
const answered = built.composedMethods?.[method] !== void 0;
|
|
16233
|
+
return [problem("command-method-unknown", `${at}.commands.${method}`, answered ? `\`${built.name}.${method}\` is answered by the composer itself — an item's \`reset\` serves it` : `\`${built.name}\` has no method \`${method}\` to serve`)];
|
|
16234
|
+
});
|
|
16235
|
+
}
|
|
16236
|
+
/**
|
|
16237
|
+
* The source DEVICES of the forwards, read: each must exist and bind the cap it
|
|
16238
|
+
* is called on. A forward onto an unread device is refused rather than stored
|
|
16239
|
+
* unchecked, like every other source (D391).
|
|
16240
|
+
*/
|
|
16241
|
+
function forwardSourceProblems(composition, sources) {
|
|
16242
|
+
return composition.features.flatMap((feature, index) => {
|
|
16243
|
+
if (feature.kind !== "fields" || !require_composition.compositionFeatureEnabled(feature)) return [];
|
|
16244
|
+
return featureForwards(feature, index).flatMap((forward) => {
|
|
16245
|
+
const key = require_composition.compositionSourceKey(forward.command.source);
|
|
16246
|
+
const desc = sources.get(key);
|
|
16247
|
+
const at = `${forward.at}.source`;
|
|
16248
|
+
if (desc === void 0 || desc.kind === "unreadable") return [problem("source-unreadable", at, `could not read source \`${key}\` (${desc === void 0 ? "it was not read" : desc.error}) — the save is refused rather than stored unchecked`)];
|
|
16249
|
+
if (desc.kind === "absent") return [problem("source-missing", at, `source \`${key}\` does not exist`)];
|
|
16250
|
+
if (!desc.caps.has(forward.command.cap)) return [problem("source-capability-missing", at, `source \`${key}\` (device ${desc.deviceId}) has no \`${forward.command.cap}\``)];
|
|
16251
|
+
return [];
|
|
16252
|
+
});
|
|
16253
|
+
});
|
|
16254
|
+
}
|
|
16255
|
+
//#endregion
|
|
15575
16256
|
//#region src/composition/helpers/catalog.ts
|
|
15576
16257
|
/**
|
|
15577
16258
|
* One catalog row per base reading a group helper can build (D944 §3).
|
|
15578
16259
|
* Data, not a form default written into the block.
|
|
15579
16260
|
*/
|
|
15580
|
-
var NOW$
|
|
16261
|
+
var NOW$3 = {
|
|
15581
16262
|
fieldPath: "lastFetchedAt",
|
|
15582
16263
|
expr: "now"
|
|
15583
16264
|
};
|
|
@@ -15629,7 +16310,7 @@ var GROUP_TEMPLATES = [
|
|
|
15629
16310
|
quantity: "temperature",
|
|
15630
16311
|
defaultAggregate: "mean",
|
|
15631
16312
|
empty: "null",
|
|
15632
|
-
companions: [NOW$
|
|
16313
|
+
companions: [NOW$3],
|
|
15633
16314
|
alsoFrom: {
|
|
15634
16315
|
deviceTypes: CLIMATE_DEVICES,
|
|
15635
16316
|
accept: {
|
|
@@ -15647,7 +16328,7 @@ var GROUP_TEMPLATES = [
|
|
|
15647
16328
|
quantity: "humidity",
|
|
15648
16329
|
defaultAggregate: "mean",
|
|
15649
16330
|
empty: "null",
|
|
15650
|
-
companions: [NOW$
|
|
16331
|
+
companions: [NOW$3],
|
|
15651
16332
|
alsoFrom: {
|
|
15652
16333
|
deviceTypes: CLIMATE_DEVICES,
|
|
15653
16334
|
accept: {
|
|
@@ -15665,7 +16346,7 @@ var GROUP_TEMPLATES = [
|
|
|
15665
16346
|
quantity: "pressure",
|
|
15666
16347
|
defaultAggregate: "mean",
|
|
15667
16348
|
empty: "null",
|
|
15668
|
-
companions: [NOW$
|
|
16349
|
+
companions: [NOW$3]
|
|
15669
16350
|
}),
|
|
15670
16351
|
numeric({
|
|
15671
16352
|
id: "illuminance",
|
|
@@ -15676,7 +16357,7 @@ var GROUP_TEMPLATES = [
|
|
|
15676
16357
|
quantity: "illuminance",
|
|
15677
16358
|
defaultAggregate: "mean",
|
|
15678
16359
|
empty: "null",
|
|
15679
|
-
companions: [NOW$
|
|
16360
|
+
companions: [NOW$3]
|
|
15680
16361
|
}),
|
|
15681
16362
|
numeric({
|
|
15682
16363
|
id: "power",
|
|
@@ -15687,7 +16368,7 @@ var GROUP_TEMPLATES = [
|
|
|
15687
16368
|
quantity: "power",
|
|
15688
16369
|
defaultAggregate: "sum",
|
|
15689
16370
|
empty: "omit",
|
|
15690
|
-
companions: [NOW$
|
|
16371
|
+
companions: [NOW$3]
|
|
15691
16372
|
}),
|
|
15692
16373
|
numeric({
|
|
15693
16374
|
id: "energy",
|
|
@@ -15698,7 +16379,7 @@ var GROUP_TEMPLATES = [
|
|
|
15698
16379
|
quantity: "energy",
|
|
15699
16380
|
defaultAggregate: "sum",
|
|
15700
16381
|
empty: "omit",
|
|
15701
|
-
companions: [NOW$
|
|
16382
|
+
companions: [NOW$3]
|
|
15702
16383
|
}),
|
|
15703
16384
|
numeric({
|
|
15704
16385
|
id: "battery",
|
|
@@ -15733,7 +16414,7 @@ var GROUP_TEMPLATES = [
|
|
|
15733
16414
|
quantity: "device",
|
|
15734
16415
|
defaultAggregate: "mean",
|
|
15735
16416
|
empty: "null",
|
|
15736
|
-
companions: [NOW$
|
|
16417
|
+
companions: [NOW$3]
|
|
15737
16418
|
}),
|
|
15738
16419
|
binary({
|
|
15739
16420
|
id: "motion",
|
|
@@ -16159,7 +16840,7 @@ async function runFanOut(calls, invoke) {
|
|
|
16159
16840
|
//#region src/generated/history-catalog.ts
|
|
16160
16841
|
/**
|
|
16161
16842
|
* Cap history catalog, projected from every `*.cap.ts` `history` block.
|
|
16162
|
-
*
|
|
16843
|
+
* 42 caps with series (80 series), 34 caps answered `'none'`.
|
|
16163
16844
|
* Field keys are `runtimeState` paths (`a.b` into fixed objects only).
|
|
16164
16845
|
*/
|
|
16165
16846
|
var HISTORY_CATALOG = {
|
|
@@ -16399,6 +17080,25 @@ var HISTORY_CATALOG = {
|
|
|
16399
17080
|
unit: "s"
|
|
16400
17081
|
}
|
|
16401
17082
|
},
|
|
17083
|
+
"pet-fountain": {
|
|
17084
|
+
"waterLevel": {
|
|
17085
|
+
kind: "gauge",
|
|
17086
|
+
unit: "%",
|
|
17087
|
+
deadband: 1
|
|
17088
|
+
},
|
|
17089
|
+
"waterVolume": {
|
|
17090
|
+
kind: "gauge",
|
|
17091
|
+
unit: "L"
|
|
17092
|
+
},
|
|
17093
|
+
"todayDrink": {
|
|
17094
|
+
kind: "gauge",
|
|
17095
|
+
unit: "L"
|
|
17096
|
+
},
|
|
17097
|
+
"last24hDrink": {
|
|
17098
|
+
kind: "gauge",
|
|
17099
|
+
unit: "L"
|
|
17100
|
+
}
|
|
17101
|
+
},
|
|
16402
17102
|
"power-meter": {
|
|
16403
17103
|
"power": {
|
|
16404
17104
|
kind: "gauge",
|
|
@@ -16596,7 +17296,7 @@ function historyFieldsFor(capName) {
|
|
|
16596
17296
|
* Project a statistics or integral helper onto a new device (D944 §3).
|
|
16597
17297
|
* The value field is `series`: the composer fills it from history.
|
|
16598
17298
|
*/
|
|
16599
|
-
var NOW$
|
|
17299
|
+
var NOW$2 = {
|
|
16600
17300
|
kind: "expression",
|
|
16601
17301
|
expr: "now",
|
|
16602
17302
|
bindings: {}
|
|
@@ -16656,7 +17356,7 @@ function draft(input) {
|
|
|
16656
17356
|
cap: input.cap,
|
|
16657
17357
|
fields: {
|
|
16658
17358
|
[input.field]: series(input.member, "value", input.empty),
|
|
16659
|
-
lastFetchedAt: NOW$
|
|
17359
|
+
lastFetchedAt: NOW$2
|
|
16660
17360
|
}
|
|
16661
17361
|
}, {
|
|
16662
17362
|
kind: "fields",
|
|
@@ -16738,12 +17438,12 @@ function integralDraft(spec, retention = require_composition.DEFAULT_HISTORY_RET
|
|
|
16738
17438
|
* a free expression is the expression engine unchanged — it still includes a
|
|
16739
17439
|
* stale input, and the template says so.
|
|
16740
17440
|
*/
|
|
16741
|
-
var NOW = {
|
|
17441
|
+
var NOW$1 = {
|
|
16742
17442
|
kind: "expression",
|
|
16743
17443
|
expr: "now",
|
|
16744
17444
|
bindings: {}
|
|
16745
17445
|
};
|
|
16746
|
-
function from$
|
|
17446
|
+
function from$2(member) {
|
|
16747
17447
|
return {
|
|
16748
17448
|
kind: "from",
|
|
16749
17449
|
source: member.source,
|
|
@@ -16774,7 +17474,7 @@ function numericSensor(helper, value, extra = []) {
|
|
|
16774
17474
|
cap: "numeric-sensor",
|
|
16775
17475
|
fields: {
|
|
16776
17476
|
value,
|
|
16777
|
-
lastFetchedAt: NOW
|
|
17477
|
+
lastFetchedAt: NOW$1
|
|
16778
17478
|
}
|
|
16779
17479
|
}, ...extra]
|
|
16780
17480
|
};
|
|
@@ -16792,7 +17492,7 @@ function binarySensor(helper, on) {
|
|
|
16792
17492
|
cap: "binary",
|
|
16793
17493
|
fields: {
|
|
16794
17494
|
on,
|
|
16795
|
-
lastChangedAt: NOW
|
|
17495
|
+
lastChangedAt: NOW$1
|
|
16796
17496
|
}
|
|
16797
17497
|
}]
|
|
16798
17498
|
};
|
|
@@ -16810,7 +17510,7 @@ function thresholdDraft(spec) {
|
|
|
16810
17510
|
const delays = onFor !== null && offFor !== null && (spec.onForMs > 0 || spec.offForMs > 0) ? `, ${onFor}, ${offFor}` : "";
|
|
16811
17511
|
return {
|
|
16812
17512
|
problems,
|
|
16813
|
-
draft: binarySensor(spec, expression$1(`coalesce(schmitt(x, ${high ?? "0"}, ${low ?? "0"}${delays}), false)`, { x: from$
|
|
17513
|
+
draft: binarySensor(spec, expression$1(`coalesce(schmitt(x, ${high ?? "0"}, ${low ?? "0"}${delays}), false)`, { x: from$2(spec.source) }))
|
|
16814
17514
|
};
|
|
16815
17515
|
}
|
|
16816
17516
|
var NAMES = ["a", "b"];
|
|
@@ -16854,7 +17554,7 @@ function arithmeticDraft(spec) {
|
|
|
16854
17554
|
}])
|
|
16855
17555
|
};
|
|
16856
17556
|
}
|
|
16857
|
-
const bindings = Object.fromEntries(spec.inputs.slice(0, 2).map((input, index) => [NAMES[index] ?? "a", from$
|
|
17557
|
+
const bindings = Object.fromEntries(spec.inputs.slice(0, 2).map((input, index) => [NAMES[index] ?? "a", from$2(input)]));
|
|
16858
17558
|
return {
|
|
16859
17559
|
problems,
|
|
16860
17560
|
draft: numericSensor(spec, expression$1(spec.op === "difference" ? "a - b" : "b == 0 ? null : a / b", bindings))
|
|
@@ -16870,7 +17570,7 @@ function expressionProblems(spec) {
|
|
|
16870
17570
|
seen.add(input.name);
|
|
16871
17571
|
});
|
|
16872
17572
|
if (problems.length > 0) return problems;
|
|
16873
|
-
const bindings = Object.fromEntries(spec.inputs.map((input) => [input.name, from$
|
|
17573
|
+
const bindings = Object.fromEntries(spec.inputs.map((input) => [input.name, from$2(input.member)]));
|
|
16874
17574
|
const message = require_composition.validateExpressionSource({
|
|
16875
17575
|
expr: spec.expr,
|
|
16876
17576
|
bindings
|
|
@@ -16879,7 +17579,7 @@ function expressionProblems(spec) {
|
|
|
16879
17579
|
}
|
|
16880
17580
|
function expressionDraft(spec) {
|
|
16881
17581
|
const problems = expressionProblems(spec);
|
|
16882
|
-
const bindings = Object.fromEntries(spec.inputs.map((input) => [input.name, from$
|
|
17582
|
+
const bindings = Object.fromEntries(spec.inputs.map((input) => [input.name, from$2(input.member)]));
|
|
16883
17583
|
const source = expression$1(spec.expr, bindings);
|
|
16884
17584
|
return {
|
|
16885
17585
|
problems,
|
|
@@ -17396,8 +18096,9 @@ function actuatorCommandCaps(composition) {
|
|
|
17396
18096
|
function builtCapProblems({ def, state, fields: targetFields }, feature, at, deviceType, servedCommands) {
|
|
17397
18097
|
const problems = [];
|
|
17398
18098
|
if (def.deviceTypes !== void 0 && !def.deviceTypes.includes(deviceType)) problems.push(problem("wrong-device-type", `${at}.cap`, `\`${def.name}\` is not offered on a \`${deviceType}\` device (it allows ${def.deviceTypes.join(", ")})`));
|
|
17399
|
-
const
|
|
17400
|
-
|
|
18099
|
+
const commanded = new Set(Object.entries(feature.commands ?? {}).flatMap(([name, target]) => target.kind === "forward" ? [name] : []));
|
|
18100
|
+
const unserved = commandedMethods(def).filter((name) => !commanded.has(name)).map((name) => `\`${name}\``);
|
|
18101
|
+
if (unserved.length > 0 && !servedCommands.has(def.name)) problems.push(problem("has-commands", `${at}.cap`, `\`${def.name}\` has ${unserved.join(", ")} with no command — a composed device serves a method only through a \`forward\` (D967)`));
|
|
17401
18102
|
const itemArrayPath = feature.items === void 0 ? null : def.status?.itemArray?.path ?? null;
|
|
17402
18103
|
for (const key of requiredTopLevelKeys(state)) {
|
|
17403
18104
|
if (key === itemArrayPath) continue;
|
|
@@ -17438,12 +18139,28 @@ function planTopLevelField({ def, fields }, field, mode, lookupCap) {
|
|
|
17438
18139
|
events: []
|
|
17439
18140
|
};
|
|
17440
18141
|
}
|
|
18142
|
+
/**
|
|
18143
|
+
* The commands of a feature (D967). Only a BUILT capability on a NEW device
|
|
18144
|
+
* serves a method through a `forward`; on an existing device the native keeps
|
|
18145
|
+
* its methods, and a `code` command is slice 4.
|
|
18146
|
+
*/
|
|
18147
|
+
function commandProblems(def, feature, featureIndex, mode, lookupCap) {
|
|
18148
|
+
const at = `features[${featureIndex}]`;
|
|
18149
|
+
const forwards = featureForwards(feature, featureIndex);
|
|
18150
|
+
const problems = Object.entries(feature.commands ?? {}).filter(([, t]) => t.kind === "code").map(([method]) => problem("reserved-variant", `${at}.commands.${method}`, "a `code` command arrives in slice 4"));
|
|
18151
|
+
if (forwards.length > 0 && mode !== "new") return [...problems, problem("reserved-variant", `${at}.commands`, "commands (`forward`) are served only by a capability a NEW device builds — not on an existing device")];
|
|
18152
|
+
return [
|
|
18153
|
+
...problems,
|
|
18154
|
+
...commandMethodProblems(def, feature, at),
|
|
18155
|
+
...forwards.flatMap((forward) => forwardProblems(def, forward, lookupCap))
|
|
18156
|
+
];
|
|
18157
|
+
}
|
|
17441
18158
|
function planFeature(feature, featureIndex, target, lookupCap, servedCommands) {
|
|
17442
18159
|
const at = `features[${featureIndex}]`;
|
|
17443
18160
|
const cap = composableCap(feature, at, lookupCap);
|
|
17444
18161
|
if ("code" in cap) return refused(cap);
|
|
17445
18162
|
const capProblems = target.mode === "replace" ? [] : [...builtCapProblems(cap, feature, at, target.deviceType, servedCommands)];
|
|
17446
|
-
|
|
18163
|
+
capProblems.push(...commandProblems(cap.def, feature, featureIndex, target.mode, lookupCap));
|
|
17447
18164
|
const perField = Object.entries(feature.fields).map(([path, source]) => planTopLevelField(cap, {
|
|
17448
18165
|
featureIndex,
|
|
17449
18166
|
path,
|
|
@@ -17562,7 +18279,7 @@ function planComposition(composition, lookupCap, target) {
|
|
|
17562
18279
|
}
|
|
17563
18280
|
function compositionSourceRefs(composition) {
|
|
17564
18281
|
const refs = composition.features.flatMap((f) => require_composition.compositionFeatureEnabled(f) && f.kind === "fields" ? require_composition.featureSources(f).flatMap(require_composition.fieldReads).map((r) => r.source) : []);
|
|
17565
|
-
return [...new Map(refs.map((r) => [require_composition.compositionSourceKey(r), r])).values()];
|
|
18282
|
+
return [...new Map([...refs, ...forwardSourceRefs(composition)].map((r) => [require_composition.compositionSourceKey(r), r])).values()];
|
|
17566
18283
|
}
|
|
17567
18284
|
/**
|
|
17568
18285
|
* The candidate's device: the existing target itself, else `self`, else a
|
|
@@ -17698,6 +18415,7 @@ function validateComposition(composition, ctx) {
|
|
|
17698
18415
|
const problems = [
|
|
17699
18416
|
...plan.problems,
|
|
17700
18417
|
...sourceProblems(plan.fields, ctx, self),
|
|
18418
|
+
...forwardSourceProblems(composition, ctx.sources),
|
|
17701
18419
|
...cycles,
|
|
17702
18420
|
...helperSaveProblems(composition, facts)
|
|
17703
18421
|
];
|
|
@@ -21058,6 +21776,36 @@ var ExposeInputSchema = zod.z.object({
|
|
|
21058
21776
|
capabilities: zod.z.array(zod.z.string()).optional()
|
|
21059
21777
|
});
|
|
21060
21778
|
var UnexposeInputSchema = zod.z.object({ deviceId: zod.z.string() });
|
|
21779
|
+
/**
|
|
21780
|
+
* What an exporter may expose besides devices (D968). An action and a
|
|
21781
|
+
* notification target are LIST ENTRIES, never devices (D954): they enter an
|
|
21782
|
+
* exporter's own selection, not the device registry.
|
|
21783
|
+
*/
|
|
21784
|
+
var ExportEntityKindSchema = zod.z.enum([
|
|
21785
|
+
"device",
|
|
21786
|
+
"action",
|
|
21787
|
+
"notifier"
|
|
21788
|
+
]);
|
|
21789
|
+
var ExportEntityRefSchema = zod.z.discriminatedUnion("kind", [
|
|
21790
|
+
zod.z.object({
|
|
21791
|
+
kind: zod.z.literal("device"),
|
|
21792
|
+
deviceId: zod.z.string()
|
|
21793
|
+
}),
|
|
21794
|
+
zod.z.object({
|
|
21795
|
+
kind: zod.z.literal("action"),
|
|
21796
|
+
actionId: zod.z.string().min(1)
|
|
21797
|
+
}),
|
|
21798
|
+
zod.z.object({
|
|
21799
|
+
kind: zod.z.literal("notifier"),
|
|
21800
|
+
targetId: zod.z.string().min(1)
|
|
21801
|
+
})
|
|
21802
|
+
]);
|
|
21803
|
+
var ExposedEntitySchema = zod.z.object({
|
|
21804
|
+
entity: ExportEntityRefSchema,
|
|
21805
|
+
exposedAs: zod.z.string().optional()
|
|
21806
|
+
});
|
|
21807
|
+
var ExposeEntityInputSchema = zod.z.object({ entity: ExportEntityRefSchema });
|
|
21808
|
+
var UnexposeEntityInputSchema = zod.z.object({ entity: ExportEntityRefSchema });
|
|
21061
21809
|
var deviceExportCapability = {
|
|
21062
21810
|
name: "device-export",
|
|
21063
21811
|
scope: "system",
|
|
@@ -21087,6 +21835,16 @@ var deviceExportCapability = {
|
|
|
21087
21835
|
unexposeDevice: require_sleep.method(UnexposeInputSchema, zod.z.void(), {
|
|
21088
21836
|
kind: "mutation",
|
|
21089
21837
|
auth: "admin"
|
|
21838
|
+
}),
|
|
21839
|
+
listSupportedEntityKinds: require_sleep.optionalMethod(zod.z.void(), zod.z.array(ExportEntityKindSchema)),
|
|
21840
|
+
listExposedEntities: require_sleep.optionalMethod(zod.z.void(), zod.z.array(ExposedEntitySchema)),
|
|
21841
|
+
exposeEntity: require_sleep.optionalMethod(ExposeEntityInputSchema, zod.z.void(), {
|
|
21842
|
+
kind: "mutation",
|
|
21843
|
+
auth: "admin"
|
|
21844
|
+
}),
|
|
21845
|
+
unexposeEntity: require_sleep.optionalMethod(UnexposeEntityInputSchema, zod.z.void(), {
|
|
21846
|
+
kind: "mutation",
|
|
21847
|
+
auth: "admin"
|
|
21090
21848
|
})
|
|
21091
21849
|
}
|
|
21092
21850
|
};
|
|
@@ -44795,7 +45553,7 @@ var LlmProviderWidgetSchema = zod.z.object({
|
|
|
44795
45553
|
/** ConfigUISchema tree passed through untyped on the wire (the
|
|
44796
45554
|
* notification-output `ConfigSchemaPassthrough` precedent at
|
|
44797
45555
|
* notification-output.cap.ts:151); the exported TS type re-tightens it. */
|
|
44798
|
-
var ConfigSchemaPassthrough$
|
|
45556
|
+
var ConfigSchemaPassthrough$2 = zod.z.unknown();
|
|
44799
45557
|
var LlmProfileKindDescriptorSchema = zod.z.object({
|
|
44800
45558
|
kind: LlmProfileKindSchema,
|
|
44801
45559
|
label: zod.z.string(),
|
|
@@ -44804,9 +45562,9 @@ var LlmProfileKindDescriptorSchema = zod.z.object({
|
|
|
44804
45562
|
/** Stamped by each provider so the concat-fanned catalog stays routable. */
|
|
44805
45563
|
addonId: zod.z.string(),
|
|
44806
45564
|
/** The provider's own fields (`providerConfig`); `password` fields are keychain-held. */
|
|
44807
|
-
connectionSchema: ConfigSchemaPassthrough$
|
|
45565
|
+
connectionSchema: ConfigSchemaPassthrough$2,
|
|
44808
45566
|
/** Provider fields that belong under "Advanced" (extra headers, runtime tuning). */
|
|
44809
|
-
advancedSchema: ConfigSchemaPassthrough$
|
|
45567
|
+
advancedSchema: ConfigSchemaPassthrough$2.optional(),
|
|
44810
45568
|
/** The kind's defaults; a model from `listModels` may override any of them. */
|
|
44811
45569
|
features: LlmModelFeaturesSchema,
|
|
44812
45570
|
/** `false` = the provider stamps `supportsVision` itself (from what a node reports). */
|
|
@@ -45563,10 +46321,10 @@ var CpuBreakdownSchema = zod.z.object({
|
|
|
45563
46321
|
cores: zod.z.number()
|
|
45564
46322
|
});
|
|
45565
46323
|
var MemoryInfoSchema = zod.z.object({
|
|
45566
|
-
percent: zod.z.number(),
|
|
46324
|
+
percent: zod.z.number().nullable(),
|
|
45567
46325
|
totalBytes: zod.z.number(),
|
|
45568
|
-
usedBytes: zod.z.number(),
|
|
45569
|
-
availableBytes: zod.z.number(),
|
|
46326
|
+
usedBytes: zod.z.number().nullable(),
|
|
46327
|
+
availableBytes: zod.z.number().nullable(),
|
|
45570
46328
|
swapUsedBytes: zod.z.number(),
|
|
45571
46329
|
swapTotalBytes: zod.z.number()
|
|
45572
46330
|
});
|
|
@@ -45870,8 +46628,9 @@ var GetLoadSeriesInputSchema = zod.z.object({
|
|
|
45870
46628
|
});
|
|
45871
46629
|
var SystemMetricsSchema = zod.z.object({
|
|
45872
46630
|
cpuPercent: zod.z.number(),
|
|
45873
|
-
|
|
45874
|
-
|
|
46631
|
+
/** `null` when the memory sample failed or was not taken yet (D393). */
|
|
46632
|
+
memoryPercent: zod.z.number().nullable(),
|
|
46633
|
+
memoryUsedMB: zod.z.number().nullable(),
|
|
45875
46634
|
memoryTotalMB: zod.z.number(),
|
|
45876
46635
|
diskPercent: zod.z.number().optional(),
|
|
45877
46636
|
temperature: zod.z.number().optional(),
|
|
@@ -46273,453 +47032,6 @@ var networkAccessCapability = {
|
|
|
46273
47032
|
}
|
|
46274
47033
|
};
|
|
46275
47034
|
//#endregion
|
|
46276
|
-
//#region src/capabilities/notification-output.cap.ts
|
|
46277
|
-
/**
|
|
46278
|
-
* notification-output — canonical, capability-gated notification delivery.
|
|
46279
|
-
*
|
|
46280
|
-
* Apprise-derived model (see
|
|
46281
|
-
* `docs/superpowers/specs/2026-07-03-notification-output-notifier-matrix.md`):
|
|
46282
|
-
* callers emit ONE canonical `Notification`; each provider declares a
|
|
46283
|
-
* per-kind capability descriptor (`TargetKind`), and the pure degrade
|
|
46284
|
-
* engine (`@camstack/types` `prepareNotification`) transcodes / degrades the
|
|
46285
|
-
* message to what the kind supports — callers never special-case a service.
|
|
46286
|
-
*
|
|
46287
|
-
* DESIGN DECISIONS (locked):
|
|
46288
|
-
* - Target CRUD lives on THIS cap (`upsertTarget` / `deleteTarget` /
|
|
46289
|
-
* `setTargetEnabled`), each provider persisting via the `settings-store`
|
|
46290
|
-
* cap. Rationale: the admin UI needs one uniform surface across the
|
|
46291
|
-
* notifiers addon AND the HA addon; the addon-`globalSettingsSchema`-array
|
|
46292
|
-
* alternative would fork the UI per addon and cannot host the
|
|
46293
|
-
* discovery→adopt flow.
|
|
46294
|
-
* - `listTargetKinds` / `listTargets` / `discoverTargets` return arrays →
|
|
46295
|
-
* the generated cap-mount auto-`concatCollection`-fans them across every
|
|
46296
|
-
* registered provider (notifiers addon + HA addon) so one catalog is
|
|
46297
|
-
* routable. `send` / `testTarget` / CRUD route to ONE provider by the
|
|
46298
|
-
* `addonId` the generated collection router extracts from the call input.
|
|
46299
|
-
* - `Attachment.bytes` is `Uint8Array`. Transport-safe: superjson (the tRPC
|
|
46300
|
-
* transformer) + UDS MsgPack both round-trip typed arrays — already used by
|
|
46301
|
-
* `storage` / `storage-provider` / `recording` caps over the same path. No
|
|
46302
|
-
* base64 fallback needed.
|
|
46303
|
-
*
|
|
46304
|
-
* TODO (deferred, closed-set change — separate decision): add
|
|
46305
|
-
* `providerKind: 'notify'` so notification providers surface on the unified
|
|
46306
|
-
* admin "Integrations" page.
|
|
46307
|
-
*/
|
|
46308
|
-
/**
|
|
46309
|
-
* Zentik-derived typed-media enum — the superset across every kind. Each
|
|
46310
|
-
* adapter picks what it supports and the degrade engine filters the rest.
|
|
46311
|
-
*/
|
|
46312
|
-
var AttachmentMediaTypeSchema = zod.z.enum([
|
|
46313
|
-
"image",
|
|
46314
|
-
"video",
|
|
46315
|
-
"gif",
|
|
46316
|
-
"audio",
|
|
46317
|
-
"icon"
|
|
46318
|
-
]);
|
|
46319
|
-
/**
|
|
46320
|
-
* A single attachment. Exactly one of `url` (remote source, most adapters
|
|
46321
|
-
* prefer this) or `bytes` (inline source; required for Pushover-style
|
|
46322
|
-
* bytes-only kinds) MUST be present — the degrade engine expresses a
|
|
46323
|
-
* url→bytes fetch as a `needsFetch` directive the adapter executes.
|
|
46324
|
-
*/
|
|
46325
|
-
var AttachmentSchema = zod.z.object({
|
|
46326
|
-
mediaType: AttachmentMediaTypeSchema,
|
|
46327
|
-
url: zod.z.string().optional(),
|
|
46328
|
-
bytes: zod.z.instanceof(Uint8Array).optional(),
|
|
46329
|
-
mime: zod.z.string().optional(),
|
|
46330
|
-
name: zod.z.string().optional()
|
|
46331
|
-
}).refine((a) => a.url !== void 0 || a.bytes !== void 0, { message: "Attachment requires either `url` or `bytes`" });
|
|
46332
|
-
var NotificationFormatSchema = zod.z.enum([
|
|
46333
|
-
"text",
|
|
46334
|
-
"markdown",
|
|
46335
|
-
"html"
|
|
46336
|
-
]);
|
|
46337
|
-
/**
|
|
46338
|
-
* The CLOSED icon vocabulary an action button may use.
|
|
46339
|
-
*
|
|
46340
|
-
* A closed set, not a free string, and that is the whole point: an arbitrary
|
|
46341
|
-
* icon name is one that ntfy renders, zentik silently drops, and nobody
|
|
46342
|
-
* notices — the same class of gap as a zone vocabulary nothing produced
|
|
46343
|
-
* ([D35](../../../docs/decisions/adr-0035.md)). Every adapter maps this set or
|
|
46344
|
-
* declares `actionIcons: false` and the degrade engine strips the field.
|
|
46345
|
-
*
|
|
46346
|
-
* Named by INTENT, never by glyph. "check" would tie the vocabulary to one
|
|
46347
|
-
* renderer's icon set; "acknowledge" survives an adapter that draws it
|
|
46348
|
-
* differently.
|
|
46349
|
-
*
|
|
46350
|
-
* ── A TOKEN IS NOT A WIRE VALUE ─────────────────────────────────────
|
|
46351
|
-
*
|
|
46352
|
-
* These names are for US. **No adapter may forward one verbatim.** Each maps
|
|
46353
|
-
* the whole set onto its own renderer's vocabulary through a
|
|
46354
|
-
* `Record<NotificationActionIcon, string>` — a Record, never a lookup with a
|
|
46355
|
-
* fallback, so adding a member here fails every adapter's build until someone
|
|
46356
|
-
* decides its glyph, which is the only place that decision can be made
|
|
46357
|
-
* honestly.
|
|
46358
|
-
*
|
|
46359
|
-
* This paragraph is the bug. Zentik declared `actionIcons: true` and passed
|
|
46360
|
-
* `disarm` straight through; iOS feeds that string to
|
|
46361
|
-
* `UNNotificationActionIcon(systemImageName:)`, `disarm` is not an SF Symbol,
|
|
46362
|
-
* and every snooze and alarm button arrived BLANK. A pass-through is not a
|
|
46363
|
-
* mapping, and "the field is documented" is not "the value renders".
|
|
46364
|
-
*
|
|
46365
|
-
* Adding a member is TRAIN-BOUND. The enum lives in the published
|
|
46366
|
-
* `@camstack/server` closure and the cap seam validates against the HUB's copy,
|
|
46367
|
-
* so an addon that emits a token the running hub does not know does not lose an
|
|
46368
|
-
* icon — its whole `send` fails Zod validation and the notification never
|
|
46369
|
-
* arrives. Never emit a new token from an addon before the train carrying it.
|
|
46370
|
-
*/
|
|
46371
|
-
var NotificationActionIconSchema = zod.z.enum([
|
|
46372
|
-
"acknowledge",
|
|
46373
|
-
"dismiss",
|
|
46374
|
-
"silence",
|
|
46375
|
-
"snooze",
|
|
46376
|
-
"view",
|
|
46377
|
-
"play",
|
|
46378
|
-
"open",
|
|
46379
|
-
"close",
|
|
46380
|
-
"lock",
|
|
46381
|
-
"unlock",
|
|
46382
|
-
"arm",
|
|
46383
|
-
"arm-home",
|
|
46384
|
-
"arm-away",
|
|
46385
|
-
"arm-night",
|
|
46386
|
-
"disarm",
|
|
46387
|
-
"light",
|
|
46388
|
-
"alert",
|
|
46389
|
-
"camera"
|
|
46390
|
-
]);
|
|
46391
|
-
/** A single tap-through action button. */
|
|
46392
|
-
var NotificationActionSchema = zod.z.object({
|
|
46393
|
-
id: zod.z.string(),
|
|
46394
|
-
label: zod.z.string(),
|
|
46395
|
-
url: zod.z.string().optional(),
|
|
46396
|
-
/** Dropped by the degrade engine for a kind with `caps.actionIcons: false`. */
|
|
46397
|
-
icon: NotificationActionIconSchema.optional(),
|
|
46398
|
-
/**
|
|
46399
|
-
* Renders in a warning style where the notifier supports it.
|
|
46400
|
-
*
|
|
46401
|
-
* A HINT, never a gate. The callback's authority is its token and nothing
|
|
46402
|
-
* else — see `notification-center/action-token.ts` for what that does and
|
|
46403
|
-
* does not buy.
|
|
46404
|
-
*/
|
|
46405
|
-
destructive: zod.z.boolean().optional(),
|
|
46406
|
-
/**
|
|
46407
|
-
* How the tap should REACH the url.
|
|
46408
|
-
*
|
|
46409
|
-
* `navigate` (absent, and every button authored before this field) opens it:
|
|
46410
|
-
* the phone leaves the notification and shows whatever the callback returns.
|
|
46411
|
-
* That is right for a button whose answer the operator wants to read.
|
|
46412
|
-
*
|
|
46413
|
-
* `background` fires it as a POST and stays put. It exists for the buttons
|
|
46414
|
-
* whose whole point is not to interrupt — "silence this for 30 minutes" is
|
|
46415
|
-
* an answer to the notification, and being thrown into a browser tab to
|
|
46416
|
-
* confirm it costs more attention than the notification did. A backend that
|
|
46417
|
-
* cannot do a background call renders it as an ordinary link (the adapters
|
|
46418
|
-
* fall back rather than dropping the button), so this is a preference, never
|
|
46419
|
-
* a requirement.
|
|
46420
|
-
*/
|
|
46421
|
-
mode: zod.z.enum(["navigate", "background"]).optional()
|
|
46422
|
-
});
|
|
46423
|
-
/** A delivery parameter value: what a notifier declared it takes. */
|
|
46424
|
-
var DeliveryParamValueSchema = zod.z.union([
|
|
46425
|
-
zod.z.string(),
|
|
46426
|
-
zod.z.number(),
|
|
46427
|
-
zod.z.boolean()
|
|
46428
|
-
]);
|
|
46429
|
-
/**
|
|
46430
|
-
* One extra delivery parameter a notifier KIND declares (D938). A rule that
|
|
46431
|
-
* addresses a target of that kind may set it; a kind that declares nothing is
|
|
46432
|
-
* never handed one. The admin UI derives its control from this descriptor —
|
|
46433
|
-
* no editor knows a service by name.
|
|
46434
|
-
*
|
|
46435
|
-
* Optional fields are `.optional()`, never `.default()` (a Zod default does not
|
|
46436
|
-
* run on the addon cap path).
|
|
46437
|
-
*/
|
|
46438
|
-
var DeliveryParamSchema = zod.z.object({
|
|
46439
|
-
key: zod.z.string().min(1),
|
|
46440
|
-
label: zod.z.string(),
|
|
46441
|
-
/** i18n key of the label, resolved by the declaring addon's namespace. */
|
|
46442
|
-
labelKey: zod.z.string().optional(),
|
|
46443
|
-
type: zod.z.enum([
|
|
46444
|
-
"enum",
|
|
46445
|
-
"number",
|
|
46446
|
-
"boolean",
|
|
46447
|
-
"string"
|
|
46448
|
-
]),
|
|
46449
|
-
/** `enum` only: the closed set of accepted values. */
|
|
46450
|
-
options: zod.z.array(zod.z.object({
|
|
46451
|
-
value: zod.z.string(),
|
|
46452
|
-
label: zod.z.string()
|
|
46453
|
-
})).optional(),
|
|
46454
|
-
/** `number` only. */
|
|
46455
|
-
min: zod.z.number().optional(),
|
|
46456
|
-
max: zod.z.number().optional(),
|
|
46457
|
-
/** What the notifier does when the rule sets nothing; shown as the placeholder. */
|
|
46458
|
-
default: DeliveryParamValueSchema.optional()
|
|
46459
|
-
});
|
|
46460
|
-
/**
|
|
46461
|
-
* The canonical notification. `body` is the only hard field (Apprise model).
|
|
46462
|
-
* `priority` is a 5-level ORDINAL (1=lowest … 3=normal(default) … 5=urgent),
|
|
46463
|
-
* NOT a fixed severity enum — each kind declares its own `caps.levels` and
|
|
46464
|
-
* the adapter maps this ordinal onto its native level. `level?` is an
|
|
46465
|
-
* optional kind-native level id (`emergency`, `silent`, …) that overrides
|
|
46466
|
-
* `priority` for that one target.
|
|
46467
|
-
*/
|
|
46468
|
-
var NotificationSchema = zod.z.object({
|
|
46469
|
-
body: zod.z.string(),
|
|
46470
|
-
title: zod.z.string().optional(),
|
|
46471
|
-
format: NotificationFormatSchema.default("text"),
|
|
46472
|
-
priority: zod.z.number().int().min(1).max(5).default(3),
|
|
46473
|
-
level: zod.z.string().optional(),
|
|
46474
|
-
attachments: zod.z.array(AttachmentSchema).optional(),
|
|
46475
|
-
clickUrl: zod.z.string().optional(),
|
|
46476
|
-
actions: zod.z.array(NotificationActionSchema).optional(),
|
|
46477
|
-
sound: zod.z.string().optional(),
|
|
46478
|
-
ttl: zod.z.number().optional(),
|
|
46479
|
-
tag: zod.z.string().optional(),
|
|
46480
|
-
deviceId: zod.z.number().optional(),
|
|
46481
|
-
eventId: zod.z.string().optional(),
|
|
46482
|
-
metadata: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
|
|
46483
|
-
/**
|
|
46484
|
-
* Values for the parameters the target's kind DECLARES in
|
|
46485
|
-
* {@link TargetKindSchema} `deliveryParams`. Already validated against the
|
|
46486
|
-
* declaration by the sender; a notifier reads only the keys it declared.
|
|
46487
|
-
*/
|
|
46488
|
-
delivery: zod.z.record(zod.z.string(), DeliveryParamValueSchema).optional()
|
|
46489
|
-
});
|
|
46490
|
-
/** One declared native severity/priority level for a kind. */
|
|
46491
|
-
var TargetKindLevelSchema = zod.z.object({
|
|
46492
|
-
id: zod.z.string(),
|
|
46493
|
-
label: zod.z.string(),
|
|
46494
|
-
/** Which canonical priority (1..5) this level maps to. `null` = qualitative-only. */
|
|
46495
|
-
ordinal: zod.z.number().int().min(1).max(5).nullable(),
|
|
46496
|
-
flags: zod.z.object({
|
|
46497
|
-
critical: zod.z.boolean().optional(),
|
|
46498
|
-
silent: zod.z.boolean().optional(),
|
|
46499
|
-
noPush: zod.z.boolean().optional()
|
|
46500
|
-
}).optional(),
|
|
46501
|
-
/** e.g. Pushover `emergency` requires `retry` / `expire`. */
|
|
46502
|
-
requires: zod.z.array(zod.z.string()).optional(),
|
|
46503
|
-
description: zod.z.string().optional()
|
|
46504
|
-
});
|
|
46505
|
-
/** Attachment capabilities for a kind (drives the degrade engine + test panel). */
|
|
46506
|
-
var TargetKindAttachmentsCapsSchema = zod.z.object({
|
|
46507
|
-
mediaTypes: zod.z.array(AttachmentMediaTypeSchema),
|
|
46508
|
-
mode: zod.z.enum([
|
|
46509
|
-
"url",
|
|
46510
|
-
"bytes",
|
|
46511
|
-
"both"
|
|
46512
|
-
]),
|
|
46513
|
-
max: zod.z.number().int().nonnegative(),
|
|
46514
|
-
maxBytes: zod.z.number().int().positive().optional()
|
|
46515
|
-
});
|
|
46516
|
-
/** The full capability block consulted before dispatch. */
|
|
46517
|
-
var TargetKindCapsSchema = zod.z.object({
|
|
46518
|
-
attachments: TargetKindAttachmentsCapsSchema,
|
|
46519
|
-
/** Max action buttons (0 = none). */
|
|
46520
|
-
actions: zod.z.number().int().nonnegative(),
|
|
46521
|
-
/**
|
|
46522
|
-
* Whether this kind renders a per-action ICON.
|
|
46523
|
-
*
|
|
46524
|
-
* `.optional()`, deliberately NOT `.default(false)`: a Zod default does not
|
|
46525
|
-
* run on the addon cap path — three production failures in one day taught
|
|
46526
|
-
* this repo that once. Absent is read as false by the degrade engine, which
|
|
46527
|
-
* is the safe direction: an icon that is not rendered costs nothing, an icon
|
|
46528
|
-
* assumed and dropped costs the operator's trust in the field.
|
|
46529
|
-
*/
|
|
46530
|
-
actionIcons: zod.z.boolean().optional(),
|
|
46531
|
-
levels: zod.z.array(TargetKindLevelSchema),
|
|
46532
|
-
format: zod.z.array(NotificationFormatSchema),
|
|
46533
|
-
clickUrl: zod.z.boolean(),
|
|
46534
|
-
sound: zod.z.boolean(),
|
|
46535
|
-
ttl: zod.z.boolean(),
|
|
46536
|
-
bodyMaxLen: zod.z.number().int().positive()
|
|
46537
|
-
});
|
|
46538
|
-
/**
|
|
46539
|
-
* `configSchema` is a `ConfigUISchema` tree passed through to the admin
|
|
46540
|
-
* FormBuilder. Stored as `z.unknown()` at the cap seam (mirrors
|
|
46541
|
-
* `device-provider.getChildCreationSchema` `CreationSchemaOutputSchema`) —
|
|
46542
|
-
* the union is large and not meant for runtime validation here; the exported
|
|
46543
|
-
* `TargetKind` type re-tightens `configSchema` to `ConfigUISchema`.
|
|
46544
|
-
*/
|
|
46545
|
-
var ConfigSchemaPassthrough$2 = zod.z.unknown();
|
|
46546
|
-
var TargetKindSchema = zod.z.object({
|
|
46547
|
-
kind: zod.z.string(),
|
|
46548
|
-
label: zod.z.string(),
|
|
46549
|
-
icon: zod.z.string(),
|
|
46550
|
-
/** Stamped by each provider so the concat-fanned catalog stays routable. */
|
|
46551
|
-
addonId: zod.z.string(),
|
|
46552
|
-
/**
|
|
46553
|
-
* URL of the kind's bundled BRAND icon, served by the providing addon over
|
|
46554
|
-
* its own `addon-routes` surface (`/addon/<addonId>/icons/<kind>`). Absent
|
|
46555
|
-
* when the addon bundles no icon for that kind — the client then falls back
|
|
46556
|
-
* to a neutral glyph rather than rendering the raw `icon` NAME as text.
|
|
46557
|
-
*
|
|
46558
|
-
* Root-relative on purpose: it resolves against whatever origin serves a web
|
|
46559
|
-
* client, and a native client joins it onto its own hub base.
|
|
46560
|
-
*
|
|
46561
|
-
* DECLARED here deliberately. It used to travel as an undeclared passthrough
|
|
46562
|
-
* field that survived only because the runtime cap-router forwards provider
|
|
46563
|
-
* output verbatim — so every consumer had to re-declare it by hand to stop
|
|
46564
|
-
* its own Zod parse from stripping it, and the whole arrangement would have
|
|
46565
|
-
* broken silently the moment output validation was tightened anywhere.
|
|
46566
|
-
*/
|
|
46567
|
-
iconUrl: zod.z.string().optional(),
|
|
46568
|
-
/**
|
|
46569
|
-
* Media type of {@link iconUrl} (`image/svg+xml`, `image/png`, …).
|
|
46570
|
-
*
|
|
46571
|
-
* The server knows this and therefore says it, because the client cannot
|
|
46572
|
-
* safely guess: a React-Native client renders SVG and raster through two
|
|
46573
|
-
* DIFFERENT components (`react-native-svg` vs `expo-image` — expo-image does
|
|
46574
|
-
* not decode SVG on iOS/Android), so without this it silently fell back to a
|
|
46575
|
-
* placeholder glyph for every vector icon while the web build looked fine.
|
|
46576
|
-
*
|
|
46577
|
-
* Absent when {@link iconUrl} is absent, or for a legacy provider that has
|
|
46578
|
-
* not been updated — a client that cannot determine the type should prefer
|
|
46579
|
-
* its raster path, which is the safe default for an unknown image.
|
|
46580
|
-
*/
|
|
46581
|
-
iconMediaType: zod.z.string().optional(),
|
|
46582
|
-
configSchema: ConfigSchemaPassthrough$2,
|
|
46583
|
-
/**
|
|
46584
|
-
* The config keys that decide WHERE this kind's secrets are sent (server,
|
|
46585
|
-
* base URL, instance, chat, recipient). A save that changes any of them
|
|
46586
|
-
* while leaving a secret redacted is refused by the provider (D634), so an
|
|
46587
|
-
* editor uses this to ask for the secret on exactly those edits instead of
|
|
46588
|
-
* on every edit.
|
|
46589
|
-
*
|
|
46590
|
-
* Optional: absent from a provider that holds no secret (the Home Assistant
|
|
46591
|
-
* kinds) and from a provider older than this field — an editor that finds
|
|
46592
|
-
* it absent must assume ANY edit may need the secret.
|
|
46593
|
-
*/
|
|
46594
|
-
destinationKeys: zod.z.array(zod.z.string()).optional(),
|
|
46595
|
-
supportsDiscovery: zod.z.boolean(),
|
|
46596
|
-
/**
|
|
46597
|
-
* Extra delivery parameters a rule may set for a target of this kind (D938).
|
|
46598
|
-
* Absent = none; the rule editor then offers nothing.
|
|
46599
|
-
*/
|
|
46600
|
-
deliveryParams: zod.z.array(DeliveryParamSchema).optional(),
|
|
46601
|
-
caps: TargetKindCapsSchema
|
|
46602
|
-
});
|
|
46603
|
-
/**
|
|
46604
|
-
* A persisted target. `config` holds secrets; providers REDACT secret fields
|
|
46605
|
-
* (return a presence marker only) when serving `listTargets` — never
|
|
46606
|
-
* round-trip a stored secret to the UI.
|
|
46607
|
-
*/
|
|
46608
|
-
var TargetSchema = zod.z.object({
|
|
46609
|
-
id: zod.z.string(),
|
|
46610
|
-
name: zod.z.string(),
|
|
46611
|
-
kind: zod.z.string(),
|
|
46612
|
-
addonId: zod.z.string(),
|
|
46613
|
-
enabled: zod.z.boolean(),
|
|
46614
|
-
config: zod.z.record(zod.z.string(), zod.z.unknown())
|
|
46615
|
-
});
|
|
46616
|
-
/** A discovery-surfaced candidate (config is partial + non-secret). */
|
|
46617
|
-
var DiscoveredTargetSchema = zod.z.object({
|
|
46618
|
-
kind: zod.z.string(),
|
|
46619
|
-
suggestedName: zod.z.string(),
|
|
46620
|
-
config: zod.z.record(zod.z.string(), zod.z.unknown())
|
|
46621
|
-
});
|
|
46622
|
-
/** The degrade engine's report — what was resolved / dropped / degraded. */
|
|
46623
|
-
var RenderedAsSchema = zod.z.object({
|
|
46624
|
-
level: zod.z.string(),
|
|
46625
|
-
format: NotificationFormatSchema,
|
|
46626
|
-
attachmentsSent: zod.z.number().int().nonnegative(),
|
|
46627
|
-
actionsSent: zod.z.number().int().nonnegative(),
|
|
46628
|
-
truncated: zod.z.boolean(),
|
|
46629
|
-
dropped: zod.z.array(zod.z.string())
|
|
46630
|
-
});
|
|
46631
|
-
var SendResultSchema = zod.z.object({
|
|
46632
|
-
success: zod.z.boolean(),
|
|
46633
|
-
error: zod.z.string().optional(),
|
|
46634
|
-
renderedAs: RenderedAsSchema.optional()
|
|
46635
|
-
});
|
|
46636
|
-
/** Same shape as SendResult — kept as a distinct name for the test panel. */
|
|
46637
|
-
var TestResultSchema = SendResultSchema;
|
|
46638
|
-
/**
|
|
46639
|
-
* Pre-save credential probe against a partial (unsaved) target config.
|
|
46640
|
-
* `resolvedUrl` never includes secrets (token stripped from path).
|
|
46641
|
-
*/
|
|
46642
|
-
var ProbeTargetConfigResultSchema = zod.z.object({
|
|
46643
|
-
ok: zod.z.boolean(),
|
|
46644
|
-
resolvedUrl: zod.z.string(),
|
|
46645
|
-
httpStatus: zod.z.number().int().optional(),
|
|
46646
|
-
stateInstance: zod.z.string().optional(),
|
|
46647
|
-
error: zod.z.string().optional()
|
|
46648
|
-
});
|
|
46649
|
-
var notificationOutputCapability = {
|
|
46650
|
-
name: "notification-output",
|
|
46651
|
-
scope: "system",
|
|
46652
|
-
mode: "collection",
|
|
46653
|
-
methods: {
|
|
46654
|
-
listTargetKinds: require_sleep.method(zod.z.object({}), zod.z.array(TargetKindSchema)),
|
|
46655
|
-
listTargets: require_sleep.method(zod.z.object({}), zod.z.array(TargetSchema), { auth: "admin" }),
|
|
46656
|
-
/**
|
|
46657
|
-
* One target WITH secrets — admin edit / duplicate hydration only.
|
|
46658
|
-
* `listTargets` stays redacted; the editor loads this so password fields
|
|
46659
|
-
* are filled (masked in the input) and a save can round-trip the token
|
|
46660
|
-
* when a destination changes (Duplicate with a new chatId, etc.).
|
|
46661
|
-
*/
|
|
46662
|
-
getTarget: require_sleep.method(zod.z.object({ targetId: zod.z.string() }), TargetSchema, { auth: "admin" }),
|
|
46663
|
-
discoverTargets: require_sleep.method(zod.z.object({
|
|
46664
|
-
kind: zod.z.string(),
|
|
46665
|
-
config: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
|
|
46666
|
-
/**
|
|
46667
|
-
* When editing / duplicating, the blank password field never round-trips
|
|
46668
|
-
* the stored token. Pass the source target id so the provider can restore
|
|
46669
|
-
* secrets server-side before dialling (same merge as upsert).
|
|
46670
|
-
*/
|
|
46671
|
-
targetId: zod.z.string().optional()
|
|
46672
|
-
}), zod.z.array(DiscoveredTargetSchema), { auth: "admin" }),
|
|
46673
|
-
probeTargetConfig: require_sleep.method(zod.z.object({
|
|
46674
|
-
kind: zod.z.string(),
|
|
46675
|
-
config: zod.z.record(zod.z.string(), zod.z.unknown()),
|
|
46676
|
-
/** See `discoverTargets.targetId` — restore stored secrets for a blank password. */
|
|
46677
|
-
targetId: zod.z.string().optional()
|
|
46678
|
-
}), ProbeTargetConfigResultSchema, {
|
|
46679
|
-
kind: "mutation",
|
|
46680
|
-
auth: "admin"
|
|
46681
|
-
}),
|
|
46682
|
-
send: require_sleep.method(zod.z.object({
|
|
46683
|
-
targetId: zod.z.string(),
|
|
46684
|
-
notification: NotificationSchema
|
|
46685
|
-
}), SendResultSchema, {
|
|
46686
|
-
kind: "mutation",
|
|
46687
|
-
auth: "admin"
|
|
46688
|
-
}),
|
|
46689
|
-
testTarget: require_sleep.method(zod.z.object({
|
|
46690
|
-
targetId: zod.z.string(),
|
|
46691
|
-
sample: NotificationSchema.optional()
|
|
46692
|
-
}), TestResultSchema, {
|
|
46693
|
-
kind: "mutation",
|
|
46694
|
-
auth: "admin"
|
|
46695
|
-
}),
|
|
46696
|
-
upsertTarget: require_sleep.method(zod.z.object({
|
|
46697
|
-
target: TargetSchema,
|
|
46698
|
-
/**
|
|
46699
|
-
* Duplicate flow: create a NEW target id while copying secrets from an
|
|
46700
|
-
* existing row. The UI never holds the stored token; blank / redacted
|
|
46701
|
-
* password fields are restored from this source (D634 still applies if
|
|
46702
|
-
* destinations diverge without a re-typed secret).
|
|
46703
|
-
*/
|
|
46704
|
-
cloneSecretsFrom: zod.z.string().optional()
|
|
46705
|
-
}), TargetSchema, {
|
|
46706
|
-
kind: "mutation",
|
|
46707
|
-
auth: "admin"
|
|
46708
|
-
}),
|
|
46709
|
-
deleteTarget: require_sleep.method(zod.z.object({ targetId: zod.z.string() }), zod.z.void(), {
|
|
46710
|
-
kind: "mutation",
|
|
46711
|
-
auth: "admin"
|
|
46712
|
-
}),
|
|
46713
|
-
setTargetEnabled: require_sleep.method(zod.z.object({
|
|
46714
|
-
targetId: zod.z.string(),
|
|
46715
|
-
enabled: zod.z.boolean()
|
|
46716
|
-
}), zod.z.void(), {
|
|
46717
|
-
kind: "mutation",
|
|
46718
|
-
auth: "admin"
|
|
46719
|
-
})
|
|
46720
|
-
}
|
|
46721
|
-
};
|
|
46722
|
-
//#endregion
|
|
46723
47035
|
//#region src/catalogs/audio-classmap.ts
|
|
46724
47036
|
var AUDIO_MACRO_LABELS = [
|
|
46725
47037
|
{
|
|
@@ -55594,14 +55906,6 @@ var EngineProvisioningSchema = zod.z.object({
|
|
|
55594
55906
|
*/
|
|
55595
55907
|
configIssues: zod.z.array(zod.z.string()).optional()
|
|
55596
55908
|
});
|
|
55597
|
-
var PipelineStepInputSchema = zod.z.lazy(() => zod.z.object({
|
|
55598
|
-
addonId: zod.z.string(),
|
|
55599
|
-
modelId: zod.z.string().optional(),
|
|
55600
|
-
enabled: zod.z.boolean().default(true),
|
|
55601
|
-
children: zod.z.array(PipelineStepInputSchema).optional(),
|
|
55602
|
-
settings: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
|
|
55603
|
-
jumpDeviceKey: zod.z.string().optional()
|
|
55604
|
-
}));
|
|
55605
55909
|
var ModelSubstitutionSchema = zod.z.object({
|
|
55606
55910
|
addonId: zod.z.string(),
|
|
55607
55911
|
chosen: zod.z.string(),
|
|
@@ -55680,7 +55984,6 @@ var ConfigUISchemaBridge = zod.z.custom();
|
|
|
55680
55984
|
var ConfigUISchemaNullableBridge = zod.z.custom();
|
|
55681
55985
|
var InferenceCapabilitiesBridge = zod.z.custom();
|
|
55682
55986
|
var ModelAvailabilityListBridge = zod.z.custom();
|
|
55683
|
-
var PipelineRunResultBridge = zod.z.custom();
|
|
55684
55987
|
/**
|
|
55685
55988
|
* Pipeline executor — detection engine + configuration + inference API.
|
|
55686
55989
|
*
|
|
@@ -55793,7 +56096,7 @@ var pipelineExecutorCapability = {
|
|
|
55793
56096
|
* reads any media: can this (node, deviceKey) run exactly this model?
|
|
55794
56097
|
*/
|
|
55795
56098
|
validatePipeline: require_sleep.method(zod.z.object({
|
|
55796
|
-
steps: zod.z.array(PipelineStepInputSchema),
|
|
56099
|
+
steps: zod.z.array(require_sleep.PipelineStepInputSchema),
|
|
55797
56100
|
deviceKey: zod.z.string().optional()
|
|
55798
56101
|
}), PipelineValidationResultSchema),
|
|
55799
56102
|
getCapabilities: require_sleep.method(zod.z.void(), InferenceCapabilitiesBridge),
|
|
@@ -55837,7 +56140,7 @@ var pipelineExecutorCapability = {
|
|
|
55837
56140
|
* - `referenceImage`: named file from the reference-image store.
|
|
55838
56141
|
*/
|
|
55839
56142
|
runPipeline: require_sleep.method(zod.z.object({
|
|
55840
|
-
steps: zod.z.array(PipelineStepInputSchema).min(1),
|
|
56143
|
+
steps: zod.z.array(require_sleep.PipelineStepInputSchema).min(1),
|
|
55841
56144
|
frame: FrameInputSchema.optional(),
|
|
55842
56145
|
/**
|
|
55843
56146
|
* Process-local lazy frame. Valid only when caller and provider resolve
|
|
@@ -55911,7 +56214,7 @@ var pipelineExecutorCapability = {
|
|
|
55911
56214
|
* PIXELS of the image this call carries. Absent ⇒ the root step runs.
|
|
55912
56215
|
*/
|
|
55913
56216
|
suppliedRoot: SuppliedRootOutputSchema.optional()
|
|
55914
|
-
}), PipelineRunResultBridge, { kind: "mutation" }),
|
|
56217
|
+
}), require_sleep.PipelineRunResultBridge, { kind: "mutation" }),
|
|
55915
56218
|
/**
|
|
55916
56219
|
* Batched run — N raw frames packed into one cap call. The provider
|
|
55917
56220
|
* routes the batch through `SharedInferencePool.inferBatch`
|
|
@@ -55924,7 +56227,7 @@ var pipelineExecutorCapability = {
|
|
|
55924
56227
|
* N frames in one call to amortise per-call IPC overhead.
|
|
55925
56228
|
*/
|
|
55926
56229
|
runPipelineBatch: require_sleep.method(zod.z.object({
|
|
55927
|
-
steps: zod.z.array(PipelineStepInputSchema).min(1),
|
|
56230
|
+
steps: zod.z.array(require_sleep.PipelineStepInputSchema).min(1),
|
|
55928
56231
|
frames: zod.z.array(FrameInputSchema).min(1).max(255),
|
|
55929
56232
|
deviceId: zod.z.number().optional(),
|
|
55930
56233
|
sessionId: zod.z.string().optional(),
|
|
@@ -55941,7 +56244,7 @@ var pipelineExecutorCapability = {
|
|
|
55941
56244
|
frameId: zod.z.number().int().nonnegative().optional(),
|
|
55942
56245
|
/** Inference-device selector (Phase 2 multi-device); see runPipeline. */
|
|
55943
56246
|
deviceKey: zod.z.string().optional()
|
|
55944
|
-
}), zod.z.object({ results: zod.z.array(PipelineRunResultBridge).readonly() }), { kind: "mutation" }),
|
|
56247
|
+
}), zod.z.object({ results: zod.z.array(require_sleep.PipelineRunResultBridge).readonly() }), { kind: "mutation" }),
|
|
55945
56248
|
/**
|
|
55946
56249
|
* Cache a raw frame inside the Python inference pool's memory.
|
|
55947
56250
|
* Returns a numeric `frameId` that `inferCached` references —
|
|
@@ -57644,7 +57947,7 @@ var RunnerCameraConfigSchema = zod.z.object({
|
|
|
57644
57947
|
detectionSources: DetectionSourcesSchema.default(["pipeline"]),
|
|
57645
57948
|
pipelineEnabled: zod.z.boolean().default(true),
|
|
57646
57949
|
/** Ordered tree of video steps. Absent → runner skips video detection. */
|
|
57647
|
-
steps: zod.z.array(PipelineStepInputSchema).readonly().optional(),
|
|
57950
|
+
steps: zod.z.array(require_sleep.PipelineStepInputSchema).readonly().optional(),
|
|
57648
57951
|
/** Audio classification branch. `enabled:false` disables, null skips. */
|
|
57649
57952
|
audio: zod.z.object({
|
|
57650
57953
|
modelId: zod.z.string().optional(),
|
|
@@ -58379,7 +58682,7 @@ var pipelineRunnerCapability = {
|
|
|
58379
58682
|
//#region src/capabilities/pipeline-orchestrator.cap.ts
|
|
58380
58683
|
var CameraPipelineConfigSchema = zod.z.object({
|
|
58381
58684
|
engine: PipelineEngineChoiceSchema.optional(),
|
|
58382
|
-
steps: zod.z.array(PipelineStepInputSchema).readonly(),
|
|
58685
|
+
steps: zod.z.array(require_sleep.PipelineStepInputSchema).readonly(),
|
|
58383
58686
|
audio: zod.z.object({
|
|
58384
58687
|
engine: PipelineEngineChoiceSchema.optional(),
|
|
58385
58688
|
modelId: zod.z.string().optional(),
|
|
@@ -60095,6 +60398,12 @@ var ServerUpdateActionResultSchema = zod.z.object({
|
|
|
60095
60398
|
*/
|
|
60096
60399
|
blockers: zod.z.array(UpdateBlockerSchema).optional()
|
|
60097
60400
|
});
|
|
60401
|
+
var LaunchOverridesSchema = zod.z.object({
|
|
60402
|
+
/** The persisted heap ceiling in MB, or `null` when none is set. */
|
|
60403
|
+
heapMb: zod.z.number().int().nullable() });
|
|
60404
|
+
var SetLaunchOverridesResultSchema = LaunchOverridesSchema.extend({
|
|
60405
|
+
/** Always true: the override is read at launch, not by the running process. */
|
|
60406
|
+
restartRequired: zod.z.boolean() });
|
|
60098
60407
|
var serverManagementCapability = {
|
|
60099
60408
|
name: "server-management",
|
|
60100
60409
|
scope: "system",
|
|
@@ -60133,6 +60442,21 @@ var serverManagementCapability = {
|
|
|
60133
60442
|
restartServer: require_sleep.method(zod.z.void(), ServerUpdateActionResultSchema, {
|
|
60134
60443
|
kind: "mutation",
|
|
60135
60444
|
auth: "admin"
|
|
60445
|
+
}),
|
|
60446
|
+
/**
|
|
60447
|
+
* The node's persisted launch override (ADR 0970): the heap ceiling the node's
|
|
60448
|
+
* `node` process is started with, or `null` when none is set (the closure's
|
|
60449
|
+
* computed default applies). Read from the node's own data dir.
|
|
60450
|
+
*/
|
|
60451
|
+
getLaunchOverrides: require_sleep.method(zod.z.void(), LaunchOverridesSchema, { auth: "admin" }),
|
|
60452
|
+
/**
|
|
60453
|
+
* Set (`heapMb`) or clear (`null`) the node's heap-ceiling override. It is
|
|
60454
|
+
* written on the node itself and applies at the NEXT launch — restart the
|
|
60455
|
+
* node (`restartServer`) for it to take effect.
|
|
60456
|
+
*/
|
|
60457
|
+
setLaunchOverrides: require_sleep.method(zod.z.object({ heapMb: zod.z.number().int().min(512).max(65536).nullable() }), SetLaunchOverridesResultSchema, {
|
|
60458
|
+
kind: "mutation",
|
|
60459
|
+
auth: "admin"
|
|
60136
60460
|
})
|
|
60137
60461
|
},
|
|
60138
60462
|
/** BIG PLAN 2: declarative mount hint — read by `@camstack/system` `buildCapRouters`. */
|
|
@@ -66984,14 +67308,13 @@ reset: require_sleep.method(zod.z.object({
|
|
|
66984
67308
|
auth: "admin"
|
|
66985
67309
|
}) },
|
|
66986
67310
|
/**
|
|
66987
|
-
* A
|
|
66988
|
-
*
|
|
66989
|
-
*
|
|
66990
|
-
* commands (`forward`) arrive in slice 3 (D663).
|
|
67311
|
+
* A consumable ADDED to an existing device (a graft) refuses `reset` by
|
|
67312
|
+
* name: only a composed device of a NEW type forwards an item's reset to a
|
|
67313
|
+
* source button, and marks that item `resettable` (D967).
|
|
66991
67314
|
*/
|
|
66992
67315
|
composedMethods: { reset: {
|
|
66993
67316
|
kind: "refuse",
|
|
66994
|
-
reason: "a
|
|
67317
|
+
reason: "a consumable added to an existing device is not resettable — only a new composed device forwards a reset"
|
|
66995
67318
|
} },
|
|
66996
67319
|
status: {
|
|
66997
67320
|
schema: ConsumablesStatusSchema,
|
|
@@ -67654,7 +67977,7 @@ var DishwasherStatusSchema = zod.z.object({
|
|
|
67654
67977
|
/** Ms epoch of the last value received from the appliance; 0 = never. */
|
|
67655
67978
|
lastFetchedAt: zod.z.number()
|
|
67656
67979
|
});
|
|
67657
|
-
var DeviceIdSchema = zod.z.number().int().nonnegative();
|
|
67980
|
+
var DeviceIdSchema$1 = zod.z.number().int().nonnegative();
|
|
67658
67981
|
/** A value a program option or setting can take. */
|
|
67659
67982
|
var DishwasherValueSchema = zod.z.union([
|
|
67660
67983
|
zod.z.boolean(),
|
|
@@ -67729,77 +68052,77 @@ var dishwasherCapability = {
|
|
|
67729
68052
|
* option feature keys; each is checked against the program's constraints.
|
|
67730
68053
|
*/
|
|
67731
68054
|
start: require_sleep.method(zod.z.object({
|
|
67732
|
-
deviceId: DeviceIdSchema,
|
|
68055
|
+
deviceId: DeviceIdSchema$1,
|
|
67733
68056
|
program: zod.z.string().min(1).optional(),
|
|
67734
68057
|
options: zod.z.record(zod.z.string(), DishwasherValueSchema).optional()
|
|
67735
68058
|
}), zod.z.void(), {
|
|
67736
68059
|
kind: "mutation",
|
|
67737
68060
|
auth: "protected"
|
|
67738
68061
|
}),
|
|
67739
|
-
pause: require_sleep.method(zod.z.object({ deviceId: DeviceIdSchema }), zod.z.void(), {
|
|
68062
|
+
pause: require_sleep.method(zod.z.object({ deviceId: DeviceIdSchema$1 }), zod.z.void(), {
|
|
67740
68063
|
kind: "mutation",
|
|
67741
68064
|
auth: "protected"
|
|
67742
68065
|
}),
|
|
67743
|
-
resume: require_sleep.method(zod.z.object({ deviceId: DeviceIdSchema }), zod.z.void(), {
|
|
68066
|
+
resume: require_sleep.method(zod.z.object({ deviceId: DeviceIdSchema$1 }), zod.z.void(), {
|
|
67744
68067
|
kind: "mutation",
|
|
67745
68068
|
auth: "protected"
|
|
67746
68069
|
}),
|
|
67747
|
-
stop: require_sleep.method(zod.z.object({ deviceId: DeviceIdSchema }), zod.z.void(), {
|
|
68070
|
+
stop: require_sleep.method(zod.z.object({ deviceId: DeviceIdSchema$1 }), zod.z.void(), {
|
|
67748
68071
|
kind: "mutation",
|
|
67749
68072
|
auth: "protected"
|
|
67750
68073
|
}),
|
|
67751
68074
|
/** Select (not start) a program; refused when the appliance does not offer it. */
|
|
67752
68075
|
setProgram: require_sleep.method(zod.z.object({
|
|
67753
|
-
deviceId: DeviceIdSchema,
|
|
68076
|
+
deviceId: DeviceIdSchema$1,
|
|
67754
68077
|
program: zod.z.string().min(1)
|
|
67755
68078
|
}), zod.z.void(), {
|
|
67756
68079
|
kind: "mutation",
|
|
67757
68080
|
auth: "protected"
|
|
67758
68081
|
}),
|
|
67759
68082
|
setPower: require_sleep.method(zod.z.object({
|
|
67760
|
-
deviceId: DeviceIdSchema,
|
|
68083
|
+
deviceId: DeviceIdSchema$1,
|
|
67761
68084
|
on: zod.z.boolean()
|
|
67762
68085
|
}), zod.z.void(), {
|
|
67763
68086
|
kind: "mutation",
|
|
67764
68087
|
auth: "protected"
|
|
67765
68088
|
}),
|
|
67766
68089
|
setHalfLoad: require_sleep.method(zod.z.object({
|
|
67767
|
-
deviceId: DeviceIdSchema,
|
|
68090
|
+
deviceId: DeviceIdSchema$1,
|
|
67768
68091
|
on: zod.z.boolean()
|
|
67769
68092
|
}), zod.z.void(), {
|
|
67770
68093
|
kind: "mutation",
|
|
67771
68094
|
auth: "protected"
|
|
67772
68095
|
}),
|
|
67773
68096
|
setHygienePlus: require_sleep.method(zod.z.object({
|
|
67774
|
-
deviceId: DeviceIdSchema,
|
|
68097
|
+
deviceId: DeviceIdSchema$1,
|
|
67775
68098
|
on: zod.z.boolean()
|
|
67776
68099
|
}), zod.z.void(), {
|
|
67777
68100
|
kind: "mutation",
|
|
67778
68101
|
auth: "protected"
|
|
67779
68102
|
}),
|
|
67780
68103
|
setExtraDry: require_sleep.method(zod.z.object({
|
|
67781
|
-
deviceId: DeviceIdSchema,
|
|
68104
|
+
deviceId: DeviceIdSchema$1,
|
|
67782
68105
|
on: zod.z.boolean()
|
|
67783
68106
|
}), zod.z.void(), {
|
|
67784
68107
|
kind: "mutation",
|
|
67785
68108
|
auth: "protected"
|
|
67786
68109
|
}),
|
|
67787
68110
|
setIntensiveZone: require_sleep.method(zod.z.object({
|
|
67788
|
-
deviceId: DeviceIdSchema,
|
|
68111
|
+
deviceId: DeviceIdSchema$1,
|
|
67789
68112
|
on: zod.z.boolean()
|
|
67790
68113
|
}), zod.z.void(), {
|
|
67791
68114
|
kind: "mutation",
|
|
67792
68115
|
auth: "protected"
|
|
67793
68116
|
}),
|
|
67794
68117
|
setVarioSpeedPlus: require_sleep.method(zod.z.object({
|
|
67795
|
-
deviceId: DeviceIdSchema,
|
|
68118
|
+
deviceId: DeviceIdSchema$1,
|
|
67796
68119
|
on: zod.z.boolean()
|
|
67797
68120
|
}), zod.z.void(), {
|
|
67798
68121
|
kind: "mutation",
|
|
67799
68122
|
auth: "protected"
|
|
67800
68123
|
}),
|
|
67801
68124
|
setChildLock: require_sleep.method(zod.z.object({
|
|
67802
|
-
deviceId: DeviceIdSchema,
|
|
68125
|
+
deviceId: DeviceIdSchema$1,
|
|
67803
68126
|
on: zod.z.boolean()
|
|
67804
68127
|
}), zod.z.void(), {
|
|
67805
68128
|
kind: "mutation",
|
|
@@ -67811,7 +68134,7 @@ var dishwasherCapability = {
|
|
|
67811
68134
|
* its declared range / members.
|
|
67812
68135
|
*/
|
|
67813
68136
|
setOption: require_sleep.method(zod.z.object({
|
|
67814
|
-
deviceId: DeviceIdSchema,
|
|
68137
|
+
deviceId: DeviceIdSchema$1,
|
|
67815
68138
|
key: zod.z.string().min(1),
|
|
67816
68139
|
value: DishwasherValueSchema
|
|
67817
68140
|
}), zod.z.void(), {
|
|
@@ -67819,7 +68142,7 @@ var dishwasherCapability = {
|
|
|
67819
68142
|
auth: "protected"
|
|
67820
68143
|
}),
|
|
67821
68144
|
/** What this appliance can do, from its own description — the UI is derived from it. */
|
|
67822
|
-
getOptions: require_sleep.method(zod.z.object({ deviceId: DeviceIdSchema }), DishwasherOptionsSchema, { auth: "protected" })
|
|
68145
|
+
getOptions: require_sleep.method(zod.z.object({ deviceId: DeviceIdSchema$1 }), DishwasherOptionsSchema, { auth: "protected" })
|
|
67823
68146
|
},
|
|
67824
68147
|
status: {
|
|
67825
68148
|
schema: DishwasherStatusSchema,
|
|
@@ -72122,7 +72445,8 @@ var TopologyNodeSchema = zod.z.object({
|
|
|
72122
72445
|
isHub: zod.z.boolean(),
|
|
72123
72446
|
isOnline: zod.z.boolean(),
|
|
72124
72447
|
cpuPercent: zod.z.number(),
|
|
72125
|
-
|
|
72448
|
+
/** `null` when the node's memory read failed or it has not reported one (D393). */
|
|
72449
|
+
memoryPercent: zod.z.number().nullable(),
|
|
72126
72450
|
uptime: zod.z.number(),
|
|
72127
72451
|
lastSeen: zod.z.string(),
|
|
72128
72452
|
localIps: zod.z.array(zod.z.string()).readonly(),
|
|
@@ -72963,9 +73287,10 @@ var PetFeederStatusSchema = zod.z.object({
|
|
|
72963
73287
|
* combined reading; per-hopper levels live in `food1`/`food2`. Null when
|
|
72964
73288
|
* the device has not reported yet. */
|
|
72965
73289
|
foodLevel: zod.z.number().nullable().meta(require_sleep.readingMeta("none")),
|
|
72966
|
-
/** Food in the BOWL
|
|
72967
|
-
* feeder
|
|
72968
|
-
|
|
73290
|
+
/** Food in the BOWL, a mass (stored in kilograms, D944). Reported only by a
|
|
73291
|
+
* feeder with a bowl scale; null when the model has none or its reading is
|
|
73292
|
+
* of an unproven unit. */
|
|
73293
|
+
bowlFood: zod.z.number().nullable().meta(require_sleep.readingMeta("mass")),
|
|
72969
73294
|
/** True while the pet is eating (`state.eating`). */
|
|
72970
73295
|
eating: zod.z.boolean(),
|
|
72971
73296
|
/** Whether `markFoodReplenished` does anything on this model. When false
|
|
@@ -73150,6 +73475,139 @@ var petFeederCapability = {
|
|
|
73150
73475
|
} }
|
|
73151
73476
|
};
|
|
73152
73477
|
//#endregion
|
|
73478
|
+
//#region src/capabilities/pet-fountain.cap.ts
|
|
73479
|
+
/**
|
|
73480
|
+
* Pet water-fountain cap. Models the telemetry and the control surface of a
|
|
73481
|
+
* circulating drinking fountain: how much water is in the tank, how much the
|
|
73482
|
+
* pet drank, whether the pump runs and on what duty cycle.
|
|
73483
|
+
*
|
|
73484
|
+
* It has no native vendor provider of its own: a fountain reaches CamStack as
|
|
73485
|
+
* a container of loose entities (a pump switch, two number boxes, a "filter
|
|
73486
|
+
* changed" button), and an operator BUILDS the device from them — a composed
|
|
73487
|
+
* device of this type (D659, D967). Every method is therefore a forward to ONE
|
|
73488
|
+
* method of ONE source entity, and every reading is a field derived from a
|
|
73489
|
+
* source entity; the provider-shaped interface below exists so the composed
|
|
73490
|
+
* device and any future native provider answer the same contract.
|
|
73491
|
+
*
|
|
73492
|
+
* Quantities are stored in the base unit of their kind (D944): volumes in
|
|
73493
|
+
* LITRES, durations in SECONDS, the tank level in percent. A source that
|
|
73494
|
+
* reports millilitres or minutes is converted in the composition's expression,
|
|
73495
|
+
* never here. Every reading may be `null`: a source that is offline or does
|
|
73496
|
+
* not report is unknown, never zero.
|
|
73497
|
+
*
|
|
73498
|
+
* The filter is not a field of this cap: it is an item of the `consumables`
|
|
73499
|
+
* cap on the same device (kind `wear`), reset by the same forward mechanism.
|
|
73500
|
+
*/
|
|
73501
|
+
var PetFountainStatusSchema = zod.z.object({
|
|
73502
|
+
/** Water in the tank, 0..100 (%). Null while the source has not reported. */
|
|
73503
|
+
waterLevel: zod.z.number().min(0).max(100).nullable().meta(require_sleep.readingMeta("percentage")),
|
|
73504
|
+
/** Water in the tank, in litres. Null while the source has not reported. */
|
|
73505
|
+
waterVolume: zod.z.number().min(0).nullable().meta(require_sleep.readingMeta("volume")),
|
|
73506
|
+
/** True when the tank is empty. Null while unknown. */
|
|
73507
|
+
empty: zod.z.boolean().nullable(),
|
|
73508
|
+
/** True while the pump is running. Null while unknown. */
|
|
73509
|
+
pumpRunning: zod.z.boolean().nullable(),
|
|
73510
|
+
/** True when the pump works on an on/off duty cycle rather than continuously. */
|
|
73511
|
+
pumpIntervalEnabled: zod.z.boolean().nullable(),
|
|
73512
|
+
/** How long the pump runs per cycle, in seconds. */
|
|
73513
|
+
pumpOnTime: zod.z.number().min(0).nullable().meta(require_sleep.readingMeta("duration")),
|
|
73514
|
+
/** How long the pump rests per cycle, in seconds. */
|
|
73515
|
+
pumpOffTime: zod.z.number().min(0).nullable().meta(require_sleep.readingMeta("duration")),
|
|
73516
|
+
/** Water drunk in the last drink, in litres. */
|
|
73517
|
+
lastDrink: zod.z.number().min(0).nullable().meta(require_sleep.readingMeta("volume")),
|
|
73518
|
+
/** Water drunk in the current hour, in litres. */
|
|
73519
|
+
currentHourDrink: zod.z.number().min(0).nullable().meta(require_sleep.readingMeta("volume")),
|
|
73520
|
+
/** Water drunk over the last 24 hours (rolling), in litres. */
|
|
73521
|
+
last24hDrink: zod.z.number().min(0).nullable().meta(require_sleep.readingMeta("volume")),
|
|
73522
|
+
/** Water drunk since local midnight, in litres. */
|
|
73523
|
+
todayDrink: zod.z.number().min(0).nullable().meta(require_sleep.readingMeta("volume")),
|
|
73524
|
+
/** Decoded fault message. Null means healthy; a non-null string is an active fault. */
|
|
73525
|
+
error: zod.z.string().nullable(),
|
|
73526
|
+
/** Ms epoch when the slice was last refreshed. */
|
|
73527
|
+
lastFetchedAt: zod.z.number()
|
|
73528
|
+
});
|
|
73529
|
+
var DeviceIdSchema = zod.z.number().int().nonnegative();
|
|
73530
|
+
var MinutesSchema = zod.z.number().int().min(0);
|
|
73531
|
+
var petFountainCapability = {
|
|
73532
|
+
name: "pet-fountain",
|
|
73533
|
+
scope: "device",
|
|
73534
|
+
deviceNative: true,
|
|
73535
|
+
mode: "singleton",
|
|
73536
|
+
deviceTypes: [require_err_msg.DeviceType.PetFountain],
|
|
73537
|
+
methods: {
|
|
73538
|
+
/** Start or stop the pump. */
|
|
73539
|
+
setPump: require_sleep.method(zod.z.object({
|
|
73540
|
+
deviceId: DeviceIdSchema,
|
|
73541
|
+
on: zod.z.boolean()
|
|
73542
|
+
}), zod.z.void(), {
|
|
73543
|
+
kind: "mutation",
|
|
73544
|
+
auth: "protected"
|
|
73545
|
+
}),
|
|
73546
|
+
/** Switch the on/off duty cycle on or off (off = the pump runs continuously). */
|
|
73547
|
+
setPumpInterval: require_sleep.method(zod.z.object({
|
|
73548
|
+
deviceId: DeviceIdSchema,
|
|
73549
|
+
on: zod.z.boolean()
|
|
73550
|
+
}), zod.z.void(), {
|
|
73551
|
+
kind: "mutation",
|
|
73552
|
+
auth: "protected"
|
|
73553
|
+
}),
|
|
73554
|
+
/** Set how many minutes the pump runs per cycle. */
|
|
73555
|
+
setPumpOnMinutes: require_sleep.method(zod.z.object({
|
|
73556
|
+
deviceId: DeviceIdSchema,
|
|
73557
|
+
minutes: MinutesSchema
|
|
73558
|
+
}), zod.z.void(), {
|
|
73559
|
+
kind: "mutation",
|
|
73560
|
+
auth: "protected"
|
|
73561
|
+
}),
|
|
73562
|
+
/** Set how many minutes the pump rests per cycle. */
|
|
73563
|
+
setPumpOffMinutes: require_sleep.method(zod.z.object({
|
|
73564
|
+
deviceId: DeviceIdSchema,
|
|
73565
|
+
minutes: MinutesSchema
|
|
73566
|
+
}), zod.z.void(), {
|
|
73567
|
+
kind: "mutation",
|
|
73568
|
+
auth: "protected"
|
|
73569
|
+
}),
|
|
73570
|
+
/** Clear the rolling daily consumption counters on the device. */
|
|
73571
|
+
resetDailyConsumption: require_sleep.method(zod.z.object({ deviceId: DeviceIdSchema }), zod.z.void(), {
|
|
73572
|
+
kind: "mutation",
|
|
73573
|
+
auth: "protected"
|
|
73574
|
+
})
|
|
73575
|
+
},
|
|
73576
|
+
status: {
|
|
73577
|
+
schema: PetFountainStatusSchema,
|
|
73578
|
+
kind: "push"
|
|
73579
|
+
},
|
|
73580
|
+
/** Runtime-state slice — mirrored by the kernel; the hero card reads it whole. */
|
|
73581
|
+
runtimeState: PetFountainStatusSchema,
|
|
73582
|
+
/**
|
|
73583
|
+
* Runtime-state durability: **session** — live appliance state re-published on connect.
|
|
73584
|
+
*
|
|
73585
|
+
* See `RuntimeStateDurability`. Enforced by
|
|
73586
|
+
* `scripts/check-runtime-state-durability.ts`.
|
|
73587
|
+
*/
|
|
73588
|
+
durability: "session",
|
|
73589
|
+
/** History (D850): recorded series. */
|
|
73590
|
+
history: { fields: {
|
|
73591
|
+
waterLevel: {
|
|
73592
|
+
kind: "gauge",
|
|
73593
|
+
unit: "%",
|
|
73594
|
+
deadband: 1
|
|
73595
|
+
},
|
|
73596
|
+
waterVolume: {
|
|
73597
|
+
kind: "gauge",
|
|
73598
|
+
unit: "L"
|
|
73599
|
+
},
|
|
73600
|
+
todayDrink: {
|
|
73601
|
+
kind: "gauge",
|
|
73602
|
+
unit: "L"
|
|
73603
|
+
},
|
|
73604
|
+
last24hDrink: {
|
|
73605
|
+
kind: "gauge",
|
|
73606
|
+
unit: "L"
|
|
73607
|
+
}
|
|
73608
|
+
} }
|
|
73609
|
+
};
|
|
73610
|
+
//#endregion
|
|
73153
73611
|
//#region src/capabilities/plate-gallery.cap.ts
|
|
73154
73612
|
var VehicleSchema = zod.z.object({
|
|
73155
73613
|
id: zod.z.string(),
|
|
@@ -83042,7 +83500,7 @@ var ROOM_EXAMPLE_MOTION_SOURCES = [{
|
|
|
83042
83500
|
addonId: "provider-homeassistant",
|
|
83043
83501
|
stableId: "binary_sensor.living_room_presence"
|
|
83044
83502
|
}];
|
|
83045
|
-
function from(source, cap, fieldPath) {
|
|
83503
|
+
function from$1(source, cap, fieldPath) {
|
|
83046
83504
|
return {
|
|
83047
83505
|
kind: "from",
|
|
83048
83506
|
source,
|
|
@@ -83051,7 +83509,7 @@ function from(source, cap, fieldPath) {
|
|
|
83051
83509
|
};
|
|
83052
83510
|
}
|
|
83053
83511
|
function named(prefix, sources, cap, fieldPath) {
|
|
83054
|
-
return Object.fromEntries(sources.map((s, i) => [`${prefix}${i + 1}`, from(s, cap, fieldPath)]));
|
|
83512
|
+
return Object.fromEntries(sources.map((s, i) => [`${prefix}${i + 1}`, from$1(s, cap, fieldPath)]));
|
|
83055
83513
|
}
|
|
83056
83514
|
function roomCompositionExample(input) {
|
|
83057
83515
|
const t = named("t", input.temperatureSources, "temperature-sensor", "temperature");
|
|
@@ -83139,7 +83597,7 @@ function feederExampleSources(brokerId) {
|
|
|
83139
83597
|
};
|
|
83140
83598
|
}
|
|
83141
83599
|
function feederCustomizationExample(sources) {
|
|
83142
|
-
const days = { d: from(sources.desiccantDays, "enum-sensor", "value") };
|
|
83600
|
+
const days = { d: from$1(sources.desiccantDays, "enum-sensor", "value") };
|
|
83143
83601
|
return require_composition.CompositionSchema.parse({
|
|
83144
83602
|
target: {
|
|
83145
83603
|
kind: "existing",
|
|
@@ -83187,7 +83645,7 @@ function feederCustomizationExample(sources) {
|
|
|
83187
83645
|
level: {
|
|
83188
83646
|
kind: "expression",
|
|
83189
83647
|
expr: "s == \"low\" ? 15 : (s == \"normal\" ? 100 : null)",
|
|
83190
|
-
bindings: { s: from(sources.batteryStatus, "enum-sensor", "value") }
|
|
83648
|
+
bindings: { s: from$1(sources.batteryStatus, "enum-sensor", "value") }
|
|
83191
83649
|
},
|
|
83192
83650
|
binary: {
|
|
83193
83651
|
kind: "expression",
|
|
@@ -83197,7 +83655,7 @@ function feederCustomizationExample(sources) {
|
|
|
83197
83655
|
charging: {
|
|
83198
83656
|
kind: "expression",
|
|
83199
83657
|
expr: "c ? \"dc\" : \"unknown\"",
|
|
83200
|
-
bindings: { c: from(sources.batteryCharging, "binary", "on") }
|
|
83658
|
+
bindings: { c: from$1(sources.batteryCharging, "binary", "on") }
|
|
83201
83659
|
},
|
|
83202
83660
|
sleeping: {
|
|
83203
83661
|
kind: "expression",
|
|
@@ -83283,6 +83741,158 @@ function convertPresetFeature(input) {
|
|
|
83283
83741
|
};
|
|
83284
83742
|
}
|
|
83285
83743
|
//#endregion
|
|
83744
|
+
//#region src/composition/presets/pet-fountain.ts
|
|
83745
|
+
/**
|
|
83746
|
+
* The preset for a pet water fountain built from loose entities (D659, D967).
|
|
83747
|
+
*
|
|
83748
|
+
* A fountain reaches CamStack as a container of single-purpose entities: a
|
|
83749
|
+
* pump switch, a cycle switch, two number boxes, a handful of sensors that
|
|
83750
|
+
* report millilitres as text, and a few buttons. This preset names the
|
|
83751
|
+
* `pet-fountain` cap's fields over those entities, forwards each of its five
|
|
83752
|
+
* methods to ONE entity method, and adds the filter as a resettable
|
|
83753
|
+
* `consumables` item.
|
|
83754
|
+
*
|
|
83755
|
+
* Stored quantities are base units (D944): litres for volume, seconds for
|
|
83756
|
+
* duration. The cycle times cannot be read back (see `pumpOnTime` below). The sensors are `enum-sensor`s, so their value is a STRING:
|
|
83757
|
+
* `number(x)` reads it and anything that is not a number stays `null`, never
|
|
83758
|
+
* 0 (D393). The caller supplies the sources — it knows which entity is which;
|
|
83759
|
+
* the preset guesses no entity id.
|
|
83760
|
+
*/
|
|
83761
|
+
var UNKNOWN = {
|
|
83762
|
+
kind: "expression",
|
|
83763
|
+
expr: "null",
|
|
83764
|
+
bindings: {}
|
|
83765
|
+
};
|
|
83766
|
+
var NOW = {
|
|
83767
|
+
kind: "expression",
|
|
83768
|
+
expr: "now",
|
|
83769
|
+
bindings: {}
|
|
83770
|
+
};
|
|
83771
|
+
function from(source, cap, fieldPath) {
|
|
83772
|
+
return {
|
|
83773
|
+
kind: "from",
|
|
83774
|
+
source,
|
|
83775
|
+
cap,
|
|
83776
|
+
fieldPath
|
|
83777
|
+
};
|
|
83778
|
+
}
|
|
83779
|
+
function over(name, binding, expr) {
|
|
83780
|
+
return {
|
|
83781
|
+
kind: "expression",
|
|
83782
|
+
expr,
|
|
83783
|
+
bindings: { [name]: binding }
|
|
83784
|
+
};
|
|
83785
|
+
}
|
|
83786
|
+
/** A text reading in millilitres, as litres; unreadable stays unknown. */
|
|
83787
|
+
function millilitresAsLitres(source) {
|
|
83788
|
+
return over("v", from(source, "enum-sensor", "value"), "number(v) == null ? null : number(v) / 1000");
|
|
83789
|
+
}
|
|
83790
|
+
function percentOf(source) {
|
|
83791
|
+
return over("l", from(source, "enum-sensor", "value"), "number(l)");
|
|
83792
|
+
}
|
|
83793
|
+
function filterFeature(filter) {
|
|
83794
|
+
const days = { d: from(filter.daysRemaining, "enum-sensor", "value") };
|
|
83795
|
+
return {
|
|
83796
|
+
kind: "fields",
|
|
83797
|
+
cap: "consumables",
|
|
83798
|
+
fields: {
|
|
83799
|
+
lastChangedAt: NOW,
|
|
83800
|
+
lastFetchedAt: NOW
|
|
83801
|
+
},
|
|
83802
|
+
items: { filter: {
|
|
83803
|
+
label: "Filter",
|
|
83804
|
+
fields: {
|
|
83805
|
+
"remaining.value": {
|
|
83806
|
+
kind: "expression",
|
|
83807
|
+
expr: "number(d)",
|
|
83808
|
+
bindings: days
|
|
83809
|
+
},
|
|
83810
|
+
"remaining.kind": {
|
|
83811
|
+
kind: "expression",
|
|
83812
|
+
expr: "\"duration\"",
|
|
83813
|
+
bindings: {}
|
|
83814
|
+
},
|
|
83815
|
+
status: {
|
|
83816
|
+
kind: "expression",
|
|
83817
|
+
expr: "number(d) == null ? null : (number(d) <= 0 ? \"replace\" : \"ok\")",
|
|
83818
|
+
bindings: days
|
|
83819
|
+
}
|
|
83820
|
+
},
|
|
83821
|
+
reset: {
|
|
83822
|
+
kind: "forward",
|
|
83823
|
+
source: filter.changed,
|
|
83824
|
+
cap: "button",
|
|
83825
|
+
method: "press"
|
|
83826
|
+
}
|
|
83827
|
+
} }
|
|
83828
|
+
};
|
|
83829
|
+
}
|
|
83830
|
+
function petFountainFromEntitiesComposition(sources) {
|
|
83831
|
+
const minutes = {
|
|
83832
|
+
kind: "numeric",
|
|
83833
|
+
value: { $input: "minutes" }
|
|
83834
|
+
};
|
|
83835
|
+
return require_composition.CompositionSchema.parse({
|
|
83836
|
+
target: {
|
|
83837
|
+
kind: "new",
|
|
83838
|
+
type: require_err_msg.DeviceType.PetFountain
|
|
83839
|
+
},
|
|
83840
|
+
features: [{
|
|
83841
|
+
kind: "fields",
|
|
83842
|
+
cap: "pet-fountain",
|
|
83843
|
+
fields: {
|
|
83844
|
+
waterLevel: percentOf(sources.waterLevel),
|
|
83845
|
+
waterVolume: millilitresAsLitres(sources.waterVolume),
|
|
83846
|
+
empty: over("l", from(sources.waterLevel, "enum-sensor", "value"), "number(l) == null ? null : number(l) <= 0"),
|
|
83847
|
+
pumpRunning: from(sources.pump, "switch", "on"),
|
|
83848
|
+
pumpIntervalEnabled: from(sources.pumpInterval, "switch", "on"),
|
|
83849
|
+
pumpOnTime: UNKNOWN,
|
|
83850
|
+
pumpOffTime: UNKNOWN,
|
|
83851
|
+
lastDrink: millilitresAsLitres(sources.lastDrink),
|
|
83852
|
+
currentHourDrink: millilitresAsLitres(sources.currentHourDrink),
|
|
83853
|
+
last24hDrink: millilitresAsLitres(sources.last24hDrink),
|
|
83854
|
+
todayDrink: millilitresAsLitres(sources.todayDrink),
|
|
83855
|
+
error: UNKNOWN,
|
|
83856
|
+
lastFetchedAt: NOW
|
|
83857
|
+
},
|
|
83858
|
+
commands: {
|
|
83859
|
+
setPump: {
|
|
83860
|
+
kind: "forward",
|
|
83861
|
+
source: sources.pump,
|
|
83862
|
+
cap: "switch",
|
|
83863
|
+
method: "setState"
|
|
83864
|
+
},
|
|
83865
|
+
setPumpInterval: {
|
|
83866
|
+
kind: "forward",
|
|
83867
|
+
source: sources.pumpInterval,
|
|
83868
|
+
cap: "switch",
|
|
83869
|
+
method: "setState"
|
|
83870
|
+
},
|
|
83871
|
+
setPumpOnMinutes: {
|
|
83872
|
+
kind: "forward",
|
|
83873
|
+
source: sources.pumpOnMinutes,
|
|
83874
|
+
cap: "control",
|
|
83875
|
+
method: "setValue",
|
|
83876
|
+
args: { control: minutes }
|
|
83877
|
+
},
|
|
83878
|
+
setPumpOffMinutes: {
|
|
83879
|
+
kind: "forward",
|
|
83880
|
+
source: sources.pumpOffMinutes,
|
|
83881
|
+
cap: "control",
|
|
83882
|
+
method: "setValue",
|
|
83883
|
+
args: { control: minutes }
|
|
83884
|
+
},
|
|
83885
|
+
resetDailyConsumption: {
|
|
83886
|
+
kind: "forward",
|
|
83887
|
+
source: sources.clearDaily,
|
|
83888
|
+
cap: "button",
|
|
83889
|
+
method: "press"
|
|
83890
|
+
}
|
|
83891
|
+
}
|
|
83892
|
+
}, ...sources.filter === void 0 ? [] : [filterFeature(sources.filter)]]
|
|
83893
|
+
});
|
|
83894
|
+
}
|
|
83895
|
+
//#endregion
|
|
83286
83896
|
//#region src/composition/cards/classify-field.ts
|
|
83287
83897
|
function fromSources(binding) {
|
|
83288
83898
|
return {
|
|
@@ -83532,6 +84142,7 @@ var CAP_CUSTOMIZE_CATALOG = {
|
|
|
83532
84142
|
require_err_msg.DeviceType.Container,
|
|
83533
84143
|
require_err_msg.DeviceType.Image,
|
|
83534
84144
|
require_err_msg.DeviceType.PetFeeder,
|
|
84145
|
+
require_err_msg.DeviceType.PetFountain,
|
|
83535
84146
|
require_err_msg.DeviceType.Dishwasher,
|
|
83536
84147
|
require_err_msg.DeviceType.Washer,
|
|
83537
84148
|
require_err_msg.DeviceType.Dryer
|
|
@@ -86044,6 +86655,7 @@ var DEVICE_LOCAL_STATE_CAPS = {
|
|
|
86044
86655
|
notifier: notifierCapability,
|
|
86045
86656
|
numericSensor: numericSensorCapability,
|
|
86046
86657
|
petFeeder: petFeederCapability,
|
|
86658
|
+
petFountain: petFountainCapability,
|
|
86047
86659
|
powerMeter: powerMeterCapability,
|
|
86048
86660
|
presence: presenceCapability,
|
|
86049
86661
|
pressureSensor: pressureSensorCapability,
|
|
@@ -88032,6 +88644,7 @@ var DEVICE_TYPE_CONTROL_KIND = {
|
|
|
88032
88644
|
[require_err_msg.DeviceType.Container]: "dummy",
|
|
88033
88645
|
[require_err_msg.DeviceType.Image]: "image",
|
|
88034
88646
|
[require_err_msg.DeviceType.PetFeeder]: "pet-feeder",
|
|
88647
|
+
[require_err_msg.DeviceType.PetFountain]: "pet-fountain",
|
|
88035
88648
|
[require_err_msg.DeviceType.Dishwasher]: "dishwasher",
|
|
88036
88649
|
[require_err_msg.DeviceType.Washer]: "dummy",
|
|
88037
88650
|
[require_err_msg.DeviceType.Dryer]: "dummy"
|
|
@@ -90074,6 +90687,13 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
90074
90687
|
access: "create",
|
|
90075
90688
|
role: "admin"
|
|
90076
90689
|
},
|
|
90690
|
+
"deviceExport.exposeEntity": {
|
|
90691
|
+
capName: "device-export",
|
|
90692
|
+
capScope: "system",
|
|
90693
|
+
addonId: null,
|
|
90694
|
+
access: "create",
|
|
90695
|
+
role: "admin"
|
|
90696
|
+
},
|
|
90077
90697
|
"deviceExport.getDeviceLiveContribution": {
|
|
90078
90698
|
capName: "device-export",
|
|
90079
90699
|
capScope: "system",
|
|
@@ -90102,6 +90722,13 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
90102
90722
|
access: "view",
|
|
90103
90723
|
role: "admin"
|
|
90104
90724
|
},
|
|
90725
|
+
"deviceExport.listExposedEntities": {
|
|
90726
|
+
capName: "device-export",
|
|
90727
|
+
capScope: "system",
|
|
90728
|
+
addonId: null,
|
|
90729
|
+
access: "view",
|
|
90730
|
+
role: "admin"
|
|
90731
|
+
},
|
|
90105
90732
|
"deviceExport.listSupportedDeviceKinds": {
|
|
90106
90733
|
capName: "device-export",
|
|
90107
90734
|
capScope: "system",
|
|
@@ -90109,6 +90736,13 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
90109
90736
|
access: "view",
|
|
90110
90737
|
role: "admin"
|
|
90111
90738
|
},
|
|
90739
|
+
"deviceExport.listSupportedEntityKinds": {
|
|
90740
|
+
capName: "device-export",
|
|
90741
|
+
capScope: "system",
|
|
90742
|
+
addonId: null,
|
|
90743
|
+
access: "view",
|
|
90744
|
+
role: "admin"
|
|
90745
|
+
},
|
|
90112
90746
|
"deviceExport.unexposeDevice": {
|
|
90113
90747
|
capName: "device-export",
|
|
90114
90748
|
capScope: "system",
|
|
@@ -90116,6 +90750,13 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
90116
90750
|
access: "create",
|
|
90117
90751
|
role: "admin"
|
|
90118
90752
|
},
|
|
90753
|
+
"deviceExport.unexposeEntity": {
|
|
90754
|
+
capName: "device-export",
|
|
90755
|
+
capScope: "system",
|
|
90756
|
+
addonId: null,
|
|
90757
|
+
access: "create",
|
|
90758
|
+
role: "admin"
|
|
90759
|
+
},
|
|
90119
90760
|
"deviceExtension.listCandidates": {
|
|
90120
90761
|
capName: "device-extension",
|
|
90121
90762
|
capScope: "device",
|
|
@@ -93581,6 +94222,48 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
93581
94222
|
access: "create",
|
|
93582
94223
|
role: "viewer"
|
|
93583
94224
|
},
|
|
94225
|
+
"petFountain.getStatus": {
|
|
94226
|
+
capName: "pet-fountain",
|
|
94227
|
+
capScope: "device",
|
|
94228
|
+
addonId: null,
|
|
94229
|
+
access: "view",
|
|
94230
|
+
role: "viewer"
|
|
94231
|
+
},
|
|
94232
|
+
"petFountain.resetDailyConsumption": {
|
|
94233
|
+
capName: "pet-fountain",
|
|
94234
|
+
capScope: "device",
|
|
94235
|
+
addonId: null,
|
|
94236
|
+
access: "delete",
|
|
94237
|
+
role: "viewer"
|
|
94238
|
+
},
|
|
94239
|
+
"petFountain.setPump": {
|
|
94240
|
+
capName: "pet-fountain",
|
|
94241
|
+
capScope: "device",
|
|
94242
|
+
addonId: null,
|
|
94243
|
+
access: "create",
|
|
94244
|
+
role: "viewer"
|
|
94245
|
+
},
|
|
94246
|
+
"petFountain.setPumpInterval": {
|
|
94247
|
+
capName: "pet-fountain",
|
|
94248
|
+
capScope: "device",
|
|
94249
|
+
addonId: null,
|
|
94250
|
+
access: "create",
|
|
94251
|
+
role: "viewer"
|
|
94252
|
+
},
|
|
94253
|
+
"petFountain.setPumpOffMinutes": {
|
|
94254
|
+
capName: "pet-fountain",
|
|
94255
|
+
capScope: "device",
|
|
94256
|
+
addonId: null,
|
|
94257
|
+
access: "create",
|
|
94258
|
+
role: "viewer"
|
|
94259
|
+
},
|
|
94260
|
+
"petFountain.setPumpOnMinutes": {
|
|
94261
|
+
capName: "pet-fountain",
|
|
94262
|
+
capScope: "device",
|
|
94263
|
+
addonId: null,
|
|
94264
|
+
access: "create",
|
|
94265
|
+
role: "viewer"
|
|
94266
|
+
},
|
|
93584
94267
|
"pipelineAnalytics.addRetrainFrameFromRecording": {
|
|
93585
94268
|
capName: "pipeline-analytics",
|
|
93586
94269
|
capScope: "device",
|
|
@@ -95982,6 +96665,13 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
95982
96665
|
access: "create",
|
|
95983
96666
|
role: "admin"
|
|
95984
96667
|
},
|
|
96668
|
+
"serverManagement.getLaunchOverrides": {
|
|
96669
|
+
capName: "server-management",
|
|
96670
|
+
capScope: "system",
|
|
96671
|
+
addonId: null,
|
|
96672
|
+
access: "view",
|
|
96673
|
+
role: "admin"
|
|
96674
|
+
},
|
|
95985
96675
|
"serverManagement.getServerPackageStatus": {
|
|
95986
96676
|
capName: "server-management",
|
|
95987
96677
|
capScope: "system",
|
|
@@ -96003,6 +96693,13 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
96003
96693
|
access: "create",
|
|
96004
96694
|
role: "admin"
|
|
96005
96695
|
},
|
|
96696
|
+
"serverManagement.setLaunchOverrides": {
|
|
96697
|
+
capName: "server-management",
|
|
96698
|
+
capScope: "system",
|
|
96699
|
+
addonId: null,
|
|
96700
|
+
access: "create",
|
|
96701
|
+
role: "admin"
|
|
96702
|
+
},
|
|
96006
96703
|
"settingsStore.aggregate": {
|
|
96007
96704
|
capName: "settings-store",
|
|
96008
96705
|
capScope: "system",
|
|
@@ -98190,6 +98887,7 @@ var KNOWN_CAP_NAMES = [
|
|
|
98190
98887
|
"osd",
|
|
98191
98888
|
"osd-manager",
|
|
98192
98889
|
"pet-feeder",
|
|
98890
|
+
"pet-fountain",
|
|
98193
98891
|
"pipeline-analytics",
|
|
98194
98892
|
"pipeline-executor",
|
|
98195
98893
|
"pipeline-orchestrator",
|
|
@@ -98321,6 +99019,7 @@ var DEVICE_CAP_NAMES = [
|
|
|
98321
99019
|
"numeric-sensor",
|
|
98322
99020
|
"osd",
|
|
98323
99021
|
"pet-feeder",
|
|
99022
|
+
"pet-fountain",
|
|
98324
99023
|
"pipeline-analytics",
|
|
98325
99024
|
"power-meter",
|
|
98326
99025
|
"presence",
|
|
@@ -100460,6 +101159,100 @@ var APPLIANCE_CAP_VOCABULARY = {
|
|
|
100460
101159
|
}
|
|
100461
101160
|
]
|
|
100462
101161
|
},
|
|
101162
|
+
"pet-fountain": {
|
|
101163
|
+
scope: "device",
|
|
101164
|
+
noun: t("Pet fountain", "Fontana per animali"),
|
|
101165
|
+
actions: [
|
|
101166
|
+
{
|
|
101167
|
+
id: "petFountain.pumpOn",
|
|
101168
|
+
method: "setPump",
|
|
101169
|
+
label: t("Pump on", "Pompa accesa"),
|
|
101170
|
+
phrase: t("Start the pump of {device}", "Avvia la pompa di {device}"),
|
|
101171
|
+
icon: "play",
|
|
101172
|
+
args: { on: true }
|
|
101173
|
+
},
|
|
101174
|
+
{
|
|
101175
|
+
id: "petFountain.pumpOff",
|
|
101176
|
+
method: "setPump",
|
|
101177
|
+
label: t("Pump off", "Pompa spenta"),
|
|
101178
|
+
phrase: t("Stop the pump of {device}", "Ferma la pompa di {device}"),
|
|
101179
|
+
icon: "square",
|
|
101180
|
+
args: { on: false }
|
|
101181
|
+
},
|
|
101182
|
+
{
|
|
101183
|
+
id: "petFountain.intervalOn",
|
|
101184
|
+
method: "setPumpInterval",
|
|
101185
|
+
label: t("Pump cycle on", "Ciclo pompa attivo"),
|
|
101186
|
+
phrase: t("Run the pump of {device} on its on/off cycle", "Fai lavorare la pompa di {device} a ciclo acceso/spento"),
|
|
101187
|
+
icon: "timer",
|
|
101188
|
+
args: { on: true }
|
|
101189
|
+
},
|
|
101190
|
+
{
|
|
101191
|
+
id: "petFountain.intervalOff",
|
|
101192
|
+
method: "setPumpInterval",
|
|
101193
|
+
label: t("Pump cycle off", "Ciclo pompa spento"),
|
|
101194
|
+
phrase: t("Run the pump of {device} continuously", "Fai lavorare la pompa di {device} in continuo"),
|
|
101195
|
+
icon: "timer-off",
|
|
101196
|
+
args: { on: false }
|
|
101197
|
+
},
|
|
101198
|
+
{
|
|
101199
|
+
id: "petFountain.pumpOnMinutes",
|
|
101200
|
+
method: "setPumpOnMinutes",
|
|
101201
|
+
label: t("Set pump run time", "Imposta il tempo di lavoro della pompa"),
|
|
101202
|
+
phrase: t("Set the pump of {device} to run {minutes} minutes per cycle", "Imposta la pompa di {device} a lavorare {minutes} minuti per ciclo"),
|
|
101203
|
+
icon: "timer",
|
|
101204
|
+
openArgs: [{
|
|
101205
|
+
key: "minutes",
|
|
101206
|
+
label: t("Minutes", "Minuti"),
|
|
101207
|
+
offer: {
|
|
101208
|
+
kind: "number",
|
|
101209
|
+
min: 0,
|
|
101210
|
+
step: 1,
|
|
101211
|
+
unit: "min"
|
|
101212
|
+
}
|
|
101213
|
+
}]
|
|
101214
|
+
},
|
|
101215
|
+
{
|
|
101216
|
+
id: "petFountain.pumpOffMinutes",
|
|
101217
|
+
method: "setPumpOffMinutes",
|
|
101218
|
+
label: t("Set pump rest time", "Imposta il tempo di riposo della pompa"),
|
|
101219
|
+
phrase: t("Set the pump of {device} to rest {minutes} minutes per cycle", "Imposta la pompa di {device} a riposare {minutes} minuti per ciclo"),
|
|
101220
|
+
icon: "timer-off",
|
|
101221
|
+
openArgs: [{
|
|
101222
|
+
key: "minutes",
|
|
101223
|
+
label: t("Minutes", "Minuti"),
|
|
101224
|
+
offer: {
|
|
101225
|
+
kind: "number",
|
|
101226
|
+
min: 0,
|
|
101227
|
+
step: 1,
|
|
101228
|
+
unit: "min"
|
|
101229
|
+
}
|
|
101230
|
+
}]
|
|
101231
|
+
},
|
|
101232
|
+
{
|
|
101233
|
+
id: "petFountain.resetDailyConsumption",
|
|
101234
|
+
method: "resetDailyConsumption",
|
|
101235
|
+
label: t("Clear daily consumption", "Azzera il consumo giornaliero"),
|
|
101236
|
+
phrase: t("Clear the daily water consumption of {device}", "Azzera il consumo giornaliero di acqua di {device}"),
|
|
101237
|
+
icon: "rotate-ccw"
|
|
101238
|
+
}
|
|
101239
|
+
],
|
|
101240
|
+
state: [{
|
|
101241
|
+
kind: "boolean",
|
|
101242
|
+
field: "empty",
|
|
101243
|
+
label: t("Tank empty", "Serbatoio vuoto"),
|
|
101244
|
+
whenTrue: t("When the tank of {device} is empty", "Quando il serbatoio di {device} è vuoto"),
|
|
101245
|
+
whenFalse: t("When the tank of {device} is refilled", "Quando il serbatoio di {device} viene riempito"),
|
|
101246
|
+
icon: "droplet"
|
|
101247
|
+
}, {
|
|
101248
|
+
kind: "numeric",
|
|
101249
|
+
field: "waterLevel",
|
|
101250
|
+
quantity: t("the water level", "il livello dell’acqua"),
|
|
101251
|
+
label: t("Water level", "Livello dell’acqua"),
|
|
101252
|
+
unit: "%",
|
|
101253
|
+
icon: "droplets"
|
|
101254
|
+
}]
|
|
101255
|
+
},
|
|
100463
101256
|
"media-player": {
|
|
100464
101257
|
scope: "device",
|
|
100465
101258
|
noun: t("Media player", "Lettore multimediale"),
|
|
@@ -102522,6 +103315,7 @@ var DEVICE_TYPE_DO_CAPS = {
|
|
|
102522
103315
|
[require_err_msg.DeviceType.Container]: [],
|
|
102523
103316
|
[require_err_msg.DeviceType.Image]: [],
|
|
102524
103317
|
[require_err_msg.DeviceType.PetFeeder]: ["pet-feeder"],
|
|
103318
|
+
[require_err_msg.DeviceType.PetFountain]: ["pet-fountain"],
|
|
102525
103319
|
[require_err_msg.DeviceType.Dishwasher]: ["dishwasher"],
|
|
102526
103320
|
[require_err_msg.DeviceType.Washer]: [],
|
|
102527
103321
|
[require_err_msg.DeviceType.Dryer]: []
|
|
@@ -104140,6 +104934,7 @@ var CAP_NAMES_WITH_STATUS = [
|
|
|
104140
104934
|
"numeric-sensor",
|
|
104141
104935
|
"osd",
|
|
104142
104936
|
"pet-feeder",
|
|
104937
|
+
"pet-fountain",
|
|
104143
104938
|
"power-meter",
|
|
104144
104939
|
"presence",
|
|
104145
104940
|
"pressure-sensor",
|
|
@@ -104294,6 +105089,7 @@ var CAPABILITY_NAMES = {
|
|
|
104294
105089
|
osd: "osd",
|
|
104295
105090
|
osdManager: "osd-manager",
|
|
104296
105091
|
petFeeder: "pet-feeder",
|
|
105092
|
+
petFountain: "pet-fountain",
|
|
104297
105093
|
pipelineAnalytics: "pipeline-analytics",
|
|
104298
105094
|
pipelineExecutor: "pipeline-executor",
|
|
104299
105095
|
pipelineOrchestrator: "pipeline-orchestrator",
|
|
@@ -104866,6 +105662,10 @@ var CAPABILITY_ROUTER_KEYS = [
|
|
|
104866
105662
|
key: "petFeeder",
|
|
104867
105663
|
name: "pet-feeder"
|
|
104868
105664
|
},
|
|
105665
|
+
{
|
|
105666
|
+
key: "petFountain",
|
|
105667
|
+
name: "pet-fountain"
|
|
105668
|
+
},
|
|
104869
105669
|
{
|
|
104870
105670
|
key: "pipelineAnalytics",
|
|
104871
105671
|
name: "pipeline-analytics"
|
|
@@ -105141,7 +105941,7 @@ var ALL_CAPABILITY_DEFINITIONS = [
|
|
|
105141
105941
|
actionSourceCapability,
|
|
105142
105942
|
actionsCapability,
|
|
105143
105943
|
addonPagesCapability,
|
|
105144
|
-
addonPagesSourceCapability,
|
|
105944
|
+
require_sleep.addonPagesSourceCapability,
|
|
105145
105945
|
addonRoutesCapability,
|
|
105146
105946
|
addonSettingsCapability,
|
|
105147
105947
|
addonWidgetsCapability,
|
|
@@ -105263,6 +106063,7 @@ var ALL_CAPABILITY_DEFINITIONS = [
|
|
|
105263
106063
|
osdCapability,
|
|
105264
106064
|
osdManagerCapability,
|
|
105265
106065
|
petFeederCapability,
|
|
106066
|
+
petFountainCapability,
|
|
105266
106067
|
pipelineAnalyticsCapability,
|
|
105267
106068
|
pipelineExecutorCapability,
|
|
105268
106069
|
pipelineOrchestratorCapability,
|
|
@@ -106841,6 +107642,36 @@ var METHOD_DEVICE_SELECTORS = Object.freeze({
|
|
|
106841
107642
|
form: "single",
|
|
106842
107643
|
optional: false
|
|
106843
107644
|
}],
|
|
107645
|
+
"petFountain.getStatus": [{
|
|
107646
|
+
name: "deviceId",
|
|
107647
|
+
form: "single",
|
|
107648
|
+
optional: false
|
|
107649
|
+
}],
|
|
107650
|
+
"petFountain.resetDailyConsumption": [{
|
|
107651
|
+
name: "deviceId",
|
|
107652
|
+
form: "single",
|
|
107653
|
+
optional: false
|
|
107654
|
+
}],
|
|
107655
|
+
"petFountain.setPump": [{
|
|
107656
|
+
name: "deviceId",
|
|
107657
|
+
form: "single",
|
|
107658
|
+
optional: false
|
|
107659
|
+
}],
|
|
107660
|
+
"petFountain.setPumpInterval": [{
|
|
107661
|
+
name: "deviceId",
|
|
107662
|
+
form: "single",
|
|
107663
|
+
optional: false
|
|
107664
|
+
}],
|
|
107665
|
+
"petFountain.setPumpOffMinutes": [{
|
|
107666
|
+
name: "deviceId",
|
|
107667
|
+
form: "single",
|
|
107668
|
+
optional: false
|
|
107669
|
+
}],
|
|
107670
|
+
"petFountain.setPumpOnMinutes": [{
|
|
107671
|
+
name: "deviceId",
|
|
107672
|
+
form: "single",
|
|
107673
|
+
optional: false
|
|
107674
|
+
}],
|
|
106844
107675
|
"pipelineAnalytics.addRetrainFrameFromRecording": [{
|
|
106845
107676
|
name: "deviceId",
|
|
106846
107677
|
form: "single",
|
|
@@ -108398,7 +109229,7 @@ function getCapsByProviderKind(kind) {
|
|
|
108398
109229
|
//#region src/generated/runtime-state-durability.ts
|
|
108399
109230
|
/**
|
|
108400
109231
|
* Per-cap runtime-state policy, projected from every `*.cap.ts` that declares
|
|
108401
|
-
* `runtimeState`.
|
|
109232
|
+
* `runtimeState`. 77 caps: 39 `restored`, 38 `session`.
|
|
108402
109233
|
*
|
|
108403
109234
|
* A cap absent from this map has no runtime-state slice at all. A cap PRESENT
|
|
108404
109235
|
* with `durability: 'session'` has one and has decided not to keep it.
|
|
@@ -108604,6 +109435,10 @@ var RUNTIME_STATE_POLICY = {
|
|
|
108604
109435
|
durability: "session",
|
|
108605
109436
|
volatileFields: []
|
|
108606
109437
|
},
|
|
109438
|
+
"pet-fountain": {
|
|
109439
|
+
durability: "session",
|
|
109440
|
+
volatileFields: []
|
|
109441
|
+
},
|
|
108607
109442
|
"power-meter": {
|
|
108608
109443
|
durability: "restored",
|
|
108609
109444
|
volatileFields: ["lastFetchedAt"]
|
|
@@ -109591,7 +110426,11 @@ function createSystemProxy(api) {
|
|
|
109591
110426
|
listSupportedDeviceKinds: (input) => dispatch("deviceExport", "listSupportedDeviceKinds", "query", input),
|
|
109592
110427
|
listExposedDevices: (input) => dispatch("deviceExport", "listExposedDevices", "query", input),
|
|
109593
110428
|
exposeDevice: (input) => dispatch("deviceExport", "exposeDevice", "mutation", input),
|
|
109594
|
-
unexposeDevice: (input) => dispatch("deviceExport", "unexposeDevice", "mutation", input)
|
|
110429
|
+
unexposeDevice: (input) => dispatch("deviceExport", "unexposeDevice", "mutation", input),
|
|
110430
|
+
listSupportedEntityKinds: (input) => dispatch("deviceExport", "listSupportedEntityKinds", "query", input),
|
|
110431
|
+
listExposedEntities: (input) => dispatch("deviceExport", "listExposedEntities", "query", input),
|
|
110432
|
+
exposeEntity: (input) => dispatch("deviceExport", "exposeEntity", "mutation", input),
|
|
110433
|
+
unexposeEntity: (input) => dispatch("deviceExport", "unexposeEntity", "mutation", input)
|
|
109595
110434
|
},
|
|
109596
110435
|
deviceHistory: {
|
|
109597
110436
|
listNodeSeries: (input) => dispatch("deviceHistory", "listNodeSeries", "query", input),
|
|
@@ -110041,7 +110880,9 @@ function createSystemProxy(api) {
|
|
|
110041
110880
|
checkServerUpdate: (input) => dispatch("serverManagement", "checkServerUpdate", "mutation", input),
|
|
110042
110881
|
applyServerUpdate: (input) => dispatch("serverManagement", "applyServerUpdate", "mutation", input),
|
|
110043
110882
|
rollbackServerUpdate: (input) => dispatch("serverManagement", "rollbackServerUpdate", "mutation", input),
|
|
110044
|
-
restartServer: (input) => dispatch("serverManagement", "restartServer", "mutation", input)
|
|
110883
|
+
restartServer: (input) => dispatch("serverManagement", "restartServer", "mutation", input),
|
|
110884
|
+
getLaunchOverrides: (input) => dispatch("serverManagement", "getLaunchOverrides", "query", input),
|
|
110885
|
+
setLaunchOverrides: (input) => dispatch("serverManagement", "setLaunchOverrides", "mutation", input)
|
|
110045
110886
|
},
|
|
110046
110887
|
settingsStore: {
|
|
110047
110888
|
get: (input) => dispatch("settingsStore", "get", "query", input),
|
|
@@ -121014,7 +121855,7 @@ exports.AddBrokerInputSchema = AddBrokerInputSchema;
|
|
|
121014
121855
|
exports.AddRetrainFrameFromRecordingResultSchema = AddRetrainFrameFromRecordingResultSchema;
|
|
121015
121856
|
exports.AddonAutoUpdateSchema = AddonAutoUpdateSchema;
|
|
121016
121857
|
exports.AddonListItemSchema = AddonListItemSchema;
|
|
121017
|
-
exports.AddonPageDeclarationSchema = AddonPageDeclarationSchema;
|
|
121858
|
+
exports.AddonPageDeclarationSchema = require_sleep.AddonPageDeclarationSchema;
|
|
121018
121859
|
exports.AddonPageInfoSchema = AddonPageInfoSchema;
|
|
121019
121860
|
exports.AddonRoutesScopeSchema = AddonRoutesScopeSchema;
|
|
121020
121861
|
exports.AdminLinkTargetEnum = AdminLinkTargetEnum;
|
|
@@ -121345,6 +122186,7 @@ exports.CompositionFieldSourceSchema = require_composition.CompositionFieldSourc
|
|
|
121345
122186
|
exports.CompositionFieldStateKindSchema = CompositionFieldStateKindSchema;
|
|
121346
122187
|
exports.CompositionFieldStateSchema = CompositionFieldStateSchema;
|
|
121347
122188
|
exports.CompositionFieldsFeatureSchema = require_composition.CompositionFieldsFeatureSchema;
|
|
122189
|
+
exports.CompositionForwardArgSchema = require_composition.CompositionForwardArgSchema;
|
|
121348
122190
|
exports.CompositionForwardCommandSchema = require_composition.CompositionForwardCommandSchema;
|
|
121349
122191
|
exports.CompositionFromSourceSchema = require_composition.CompositionFromSourceSchema;
|
|
121350
122192
|
exports.CompositionGetReadSchema = CompositionGetReadSchema;
|
|
@@ -121471,6 +122313,7 @@ exports.DEVICE_HISTORY_ENERGY_KEY = DEVICE_HISTORY_ENERGY_KEY;
|
|
|
121471
122313
|
exports.DEVICE_HISTORY_ORPHAN_DELETE_MAX = DEVICE_HISTORY_ORPHAN_DELETE_MAX;
|
|
121472
122314
|
exports.DEVICE_HISTORY_ORPHAN_LIST_MAX = DEVICE_HISTORY_ORPHAN_LIST_MAX;
|
|
121473
122315
|
exports.DEVICE_HISTORY_QUERY_MANY_MAX_ITEMS = DEVICE_HISTORY_QUERY_MANY_MAX_ITEMS;
|
|
122316
|
+
exports.DEVICE_ID_FIELD = DEVICE_ID_FIELD;
|
|
121474
122317
|
exports.DEVICE_NONCE_TTL_MS = DEVICE_NONCE_TTL_MS;
|
|
121475
122318
|
exports.DEVICE_PROFILES = DEVICE_PROFILES;
|
|
121476
122319
|
exports.DEVICE_RAMP = DEVICE_RAMP;
|
|
@@ -121653,6 +122496,8 @@ exports.ExportClipSubjectSchema = ExportClipSubjectSchema;
|
|
|
121653
122496
|
exports.ExportDenseRangeSchema = ExportDenseRangeSchema;
|
|
121654
122497
|
exports.ExportDenseSchema = ExportDenseSchema;
|
|
121655
122498
|
exports.ExportDownloadSchema = ExportDownloadSchema;
|
|
122499
|
+
exports.ExportEntityKindSchema = ExportEntityKindSchema;
|
|
122500
|
+
exports.ExportEntityRefSchema = ExportEntityRefSchema;
|
|
121656
122501
|
exports.ExportFootageSubjectSchema = ExportFootageSubjectSchema;
|
|
121657
122502
|
exports.ExportOptionsSchema = ExportOptionsSchema;
|
|
121658
122503
|
exports.ExportRecordSchema = ExportRecordSchema;
|
|
@@ -121662,7 +122507,9 @@ exports.ExportSpeedSchema = ExportSpeedSchema;
|
|
|
121662
122507
|
exports.ExportStateSchema = ExportStateSchema;
|
|
121663
122508
|
exports.ExportSubjectSchema = ExportSubjectSchema;
|
|
121664
122509
|
exports.ExportTimelapseSchema = ExportTimelapseSchema;
|
|
122510
|
+
exports.ExposeEntityInputSchema = ExposeEntityInputSchema;
|
|
121665
122511
|
exports.ExposedDeviceSchema = ExposedDeviceSchema;
|
|
122512
|
+
exports.ExposedEntitySchema = ExposedEntitySchema;
|
|
121666
122513
|
exports.ExposureModeSchema = ExposureModeSchema;
|
|
121667
122514
|
exports.ExpressionBindingSourceSchema = ExpressionBindingSourceSchema;
|
|
121668
122515
|
exports.ExpressionEvalError = require_composition.ExpressionEvalError;
|
|
@@ -121698,6 +122545,7 @@ exports.FEEDER_EXAMPLE_ADDON_ID = FEEDER_EXAMPLE_ADDON_ID;
|
|
|
121698
122545
|
exports.FEEDER_EXAMPLE_HA_DEVICE_ID = FEEDER_EXAMPLE_HA_DEVICE_ID;
|
|
121699
122546
|
exports.FFMPEG_PATH_ENV = require_composition.FFMPEG_PATH_ENV;
|
|
121700
122547
|
exports.FIRST_LEVEL_MACRO_CLASSES = FIRST_LEVEL_MACRO_CLASSES;
|
|
122548
|
+
exports.FORWARD_INPUT_KEY = require_composition.FORWARD_INPUT_KEY;
|
|
121701
122549
|
exports.FULL_IMAGE_BBOX = FULL_IMAGE_BBOX;
|
|
121702
122550
|
exports.FailureContributionSchema = FailureContributionSchema;
|
|
121703
122551
|
exports.FailureCounters = FailureCounters;
|
|
@@ -122410,6 +123258,7 @@ exports.PcmSampleFormatSchema = PcmSampleFormatSchema;
|
|
|
122410
123258
|
exports.PeerBytesTicketSchema = require_sleep.PeerBytesTicketSchema;
|
|
122411
123259
|
exports.PerScopeBreakdownSchema = PerScopeBreakdownSchema;
|
|
122412
123260
|
exports.PetFeederStatusSchema = PetFeederStatusSchema;
|
|
123261
|
+
exports.PetFountainStatusSchema = PetFountainStatusSchema;
|
|
122413
123262
|
exports.PickStreamPreferencesSchema = PickStreamPreferencesSchema;
|
|
122414
123263
|
exports.PickStreamRequirementsSchema = PickStreamRequirementsSchema;
|
|
122415
123264
|
exports.PickedCamStreamSchema = PickedCamStreamSchema;
|
|
@@ -122417,8 +123266,8 @@ exports.PipelineAssignmentSchema = PipelineAssignmentSchema;
|
|
|
122417
123266
|
exports.PipelineDefaultStepSchema = PipelineDefaultStepSchema;
|
|
122418
123267
|
exports.PipelineEngineChoiceSchema = PipelineEngineChoiceSchema;
|
|
122419
123268
|
exports.PipelineModelFormatStatusSchema = PipelineModelFormatStatusSchema;
|
|
122420
|
-
exports.PipelineRunResultBridge = PipelineRunResultBridge;
|
|
122421
|
-
exports.PipelineStepInputSchema = PipelineStepInputSchema;
|
|
123269
|
+
exports.PipelineRunResultBridge = require_sleep.PipelineRunResultBridge;
|
|
123270
|
+
exports.PipelineStepInputSchema = require_sleep.PipelineStepInputSchema;
|
|
122422
123271
|
exports.PipelineValidationIssueSchema = PipelineValidationIssueSchema;
|
|
122423
123272
|
exports.PipelineValidationResultSchema = PipelineValidationResultSchema;
|
|
122424
123273
|
exports.PlaceholderReasonSchema = PlaceholderReasonSchema;
|
|
@@ -123007,6 +123856,7 @@ exports.UNIT_TABLE = UNIT_TABLE;
|
|
|
123007
123856
|
exports.UNLOCK_CONFIRMATION = UNLOCK_CONFIRMATION;
|
|
123008
123857
|
exports.USE_ROOT_MODEL_DEFAULTS = USE_ROOT_MODEL_DEFAULTS;
|
|
123009
123858
|
exports.USE_ROOT_MODEL_SETTING_KEY = USE_ROOT_MODEL_SETTING_KEY;
|
|
123859
|
+
exports.UnexposeEntityInputSchema = UnexposeEntityInputSchema;
|
|
123010
123860
|
exports.UnifiedBrokerInfoSchema = BrokerInfoSchema;
|
|
123011
123861
|
exports.UnindexedFilterError = require_sleep.UnindexedFilterError;
|
|
123012
123862
|
exports.UninstallNodeOutcomeSchema = UninstallNodeOutcomeSchema;
|
|
@@ -123111,7 +123961,7 @@ exports.actuatorMethodRow = actuatorMethodRow;
|
|
|
123111
123961
|
exports.addonCatalogHref = addonCatalogHref;
|
|
123112
123962
|
exports.addonIdOfActionId = addonIdOfActionId;
|
|
123113
123963
|
exports.addonPagesCapability = addonPagesCapability;
|
|
123114
|
-
exports.addonPagesSourceCapability = addonPagesSourceCapability;
|
|
123964
|
+
exports.addonPagesSourceCapability = require_sleep.addonPagesSourceCapability;
|
|
123115
123965
|
exports.addonRoutesCapability = addonRoutesCapability;
|
|
123116
123966
|
exports.addonSettingsCapability = addonSettingsCapability;
|
|
123117
123967
|
exports.addonWidgetsCapability = addonWidgetsCapability;
|
|
@@ -123267,6 +124117,8 @@ exports.collectSecretMarkerRefs = require_sleep.collectSecretMarkerRefs;
|
|
|
123267
124117
|
exports.collectZodSecretPaths = require_sleep.collectZodSecretPaths;
|
|
123268
124118
|
exports.colorCapability = colorCapability;
|
|
123269
124119
|
exports.colorForKind = colorForKind;
|
|
124120
|
+
exports.commandMethodProblems = commandMethodProblems;
|
|
124121
|
+
exports.commandedMethods = commandedMethods;
|
|
123270
124122
|
exports.commitWatchdogRestart = commitWatchdogRestart;
|
|
123271
124123
|
exports.compareToTarget = compareToTarget;
|
|
123272
124124
|
exports.compileExpression = require_composition.compileExpression;
|
|
@@ -123480,6 +124332,7 @@ exports.failureRate = failureRate;
|
|
|
123480
124332
|
exports.fanControlCapability = fanControlCapability;
|
|
123481
124333
|
exports.fanOutTargets = fanOutTargets;
|
|
123482
124334
|
exports.featureFieldEntries = require_composition.featureFieldEntries;
|
|
124335
|
+
exports.featureForwards = featureForwards;
|
|
123483
124336
|
exports.featureOfRole = featureOfRole;
|
|
123484
124337
|
exports.featureProbeCapability = featureProbeCapability;
|
|
123485
124338
|
exports.featureSources = require_composition.featureSources;
|
|
@@ -123507,6 +124360,9 @@ exports.formatParkedFor = formatParkedFor;
|
|
|
123507
124360
|
exports.formatReading = formatReading;
|
|
123508
124361
|
exports.formatSecretScope = require_sleep.formatSecretScope;
|
|
123509
124362
|
exports.formulaProblem = formulaProblem;
|
|
124363
|
+
exports.forwardProblems = forwardProblems;
|
|
124364
|
+
exports.forwardSourceProblems = forwardSourceProblems;
|
|
124365
|
+
exports.forwardSourceRefs = forwardSourceRefs;
|
|
123510
124366
|
exports.freshResults = freshResults;
|
|
123511
124367
|
exports.fuseRecoveredDetections = fuseRecoveredDetections;
|
|
123512
124368
|
exports.gasCapability = gasCapability;
|
|
@@ -123597,6 +124453,7 @@ exports.isEvent = require_sleep.isEvent;
|
|
|
123597
124453
|
exports.isEventKindLabelKey = isEventKindLabelKey;
|
|
123598
124454
|
exports.isEventOwnerType = isEventOwnerType;
|
|
123599
124455
|
exports.isFirstLevelMacroClass = isFirstLevelMacroClass;
|
|
124456
|
+
exports.isForwardInputRef = require_composition.isForwardInputRef;
|
|
123600
124457
|
exports.isHeldBackTemplateVar = isHeldBackTemplateVar;
|
|
123601
124458
|
exports.isHistoryHelper = require_composition.isHistoryHelper;
|
|
123602
124459
|
exports.isIconKey = isIconKey;
|
|
@@ -123812,6 +124669,8 @@ exports.parseStreamParamsFormPatch = parseStreamParamsFormPatch;
|
|
|
123812
124669
|
exports.parseTrainingEventLine = parseTrainingEventLine;
|
|
123813
124670
|
exports.patchAudio = patchAudio;
|
|
123814
124671
|
exports.petFeederCapability = petFeederCapability;
|
|
124672
|
+
exports.petFountainCapability = petFountainCapability;
|
|
124673
|
+
exports.petFountainFromEntitiesComposition = petFountainFromEntitiesComposition;
|
|
123815
124674
|
exports.pickAccessoryControl = pickAccessoryControl;
|
|
123816
124675
|
exports.pickAppLinkHub = pickAppLinkHub;
|
|
123817
124676
|
exports.pickClusterStepModels = pickClusterStepModels;
|
|
@@ -123860,6 +124719,7 @@ exports.projectScalarAssignment = projectScalarAssignment;
|
|
|
123860
124719
|
exports.projectSpanAssignment = projectSpanAssignment;
|
|
123861
124720
|
exports.projectSubjectPath = projectSubjectPath;
|
|
123862
124721
|
exports.providerMotionEvent = providerMotionEvent;
|
|
124722
|
+
exports.pruneDeletedEntities = pruneDeletedEntities;
|
|
123863
124723
|
exports.ptzAutotrackCapability = ptzAutotrackCapability;
|
|
123864
124724
|
exports.ptzCapability = ptzCapability;
|
|
123865
124725
|
exports.publicEventCategories = require_event_category.publicEventCategories;
|
|
@@ -123989,6 +124849,7 @@ exports.ruleSection = ruleSection;
|
|
|
123989
124849
|
exports.ruleSectionOf = ruleSectionOf;
|
|
123990
124850
|
exports.ruleSeedForSection = ruleSeedForSection;
|
|
123991
124851
|
exports.ruleTriggerZoneIds = ruleTriggerZoneIds;
|
|
124852
|
+
exports.runExportedAction = runExportedAction;
|
|
123992
124853
|
exports.runFanOut = runFanOut;
|
|
123993
124854
|
exports.runInferenceStep = runInferenceStep;
|
|
123994
124855
|
exports.runSteps = runSteps;
|
|
@@ -124027,6 +124888,7 @@ exports.selectAssignedProfileSlots = require_sleep.selectAssignedProfileSlots;
|
|
|
124027
124888
|
exports.selectRecoveryStep = selectRecoveryStep;
|
|
124028
124889
|
exports.sendTimesForEditor = sendTimesForEditor;
|
|
124029
124890
|
exports.sendTimesOfSchedule = sendTimesOfSchedule;
|
|
124891
|
+
exports.sendToExportedTarget = sendToExportedTarget;
|
|
124030
124892
|
exports.sensorRaisedOf = sensorRaisedOf;
|
|
124031
124893
|
exports.sensorTransitionNeverFires = sensorTransitionNeverFires;
|
|
124032
124894
|
exports.sensorTransitionOffered = sensorTransitionOffered;
|