@camstack/types 1.1.16 → 1.1.17

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/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_sleep = require("./sleep-BQzZ7joF.js");
2
+ const require_sleep = require("./sleep-BabrCASa.js");
3
3
  const require_err_msg = require("./err-msg-COpsHMw2.js");
4
4
  let zod = require("zod");
5
5
  //#region src/health/wiring-health.ts
@@ -2772,6 +2772,203 @@ function createRuntimeStateBridge(params) {
2772
2772
  };
2773
2773
  }
2774
2774
  //#endregion
2775
+ //#region src/notification/format-transcode.ts
2776
+ /** Strip a small, safe subset of Markdown down to plain text. */
2777
+ function markdownToText(md) {
2778
+ return md.replace(/!\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/(\*\*|__)(.*?)\1/g, "$2").replace(/(\*|_)(.*?)\1/g, "$2").replace(/`([^`]*)`/g, "$1").replace(/^\s{0,3}#{1,6}\s*/gm, "").replace(/^\s{0,3}>\s?/gm, "").replace(/^\s{0,3}[-*+]\s+/gm, "").replace(/^\s{0,3}\d+\.\s+/gm, "").trim();
2779
+ }
2780
+ var HTML_ENTITIES = [
2781
+ [/ /g, " "],
2782
+ [/&/g, "&"],
2783
+ [/&lt;/g, "<"],
2784
+ [/&gt;/g, ">"],
2785
+ [/&quot;/g, "\""],
2786
+ [/&#39;/g, "'"]
2787
+ ];
2788
+ /** Strip HTML tags, decode a few entities, map block/br elements to newlines. */
2789
+ function htmlToText(html) {
2790
+ let out = html.replace(/<\s*br\s*\/?\s*>/gi, "\n").replace(/<\s*\/\s*(p|div|li|h[1-6])\s*>/gi, "\n").replace(/<[^>]+>/g, "");
2791
+ for (const [re, rep] of HTML_ENTITIES) out = out.replace(re, rep);
2792
+ return out.replace(/\n{3,}/g, "\n\n").trim();
2793
+ }
2794
+ var HTML_ESCAPES = [
2795
+ [/&/g, "&amp;"],
2796
+ [/</g, "&lt;"],
2797
+ [/>/g, "&gt;"],
2798
+ [/"/g, "&quot;"],
2799
+ [/'/g, "&#39;"]
2800
+ ];
2801
+ function escapeHtml(text) {
2802
+ let out = text;
2803
+ for (const [re, rep] of HTML_ESCAPES) out = out.replace(re, rep);
2804
+ return out;
2805
+ }
2806
+ /** Plain text → HTML-lite (escape + newlines to <br>). */
2807
+ function textToHtml(text) {
2808
+ return escapeHtml(text).replace(/\n/g, "<br>");
2809
+ }
2810
+ /** Markdown → HTML-lite (bold/italic/code/links; used e.g. for Pushover). */
2811
+ function markdownToHtmlLite(md) {
2812
+ return escapeHtml(md).replace(/(\*\*|__)(.*?)\1/g, "<b>$2</b>").replace(/(\*|_)(.*?)\1/g, "<i>$2</i>").replace(/`([^`]*)`/g, "<code>$1</code>").replace(/\[([^\]]*)\]\(([^)]*)\)/g, "<a href=\"$2\">$1</a>").replace(/\n/g, "<br>");
2813
+ }
2814
+ /**
2815
+ * Preference order when the source format is NOT supported — first supported
2816
+ * entry wins. Encodes the Apprise-style "degrade DOWN, but preserve rendering
2817
+ * where a richer target exists" policy:
2818
+ * - markdown → html (html-lite) before text (strip)
2819
+ * - html → text before markdown
2820
+ * - text → markdown before html (text is valid markdown)
2821
+ */
2822
+ var DEGRADE_ORDER = {
2823
+ text: [
2824
+ "text",
2825
+ "markdown",
2826
+ "html"
2827
+ ],
2828
+ markdown: [
2829
+ "markdown",
2830
+ "html",
2831
+ "text"
2832
+ ],
2833
+ html: [
2834
+ "html",
2835
+ "text",
2836
+ "markdown"
2837
+ ]
2838
+ };
2839
+ /** Pick the best target format the kind supports for a given source format. */
2840
+ function resolveFormat(source, supported) {
2841
+ for (const candidate of DEGRADE_ORDER[source]) if (supported.includes(candidate)) return candidate;
2842
+ return supported[0] ?? "text";
2843
+ }
2844
+ /** Transcode a body between formats. */
2845
+ function transcodeBody(body, from, to) {
2846
+ if (from === to) return body;
2847
+ if (to === "text") {
2848
+ if (from === "markdown") return markdownToText(body);
2849
+ if (from === "html") return htmlToText(body);
2850
+ }
2851
+ if (to === "html") {
2852
+ if (from === "text") return textToHtml(body);
2853
+ if (from === "markdown") return markdownToHtmlLite(body);
2854
+ }
2855
+ if (to === "markdown") {
2856
+ if (from === "text") return body;
2857
+ if (from === "html") return htmlToText(body);
2858
+ }
2859
+ return body;
2860
+ }
2861
+ //#endregion
2862
+ //#region src/notification/degrade-engine.ts
2863
+ function toResolvedLevel(level) {
2864
+ return {
2865
+ id: level.id,
2866
+ ordinal: level.ordinal,
2867
+ ...level.flags ? { flags: level.flags } : {},
2868
+ ...level.requires ? { requires: level.requires } : {}
2869
+ };
2870
+ }
2871
+ function resolveLevel(levels, n) {
2872
+ if (levels.length === 0) return null;
2873
+ if (n.level !== void 0) {
2874
+ const explicit = levels.find((l) => l.id === n.level);
2875
+ if (explicit) return toResolvedLevel(explicit);
2876
+ }
2877
+ const withOrdinal = levels.filter((l) => l.ordinal !== null);
2878
+ if (withOrdinal.length === 0) return toResolvedLevel(levels[0]);
2879
+ const priority = n.priority;
2880
+ return toResolvedLevel([...withOrdinal].sort((a, b) => {
2881
+ const da = Math.abs((a.ordinal ?? 0) - priority);
2882
+ const db = Math.abs((b.ordinal ?? 0) - priority);
2883
+ if (da !== db) return da - db;
2884
+ return (b.ordinal ?? 0) - (a.ordinal ?? 0);
2885
+ })[0]);
2886
+ }
2887
+ function splitBody(body, maxLen) {
2888
+ if (maxLen <= 0 || body.length <= maxLen) return [body];
2889
+ const parts = [];
2890
+ for (let i = 0; i < body.length; i += maxLen) parts.push(body.slice(i, i + maxLen));
2891
+ return parts;
2892
+ }
2893
+ /**
2894
+ * Prepare a canonical notification for one kind. Never throws — degradation is
2895
+ * always reported in `renderedAs`, never surfaced as an error.
2896
+ */
2897
+ function prepareNotification(caps, n) {
2898
+ const dropped = [];
2899
+ const sourceFormat = n.format;
2900
+ const format = resolveFormat(sourceFormat, caps.format);
2901
+ if (format !== sourceFormat) dropped.push("format");
2902
+ const transcoded = transcodeBody(n.body, sourceFormat, format);
2903
+ const level = resolveLevel(caps.levels, n);
2904
+ const inAttachments = n.attachments ?? [];
2905
+ const attachments = [];
2906
+ for (const att of inAttachments) {
2907
+ if (!caps.attachments.mediaTypes.includes(att.mediaType)) {
2908
+ dropped.push(`attachment:${att.mediaType}`);
2909
+ continue;
2910
+ }
2911
+ if (caps.attachments.mode === "url" && att.url === void 0) {
2912
+ dropped.push("attachment:noUrl");
2913
+ continue;
2914
+ }
2915
+ if (att.bytes !== void 0 && caps.attachments.maxBytes !== void 0 && att.bytes.length > caps.attachments.maxBytes) {
2916
+ dropped.push("attachment:maxBytes");
2917
+ continue;
2918
+ }
2919
+ if (attachments.length >= caps.attachments.max) {
2920
+ dropped.push("attachment:max");
2921
+ continue;
2922
+ }
2923
+ const needsFetch = caps.attachments.mode === "bytes" && att.bytes === void 0 && att.url !== void 0;
2924
+ attachments.push({
2925
+ mediaType: att.mediaType,
2926
+ ...att.url !== void 0 ? { url: att.url } : {},
2927
+ ...att.bytes !== void 0 ? { bytes: att.bytes } : {},
2928
+ ...att.mime !== void 0 ? { mime: att.mime } : {},
2929
+ ...att.name !== void 0 ? { name: att.name } : {},
2930
+ needsFetch
2931
+ });
2932
+ }
2933
+ const inActions = n.actions ?? [];
2934
+ const actions = inActions.slice(0, Math.max(0, caps.actions));
2935
+ if (inActions.length > actions.length) dropped.push("actions");
2936
+ let clickUrl = null;
2937
+ if (n.clickUrl !== void 0) if (caps.clickUrl) clickUrl = n.clickUrl;
2938
+ else dropped.push("clickUrl");
2939
+ let sound = null;
2940
+ if (n.sound !== void 0) if (caps.sound) sound = n.sound;
2941
+ else dropped.push("sound");
2942
+ let ttl = null;
2943
+ if (n.ttl !== void 0) if (caps.ttl) ttl = n.ttl;
2944
+ else dropped.push("ttl");
2945
+ const tag = n.tag ?? null;
2946
+ const bodyParts = splitBody(transcoded, caps.bodyMaxLen);
2947
+ const truncated = bodyParts.length > 1;
2948
+ const renderedAs = {
2949
+ level: level?.id ?? "",
2950
+ format,
2951
+ attachmentsSent: attachments.length,
2952
+ actionsSent: actions.length,
2953
+ truncated,
2954
+ dropped
2955
+ };
2956
+ return {
2957
+ body: bodyParts[0] ?? "",
2958
+ ...n.title !== void 0 ? { title: n.title } : {},
2959
+ format,
2960
+ level,
2961
+ attachments,
2962
+ actions,
2963
+ clickUrl,
2964
+ sound,
2965
+ ttl,
2966
+ tag,
2967
+ bodyParts,
2968
+ renderedAs
2969
+ };
2970
+ }
2971
+ //#endregion
2775
2972
  //#region src/capabilities/device-status.cap.ts
