@camstack/addon-admin-ui 1.2.515 → 1.2.517
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 +17 -0
- package/dist/assets/{AddonAssetIcon-CBiyVWSK.js → AddonAssetIcon-DaAStKC8.js} +1 -1
- package/dist/assets/Addons-Do9U7LcM.js +5 -0
- package/dist/assets/{AdminPage-B_wUVHLs.js → AdminPage-CgFhd3My.js} +1 -1
- package/dist/assets/{AdminSectionedPage-bjMTXExV.js → AdminSectionedPage-C9702pKD.js} +1 -1
- package/dist/assets/AiProfiles-CZMD4KM-.js +3 -0
- package/dist/assets/{BrokerEditorDialog-DPVRE7-s.js → BrokerEditorDialog-BCtpOmtb.js} +1 -1
- package/dist/assets/Build-BgRIdgDr.js +40 -0
- package/dist/assets/{Calendars-wYE1IQBj.js → Calendars-CvhWz72R.js} +1 -1
- package/dist/assets/Cluster-GaxjV7h4.js +1 -0
- package/dist/assets/{ComposedDeviceEditDialog-CymtiQhN.js → ComposedDeviceEditDialog-B1R5Dm6Q.js} +1 -1
- package/dist/assets/CompositionBlockEditor-CKIEoswd.js +2 -0
- package/dist/assets/{CompositionEditorPage-Bp0gwdfh.js → CompositionEditorPage-CZQd9oj4.js} +1 -1
- package/dist/assets/{Data-Cgf6SD1c.js → Data-CZij0oVZ.js} +2 -2
- package/dist/assets/DeviceDetail-DIqK-Pxm.js +2 -0
- package/dist/assets/{DeviceDoActionFields-BKIcUinN.js → DeviceDoActionFields-DAsmzytT.js} +1 -1
- package/dist/assets/{Devices-DtwfpOJe.js → Devices-60E3KVab.js} +1 -1
- package/dist/assets/{EmbedPlayerPage-C0JL6O13.js → EmbedPlayerPage-BCjssXwM.js} +1 -1
- package/dist/assets/{History-0nvSdtVT.js → History-QHsS9OSz.js} +1 -1
- package/dist/assets/{Identity-B9Ly0pEQ.js → Identity-Ck9bdqfT.js} +1 -1
- package/dist/assets/IntegrationDetail-Cggj8UuG.js +1 -0
- package/dist/assets/{IntegrationHub-BdTFw8jM.js → IntegrationHub-YFOb5Q5f.js} +1 -1
- package/dist/assets/{Integrations-DuajWOh1.js → Integrations-CAGCgM4m.js} +1 -1
- package/dist/assets/Integrations-CM_r2esc.js +1 -0
- package/dist/assets/Library-CDBh4UY7.js +1 -0
- package/dist/assets/{Locations-DbGCMvY_.js → Locations-C5J-xGpv.js} +2 -2
- package/dist/assets/{Logs-BsejI0N_.js → Logs-BzR8S8Az.js} +1 -1
- package/dist/assets/{MaskShapeCanvas-CCcjwlTm.js → MaskShapeCanvas-v1VFSWGn.js} +1 -1
- package/dist/assets/{MotionZonesSettings-15VWTACI.js → MotionZonesSettings-sNv6UeyN.js} +1 -1
- package/dist/assets/{MyAccess-BybIWHCc.js → MyAccess-d7f5aurQ.js} +1 -1
- package/dist/assets/{Network-DDhjZ0n2.js → Network-D5kLXsF4.js} +1 -1
- package/dist/assets/{NodeAddonsSettingsPanel-Cj9J3VCz.js → NodeAddonsSettingsPanel-Dul-TVez.js} +1 -1
- package/dist/assets/Notifications-BCXKW0H1.js +1 -0
- package/dist/assets/Pipeline-DQ0gg-q3.js +1 -0
- package/dist/assets/{PrivacyMaskSettings-boU8xnXR.js → PrivacyMaskSettings-BOFfKtZS.js} +1 -1
- package/dist/assets/{Recordings-BgaF6LHi.js → Recordings-CSEh6SKS.js} +1 -1
- package/dist/assets/{RemoteGrid-HppYsb5t.js → RemoteGrid-DwD_77yd.js} +1 -1
- package/dist/assets/{ScanNetworkModal-C44T3xR0.js → ScanNetworkModal-DfCSNZP7.js} +1 -1
- package/dist/assets/{SceneMonitorEditor-DbEDdw8n.js → SceneMonitorEditor-CYSd3nvA.js} +1 -1
- package/dist/assets/{SessionsList-DyX_VF8l.js → SessionsList-e-yTK3Ce.js} +2 -2
- package/dist/assets/{Showroom-B5qRvr4H.js → Showroom-BW0s66nO.js} +1 -1
- package/dist/assets/{System-DlY0oaGn.js → System-lEmnBarz.js} +1 -1
- package/dist/assets/{Templates-lCo5yN4g.js → Templates-oi3TGvJ_.js} +1 -1
- package/dist/assets/{Terminal-qRe7fRtd.js → Terminal-DSohGtV9.js} +2 -2
- package/dist/assets/{Viewer-BFtLOgb5.js → Viewer-B6FpTku6.js} +1 -1
- package/dist/assets/{__vite-browser-external-BlMfPwfH.js → __vite-browser-external-BCAtXlNQ.js} +1 -1
- package/dist/assets/{_virtual_mf-localSharedImportMap___mfe_internal__admin_ui_host-Dd1lnVnV.js → _virtual_mf-localSharedImportMap___mfe_internal__admin_ui_host-DqPNLVRX.js} +1 -1
- package/dist/assets/{addon-icons-context-BqCF3aDM.js → addon-icons-context-BAMZN6v3.js} +1 -1
- package/dist/assets/{archive-COJvuz8j.js → archive-CQSA3no9.js} +1 -1
- package/dist/assets/{assignment-candidates-WjzzD3xR.js → assignment-candidates-CX47iOH5.js} +1 -1
- package/dist/assets/{authed-media-CPH4gDSb.js → authed-media-Bk6ZG2lV.js} +1 -1
- package/dist/assets/{bell-off-CEHvcpV8.js → bell-off-ByVFjmad.js} +1 -1
- package/dist/assets/{board-model-BkMxMFGJ.js → board-model-Cij0wyiz.js} +1 -1
- package/dist/assets/{boxes-C0Z7cB0S.js → boxes-B8shBGyA.js} +1 -1
- package/dist/assets/circle-slash-CYJP5692.js +1 -0
- package/dist/assets/client-B3Uh4h4a.js +674 -0
- package/dist/assets/{cloud-upload-yzPIJtWW.js → cloud-upload-knnOuFf0.js} +1 -1
- package/dist/assets/crop-CO-cCOHc.js +1 -0
- package/dist/assets/{device-integration-icon-Bo_gTwOD.js → device-integration-icon-CXZW9un_.js} +1 -1
- package/dist/assets/device-picker-model-CLwbjCLX.js +1 -0
- package/dist/assets/dist-2sWhwHC7.js +674 -0
- package/dist/assets/{dist-D7eSjbBx.js → dist-DWGbpqHP.js} +1 -1
- package/dist/assets/{file-up-gEH5fPam.js → file-up-DsJKDfNx.js} +1 -1
- package/dist/assets/{hard-drive-download-CwO_DU-K.js → hard-drive-download-3fltBasv.js} +1 -1
- package/dist/assets/{hostInit-BonUhoQT.js → hostInit-Djg3zVjo.js} +1 -1
- package/dist/assets/i18n-qDGVD_PF.js +1 -0
- package/dist/assets/icons-yMzKblPs.js +1 -0
- package/dist/assets/{index-i7JLUpAu.css → index-DrGgMc78.css} +1 -1
- package/dist/assets/index-Dvd8RKBK.js +4 -0
- package/dist/assets/{key-03tb4am1.js → key-DCYw0FNE.js} +1 -1
- package/dist/assets/{key-round-CxRbUD09.js → key-round-CTD-QhVl.js} +1 -1
- package/dist/assets/{layers-B_aq5GyC.js → layers-7Ihtoyz5.js} +1 -1
- package/dist/assets/{linked-devices-model-DO7_gXoE.js → linked-devices-model-n5gH_HKu.js} +1 -1
- package/dist/assets/{list-ordered-BIOnBH5V.js → list-ordered-oYfsQM3w.js} +1 -1
- package/dist/assets/location-owned-usage-CT1Figq_.js +1 -0
- package/dist/assets/{log-in-DYRRiyUu.js → log-in-BzAjDKMU.js} +1 -1
- package/dist/assets/{memory-stick-BTjX5XXU.js → memory-stick-XgJPnz3h.js} +1 -1
- package/dist/assets/{message-square-plus-CYHn2tx1.js → message-square-plus-DObXI5UO.js} +1 -1
- package/dist/assets/{mf-entry-bootstrap-0-2f0f55bc.js → mf-entry-bootstrap-0-8ecb92b3.js} +2 -2
- package/dist/assets/{mic-off-BfWqJn2R.js → mic-off-CFZpIFfk.js} +1 -1
- package/dist/assets/{monitor-off-Dy7WsqTN.js → monitor-off-610T_Gdj.js} +1 -1
- package/dist/assets/{monitor-smartphone-Cl-w7Gs0.js → monitor-smartphone-Dn0zJRqy.js} +1 -1
- package/dist/assets/mount-CLwbjCLX.js +1 -0
- package/dist/assets/player-overlays-CJHEGkWA.js +1 -0
- package/dist/assets/{recycle-CC6kU24N.js → recycle-BDhcl0YV.js} +1 -1
- package/dist/assets/remoteEntry-BkNPWH4W.js +1 -0
- package/dist/assets/{ruler-C6bIqLbX.js → ruler-DRBBjPda.js} +1 -1
- package/dist/assets/{scan-eye-BbYgoJiK.js → scan-eye-Cq1A21Jj.js} +1 -1
- package/dist/assets/{scissors-oYo-ZhBm.js → scissors-_YyUi2Wc.js} +1 -1
- package/dist/assets/{search-x-CySi2ygd.js → search-x-0cpMKp48.js} +1 -1
- package/dist/assets/{send-FMXSDirA.js → send-BPU5cRG9.js} +1 -1
- package/dist/assets/{settings-2-WfXnibr2.js → settings-2-L8TMaIKQ.js} +1 -1
- package/dist/assets/{shapes-JaoPTvAm.js → shapes-DJVtgjGZ.js} +1 -1
- package/dist/assets/{sigma-C2um2nX9.js → sigma-DPXOWC0b.js} +1 -1
- package/dist/assets/{speaker-DVh7yO4_.js → speaker-CokRNflr.js} +1 -1
- package/dist/assets/src-CzDAA2fz.js +67 -0
- package/dist/assets/{step-inspector-model-Xr3EG73i.js → step-inspector-model-8FwvV-vd.js} +1 -1
- package/dist/assets/{table-2-BzvZ1C8Y.js → table-2-DBJuUbJh.js} +1 -1
- package/dist/assets/{timer-reset-BFyZoIS7.js → timer-reset-D9k5wmF9.js} +1 -1
- package/dist/assets/{unlink-Bf6pcFmm.js → unlink-Bs2RzKEu.js} +1 -1
- package/dist/assets/{usb-oSHxCOV9.js → usb-BjhR3doW.js} +1 -1
- package/dist/assets/{use-scenes-feed-DrR6sBRO.js → use-scenes-feed-CT1HkH56.js} +1 -1
- package/dist/assets/{use-stationary-objects-DVmg7h4R.js → use-stationary-objects-HuzwOvOv.js} +1 -1
- package/dist/assets/useEventInvalidation-CLwbjCLX.js +1 -0
- package/dist/assets/{useNodeUrlSelection-CikIoR0h.js → useNodeUrlSelection-B82QsLnx.js} +1 -1
- package/dist/assets/user-round-reErwwaE.js +1 -0
- package/dist/assets/{user-x-aU8InWh0.js → user-x-lD1eMNGr.js} +1 -1
- package/dist/assets/{variable-DwONvC9h.js → variable-f5kvdTkN.js} +1 -1
- package/dist/assets/{video-DOy8UceJ.js → video-DNdx4dbt.js} +1 -1
- package/dist/assets/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__admin_ui_host__remoteEntry-_hash_-DXQ8OkGD.js → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__admin_ui_host__remoteEntry-_hash_-BwnfAs-v.js} +2 -2
- package/dist/index.html +11 -11
- package/dist/server/addon.js +1282 -871
- package/package.json +1 -1
- package/dist/assets/Addons-BYYIoFw9.js +0 -5
- package/dist/assets/AiProfiles-Dp3jiABg.js +0 -3
- package/dist/assets/Build-C-tGTJ6v.js +0 -40
- package/dist/assets/Cluster-DaviTht0.js +0 -1
- package/dist/assets/CompositionBlockEditor-Bgk7i1Ug.js +0 -2
- package/dist/assets/DeviceDetail-B5bgKOno.js +0 -2
- package/dist/assets/IntegrationDetail-C7nPuXa_.js +0 -1
- package/dist/assets/Integrations-PJkA_opy.js +0 -1
- package/dist/assets/Library-fp_epw-B.js +0 -1
- package/dist/assets/Notifications-CxzR6VyG.js +0 -1
- package/dist/assets/Pipeline-DApdVNZ-.js +0 -1
- package/dist/assets/circle-slash-BY9zkWdJ.js +0 -1
- package/dist/assets/client-BjsFVjEa.js +0 -674
- package/dist/assets/crop-DpfML6TR.js +0 -1
- package/dist/assets/device-picker-model-C9XdDI0R.js +0 -1
- package/dist/assets/dist-DuYXDhcZ.js +0 -674
- package/dist/assets/eraser-CcAxRsoL.js +0 -1
- package/dist/assets/i18n-ZdV8UiYr.js +0 -1
- package/dist/assets/icons-l5aYjks5.js +0 -1
- package/dist/assets/index-CuSxNbC8.js +0 -4
- package/dist/assets/location-owned-usage-CYNROgPA.js +0 -1
- package/dist/assets/mount-C9XdDI0R.js +0 -1
- package/dist/assets/player-overlays-DaSesfVn.js +0 -1
- package/dist/assets/remoteEntry-C7WJfwvN.js +0 -1
- package/dist/assets/src-DxOL9qHw.js +0 -67
- package/dist/assets/useEventInvalidation-C9XdDI0R.js +0 -1
- package/dist/assets/user-round-BZHQXbgV.js +0 -1
package/dist/server/addon.js
CHANGED
|
@@ -5069,6 +5069,14 @@ function object(shape, params) {
|
|
|
5069
5069
|
...normalizeParams(params)
|
|
5070
5070
|
});
|
|
5071
5071
|
}
|
|
5072
|
+
function strictObject(shape, params) {
|
|
5073
|
+
return new ZodObject({
|
|
5074
|
+
type: "object",
|
|
5075
|
+
shape,
|
|
5076
|
+
catchall: never(),
|
|
5077
|
+
...normalizeParams(params)
|
|
5078
|
+
});
|
|
5079
|
+
}
|
|
5072
5080
|
function looseObject(shape, params) {
|
|
5073
5081
|
return new ZodObject({
|
|
5074
5082
|
type: "object",
|
|
@@ -5448,7 +5456,7 @@ var ZodIssueCode = {
|
|
|
5448
5456
|
var ZodFirstPartyTypeKind;
|
|
5449
5457
|
ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
|
|
5450
5458
|
//#endregion
|
|
5451
|
-
//#region ../types/dist/sleep-
|
|
5459
|
+
//#region ../types/dist/sleep-6eG9C8Xl.mjs
|
|
5452
5460
|
/**
|
|
5453
5461
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
5454
5462
|
* window to float samples (D455).
|
|
@@ -8424,6 +8432,52 @@ function optionalMethod(input, output, options) {
|
|
|
8424
8432
|
providerOptional: true
|
|
8425
8433
|
};
|
|
8426
8434
|
}
|
|
8435
|
+
/**
|
|
8436
|
+
* `addon-pages-source` — collection cap exposing per-provider raw page
|
|
8437
|
+
* declarations. Every addon that contributes a UI page registers a
|
|
8438
|
+
* provider here. The hub-side singleton aggregator (`addon-pages` cap,
|
|
8439
|
+
* see `addon-pages.cap.ts`) walks this collection, stamps versioned
|
|
8440
|
+
* `bundleUrl` values, and returns the enriched `AddonPageInfo[]` list
|
|
8441
|
+
* that admin-ui consumes.
|
|
8442
|
+
*
|
|
8443
|
+
* The split exists because the public listing has a different output
|
|
8444
|
+
* shape than the per-provider raw declarations, and we want both ends
|
|
8445
|
+
* to flow through codegen instead of relying on a hand-written wrapper.
|
|
8446
|
+
*/
|
|
8447
|
+
var AddonPageDeclarationSchema = object({
|
|
8448
|
+
id: string(),
|
|
8449
|
+
label: string(),
|
|
8450
|
+
icon: string(),
|
|
8451
|
+
path: string(),
|
|
8452
|
+
/**
|
|
8453
|
+
* Module Federation remote name — must match the `name` field on the
|
|
8454
|
+
* page addon's `federation()` plugin config. Used by admin-ui's
|
|
8455
|
+
* `<AddonPageLoader>` to call `loadRemote('<remoteName>/page')`.
|
|
8456
|
+
* Conventionally `addon_<id>_page` (snake_case; MF names cannot
|
|
8457
|
+
* contain hyphens).
|
|
8458
|
+
*/
|
|
8459
|
+
remoteName: string(),
|
|
8460
|
+
/**
|
|
8461
|
+
* Bundle filename inside the addon's `dist/` dir served at
|
|
8462
|
+
* `/api/addon-pages/<addonId>/<bundle>`. With Module Federation this
|
|
8463
|
+
* is always `'remoteEntry.js'`; the value is kept on the metadata so
|
|
8464
|
+
* the static-file route can compute an mtime-based cache-buster URL
|
|
8465
|
+
* without a separate filesystem stat.
|
|
8466
|
+
*/
|
|
8467
|
+
bundle: string(),
|
|
8468
|
+
/**
|
|
8469
|
+
* Sidebar section this page docks into. Well-known ids: `'detection'`,
|
|
8470
|
+
* `'cluster'`, `'administration'` — the page renders inside that group.
|
|
8471
|
+
* Any OTHER string creates (or joins) a custom section rendered after
|
|
8472
|
+
* the built-in groups; its label comes from `sectionLabel` (first
|
|
8473
|
+
* declaration wins), falling back to the id. Absent → the legacy
|
|
8474
|
+
* "Addon Pages" group.
|
|
8475
|
+
*/
|
|
8476
|
+
section: string().optional(),
|
|
8477
|
+
/** Display label for a CUSTOM `section` id (ignored for well-known ids). */
|
|
8478
|
+
sectionLabel: string().optional()
|
|
8479
|
+
});
|
|
8480
|
+
method(_void(), array(AddonPageDeclarationSchema).readonly(), { auth: "admin" });
|
|
8427
8481
|
var StaticDirOutputSchema$1 = object({ staticDir: string() });
|
|
8428
8482
|
var VersionOutputSchema$1 = object({ version: string() });
|
|
8429
8483
|
var adminUiCapability = {
|
|
@@ -8445,6 +8499,27 @@ var adminUiCapability = {
|
|
|
8445
8499
|
getVersion: method(_void(), VersionOutputSchema$1, { auth: "admin" })
|
|
8446
8500
|
}
|
|
8447
8501
|
};
|
|
8502
|
+
/**
|
|
8503
|
+
* The pipeline step-input shape and the run-result bridge, in a module that
|
|
8504
|
+
* imports nothing but zod and types.
|
|
8505
|
+
*
|
|
8506
|
+
* WHY A SEPARATE FILE (addon footprint, D28): both were declared in
|
|
8507
|
+
* `pipeline-executor.cap.ts`, whose import evaluates the whole executor schema
|
|
8508
|
+
* graph. An addon that only needs these two (the benchmark's `runPipelineTest`
|
|
8509
|
+
* action) paid ~130 MB of heap at load. `pipeline-executor.cap.ts` re-exports
|
|
8510
|
+
* them, so every existing import keeps working; addon server code takes them
|
|
8511
|
+
* from `@camstack/types/addon`.
|
|
8512
|
+
*/
|
|
8513
|
+
var PipelineStepInputSchema = lazy(() => object({
|
|
8514
|
+
addonId: string(),
|
|
8515
|
+
modelId: string().optional(),
|
|
8516
|
+
enabled: boolean().default(true),
|
|
8517
|
+
children: array(PipelineStepInputSchema).optional(),
|
|
8518
|
+
settings: record(string(), unknown()).optional(),
|
|
8519
|
+
jumpDeviceKey: string().optional()
|
|
8520
|
+
}));
|
|
8521
|
+
/** Typed bridge to the recursive `FrameResult` graph; validation is structural. */
|
|
8522
|
+
var PipelineRunResultBridge = custom();
|
|
8448
8523
|
var StaticDirOutputSchema = object({ staticDir: string() });
|
|
8449
8524
|
var VersionOutputSchema = object({ version: string() });
|
|
8450
8525
|
method(_void(), StaticDirOutputSchema, { auth: "admin" }), method(_void(), VersionOutputSchema, { auth: "admin" });
|
|
@@ -8629,6 +8704,7 @@ var CAP_NAMES = Object.freeze([
|
|
|
8629
8704
|
"network-link",
|
|
8630
8705
|
"network-quality",
|
|
8631
8706
|
"node-certificates",
|
|
8707
|
+
"node-removal-hook",
|
|
8632
8708
|
"nodes",
|
|
8633
8709
|
"notification-output",
|
|
8634
8710
|
"notification-rules",
|
|
@@ -8639,6 +8715,7 @@ var CAP_NAMES = Object.freeze([
|
|
|
8639
8715
|
"osd",
|
|
8640
8716
|
"osd-manager",
|
|
8641
8717
|
"pet-feeder",
|
|
8718
|
+
"pet-fountain",
|
|
8642
8719
|
"pipeline-analytics",
|
|
8643
8720
|
"pipeline-executor",
|
|
8644
8721
|
"pipeline-orchestrator",
|
|
@@ -9918,6 +9995,56 @@ Object.freeze({
|
|
|
9918
9995
|
"valueType": "number"
|
|
9919
9996
|
}
|
|
9920
9997
|
],
|
|
9998
|
+
"pet-fountain": [
|
|
9999
|
+
{
|
|
10000
|
+
"path": "waterLevel",
|
|
10001
|
+
"valueType": "number"
|
|
10002
|
+
},
|
|
10003
|
+
{
|
|
10004
|
+
"path": "waterVolume",
|
|
10005
|
+
"valueType": "number"
|
|
10006
|
+
},
|
|
10007
|
+
{
|
|
10008
|
+
"path": "empty",
|
|
10009
|
+
"valueType": "boolean"
|
|
10010
|
+
},
|
|
10011
|
+
{
|
|
10012
|
+
"path": "pumpRunning",
|
|
10013
|
+
"valueType": "boolean"
|
|
10014
|
+
},
|
|
10015
|
+
{
|
|
10016
|
+
"path": "pumpIntervalEnabled",
|
|
10017
|
+
"valueType": "boolean"
|
|
10018
|
+
},
|
|
10019
|
+
{
|
|
10020
|
+
"path": "pumpOnTime",
|
|
10021
|
+
"valueType": "number"
|
|
10022
|
+
},
|
|
10023
|
+
{
|
|
10024
|
+
"path": "pumpOffTime",
|
|
10025
|
+
"valueType": "number"
|
|
10026
|
+
},
|
|
10027
|
+
{
|
|
10028
|
+
"path": "lastDrink",
|
|
10029
|
+
"valueType": "number"
|
|
10030
|
+
},
|
|
10031
|
+
{
|
|
10032
|
+
"path": "currentHourDrink",
|
|
10033
|
+
"valueType": "number"
|
|
10034
|
+
},
|
|
10035
|
+
{
|
|
10036
|
+
"path": "last24hDrink",
|
|
10037
|
+
"valueType": "number"
|
|
10038
|
+
},
|
|
10039
|
+
{
|
|
10040
|
+
"path": "todayDrink",
|
|
10041
|
+
"valueType": "number"
|
|
10042
|
+
},
|
|
10043
|
+
{
|
|
10044
|
+
"path": "error",
|
|
10045
|
+
"valueType": "string"
|
|
10046
|
+
}
|
|
10047
|
+
],
|
|
9921
10048
|
"power-meter": [
|
|
9922
10049
|
{
|
|
9923
10050
|
"path": "power",
|
|
@@ -10455,7 +10582,7 @@ object({
|
|
|
10455
10582
|
params: record(string(), union([string(), number()])).optional()
|
|
10456
10583
|
});
|
|
10457
10584
|
//#endregion
|
|
10458
|
-
//#region ../types/dist/err-msg-
|
|
10585
|
+
//#region ../types/dist/err-msg-DWXWc0Di.mjs
|
|
10459
10586
|
var DeviceType = /* @__PURE__ */ function(DeviceType) {
|
|
10460
10587
|
DeviceType["Camera"] = "camera";
|
|
10461
10588
|
DeviceType["Hub"] = "hub";
|
|
@@ -10547,6 +10674,10 @@ var DeviceType = /* @__PURE__ */ function(DeviceType) {
|
|
|
10547
10674
|
* native PetKit (`nodepetkit` `FeederDevice`), reusable by other feeder
|
|
10548
10675
|
* integrations sharing the same food/desiccant/hopper surface. */
|
|
10549
10676
|
DeviceType["PetFeeder"] = "pet-feeder";
|
|
10677
|
+
/** Pet water fountain — tank level, water drunk, pump and its duty cycle.
|
|
10678
|
+
* Installed with the `pet-fountain` cap. Reaches CamStack as loose entities
|
|
10679
|
+
* of a container and is BUILT as a composed device (D967). */
|
|
10680
|
+
DeviceType["PetFountain"] = "pet-fountain";
|
|
10550
10681
|
/** Built-in dishwasher — program lifecycle, door / remote-start gates,
|
|
10551
10682
|
* salt and rinse-aid levels. Installed with the `dishwasher` cap.
|
|
10552
10683
|
* Sources: native Bosch Home Connect, reusable by similar integrations.
|
|
@@ -10807,7 +10938,7 @@ var DeviceRole = /* @__PURE__ */ function(DeviceRole) {
|
|
|
10807
10938
|
return DeviceRole;
|
|
10808
10939
|
}({});
|
|
10809
10940
|
//#endregion
|
|
10810
|
-
//#region ../types/dist/composition-
|
|
10941
|
+
//#region ../types/dist/composition-kSuOifuG.mjs
|
|
10811
10942
|
/**
|
|
10812
10943
|
* The ffmpeg build every CamStack node downloads, per platform and arch.
|
|
10813
10944
|
*
|
|
@@ -11892,12 +12023,28 @@ var CompositionFieldSourceSchema = discriminatedUnion("kind", [
|
|
|
11892
12023
|
])
|
|
11893
12024
|
})
|
|
11894
12025
|
]);
|
|
11895
|
-
var
|
|
12026
|
+
var forwardArgUnion = union([
|
|
12027
|
+
string(),
|
|
12028
|
+
number(),
|
|
12029
|
+
boolean(),
|
|
12030
|
+
strictObject({ ["$input"]: string().min(1) }),
|
|
12031
|
+
record(string().min(1), lazy(() => forwardArgUnion))
|
|
12032
|
+
]);
|
|
12033
|
+
var CompositionForwardArgSchema = forwardArgUnion;
|
|
12034
|
+
/**
|
|
12035
|
+
* `forward` (D659, amended by D967): one method of a BUILT capability is one
|
|
12036
|
+
* call of `cap.method` on `source`. Without `args` the built method's input
|
|
12037
|
+
* passes through minus `deviceId`; with `args` the template IS the source's
|
|
12038
|
+
* whole input. `deviceId` is always the source's own, never an argument.
|
|
12039
|
+
*/
|
|
12040
|
+
var CompositionForwardCommandSchema = object({
|
|
11896
12041
|
kind: literal("forward"),
|
|
11897
12042
|
source: CompositionSourceRefSchema,
|
|
11898
12043
|
cap: string().min(1),
|
|
11899
|
-
method: string().min(1)
|
|
11900
|
-
|
|
12044
|
+
method: string().min(1),
|
|
12045
|
+
args: record(string().min(1), CompositionForwardArgSchema).optional()
|
|
12046
|
+
});
|
|
12047
|
+
var CompositionCommandTargetSchema = discriminatedUnion("kind", [CompositionForwardCommandSchema, CompositionCodeSourceSchema]);
|
|
11901
12048
|
/** An item key inside an item-array cap (`consumables.items[<key>]`). */
|
|
11902
12049
|
var COMPOSITION_ITEM_KEY_RE = /^[a-z0-9][a-z0-9-]{0,47}$/;
|
|
11903
12050
|
/**
|
|
@@ -11907,7 +12054,13 @@ var COMPOSITION_ITEM_KEY_RE = /^[a-z0-9][a-z0-9-]{0,47}$/;
|
|
|
11907
12054
|
*/
|
|
11908
12055
|
var CompositionItemEntrySchema = object({
|
|
11909
12056
|
label: string().min(1).max(80),
|
|
11910
|
-
fields: record(string().min(1), CompositionFieldSourceSchema)
|
|
12057
|
+
fields: record(string().min(1), CompositionFieldSourceSchema),
|
|
12058
|
+
/**
|
|
12059
|
+
* What the cap's `reset` does for THIS item (consumables). Present = the item
|
|
12060
|
+
* is resettable and a `reset` call naming its key forwards here. The item key
|
|
12061
|
+
* selects the command, so it is never an argument: there is no pass-through.
|
|
12062
|
+
*/
|
|
12063
|
+
reset: CompositionForwardCommandSchema.optional()
|
|
11911
12064
|
});
|
|
11912
12065
|
var CompositionFeatureSchema = discriminatedUnion("kind", [object({
|
|
11913
12066
|
kind: literal("fields"),
|
|
@@ -11919,7 +12072,7 @@ var CompositionFeatureSchema = discriminatedUnion("kind", [object({
|
|
|
11919
12072
|
* owns the WHOLE array field: the composed value holds exactly these items.
|
|
11920
12073
|
*/
|
|
11921
12074
|
items: record(string().regex(COMPOSITION_ITEM_KEY_RE), CompositionItemEntrySchema).refine((items) => Object.keys(items).length <= 16, { message: `at most 16 items` }).optional(),
|
|
11922
|
-
/**
|
|
12075
|
+
/** Method name → what serves it. Only a BUILT capability takes commands (D967). */
|
|
11923
12076
|
commands: record(string().min(1), CompositionCommandTargetSchema).optional()
|
|
11924
12077
|
}), object({
|
|
11925
12078
|
kind: literal("passthrough"),
|
|
@@ -15859,179 +16012,554 @@ object({
|
|
|
15859
16012
|
lastError: string().nullable()
|
|
15860
16013
|
});
|
|
15861
16014
|
/**
|
|
15862
|
-
*
|
|
15863
|
-
* surface that admin-ui consumes through `useAddonPagesListPages()`.
|
|
16015
|
+
* notification-output — canonical, capability-gated notification delivery.
|
|
15864
16016
|
*
|
|
15865
|
-
*
|
|
15866
|
-
*
|
|
15867
|
-
*
|
|
15868
|
-
*
|
|
15869
|
-
*
|
|
16017
|
+
* Apprise-derived model (see
|
|
16018
|
+
* `docs/superpowers/specs/2026-07-03-notification-output-notifier-matrix.md`):
|
|
16019
|
+
* callers emit ONE canonical `Notification`; each provider declares a
|
|
16020
|
+
* per-kind capability descriptor (`TargetKind`), and the pure degrade
|
|
16021
|
+
* engine (`@camstack/types` `prepareNotification`) transcodes / degrades the
|
|
16022
|
+
* message to what the kind supports — callers never special-case a service.
|
|
15870
16023
|
*
|
|
15871
|
-
*
|
|
15872
|
-
*
|
|
15873
|
-
* provider
|
|
15874
|
-
*
|
|
15875
|
-
*
|
|
16024
|
+
* DESIGN DECISIONS (locked):
|
|
16025
|
+
* - Target CRUD lives on THIS cap (`upsertTarget` / `deleteTarget` /
|
|
16026
|
+
* `setTargetEnabled`), each provider persisting via the `settings-store`
|
|
16027
|
+
* cap. Rationale: the admin UI needs one uniform surface across the
|
|
16028
|
+
* notifiers addon AND the HA addon; the addon-`globalSettingsSchema`-array
|
|
16029
|
+
* alternative would fork the UI per addon and cannot host the
|
|
16030
|
+
* discovery→adopt flow.
|
|
16031
|
+
* - `listTargetKinds` / `listTargets` / `discoverTargets` return arrays →
|
|
16032
|
+
* the generated cap-mount auto-`concatCollection`-fans them across every
|
|
16033
|
+
* registered provider (notifiers addon + HA addon) so one catalog is
|
|
16034
|
+
* routable. `send` / `testTarget` / CRUD route to ONE provider by the
|
|
16035
|
+
* `addonId` the generated collection router extracts from the call input.
|
|
16036
|
+
* - `Attachment.bytes` is `Uint8Array`. Transport-safe: superjson (the tRPC
|
|
16037
|
+
* transformer) + UDS MsgPack both round-trip typed arrays — already used by
|
|
16038
|
+
* `storage` / `storage-provider` / `recording` caps over the same path. No
|
|
16039
|
+
* base64 fallback needed.
|
|
16040
|
+
*
|
|
16041
|
+
* TODO (deferred, closed-set change — separate decision): add
|
|
16042
|
+
* `providerKind: 'notify'` so notification providers surface on the unified
|
|
16043
|
+
* admin "Integrations" page.
|
|
15876
16044
|
*/
|
|
15877
|
-
var AddonPageDeclarationSchema$1 = object({
|
|
15878
|
-
id: string(),
|
|
15879
|
-
label: string(),
|
|
15880
|
-
icon: string(),
|
|
15881
|
-
path: string(),
|
|
15882
|
-
remoteName: string(),
|
|
15883
|
-
bundle: string(),
|
|
15884
|
-
section: string().optional(),
|
|
15885
|
-
sectionLabel: string().optional()
|
|
15886
|
-
});
|
|
15887
|
-
var AddonPageInfoSchema = object({
|
|
15888
|
-
addonId: string(),
|
|
15889
|
-
page: AddonPageDeclarationSchema$1,
|
|
15890
|
-
bundleUrl: string()
|
|
15891
|
-
});
|
|
15892
|
-
method(_void(), array(AddonPageInfoSchema).readonly());
|
|
15893
16045
|
/**
|
|
15894
|
-
*
|
|
15895
|
-
*
|
|
15896
|
-
|
|
15897
|
-
|
|
15898
|
-
|
|
15899
|
-
|
|
16046
|
+
* Zentik-derived typed-media enum — the superset across every kind. Each
|
|
16047
|
+
* adapter picks what it supports and the degrade engine filters the rest.
|
|
16048
|
+
*/
|
|
16049
|
+
var AttachmentMediaTypeSchema = _enum([
|
|
16050
|
+
"image",
|
|
16051
|
+
"video",
|
|
16052
|
+
"gif",
|
|
16053
|
+
"audio",
|
|
16054
|
+
"icon"
|
|
16055
|
+
]);
|
|
16056
|
+
/**
|
|
16057
|
+
* A single attachment. Exactly one of `url` (remote source, most adapters
|
|
16058
|
+
* prefer this) or `bytes` (inline source; required for Pushover-style
|
|
16059
|
+
* bytes-only kinds) MUST be present — the degrade engine expresses a
|
|
16060
|
+
* url→bytes fetch as a `needsFetch` directive the adapter executes.
|
|
16061
|
+
*/
|
|
16062
|
+
var AttachmentSchema = object({
|
|
16063
|
+
mediaType: AttachmentMediaTypeSchema,
|
|
16064
|
+
url: string().optional(),
|
|
16065
|
+
bytes: _instanceof(Uint8Array).optional(),
|
|
16066
|
+
mime: string().optional(),
|
|
16067
|
+
name: string().optional()
|
|
16068
|
+
}).refine((a) => a.url !== void 0 || a.bytes !== void 0, { message: "Attachment requires either `url` or `bytes`" });
|
|
16069
|
+
var NotificationFormatSchema = _enum([
|
|
16070
|
+
"text",
|
|
16071
|
+
"markdown",
|
|
16072
|
+
"html"
|
|
16073
|
+
]);
|
|
16074
|
+
/**
|
|
16075
|
+
* The CLOSED icon vocabulary an action button may use.
|
|
15900
16076
|
*
|
|
15901
|
-
*
|
|
15902
|
-
*
|
|
15903
|
-
*
|
|
16077
|
+
* A closed set, not a free string, and that is the whole point: an arbitrary
|
|
16078
|
+
* icon name is one that ntfy renders, zentik silently drops, and nobody
|
|
16079
|
+
* notices — the same class of gap as a zone vocabulary nothing produced
|
|
16080
|
+
* ([D35](../../../docs/decisions/adr-0035.md)). Every adapter maps this set or
|
|
16081
|
+
* declares `actionIcons: false` and the degrade engine strips the field.
|
|
16082
|
+
*
|
|
16083
|
+
* Named by INTENT, never by glyph. "check" would tie the vocabulary to one
|
|
16084
|
+
* renderer's icon set; "acknowledge" survives an adapter that draws it
|
|
16085
|
+
* differently.
|
|
16086
|
+
*
|
|
16087
|
+
* ── A TOKEN IS NOT A WIRE VALUE ─────────────────────────────────────
|
|
16088
|
+
*
|
|
16089
|
+
* These names are for US. **No adapter may forward one verbatim.** Each maps
|
|
16090
|
+
* the whole set onto its own renderer's vocabulary through a
|
|
16091
|
+
* `Record<NotificationActionIcon, string>` — a Record, never a lookup with a
|
|
16092
|
+
* fallback, so adding a member here fails every adapter's build until someone
|
|
16093
|
+
* decides its glyph, which is the only place that decision can be made
|
|
16094
|
+
* honestly.
|
|
16095
|
+
*
|
|
16096
|
+
* This paragraph is the bug. Zentik declared `actionIcons: true` and passed
|
|
16097
|
+
* `disarm` straight through; iOS feeds that string to
|
|
16098
|
+
* `UNNotificationActionIcon(systemImageName:)`, `disarm` is not an SF Symbol,
|
|
16099
|
+
* and every snooze and alarm button arrived BLANK. A pass-through is not a
|
|
16100
|
+
* mapping, and "the field is documented" is not "the value renders".
|
|
16101
|
+
*
|
|
16102
|
+
* Adding a member is TRAIN-BOUND. The enum lives in the published
|
|
16103
|
+
* `@camstack/server` closure and the cap seam validates against the HUB's copy,
|
|
16104
|
+
* so an addon that emits a token the running hub does not know does not lose an
|
|
16105
|
+
* icon — its whole `send` fails Zod validation and the notification never
|
|
16106
|
+
* arrives. Never emit a new token from an addon before the train carrying it.
|
|
15904
16107
|
*/
|
|
15905
|
-
var
|
|
16108
|
+
var NotificationActionIconSchema = _enum([
|
|
16109
|
+
"acknowledge",
|
|
16110
|
+
"dismiss",
|
|
16111
|
+
"silence",
|
|
16112
|
+
"snooze",
|
|
16113
|
+
"view",
|
|
16114
|
+
"play",
|
|
16115
|
+
"open",
|
|
16116
|
+
"close",
|
|
16117
|
+
"lock",
|
|
16118
|
+
"unlock",
|
|
16119
|
+
"arm",
|
|
16120
|
+
"arm-home",
|
|
16121
|
+
"arm-away",
|
|
16122
|
+
"arm-night",
|
|
16123
|
+
"disarm",
|
|
16124
|
+
"light",
|
|
16125
|
+
"alert",
|
|
16126
|
+
"camera"
|
|
16127
|
+
]);
|
|
16128
|
+
/** A single tap-through action button. */
|
|
16129
|
+
var NotificationActionSchema = object({
|
|
15906
16130
|
id: string(),
|
|
15907
16131
|
label: string(),
|
|
15908
|
-
|
|
15909
|
-
|
|
15910
|
-
|
|
15911
|
-
* Module Federation remote name — must match the `name` field on the
|
|
15912
|
-
* page addon's `federation()` plugin config. Used by admin-ui's
|
|
15913
|
-
* `<AddonPageLoader>` to call `loadRemote('<remoteName>/page')`.
|
|
15914
|
-
* Conventionally `addon_<id>_page` (snake_case; MF names cannot
|
|
15915
|
-
* contain hyphens).
|
|
15916
|
-
*/
|
|
15917
|
-
remoteName: string(),
|
|
16132
|
+
url: string().optional(),
|
|
16133
|
+
/** Dropped by the degrade engine for a kind with `caps.actionIcons: false`. */
|
|
16134
|
+
icon: NotificationActionIconSchema.optional(),
|
|
15918
16135
|
/**
|
|
15919
|
-
*
|
|
15920
|
-
*
|
|
15921
|
-
*
|
|
15922
|
-
*
|
|
15923
|
-
*
|
|
16136
|
+
* Renders in a warning style where the notifier supports it.
|
|
16137
|
+
*
|
|
16138
|
+
* A HINT, never a gate. The callback's authority is its token and nothing
|
|
16139
|
+
* else — see `notification-center/action-token.ts` for what that does and
|
|
16140
|
+
* does not buy.
|
|
15924
16141
|
*/
|
|
15925
|
-
|
|
16142
|
+
destructive: boolean().optional(),
|
|
15926
16143
|
/**
|
|
15927
|
-
*
|
|
15928
|
-
*
|
|
15929
|
-
*
|
|
15930
|
-
* the
|
|
15931
|
-
*
|
|
15932
|
-
*
|
|
16144
|
+
* How the tap should REACH the url.
|
|
16145
|
+
*
|
|
16146
|
+
* `navigate` (absent, and every button authored before this field) opens it:
|
|
16147
|
+
* the phone leaves the notification and shows whatever the callback returns.
|
|
16148
|
+
* That is right for a button whose answer the operator wants to read.
|
|
16149
|
+
*
|
|
16150
|
+
* `background` fires it as a POST and stays put. It exists for the buttons
|
|
16151
|
+
* whose whole point is not to interrupt — "silence this for 30 minutes" is
|
|
16152
|
+
* an answer to the notification, and being thrown into a browser tab to
|
|
16153
|
+
* confirm it costs more attention than the notification did. A backend that
|
|
16154
|
+
* cannot do a background call renders it as an ordinary link (the adapters
|
|
16155
|
+
* fall back rather than dropping the button), so this is a preference, never
|
|
16156
|
+
* a requirement.
|
|
15933
16157
|
*/
|
|
15934
|
-
|
|
15935
|
-
/** Display label for a CUSTOM `section` id (ignored for well-known ids). */
|
|
15936
|
-
sectionLabel: string().optional()
|
|
16158
|
+
mode: _enum(["navigate", "background"]).optional()
|
|
15937
16159
|
});
|
|
15938
|
-
|
|
15939
|
-
var
|
|
15940
|
-
|
|
15941
|
-
|
|
15942
|
-
|
|
15943
|
-
|
|
15944
|
-
|
|
15945
|
-
|
|
16160
|
+
/** A delivery parameter value: what a notifier declared it takes. */
|
|
16161
|
+
var DeliveryParamValueSchema = union([
|
|
16162
|
+
string(),
|
|
16163
|
+
number(),
|
|
16164
|
+
boolean()
|
|
16165
|
+
]);
|
|
16166
|
+
/**
|
|
16167
|
+
* One extra delivery parameter a notifier KIND declares (D938). A rule that
|
|
16168
|
+
* addresses a target of that kind may set it; a kind that declares nothing is
|
|
16169
|
+
* never handed one. The admin UI derives its control from this descriptor —
|
|
16170
|
+
* no editor knows a service by name.
|
|
16171
|
+
*
|
|
16172
|
+
* Optional fields are `.optional()`, never `.default()` (a Zod default does not
|
|
16173
|
+
* run on the addon cap path).
|
|
16174
|
+
*/
|
|
16175
|
+
var DeliveryParamSchema = object({
|
|
16176
|
+
key: string().min(1),
|
|
16177
|
+
label: string(),
|
|
16178
|
+
/** i18n key of the label, resolved by the declaring addon's namespace. */
|
|
16179
|
+
labelKey: string().optional(),
|
|
16180
|
+
type: _enum([
|
|
16181
|
+
"enum",
|
|
16182
|
+
"number",
|
|
16183
|
+
"boolean",
|
|
16184
|
+
"string"
|
|
15946
16185
|
]),
|
|
15947
|
-
|
|
15948
|
-
|
|
15949
|
-
|
|
15950
|
-
|
|
15951
|
-
|
|
15952
|
-
|
|
15953
|
-
|
|
15954
|
-
|
|
15955
|
-
|
|
16186
|
+
/** `enum` only: the closed set of accepted values. */
|
|
16187
|
+
options: array(object({
|
|
16188
|
+
value: string(),
|
|
16189
|
+
label: string()
|
|
16190
|
+
})).optional(),
|
|
16191
|
+
/** `number` only. */
|
|
16192
|
+
min: number().optional(),
|
|
16193
|
+
max: number().optional(),
|
|
16194
|
+
/** What the notifier does when the rule sets nothing; shown as the placeholder. */
|
|
16195
|
+
default: DeliveryParamValueSchema.optional()
|
|
15956
16196
|
});
|
|
15957
16197
|
/**
|
|
15958
|
-
*
|
|
15959
|
-
*
|
|
15960
|
-
*
|
|
15961
|
-
*
|
|
15962
|
-
*
|
|
15963
|
-
*
|
|
16198
|
+
* The canonical notification. `body` is the only hard field (Apprise model).
|
|
16199
|
+
* `priority` is a 5-level ORDINAL (1=lowest … 3=normal(default) … 5=urgent),
|
|
16200
|
+
* NOT a fixed severity enum — each kind declares its own `caps.levels` and
|
|
16201
|
+
* the adapter maps this ordinal onto its native level. `level?` is an
|
|
16202
|
+
* optional kind-native level id (`emergency`, `silent`, …) that overrides
|
|
16203
|
+
* `priority` for that one target.
|
|
15964
16204
|
*/
|
|
15965
|
-
var
|
|
15966
|
-
|
|
15967
|
-
|
|
15968
|
-
|
|
15969
|
-
|
|
15970
|
-
|
|
15971
|
-
|
|
15972
|
-
|
|
15973
|
-
|
|
15974
|
-
|
|
15975
|
-
|
|
15976
|
-
|
|
15977
|
-
|
|
15978
|
-
|
|
15979
|
-
|
|
15980
|
-
|
|
15981
|
-
|
|
15982
|
-
|
|
15983
|
-
*
|
|
15984
|
-
|
|
15985
|
-
|
|
15986
|
-
/** JSON-serializable body. `undefined` is treated as "no body". */
|
|
15987
|
-
body: unknown().optional(),
|
|
15988
|
-
/** Set when the handler called `reply.type(mime)`. */
|
|
15989
|
-
contentType: string().optional()
|
|
16205
|
+
var NotificationSchema = object({
|
|
16206
|
+
body: string(),
|
|
16207
|
+
title: string().optional(),
|
|
16208
|
+
format: NotificationFormatSchema.default("text"),
|
|
16209
|
+
priority: number().int().min(1).max(5).default(3),
|
|
16210
|
+
level: string().optional(),
|
|
16211
|
+
attachments: array(AttachmentSchema).optional(),
|
|
16212
|
+
clickUrl: string().optional(),
|
|
16213
|
+
actions: array(NotificationActionSchema).optional(),
|
|
16214
|
+
sound: string().optional(),
|
|
16215
|
+
ttl: number().optional(),
|
|
16216
|
+
tag: string().optional(),
|
|
16217
|
+
deviceId: number().optional(),
|
|
16218
|
+
eventId: string().optional(),
|
|
16219
|
+
metadata: record(string(), unknown()).optional(),
|
|
16220
|
+
/**
|
|
16221
|
+
* Values for the parameters the target's kind DECLARES in
|
|
16222
|
+
* {@link TargetKindSchema} `deliveryParams`. Already validated against the
|
|
16223
|
+
* declaration by the sender; a notifier reads only the keys it declared.
|
|
16224
|
+
*/
|
|
16225
|
+
delivery: record(string(), DeliveryParamValueSchema).optional()
|
|
15990
16226
|
});
|
|
15991
|
-
|
|
15992
|
-
var
|
|
16227
|
+
/** One declared native severity/priority level for a kind. */
|
|
16228
|
+
var TargetKindLevelSchema = object({
|
|
15993
16229
|
id: string(),
|
|
15994
16230
|
label: string(),
|
|
15995
|
-
|
|
15996
|
-
|
|
15997
|
-
|
|
15998
|
-
|
|
15999
|
-
|
|
16000
|
-
|
|
16001
|
-
|
|
16002
|
-
|
|
16003
|
-
|
|
16004
|
-
|
|
16005
|
-
defaultCollapsed: boolean().optional(),
|
|
16006
|
-
columns: union([
|
|
16007
|
-
literal(1),
|
|
16008
|
-
literal(2),
|
|
16009
|
-
literal(3),
|
|
16010
|
-
literal(4)
|
|
16011
|
-
]).optional(),
|
|
16012
|
-
tab: string().optional(),
|
|
16013
|
-
location: _enum([
|
|
16014
|
-
"settings",
|
|
16015
|
-
"top-tab",
|
|
16016
|
-
"hero"
|
|
16017
|
-
]).optional(),
|
|
16018
|
-
order: number().optional(),
|
|
16019
|
-
fields: array(any())
|
|
16231
|
+
/** Which canonical priority (1..5) this level maps to. `null` = qualitative-only. */
|
|
16232
|
+
ordinal: number().int().min(1).max(5).nullable(),
|
|
16233
|
+
flags: object({
|
|
16234
|
+
critical: boolean().optional(),
|
|
16235
|
+
silent: boolean().optional(),
|
|
16236
|
+
noPush: boolean().optional()
|
|
16237
|
+
}).optional(),
|
|
16238
|
+
/** e.g. Pushover `emergency` requires `retry` / `expire`. */
|
|
16239
|
+
requires: array(string()).optional(),
|
|
16240
|
+
description: string().optional()
|
|
16020
16241
|
});
|
|
16021
|
-
|
|
16022
|
-
|
|
16023
|
-
|
|
16242
|
+
/** The full capability block consulted before dispatch. */
|
|
16243
|
+
var TargetKindCapsSchema = object({
|
|
16244
|
+
attachments: object({
|
|
16245
|
+
mediaTypes: array(AttachmentMediaTypeSchema),
|
|
16246
|
+
mode: _enum([
|
|
16247
|
+
"url",
|
|
16248
|
+
"bytes",
|
|
16249
|
+
"both"
|
|
16250
|
+
]),
|
|
16251
|
+
max: number().int().nonnegative(),
|
|
16252
|
+
maxBytes: number().int().positive().optional()
|
|
16253
|
+
}),
|
|
16254
|
+
/** Max action buttons (0 = none). */
|
|
16255
|
+
actions: number().int().nonnegative(),
|
|
16256
|
+
/**
|
|
16257
|
+
* Whether this kind renders a per-action ICON.
|
|
16258
|
+
*
|
|
16259
|
+
* `.optional()`, deliberately NOT `.default(false)`: a Zod default does not
|
|
16260
|
+
* run on the addon cap path — three production failures in one day taught
|
|
16261
|
+
* this repo that once. Absent is read as false by the degrade engine, which
|
|
16262
|
+
* is the safe direction: an icon that is not rendered costs nothing, an icon
|
|
16263
|
+
* assumed and dropped costs the operator's trust in the field.
|
|
16264
|
+
*/
|
|
16265
|
+
actionIcons: boolean().optional(),
|
|
16266
|
+
levels: array(TargetKindLevelSchema),
|
|
16267
|
+
format: array(NotificationFormatSchema),
|
|
16268
|
+
clickUrl: boolean(),
|
|
16269
|
+
sound: boolean(),
|
|
16270
|
+
ttl: boolean(),
|
|
16271
|
+
bodyMaxLen: number().int().positive()
|
|
16024
16272
|
});
|
|
16025
|
-
/**
|
|
16026
|
-
|
|
16027
|
-
|
|
16028
|
-
|
|
16029
|
-
|
|
16030
|
-
|
|
16031
|
-
|
|
16032
|
-
|
|
16033
|
-
|
|
16034
|
-
|
|
16273
|
+
/**
|
|
16274
|
+
* `configSchema` is a `ConfigUISchema` tree passed through to the admin
|
|
16275
|
+
* FormBuilder. Stored as `z.unknown()` at the cap seam (mirrors
|
|
16276
|
+
* `device-provider.getChildCreationSchema` `CreationSchemaOutputSchema`) —
|
|
16277
|
+
* the union is large and not meant for runtime validation here; the exported
|
|
16278
|
+
* `TargetKind` type re-tightens `configSchema` to `ConfigUISchema`.
|
|
16279
|
+
*/
|
|
16280
|
+
var ConfigSchemaPassthrough$3 = unknown();
|
|
16281
|
+
var TargetKindSchema = object({
|
|
16282
|
+
kind: string(),
|
|
16283
|
+
label: string(),
|
|
16284
|
+
icon: string(),
|
|
16285
|
+
/** Stamped by each provider so the concat-fanned catalog stays routable. */
|
|
16286
|
+
addonId: string(),
|
|
16287
|
+
/**
|
|
16288
|
+
* URL of the kind's bundled BRAND icon, served by the providing addon over
|
|
16289
|
+
* its own `addon-routes` surface (`/addon/<addonId>/icons/<kind>`). Absent
|
|
16290
|
+
* when the addon bundles no icon for that kind — the client then falls back
|
|
16291
|
+
* to a neutral glyph rather than rendering the raw `icon` NAME as text.
|
|
16292
|
+
*
|
|
16293
|
+
* Root-relative on purpose: it resolves against whatever origin serves a web
|
|
16294
|
+
* client, and a native client joins it onto its own hub base.
|
|
16295
|
+
*
|
|
16296
|
+
* DECLARED here deliberately. It used to travel as an undeclared passthrough
|
|
16297
|
+
* field that survived only because the runtime cap-router forwards provider
|
|
16298
|
+
* output verbatim — so every consumer had to re-declare it by hand to stop
|
|
16299
|
+
* its own Zod parse from stripping it, and the whole arrangement would have
|
|
16300
|
+
* broken silently the moment output validation was tightened anywhere.
|
|
16301
|
+
*/
|
|
16302
|
+
iconUrl: string().optional(),
|
|
16303
|
+
/**
|
|
16304
|
+
* Media type of {@link iconUrl} (`image/svg+xml`, `image/png`, …).
|
|
16305
|
+
*
|
|
16306
|
+
* The server knows this and therefore says it, because the client cannot
|
|
16307
|
+
* safely guess: a React-Native client renders SVG and raster through two
|
|
16308
|
+
* DIFFERENT components (`react-native-svg` vs `expo-image` — expo-image does
|
|
16309
|
+
* not decode SVG on iOS/Android), so without this it silently fell back to a
|
|
16310
|
+
* placeholder glyph for every vector icon while the web build looked fine.
|
|
16311
|
+
*
|
|
16312
|
+
* Absent when {@link iconUrl} is absent, or for a legacy provider that has
|
|
16313
|
+
* not been updated — a client that cannot determine the type should prefer
|
|
16314
|
+
* its raster path, which is the safe default for an unknown image.
|
|
16315
|
+
*/
|
|
16316
|
+
iconMediaType: string().optional(),
|
|
16317
|
+
configSchema: ConfigSchemaPassthrough$3,
|
|
16318
|
+
/**
|
|
16319
|
+
* The config keys that decide WHERE this kind's secrets are sent (server,
|
|
16320
|
+
* base URL, instance, chat, recipient). A save that changes any of them
|
|
16321
|
+
* while leaving a secret redacted is refused by the provider (D634), so an
|
|
16322
|
+
* editor uses this to ask for the secret on exactly those edits instead of
|
|
16323
|
+
* on every edit.
|
|
16324
|
+
*
|
|
16325
|
+
* Optional: absent from a provider that holds no secret (the Home Assistant
|
|
16326
|
+
* kinds) and from a provider older than this field — an editor that finds
|
|
16327
|
+
* it absent must assume ANY edit may need the secret.
|
|
16328
|
+
*/
|
|
16329
|
+
destinationKeys: array(string()).optional(),
|
|
16330
|
+
supportsDiscovery: boolean(),
|
|
16331
|
+
/**
|
|
16332
|
+
* Extra delivery parameters a rule may set for a target of this kind (D938).
|
|
16333
|
+
* Absent = none; the rule editor then offers nothing.
|
|
16334
|
+
*/
|
|
16335
|
+
deliveryParams: array(DeliveryParamSchema).optional(),
|
|
16336
|
+
caps: TargetKindCapsSchema
|
|
16337
|
+
});
|
|
16338
|
+
/**
|
|
16339
|
+
* A persisted target. `config` holds secrets; providers REDACT secret fields
|
|
16340
|
+
* (return a presence marker only) when serving `listTargets` — never
|
|
16341
|
+
* round-trip a stored secret to the UI.
|
|
16342
|
+
*/
|
|
16343
|
+
var TargetSchema = object({
|
|
16344
|
+
id: string(),
|
|
16345
|
+
name: string(),
|
|
16346
|
+
kind: string(),
|
|
16347
|
+
addonId: string(),
|
|
16348
|
+
enabled: boolean(),
|
|
16349
|
+
config: record(string(), unknown())
|
|
16350
|
+
});
|
|
16351
|
+
/** A discovery-surfaced candidate (config is partial + non-secret). */
|
|
16352
|
+
var DiscoveredTargetSchema = object({
|
|
16353
|
+
kind: string(),
|
|
16354
|
+
suggestedName: string(),
|
|
16355
|
+
config: record(string(), unknown())
|
|
16356
|
+
});
|
|
16357
|
+
/** The degrade engine's report — what was resolved / dropped / degraded. */
|
|
16358
|
+
var RenderedAsSchema = object({
|
|
16359
|
+
level: string(),
|
|
16360
|
+
format: NotificationFormatSchema,
|
|
16361
|
+
attachmentsSent: number().int().nonnegative(),
|
|
16362
|
+
actionsSent: number().int().nonnegative(),
|
|
16363
|
+
truncated: boolean(),
|
|
16364
|
+
dropped: array(string())
|
|
16365
|
+
});
|
|
16366
|
+
var SendResultSchema = object({
|
|
16367
|
+
success: boolean(),
|
|
16368
|
+
error: string().optional(),
|
|
16369
|
+
renderedAs: RenderedAsSchema.optional()
|
|
16370
|
+
});
|
|
16371
|
+
/** Same shape as SendResult — kept as a distinct name for the test panel. */
|
|
16372
|
+
var TestResultSchema = SendResultSchema;
|
|
16373
|
+
/**
|
|
16374
|
+
* Pre-save credential probe against a partial (unsaved) target config.
|
|
16375
|
+
* `resolvedUrl` never includes secrets (token stripped from path).
|
|
16376
|
+
*/
|
|
16377
|
+
var ProbeTargetConfigResultSchema = object({
|
|
16378
|
+
ok: boolean(),
|
|
16379
|
+
resolvedUrl: string(),
|
|
16380
|
+
httpStatus: number().int().optional(),
|
|
16381
|
+
stateInstance: string().optional(),
|
|
16382
|
+
error: string().optional()
|
|
16383
|
+
});
|
|
16384
|
+
method(object({}), array(TargetKindSchema)), method(object({}), array(TargetSchema), { auth: "admin" }), method(object({ targetId: string() }), TargetSchema, { auth: "admin" }), method(object({
|
|
16385
|
+
kind: string(),
|
|
16386
|
+
config: record(string(), unknown()).optional(),
|
|
16387
|
+
/**
|
|
16388
|
+
* When editing / duplicating, the blank password field never round-trips
|
|
16389
|
+
* the stored token. Pass the source target id so the provider can restore
|
|
16390
|
+
* secrets server-side before dialling (same merge as upsert).
|
|
16391
|
+
*/
|
|
16392
|
+
targetId: string().optional()
|
|
16393
|
+
}), array(DiscoveredTargetSchema), { auth: "admin" }), method(object({
|
|
16394
|
+
kind: string(),
|
|
16395
|
+
config: record(string(), unknown()),
|
|
16396
|
+
/** See `discoverTargets.targetId` — restore stored secrets for a blank password. */
|
|
16397
|
+
targetId: string().optional()
|
|
16398
|
+
}), ProbeTargetConfigResultSchema, {
|
|
16399
|
+
kind: "mutation",
|
|
16400
|
+
auth: "admin"
|
|
16401
|
+
}), method(object({
|
|
16402
|
+
targetId: string(),
|
|
16403
|
+
notification: NotificationSchema
|
|
16404
|
+
}), SendResultSchema, {
|
|
16405
|
+
kind: "mutation",
|
|
16406
|
+
auth: "admin"
|
|
16407
|
+
}), method(object({
|
|
16408
|
+
targetId: string(),
|
|
16409
|
+
sample: NotificationSchema.optional()
|
|
16410
|
+
}), TestResultSchema, {
|
|
16411
|
+
kind: "mutation",
|
|
16412
|
+
auth: "admin"
|
|
16413
|
+
}), method(object({
|
|
16414
|
+
target: TargetSchema,
|
|
16415
|
+
/**
|
|
16416
|
+
* Duplicate flow: create a NEW target id while copying secrets from an
|
|
16417
|
+
* existing row. The UI never holds the stored token; blank / redacted
|
|
16418
|
+
* password fields are restored from this source (D634 still applies if
|
|
16419
|
+
* destinations diverge without a re-typed secret).
|
|
16420
|
+
*/
|
|
16421
|
+
cloneSecretsFrom: string().optional()
|
|
16422
|
+
}), TargetSchema, {
|
|
16423
|
+
kind: "mutation",
|
|
16424
|
+
auth: "admin"
|
|
16425
|
+
}), method(object({ targetId: string() }), _void(), {
|
|
16426
|
+
kind: "mutation",
|
|
16427
|
+
auth: "admin"
|
|
16428
|
+
}), method(object({
|
|
16429
|
+
targetId: string(),
|
|
16430
|
+
enabled: boolean()
|
|
16431
|
+
}), _void(), {
|
|
16432
|
+
kind: "mutation",
|
|
16433
|
+
auth: "admin"
|
|
16434
|
+
});
|
|
16435
|
+
/**
|
|
16436
|
+
* `addon-pages` — system-scoped singleton aggregator cap. Public-facing
|
|
16437
|
+
* surface that admin-ui consumes through `useAddonPagesListPages()`.
|
|
16438
|
+
*
|
|
16439
|
+
* The provider iterates every `addon-pages-source` (collection) provider
|
|
16440
|
+
* and emits `AddonPageInfo[]` enriched with versioned `bundleUrl` strings
|
|
16441
|
+
* pointing at `/api/addon-pages/<addonId>/<bundle>?v=<mtime>`. The
|
|
16442
|
+
* filesystem `mtime` cache-buster lets the browser pick up addon
|
|
16443
|
+
* rebuilds without manual reload.
|
|
16444
|
+
*
|
|
16445
|
+
* The hub-local builtin `addon-pages-aggregator` (see
|
|
16446
|
+
* `@camstack/system/builtins/addon-pages-aggregator`) registers the
|
|
16447
|
+
* provider. Splitting the public aggregator from the raw collection
|
|
16448
|
+
* keeps both ends in codegen — there's no hand-written
|
|
16449
|
+
* `addon-pages.router.ts` wrapper anymore.
|
|
16450
|
+
*/
|
|
16451
|
+
var AddonPageDeclarationSchema$1 = object({
|
|
16452
|
+
id: string(),
|
|
16453
|
+
label: string(),
|
|
16454
|
+
icon: string(),
|
|
16455
|
+
path: string(),
|
|
16456
|
+
remoteName: string(),
|
|
16457
|
+
bundle: string(),
|
|
16458
|
+
section: string().optional(),
|
|
16459
|
+
sectionLabel: string().optional()
|
|
16460
|
+
});
|
|
16461
|
+
var AddonPageInfoSchema = object({
|
|
16462
|
+
addonId: string(),
|
|
16463
|
+
page: AddonPageDeclarationSchema$1,
|
|
16464
|
+
bundleUrl: string()
|
|
16465
|
+
});
|
|
16466
|
+
method(_void(), array(AddonPageInfoSchema).readonly());
|
|
16467
|
+
var AddonHttpRouteSchema = object({
|
|
16468
|
+
method: _enum([
|
|
16469
|
+
"GET",
|
|
16470
|
+
"POST",
|
|
16471
|
+
"PUT",
|
|
16472
|
+
"DELETE",
|
|
16473
|
+
"PATCH"
|
|
16474
|
+
]),
|
|
16475
|
+
path: string(),
|
|
16476
|
+
access: _enum([
|
|
16477
|
+
"public",
|
|
16478
|
+
"authenticated",
|
|
16479
|
+
"admin"
|
|
16480
|
+
]).optional(),
|
|
16481
|
+
description: string().optional(),
|
|
16482
|
+
/** The hub limits this route per client address before the handler runs. */
|
|
16483
|
+
rateLimit: _enum(["auth"]).optional()
|
|
16484
|
+
});
|
|
16485
|
+
/**
|
|
16486
|
+
* Cross-process route invocation envelope. The hub captures the
|
|
16487
|
+
* request as plain data, ships it to the worker via Moleculer, and
|
|
16488
|
+
* the worker runs the local handler against a capturing reply. The
|
|
16489
|
+
* envelope returned describes what the handler intended (status,
|
|
16490
|
+
* headers, body, or a redirect) so the hub can translate it back to
|
|
16491
|
+
* the Fastify reply that's actually wired to the socket.
|
|
16492
|
+
*/
|
|
16493
|
+
var InvokeRequestSchema = object({
|
|
16494
|
+
method: string(),
|
|
16495
|
+
path: string(),
|
|
16496
|
+
params: record(string(), string()),
|
|
16497
|
+
query: record(string(), string()),
|
|
16498
|
+
body: unknown(),
|
|
16499
|
+
headers: record(string(), string()),
|
|
16500
|
+
user: object({
|
|
16501
|
+
id: string(),
|
|
16502
|
+
username: string(),
|
|
16503
|
+
isAdmin: boolean()
|
|
16504
|
+
}).optional(),
|
|
16505
|
+
scopedToken: unknown().optional()
|
|
16506
|
+
});
|
|
16507
|
+
var InvokeReplyEnvelopeSchema = object({
|
|
16508
|
+
status: number().int(),
|
|
16509
|
+
headers: record(string(), string()),
|
|
16510
|
+
/** When set, the hub MUST `reply.redirect(redirectUrl)` instead of
|
|
16511
|
+
* sending `body`. Status defaults to 302 when this is set unless
|
|
16512
|
+
* the handler called `reply.code(...)` explicitly. */
|
|
16513
|
+
redirectUrl: string().nullable(),
|
|
16514
|
+
/** JSON-serializable body. `undefined` is treated as "no body". */
|
|
16515
|
+
body: unknown().optional(),
|
|
16516
|
+
/** Set when the handler called `reply.type(mime)`. */
|
|
16517
|
+
contentType: string().optional()
|
|
16518
|
+
});
|
|
16519
|
+
method(_void(), array(AddonHttpRouteSchema)), method(InvokeRequestSchema, InvokeReplyEnvelopeSchema, { kind: "mutation" });
|
|
16520
|
+
var ConfigTabDeclarationSchema = object({
|
|
16521
|
+
id: string(),
|
|
16522
|
+
label: string(),
|
|
16523
|
+
icon: string(),
|
|
16524
|
+
order: number().optional()
|
|
16525
|
+
});
|
|
16526
|
+
var ConfigSectionWithValuesSchema = object({
|
|
16527
|
+
id: string(),
|
|
16528
|
+
title: string(),
|
|
16529
|
+
titleKey: string().optional(),
|
|
16530
|
+
description: string().optional(),
|
|
16531
|
+
descriptionKey: string().optional(),
|
|
16532
|
+
style: _enum(["card", "accordion"]).optional(),
|
|
16533
|
+
defaultCollapsed: boolean().optional(),
|
|
16534
|
+
columns: union([
|
|
16535
|
+
literal(1),
|
|
16536
|
+
literal(2),
|
|
16537
|
+
literal(3),
|
|
16538
|
+
literal(4)
|
|
16539
|
+
]).optional(),
|
|
16540
|
+
tab: string().optional(),
|
|
16541
|
+
location: _enum([
|
|
16542
|
+
"settings",
|
|
16543
|
+
"top-tab",
|
|
16544
|
+
"hero"
|
|
16545
|
+
]).optional(),
|
|
16546
|
+
order: number().optional(),
|
|
16547
|
+
fields: array(any())
|
|
16548
|
+
});
|
|
16549
|
+
var SettingsSchemaWithValuesSchema = object({
|
|
16550
|
+
tabs: array(ConfigTabDeclarationSchema).optional(),
|
|
16551
|
+
sections: array(ConfigSectionWithValuesSchema)
|
|
16552
|
+
});
|
|
16553
|
+
/** Patch object — keys are field names, values are the new field values. */
|
|
16554
|
+
var SettingsPatchSchema = record(string(), unknown());
|
|
16555
|
+
/** Standard success response for update operations. */
|
|
16556
|
+
var SettingsUpdateResultSchema = object({ success: literal(true) });
|
|
16557
|
+
method(object({
|
|
16558
|
+
addonId: string(),
|
|
16559
|
+
nodeId: string().optional(),
|
|
16560
|
+
overlay: record(string(), unknown()).optional(),
|
|
16561
|
+
cap: string().optional()
|
|
16562
|
+
}), SettingsSchemaWithValuesSchema.nullable()), method(object({
|
|
16035
16563
|
addonId: string(),
|
|
16036
16564
|
nodeId: string().optional(),
|
|
16037
16565
|
patch: SettingsPatchSchema
|
|
@@ -18478,7 +19006,11 @@ var CompositionProblemSchema = object({
|
|
|
18478
19006
|
"mixed-quantity",
|
|
18479
19007
|
"helper-mismatch",
|
|
18480
19008
|
"member-constraint",
|
|
18481
|
-
"retention"
|
|
19009
|
+
"retention",
|
|
19010
|
+
"command-method-unknown",
|
|
19011
|
+
"command-source-unknown",
|
|
19012
|
+
"command-input-unknown",
|
|
19013
|
+
"command-input-missing"
|
|
18482
19014
|
]),
|
|
18483
19015
|
path: string(),
|
|
18484
19016
|
message: string()
|
|
@@ -18517,7 +19049,9 @@ var CompositionFieldRoleSchema = _enum([
|
|
|
18517
19049
|
var CompositionFieldItemSchema = object({
|
|
18518
19050
|
arrayPath: string(),
|
|
18519
19051
|
key: string(),
|
|
18520
|
-
label: string()
|
|
19052
|
+
label: string(),
|
|
19053
|
+
/** True when the item carries a `reset` forward: the composer writes `resettable` from this (D967). */
|
|
19054
|
+
resettable: boolean().optional()
|
|
18521
19055
|
});
|
|
18522
19056
|
var CompositionFieldPlanSchema = object({
|
|
18523
19057
|
cap: string(),
|
|
@@ -18722,7 +19256,7 @@ Object.freeze({
|
|
|
18722
19256
|
* One catalog row per base reading a group helper can build (D944 §3).
|
|
18723
19257
|
* Data, not a form default written into the block.
|
|
18724
19258
|
*/
|
|
18725
|
-
var NOW$
|
|
19259
|
+
var NOW$3 = {
|
|
18726
19260
|
fieldPath: "lastFetchedAt",
|
|
18727
19261
|
expr: "now"
|
|
18728
19262
|
};
|
|
@@ -18774,7 +19308,7 @@ var GROUP_TEMPLATES = [
|
|
|
18774
19308
|
quantity: "temperature",
|
|
18775
19309
|
defaultAggregate: "mean",
|
|
18776
19310
|
empty: "null",
|
|
18777
|
-
companions: [NOW$
|
|
19311
|
+
companions: [NOW$3],
|
|
18778
19312
|
alsoFrom: {
|
|
18779
19313
|
deviceTypes: CLIMATE_DEVICES,
|
|
18780
19314
|
accept: {
|
|
@@ -18792,7 +19326,7 @@ var GROUP_TEMPLATES = [
|
|
|
18792
19326
|
quantity: "humidity",
|
|
18793
19327
|
defaultAggregate: "mean",
|
|
18794
19328
|
empty: "null",
|
|
18795
|
-
companions: [NOW$
|
|
19329
|
+
companions: [NOW$3],
|
|
18796
19330
|
alsoFrom: {
|
|
18797
19331
|
deviceTypes: CLIMATE_DEVICES,
|
|
18798
19332
|
accept: {
|
|
@@ -18810,7 +19344,7 @@ var GROUP_TEMPLATES = [
|
|
|
18810
19344
|
quantity: "pressure",
|
|
18811
19345
|
defaultAggregate: "mean",
|
|
18812
19346
|
empty: "null",
|
|
18813
|
-
companions: [NOW$
|
|
19347
|
+
companions: [NOW$3]
|
|
18814
19348
|
}),
|
|
18815
19349
|
numeric({
|
|
18816
19350
|
id: "illuminance",
|
|
@@ -18821,7 +19355,7 @@ var GROUP_TEMPLATES = [
|
|
|
18821
19355
|
quantity: "illuminance",
|
|
18822
19356
|
defaultAggregate: "mean",
|
|
18823
19357
|
empty: "null",
|
|
18824
|
-
companions: [NOW$
|
|
19358
|
+
companions: [NOW$3]
|
|
18825
19359
|
}),
|
|
18826
19360
|
numeric({
|
|
18827
19361
|
id: "power",
|
|
@@ -18832,7 +19366,7 @@ var GROUP_TEMPLATES = [
|
|
|
18832
19366
|
quantity: "power",
|
|
18833
19367
|
defaultAggregate: "sum",
|
|
18834
19368
|
empty: "omit",
|
|
18835
|
-
companions: [NOW$
|
|
19369
|
+
companions: [NOW$3]
|
|
18836
19370
|
}),
|
|
18837
19371
|
numeric({
|
|
18838
19372
|
id: "energy",
|
|
@@ -18843,7 +19377,7 @@ var GROUP_TEMPLATES = [
|
|
|
18843
19377
|
quantity: "energy",
|
|
18844
19378
|
defaultAggregate: "sum",
|
|
18845
19379
|
empty: "omit",
|
|
18846
|
-
companions: [NOW$
|
|
19380
|
+
companions: [NOW$3]
|
|
18847
19381
|
}),
|
|
18848
19382
|
numeric({
|
|
18849
19383
|
id: "battery",
|
|
@@ -18878,7 +19412,7 @@ var GROUP_TEMPLATES = [
|
|
|
18878
19412
|
quantity: "device",
|
|
18879
19413
|
defaultAggregate: "mean",
|
|
18880
19414
|
empty: "null",
|
|
18881
|
-
companions: [NOW$
|
|
19415
|
+
companions: [NOW$3]
|
|
18882
19416
|
}),
|
|
18883
19417
|
binary({
|
|
18884
19418
|
id: "motion",
|
|
@@ -21224,12 +21758,48 @@ var ExposeInputSchema = object({
|
|
|
21224
21758
|
capabilities: array(string()).optional()
|
|
21225
21759
|
});
|
|
21226
21760
|
var UnexposeInputSchema = object({ deviceId: string() });
|
|
21761
|
+
/**
|
|
21762
|
+
* What an exporter may expose besides devices (D968). An action and a
|
|
21763
|
+
* notification target are LIST ENTRIES, never devices (D954): they enter an
|
|
21764
|
+
* exporter's own selection, not the device registry.
|
|
21765
|
+
*/
|
|
21766
|
+
var ExportEntityKindSchema = _enum([
|
|
21767
|
+
"device",
|
|
21768
|
+
"action",
|
|
21769
|
+
"notifier"
|
|
21770
|
+
]);
|
|
21771
|
+
var ExportEntityRefSchema = discriminatedUnion("kind", [
|
|
21772
|
+
object({
|
|
21773
|
+
kind: literal("device"),
|
|
21774
|
+
deviceId: string()
|
|
21775
|
+
}),
|
|
21776
|
+
object({
|
|
21777
|
+
kind: literal("action"),
|
|
21778
|
+
actionId: string().min(1)
|
|
21779
|
+
}),
|
|
21780
|
+
object({
|
|
21781
|
+
kind: literal("notifier"),
|
|
21782
|
+
targetId: string().min(1)
|
|
21783
|
+
})
|
|
21784
|
+
]);
|
|
21785
|
+
var ExposedEntitySchema = object({
|
|
21786
|
+
entity: ExportEntityRefSchema,
|
|
21787
|
+
exposedAs: string().optional()
|
|
21788
|
+
});
|
|
21789
|
+
var ExposeEntityInputSchema = object({ entity: ExportEntityRefSchema });
|
|
21790
|
+
var UnexposeEntityInputSchema = object({ entity: ExportEntityRefSchema });
|
|
21227
21791
|
method(_void(), DeviceExportStatusSchema), method(_void(), array(DeviceKindSchema)), method(_void(), array(ExposedDeviceSchema)), method(ExposeInputSchema, _void(), {
|
|
21228
21792
|
kind: "mutation",
|
|
21229
21793
|
auth: "admin"
|
|
21230
21794
|
}), method(UnexposeInputSchema, _void(), {
|
|
21231
21795
|
kind: "mutation",
|
|
21232
21796
|
auth: "admin"
|
|
21797
|
+
}), optionalMethod(_void(), array(ExportEntityKindSchema)), optionalMethod(_void(), array(ExposedEntitySchema)), optionalMethod(ExposeEntityInputSchema, _void(), {
|
|
21798
|
+
kind: "mutation",
|
|
21799
|
+
auth: "admin"
|
|
21800
|
+
}), optionalMethod(UnexposeEntityInputSchema, _void(), {
|
|
21801
|
+
kind: "mutation",
|
|
21802
|
+
auth: "admin"
|
|
21233
21803
|
});
|
|
21234
21804
|
/** Lucide category ids, alphabetical. `ICON_META` indexes into this. */
|
|
21235
21805
|
var ICON_CATEGORY_IDS = [
|
|
@@ -42370,6 +42940,14 @@ method(object({
|
|
|
42370
42940
|
kind: "mutation",
|
|
42371
42941
|
auth: "admin"
|
|
42372
42942
|
});
|
|
42943
|
+
method(object({
|
|
42944
|
+
nodeId: string().min(1),
|
|
42945
|
+
/** Epoch ms the node was forgotten (the tombstone's `removedAt`). */
|
|
42946
|
+
removedAt: number()
|
|
42947
|
+
}), object({ counts: record(string(), number().int().nonnegative()) }), {
|
|
42948
|
+
kind: "mutation",
|
|
42949
|
+
auth: "admin"
|
|
42950
|
+
});
|
|
42373
42951
|
/**
|
|
42374
42952
|
* `device-removal-hook` — the reliable way an addon learns a device was DELETED,
|
|
42375
42953
|
* so it can delete what it keeps for that device (D865).
|
|
@@ -43090,7 +43668,7 @@ var LlmProviderWidgetSchema = object({
|
|
|
43090
43668
|
/** ConfigUISchema tree passed through untyped on the wire (the
|
|
43091
43669
|
* notification-output `ConfigSchemaPassthrough` precedent at
|
|
43092
43670
|
* notification-output.cap.ts:151); the exported TS type re-tightens it. */
|
|
43093
|
-
var ConfigSchemaPassthrough$
|
|
43671
|
+
var ConfigSchemaPassthrough$2 = unknown();
|
|
43094
43672
|
var LlmProfileKindDescriptorSchema = object({
|
|
43095
43673
|
kind: LlmProfileKindSchema,
|
|
43096
43674
|
label: string(),
|
|
@@ -43099,9 +43677,9 @@ var LlmProfileKindDescriptorSchema = object({
|
|
|
43099
43677
|
/** Stamped by each provider so the concat-fanned catalog stays routable. */
|
|
43100
43678
|
addonId: string(),
|
|
43101
43679
|
/** The provider's own fields (`providerConfig`); `password` fields are keychain-held. */
|
|
43102
|
-
connectionSchema: ConfigSchemaPassthrough$
|
|
43680
|
+
connectionSchema: ConfigSchemaPassthrough$2,
|
|
43103
43681
|
/** Provider fields that belong under "Advanced" (extra headers, runtime tuning). */
|
|
43104
|
-
advancedSchema: ConfigSchemaPassthrough$
|
|
43682
|
+
advancedSchema: ConfigSchemaPassthrough$2.optional(),
|
|
43105
43683
|
/** The kind's defaults; a model from `listModels` may override any of them. */
|
|
43106
43684
|
features: LlmModelFeaturesSchema,
|
|
43107
43685
|
/** `false` = the provider stamps `supportsVision` itself (from what a node reports). */
|
|
@@ -43627,10 +44205,10 @@ var CpuBreakdownSchema = object({
|
|
|
43627
44205
|
cores: number()
|
|
43628
44206
|
});
|
|
43629
44207
|
var MemoryInfoSchema = object({
|
|
43630
|
-
percent: number(),
|
|
44208
|
+
percent: number().nullable(),
|
|
43631
44209
|
totalBytes: number(),
|
|
43632
|
-
usedBytes: number(),
|
|
43633
|
-
availableBytes: number(),
|
|
44210
|
+
usedBytes: number().nullable(),
|
|
44211
|
+
availableBytes: number().nullable(),
|
|
43634
44212
|
swapUsedBytes: number(),
|
|
43635
44213
|
swapTotalBytes: number()
|
|
43636
44214
|
});
|
|
@@ -43900,698 +44478,278 @@ var NodeLoadSeriesSchema = object({
|
|
|
43900
44478
|
/**
|
|
43901
44479
|
* Did the DURABLE tier contribute? `false` means the answer is the hot ring
|
|
43902
44480
|
* alone — an agent (which holds no table), or a store that refused.
|
|
43903
|
-
* Reported because "the last hour" and "the last six hours" are different
|
|
43904
|
-
* questions and an operator must not have to guess which was answered.
|
|
43905
|
-
*/
|
|
43906
|
-
durable: boolean()
|
|
43907
|
-
});
|
|
43908
|
-
var GetLoadSeriesInputSchema = object({
|
|
43909
|
-
/**
|
|
43910
|
-
* The node whose series is wanted.
|
|
43911
|
-
*
|
|
43912
|
-
* NOT named `nodeId`: the generated cap router strips a top-level
|
|
43913
|
-
* `nodeId` from every method input and uses it to ROUTE the call to
|
|
43914
|
-
* that node's provider (`generated-cap-routers.ts`). A series target
|
|
43915
|
-
* called `nodeId` would silently become a routing pin and never reach
|
|
43916
|
-
* the provider. The hub holds every node it hears from, so the
|
|
43917
|
-
* ordinary call is unpinned — answered by the hub, for any node.
|
|
43918
|
-
*/
|
|
43919
|
-
forNodeId: string(),
|
|
43920
|
-
/**
|
|
43921
|
-
* EXCLUSIVE lower bound. A caller passes the newest `atMs` it already
|
|
43922
|
-
* holds and receives only what it is missing, so seeding a live chart
|
|
43923
|
-
* from this method cannot double a point already drawn.
|
|
43924
|
-
*/
|
|
43925
|
-
sinceMs: number().optional(),
|
|
43926
|
-
/**
|
|
43927
|
-
* Most points the caller wants PER FUNCTION. The window is reduced to fit,
|
|
43928
|
-
* preserving min and max per bucket.
|
|
43929
|
-
*
|
|
43930
|
-
* Absent means NO reduction — legitimate for a short window and a trap for a
|
|
43931
|
-
* long one, which is why a chart passes its own pixel width.
|
|
43932
|
-
*/
|
|
43933
|
-
maxPoints: number().int().positive().optional()
|
|
43934
|
-
});
|
|
43935
|
-
var SystemMetricsSchema = object({
|
|
43936
|
-
cpuPercent: number(),
|
|
43937
|
-
memoryPercent: number(),
|
|
43938
|
-
memoryUsedMB: number(),
|
|
43939
|
-
memoryTotalMB: number(),
|
|
43940
|
-
diskPercent: number().optional(),
|
|
43941
|
-
temperature: number().optional(),
|
|
43942
|
-
gpuPercent: number().optional(),
|
|
43943
|
-
gpuMemoryPercent: number().optional()
|
|
43944
|
-
});
|
|
43945
|
-
method(_void(), SystemResourceSnapshotSchema), method(_void(), SystemResourceSnapshotSchema.nullable()), method(_void(), SystemMetricsSchema), method(object({ dirPath: string() }), DiskSpaceInfoSchema), method(_void(), MetricsGpuInfoSchema.nullable()), method(_void(), number().nullable()), method(object({ pids: array(number()) }), array(PidResourceStatsSchema)), method(_void(), array(AddonInstanceSchema).readonly()), method(object({ addonId: string() }), PidResourceStatsSchema.nullable()), method(_void(), array(NodeProcessSchema).readonly()), method(GetLoadSeriesInputSchema, NodeLoadSeriesSchema);
|
|
43946
|
-
method(object({
|
|
43947
|
-
sourceUrl: string(),
|
|
43948
|
-
metadata: ModelConvertMetadataSchema,
|
|
43949
|
-
targets: array(ConvertTargetSchema).min(1).readonly(),
|
|
43950
|
-
calibrationRef: string().optional(),
|
|
43951
|
-
sessionId: string().optional()
|
|
43952
|
-
}), ConvertResultSchema, {
|
|
43953
|
-
kind: "mutation",
|
|
43954
|
-
auth: "admin",
|
|
43955
|
-
timeoutMs: 6e5
|
|
43956
|
-
});
|
|
43957
|
-
method(object({
|
|
43958
|
-
targetNodeId: string(),
|
|
43959
|
-
modelId: string(),
|
|
43960
|
-
format: _enum(MODEL_FORMATS),
|
|
43961
|
-
entry: ModelCatalogEntrySchema
|
|
43962
|
-
}), object({
|
|
43963
|
-
ok: boolean(),
|
|
43964
|
-
/** sha256 of the staged tarball (empty for a hub-local no-op). */
|
|
43965
|
-
sha256: string(),
|
|
43966
|
-
bytes: number(),
|
|
43967
|
-
/** The target node's modelsDir the artifact landed in. */
|
|
43968
|
-
path: string()
|
|
43969
|
-
}), {
|
|
43970
|
-
kind: "mutation",
|
|
43971
|
-
auth: "admin"
|
|
43972
|
-
});
|
|
43973
|
-
var MotionRegionSchema = object({
|
|
43974
|
-
bbox: BoundingBoxSchema,
|
|
43975
|
-
pixelCount: number(),
|
|
43976
|
-
intensity: number()
|
|
43977
|
-
});
|
|
43978
|
-
var MotionAnalysisResultSchema = object({
|
|
43979
|
-
detected: boolean(),
|
|
43980
|
-
regionCount: number(),
|
|
43981
|
-
/** Regions passing minArea filter — used for pipeline triggering. */
|
|
43982
|
-
regions: array(MotionRegionSchema).readonly(),
|
|
43983
|
-
/** All raw regions from CCL before minArea filter — used for UI debug overlay. */
|
|
43984
|
-
rawRegions: array(MotionRegionSchema).readonly(),
|
|
43985
|
-
frameWidth: number(),
|
|
43986
|
-
frameHeight: number(),
|
|
43987
|
-
analysisMs: number()
|
|
43988
|
-
});
|
|
43989
|
-
DeviceType.Camera, method(object({
|
|
43990
|
-
deviceId: number(),
|
|
43991
|
-
frame: FrameInputSchema.optional(),
|
|
43992
|
-
frameHandle: FrameHandleSchema.optional()
|
|
43993
|
-
}), MotionAnalysisResultSchema, {
|
|
43994
|
-
role: "admin",
|
|
43995
|
-
kind: "mutation"
|
|
43996
|
-
}), method(object({ deviceId: number() }), _void(), {
|
|
43997
|
-
role: "admin",
|
|
43998
|
-
kind: "mutation"
|
|
43999
|
-
}), method(_void(), _void(), {
|
|
44000
|
-
role: "admin",
|
|
44001
|
-
kind: "mutation"
|
|
44002
|
-
}), object({
|
|
44003
|
-
deviceId: number(),
|
|
44004
|
-
detected: boolean(),
|
|
44005
|
-
regionCount: number()
|
|
44006
|
-
});
|
|
44007
|
-
/**
|
|
44008
|
-
* `mqtt-broker` — broker-registry cap.
|
|
44009
|
-
*
|
|
44010
|
-
* NOT a pub/sub proxy. The cap exposes (a) a registry of configured
|
|
44011
|
-
* MQTT brokers (external + optionally an embedded `aedes`-backed one)
|
|
44012
|
-
* and (b) the connection details a consumer addon needs to spin up
|
|
44013
|
-
* its OWN `mqtt.js` client.
|
|
44014
|
-
*
|
|
44015
|
-
* Why: pub/sub routing over the system event-bus loses fidelity
|
|
44016
|
-
* (callback shape, QoS guarantees, will/retain semantics) and adds
|
|
44017
|
-
* refcount bookkeeping that addons would rather own themselves. The
|
|
44018
|
-
* canonical consumer needs raw `mqtt.js`
|
|
44019
|
-
* features anyway — give it the connection config, get out of the way.
|
|
44020
|
-
*
|
|
44021
|
-
* Consumer flow:
|
|
44022
|
-
* const cfg = await ctx.api.mqttBroker.getBrokerConfig({ id })
|
|
44023
|
-
* const client = mqtt.connect(cfg.url, { username: cfg.username, … })
|
|
44024
|
-
* client.subscribe('zigbee2mqtt/+')
|
|
44025
|
-
*
|
|
44026
|
-
* Collection mode: multiple brokers (e.g. one local mosquitto + one
|
|
44027
|
-
* cloud bridge). The "embedded" entry (when present) is just another
|
|
44028
|
-
* broker in the registry — its lifecycle is owned by the addon that
|
|
44029
|
-
* spawned it.
|
|
44030
|
-
*/
|
|
44031
|
-
var BrokerKindSchema = _enum(["external", "embedded"]);
|
|
44032
|
-
/**
|
|
44033
|
-
* Broker live-probe status.
|
|
44034
|
-
*
|
|
44035
|
-
* - `connected` — last probe completed a clean CONNACK
|
|
44036
|
-
* - `disconnected` — no probe has run yet (cold cache)
|
|
44037
|
-
* - `auth-failed` — CONNACK refused with auth error (RC 4 / 5)
|
|
44038
|
-
* - `unreachable` — TCP connect timed out / refused
|
|
44039
|
-
* - `tls-error` — TLS handshake failed (cert / SNI / cipher)
|
|
44040
|
-
*/
|
|
44041
|
-
var BrokerStatusSchema$1 = _enum([
|
|
44042
|
-
"connected",
|
|
44043
|
-
"disconnected",
|
|
44044
|
-
"auth-failed",
|
|
44045
|
-
"unreachable",
|
|
44046
|
-
"tls-error"
|
|
44047
|
-
]);
|
|
44048
|
-
var BrokerInfoSchema$1 = object({
|
|
44049
|
-
id: string(),
|
|
44050
|
-
name: string(),
|
|
44051
|
-
url: string(),
|
|
44052
|
-
kind: BrokerKindSchema,
|
|
44053
|
-
status: BrokerStatusSchema$1,
|
|
44054
|
-
latencyMs: number().nullable(),
|
|
44055
|
-
error: string().optional(),
|
|
44056
|
-
/** Embedded brokers only: number of MQTT clients currently connected. */
|
|
44057
|
-
connectedClients: number().int().nonnegative().optional(),
|
|
44058
|
-
/** Epoch ms of the last live probe (external) or aedes snapshot (embedded). */
|
|
44059
|
-
lastCheckedAt: number().optional()
|
|
44060
|
-
});
|
|
44061
|
-
/**
|
|
44062
|
-
* Connection details — what a consumer needs to call
|
|
44063
|
-
* `mqtt.connect(url, options)`. We split URL + credentials so the
|
|
44064
|
-
* consumer can pass them as `mqtt.connect(url, { username, password })`
|
|
44065
|
-
* instead of stuffing creds into the URL (which leaks them into logs).
|
|
44066
|
-
*/
|
|
44067
|
-
var BrokerConnectionDetailsSchema = object({
|
|
44068
|
-
url: string(),
|
|
44069
|
-
username: string().optional(),
|
|
44070
|
-
password: string().optional(),
|
|
44071
|
-
/**
|
|
44072
|
-
* Suggested prefix for `clientId`. Each consumer should suffix this
|
|
44073
|
-
* with its own discriminator (addon id, instance id) so reconnects
|
|
44074
|
-
* don't kick each other off (MQTT spec: clientId must be unique per
|
|
44075
|
-
* broker).
|
|
44076
|
-
*/
|
|
44077
|
-
clientIdPrefix: string().optional()
|
|
44078
|
-
});
|
|
44079
|
-
var AddBrokerInputSchema = object({
|
|
44080
|
-
name: string().min(1),
|
|
44081
|
-
url: string().regex(/^(mqtt|mqtts|ws|wss):\/\//, "URL must start with mqtt(s):// or ws(s)://"),
|
|
44082
|
-
username: string().optional(),
|
|
44083
|
-
password: string().optional(),
|
|
44084
|
-
clientIdPrefix: string().optional()
|
|
44085
|
-
});
|
|
44086
|
-
var AddBrokerResultSchema = object({ id: string() });
|
|
44087
|
-
var IdInputSchema = object({ id: string() });
|
|
44088
|
-
var TestResultSchema$1 = discriminatedUnion("ok", [object({
|
|
44089
|
-
ok: literal(true),
|
|
44090
|
-
latencyMs: number()
|
|
44091
|
-
}), object({
|
|
44092
|
-
ok: literal(false),
|
|
44093
|
-
error: string()
|
|
44094
|
-
})]);
|
|
44095
|
-
var StartEmbeddedInputSchema = object({
|
|
44096
|
-
port: number().int().min(1).max(65535).default(1883),
|
|
44097
|
-
/** Allow anonymous connect (no username/password). Default: false. */
|
|
44098
|
-
allowAnonymous: boolean().default(false),
|
|
44099
|
-
/** Optional shared username/password for clients. */
|
|
44100
|
-
username: string().optional(),
|
|
44101
|
-
password: string().optional()
|
|
44102
|
-
});
|
|
44103
|
-
var StartEmbeddedResultSchema = object({
|
|
44104
|
-
id: string(),
|
|
44105
|
-
url: string()
|
|
44106
|
-
});
|
|
44107
|
-
var StatusSchema = object({
|
|
44108
|
-
brokerCount: number(),
|
|
44109
|
-
embeddedRunning: boolean()
|
|
44110
|
-
});
|
|
44111
|
-
method(_void(), array(BrokerInfoSchema$1)), method(IdInputSchema, BrokerConnectionDetailsSchema, { auth: "admin" }), method(AddBrokerInputSchema, AddBrokerResultSchema, {
|
|
44112
|
-
kind: "mutation",
|
|
44113
|
-
auth: "admin"
|
|
44114
|
-
}), method(IdInputSchema, _void(), {
|
|
44115
|
-
kind: "mutation",
|
|
44116
|
-
auth: "admin"
|
|
44117
|
-
}), method(IdInputSchema, TestResultSchema$1, {
|
|
44118
|
-
kind: "mutation",
|
|
44119
|
-
auth: "admin"
|
|
44120
|
-
}), method(StartEmbeddedInputSchema, StartEmbeddedResultSchema, {
|
|
44121
|
-
kind: "mutation",
|
|
44122
|
-
auth: "admin"
|
|
44123
|
-
}), method(IdInputSchema, _void(), {
|
|
44124
|
-
kind: "mutation",
|
|
44125
|
-
auth: "admin"
|
|
44126
|
-
}), method(_void(), StatusSchema);
|
|
44127
|
-
var NetworkEndpointSchema = object({
|
|
44128
|
-
url: string(),
|
|
44129
|
-
hostname: string(),
|
|
44130
|
-
port: number(),
|
|
44131
|
-
protocol: _enum(["http", "https"]),
|
|
44132
|
-
/**
|
|
44133
|
-
* Whether this address survives a restart of its provider. `false` = it is
|
|
44134
|
-
* re-issued every time (a Quick tunnel's random `*.trycloudflare.com`); the
|
|
44135
|
-
* hub never selects such an address AUTOMATICALLY for a role (D860), though
|
|
44136
|
-
* it stays visible and an operator may still flag it. Absent = stable: every
|
|
44137
|
-
* provider except a Quick tunnel owns a name that does not change.
|
|
44138
|
-
*/
|
|
44139
|
-
stable: boolean().optional()
|
|
44140
|
-
});
|
|
44141
|
-
object({
|
|
44142
|
-
url: string(),
|
|
44143
|
-
/** Mirrors {@link NetworkEndpointSchema} `stable`; absent = stable. */
|
|
44144
|
-
stable: boolean().optional(),
|
|
44145
|
-
updated: boolean().optional()
|
|
44146
|
-
});
|
|
44147
|
-
var NetworkAccessStatusSchema = object({
|
|
44148
|
-
connected: boolean(),
|
|
44149
|
-
endpoint: NetworkEndpointSchema.nullable(),
|
|
44150
|
-
error: string().optional()
|
|
44151
|
-
});
|
|
44152
|
-
/**
|
|
44153
|
-
* Optional, richer endpoint shape returned by providers that expose
|
|
44154
|
-
* MORE than one ingress concurrently (Tailscale Funnel with mixed
|
|
44155
|
-
* serve+funnel rules, future ngrok multi-tunnel, …). Each entry carries
|
|
44156
|
-
* the originating provider config (mode + sourcePort) so the
|
|
44157
|
-
* orchestrator UI can label rows distinctly. Providers that expose only
|
|
44158
|
-
* one endpoint just omit `listEndpoints` from their provider impl.
|
|
44159
|
-
*/
|
|
44160
|
-
var NetworkEndpointEntrySchema = NetworkEndpointSchema.extend({
|
|
44161
|
-
/**
|
|
44162
|
-
* Stable id within the provider — typically `<mode>-<sourcePort>` so
|
|
44163
|
-
* the orchestrator can dedupe across `listEndpoints` polls.
|
|
44164
|
-
*/
|
|
44165
|
-
id: string(),
|
|
44166
|
-
/** Operator-facing label (mirrors `MeshEndpoint.label`). */
|
|
44167
|
-
label: string(),
|
|
44168
|
-
/** Optional provider-specific mode tag, used for icon/colour in admin UI. */
|
|
44169
|
-
mode: string().optional(),
|
|
44170
|
-
/** Originating local port the ingress fronts (informational). */
|
|
44171
|
-
sourcePort: number().optional()
|
|
44172
|
-
});
|
|
44173
|
-
method(_void(), NetworkEndpointSchema, { kind: "mutation" }), method(_void(), _void(), { kind: "mutation" }), method(_void(), NetworkEndpointSchema.nullable()), method(_void(), NetworkAccessStatusSchema), method(_void(), array(NetworkEndpointEntrySchema).readonly());
|
|
44174
|
-
/**
|
|
44175
|
-
* notification-output — canonical, capability-gated notification delivery.
|
|
44176
|
-
*
|
|
44177
|
-
* Apprise-derived model (see
|
|
44178
|
-
* `docs/superpowers/specs/2026-07-03-notification-output-notifier-matrix.md`):
|
|
44179
|
-
* callers emit ONE canonical `Notification`; each provider declares a
|
|
44180
|
-
* per-kind capability descriptor (`TargetKind`), and the pure degrade
|
|
44181
|
-
* engine (`@camstack/types` `prepareNotification`) transcodes / degrades the
|
|
44182
|
-
* message to what the kind supports — callers never special-case a service.
|
|
44183
|
-
*
|
|
44184
|
-
* DESIGN DECISIONS (locked):
|
|
44185
|
-
* - Target CRUD lives on THIS cap (`upsertTarget` / `deleteTarget` /
|
|
44186
|
-
* `setTargetEnabled`), each provider persisting via the `settings-store`
|
|
44187
|
-
* cap. Rationale: the admin UI needs one uniform surface across the
|
|
44188
|
-
* notifiers addon AND the HA addon; the addon-`globalSettingsSchema`-array
|
|
44189
|
-
* alternative would fork the UI per addon and cannot host the
|
|
44190
|
-
* discovery→adopt flow.
|
|
44191
|
-
* - `listTargetKinds` / `listTargets` / `discoverTargets` return arrays →
|
|
44192
|
-
* the generated cap-mount auto-`concatCollection`-fans them across every
|
|
44193
|
-
* registered provider (notifiers addon + HA addon) so one catalog is
|
|
44194
|
-
* routable. `send` / `testTarget` / CRUD route to ONE provider by the
|
|
44195
|
-
* `addonId` the generated collection router extracts from the call input.
|
|
44196
|
-
* - `Attachment.bytes` is `Uint8Array`. Transport-safe: superjson (the tRPC
|
|
44197
|
-
* transformer) + UDS MsgPack both round-trip typed arrays — already used by
|
|
44198
|
-
* `storage` / `storage-provider` / `recording` caps over the same path. No
|
|
44199
|
-
* base64 fallback needed.
|
|
44200
|
-
*
|
|
44201
|
-
* TODO (deferred, closed-set change — separate decision): add
|
|
44202
|
-
* `providerKind: 'notify'` so notification providers surface on the unified
|
|
44203
|
-
* admin "Integrations" page.
|
|
44204
|
-
*/
|
|
44205
|
-
/**
|
|
44206
|
-
* Zentik-derived typed-media enum — the superset across every kind. Each
|
|
44207
|
-
* adapter picks what it supports and the degrade engine filters the rest.
|
|
44208
|
-
*/
|
|
44209
|
-
var AttachmentMediaTypeSchema = _enum([
|
|
44210
|
-
"image",
|
|
44211
|
-
"video",
|
|
44212
|
-
"gif",
|
|
44213
|
-
"audio",
|
|
44214
|
-
"icon"
|
|
44215
|
-
]);
|
|
44216
|
-
/**
|
|
44217
|
-
* A single attachment. Exactly one of `url` (remote source, most adapters
|
|
44218
|
-
* prefer this) or `bytes` (inline source; required for Pushover-style
|
|
44219
|
-
* bytes-only kinds) MUST be present — the degrade engine expresses a
|
|
44220
|
-
* url→bytes fetch as a `needsFetch` directive the adapter executes.
|
|
44221
|
-
*/
|
|
44222
|
-
var AttachmentSchema = object({
|
|
44223
|
-
mediaType: AttachmentMediaTypeSchema,
|
|
44224
|
-
url: string().optional(),
|
|
44225
|
-
bytes: _instanceof(Uint8Array).optional(),
|
|
44226
|
-
mime: string().optional(),
|
|
44227
|
-
name: string().optional()
|
|
44228
|
-
}).refine((a) => a.url !== void 0 || a.bytes !== void 0, { message: "Attachment requires either `url` or `bytes`" });
|
|
44229
|
-
var NotificationFormatSchema = _enum([
|
|
44230
|
-
"text",
|
|
44231
|
-
"markdown",
|
|
44232
|
-
"html"
|
|
44233
|
-
]);
|
|
44234
|
-
/**
|
|
44235
|
-
* The CLOSED icon vocabulary an action button may use.
|
|
44236
|
-
*
|
|
44237
|
-
* A closed set, not a free string, and that is the whole point: an arbitrary
|
|
44238
|
-
* icon name is one that ntfy renders, zentik silently drops, and nobody
|
|
44239
|
-
* notices — the same class of gap as a zone vocabulary nothing produced
|
|
44240
|
-
* ([D35](../../../docs/decisions/adr-0035.md)). Every adapter maps this set or
|
|
44241
|
-
* declares `actionIcons: false` and the degrade engine strips the field.
|
|
44242
|
-
*
|
|
44243
|
-
* Named by INTENT, never by glyph. "check" would tie the vocabulary to one
|
|
44244
|
-
* renderer's icon set; "acknowledge" survives an adapter that draws it
|
|
44245
|
-
* differently.
|
|
44246
|
-
*
|
|
44247
|
-
* ── A TOKEN IS NOT A WIRE VALUE ─────────────────────────────────────
|
|
44248
|
-
*
|
|
44249
|
-
* These names are for US. **No adapter may forward one verbatim.** Each maps
|
|
44250
|
-
* the whole set onto its own renderer's vocabulary through a
|
|
44251
|
-
* `Record<NotificationActionIcon, string>` — a Record, never a lookup with a
|
|
44252
|
-
* fallback, so adding a member here fails every adapter's build until someone
|
|
44253
|
-
* decides its glyph, which is the only place that decision can be made
|
|
44254
|
-
* honestly.
|
|
44255
|
-
*
|
|
44256
|
-
* This paragraph is the bug. Zentik declared `actionIcons: true` and passed
|
|
44257
|
-
* `disarm` straight through; iOS feeds that string to
|
|
44258
|
-
* `UNNotificationActionIcon(systemImageName:)`, `disarm` is not an SF Symbol,
|
|
44259
|
-
* and every snooze and alarm button arrived BLANK. A pass-through is not a
|
|
44260
|
-
* mapping, and "the field is documented" is not "the value renders".
|
|
44261
|
-
*
|
|
44262
|
-
* Adding a member is TRAIN-BOUND. The enum lives in the published
|
|
44263
|
-
* `@camstack/server` closure and the cap seam validates against the HUB's copy,
|
|
44264
|
-
* so an addon that emits a token the running hub does not know does not lose an
|
|
44265
|
-
* icon — its whole `send` fails Zod validation and the notification never
|
|
44266
|
-
* arrives. Never emit a new token from an addon before the train carrying it.
|
|
44267
|
-
*/
|
|
44268
|
-
var NotificationActionIconSchema = _enum([
|
|
44269
|
-
"acknowledge",
|
|
44270
|
-
"dismiss",
|
|
44271
|
-
"silence",
|
|
44272
|
-
"snooze",
|
|
44273
|
-
"view",
|
|
44274
|
-
"play",
|
|
44275
|
-
"open",
|
|
44276
|
-
"close",
|
|
44277
|
-
"lock",
|
|
44278
|
-
"unlock",
|
|
44279
|
-
"arm",
|
|
44280
|
-
"arm-home",
|
|
44281
|
-
"arm-away",
|
|
44282
|
-
"arm-night",
|
|
44283
|
-
"disarm",
|
|
44284
|
-
"light",
|
|
44285
|
-
"alert",
|
|
44286
|
-
"camera"
|
|
44287
|
-
]);
|
|
44288
|
-
/** A single tap-through action button. */
|
|
44289
|
-
var NotificationActionSchema = object({
|
|
44290
|
-
id: string(),
|
|
44291
|
-
label: string(),
|
|
44292
|
-
url: string().optional(),
|
|
44293
|
-
/** Dropped by the degrade engine for a kind with `caps.actionIcons: false`. */
|
|
44294
|
-
icon: NotificationActionIconSchema.optional(),
|
|
44295
|
-
/**
|
|
44296
|
-
* Renders in a warning style where the notifier supports it.
|
|
44297
|
-
*
|
|
44298
|
-
* A HINT, never a gate. The callback's authority is its token and nothing
|
|
44299
|
-
* else — see `notification-center/action-token.ts` for what that does and
|
|
44300
|
-
* does not buy.
|
|
44301
|
-
*/
|
|
44302
|
-
destructive: boolean().optional(),
|
|
44303
|
-
/**
|
|
44304
|
-
* How the tap should REACH the url.
|
|
44305
|
-
*
|
|
44306
|
-
* `navigate` (absent, and every button authored before this field) opens it:
|
|
44307
|
-
* the phone leaves the notification and shows whatever the callback returns.
|
|
44308
|
-
* That is right for a button whose answer the operator wants to read.
|
|
44309
|
-
*
|
|
44310
|
-
* `background` fires it as a POST and stays put. It exists for the buttons
|
|
44311
|
-
* whose whole point is not to interrupt — "silence this for 30 minutes" is
|
|
44312
|
-
* an answer to the notification, and being thrown into a browser tab to
|
|
44313
|
-
* confirm it costs more attention than the notification did. A backend that
|
|
44314
|
-
* cannot do a background call renders it as an ordinary link (the adapters
|
|
44315
|
-
* fall back rather than dropping the button), so this is a preference, never
|
|
44316
|
-
* a requirement.
|
|
44317
|
-
*/
|
|
44318
|
-
mode: _enum(["navigate", "background"]).optional()
|
|
44319
|
-
});
|
|
44320
|
-
/** A delivery parameter value: what a notifier declared it takes. */
|
|
44321
|
-
var DeliveryParamValueSchema = union([
|
|
44322
|
-
string(),
|
|
44323
|
-
number(),
|
|
44324
|
-
boolean()
|
|
44325
|
-
]);
|
|
44326
|
-
/**
|
|
44327
|
-
* One extra delivery parameter a notifier KIND declares (D938). A rule that
|
|
44328
|
-
* addresses a target of that kind may set it; a kind that declares nothing is
|
|
44329
|
-
* never handed one. The admin UI derives its control from this descriptor —
|
|
44330
|
-
* no editor knows a service by name.
|
|
44331
|
-
*
|
|
44332
|
-
* Optional fields are `.optional()`, never `.default()` (a Zod default does not
|
|
44333
|
-
* run on the addon cap path).
|
|
44334
|
-
*/
|
|
44335
|
-
var DeliveryParamSchema = object({
|
|
44336
|
-
key: string().min(1),
|
|
44337
|
-
label: string(),
|
|
44338
|
-
/** i18n key of the label, resolved by the declaring addon's namespace. */
|
|
44339
|
-
labelKey: string().optional(),
|
|
44340
|
-
type: _enum([
|
|
44341
|
-
"enum",
|
|
44342
|
-
"number",
|
|
44343
|
-
"boolean",
|
|
44344
|
-
"string"
|
|
44345
|
-
]),
|
|
44346
|
-
/** `enum` only: the closed set of accepted values. */
|
|
44347
|
-
options: array(object({
|
|
44348
|
-
value: string(),
|
|
44349
|
-
label: string()
|
|
44350
|
-
})).optional(),
|
|
44351
|
-
/** `number` only. */
|
|
44352
|
-
min: number().optional(),
|
|
44353
|
-
max: number().optional(),
|
|
44354
|
-
/** What the notifier does when the rule sets nothing; shown as the placeholder. */
|
|
44355
|
-
default: DeliveryParamValueSchema.optional()
|
|
44356
|
-
});
|
|
44357
|
-
/**
|
|
44358
|
-
* The canonical notification. `body` is the only hard field (Apprise model).
|
|
44359
|
-
* `priority` is a 5-level ORDINAL (1=lowest … 3=normal(default) … 5=urgent),
|
|
44360
|
-
* NOT a fixed severity enum — each kind declares its own `caps.levels` and
|
|
44361
|
-
* the adapter maps this ordinal onto its native level. `level?` is an
|
|
44362
|
-
* optional kind-native level id (`emergency`, `silent`, …) that overrides
|
|
44363
|
-
* `priority` for that one target.
|
|
44364
|
-
*/
|
|
44365
|
-
var NotificationSchema = object({
|
|
44366
|
-
body: string(),
|
|
44367
|
-
title: string().optional(),
|
|
44368
|
-
format: NotificationFormatSchema.default("text"),
|
|
44369
|
-
priority: number().int().min(1).max(5).default(3),
|
|
44370
|
-
level: string().optional(),
|
|
44371
|
-
attachments: array(AttachmentSchema).optional(),
|
|
44372
|
-
clickUrl: string().optional(),
|
|
44373
|
-
actions: array(NotificationActionSchema).optional(),
|
|
44374
|
-
sound: string().optional(),
|
|
44375
|
-
ttl: number().optional(),
|
|
44376
|
-
tag: string().optional(),
|
|
44377
|
-
deviceId: number().optional(),
|
|
44378
|
-
eventId: string().optional(),
|
|
44379
|
-
metadata: record(string(), unknown()).optional(),
|
|
44380
|
-
/**
|
|
44381
|
-
* Values for the parameters the target's kind DECLARES in
|
|
44382
|
-
* {@link TargetKindSchema} `deliveryParams`. Already validated against the
|
|
44383
|
-
* declaration by the sender; a notifier reads only the keys it declared.
|
|
44384
|
-
*/
|
|
44385
|
-
delivery: record(string(), DeliveryParamValueSchema).optional()
|
|
44386
|
-
});
|
|
44387
|
-
/** One declared native severity/priority level for a kind. */
|
|
44388
|
-
var TargetKindLevelSchema = object({
|
|
44389
|
-
id: string(),
|
|
44390
|
-
label: string(),
|
|
44391
|
-
/** Which canonical priority (1..5) this level maps to. `null` = qualitative-only. */
|
|
44392
|
-
ordinal: number().int().min(1).max(5).nullable(),
|
|
44393
|
-
flags: object({
|
|
44394
|
-
critical: boolean().optional(),
|
|
44395
|
-
silent: boolean().optional(),
|
|
44396
|
-
noPush: boolean().optional()
|
|
44397
|
-
}).optional(),
|
|
44398
|
-
/** e.g. Pushover `emergency` requires `retry` / `expire`. */
|
|
44399
|
-
requires: array(string()).optional(),
|
|
44400
|
-
description: string().optional()
|
|
44401
|
-
});
|
|
44402
|
-
/** The full capability block consulted before dispatch. */
|
|
44403
|
-
var TargetKindCapsSchema = object({
|
|
44404
|
-
attachments: object({
|
|
44405
|
-
mediaTypes: array(AttachmentMediaTypeSchema),
|
|
44406
|
-
mode: _enum([
|
|
44407
|
-
"url",
|
|
44408
|
-
"bytes",
|
|
44409
|
-
"both"
|
|
44410
|
-
]),
|
|
44411
|
-
max: number().int().nonnegative(),
|
|
44412
|
-
maxBytes: number().int().positive().optional()
|
|
44413
|
-
}),
|
|
44414
|
-
/** Max action buttons (0 = none). */
|
|
44415
|
-
actions: number().int().nonnegative(),
|
|
44416
|
-
/**
|
|
44417
|
-
* Whether this kind renders a per-action ICON.
|
|
44418
|
-
*
|
|
44419
|
-
* `.optional()`, deliberately NOT `.default(false)`: a Zod default does not
|
|
44420
|
-
* run on the addon cap path — three production failures in one day taught
|
|
44421
|
-
* this repo that once. Absent is read as false by the degrade engine, which
|
|
44422
|
-
* is the safe direction: an icon that is not rendered costs nothing, an icon
|
|
44423
|
-
* assumed and dropped costs the operator's trust in the field.
|
|
44424
|
-
*/
|
|
44425
|
-
actionIcons: boolean().optional(),
|
|
44426
|
-
levels: array(TargetKindLevelSchema),
|
|
44427
|
-
format: array(NotificationFormatSchema),
|
|
44428
|
-
clickUrl: boolean(),
|
|
44429
|
-
sound: boolean(),
|
|
44430
|
-
ttl: boolean(),
|
|
44431
|
-
bodyMaxLen: number().int().positive()
|
|
44432
|
-
});
|
|
44433
|
-
/**
|
|
44434
|
-
* `configSchema` is a `ConfigUISchema` tree passed through to the admin
|
|
44435
|
-
* FormBuilder. Stored as `z.unknown()` at the cap seam (mirrors
|
|
44436
|
-
* `device-provider.getChildCreationSchema` `CreationSchemaOutputSchema`) —
|
|
44437
|
-
* the union is large and not meant for runtime validation here; the exported
|
|
44438
|
-
* `TargetKind` type re-tightens `configSchema` to `ConfigUISchema`.
|
|
44439
|
-
*/
|
|
44440
|
-
var ConfigSchemaPassthrough$2 = unknown();
|
|
44441
|
-
var TargetKindSchema = object({
|
|
44442
|
-
kind: string(),
|
|
44443
|
-
label: string(),
|
|
44444
|
-
icon: string(),
|
|
44445
|
-
/** Stamped by each provider so the concat-fanned catalog stays routable. */
|
|
44446
|
-
addonId: string(),
|
|
44447
|
-
/**
|
|
44448
|
-
* URL of the kind's bundled BRAND icon, served by the providing addon over
|
|
44449
|
-
* its own `addon-routes` surface (`/addon/<addonId>/icons/<kind>`). Absent
|
|
44450
|
-
* when the addon bundles no icon for that kind — the client then falls back
|
|
44451
|
-
* to a neutral glyph rather than rendering the raw `icon` NAME as text.
|
|
44452
|
-
*
|
|
44453
|
-
* Root-relative on purpose: it resolves against whatever origin serves a web
|
|
44454
|
-
* client, and a native client joins it onto its own hub base.
|
|
44455
|
-
*
|
|
44456
|
-
* DECLARED here deliberately. It used to travel as an undeclared passthrough
|
|
44457
|
-
* field that survived only because the runtime cap-router forwards provider
|
|
44458
|
-
* output verbatim — so every consumer had to re-declare it by hand to stop
|
|
44459
|
-
* its own Zod parse from stripping it, and the whole arrangement would have
|
|
44460
|
-
* broken silently the moment output validation was tightened anywhere.
|
|
44461
|
-
*/
|
|
44462
|
-
iconUrl: string().optional(),
|
|
44463
|
-
/**
|
|
44464
|
-
* Media type of {@link iconUrl} (`image/svg+xml`, `image/png`, …).
|
|
44465
|
-
*
|
|
44466
|
-
* The server knows this and therefore says it, because the client cannot
|
|
44467
|
-
* safely guess: a React-Native client renders SVG and raster through two
|
|
44468
|
-
* DIFFERENT components (`react-native-svg` vs `expo-image` — expo-image does
|
|
44469
|
-
* not decode SVG on iOS/Android), so without this it silently fell back to a
|
|
44470
|
-
* placeholder glyph for every vector icon while the web build looked fine.
|
|
44471
|
-
*
|
|
44472
|
-
* Absent when {@link iconUrl} is absent, or for a legacy provider that has
|
|
44473
|
-
* not been updated — a client that cannot determine the type should prefer
|
|
44474
|
-
* its raster path, which is the safe default for an unknown image.
|
|
44481
|
+
* Reported because "the last hour" and "the last six hours" are different
|
|
44482
|
+
* questions and an operator must not have to guess which was answered.
|
|
44475
44483
|
*/
|
|
44476
|
-
|
|
44477
|
-
|
|
44484
|
+
durable: boolean()
|
|
44485
|
+
});
|
|
44486
|
+
var GetLoadSeriesInputSchema = object({
|
|
44478
44487
|
/**
|
|
44479
|
-
* The
|
|
44480
|
-
* base URL, instance, chat, recipient). A save that changes any of them
|
|
44481
|
-
* while leaving a secret redacted is refused by the provider (D634), so an
|
|
44482
|
-
* editor uses this to ask for the secret on exactly those edits instead of
|
|
44483
|
-
* on every edit.
|
|
44488
|
+
* The node whose series is wanted.
|
|
44484
44489
|
*
|
|
44485
|
-
*
|
|
44486
|
-
*
|
|
44487
|
-
*
|
|
44490
|
+
* NOT named `nodeId`: the generated cap router strips a top-level
|
|
44491
|
+
* `nodeId` from every method input and uses it to ROUTE the call to
|
|
44492
|
+
* that node's provider (`generated-cap-routers.ts`). A series target
|
|
44493
|
+
* called `nodeId` would silently become a routing pin and never reach
|
|
44494
|
+
* the provider. The hub holds every node it hears from, so the
|
|
44495
|
+
* ordinary call is unpinned — answered by the hub, for any node.
|
|
44488
44496
|
*/
|
|
44489
|
-
|
|
44490
|
-
supportsDiscovery: boolean(),
|
|
44497
|
+
forNodeId: string(),
|
|
44491
44498
|
/**
|
|
44492
|
-
*
|
|
44493
|
-
*
|
|
44499
|
+
* EXCLUSIVE lower bound. A caller passes the newest `atMs` it already
|
|
44500
|
+
* holds and receives only what it is missing, so seeding a live chart
|
|
44501
|
+
* from this method cannot double a point already drawn.
|
|
44494
44502
|
*/
|
|
44495
|
-
|
|
44496
|
-
|
|
44503
|
+
sinceMs: number().optional(),
|
|
44504
|
+
/**
|
|
44505
|
+
* Most points the caller wants PER FUNCTION. The window is reduced to fit,
|
|
44506
|
+
* preserving min and max per bucket.
|
|
44507
|
+
*
|
|
44508
|
+
* Absent means NO reduction — legitimate for a short window and a trap for a
|
|
44509
|
+
* long one, which is why a chart passes its own pixel width.
|
|
44510
|
+
*/
|
|
44511
|
+
maxPoints: number().int().positive().optional()
|
|
44512
|
+
});
|
|
44513
|
+
var SystemMetricsSchema = object({
|
|
44514
|
+
cpuPercent: number(),
|
|
44515
|
+
/** `null` when the memory sample failed or was not taken yet (D393). */
|
|
44516
|
+
memoryPercent: number().nullable(),
|
|
44517
|
+
memoryUsedMB: number().nullable(),
|
|
44518
|
+
memoryTotalMB: number(),
|
|
44519
|
+
diskPercent: number().optional(),
|
|
44520
|
+
temperature: number().optional(),
|
|
44521
|
+
gpuPercent: number().optional(),
|
|
44522
|
+
gpuMemoryPercent: number().optional()
|
|
44523
|
+
});
|
|
44524
|
+
method(_void(), SystemResourceSnapshotSchema), method(_void(), SystemResourceSnapshotSchema.nullable()), method(_void(), SystemMetricsSchema), method(object({ dirPath: string() }), DiskSpaceInfoSchema), method(_void(), MetricsGpuInfoSchema.nullable()), method(_void(), number().nullable()), method(object({ pids: array(number()) }), array(PidResourceStatsSchema)), method(_void(), array(AddonInstanceSchema).readonly()), method(object({ addonId: string() }), PidResourceStatsSchema.nullable()), method(_void(), array(NodeProcessSchema).readonly()), method(GetLoadSeriesInputSchema, NodeLoadSeriesSchema);
|
|
44525
|
+
method(object({
|
|
44526
|
+
sourceUrl: string(),
|
|
44527
|
+
metadata: ModelConvertMetadataSchema,
|
|
44528
|
+
targets: array(ConvertTargetSchema).min(1).readonly(),
|
|
44529
|
+
calibrationRef: string().optional(),
|
|
44530
|
+
sessionId: string().optional()
|
|
44531
|
+
}), ConvertResultSchema, {
|
|
44532
|
+
kind: "mutation",
|
|
44533
|
+
auth: "admin",
|
|
44534
|
+
timeoutMs: 6e5
|
|
44535
|
+
});
|
|
44536
|
+
method(object({
|
|
44537
|
+
targetNodeId: string(),
|
|
44538
|
+
modelId: string(),
|
|
44539
|
+
format: _enum(MODEL_FORMATS),
|
|
44540
|
+
entry: ModelCatalogEntrySchema
|
|
44541
|
+
}), object({
|
|
44542
|
+
ok: boolean(),
|
|
44543
|
+
/** sha256 of the staged tarball (empty for a hub-local no-op). */
|
|
44544
|
+
sha256: string(),
|
|
44545
|
+
bytes: number(),
|
|
44546
|
+
/** The target node's modelsDir the artifact landed in. */
|
|
44547
|
+
path: string()
|
|
44548
|
+
}), {
|
|
44549
|
+
kind: "mutation",
|
|
44550
|
+
auth: "admin"
|
|
44551
|
+
});
|
|
44552
|
+
var MotionRegionSchema = object({
|
|
44553
|
+
bbox: BoundingBoxSchema,
|
|
44554
|
+
pixelCount: number(),
|
|
44555
|
+
intensity: number()
|
|
44556
|
+
});
|
|
44557
|
+
var MotionAnalysisResultSchema = object({
|
|
44558
|
+
detected: boolean(),
|
|
44559
|
+
regionCount: number(),
|
|
44560
|
+
/** Regions passing minArea filter — used for pipeline triggering. */
|
|
44561
|
+
regions: array(MotionRegionSchema).readonly(),
|
|
44562
|
+
/** All raw regions from CCL before minArea filter — used for UI debug overlay. */
|
|
44563
|
+
rawRegions: array(MotionRegionSchema).readonly(),
|
|
44564
|
+
frameWidth: number(),
|
|
44565
|
+
frameHeight: number(),
|
|
44566
|
+
analysisMs: number()
|
|
44567
|
+
});
|
|
44568
|
+
DeviceType.Camera, method(object({
|
|
44569
|
+
deviceId: number(),
|
|
44570
|
+
frame: FrameInputSchema.optional(),
|
|
44571
|
+
frameHandle: FrameHandleSchema.optional()
|
|
44572
|
+
}), MotionAnalysisResultSchema, {
|
|
44573
|
+
role: "admin",
|
|
44574
|
+
kind: "mutation"
|
|
44575
|
+
}), method(object({ deviceId: number() }), _void(), {
|
|
44576
|
+
role: "admin",
|
|
44577
|
+
kind: "mutation"
|
|
44578
|
+
}), method(_void(), _void(), {
|
|
44579
|
+
role: "admin",
|
|
44580
|
+
kind: "mutation"
|
|
44581
|
+
}), object({
|
|
44582
|
+
deviceId: number(),
|
|
44583
|
+
detected: boolean(),
|
|
44584
|
+
regionCount: number()
|
|
44497
44585
|
});
|
|
44498
44586
|
/**
|
|
44499
|
-
*
|
|
44500
|
-
*
|
|
44501
|
-
*
|
|
44587
|
+
* `mqtt-broker` — broker-registry cap.
|
|
44588
|
+
*
|
|
44589
|
+
* NOT a pub/sub proxy. The cap exposes (a) a registry of configured
|
|
44590
|
+
* MQTT brokers (external + optionally an embedded `aedes`-backed one)
|
|
44591
|
+
* and (b) the connection details a consumer addon needs to spin up
|
|
44592
|
+
* its OWN `mqtt.js` client.
|
|
44593
|
+
*
|
|
44594
|
+
* Why: pub/sub routing over the system event-bus loses fidelity
|
|
44595
|
+
* (callback shape, QoS guarantees, will/retain semantics) and adds
|
|
44596
|
+
* refcount bookkeeping that addons would rather own themselves. The
|
|
44597
|
+
* canonical consumer needs raw `mqtt.js`
|
|
44598
|
+
* features anyway — give it the connection config, get out of the way.
|
|
44599
|
+
*
|
|
44600
|
+
* Consumer flow:
|
|
44601
|
+
* const cfg = await ctx.api.mqttBroker.getBrokerConfig({ id })
|
|
44602
|
+
* const client = mqtt.connect(cfg.url, { username: cfg.username, … })
|
|
44603
|
+
* client.subscribe('zigbee2mqtt/+')
|
|
44604
|
+
*
|
|
44605
|
+
* Collection mode: multiple brokers (e.g. one local mosquitto + one
|
|
44606
|
+
* cloud bridge). The "embedded" entry (when present) is just another
|
|
44607
|
+
* broker in the registry — its lifecycle is owned by the addon that
|
|
44608
|
+
* spawned it.
|
|
44502
44609
|
*/
|
|
44503
|
-
var
|
|
44610
|
+
var BrokerKindSchema = _enum(["external", "embedded"]);
|
|
44611
|
+
/**
|
|
44612
|
+
* Broker live-probe status.
|
|
44613
|
+
*
|
|
44614
|
+
* - `connected` — last probe completed a clean CONNACK
|
|
44615
|
+
* - `disconnected` — no probe has run yet (cold cache)
|
|
44616
|
+
* - `auth-failed` — CONNACK refused with auth error (RC 4 / 5)
|
|
44617
|
+
* - `unreachable` — TCP connect timed out / refused
|
|
44618
|
+
* - `tls-error` — TLS handshake failed (cert / SNI / cipher)
|
|
44619
|
+
*/
|
|
44620
|
+
var BrokerStatusSchema$1 = _enum([
|
|
44621
|
+
"connected",
|
|
44622
|
+
"disconnected",
|
|
44623
|
+
"auth-failed",
|
|
44624
|
+
"unreachable",
|
|
44625
|
+
"tls-error"
|
|
44626
|
+
]);
|
|
44627
|
+
var BrokerInfoSchema$1 = object({
|
|
44504
44628
|
id: string(),
|
|
44505
44629
|
name: string(),
|
|
44506
|
-
|
|
44507
|
-
|
|
44508
|
-
|
|
44509
|
-
|
|
44510
|
-
});
|
|
44511
|
-
/** A discovery-surfaced candidate (config is partial + non-secret). */
|
|
44512
|
-
var DiscoveredTargetSchema = object({
|
|
44513
|
-
kind: string(),
|
|
44514
|
-
suggestedName: string(),
|
|
44515
|
-
config: record(string(), unknown())
|
|
44516
|
-
});
|
|
44517
|
-
/** The degrade engine's report — what was resolved / dropped / degraded. */
|
|
44518
|
-
var RenderedAsSchema = object({
|
|
44519
|
-
level: string(),
|
|
44520
|
-
format: NotificationFormatSchema,
|
|
44521
|
-
attachmentsSent: number().int().nonnegative(),
|
|
44522
|
-
actionsSent: number().int().nonnegative(),
|
|
44523
|
-
truncated: boolean(),
|
|
44524
|
-
dropped: array(string())
|
|
44525
|
-
});
|
|
44526
|
-
var SendResultSchema = object({
|
|
44527
|
-
success: boolean(),
|
|
44630
|
+
url: string(),
|
|
44631
|
+
kind: BrokerKindSchema,
|
|
44632
|
+
status: BrokerStatusSchema$1,
|
|
44633
|
+
latencyMs: number().nullable(),
|
|
44528
44634
|
error: string().optional(),
|
|
44529
|
-
|
|
44635
|
+
/** Embedded brokers only: number of MQTT clients currently connected. */
|
|
44636
|
+
connectedClients: number().int().nonnegative().optional(),
|
|
44637
|
+
/** Epoch ms of the last live probe (external) or aedes snapshot (embedded). */
|
|
44638
|
+
lastCheckedAt: number().optional()
|
|
44530
44639
|
});
|
|
44531
|
-
/** Same shape as SendResult — kept as a distinct name for the test panel. */
|
|
44532
|
-
var TestResultSchema = SendResultSchema;
|
|
44533
44640
|
/**
|
|
44534
|
-
*
|
|
44535
|
-
* `
|
|
44641
|
+
* Connection details — what a consumer needs to call
|
|
44642
|
+
* `mqtt.connect(url, options)`. We split URL + credentials so the
|
|
44643
|
+
* consumer can pass them as `mqtt.connect(url, { username, password })`
|
|
44644
|
+
* instead of stuffing creds into the URL (which leaks them into logs).
|
|
44536
44645
|
*/
|
|
44537
|
-
var
|
|
44538
|
-
|
|
44539
|
-
|
|
44540
|
-
|
|
44541
|
-
stateInstance: string().optional(),
|
|
44542
|
-
error: string().optional()
|
|
44543
|
-
});
|
|
44544
|
-
method(object({}), array(TargetKindSchema)), method(object({}), array(TargetSchema), { auth: "admin" }), method(object({ targetId: string() }), TargetSchema, { auth: "admin" }), method(object({
|
|
44545
|
-
kind: string(),
|
|
44546
|
-
config: record(string(), unknown()).optional(),
|
|
44646
|
+
var BrokerConnectionDetailsSchema = object({
|
|
44647
|
+
url: string(),
|
|
44648
|
+
username: string().optional(),
|
|
44649
|
+
password: string().optional(),
|
|
44547
44650
|
/**
|
|
44548
|
-
*
|
|
44549
|
-
*
|
|
44550
|
-
*
|
|
44651
|
+
* Suggested prefix for `clientId`. Each consumer should suffix this
|
|
44652
|
+
* with its own discriminator (addon id, instance id) so reconnects
|
|
44653
|
+
* don't kick each other off (MQTT spec: clientId must be unique per
|
|
44654
|
+
* broker).
|
|
44551
44655
|
*/
|
|
44552
|
-
|
|
44553
|
-
})
|
|
44554
|
-
|
|
44555
|
-
|
|
44556
|
-
|
|
44557
|
-
|
|
44558
|
-
|
|
44559
|
-
|
|
44560
|
-
|
|
44561
|
-
|
|
44562
|
-
|
|
44563
|
-
|
|
44564
|
-
|
|
44656
|
+
clientIdPrefix: string().optional()
|
|
44657
|
+
});
|
|
44658
|
+
var AddBrokerInputSchema = object({
|
|
44659
|
+
name: string().min(1),
|
|
44660
|
+
url: string().regex(/^(mqtt|mqtts|ws|wss):\/\//, "URL must start with mqtt(s):// or ws(s)://"),
|
|
44661
|
+
username: string().optional(),
|
|
44662
|
+
password: string().optional(),
|
|
44663
|
+
clientIdPrefix: string().optional()
|
|
44664
|
+
});
|
|
44665
|
+
var AddBrokerResultSchema = object({ id: string() });
|
|
44666
|
+
var IdInputSchema = object({ id: string() });
|
|
44667
|
+
var TestResultSchema$1 = discriminatedUnion("ok", [object({
|
|
44668
|
+
ok: literal(true),
|
|
44669
|
+
latencyMs: number()
|
|
44670
|
+
}), object({
|
|
44671
|
+
ok: literal(false),
|
|
44672
|
+
error: string()
|
|
44673
|
+
})]);
|
|
44674
|
+
var StartEmbeddedInputSchema = object({
|
|
44675
|
+
port: number().int().min(1).max(65535).default(1883),
|
|
44676
|
+
/** Allow anonymous connect (no username/password). Default: false. */
|
|
44677
|
+
allowAnonymous: boolean().default(false),
|
|
44678
|
+
/** Optional shared username/password for clients. */
|
|
44679
|
+
username: string().optional(),
|
|
44680
|
+
password: string().optional()
|
|
44681
|
+
});
|
|
44682
|
+
var StartEmbeddedResultSchema = object({
|
|
44683
|
+
id: string(),
|
|
44684
|
+
url: string()
|
|
44685
|
+
});
|
|
44686
|
+
var StatusSchema = object({
|
|
44687
|
+
brokerCount: number(),
|
|
44688
|
+
embeddedRunning: boolean()
|
|
44689
|
+
});
|
|
44690
|
+
method(_void(), array(BrokerInfoSchema$1)), method(IdInputSchema, BrokerConnectionDetailsSchema, { auth: "admin" }), method(AddBrokerInputSchema, AddBrokerResultSchema, {
|
|
44565
44691
|
kind: "mutation",
|
|
44566
44692
|
auth: "admin"
|
|
44567
|
-
}), method(
|
|
44568
|
-
targetId: string(),
|
|
44569
|
-
sample: NotificationSchema.optional()
|
|
44570
|
-
}), TestResultSchema, {
|
|
44693
|
+
}), method(IdInputSchema, _void(), {
|
|
44571
44694
|
kind: "mutation",
|
|
44572
44695
|
auth: "admin"
|
|
44573
|
-
}), method(
|
|
44574
|
-
target: TargetSchema,
|
|
44575
|
-
/**
|
|
44576
|
-
* Duplicate flow: create a NEW target id while copying secrets from an
|
|
44577
|
-
* existing row. The UI never holds the stored token; blank / redacted
|
|
44578
|
-
* password fields are restored from this source (D634 still applies if
|
|
44579
|
-
* destinations diverge without a re-typed secret).
|
|
44580
|
-
*/
|
|
44581
|
-
cloneSecretsFrom: string().optional()
|
|
44582
|
-
}), TargetSchema, {
|
|
44696
|
+
}), method(IdInputSchema, TestResultSchema$1, {
|
|
44583
44697
|
kind: "mutation",
|
|
44584
44698
|
auth: "admin"
|
|
44585
|
-
}), method(
|
|
44699
|
+
}), method(StartEmbeddedInputSchema, StartEmbeddedResultSchema, {
|
|
44586
44700
|
kind: "mutation",
|
|
44587
44701
|
auth: "admin"
|
|
44588
|
-
}), method(
|
|
44589
|
-
targetId: string(),
|
|
44590
|
-
enabled: boolean()
|
|
44591
|
-
}), _void(), {
|
|
44702
|
+
}), method(IdInputSchema, _void(), {
|
|
44592
44703
|
kind: "mutation",
|
|
44593
44704
|
auth: "admin"
|
|
44705
|
+
}), method(_void(), StatusSchema);
|
|
44706
|
+
var NetworkEndpointSchema = object({
|
|
44707
|
+
url: string(),
|
|
44708
|
+
hostname: string(),
|
|
44709
|
+
port: number(),
|
|
44710
|
+
protocol: _enum(["http", "https"]),
|
|
44711
|
+
/**
|
|
44712
|
+
* Whether this address survives a restart of its provider. `false` = it is
|
|
44713
|
+
* re-issued every time (a Quick tunnel's random `*.trycloudflare.com`); the
|
|
44714
|
+
* hub never selects such an address AUTOMATICALLY for a role (D860), though
|
|
44715
|
+
* it stays visible and an operator may still flag it. Absent = stable: every
|
|
44716
|
+
* provider except a Quick tunnel owns a name that does not change.
|
|
44717
|
+
*/
|
|
44718
|
+
stable: boolean().optional()
|
|
44719
|
+
});
|
|
44720
|
+
object({
|
|
44721
|
+
url: string(),
|
|
44722
|
+
/** Mirrors {@link NetworkEndpointSchema} `stable`; absent = stable. */
|
|
44723
|
+
stable: boolean().optional(),
|
|
44724
|
+
updated: boolean().optional()
|
|
44725
|
+
});
|
|
44726
|
+
var NetworkAccessStatusSchema = object({
|
|
44727
|
+
connected: boolean(),
|
|
44728
|
+
endpoint: NetworkEndpointSchema.nullable(),
|
|
44729
|
+
error: string().optional()
|
|
44730
|
+
});
|
|
44731
|
+
/**
|
|
44732
|
+
* Optional, richer endpoint shape returned by providers that expose
|
|
44733
|
+
* MORE than one ingress concurrently (Tailscale Funnel with mixed
|
|
44734
|
+
* serve+funnel rules, future ngrok multi-tunnel, …). Each entry carries
|
|
44735
|
+
* the originating provider config (mode + sourcePort) so the
|
|
44736
|
+
* orchestrator UI can label rows distinctly. Providers that expose only
|
|
44737
|
+
* one endpoint just omit `listEndpoints` from their provider impl.
|
|
44738
|
+
*/
|
|
44739
|
+
var NetworkEndpointEntrySchema = NetworkEndpointSchema.extend({
|
|
44740
|
+
/**
|
|
44741
|
+
* Stable id within the provider — typically `<mode>-<sourcePort>` so
|
|
44742
|
+
* the orchestrator can dedupe across `listEndpoints` polls.
|
|
44743
|
+
*/
|
|
44744
|
+
id: string(),
|
|
44745
|
+
/** Operator-facing label (mirrors `MeshEndpoint.label`). */
|
|
44746
|
+
label: string(),
|
|
44747
|
+
/** Optional provider-specific mode tag, used for icon/colour in admin UI. */
|
|
44748
|
+
mode: string().optional(),
|
|
44749
|
+
/** Originating local port the ingress fronts (informational). */
|
|
44750
|
+
sourcePort: number().optional()
|
|
44594
44751
|
});
|
|
44752
|
+
method(_void(), NetworkEndpointSchema, { kind: "mutation" }), method(_void(), _void(), { kind: "mutation" }), method(_void(), NetworkEndpointSchema.nullable()), method(_void(), NetworkAccessStatusSchema), method(_void(), array(NetworkEndpointEntrySchema).readonly());
|
|
44595
44753
|
var AUDIO_MACRO_LABELS = [
|
|
44596
44754
|
{
|
|
44597
44755
|
id: "speech",
|
|
@@ -50992,14 +51150,6 @@ var EngineProvisioningSchema = object({
|
|
|
50992
51150
|
*/
|
|
50993
51151
|
configIssues: array(string()).optional()
|
|
50994
51152
|
});
|
|
50995
|
-
var PipelineStepInputSchema = lazy(() => object({
|
|
50996
|
-
addonId: string(),
|
|
50997
|
-
modelId: string().optional(),
|
|
50998
|
-
enabled: boolean().default(true),
|
|
50999
|
-
children: array(PipelineStepInputSchema).optional(),
|
|
51000
|
-
settings: record(string(), unknown()).optional(),
|
|
51001
|
-
jumpDeviceKey: string().optional()
|
|
51002
|
-
}));
|
|
51003
51153
|
var ModelSubstitutionSchema = object({
|
|
51004
51154
|
addonId: string(),
|
|
51005
51155
|
chosen: string(),
|
|
@@ -51078,7 +51228,6 @@ var ConfigUISchemaBridge = custom();
|
|
|
51078
51228
|
var ConfigUISchemaNullableBridge = custom();
|
|
51079
51229
|
var InferenceCapabilitiesBridge = custom();
|
|
51080
51230
|
var ModelAvailabilityListBridge = custom();
|
|
51081
|
-
var PipelineRunResultBridge = custom();
|
|
51082
51231
|
method(_void(), array(PipelineEngineChoiceSchema)), method(_void(), PipelineEngineChoiceSchema), method(object({ nodeId: string() }), EngineProvisioningSchema), method(_void(), record(string(), object({
|
|
51083
51232
|
modelId: string(),
|
|
51084
51233
|
settings: record(string(), unknown()).readonly()
|
|
@@ -58752,7 +58901,7 @@ object({
|
|
|
58752
58901
|
/** Ms epoch of the last value received from the appliance; 0 = never. */
|
|
58753
58902
|
lastFetchedAt: number()
|
|
58754
58903
|
});
|
|
58755
|
-
var DeviceIdSchema = number().int().nonnegative();
|
|
58904
|
+
var DeviceIdSchema$1 = number().int().nonnegative();
|
|
58756
58905
|
/** A value a program option or setting can take. */
|
|
58757
58906
|
var DishwasherValueSchema = union([
|
|
58758
58907
|
boolean(),
|
|
@@ -58816,77 +58965,77 @@ var DishwasherOptionsSchema = object({
|
|
|
58816
58965
|
options: array(DishwasherOptionDescriptorSchema)
|
|
58817
58966
|
});
|
|
58818
58967
|
DeviceType.Dishwasher, method(object({
|
|
58819
|
-
deviceId: DeviceIdSchema,
|
|
58968
|
+
deviceId: DeviceIdSchema$1,
|
|
58820
58969
|
program: string().min(1).optional(),
|
|
58821
58970
|
options: record(string(), DishwasherValueSchema).optional()
|
|
58822
58971
|
}), _void(), {
|
|
58823
58972
|
kind: "mutation",
|
|
58824
58973
|
auth: "protected"
|
|
58825
|
-
}), method(object({ deviceId: DeviceIdSchema }), _void(), {
|
|
58974
|
+
}), method(object({ deviceId: DeviceIdSchema$1 }), _void(), {
|
|
58826
58975
|
kind: "mutation",
|
|
58827
58976
|
auth: "protected"
|
|
58828
|
-
}), method(object({ deviceId: DeviceIdSchema }), _void(), {
|
|
58977
|
+
}), method(object({ deviceId: DeviceIdSchema$1 }), _void(), {
|
|
58829
58978
|
kind: "mutation",
|
|
58830
58979
|
auth: "protected"
|
|
58831
|
-
}), method(object({ deviceId: DeviceIdSchema }), _void(), {
|
|
58980
|
+
}), method(object({ deviceId: DeviceIdSchema$1 }), _void(), {
|
|
58832
58981
|
kind: "mutation",
|
|
58833
58982
|
auth: "protected"
|
|
58834
58983
|
}), method(object({
|
|
58835
|
-
deviceId: DeviceIdSchema,
|
|
58984
|
+
deviceId: DeviceIdSchema$1,
|
|
58836
58985
|
program: string().min(1)
|
|
58837
58986
|
}), _void(), {
|
|
58838
58987
|
kind: "mutation",
|
|
58839
58988
|
auth: "protected"
|
|
58840
58989
|
}), method(object({
|
|
58841
|
-
deviceId: DeviceIdSchema,
|
|
58990
|
+
deviceId: DeviceIdSchema$1,
|
|
58842
58991
|
on: boolean()
|
|
58843
58992
|
}), _void(), {
|
|
58844
58993
|
kind: "mutation",
|
|
58845
58994
|
auth: "protected"
|
|
58846
58995
|
}), method(object({
|
|
58847
|
-
deviceId: DeviceIdSchema,
|
|
58996
|
+
deviceId: DeviceIdSchema$1,
|
|
58848
58997
|
on: boolean()
|
|
58849
58998
|
}), _void(), {
|
|
58850
58999
|
kind: "mutation",
|
|
58851
59000
|
auth: "protected"
|
|
58852
59001
|
}), method(object({
|
|
58853
|
-
deviceId: DeviceIdSchema,
|
|
59002
|
+
deviceId: DeviceIdSchema$1,
|
|
58854
59003
|
on: boolean()
|
|
58855
59004
|
}), _void(), {
|
|
58856
59005
|
kind: "mutation",
|
|
58857
59006
|
auth: "protected"
|
|
58858
59007
|
}), method(object({
|
|
58859
|
-
deviceId: DeviceIdSchema,
|
|
59008
|
+
deviceId: DeviceIdSchema$1,
|
|
58860
59009
|
on: boolean()
|
|
58861
59010
|
}), _void(), {
|
|
58862
59011
|
kind: "mutation",
|
|
58863
59012
|
auth: "protected"
|
|
58864
59013
|
}), method(object({
|
|
58865
|
-
deviceId: DeviceIdSchema,
|
|
59014
|
+
deviceId: DeviceIdSchema$1,
|
|
58866
59015
|
on: boolean()
|
|
58867
59016
|
}), _void(), {
|
|
58868
59017
|
kind: "mutation",
|
|
58869
59018
|
auth: "protected"
|
|
58870
59019
|
}), method(object({
|
|
58871
|
-
deviceId: DeviceIdSchema,
|
|
59020
|
+
deviceId: DeviceIdSchema$1,
|
|
58872
59021
|
on: boolean()
|
|
58873
59022
|
}), _void(), {
|
|
58874
59023
|
kind: "mutation",
|
|
58875
59024
|
auth: "protected"
|
|
58876
59025
|
}), method(object({
|
|
58877
|
-
deviceId: DeviceIdSchema,
|
|
59026
|
+
deviceId: DeviceIdSchema$1,
|
|
58878
59027
|
on: boolean()
|
|
58879
59028
|
}), _void(), {
|
|
58880
59029
|
kind: "mutation",
|
|
58881
59030
|
auth: "protected"
|
|
58882
59031
|
}), method(object({
|
|
58883
|
-
deviceId: DeviceIdSchema,
|
|
59032
|
+
deviceId: DeviceIdSchema$1,
|
|
58884
59033
|
key: string().min(1),
|
|
58885
59034
|
value: DishwasherValueSchema
|
|
58886
59035
|
}), _void(), {
|
|
58887
59036
|
kind: "mutation",
|
|
58888
59037
|
auth: "protected"
|
|
58889
|
-
}), method(object({ deviceId: DeviceIdSchema }), DishwasherOptionsSchema, { auth: "protected" });
|
|
59038
|
+
}), method(object({ deviceId: DeviceIdSchema$1 }), DishwasherOptionsSchema, { auth: "protected" });
|
|
58890
59039
|
DeviceType.Camera;
|
|
58891
59040
|
object({
|
|
58892
59041
|
/** Ms epoch of the last press. null = never observed since this provider started. */
|
|
@@ -61324,7 +61473,8 @@ var TopologyNodeSchema = object({
|
|
|
61324
61473
|
isHub: boolean(),
|
|
61325
61474
|
isOnline: boolean(),
|
|
61326
61475
|
cpuPercent: number(),
|
|
61327
|
-
|
|
61476
|
+
/** `null` when the node's memory read failed or it has not reported one (D393). */
|
|
61477
|
+
memoryPercent: number().nullable(),
|
|
61328
61478
|
uptime: number(),
|
|
61329
61479
|
lastSeen: string(),
|
|
61330
61480
|
localIps: array(string()).readonly(),
|
|
@@ -61859,9 +62009,10 @@ object({
|
|
|
61859
62009
|
* combined reading; per-hopper levels live in `food1`/`food2`. Null when
|
|
61860
62010
|
* the device has not reported yet. */
|
|
61861
62011
|
foodLevel: number().nullable().meta(readingMeta("none")),
|
|
61862
|
-
/** Food in the BOWL
|
|
61863
|
-
* feeder
|
|
61864
|
-
|
|
62012
|
+
/** Food in the BOWL, a mass (stored in kilograms, D944). Reported only by a
|
|
62013
|
+
* feeder with a bowl scale; null when the model has none or its reading is
|
|
62014
|
+
* of an unproven unit. */
|
|
62015
|
+
bowlFood: number().nullable().meta(readingMeta("mass")),
|
|
61865
62016
|
/** True while the pet is eating (`state.eating`). */
|
|
61866
62017
|
eating: boolean(),
|
|
61867
62018
|
/** Whether `markFoodReplenished` does anything on this model. When false
|
|
@@ -61974,6 +62125,64 @@ DeviceType.PetFeeder, method(object({
|
|
|
61974
62125
|
kind: "mutation",
|
|
61975
62126
|
auth: "protected"
|
|
61976
62127
|
});
|
|
62128
|
+
object({
|
|
62129
|
+
/** Water in the tank, 0..100 (%). Null while the source has not reported. */
|
|
62130
|
+
waterLevel: number().min(0).max(100).nullable().meta(readingMeta("percentage")),
|
|
62131
|
+
/** Water in the tank, in litres. Null while the source has not reported. */
|
|
62132
|
+
waterVolume: number().min(0).nullable().meta(readingMeta("volume")),
|
|
62133
|
+
/** True when the tank is empty. Null while unknown. */
|
|
62134
|
+
empty: boolean().nullable(),
|
|
62135
|
+
/** True while the pump is running. Null while unknown. */
|
|
62136
|
+
pumpRunning: boolean().nullable(),
|
|
62137
|
+
/** True when the pump works on an on/off duty cycle rather than continuously. */
|
|
62138
|
+
pumpIntervalEnabled: boolean().nullable(),
|
|
62139
|
+
/** How long the pump runs per cycle, in seconds. */
|
|
62140
|
+
pumpOnTime: number().min(0).nullable().meta(readingMeta("duration")),
|
|
62141
|
+
/** How long the pump rests per cycle, in seconds. */
|
|
62142
|
+
pumpOffTime: number().min(0).nullable().meta(readingMeta("duration")),
|
|
62143
|
+
/** Water drunk in the last drink, in litres. */
|
|
62144
|
+
lastDrink: number().min(0).nullable().meta(readingMeta("volume")),
|
|
62145
|
+
/** Water drunk in the current hour, in litres. */
|
|
62146
|
+
currentHourDrink: number().min(0).nullable().meta(readingMeta("volume")),
|
|
62147
|
+
/** Water drunk over the last 24 hours (rolling), in litres. */
|
|
62148
|
+
last24hDrink: number().min(0).nullable().meta(readingMeta("volume")),
|
|
62149
|
+
/** Water drunk since local midnight, in litres. */
|
|
62150
|
+
todayDrink: number().min(0).nullable().meta(readingMeta("volume")),
|
|
62151
|
+
/** Decoded fault message. Null means healthy; a non-null string is an active fault. */
|
|
62152
|
+
error: string().nullable(),
|
|
62153
|
+
/** Ms epoch when the slice was last refreshed. */
|
|
62154
|
+
lastFetchedAt: number()
|
|
62155
|
+
});
|
|
62156
|
+
var DeviceIdSchema = number().int().nonnegative();
|
|
62157
|
+
var MinutesSchema = number().int().min(0);
|
|
62158
|
+
DeviceType.PetFountain, method(object({
|
|
62159
|
+
deviceId: DeviceIdSchema,
|
|
62160
|
+
on: boolean()
|
|
62161
|
+
}), _void(), {
|
|
62162
|
+
kind: "mutation",
|
|
62163
|
+
auth: "protected"
|
|
62164
|
+
}), method(object({
|
|
62165
|
+
deviceId: DeviceIdSchema,
|
|
62166
|
+
on: boolean()
|
|
62167
|
+
}), _void(), {
|
|
62168
|
+
kind: "mutation",
|
|
62169
|
+
auth: "protected"
|
|
62170
|
+
}), method(object({
|
|
62171
|
+
deviceId: DeviceIdSchema,
|
|
62172
|
+
minutes: MinutesSchema
|
|
62173
|
+
}), _void(), {
|
|
62174
|
+
kind: "mutation",
|
|
62175
|
+
auth: "protected"
|
|
62176
|
+
}), method(object({
|
|
62177
|
+
deviceId: DeviceIdSchema,
|
|
62178
|
+
minutes: MinutesSchema
|
|
62179
|
+
}), _void(), {
|
|
62180
|
+
kind: "mutation",
|
|
62181
|
+
auth: "protected"
|
|
62182
|
+
}), method(object({ deviceId: DeviceIdSchema }), _void(), {
|
|
62183
|
+
kind: "mutation",
|
|
62184
|
+
auth: "protected"
|
|
62185
|
+
});
|
|
61977
62186
|
var VehicleSchema = object({
|
|
61978
62187
|
id: string(),
|
|
61979
62188
|
name: string(),
|
|
@@ -66571,7 +66780,7 @@ discriminatedUnion("kind", [object({
|
|
|
66571
66780
|
})]);
|
|
66572
66781
|
DeviceFeature.FanSpeed, DeviceFeature.FanPreset, DeviceFeature.FanDirection, DeviceFeature.FanOscillating, DeviceFeature.CoverPositionable, DeviceFeature.CoverTilt, DeviceFeature.ValvePositionable, DeviceFeature.MediaPlayerVolume, DeviceFeature.ClimateFanMode;
|
|
66573
66782
|
SOURCE_CAPS.filter((cap) => cap !== "switch" && cap !== "motion");
|
|
66574
|
-
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.EventEmitter, DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Camera, DeviceType.Camera, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
|
|
66783
|
+
DeviceType.Camera, DeviceType.Sensor, DeviceType.Button, DeviceType.Switch, DeviceType.PetFeeder, DeviceType.Container, DeviceType.Thermostat, DeviceType.EventEmitter, DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.PetFountain, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer, DeviceType.Camera, DeviceType.Camera, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.Switch, DeviceType.Light, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.PetFeeder, DeviceType.MediaPlayer, DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.MediaPlayer, DeviceType.WaterHeater, DeviceType.Humidifier, DeviceType.Fan, DeviceType.Climate, DeviceType.Thermostat, DeviceType.PetFeeder;
|
|
66575
66784
|
String.raw`rose\(active(\d+), changed(\d+), (\d+(?:\.\d+)?)\)`;
|
|
66576
66785
|
DeviceRole.BinarySensor, DeviceRole.MotionSensor;
|
|
66577
66786
|
new Set(CAP_NAMES);
|
|
@@ -66624,7 +66833,7 @@ var AccessoryKind = {
|
|
|
66624
66833
|
PrivacyMask: DeviceRole.PrivacyMask
|
|
66625
66834
|
};
|
|
66626
66835
|
AccessoryKind.Siren, AccessoryKind.Floodlight, AccessoryKind.Spotlight, AccessoryKind.PirSensor, AccessoryKind.Chime, AccessoryKind.Autotrack, AccessoryKind.Nightvision, AccessoryKind.PrivacyMask;
|
|
66627
|
-
DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Camera, DeviceType.Hub, DeviceType.Switch, DeviceType.Siren, DeviceType.Light, DeviceType.Fan, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer;
|
|
66836
|
+
DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Camera, DeviceType.Hub, DeviceType.Switch, DeviceType.Siren, DeviceType.Light, DeviceType.Fan, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.PetFountain, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer;
|
|
66628
66837
|
new Set(Object.values(DeviceType));
|
|
66629
66838
|
Object.freeze({
|
|
66630
66839
|
"accessories.getStatus": {
|
|
@@ -68559,6 +68768,13 @@ Object.freeze({
|
|
|
68559
68768
|
access: "create",
|
|
68560
68769
|
role: "admin"
|
|
68561
68770
|
},
|
|
68771
|
+
"deviceExport.exposeEntity": {
|
|
68772
|
+
capName: "device-export",
|
|
68773
|
+
capScope: "system",
|
|
68774
|
+
addonId: null,
|
|
68775
|
+
access: "create",
|
|
68776
|
+
role: "admin"
|
|
68777
|
+
},
|
|
68562
68778
|
"deviceExport.getDeviceLiveContribution": {
|
|
68563
68779
|
capName: "device-export",
|
|
68564
68780
|
capScope: "system",
|
|
@@ -68587,6 +68803,13 @@ Object.freeze({
|
|
|
68587
68803
|
access: "view",
|
|
68588
68804
|
role: "admin"
|
|
68589
68805
|
},
|
|
68806
|
+
"deviceExport.listExposedEntities": {
|
|
68807
|
+
capName: "device-export",
|
|
68808
|
+
capScope: "system",
|
|
68809
|
+
addonId: null,
|
|
68810
|
+
access: "view",
|
|
68811
|
+
role: "admin"
|
|
68812
|
+
},
|
|
68590
68813
|
"deviceExport.listSupportedDeviceKinds": {
|
|
68591
68814
|
capName: "device-export",
|
|
68592
68815
|
capScope: "system",
|
|
@@ -68594,6 +68817,13 @@ Object.freeze({
|
|
|
68594
68817
|
access: "view",
|
|
68595
68818
|
role: "admin"
|
|
68596
68819
|
},
|
|
68820
|
+
"deviceExport.listSupportedEntityKinds": {
|
|
68821
|
+
capName: "device-export",
|
|
68822
|
+
capScope: "system",
|
|
68823
|
+
addonId: null,
|
|
68824
|
+
access: "view",
|
|
68825
|
+
role: "admin"
|
|
68826
|
+
},
|
|
68597
68827
|
"deviceExport.unexposeDevice": {
|
|
68598
68828
|
capName: "device-export",
|
|
68599
68829
|
capScope: "system",
|
|
@@ -68601,6 +68831,13 @@ Object.freeze({
|
|
|
68601
68831
|
access: "create",
|
|
68602
68832
|
role: "admin"
|
|
68603
68833
|
},
|
|
68834
|
+
"deviceExport.unexposeEntity": {
|
|
68835
|
+
capName: "device-export",
|
|
68836
|
+
capScope: "system",
|
|
68837
|
+
addonId: null,
|
|
68838
|
+
access: "create",
|
|
68839
|
+
role: "admin"
|
|
68840
|
+
},
|
|
68604
68841
|
"deviceExtension.listCandidates": {
|
|
68605
68842
|
capName: "device-extension",
|
|
68606
68843
|
capScope: "device",
|
|
@@ -71422,6 +71659,13 @@ Object.freeze({
|
|
|
71422
71659
|
access: "create",
|
|
71423
71660
|
role: "admin"
|
|
71424
71661
|
},
|
|
71662
|
+
"nodeRemovalHook.onNodeRemoved": {
|
|
71663
|
+
capName: "node-removal-hook",
|
|
71664
|
+
capScope: "system",
|
|
71665
|
+
addonId: null,
|
|
71666
|
+
access: "create",
|
|
71667
|
+
role: "admin"
|
|
71668
|
+
},
|
|
71425
71669
|
"nodes.clusterAddonStatus": {
|
|
71426
71670
|
capName: "nodes",
|
|
71427
71671
|
capScope: "system",
|
|
@@ -72059,6 +72303,48 @@ Object.freeze({
|
|
|
72059
72303
|
access: "create",
|
|
72060
72304
|
role: "viewer"
|
|
72061
72305
|
},
|
|
72306
|
+
"petFountain.getStatus": {
|
|
72307
|
+
capName: "pet-fountain",
|
|
72308
|
+
capScope: "device",
|
|
72309
|
+
addonId: null,
|
|
72310
|
+
access: "view",
|
|
72311
|
+
role: "viewer"
|
|
72312
|
+
},
|
|
72313
|
+
"petFountain.resetDailyConsumption": {
|
|
72314
|
+
capName: "pet-fountain",
|
|
72315
|
+
capScope: "device",
|
|
72316
|
+
addonId: null,
|
|
72317
|
+
access: "delete",
|
|
72318
|
+
role: "viewer"
|
|
72319
|
+
},
|
|
72320
|
+
"petFountain.setPump": {
|
|
72321
|
+
capName: "pet-fountain",
|
|
72322
|
+
capScope: "device",
|
|
72323
|
+
addonId: null,
|
|
72324
|
+
access: "create",
|
|
72325
|
+
role: "viewer"
|
|
72326
|
+
},
|
|
72327
|
+
"petFountain.setPumpInterval": {
|
|
72328
|
+
capName: "pet-fountain",
|
|
72329
|
+
capScope: "device",
|
|
72330
|
+
addonId: null,
|
|
72331
|
+
access: "create",
|
|
72332
|
+
role: "viewer"
|
|
72333
|
+
},
|
|
72334
|
+
"petFountain.setPumpOffMinutes": {
|
|
72335
|
+
capName: "pet-fountain",
|
|
72336
|
+
capScope: "device",
|
|
72337
|
+
addonId: null,
|
|
72338
|
+
access: "create",
|
|
72339
|
+
role: "viewer"
|
|
72340
|
+
},
|
|
72341
|
+
"petFountain.setPumpOnMinutes": {
|
|
72342
|
+
capName: "pet-fountain",
|
|
72343
|
+
capScope: "device",
|
|
72344
|
+
addonId: null,
|
|
72345
|
+
access: "create",
|
|
72346
|
+
role: "viewer"
|
|
72347
|
+
},
|
|
72062
72348
|
"pipelineAnalytics.addRetrainFrameFromRecording": {
|
|
72063
72349
|
capName: "pipeline-analytics",
|
|
72064
72350
|
capScope: "device",
|
|
@@ -78541,6 +78827,100 @@ var APPLIANCE_CAP_VOCABULARY = {
|
|
|
78541
78827
|
}
|
|
78542
78828
|
]
|
|
78543
78829
|
},
|
|
78830
|
+
"pet-fountain": {
|
|
78831
|
+
scope: "device",
|
|
78832
|
+
noun: t("Pet fountain", "Fontana per animali"),
|
|
78833
|
+
actions: [
|
|
78834
|
+
{
|
|
78835
|
+
id: "petFountain.pumpOn",
|
|
78836
|
+
method: "setPump",
|
|
78837
|
+
label: t("Pump on", "Pompa accesa"),
|
|
78838
|
+
phrase: t("Start the pump of {device}", "Avvia la pompa di {device}"),
|
|
78839
|
+
icon: "play",
|
|
78840
|
+
args: { on: true }
|
|
78841
|
+
},
|
|
78842
|
+
{
|
|
78843
|
+
id: "petFountain.pumpOff",
|
|
78844
|
+
method: "setPump",
|
|
78845
|
+
label: t("Pump off", "Pompa spenta"),
|
|
78846
|
+
phrase: t("Stop the pump of {device}", "Ferma la pompa di {device}"),
|
|
78847
|
+
icon: "square",
|
|
78848
|
+
args: { on: false }
|
|
78849
|
+
},
|
|
78850
|
+
{
|
|
78851
|
+
id: "petFountain.intervalOn",
|
|
78852
|
+
method: "setPumpInterval",
|
|
78853
|
+
label: t("Pump cycle on", "Ciclo pompa attivo"),
|
|
78854
|
+
phrase: t("Run the pump of {device} on its on/off cycle", "Fai lavorare la pompa di {device} a ciclo acceso/spento"),
|
|
78855
|
+
icon: "timer",
|
|
78856
|
+
args: { on: true }
|
|
78857
|
+
},
|
|
78858
|
+
{
|
|
78859
|
+
id: "petFountain.intervalOff",
|
|
78860
|
+
method: "setPumpInterval",
|
|
78861
|
+
label: t("Pump cycle off", "Ciclo pompa spento"),
|
|
78862
|
+
phrase: t("Run the pump of {device} continuously", "Fai lavorare la pompa di {device} in continuo"),
|
|
78863
|
+
icon: "timer-off",
|
|
78864
|
+
args: { on: false }
|
|
78865
|
+
},
|
|
78866
|
+
{
|
|
78867
|
+
id: "petFountain.pumpOnMinutes",
|
|
78868
|
+
method: "setPumpOnMinutes",
|
|
78869
|
+
label: t("Set pump run time", "Imposta il tempo di lavoro della pompa"),
|
|
78870
|
+
phrase: t("Set the pump of {device} to run {minutes} minutes per cycle", "Imposta la pompa di {device} a lavorare {minutes} minuti per ciclo"),
|
|
78871
|
+
icon: "timer",
|
|
78872
|
+
openArgs: [{
|
|
78873
|
+
key: "minutes",
|
|
78874
|
+
label: t("Minutes", "Minuti"),
|
|
78875
|
+
offer: {
|
|
78876
|
+
kind: "number",
|
|
78877
|
+
min: 0,
|
|
78878
|
+
step: 1,
|
|
78879
|
+
unit: "min"
|
|
78880
|
+
}
|
|
78881
|
+
}]
|
|
78882
|
+
},
|
|
78883
|
+
{
|
|
78884
|
+
id: "petFountain.pumpOffMinutes",
|
|
78885
|
+
method: "setPumpOffMinutes",
|
|
78886
|
+
label: t("Set pump rest time", "Imposta il tempo di riposo della pompa"),
|
|
78887
|
+
phrase: t("Set the pump of {device} to rest {minutes} minutes per cycle", "Imposta la pompa di {device} a riposare {minutes} minuti per ciclo"),
|
|
78888
|
+
icon: "timer-off",
|
|
78889
|
+
openArgs: [{
|
|
78890
|
+
key: "minutes",
|
|
78891
|
+
label: t("Minutes", "Minuti"),
|
|
78892
|
+
offer: {
|
|
78893
|
+
kind: "number",
|
|
78894
|
+
min: 0,
|
|
78895
|
+
step: 1,
|
|
78896
|
+
unit: "min"
|
|
78897
|
+
}
|
|
78898
|
+
}]
|
|
78899
|
+
},
|
|
78900
|
+
{
|
|
78901
|
+
id: "petFountain.resetDailyConsumption",
|
|
78902
|
+
method: "resetDailyConsumption",
|
|
78903
|
+
label: t("Clear daily consumption", "Azzera il consumo giornaliero"),
|
|
78904
|
+
phrase: t("Clear the daily water consumption of {device}", "Azzera il consumo giornaliero di acqua di {device}"),
|
|
78905
|
+
icon: "rotate-ccw"
|
|
78906
|
+
}
|
|
78907
|
+
],
|
|
78908
|
+
state: [{
|
|
78909
|
+
kind: "boolean",
|
|
78910
|
+
field: "empty",
|
|
78911
|
+
label: t("Tank empty", "Serbatoio vuoto"),
|
|
78912
|
+
whenTrue: t("When the tank of {device} is empty", "Quando il serbatoio di {device} è vuoto"),
|
|
78913
|
+
whenFalse: t("When the tank of {device} is refilled", "Quando il serbatoio di {device} viene riempito"),
|
|
78914
|
+
icon: "droplet"
|
|
78915
|
+
}, {
|
|
78916
|
+
kind: "numeric",
|
|
78917
|
+
field: "waterLevel",
|
|
78918
|
+
quantity: t("the water level", "il livello dell’acqua"),
|
|
78919
|
+
label: t("Water level", "Livello dell’acqua"),
|
|
78920
|
+
unit: "%",
|
|
78921
|
+
icon: "droplets"
|
|
78922
|
+
}]
|
|
78923
|
+
},
|
|
78544
78924
|
"media-player": {
|
|
78545
78925
|
scope: "device",
|
|
78546
78926
|
noun: t("Media player", "Lettore multimediale"),
|
|
@@ -80365,6 +80745,7 @@ var SYSTEM_CAP_VOCABULARY = {
|
|
|
80365
80745
|
"device-manager": system("the device registry itself — rename, move and remove are administration"),
|
|
80366
80746
|
"device-provider": system(INTERNAL),
|
|
80367
80747
|
"device-removal-hook": system(INTERNAL),
|
|
80748
|
+
"node-removal-hook": system(INTERNAL),
|
|
80368
80749
|
"device-state": system("the runtime-state mirror every trigger already reads through"),
|
|
80369
80750
|
"display-palette": system("the cluster display palette — one colour table for every client, not a device action"),
|
|
80370
80751
|
"embedding-encoder": system(ML),
|
|
@@ -80477,7 +80858,7 @@ function projectAction(cap, action) {
|
|
|
80477
80858
|
};
|
|
80478
80859
|
}
|
|
80479
80860
|
Object.entries(CAP_VOCABULARY_BY_NAME).flatMap(([cap, entry]) => entry.scope === "device" ? (entry.actions ?? []).map((a) => projectAction(cap, a)) : []);
|
|
80480
|
-
DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer;
|
|
80861
|
+
DeviceType.Camera, DeviceType.Hub, DeviceType.Light, DeviceType.Siren, DeviceType.Switch, DeviceType.Sensor, DeviceType.Thermostat, DeviceType.Climate, DeviceType.Button, DeviceType.EventEmitter, DeviceType.Update, DeviceType.Generic, DeviceType.Notifier, DeviceType.Script, DeviceType.Automation, DeviceType.Lock, DeviceType.Cover, DeviceType.Valve, DeviceType.Humidifier, DeviceType.WaterHeater, DeviceType.Fan, DeviceType.MediaPlayer, DeviceType.AlarmPanel, DeviceType.Control, DeviceType.Presence, DeviceType.Weather, DeviceType.Vacuum, DeviceType.LawnMower, DeviceType.Container, DeviceType.Image, DeviceType.PetFeeder, DeviceType.PetFountain, DeviceType.Dishwasher, DeviceType.Washer, DeviceType.Dryer;
|
|
80481
80862
|
DeviceFeature.BatteryOperated;
|
|
80482
80863
|
DeviceType.Washer, DeviceType.Dryer, DeviceType.Dishwasher;
|
|
80483
80864
|
var HA_AS = "a power sensor (device_class power). Home Assistant has no laundry domain. running-state stays unexported until a null reading can be published as unavailable.";
|
|
@@ -82028,6 +82409,36 @@ Object.freeze({
|
|
|
82028
82409
|
form: "single",
|
|
82029
82410
|
optional: false
|
|
82030
82411
|
}],
|
|
82412
|
+
"petFountain.getStatus": [{
|
|
82413
|
+
name: "deviceId",
|
|
82414
|
+
form: "single",
|
|
82415
|
+
optional: false
|
|
82416
|
+
}],
|
|
82417
|
+
"petFountain.resetDailyConsumption": [{
|
|
82418
|
+
name: "deviceId",
|
|
82419
|
+
form: "single",
|
|
82420
|
+
optional: false
|
|
82421
|
+
}],
|
|
82422
|
+
"petFountain.setPump": [{
|
|
82423
|
+
name: "deviceId",
|
|
82424
|
+
form: "single",
|
|
82425
|
+
optional: false
|
|
82426
|
+
}],
|
|
82427
|
+
"petFountain.setPumpInterval": [{
|
|
82428
|
+
name: "deviceId",
|
|
82429
|
+
form: "single",
|
|
82430
|
+
optional: false
|
|
82431
|
+
}],
|
|
82432
|
+
"petFountain.setPumpOffMinutes": [{
|
|
82433
|
+
name: "deviceId",
|
|
82434
|
+
form: "single",
|
|
82435
|
+
optional: false
|
|
82436
|
+
}],
|
|
82437
|
+
"petFountain.setPumpOnMinutes": [{
|
|
82438
|
+
name: "deviceId",
|
|
82439
|
+
form: "single",
|
|
82440
|
+
optional: false
|
|
82441
|
+
}],
|
|
82031
82442
|
"pipelineAnalytics.addRetrainFrameFromRecording": [{
|
|
82032
82443
|
name: "deviceId",
|
|
82033
82444
|
form: "single",
|
|
@@ -84704,7 +85115,7 @@ var AdminUIAddon = class extends BaseAddon {
|
|
|
84704
85115
|
capability: adminUiCapability,
|
|
84705
85116
|
provider: {
|
|
84706
85117
|
getStaticDir: async () => ({ staticDir: resolveAdminUiDistDir() }),
|
|
84707
|
-
getVersion: async () => ({ version: "1.2.
|
|
85118
|
+
getVersion: async () => ({ version: "1.2.517" })
|
|
84708
85119
|
}
|
|
84709
85120
|
}];
|
|
84710
85121
|
}
|