@camstack/types 1.1.15 → 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/addon.js +1 -1
- package/dist/addon.mjs +1 -1
- package/dist/capabilities/audio-codec.cap.d.ts +1 -0
- package/dist/capabilities/camera-streams.cap.d.ts +2 -0
- package/dist/capabilities/index.d.ts +1 -1
- package/dist/capabilities/notification-output.cap.d.ts +503 -24
- package/dist/capabilities/pipeline-orchestrator.cap.d.ts +6 -5
- package/dist/capabilities/schemas/streaming-shared.d.ts +2 -0
- package/dist/capabilities/storage.cap.d.ts +4 -0
- package/dist/capabilities/stream-broker.cap.d.ts +5 -0
- package/dist/capabilities/stream-catalog.cap.d.ts +2 -0
- package/dist/generated/addon-api.d.ts +392 -74
- package/dist/generated/method-access-map.d.ts +1 -1
- package/dist/generated/system-proxy.d.ts +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +483 -23
- package/dist/index.mjs +465 -24
- package/dist/interfaces/notification.d.ts +24 -14
- package/dist/interfaces/storage-location-declaration.d.ts +4 -0
- package/dist/interfaces/stream-broker.d.ts +13 -2
- package/dist/notification/degrade-engine.d.ts +60 -0
- package/dist/notification/format-transcode.d.ts +19 -0
- package/dist/{sleep-BQzZ7joF.js → sleep-BabrCASa.js} +1 -0
- package/dist/{sleep-C2M2zF7x.mjs → sleep-MHm--th-.mjs} +1 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_sleep = require("./sleep-
|
|
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
|
|
@@ -832,7 +832,21 @@ var StorageLocationDeclarationSchema = zod.z.object({
|
|
|
832
832
|
* slots (e.g. `recordingsLow` → `recordings`) so operators only need to
|
|
833
833
|
* configure the primary location.
|
|
834
834
|
*/
|
|
835
|
-
defaultsTo: zod.z.string().optional()
|
|
835
|
+
defaultsTo: zod.z.string().optional(),
|
|
836
|
+
/**
|
|
837
|
+
* Which node root the seeded `<id>:default` instance is placed under on a
|
|
838
|
+
* FRESH install:
|
|
839
|
+
* - `'data'` (default) — the node's data dir (`CAMSTACK_DATA` / boot dir),
|
|
840
|
+
* the appData volume. Right for small/durable data (backups, logs, models).
|
|
841
|
+
* - `'media'` — the dedicated media volume (`CAMSTACK_MEDIA_ROOT`) when that
|
|
842
|
+
* env is set, else falls back to the data root. Right for bulky, hot media
|
|
843
|
+
* (recordings, event media) that should stay off the appData disk.
|
|
844
|
+
*
|
|
845
|
+
* Only affects the seeded default's `basePath`; operators can repoint any
|
|
846
|
+
* location afterwards, and a `defaultsTo` slot inherits its parent's root
|
|
847
|
+
* regardless of this field. Absent (the common case) is treated as `'data'`.
|
|
848
|
+
*/
|
|
849
|
+
defaultRoot: zod.z.enum(["data", "media"]).optional()
|
|
836
850
|
});
|
|
837
851
|
//#endregion
|
|
838
852
|
//#region src/interfaces/device-capabilities/camera.ts
|
|
@@ -2758,6 +2772,203 @@ function createRuntimeStateBridge(params) {
|
|
|
2758
2772
|
};
|
|
2759
2773
|
}
|
|
2760
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
|
+
[/</g, "<"],
|
|
2784
|
+
[/>/g, ">"],
|
|
2785
|
+
[/"/g, "\""],
|
|
2786
|
+
[/'/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, "&"],
|
|
2796
|
+
[/</g, "<"],
|
|
2797
|
+
[/>/g, ">"],
|
|
2798
|
+
[/"/g, """],
|
|
2799
|
+
[/'/g, "'"]
|
|
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
|
|
2761
2972
|
//#region src/capabilities/device-status.cap.ts
|
|
2762
2973
|
/**
|
|
2763
2974
|
* Generic device-level status snapshot. Auto-registered by `BaseDevice`
|
|
@@ -3504,6 +3715,10 @@ var RtspRestreamEntrySchema = zod.z.object({
|
|
|
3504
3715
|
var BrokerRtspClientSchema = zod.z.object({
|
|
3505
3716
|
sessionId: zod.z.string(),
|
|
3506
3717
|
remoteAddr: zod.z.string(),
|
|
3718
|
+
/** Client `User-Agent` (e.g. `recorder` for the recorder's RTSP pull), or
|
|
3719
|
+
* null/absent when the client sent none. Lets the UI label a consumer by
|
|
3720
|
+
* purpose. Optional so a client built against an older schema stays valid. */
|
|
3721
|
+
userAgent: zod.z.string().nullish(),
|
|
3507
3722
|
playing: zod.z.boolean(),
|
|
3508
3723
|
muted: zod.z.boolean(),
|
|
3509
3724
|
connectedAt: zod.z.number(),
|
|
@@ -10324,8 +10539,14 @@ function createSystemProxy(api) {
|
|
|
10324
10539
|
executeQuery: (input) => dispatch("nodes", "executeQuery", "mutation", input)
|
|
10325
10540
|
},
|
|
10326
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),
|
|
10327
10545
|
send: (input) => dispatch("notificationOutput", "send", "mutation", input),
|
|
10328
|
-
|
|
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)
|
|
10329
10550
|
},
|
|
10330
10551
|
pipelineExecutor: {
|
|
10331
10552
|
getAvailableEngines: (input) => dispatch("pipelineExecutor", "getAvailableEngines", "query", input),
|
|
@@ -11888,6 +12109,7 @@ var audioCodecCapability = {
|
|
|
11888
12109
|
name: "audio-codec",
|
|
11889
12110
|
scope: "system",
|
|
11890
12111
|
mode: "singleton",
|
|
12112
|
+
preferredProvider: "audio-codec-ffmpeg",
|
|
11891
12113
|
methods: {
|
|
11892
12114
|
/** Probe the local runtime and return the supported codec matrix. */
|
|
11893
12115
|
listSupportedCodecs: require_sleep.method(zod.z.void(), zod.z.array(AudioCodecInfoSchema).readonly()),
|
|
@@ -14367,7 +14589,7 @@ var AddBrokerInputSchema = zod.z.object({
|
|
|
14367
14589
|
});
|
|
14368
14590
|
var AddBrokerResultSchema = zod.z.object({ id: zod.z.string() });
|
|
14369
14591
|
var IdInputSchema = zod.z.object({ id: zod.z.string() });
|
|
14370
|
-
var TestResultSchema = zod.z.discriminatedUnion("ok", [zod.z.object({
|
|
14592
|
+
var TestResultSchema$1 = zod.z.discriminatedUnion("ok", [zod.z.object({
|
|
14371
14593
|
ok: zod.z.literal(true),
|
|
14372
14594
|
latencyMs: zod.z.number()
|
|
14373
14595
|
}), zod.z.object({
|
|
@@ -14404,7 +14626,7 @@ var mqttBrokerCapability = {
|
|
|
14404
14626
|
getBrokerConfig: require_sleep.method(IdInputSchema, BrokerConnectionDetailsSchema),
|
|
14405
14627
|
addBroker: require_sleep.method(AddBrokerInputSchema, AddBrokerResultSchema, { kind: "mutation" }),
|
|
14406
14628
|
removeBroker: require_sleep.method(IdInputSchema, zod.z.void(), { kind: "mutation" }),
|
|
14407
|
-
testConnection: require_sleep.method(IdInputSchema, TestResultSchema, { kind: "mutation" }),
|
|
14629
|
+
testConnection: require_sleep.method(IdInputSchema, TestResultSchema$1, { kind: "mutation" }),
|
|
14408
14630
|
startEmbeddedBroker: require_sleep.method(StartEmbeddedInputSchema, StartEmbeddedResultSchema, { kind: "mutation" }),
|
|
14409
14631
|
stopEmbeddedBroker: require_sleep.method(IdInputSchema, zod.z.void(), { kind: "mutation" }),
|
|
14410
14632
|
getStatus: require_sleep.method(zod.z.void(), StatusSchema)
|
|
@@ -14464,30 +14686,212 @@ var networkAccessCapability = {
|
|
|
14464
14686
|
};
|
|
14465
14687
|
//#endregion
|
|
14466
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
|
+
*/
|
|
14467
14763
|
var NotificationSchema = zod.z.object({
|
|
14468
|
-
title: zod.z.string(),
|
|
14469
14764
|
body: zod.z.string(),
|
|
14470
|
-
|
|
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(),
|
|
14471
14775
|
deviceId: zod.z.number().optional(),
|
|
14472
14776
|
eventId: zod.z.string().optional(),
|
|
14473
|
-
priority: zod.z.enum([
|
|
14474
|
-
"low",
|
|
14475
|
-
"normal",
|
|
14476
|
-
"high",
|
|
14477
|
-
"critical"
|
|
14478
|
-
]).default("normal"),
|
|
14479
14777
|
metadata: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
|
|
14480
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;
|
|
14481
14870
|
var notificationOutputCapability = {
|
|
14482
14871
|
name: "notification-output",
|
|
14483
14872
|
scope: "system",
|
|
14484
14873
|
mode: "collection",
|
|
14485
14874
|
methods: {
|
|
14486
|
-
|
|
14487
|
-
|
|
14488
|
-
|
|
14489
|
-
|
|
14490
|
-
|
|
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" })
|
|
14491
14895
|
}
|
|
14492
14896
|
};
|
|
14493
14897
|
//#endregion
|
|
@@ -15359,10 +15763,11 @@ var pipelineOrchestratorCapability = {
|
|
|
15359
15763
|
}))),
|
|
15360
15764
|
/**
|
|
15361
15765
|
* Get one camera's decoder placement (computed if not yet pinned).
|
|
15362
|
-
*
|
|
15363
|
-
*
|
|
15364
|
-
*
|
|
15365
|
-
*
|
|
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).
|
|
15366
15771
|
*
|
|
15367
15772
|
* `pipelineNodeId` is the node already chosen to run inference for
|
|
15368
15773
|
* this camera. When provided, the balancer prefers co-location with
|
|
@@ -23259,13 +23664,49 @@ var METHOD_ACCESS_MAP = Object.freeze({
|
|
|
23259
23664
|
addonId: null,
|
|
23260
23665
|
access: "create"
|
|
23261
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
|
+
},
|
|
23262
23691
|
"notificationOutput.send": {
|
|
23263
23692
|
capName: "notification-output",
|
|
23264
23693
|
capScope: "system",
|
|
23265
23694
|
addonId: null,
|
|
23266
23695
|
access: "create"
|
|
23267
23696
|
},
|
|
23268
|
-
"notificationOutput.
|
|
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": {
|
|
23269
23710
|
capName: "notification-output",
|
|
23270
23711
|
capScope: "system",
|
|
23271
23712
|
addonId: null,
|
|
@@ -26034,6 +26475,8 @@ exports.ApiKeyRecordSchema = ApiKeyRecordSchema;
|
|
|
26034
26475
|
exports.ApiKeySummarySchema = ApiKeySummarySchema;
|
|
26035
26476
|
exports.ArchiveEntrySchema = ArchiveEntrySchema;
|
|
26036
26477
|
exports.ArchiveManifestSchema = ArchiveManifestSchema;
|
|
26478
|
+
exports.AttachmentMediaTypeSchema = AttachmentMediaTypeSchema;
|
|
26479
|
+
exports.AttachmentSchema = AttachmentSchema;
|
|
26037
26480
|
exports.AudioAnalysisResultSchema = AudioAnalysisResultSchema;
|
|
26038
26481
|
exports.AudioAnalysisSettingsSchema = AudioAnalysisSettingsSchema;
|
|
26039
26482
|
exports.AudioChunkInputSchema = AudioChunkInputSchema;
|
|
@@ -26191,6 +26634,7 @@ exports.DeviceType = require_sleep.DeviceType;
|
|
|
26191
26634
|
exports.DiscoveredChildDeviceSchema = DiscoveredChildDeviceSchema;
|
|
26192
26635
|
exports.DiscoveredChildStatusSchema = DiscoveredChildStatusSchema;
|
|
26193
26636
|
exports.DiscoveredDeviceSchema = DiscoveredDeviceSchema;
|
|
26637
|
+
exports.DiscoveredTargetSchema = DiscoveredTargetSchema;
|
|
26194
26638
|
exports.DisposerChain = require_sleep.DisposerChain;
|
|
26195
26639
|
exports.DoorbellPressEventSchema = DoorbellPressEventSchema;
|
|
26196
26640
|
exports.DoorbellStatusSchema = DoorbellStatusSchema;
|
|
@@ -26297,6 +26741,8 @@ exports.NativeObjectDetectionStatusSchema = NativeObjectDetectionStatusSchema;
|
|
|
26297
26741
|
exports.NetworkAccessStatusSchema = NetworkAccessStatusSchema;
|
|
26298
26742
|
exports.NetworkAddressSchema = NetworkAddressSchema;
|
|
26299
26743
|
exports.NetworkEndpointSchema = NetworkEndpointSchema;
|
|
26744
|
+
exports.NotificationActionSchema = NotificationActionSchema;
|
|
26745
|
+
exports.NotificationFormatSchema = NotificationFormatSchema;
|
|
26300
26746
|
exports.NotificationHistoryEntrySchema = NotificationHistoryEntrySchema;
|
|
26301
26747
|
exports.NotificationRuleSchema = NotificationRuleSchema;
|
|
26302
26748
|
exports.NotificationSchema = NotificationSchema;
|
|
@@ -26377,6 +26823,7 @@ exports.RecordingStorageUsageSchema = RecordingStorageUsageSchema;
|
|
|
26377
26823
|
exports.RecordingTriggersSchema = RecordingTriggersSchema;
|
|
26378
26824
|
exports.RecordingWeekdaySchema = RecordingWeekdaySchema;
|
|
26379
26825
|
exports.RegisteredStreamSchema = RegisteredStreamSchema;
|
|
26826
|
+
exports.RenderedAsSchema = RenderedAsSchema;
|
|
26380
26827
|
exports.ReportMotionInputSchema = ReportMotionInputSchema;
|
|
26381
26828
|
exports.RingBuffer = RingBuffer;
|
|
26382
26829
|
exports.RtpSourceSchema = RtpSourceSchema;
|
|
@@ -26398,6 +26845,7 @@ exports.ScriptRunnerStatusSchema = ScriptRunnerStatusSchema;
|
|
|
26398
26845
|
exports.SearchResultSchema = SearchResultSchema;
|
|
26399
26846
|
exports.SendEmailInputSchema = SendEmailInputSchema;
|
|
26400
26847
|
exports.SendEmailResultSchema = SendEmailResultSchema;
|
|
26848
|
+
exports.SendResultSchema = SendResultSchema;
|
|
26401
26849
|
exports.SettingsPatchSchema = SettingsPatchSchema;
|
|
26402
26850
|
exports.SettingsRecordSchema = SettingsRecordSchema;
|
|
26403
26851
|
exports.SettingsSchemaWithValuesSchema = SettingsSchemaWithValuesSchema;
|
|
@@ -26447,8 +26895,13 @@ exports.SystemMirror = SystemMirror;
|
|
|
26447
26895
|
exports.TIMEZONES = TIMEZONES;
|
|
26448
26896
|
exports.TamperStatusSchema = TamperStatusSchema;
|
|
26449
26897
|
exports.TankStatusSchema = TankStatusSchema;
|
|
26898
|
+
exports.TargetKindCapsSchema = TargetKindCapsSchema;
|
|
26899
|
+
exports.TargetKindLevelSchema = TargetKindLevelSchema;
|
|
26900
|
+
exports.TargetKindSchema = TargetKindSchema;
|
|
26901
|
+
exports.TargetSchema = TargetSchema;
|
|
26450
26902
|
exports.TemperatureSensorStatusSchema = TemperatureSensorStatusSchema;
|
|
26451
26903
|
exports.TestConnectionResultSchema = TestConnectionResultSchema$1;
|
|
26904
|
+
exports.TestResultSchema = TestResultSchema;
|
|
26452
26905
|
exports.ToastSchema = ToastSchema;
|
|
26453
26906
|
exports.TokenScopeSchema = TokenScopeSchema;
|
|
26454
26907
|
exports.TopologyNodeSchema = TopologyNodeSchema;
|
|
@@ -26594,6 +27047,7 @@ exports.getAudioMacroClassIds = getAudioMacroClassIds;
|
|
|
26594
27047
|
exports.getByPath = getByPath;
|
|
26595
27048
|
exports.getCapsByProviderKind = getCapsByProviderKind;
|
|
26596
27049
|
exports.hfModelUrl = hfModelUrl;
|
|
27050
|
+
exports.htmlToText = htmlToText;
|
|
26597
27051
|
exports.humidifierCapability = humidifierCapability;
|
|
26598
27052
|
exports.humiditySensorCapability = humiditySensorCapability;
|
|
26599
27053
|
exports.hydrateSchema = require_sleep.hydrateSchema;
|
|
@@ -26617,6 +27071,8 @@ exports.logDestinationCapability = logDestinationCapability;
|
|
|
26617
27071
|
exports.makeProfileBrokerId = require_sleep.makeProfileBrokerId;
|
|
26618
27072
|
exports.makeSourceBrokerId = require_sleep.makeSourceBrokerId;
|
|
26619
27073
|
exports.mapAudioLabelToMacro = mapAudioLabelToMacro;
|
|
27074
|
+
exports.markdownToHtmlLite = markdownToHtmlLite;
|
|
27075
|
+
exports.markdownToText = markdownToText;
|
|
26620
27076
|
exports.maskUrlCredentials = maskUrlCredentials;
|
|
26621
27077
|
exports.mediaPlayerCapability = mediaPlayerCapability;
|
|
26622
27078
|
exports.mergeSourceInfo = mergeSourceInfo;
|
|
@@ -26659,6 +27115,7 @@ exports.pipelineRunnerCapability = pipelineRunnerCapability;
|
|
|
26659
27115
|
exports.plateGalleryCapability = plateGalleryCapability;
|
|
26660
27116
|
exports.platformProbeCapability = platformProbeCapability;
|
|
26661
27117
|
exports.powerMeterCapability = powerMeterCapability;
|
|
27118
|
+
exports.prepareNotification = prepareNotification;
|
|
26662
27119
|
exports.presenceCapability = presenceCapability;
|
|
26663
27120
|
exports.pressureSensorCapability = pressureSensorCapability;
|
|
26664
27121
|
exports.privacyMaskCapability = privacyMaskCapability;
|
|
@@ -26678,6 +27135,7 @@ exports.resolveAddonRuntime = resolveAddonRuntime;
|
|
|
26678
27135
|
exports.resolveCapMount = require_sleep.resolveCapMount;
|
|
26679
27136
|
exports.resolveDetectionRuntime = resolveDetectionRuntime;
|
|
26680
27137
|
exports.resolveDeviceProfile = resolveDeviceProfile;
|
|
27138
|
+
exports.resolveFormat = resolveFormat;
|
|
26681
27139
|
exports.resolveModelFormat = resolveModelFormat;
|
|
26682
27140
|
exports.resolveRunnerId = resolveRunnerId;
|
|
26683
27141
|
exports.restreamerCapability = restreamerCapability;
|
|
@@ -26714,9 +27172,11 @@ exports.taskLogEntrySchema = taskLogEntrySchema;
|
|
|
26714
27172
|
exports.taskPhaseSchema = taskPhaseSchema;
|
|
26715
27173
|
exports.taskTargetSchema = taskTargetSchema;
|
|
26716
27174
|
exports.temperatureSensorCapability = temperatureSensorCapability;
|
|
27175
|
+
exports.textToHtml = textToHtml;
|
|
26717
27176
|
exports.toDeviceSummary = toDeviceSummary;
|
|
26718
27177
|
exports.toStreamSourceEntry = toStreamSourceEntry;
|
|
26719
27178
|
exports.toastCapability = toastCapability;
|
|
27179
|
+
exports.transcodeBody = transcodeBody;
|
|
26720
27180
|
exports.turnProviderCapability = turnProviderCapability;
|
|
26721
27181
|
exports.updateCapability = updateCapability;
|
|
26722
27182
|
exports.userManagementCapability = userManagementCapability;
|