2776
2973
  /**
2777
2974
  * Generic device-level status snapshot. Auto-registered by `BaseDevice`
@@ -10342,8 +10539,14 @@ function createSystemProxy(api) {
10342
10539
  executeQuery: (input) => dispatch("nodes", "executeQuery", "mutation", input)
10343
10540
  },
10344
10541
  notificationOutput: {
10542
+ listTargetKinds: (input) => dispatch("notificationOutput", "listTargetKinds", "query", input),
10543
+ listTargets: (input) => dispatch("notificationOutput", "listTargets", "query", input),
10544
+ discoverTargets: (input) => dispatch("notificationOutput", "discoverTargets", "query", input),
10345
10545
  send: (input) => dispatch("notificationOutput", "send", "mutation", input),
10346
- sendTest: (input) => dispatch("notificationOutput", "sendTest", "mutation", input)
10546
+ testTarget: (input) => dispatch("notificationOutput", "testTarget", "mutation", input),
10547
+ upsertTarget: (input) => dispatch("notificationOutput", "upsertTarget", "mutation", input),
10548
+ deleteTarget: (input) => dispatch("notificationOutput", "deleteTarget", "mutation", input),
10549
+ setTargetEnabled: (input) => dispatch("notificationOutput", "setTargetEnabled", "mutation", input)
10347
10550
  },
10348
10551
  pipelineExecutor: {
10349
10552
  getAvailableEngines: (input) => dispatch("pipelineExecutor", "getAvailableEngines", "query", input),
@@ -14386,7 +14589,7 @@ var AddBrokerInputSchema = zod.z.object({
14386
14589
  });
14387
14590
  var AddBrokerResultSchema = zod.z.object({ id: zod.z.string() });
14388
14591
  var IdInputSchema = zod.z.object({ id: zod.z.string() });
14389
- var TestResultSchema = zod.z.discriminatedUnion("ok", [zod.z.object({
14592
+ var TestResultSchema$1 = zod.z.discriminatedUnion("ok", [zod.z.object({
14390
14593
  ok: zod.z.literal(true),
14391
14594
  latencyMs: zod.z.number()
14392
14595
  }), zod.z.object({
@@ -14423,7 +14626,7 @@ var mqttBrokerCapability = {
14423
14626
  getBrokerConfig: require_sleep.method(IdInputSchema, BrokerConnectionDetailsSchema),
14424
14627
  addBroker: require_sleep.method(AddBrokerInputSchema, AddBrokerResultSchema, { kind: "mutation" }),
14425
14628
  removeBroker: require_sleep.method(IdInputSchema, zod.z.void(), { kind: "mutation" }),
14426
- testConnection: require_sleep.method(IdInputSchema, TestResultSchema, { kind: "mutation" }),
14629
+ testConnection: require_sleep.method(IdInputSchema, TestResultSchema$1, { kind: "mutation" }),
14427
14630
  startEmbeddedBroker: require_sleep.method(StartEmbeddedInputSchema, StartEmbeddedResultSchema, { kind: "mutation" }),
14428
14631
  stopEmbeddedBroker: require_sleep.method(IdInputSchema, zod.z.void(), { kind: "mutation" }),
14429
14632
  getStatus: require_sleep.method(zod.z.void(), StatusSchema)
@@ -14483,30 +14686,212 @@ var networkAccessCapability = {
14483
14686
  };
14484
14687
  //#endregion
14485
14688
  //#region src/capabilities/notification-output.cap.ts
14689
+ /**
14690
+ * notification-output — canonical, capability-gated notification delivery.
14691
+ *
14692
+ * Apprise-derived model (see
14693
+ * `docs/superpowers/specs/2026-07-03-notification-output-notifier-matrix.md`):
14694
+ * callers emit ONE canonical `Notification`; each provider declares a
14695
+ * per-kind capability descriptor (`TargetKind`), and the pure degrade
14696
+ * engine (`@camstack/types` `prepareNotification`) transcodes / degrades the
14697
+ * message to what the kind supports — callers never special-case a service.
14698
+ *
14699
+ * DESIGN DECISIONS (locked):
14700
+ * - Target CRUD lives on THIS cap (`upsertTarget` / `deleteTarget` /
14701
+ * `setTargetEnabled`), each provider persisting via the `settings-store`
14702
+ * cap. Rationale: the admin UI needs one uniform surface across the
14703
+ * notifiers addon AND the HA addon; the addon-`globalSettingsSchema`-array
14704
+ * alternative would fork the UI per addon and cannot host the
14705
+ * discovery→adopt flow.
14706
+ * - `listTargetKinds` / `listTargets` / `discoverTargets` return arrays →
14707
+ * the generated cap-mount auto-`concatCollection`-fans them across every
14708
+ * registered provider (notifiers addon + HA addon) so one catalog is
14709
+ * routable. `send` / `testTarget` / CRUD route to ONE provider by the
14710
+ * `addonId` the generated collection router extracts from the call input.
14711
+ * - `Attachment.bytes` is `Uint8Array`. Transport-safe: superjson (the tRPC
14712
+ * transformer) + UDS MsgPack both round-trip typed arrays — already used by
14713
+ * `storage` / `storage-provider` / `recording` caps over the same path. No
14714
+ * base64 fallback needed.
14715
+ *
14716
+ * TODO (deferred, closed-set change — separate decision): add
14717
+ * `providerKind: 'notify'` so notification providers surface on the unified
14718
+ * admin "Integrations" page.
14719
+ */
14720
+ /**
14721
+ * Zentik-derived typed-media enum — the superset across every kind. Each
14722
+ * adapter picks what it supports and the degrade engine filters the rest.
14723
+ */
14724
+ var AttachmentMediaTypeSchema = zod.z.enum([
14725
+ "image",
14726
+ "video",
14727
+ "gif",
14728
+ "audio",
14729
+ "icon"
14730
+ ]);
14731
+ /**
14732
+ * A single attachment. Exactly one of `url` (remote source, most adapters
14733
+ * prefer this) or `bytes` (inline source; required for Pushover-style
14734
+ * bytes-only kinds) MUST be present — the degrade engine expresses a
14735
+ * url→bytes fetch as a `needsFetch` directive the adapter executes.
14736
+ */
14737
+ var AttachmentSchema = zod.z.object({
14738
+ mediaType: AttachmentMediaTypeSchema,
14739
+ url: zod.z.string().optional(),
14740
+ bytes: zod.z.instanceof(Uint8Array).optional(),
14741
+ mime: zod.z.string().optional(),
14742
+ name: zod.z.string().optional()
14743
+ }).refine((a) => a.url !== void 0 || a.bytes !== void 0, { message: "Attachment requires either `url` or `bytes`" });
14744
+ var NotificationFormatSchema = zod.z.enum([
14745
+ "text",
14746
+ "markdown",
14747
+ "html"
14748
+ ]);
14749
+ /** A single tap-through action button. */
14750
+ var NotificationActionSchema = zod.z.object({
14751
+ id: zod.z.string(),
14752
+ label: zod.z.string(),
14753
+ url: zod.z.string().optional()
14754
+ });
14755
+ /**
14756
+ * The canonical notification. `body` is the only hard field (Apprise model).
14757
+ * `priority` is a 5-level ORDINAL (1=lowest … 3=normal(default) … 5=urgent),
14758
+ * NOT a fixed severity enum — each kind declares its own `caps.levels` and
14759
+ * the adapter maps this ordinal onto its native level. `level?` is an
14760
+ * optional kind-native level id (`emergency`, `silent`, …) that overrides
14761
+ * `priority` for that one target.
14762
+ */
14486
14763
  var NotificationSchema = zod.z.object({
14487
- title: zod.z.string(),
14488
14764
  body: zod.z.string(),
14489
- imageUrl: zod.z.string().optional(),
14765
+ title: zod.z.string().optional(),
14766
+ format: NotificationFormatSchema.default("text"),
14767
+ priority: zod.z.number().int().min(1).max(5).default(3),
14768
+ level: zod.z.string().optional(),
14769
+ attachments: zod.z.array(AttachmentSchema).optional(),
14770
+ clickUrl: zod.z.string().optional(),
14771
+ actions: zod.z.array(NotificationActionSchema).optional(),
14772
+ sound: zod.z.string().optional(),
14773
+ ttl: zod.z.number().optional(),
14774
+ tag: zod.z.string().optional(),
14490
14775
  deviceId: zod.z.number().optional(),
14491
14776
  eventId: zod.z.string().optional(),
14492
- priority: zod.z.enum([
14493
- "low",
14494
- "normal",
14495
- "high",
14496
- "critical"
14497
- ]).default("normal"),
14498
14777
  metadata: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
14499
14778
  });
