@camstack/addon-admin-ui 1.2.27 → 1.2.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/{AddLocationWizard-8cRW4Jzl.js → AddLocationWizard-f89-IkPt.js} +1 -1
- package/dist/assets/{AddonCollectionPage-CiaXvpIo.js → AddonCollectionPage-Ch2XRf5H.js} +1 -1
- package/dist/assets/Addons-CdHie4yk.js +1 -0
- package/dist/assets/{AdminTabs-Dqs2B5TP.js → AdminTabs-CMrAY8Sg.js} +1 -1
- package/dist/assets/{AiProfiles-B-ZYpQv6.js → AiProfiles-pTNZy3y1.js} +1 -1
- package/dist/assets/Automation-QfkBqrcI.js +29 -0
- package/dist/assets/{BrokerForm-BJMUS91J.js → BrokerForm-BAZ82UHs.js} +1 -1
- package/dist/assets/Capabilities-BU0m67L8.js +1 -0
- package/dist/assets/CapabilityBadges-Bd-jxf5M.js +1 -0
- package/dist/assets/{Cluster-DFBi0ryq.js → Cluster-Kz7sxkEh.js} +1 -1
- package/dist/assets/{ClusterRecordingTab-CZZq6Ou8.js → ClusterRecordingTab-1Ep0a4vW.js} +1 -1
- package/dist/assets/{Dashboard-LzquRrCy.js → Dashboard-BkqNzZ9k.js} +1 -1
- package/dist/assets/Data-VrvWqvck.js +1 -0
- package/dist/assets/DetectionIntelligence-DhvaWm4u.js +1 -0
- package/dist/assets/{DeviceAggregateSection-QGY3DOSD.js → DeviceAggregateSection-BjhiujPl.js} +1 -1
- package/dist/assets/{DeviceDetail-DcqxA5OP.js → DeviceDetail-CkQKBq03.js} +2 -2
- package/dist/assets/{Devices-hWiMd09n.js → Devices-D8-uaQ9P.js} +1 -1
- package/dist/assets/{EmbedPlayerPage-D2laK8qP.js → EmbedPlayerPage-VSLkL4EV.js} +1 -1
- package/dist/assets/Events-C2Pic1x_.js +1 -0
- package/dist/assets/{FormBuilder-9QasrqDp.js → FormBuilder-4LCVdSVV.js} +1 -1
- package/dist/assets/Identity-q7i7NqN9.js +1 -0
- package/dist/assets/IntegrationDetail-Dkxb4wOF.js +1 -0
- package/dist/assets/{Integrations-KpJqa2eh.js → Integrations-Bp74D4gz.js} +1 -1
- package/dist/assets/Integrations-Ds4j_JJ8.js +1 -0
- package/dist/assets/{Logs-DvIm0V8i.js → Logs-fg8GZafU.js} +1 -1
- package/dist/assets/{MotionZonesSettings-DMkPYwfm.js → MotionZonesSettings-DjXYc9mc.js} +1 -1
- package/dist/assets/{MyAccess-DQRxiDVc.js → MyAccess-COiq6WO3.js} +1 -1
- package/dist/assets/Network-CiqowSs4.js +1 -0
- package/dist/assets/{NodeAddonsSettingsPanel-mtSSN5di.js → NodeAddonsSettingsPanel-BGclM9Ra.js} +1 -1
- package/dist/assets/NodeInferenceDevices-DrRLe_-U.js +1 -0
- package/dist/assets/Notifications-DQQm9HiJ.js +1 -0
- package/dist/assets/Pipeline-BJAW6qZG.js +1 -0
- package/dist/assets/{Plates-CJZ3YLDf.js → Plates-CvGuC_Lp.js} +1 -1
- package/dist/assets/{PrivacyMaskSettings-DJbI6C5O.js → PrivacyMaskSettings-_kxexVKf.js} +1 -1
- package/dist/assets/{ProviderIcon-_3FEm0BG.js → ProviderIcon-wbxEq0bC.js} +1 -1
- package/dist/assets/Recordings-Nl54spnw.js +1 -0
- package/dist/assets/ScanNetworkModal-DeJtIRyh.js +1 -0
- package/dist/assets/{Settings-BrE-eHJV.js → Settings-DeEQKEal.js} +1 -1
- package/dist/assets/{Showroom-Bu1fPAOX.js → Showroom-CEeMdl7x.js} +1 -1
- package/dist/assets/{Terminal-C5p955Pa.js → Terminal-Bg-v89nq.js} +2 -2
- package/dist/assets/_virtual_mf-localSharedImportMap___mfe_internal__admin_ui_host-CDUWxK0N.js +1 -0
- package/dist/assets/{build-cluster-graph-yvmQsU2l.js → build-cluster-graph-Cv0zvtyF.js} +2 -2
- package/dist/assets/circle-check-big-CkPzYYPA.js +1 -0
- package/dist/assets/clock-J0G5s40X.js +1 -0
- package/dist/assets/{copy-BKONNj-k.js → copy-CL5WAyDW.js} +1 -1
- package/dist/assets/{debounced-invalidate-vPoYh4bP.js → debounced-invalidate-DCC0mRXL.js} +1 -1
- package/dist/assets/{dist-DvvMnEMz.js → dist-AGMCUw5A.js} +1 -1
- package/dist/assets/dist-B3duXlmo.js +7 -0
- package/dist/assets/{download-BXKxeM9W.js → download-_vQgHc_K.js} +1 -1
- package/dist/assets/{face-bbox-BIL9CxXo.js → face-bbox-BzRb0Cay.js} +1 -1
- package/dist/assets/hostInit-BvGX5XHF.js +1 -0
- package/dist/assets/index-BHm1FmD-.css +2 -0
- package/dist/assets/index-BeCIFexS.js +4 -0
- package/dist/assets/{key-round-DlIq6OT0.js → key-round-BLz8Hopw.js} +1 -1
- package/dist/assets/{mf-entry-bootstrap-0-f0799171.js → mf-entry-bootstrap-0-6ae366a5.js} +2 -2
- package/dist/assets/{pencil-Czmub7zF.js → pencil-omAkHegX.js} +1 -1
- package/dist/assets/{player-overlays-BBqyPKM2.js → player-overlays-DHswkbsp.js} +1 -1
- package/dist/assets/plus-BpyRM_02.js +1 -0
- package/dist/assets/{radio-Bsvrf66r.js → radio-DoX1V1g-.js} +1 -1
- package/dist/assets/{refresh-cw-DHug6qjw.js → refresh-cw-CE37ff37.js} +1 -1
- package/dist/assets/remoteEntry-Czt3qcfu.js +1 -0
- package/dist/assets/{rotate-ccw-mEW0yUja.js → rotate-ccw-DkNejMx0.js} +1 -1
- package/dist/assets/rotate-cw-DjzrA-is.js +1 -0
- package/dist/assets/search-BfmAjYfy.js +1 -0
- package/dist/assets/{send-BkJjp8Ci.js → send-BOE-EMzz.js} +1 -1
- package/dist/assets/{server-D502ug1V.js → server-Cmm-r2A6.js} +1 -1
- package/dist/assets/square-CC6Ki3FL.js +1 -0
- package/dist/assets/{square-check-big-oO6WcOKX.js → square-check-big-BAgeP4VI.js} +1 -1
- package/dist/assets/{src-Cus9kyK5.js → src-BuqU1Y2C.js} +10 -10
- package/dist/assets/src-d71rtvEQ.js +7 -0
- package/dist/assets/{upload-AHyvKWFD.js → upload-BgE7db3Z.js} +1 -1
- package/dist/assets/{useEventInvalidation-By-LiR-C.js → useEventInvalidation-Cw6wrN4q.js} +1 -1
- package/dist/assets/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__admin_ui_host__remoteEntry-_hash_-BX5F-03u.js → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__admin_ui_host__remoteEntry-_hash_-BlNrk-4E.js} +2 -2
- package/dist/assets/{wifi-BqTNMokE.js → wifi-DfeLPHsk.js} +1 -1
- package/dist/assets/{zap-jkJVy5w-.js → zap-Bp4zqxqw.js} +1 -1
- package/dist/index.html +6 -6
- package/dist/server/addon.js +388 -236
- package/package.json +1 -1
- package/dist/assets/Addons-y8PCNUow.js +0 -1
- package/dist/assets/Capabilities-OzzB0e6-.js +0 -1
- package/dist/assets/CapabilityBadges-D2-uEkVq.js +0 -1
- package/dist/assets/Data-BH6j9g_-.js +0 -1
- package/dist/assets/DetectionIntelligence-DkrxY5iA.js +0 -1
- package/dist/assets/Events-BVAQ0-5E.js +0 -1
- package/dist/assets/Identity-DG2IFYUh.js +0 -1
- package/dist/assets/IntegrationDetail-RaObjV5m.js +0 -1
- package/dist/assets/Integrations-C-qBCiiD.js +0 -1
- package/dist/assets/Network-BqLXlaZV.js +0 -1
- package/dist/assets/NodeInferenceDevices-Cm_uziKY.js +0 -1
- package/dist/assets/Notifications-ehh4Wa5P.js +0 -1
- package/dist/assets/Pipeline-72XZmLkf.js +0 -1
- package/dist/assets/Recordings-D-q-9ZgS.js +0 -1
- package/dist/assets/ScanNetworkModal-BB5EPjw1.js +0 -1
- package/dist/assets/_virtual_mf-localSharedImportMap___mfe_internal__admin_ui_host-CbN7kJoK.js +0 -1
- package/dist/assets/circle-check-big-C_hc4h2j.js +0 -1
- package/dist/assets/clock-B0tltvJs.js +0 -1
- package/dist/assets/dist-tJNbI9ls.js +0 -7
- package/dist/assets/hostInit-BivS7viV.js +0 -1
- package/dist/assets/index-DVapnh8_.js +0 -4
- package/dist/assets/index-DvpMTqDC.css +0 -2
- package/dist/assets/plus-BpWlTXb3.js +0 -1
- package/dist/assets/remoteEntry-8JprVD_7.js +0 -1
- package/dist/assets/rotate-cw-BF1cMOF6.js +0 -1
- package/dist/assets/search-B24_Xm4V.js +0 -1
- package/dist/assets/square-C8ZyC2yg.js +0 -1
- package/dist/assets/src-CSJZQK3p.js +0 -7
package/dist/server/addon.js
CHANGED
|
@@ -8995,6 +8995,276 @@ var MaskGridDimsSchema = object({
|
|
|
8995
8995
|
height: number()
|
|
8996
8996
|
});
|
|
8997
8997
|
/**
|
|
8998
|
+
* notification-output — canonical, capability-gated notification delivery.
|
|
8999
|
+
*
|
|
9000
|
+
* Apprise-derived model (see
|
|
9001
|
+
* `docs/superpowers/specs/2026-07-03-notification-output-notifier-matrix.md`):
|
|
9002
|
+
* callers emit ONE canonical `Notification`; each provider declares a
|
|
9003
|
+
* per-kind capability descriptor (`TargetKind`), and the pure degrade
|
|
9004
|
+
* engine (`@camstack/types` `prepareNotification`) transcodes / degrades the
|
|
9005
|
+
* message to what the kind supports — callers never special-case a service.
|
|
9006
|
+
*
|
|
9007
|
+
* DESIGN DECISIONS (locked):
|
|
9008
|
+
* - Target CRUD lives on THIS cap (`upsertTarget` / `deleteTarget` /
|
|
9009
|
+
* `setTargetEnabled`), each provider persisting via the `settings-store`
|
|
9010
|
+
* cap. Rationale: the admin UI needs one uniform surface across the
|
|
9011
|
+
* notifiers addon AND the HA addon; the addon-`globalSettingsSchema`-array
|
|
9012
|
+
* alternative would fork the UI per addon and cannot host the
|
|
9013
|
+
* discovery→adopt flow.
|
|
9014
|
+
* - `listTargetKinds` / `listTargets` / `discoverTargets` return arrays →
|
|
9015
|
+
* the generated cap-mount auto-`concatCollection`-fans them across every
|
|
9016
|
+
* registered provider (notifiers addon + HA addon) so one catalog is
|
|
9017
|
+
* routable. `send` / `testTarget` / CRUD route to ONE provider by the
|
|
9018
|
+
* `addonId` the generated collection router extracts from the call input.
|
|
9019
|
+
* - `Attachment.bytes` is `Uint8Array`. Transport-safe: superjson (the tRPC
|
|
9020
|
+
* transformer) + UDS MsgPack both round-trip typed arrays — already used by
|
|
9021
|
+
* `storage` / `storage-provider` / `recording` caps over the same path. No
|
|
9022
|
+
* base64 fallback needed.
|
|
9023
|
+
*
|
|
9024
|
+
* TODO (deferred, closed-set change — separate decision): add
|
|
9025
|
+
* `providerKind: 'notify'` so notification providers surface on the unified
|
|
9026
|
+
* admin "Integrations" page.
|
|
9027
|
+
*/
|
|
9028
|
+
/**
|
|
9029
|
+
* Zentik-derived typed-media enum — the superset across every kind. Each
|
|
9030
|
+
* adapter picks what it supports and the degrade engine filters the rest.
|
|
9031
|
+
*/
|
|
9032
|
+
var AttachmentMediaTypeSchema = _enum([
|
|
9033
|
+
"image",
|
|
9034
|
+
"video",
|
|
9035
|
+
"gif",
|
|
9036
|
+
"audio",
|
|
9037
|
+
"icon"
|
|
9038
|
+
]);
|
|
9039
|
+
/**
|
|
9040
|
+
* A single attachment. Exactly one of `url` (remote source, most adapters
|
|
9041
|
+
* prefer this) or `bytes` (inline source; required for Pushover-style
|
|
9042
|
+
* bytes-only kinds) MUST be present — the degrade engine expresses a
|
|
9043
|
+
* url→bytes fetch as a `needsFetch` directive the adapter executes.
|
|
9044
|
+
*/
|
|
9045
|
+
var AttachmentSchema = object({
|
|
9046
|
+
mediaType: AttachmentMediaTypeSchema,
|
|
9047
|
+
url: string().optional(),
|
|
9048
|
+
bytes: _instanceof(Uint8Array).optional(),
|
|
9049
|
+
mime: string().optional(),
|
|
9050
|
+
name: string().optional()
|
|
9051
|
+
}).refine((a) => a.url !== void 0 || a.bytes !== void 0, { message: "Attachment requires either `url` or `bytes`" });
|
|
9052
|
+
var NotificationFormatSchema = _enum([
|
|
9053
|
+
"text",
|
|
9054
|
+
"markdown",
|
|
9055
|
+
"html"
|
|
9056
|
+
]);
|
|
9057
|
+
/**
|
|
9058
|
+
* The CLOSED icon vocabulary an action button may use.
|
|
9059
|
+
*
|
|
9060
|
+
* A closed set, not a free string, and that is the whole point: an arbitrary
|
|
9061
|
+
* icon name is one that ntfy renders, zentik silently drops, and nobody
|
|
9062
|
+
* notices — the same class of gap as a zone vocabulary nothing produced
|
|
9063
|
+
* ([D35](../../../docs/decisions/adr-0035.md)). Every adapter maps this set or
|
|
9064
|
+
* declares `actionIcons: false` and the degrade engine strips the field.
|
|
9065
|
+
*
|
|
9066
|
+
* Named by INTENT, never by glyph. "check" would tie the vocabulary to one
|
|
9067
|
+
* renderer's icon set; "acknowledge" survives an adapter that draws it
|
|
9068
|
+
* differently.
|
|
9069
|
+
*/
|
|
9070
|
+
var NotificationActionIconSchema = _enum([
|
|
9071
|
+
"acknowledge",
|
|
9072
|
+
"dismiss",
|
|
9073
|
+
"silence",
|
|
9074
|
+
"view",
|
|
9075
|
+
"play",
|
|
9076
|
+
"open",
|
|
9077
|
+
"close",
|
|
9078
|
+
"lock",
|
|
9079
|
+
"unlock",
|
|
9080
|
+
"arm",
|
|
9081
|
+
"disarm",
|
|
9082
|
+
"light",
|
|
9083
|
+
"alert"
|
|
9084
|
+
]);
|
|
9085
|
+
/** A single tap-through action button. */
|
|
9086
|
+
var NotificationActionSchema = object({
|
|
9087
|
+
id: string(),
|
|
9088
|
+
label: string(),
|
|
9089
|
+
url: string().optional(),
|
|
9090
|
+
/** Dropped by the degrade engine for a kind with `caps.actionIcons: false`. */
|
|
9091
|
+
icon: NotificationActionIconSchema.optional(),
|
|
9092
|
+
/**
|
|
9093
|
+
* Renders in a warning style where the notifier supports it.
|
|
9094
|
+
*
|
|
9095
|
+
* A HINT, never a gate. The callback's authority is its token and nothing
|
|
9096
|
+
* else — see `notification-center/action-token.ts` for what that does and
|
|
9097
|
+
* does not buy.
|
|
9098
|
+
*/
|
|
9099
|
+
destructive: boolean().optional()
|
|
9100
|
+
});
|
|
9101
|
+
/**
|
|
9102
|
+
* The canonical notification. `body` is the only hard field (Apprise model).
|
|
9103
|
+
* `priority` is a 5-level ORDINAL (1=lowest … 3=normal(default) … 5=urgent),
|
|
9104
|
+
* NOT a fixed severity enum — each kind declares its own `caps.levels` and
|
|
9105
|
+
* the adapter maps this ordinal onto its native level. `level?` is an
|
|
9106
|
+
* optional kind-native level id (`emergency`, `silent`, …) that overrides
|
|
9107
|
+
* `priority` for that one target.
|
|
9108
|
+
*/
|
|
9109
|
+
var NotificationSchema = object({
|
|
9110
|
+
body: string(),
|
|
9111
|
+
title: string().optional(),
|
|
9112
|
+
format: NotificationFormatSchema.default("text"),
|
|
9113
|
+
priority: number().int().min(1).max(5).default(3),
|
|
9114
|
+
level: string().optional(),
|
|
9115
|
+
attachments: array(AttachmentSchema).optional(),
|
|
9116
|
+
clickUrl: string().optional(),
|
|
9117
|
+
actions: array(NotificationActionSchema).optional(),
|
|
9118
|
+
sound: string().optional(),
|
|
9119
|
+
ttl: number().optional(),
|
|
9120
|
+
tag: string().optional(),
|
|
9121
|
+
deviceId: number().optional(),
|
|
9122
|
+
eventId: string().optional(),
|
|
9123
|
+
metadata: record(string(), unknown()).optional()
|
|
9124
|
+
});
|
|
9125
|
+
/** One declared native severity/priority level for a kind. */
|
|
9126
|
+
var TargetKindLevelSchema = object({
|
|
9127
|
+
id: string(),
|
|
9128
|
+
label: string(),
|
|
9129
|
+
/** Which canonical priority (1..5) this level maps to. `null` = qualitative-only. */
|
|
9130
|
+
ordinal: number().int().min(1).max(5).nullable(),
|
|
9131
|
+
flags: object({
|
|
9132
|
+
critical: boolean().optional(),
|
|
9133
|
+
silent: boolean().optional(),
|
|
9134
|
+
noPush: boolean().optional()
|
|
9135
|
+
}).optional(),
|
|
9136
|
+
/** e.g. Pushover `emergency` requires `retry` / `expire`. */
|
|
9137
|
+
requires: array(string()).optional(),
|
|
9138
|
+
description: string().optional()
|
|
9139
|
+
});
|
|
9140
|
+
/** The full capability block consulted before dispatch. */
|
|
9141
|
+
var TargetKindCapsSchema = object({
|
|
9142
|
+
attachments: object({
|
|
9143
|
+
mediaTypes: array(AttachmentMediaTypeSchema),
|
|
9144
|
+
mode: _enum([
|
|
9145
|
+
"url",
|
|
9146
|
+
"bytes",
|
|
9147
|
+
"both"
|
|
9148
|
+
]),
|
|
9149
|
+
max: number().int().nonnegative(),
|
|
9150
|
+
maxBytes: number().int().positive().optional()
|
|
9151
|
+
}),
|
|
9152
|
+
/** Max action buttons (0 = none). */
|
|
9153
|
+
actions: number().int().nonnegative(),
|
|
9154
|
+
/**
|
|
9155
|
+
* Whether this kind renders a per-action ICON.
|
|
9156
|
+
*
|
|
9157
|
+
* `.optional()`, deliberately NOT `.default(false)`: a Zod default does not
|
|
9158
|
+
* run on the addon cap path — three production failures in one day taught
|
|
9159
|
+
* this repo that once. Absent is read as false by the degrade engine, which
|
|
9160
|
+
* is the safe direction: an icon that is not rendered costs nothing, an icon
|
|
9161
|
+
* assumed and dropped costs the operator's trust in the field.
|
|
9162
|
+
*/
|
|
9163
|
+
actionIcons: boolean().optional(),
|
|
9164
|
+
levels: array(TargetKindLevelSchema),
|
|
9165
|
+
format: array(NotificationFormatSchema),
|
|
9166
|
+
clickUrl: boolean(),
|
|
9167
|
+
sound: boolean(),
|
|
9168
|
+
ttl: boolean(),
|
|
9169
|
+
bodyMaxLen: number().int().positive()
|
|
9170
|
+
});
|
|
9171
|
+
/**
|
|
9172
|
+
* `configSchema` is a `ConfigUISchema` tree passed through to the admin
|
|
9173
|
+
* FormBuilder. Stored as `z.unknown()` at the cap seam (mirrors
|
|
9174
|
+
* `device-provider.getChildCreationSchema` `CreationSchemaOutputSchema`) —
|
|
9175
|
+
* the union is large and not meant for runtime validation here; the exported
|
|
9176
|
+
* `TargetKind` type re-tightens `configSchema` to `ConfigUISchema`.
|
|
9177
|
+
*/
|
|
9178
|
+
var ConfigSchemaPassthrough$1 = unknown();
|
|
9179
|
+
var TargetKindSchema = object({
|
|
9180
|
+
kind: string(),
|
|
9181
|
+
label: string(),
|
|
9182
|
+
icon: string(),
|
|
9183
|
+
/** Stamped by each provider so the concat-fanned catalog stays routable. */
|
|
9184
|
+
addonId: string(),
|
|
9185
|
+
/**
|
|
9186
|
+
* URL of the kind's bundled BRAND icon, served by the providing addon over
|
|
9187
|
+
* its own `addon-routes` surface (`/addon/<addonId>/icons/<kind>`). Absent
|
|
9188
|
+
* when the addon bundles no icon for that kind — the client then falls back
|
|
9189
|
+
* to a neutral glyph rather than rendering the raw `icon` NAME as text.
|
|
9190
|
+
*
|
|
9191
|
+
* Root-relative on purpose: it resolves against whatever origin serves a web
|
|
9192
|
+
* client, and a native client joins it onto its own hub base.
|
|
9193
|
+
*
|
|
9194
|
+
* DECLARED here deliberately. It used to travel as an undeclared passthrough
|
|
9195
|
+
* field that survived only because the runtime cap-router forwards provider
|
|
9196
|
+
* output verbatim — so every consumer had to re-declare it by hand to stop
|
|
9197
|
+
* its own Zod parse from stripping it, and the whole arrangement would have
|
|
9198
|
+
* broken silently the moment output validation was tightened anywhere.
|
|
9199
|
+
*/
|
|
9200
|
+
iconUrl: string().optional(),
|
|
9201
|
+
/**
|
|
9202
|
+
* Media type of {@link iconUrl} (`image/svg+xml`, `image/png`, …).
|
|
9203
|
+
*
|
|
9204
|
+
* The server knows this and therefore says it, because the client cannot
|
|
9205
|
+
* safely guess: a React-Native client renders SVG and raster through two
|
|
9206
|
+
* DIFFERENT components (`react-native-svg` vs `expo-image` — expo-image does
|
|
9207
|
+
* not decode SVG on iOS/Android), so without this it silently fell back to a
|
|
9208
|
+
* placeholder glyph for every vector icon while the web build looked fine.
|
|
9209
|
+
*
|
|
9210
|
+
* Absent when {@link iconUrl} is absent, or for a legacy provider that has
|
|
9211
|
+
* not been updated — a client that cannot determine the type should prefer
|
|
9212
|
+
* its raster path, which is the safe default for an unknown image.
|
|
9213
|
+
*/
|
|
9214
|
+
iconMediaType: string().optional(),
|
|
9215
|
+
configSchema: ConfigSchemaPassthrough$1,
|
|
9216
|
+
supportsDiscovery: boolean(),
|
|
9217
|
+
caps: TargetKindCapsSchema
|
|
9218
|
+
});
|
|
9219
|
+
/**
|
|
9220
|
+
* A persisted target. `config` holds secrets; providers REDACT secret fields
|
|
9221
|
+
* (return a presence marker only) when serving `listTargets` — never
|
|
9222
|
+
* round-trip a stored secret to the UI.
|
|
9223
|
+
*/
|
|
9224
|
+
var TargetSchema = object({
|
|
9225
|
+
id: string(),
|
|
9226
|
+
name: string(),
|
|
9227
|
+
kind: string(),
|
|
9228
|
+
addonId: string(),
|
|
9229
|
+
enabled: boolean(),
|
|
9230
|
+
config: record(string(), unknown())
|
|
9231
|
+
});
|
|
9232
|
+
/** A discovery-surfaced candidate (config is partial + non-secret). */
|
|
9233
|
+
var DiscoveredTargetSchema = object({
|
|
9234
|
+
kind: string(),
|
|
9235
|
+
suggestedName: string(),
|
|
9236
|
+
config: record(string(), unknown())
|
|
9237
|
+
});
|
|
9238
|
+
/** The degrade engine's report — what was resolved / dropped / degraded. */
|
|
9239
|
+
var RenderedAsSchema = object({
|
|
9240
|
+
level: string(),
|
|
9241
|
+
format: NotificationFormatSchema,
|
|
9242
|
+
attachmentsSent: number().int().nonnegative(),
|
|
9243
|
+
actionsSent: number().int().nonnegative(),
|
|
9244
|
+
truncated: boolean(),
|
|
9245
|
+
dropped: array(string())
|
|
9246
|
+
});
|
|
9247
|
+
var SendResultSchema = object({
|
|
9248
|
+
success: boolean(),
|
|
9249
|
+
error: string().optional(),
|
|
9250
|
+
renderedAs: RenderedAsSchema.optional()
|
|
9251
|
+
});
|
|
9252
|
+
/** Same shape as SendResult — kept as a distinct name for the test panel. */
|
|
9253
|
+
var TestResultSchema = SendResultSchema;
|
|
9254
|
+
method(object({}), array(TargetKindSchema)), method(object({}), array(TargetSchema)), method(object({
|
|
9255
|
+
kind: string(),
|
|
9256
|
+
config: record(string(), unknown()).optional()
|
|
9257
|
+
}), array(DiscoveredTargetSchema)), method(object({
|
|
9258
|
+
targetId: string(),
|
|
9259
|
+
notification: NotificationSchema
|
|
9260
|
+
}), SendResultSchema, { kind: "mutation" }), method(object({
|
|
9261
|
+
targetId: string(),
|
|
9262
|
+
sample: NotificationSchema.optional()
|
|
9263
|
+
}), TestResultSchema, { kind: "mutation" }), method(object({ target: TargetSchema }), TargetSchema, { kind: "mutation" }), method(object({ targetId: string() }), _void(), { kind: "mutation" }), method(object({
|
|
9264
|
+
targetId: string(),
|
|
9265
|
+
enabled: boolean()
|
|
9266
|
+
}), _void(), { kind: "mutation" });
|
|
9267
|
+
/**
|
|
8998
9268
|
* notification-rules — the Notification Center rule surface (P1 core).
|
|
8999
9269
|
*
|
|
9000
9270
|
* Spec: `docs/superpowers/specs/2026-07-22-notification-center-requirements.md`
|
|
@@ -9164,6 +9434,41 @@ var NcRuleActionSchema = discriminatedUnion("kind", [object({
|
|
|
9164
9434
|
args: record(string(), unknown()).optional()
|
|
9165
9435
|
})]);
|
|
9166
9436
|
/**
|
|
9437
|
+
* A named, ordered run of steps with its own throttle.
|
|
9438
|
+
*
|
|
9439
|
+
* `minDelaySec` exists because a noisy rule otherwise hammers a physical
|
|
9440
|
+
* actuator — the rule's own cooldown governs NOTIFICATIONS, which is a
|
|
9441
|
+
* different budget from "how often may this gate actually open".
|
|
9442
|
+
*/
|
|
9443
|
+
var NcRuleActionSequenceSchema = object({
|
|
9444
|
+
name: string().min(1).max(120),
|
|
9445
|
+
enabled: boolean(),
|
|
9446
|
+
minDelaySec: number().int().min(0).max(86400).optional(),
|
|
9447
|
+
actions: array(NcRuleActionSchema).min(1)
|
|
9448
|
+
});
|
|
9449
|
+
/**
|
|
9450
|
+
* One button carried by the notification, running a named sequence on tap.
|
|
9451
|
+
*
|
|
9452
|
+
* **Read this before adding a button that does something physical.** The tap
|
|
9453
|
+
* arrives over a link that travelled through third-party infrastructure — ntfy,
|
|
9454
|
+
* a push relay, whatever forwarded the message — and the callback's ONLY
|
|
9455
|
+
* authority is the token in that link: single-use, short-lived, bound to this
|
|
9456
|
+
* one action of this one notification. It does not identify who tapped.
|
|
9457
|
+
* Whoever holds the notification can run the button, once, inside the window.
|
|
9458
|
+
* That is the operator's explicit choice (2026-08-05), and `destructive` is a
|
|
9459
|
+
* rendering hint, not a second gate. [D47](decisions/adr-0047.md).
|
|
9460
|
+
*/
|
|
9461
|
+
var NcRuleNotificationButtonSchema = object({
|
|
9462
|
+
/** Stable id — travels in the callback and identifies the button in logs. */
|
|
9463
|
+
id: string().min(1).max(64),
|
|
9464
|
+
label: string().min(1).max(40),
|
|
9465
|
+
/** Name of a sequence in `onTrigger`. The dispatcher drops a button whose
|
|
9466
|
+
* sequence does not exist rather than minting a token for nothing. */
|
|
9467
|
+
sequence: string().min(1).max(120),
|
|
9468
|
+
icon: NotificationActionIconSchema.optional(),
|
|
9469
|
+
destructive: boolean().optional()
|
|
9470
|
+
});
|
|
9471
|
+
/**
|
|
9167
9472
|
* Sequences a rule runs, by hook point.
|
|
9168
9473
|
*
|
|
9169
9474
|
* ONLY `onTrigger` is here, deliberately. The reference also has activation /
|
|
@@ -9171,14 +9476,26 @@ var NcRuleActionSchema = discriminatedUnion("kind", [object({
|
|
|
9171
9476
|
* repo's expensive failure mode is declaring a surface nothing produces, so a
|
|
9172
9477
|
* hook appears here in the same change that produces its edge, never before.
|
|
9173
9478
|
*/
|
|
9174
|
-
var NcRuleActionsSchema = object({
|
|
9175
|
-
/** Runs when the rule MATCHES. */
|
|
9176
|
-
onTrigger: array(
|
|
9177
|
-
|
|
9178
|
-
|
|
9179
|
-
|
|
9180
|
-
|
|
9181
|
-
|
|
9479
|
+
var NcRuleActionsSchema = object({
|
|
9480
|
+
/** Runs when the rule MATCHES. */
|
|
9481
|
+
onTrigger: array(NcRuleActionSequenceSchema).optional(),
|
|
9482
|
+
/**
|
|
9483
|
+
* Buttons the NOTIFICATION carries, each running one of this rule's
|
|
9484
|
+
* sequences when tapped.
|
|
9485
|
+
*
|
|
9486
|
+
* Deliberately a REFERENCE to a sequence rather than a second place to
|
|
9487
|
+
* author steps. A button that could define its own actions would be a
|
|
9488
|
+
* parallel actuation vocabulary — the executor's device-scope check, the
|
|
9489
|
+
* stop-at-first-failure rule and the per-sequence throttle all live on
|
|
9490
|
+
* sequences, and a second authoring surface would drift from every one of
|
|
9491
|
+
* them.
|
|
9492
|
+
*
|
|
9493
|
+
* A sequence reachable ONLY by a button simply appears in `onTrigger` with
|
|
9494
|
+
* `enabled: false`: it is then authored, throttled and validated like the
|
|
9495
|
+
* rest, and nothing runs it automatically.
|
|
9496
|
+
*/
|
|
9497
|
+
buttons: array(NcRuleNotificationButtonSchema).max(8).optional()
|
|
9498
|
+
});
|
|
9182
9499
|
var NcConditionsSchema = object({
|
|
9183
9500
|
/** Gate on ANOTHER device's current state (the alarm armed, a switch on). */
|
|
9184
9501
|
deviceState: object({
|
|
@@ -15121,6 +15438,20 @@ var GetInputSchema = object({ id: string() });
|
|
|
15121
15438
|
var AddInputSchema = object({
|
|
15122
15439
|
kind: string().min(1),
|
|
15123
15440
|
name: string().min(1),
|
|
15441
|
+
/**
|
|
15442
|
+
* ADOPT an existing id instead of minting a new one.
|
|
15443
|
+
*
|
|
15444
|
+
* Written the day this cost an outage. A broker's id is not a detail: HA
|
|
15445
|
+
* devices carry it inside their `stableId` (`ha:ha_004:dev:…`), so a broker
|
|
15446
|
+
* lost from config and re-added as `ha_001` leaves every one of its devices
|
|
15447
|
+
* bound to a broker that no longer exists. Re-entering the password under the
|
|
15448
|
+
* ORIGINAL id turns a multi-step device migration back into re-entering a
|
|
15449
|
+
* password.
|
|
15450
|
+
*
|
|
15451
|
+
* A provider MUST refuse an id that is already in use — adopting a live
|
|
15452
|
+
* broker's id would silently take it over.
|
|
15453
|
+
*/
|
|
15454
|
+
id: string().min(1).optional(),
|
|
15124
15455
|
/** Kind-specific settings (e.g. MQTT `{url,username,password}` or HA
|
|
15125
15456
|
* `{baseUrl,accessToken}`). Validated by the kind-specific provider
|
|
15126
15457
|
* branch on receipt — invalid shape rejects the add. */
|
|
@@ -16166,7 +16497,20 @@ method(object({
|
|
|
16166
16497
|
}), _void(), {
|
|
16167
16498
|
kind: "mutation",
|
|
16168
16499
|
auth: "admin"
|
|
16169
|
-
}), method(object({ addonId: string() }), array(SavedDeviceRowSchema)), method(object({
|
|
16500
|
+
}), method(object({ addonId: string() }), array(SavedDeviceRowSchema)), method(object({
|
|
16501
|
+
addonId: string().optional(),
|
|
16502
|
+
/**
|
|
16503
|
+
* `slim` omits `config` (returned `{}`), `metadata` (null) and the
|
|
16504
|
+
* `sourceInfo` derived from config — and skips the per-device settings
|
|
16505
|
+
* read that produces them. Everything identifying a device (id, name,
|
|
16506
|
+
* type, online, features, isCamera, parent/link ids) is unchanged.
|
|
16507
|
+
* Do not use it for dispatch routing, which needs `sourceInfo`.
|
|
16508
|
+
*/
|
|
16509
|
+
projection: _enum(["full", "slim"]).optional(),
|
|
16510
|
+
/** Return only camera devices. Filtering server-side instead of
|
|
16511
|
+
* shipping 293 rows to find 12. */
|
|
16512
|
+
isCamera: boolean().optional()
|
|
16513
|
+
}), array(DeviceInfoSchema)), method(object({ deviceId: number() }), DeviceInfoSchema.nullable()), method(object({ parentDeviceId: number() }), array(DeviceInfoSchema)), method(object({ deviceId: number() }), object({
|
|
16170
16514
|
mode: DeviceLinkModeSchema,
|
|
16171
16515
|
devices: array(LinkedDeviceSchema)
|
|
16172
16516
|
})), method(object({ deviceId: number() }), array(StreamSourceEntrySchema$1)), method(object({ deviceId: number() }), array(ConfigEntrySchema)), method(object({ deviceId: number() }), ConfigUISchemaOutput), method(object({
|
|
@@ -16605,14 +16949,14 @@ var LlmProfileSchema = object({
|
|
|
16605
16949
|
/** ConfigUISchema tree passed through untyped on the wire (the
|
|
16606
16950
|
* notification-output `ConfigSchemaPassthrough` precedent at
|
|
16607
16951
|
* notification-output.cap.ts:151); the exported TS type re-tightens it. */
|
|
16608
|
-
var ConfigSchemaPassthrough
|
|
16952
|
+
var ConfigSchemaPassthrough = unknown();
|
|
16609
16953
|
var LlmProfileKindDescriptorSchema = object({
|
|
16610
16954
|
kind: LlmProfileKindSchema,
|
|
16611
16955
|
label: string(),
|
|
16612
16956
|
icon: string(),
|
|
16613
16957
|
/** Stamped by each provider so the concat-fanned catalog stays routable. */
|
|
16614
16958
|
addonId: string(),
|
|
16615
|
-
configSchema: ConfigSchemaPassthrough
|
|
16959
|
+
configSchema: ConfigSchemaPassthrough
|
|
16616
16960
|
});
|
|
16617
16961
|
var LlmDefaultSelectorSchema = union([object({ consumer: string() }), object({ purpose: _enum(["text", "vision"]) })]);
|
|
16618
16962
|
var LlmDefaultSchema = object({
|
|
@@ -17143,228 +17487,6 @@ var NetworkEndpointEntrySchema = NetworkEndpointSchema.extend({
|
|
|
17143
17487
|
});
|
|
17144
17488
|
method(_void(), NetworkEndpointSchema, { kind: "mutation" }), method(_void(), _void(), { kind: "mutation" }), method(_void(), NetworkEndpointSchema.nullable()), method(_void(), NetworkAccessStatusSchema), method(_void(), array(NetworkEndpointEntrySchema).readonly());
|
|
17145
17489
|
/**
|
|
17146
|
-
* notification-output — canonical, capability-gated notification delivery.
|
|
17147
|
-
*
|
|
17148
|
-
* Apprise-derived model (see
|
|
17149
|
-
* `docs/superpowers/specs/2026-07-03-notification-output-notifier-matrix.md`):
|
|
17150
|
-
* callers emit ONE canonical `Notification`; each provider declares a
|
|
17151
|
-
* per-kind capability descriptor (`TargetKind`), and the pure degrade
|
|
17152
|
-
* engine (`@camstack/types` `prepareNotification`) transcodes / degrades the
|
|
17153
|
-
* message to what the kind supports — callers never special-case a service.
|
|
17154
|
-
*
|
|
17155
|
-
* DESIGN DECISIONS (locked):
|
|
17156
|
-
* - Target CRUD lives on THIS cap (`upsertTarget` / `deleteTarget` /
|
|
17157
|
-
* `setTargetEnabled`), each provider persisting via the `settings-store`
|
|
17158
|
-
* cap. Rationale: the admin UI needs one uniform surface across the
|
|
17159
|
-
* notifiers addon AND the HA addon; the addon-`globalSettingsSchema`-array
|
|
17160
|
-
* alternative would fork the UI per addon and cannot host the
|
|
17161
|
-
* discovery→adopt flow.
|
|
17162
|
-
* - `listTargetKinds` / `listTargets` / `discoverTargets` return arrays →
|
|
17163
|
-
* the generated cap-mount auto-`concatCollection`-fans them across every
|
|
17164
|
-
* registered provider (notifiers addon + HA addon) so one catalog is
|
|
17165
|
-
* routable. `send` / `testTarget` / CRUD route to ONE provider by the
|
|
17166
|
-
* `addonId` the generated collection router extracts from the call input.
|
|
17167
|
-
* - `Attachment.bytes` is `Uint8Array`. Transport-safe: superjson (the tRPC
|
|
17168
|
-
* transformer) + UDS MsgPack both round-trip typed arrays — already used by
|
|
17169
|
-
* `storage` / `storage-provider` / `recording` caps over the same path. No
|
|
17170
|
-
* base64 fallback needed.
|
|
17171
|
-
*
|
|
17172
|
-
* TODO (deferred, closed-set change — separate decision): add
|
|
17173
|
-
* `providerKind: 'notify'` so notification providers surface on the unified
|
|
17174
|
-
* admin "Integrations" page.
|
|
17175
|
-
*/
|
|
17176
|
-
/**
|
|
17177
|
-
* Zentik-derived typed-media enum — the superset across every kind. Each
|
|
17178
|
-
* adapter picks what it supports and the degrade engine filters the rest.
|
|
17179
|
-
*/
|
|
17180
|
-
var AttachmentMediaTypeSchema = _enum([
|
|
17181
|
-
"image",
|
|
17182
|
-
"video",
|
|
17183
|
-
"gif",
|
|
17184
|
-
"audio",
|
|
17185
|
-
"icon"
|
|
17186
|
-
]);
|
|
17187
|
-
/**
|
|
17188
|
-
* A single attachment. Exactly one of `url` (remote source, most adapters
|
|
17189
|
-
* prefer this) or `bytes` (inline source; required for Pushover-style
|
|
17190
|
-
* bytes-only kinds) MUST be present — the degrade engine expresses a
|
|
17191
|
-
* url→bytes fetch as a `needsFetch` directive the adapter executes.
|
|
17192
|
-
*/
|
|
17193
|
-
var AttachmentSchema = object({
|
|
17194
|
-
mediaType: AttachmentMediaTypeSchema,
|
|
17195
|
-
url: string().optional(),
|
|
17196
|
-
bytes: _instanceof(Uint8Array).optional(),
|
|
17197
|
-
mime: string().optional(),
|
|
17198
|
-
name: string().optional()
|
|
17199
|
-
}).refine((a) => a.url !== void 0 || a.bytes !== void 0, { message: "Attachment requires either `url` or `bytes`" });
|
|
17200
|
-
var NotificationFormatSchema = _enum([
|
|
17201
|
-
"text",
|
|
17202
|
-
"markdown",
|
|
17203
|
-
"html"
|
|
17204
|
-
]);
|
|
17205
|
-
/** A single tap-through action button. */
|
|
17206
|
-
var NotificationActionSchema = object({
|
|
17207
|
-
id: string(),
|
|
17208
|
-
label: string(),
|
|
17209
|
-
url: string().optional()
|
|
17210
|
-
});
|
|
17211
|
-
/**
|
|
17212
|
-
* The canonical notification. `body` is the only hard field (Apprise model).
|
|
17213
|
-
* `priority` is a 5-level ORDINAL (1=lowest … 3=normal(default) … 5=urgent),
|
|
17214
|
-
* NOT a fixed severity enum — each kind declares its own `caps.levels` and
|
|
17215
|
-
* the adapter maps this ordinal onto its native level. `level?` is an
|
|
17216
|
-
* optional kind-native level id (`emergency`, `silent`, …) that overrides
|
|
17217
|
-
* `priority` for that one target.
|
|
17218
|
-
*/
|
|
17219
|
-
var NotificationSchema = object({
|
|
17220
|
-
body: string(),
|
|
17221
|
-
title: string().optional(),
|
|
17222
|
-
format: NotificationFormatSchema.default("text"),
|
|
17223
|
-
priority: number().int().min(1).max(5).default(3),
|
|
17224
|
-
level: string().optional(),
|
|
17225
|
-
attachments: array(AttachmentSchema).optional(),
|
|
17226
|
-
clickUrl: string().optional(),
|
|
17227
|
-
actions: array(NotificationActionSchema).optional(),
|
|
17228
|
-
sound: string().optional(),
|
|
17229
|
-
ttl: number().optional(),
|
|
17230
|
-
tag: string().optional(),
|
|
17231
|
-
deviceId: number().optional(),
|
|
17232
|
-
eventId: string().optional(),
|
|
17233
|
-
metadata: record(string(), unknown()).optional()
|
|
17234
|
-
});
|
|
17235
|
-
/** One declared native severity/priority level for a kind. */
|
|
17236
|
-
var TargetKindLevelSchema = object({
|
|
17237
|
-
id: string(),
|
|
17238
|
-
label: string(),
|
|
17239
|
-
/** Which canonical priority (1..5) this level maps to. `null` = qualitative-only. */
|
|
17240
|
-
ordinal: number().int().min(1).max(5).nullable(),
|
|
17241
|
-
flags: object({
|
|
17242
|
-
critical: boolean().optional(),
|
|
17243
|
-
silent: boolean().optional(),
|
|
17244
|
-
noPush: boolean().optional()
|
|
17245
|
-
}).optional(),
|
|
17246
|
-
/** e.g. Pushover `emergency` requires `retry` / `expire`. */
|
|
17247
|
-
requires: array(string()).optional(),
|
|
17248
|
-
description: string().optional()
|
|
17249
|
-
});
|
|
17250
|
-
/** The full capability block consulted before dispatch. */
|
|
17251
|
-
var TargetKindCapsSchema = object({
|
|
17252
|
-
attachments: object({
|
|
17253
|
-
mediaTypes: array(AttachmentMediaTypeSchema),
|
|
17254
|
-
mode: _enum([
|
|
17255
|
-
"url",
|
|
17256
|
-
"bytes",
|
|
17257
|
-
"both"
|
|
17258
|
-
]),
|
|
17259
|
-
max: number().int().nonnegative(),
|
|
17260
|
-
maxBytes: number().int().positive().optional()
|
|
17261
|
-
}),
|
|
17262
|
-
/** Max action buttons (0 = none). */
|
|
17263
|
-
actions: number().int().nonnegative(),
|
|
17264
|
-
levels: array(TargetKindLevelSchema),
|
|
17265
|
-
format: array(NotificationFormatSchema),
|
|
17266
|
-
clickUrl: boolean(),
|
|
17267
|
-
sound: boolean(),
|
|
17268
|
-
ttl: boolean(),
|
|
17269
|
-
bodyMaxLen: number().int().positive()
|
|
17270
|
-
});
|
|
17271
|
-
/**
|
|
17272
|
-
* `configSchema` is a `ConfigUISchema` tree passed through to the admin
|
|
17273
|
-
* FormBuilder. Stored as `z.unknown()` at the cap seam (mirrors
|
|
17274
|
-
* `device-provider.getChildCreationSchema` `CreationSchemaOutputSchema`) —
|
|
17275
|
-
* the union is large and not meant for runtime validation here; the exported
|
|
17276
|
-
* `TargetKind` type re-tightens `configSchema` to `ConfigUISchema`.
|
|
17277
|
-
*/
|
|
17278
|
-
var ConfigSchemaPassthrough = unknown();
|
|
17279
|
-
var TargetKindSchema = object({
|
|
17280
|
-
kind: string(),
|
|
17281
|
-
label: string(),
|
|
17282
|
-
icon: string(),
|
|
17283
|
-
/** Stamped by each provider so the concat-fanned catalog stays routable. */
|
|
17284
|
-
addonId: string(),
|
|
17285
|
-
/**
|
|
17286
|
-
* URL of the kind's bundled BRAND icon, served by the providing addon over
|
|
17287
|
-
* its own `addon-routes` surface (`/addon/<addonId>/icons/<kind>`). Absent
|
|
17288
|
-
* when the addon bundles no icon for that kind — the client then falls back
|
|
17289
|
-
* to a neutral glyph rather than rendering the raw `icon` NAME as text.
|
|
17290
|
-
*
|
|
17291
|
-
* Root-relative on purpose: it resolves against whatever origin serves a web
|
|
17292
|
-
* client, and a native client joins it onto its own hub base.
|
|
17293
|
-
*
|
|
17294
|
-
* DECLARED here deliberately. It used to travel as an undeclared passthrough
|
|
17295
|
-
* field that survived only because the runtime cap-router forwards provider
|
|
17296
|
-
* output verbatim — so every consumer had to re-declare it by hand to stop
|
|
17297
|
-
* its own Zod parse from stripping it, and the whole arrangement would have
|
|
17298
|
-
* broken silently the moment output validation was tightened anywhere.
|
|
17299
|
-
*/
|
|
17300
|
-
iconUrl: string().optional(),
|
|
17301
|
-
/**
|
|
17302
|
-
* Media type of {@link iconUrl} (`image/svg+xml`, `image/png`, …).
|
|
17303
|
-
*
|
|
17304
|
-
* The server knows this and therefore says it, because the client cannot
|
|
17305
|
-
* safely guess: a React-Native client renders SVG and raster through two
|
|
17306
|
-
* DIFFERENT components (`react-native-svg` vs `expo-image` — expo-image does
|
|
17307
|
-
* not decode SVG on iOS/Android), so without this it silently fell back to a
|
|
17308
|
-
* placeholder glyph for every vector icon while the web build looked fine.
|
|
17309
|
-
*
|
|
17310
|
-
* Absent when {@link iconUrl} is absent, or for a legacy provider that has
|
|
17311
|
-
* not been updated — a client that cannot determine the type should prefer
|
|
17312
|
-
* its raster path, which is the safe default for an unknown image.
|
|
17313
|
-
*/
|
|
17314
|
-
iconMediaType: string().optional(),
|
|
17315
|
-
configSchema: ConfigSchemaPassthrough,
|
|
17316
|
-
supportsDiscovery: boolean(),
|
|
17317
|
-
caps: TargetKindCapsSchema
|
|
17318
|
-
});
|
|
17319
|
-
/**
|
|
17320
|
-
* A persisted target. `config` holds secrets; providers REDACT secret fields
|
|
17321
|
-
* (return a presence marker only) when serving `listTargets` — never
|
|
17322
|
-
* round-trip a stored secret to the UI.
|
|
17323
|
-
*/
|
|
17324
|
-
var TargetSchema = object({
|
|
17325
|
-
id: string(),
|
|
17326
|
-
name: string(),
|
|
17327
|
-
kind: string(),
|
|
17328
|
-
addonId: string(),
|
|
17329
|
-
enabled: boolean(),
|
|
17330
|
-
config: record(string(), unknown())
|
|
17331
|
-
});
|
|
17332
|
-
/** A discovery-surfaced candidate (config is partial + non-secret). */
|
|
17333
|
-
var DiscoveredTargetSchema = object({
|
|
17334
|
-
kind: string(),
|
|
17335
|
-
suggestedName: string(),
|
|
17336
|
-
config: record(string(), unknown())
|
|
17337
|
-
});
|
|
17338
|
-
/** The degrade engine's report — what was resolved / dropped / degraded. */
|
|
17339
|
-
var RenderedAsSchema = object({
|
|
17340
|
-
level: string(),
|
|
17341
|
-
format: NotificationFormatSchema,
|
|
17342
|
-
attachmentsSent: number().int().nonnegative(),
|
|
17343
|
-
actionsSent: number().int().nonnegative(),
|
|
17344
|
-
truncated: boolean(),
|
|
17345
|
-
dropped: array(string())
|
|
17346
|
-
});
|
|
17347
|
-
var SendResultSchema = object({
|
|
17348
|
-
success: boolean(),
|
|
17349
|
-
error: string().optional(),
|
|
17350
|
-
renderedAs: RenderedAsSchema.optional()
|
|
17351
|
-
});
|
|
17352
|
-
/** Same shape as SendResult — kept as a distinct name for the test panel. */
|
|
17353
|
-
var TestResultSchema = SendResultSchema;
|
|
17354
|
-
method(object({}), array(TargetKindSchema)), method(object({}), array(TargetSchema)), method(object({
|
|
17355
|
-
kind: string(),
|
|
17356
|
-
config: record(string(), unknown()).optional()
|
|
17357
|
-
}), array(DiscoveredTargetSchema)), method(object({
|
|
17358
|
-
targetId: string(),
|
|
17359
|
-
notification: NotificationSchema
|
|
17360
|
-
}), SendResultSchema, { kind: "mutation" }), method(object({
|
|
17361
|
-
targetId: string(),
|
|
17362
|
-
sample: NotificationSchema.optional()
|
|
17363
|
-
}), TestResultSchema, { kind: "mutation" }), method(object({ target: TargetSchema }), TargetSchema, { kind: "mutation" }), method(object({ targetId: string() }), _void(), { kind: "mutation" }), method(object({
|
|
17364
|
-
targetId: string(),
|
|
17365
|
-
enabled: boolean()
|
|
17366
|
-
}), _void(), { kind: "mutation" });
|
|
17367
|
-
/**
|
|
17368
17490
|
* core-blocks — user-authored TypeScript, stored in the kernel and executed in
|
|
17369
17491
|
* its own process.
|
|
17370
17492
|
*
|
|
@@ -17708,6 +17830,11 @@ var EventKindDescriptorSchema = object({
|
|
|
17708
17830
|
deviceId: number()
|
|
17709
17831
|
})
|
|
17710
17832
|
});
|
|
17833
|
+
/** One camera's event vocabulary, as returned by `listEventKindsBatch`. */
|
|
17834
|
+
var EventKindsForDeviceSchema = object({
|
|
17835
|
+
deviceId: number(),
|
|
17836
|
+
kinds: array(EventKindDescriptorSchema).readonly()
|
|
17837
|
+
});
|
|
17711
17838
|
var SensorEventSchema = object({
|
|
17712
17839
|
id: string(),
|
|
17713
17840
|
/** The CAMERA the event is attributed to (a sensor linked to N cameras
|
|
@@ -17964,6 +18091,19 @@ var MediaFileSchema = object({
|
|
|
17964
18091
|
sizeBytes: number(),
|
|
17965
18092
|
timestamp: number()
|
|
17966
18093
|
});
|
|
18094
|
+
/**
|
|
18095
|
+
* One media row WITHOUT its bytes.
|
|
18096
|
+
*
|
|
18097
|
+
* A track's media is 5-8 MB of base64 (measured: 7.67 MB across 23 files for a
|
|
18098
|
+
* 140 s track), and a client that renders tiles from the media data plane needs
|
|
18099
|
+
* to know only WHAT EXISTS — the bytes then arrive per tile, lazily, over HTTP
|
|
18100
|
+
* with an immutable cache, instead of all at once inside a tRPC response that
|
|
18101
|
+
* blocks the whole view.
|
|
18102
|
+
*
|
|
18103
|
+
* `sizeBytes` is carried because it is what lets a client decide between the
|
|
18104
|
+
* stored blob and a `?variant=thumb` rendering without fetching either.
|
|
18105
|
+
*/
|
|
18106
|
+
var MediaFileInfoSchema = MediaFileSchema.omit({ base64: true });
|
|
17967
18107
|
var DEFAULT_EVENT_QUERY_LIMIT = 1e3;
|
|
17968
18108
|
var MAX_EVENT_QUERY_LIMIT = 5e3;
|
|
17969
18109
|
var DeviceEventQueryInput = object({
|
|
@@ -18113,7 +18253,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
18113
18253
|
}), array(TrackSchema).readonly()), method(RecentTracksQueryInput, RecentTracksPageSchema), method(object({ deviceId: number() }), _void(), {
|
|
18114
18254
|
kind: "mutation",
|
|
18115
18255
|
auth: "admin"
|
|
18116
|
-
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({
|
|
18256
|
+
}), method(DeviceEventQueryInput, array(MotionEventSchema).readonly()), method(ObjectEventQueryInput, array(ObjectEventSchema).readonly()), method(DeviceEventQueryInput, array(AudioEventSchema).readonly()), method(object({ deviceId: number() }), array(EventKindDescriptorSchema).readonly()), method(object({ deviceIds: array(number()).min(1).max(200) }), array(EventKindsForDeviceSchema).readonly()), method(object({
|
|
18117
18257
|
deviceId: number(),
|
|
18118
18258
|
since: number().optional(),
|
|
18119
18259
|
until: number().optional(),
|
|
@@ -18187,7 +18327,7 @@ DeviceType.Camera, method(object({ deviceId: number() }), array(TrackSchema).rea
|
|
|
18187
18327
|
}), array(MediaFileSchema).readonly()), method(object({
|
|
18188
18328
|
trackId: string(),
|
|
18189
18329
|
kinds: array(MediaFileKindEnum).optional()
|
|
18190
|
-
}), array(MediaFileSchema).readonly()), method(SearchObjectEventsInput, array(ScoredObjectEventSchema).readonly()), object({
|
|
18330
|
+
}), array(MediaFileSchema).readonly()), method(object({ trackId: string() }), array(MediaFileInfoSchema).readonly()), method(SearchObjectEventsInput, array(ScoredObjectEventSchema).readonly()), object({
|
|
18191
18331
|
deviceId: number(),
|
|
18192
18332
|
timestamp: number(),
|
|
18193
18333
|
frameWidth: number(),
|
|
@@ -24991,6 +25131,12 @@ Object.freeze({
|
|
|
24991
25131
|
addonId: null,
|
|
24992
25132
|
access: "view"
|
|
24993
25133
|
},
|
|
25134
|
+
"pipelineAnalytics.listEventKindsBatch": {
|
|
25135
|
+
capName: "pipeline-analytics",
|
|
25136
|
+
capScope: "device",
|
|
25137
|
+
addonId: null,
|
|
25138
|
+
access: "view"
|
|
25139
|
+
},
|
|
24994
25140
|
"pipelineAnalytics.listOpsLog": {
|
|
24995
25141
|
capName: "pipeline-analytics",
|
|
24996
25142
|
capScope: "device",
|
|
@@ -25003,6 +25149,12 @@ Object.freeze({
|
|
|
25003
25149
|
addonId: null,
|
|
25004
25150
|
access: "view"
|
|
25005
25151
|
},
|
|
25152
|
+
"pipelineAnalytics.listTrackMedia": {
|
|
25153
|
+
capName: "pipeline-analytics",
|
|
25154
|
+
capScope: "device",
|
|
25155
|
+
addonId: null,
|
|
25156
|
+
access: "view"
|
|
25157
|
+
},
|
|
25006
25158
|
"pipelineAnalytics.listTracks": {
|
|
25007
25159
|
capName: "pipeline-analytics",
|
|
25008
25160
|
capScope: "device",
|
|
@@ -27132,7 +27284,7 @@ var AdminUIAddon = class extends BaseAddon {
|
|
|
27132
27284
|
capability: adminUiCapability,
|
|
27133
27285
|
provider: {
|
|
27134
27286
|
getStaticDir: async () => ({ staticDir: resolveAdminUiDistDir() }),
|
|
27135
|
-
getVersion: async () => ({ version: "1.2.
|
|
27287
|
+
getVersion: async () => ({ version: "1.2.29" })
|
|
27136
27288
|
}
|
|
27137
27289
|
}];
|
|
27138
27290
|
}
|