14779
+ /** One declared native severity/priority level for a kind. */
14780
+ var TargetKindLevelSchema = zod.z.object({
14781
+ id: zod.z.string(),
14782
+ label: zod.z.string(),
14783
+ /** Which canonical priority (1..5) this level maps to. `null` = qualitative-only. */
14784
+ ordinal: zod.z.number().int().min(1).max(5).nullable(),
14785
+ flags: zod.z.object({
14786
+ critical: zod.z.boolean().optional(),
14787
+ silent: zod.z.boolean().optional(),
14788
+ noPush: zod.z.boolean().optional()
14789
+ }).optional(),
14790
+ /** e.g. Pushover `emergency` requires `retry` / `expire`. */
14791
+ requires: zod.z.array(zod.z.string()).optional(),
14792
+ description: zod.z.string().optional()
14793
+ });
14794
+ /** Attachment capabilities for a kind (drives the degrade engine + test panel). */
14795
+ var TargetKindAttachmentsCapsSchema = zod.z.object({
14796
+ mediaTypes: zod.z.array(AttachmentMediaTypeSchema),
14797
+ mode: zod.z.enum([
14798
+ "url",
14799
+ "bytes",
14800
+ "both"
14801
+ ]),
14802
+ max: zod.z.number().int().nonnegative(),
14803
+ maxBytes: zod.z.number().int().positive().optional()
14804
+ });
14805
+ /** The full capability block consulted before dispatch. */
14806
+ var TargetKindCapsSchema = zod.z.object({
14807
+ attachments: TargetKindAttachmentsCapsSchema,
14808
+ /** Max action buttons (0 = none). */
14809
+ actions: zod.z.number().int().nonnegative(),
14810
+ levels: zod.z.array(TargetKindLevelSchema),
14811
+ format: zod.z.array(NotificationFormatSchema),
14812
+ clickUrl: zod.z.boolean(),
14813
+ sound: zod.z.boolean(),
14814
+ ttl: zod.z.boolean(),
14815
+ bodyMaxLen: zod.z.number().int().positive()
14816
+ });
14817
+ /**
14818
+ * `configSchema` is a `ConfigUISchema` tree passed through to the admin
14819
+ * FormBuilder. Stored as `z.unknown()` at the cap seam (mirrors
14820
+ * `device-provider.getChildCreationSchema` `CreationSchemaOutputSchema`) —
14821
+ * the union is large and not meant for runtime validation here; the exported
14822
+ * `TargetKind` type re-tightens `configSchema` to `ConfigUISchema`.
14823
+ */
14824
+ var ConfigSchemaPassthrough = zod.z.unknown();
14825
+ var TargetKindSchema = zod.z.object({
14826
+ kind: zod.z.string(),
14827
+ label: zod.z.string(),
14828
+ icon: zod.z.string(),
14829
+ /** Stamped by each provider so the concat-fanned catalog stays routable. */
14830
+ addonId: zod.z.string(),
14831
+ configSchema: ConfigSchemaPassthrough,
14832
+ supportsDiscovery: zod.z.boolean(),
14833
+ caps: TargetKindCapsSchema
14834
+ });
14835
+ /**
14836
+ * A persisted target. `config` holds secrets; providers REDACT secret fields
14837
+ * (return a presence marker only) when serving `listTargets` — never
14838
+ * round-trip a stored secret to the UI.
14839
+ */
14840
+ var TargetSchema = zod.z.object({
14841
+ id: zod.z.string(),
14842
+ name: zod.z.string(),
14843
+ kind: zod.z.string(),
14844
+ addonId: zod.z.string(),
14845
+ enabled: zod.z.boolean(),
14846
+ config: zod.z.record(zod.z.string(), zod.z.unknown())
14847
+ });
14848
+ /** A discovery-surfaced candidate (config is partial + non-secret). */
14849
+ var DiscoveredTargetSchema = zod.z.object({
14850
+ kind: zod.z.string(),
14851
+ suggestedName: zod.z.string(),
14852
+ config: zod.z.record(zod.z.string(), zod.z.unknown())
14853
+ });
14854
+ /** The degrade engine's report — what was resolved / dropped / degraded. */
14855
+ var RenderedAsSchema = zod.z.object({
14856
+ level: zod.z.string(),
14857
+ format: NotificationFormatSchema,
14858
+ attachmentsSent: zod.z.number().int().nonnegative(),
14859
+ actionsSent: zod.z.number().int().nonnegative(),
14860
+ truncated: zod.z.boolean(),
14861
+ dropped: zod.z.array(zod.z.string())
14862
+ });
14863
+ var SendResultSchema = zod.z.object({
14864
+ success: zod.z.boolean(),
14865
+ error: zod.z.string().optional(),
14866
+ renderedAs: RenderedAsSchema.optional()
14867
+ });
14868
+ /** Same shape as SendResult — kept as a distinct name for the test panel. */
14869
+ var TestResultSchema = SendResultSchema;
14500
14870
  var notificationOutputCapability = {
14501
14871
  name: "notification-output",
14502
14872
  scope: "system",
14503
14873
  mode: "collection",
14504
14874
  methods: {
14505
- send: require_sleep.method(NotificationSchema, zod.z.void(), { kind: "mutation" }),
14506
- sendTest: require_sleep.method(zod.z.void(), zod.z.object({
14507
- success: zod.z.boolean(),
14508
- error: zod.z.string().optional()
14509
- }), { kind: "mutation" })
14875
+ listTargetKinds: require_sleep.method(zod.z.object({}), zod.z.array(TargetKindSchema)),
14876
+ listTargets: require_sleep.method(zod.z.object({}), zod.z.array(TargetSchema)),
14877
+ discoverTargets: require_sleep.method(zod.z.object({
14878
+ kind: zod.z.string(),
14879
+ config: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
14880
+ }), zod.z.array(DiscoveredTargetSchema)),
14881
+ send: require_sleep.method(zod.z.object({
14882
+ targetId: zod.z.string(),
14883
+ notification: NotificationSchema
14884
+ }), SendResultSchema, { kind: "mutation" }),
14885
+ testTarget: require_sleep.method(zod.z.object({
14886
+ targetId: zod.z.string(),
14887
+ sample: NotificationSchema.optional()
14888
+ }), TestResultSchema, { kind: "mutation" }),
14889
+ upsertTarget: require_sleep.method(zod.z.object({ target: TargetSchema }), TargetSchema, { kind: "mutation" }),
14890
+ deleteTarget: require_sleep.method(zod.z.object({ targetId: zod.z.string() }), zod.z.void(), { kind: "mutation" }),
14891
+ setTargetEnabled: require_sleep.method(zod.z.object({
14892
+ targetId: zod.z.string(),
14893
+ enabled: zod.z.boolean()
14894
+ }), zod.z.void(), { kind: "mutation" })
14510
14895
  }
14511
14896
  };
14512
14897
  //#endregion
@@ -15378,10 +15763,11 @@ var pipelineOrchestratorCapability = {
15378
15763
  }))),
15379
15764
  /**
15380
15765
  * Get one camera's decoder placement (computed if not yet pinned).
15381
- * Consumed by `stream-broker.createBroker` so decoder provider
15382
- * selection is deterministic fixes the 2026-04-18 race where
15383
- * `capProviders[0]` silently picked ffmpeg-on-agent-0 for a
15384
- * hub-assigned camera.
15766
+ *
15767
+ * ADVISORY today: reports the orchestrator's decoder preference only.
15768
+ * Actual decode placement is broker-owned (local-node pin + frame-plane
15769
+ * co-location guard). Reserved to become the binding source/decoder-owner
15770
+ * control in the stream-LB epic (Phase 2).
15385
15771
  *
15386
15772
  * `pipelineNodeId` is the node already chosen to run inference for
15387
15773
  * this camera. When provided, the balancer prefers co-location with
@@ -23278,13 +23664,49 @@ var METHOD_ACCESS_MAP = Object.freeze({
23278
23664
  addonId: null,
23279
23665
  access: "create"
23280
23666
  },
23667
+ "notificationOutput.deleteTarget": {
23668
+ capName: "notification-output",
23669
+ capScope: "system",
23670
+ addonId: null,
23671
+ access: "delete"
23672
+ },
23673
+ "notificationOutput.discoverTargets": {
23674
+ capName: "notification-output",
23675
+ capScope: "system",
23676
+ addonId: null,
23677
+ access: "view"
23678
+ },
23679
+ "notificationOutput.listTargetKinds": {
23680
+ capName: "notification-output",
23681
+ capScope: "system",
23682
+ addonId: null,
23683
+ access: "view"
23684
+ },
23685
+ "notificationOutput.listTargets": {
23686
+ capName: "notification-output",
23687
+ capScope: "system",
23688
+ addonId: null,
23689
+ access: "view"
23690
+ },
23281
23691
  "notificationOutput.send": {
23282
23692
  capName: "notification-output",
23283
23693
  capScope: "system",
23284
23694
  addonId: null,
23285
23695
  access: "create"
23286
23696
  },
23287
- "notificationOutput.sendTest": {
23697
+ "notificationOutput.setTargetEnabled": {
23698
+ capName: "notification-output",
23699
+ capScope: "system",
23700
+ addonId: null,
23701
+ access: "create"
23702
+ },
23703
+ "notificationOutput.testTarget": {
23704
+ capName: "notification-output",
23705
+ capScope: "system",
23706
+ addonId: null,
23707
+ access: "create"
23708
+ },
23709
+ "notificationOutput.upsertTarget": {
23288
23710
  capName: "notification-output",
23289
23711
  capScope: "system",
23290
23712
  addonId: null,
@@ -26053,6 +26475,8 @@ exports.ApiKeyRecordSchema = ApiKeyRecordSchema;
26053
26475
  exports.ApiKeySummarySchema = ApiKeySummarySchema;
26054
26476
  exports.ArchiveEntrySchema = ArchiveEntrySchema;
26055
26477
  exports.ArchiveManifestSchema = ArchiveManifestSchema;
26478
+ exports.AttachmentMediaTypeSchema = AttachmentMediaTypeSchema;
26479
+ exports.AttachmentSchema = AttachmentSchema;
26056
26480
  exports.AudioAnalysisResultSchema = AudioAnalysisResultSchema;
26057
26481
  exports.AudioAnalysisSettingsSchema = AudioAnalysisSettingsSchema;
26058
26482
  exports.AudioChunkInputSchema = AudioChunkInputSchema;
@@ -26210,6 +26634,7 @@ exports.DeviceType = require_sleep.DeviceType;
26210
26634
  exports.DiscoveredChildDeviceSchema = DiscoveredChildDeviceSchema;
26211
26635
  exports.DiscoveredChildStatusSchema = DiscoveredChildStatusSchema;
26212
26636
  exports.DiscoveredDeviceSchema = DiscoveredDeviceSchema;
26637
+ exports.DiscoveredTargetSchema = DiscoveredTargetSchema;
26213
26638
  exports.DisposerChain = require_sleep.DisposerChain;
26214
26639
  exports.DoorbellPressEventSchema = DoorbellPressEventSchema;
26215
26640
  exports.DoorbellStatusSchema = DoorbellStatusSchema;
@@ -26316,6 +26741,8 @@ exports.NativeObjectDetectionStatusSchema = NativeObjectDetectionStatusSchema;
26316
26741
  exports.NetworkAccessStatusSchema = NetworkAccessStatusSchema;
26317
26742
  exports.NetworkAddressSchema = NetworkAddressSchema;
26318
26743
  exports.NetworkEndpointSchema = NetworkEndpointSchema;
26744
+ exports.NotificationActionSchema = NotificationActionSchema;
26745
+ exports.NotificationFormatSchema = NotificationFormatSchema;
26319
26746
  exports.NotificationHistoryEntrySchema = NotificationHistoryEntrySchema;
26320
26747
  exports.NotificationRuleSchema = NotificationRuleSchema;
26321
26748
  exports.NotificationSchema = NotificationSchema;
@@ -26396,6 +26823,7 @@ exports.RecordingStorageUsageSchema = RecordingStorageUsageSchema;
26396
26823
  exports.RecordingTriggersSchema = RecordingTriggersSchema;
26397
26824
  exports.RecordingWeekdaySchema = RecordingWeekdaySchema;
26398
26825
  exports.RegisteredStreamSchema = RegisteredStreamSchema;
26826
+ exports.RenderedAsSchema = RenderedAsSchema;
26399
26827
  exports.ReportMotionInputSchema = ReportMotionInputSchema;
26400
26828
  exports.RingBuffer = RingBuffer;
26401
26829
  exports.RtpSourceSchema = RtpSourceSchema;
@@ -26417,6 +26845,7 @@ exports.ScriptRunnerStatusSchema = ScriptRunnerStatusSchema;
26417
26845
  exports.SearchResultSchema = SearchResultSchema;
26418
26846
  exports.SendEmailInputSchema = SendEmailInputSchema;
26419
26847
  exports.SendEmailResultSchema = SendEmailResultSchema;
26848
+ exports.SendResultSchema = SendResultSchema;
26420
26849
  exports.SettingsPatchSchema = SettingsPatchSchema;
26421
26850
  exports.SettingsRecordSchema = SettingsRecordSchema;
26422
26851
  exports.SettingsSchemaWithValuesSchema = SettingsSchemaWithValuesSchema;
@@ -26466,8 +26895,13 @@ exports.SystemMirror = SystemMirror;
26466
26895
  exports.TIMEZONES = TIMEZONES;
26467
26896
  exports.TamperStatusSchema = TamperStatusSchema;
26468
26897
  exports.TankStatusSchema = TankStatusSchema;
26898
+ exports.TargetKindCapsSchema = TargetKindCapsSchema;
26899
+ exports.TargetKindLevelSchema = TargetKindLevelSchema;
26900
+ exports.TargetKindSchema = TargetKindSchema;
26901
+ exports.TargetSchema = TargetSchema;
26469
26902
  exports.TemperatureSensorStatusSchema = TemperatureSensorStatusSchema;
26470
26903
  exports.TestConnectionResultSchema = TestConnectionResultSchema$1;
26904
+ exports.TestResultSchema = TestResultSchema;
26471
26905
  exports.ToastSchema = ToastSchema;
26472
26906
  exports.TokenScopeSchema = TokenScopeSchema;
26473
26907
  exports.TopologyNodeSchema = TopologyNodeSchema;
@@ -26613,6 +27047,7 @@ exports.getAudioMacroClassIds = getAudioMacroClassIds;
26613
27047
  exports.getByPath = getByPath;
26614
27048
  exports.getCapsByProviderKind = getCapsByProviderKind;
26615
27049
  exports.hfModelUrl = hfModelUrl;
27050
+ exports.htmlToText = htmlToText;
26616
27051
  exports.humidifierCapability = humidifierCapability;
26617
27052
  exports.humiditySensorCapability = humiditySensorCapability;
26618
27053
  exports.hydrateSchema = require_sleep.hydrateSchema;
@@ -26636,6 +27071,8 @@ exports.logDestinationCapability = logDestinationCapability;
26636
27071
  exports.makeProfileBrokerId = require_sleep.makeProfileBrokerId;
26637
27072
  exports.makeSourceBrokerId = require_sleep.makeSourceBrokerId;
26638
27073
  exports.mapAudioLabelToMacro = mapAudioLabelToMacro;
27074
+ exports.markdownToHtmlLite = markdownToHtmlLite;
27075
+ exports.markdownToText = markdownToText;
26639
27076
  exports.maskUrlCredentials = maskUrlCredentials;
26640
27077
  exports.mediaPlayerCapability = mediaPlayerCapability;
26641
27078
  exports.mergeSourceInfo = mergeSourceInfo;
@@ -26678,6 +27115,7 @@ exports.pipelineRunnerCapability = pipelineRunnerCapability;
26678
27115
  exports.plateGalleryCapability = plateGalleryCapability;
26679
27116
  exports.platformProbeCapability = platformProbeCapability;
26680
27117
  exports.powerMeterCapability = powerMeterCapability;
27118
+ exports.prepareNotification = prepareNotification;
26681
27119
  exports.presenceCapability = presenceCapability;
26682
27120
  exports.pressureSensorCapability = pressureSensorCapability;
26683
27121
  exports.privacyMaskCapability = privacyMaskCapability;
@@ -26697,6 +27135,7 @@ exports.resolveAddonRuntime = resolveAddonRuntime;
26697
27135
  exports.resolveCapMount = require_sleep.resolveCapMount;
26698
27136
  exports.resolveDetectionRuntime = resolveDetectionRuntime;
26699
27137
  exports.resolveDeviceProfile = resolveDeviceProfile;
27138
+ exports.resolveFormat = resolveFormat;
26700
27139
  exports.resolveModelFormat = resolveModelFormat;
26701
27140
  exports.resolveRunnerId = resolveRunnerId;
26702
27141
  exports.restreamerCapability = restreamerCapability;
@@ -26733,9 +27172,11 @@ exports.taskLogEntrySchema = taskLogEntrySchema;
26733
27172
  exports.taskPhaseSchema = taskPhaseSchema;
26734
27173
  exports.taskTargetSchema = taskTargetSchema;
26735
27174
  exports.temperatureSensorCapability = temperatureSensorCapability;
27175
+ exports.textToHtml = textToHtml;
26736
27176
  exports.toDeviceSummary = toDeviceSummary;
26737
27177
  exports.toStreamSourceEntry = toStreamSourceEntry;
26738
27178
  exports.toastCapability = toastCapability;
27179
+ exports.transcodeBody = transcodeBody;
26739
27180
  exports.turnProviderCapability = turnProviderCapability;
26740
27181
  exports.updateCapability = updateCapability;
26741
27182
  exports.userManagementCapability = userManagementCapability;