@camstack/addon-import-alexa 0.2.193 → 0.2.195
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/dist/addon.js +163 -416
- package/dist/addon.mjs +163 -416
- package/package.json +2 -2
package/dist/addon.mjs
CHANGED
|
@@ -46,7 +46,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
46
46
|
var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["module.exports"] : __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
47
47
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
48
48
|
//#endregion
|
|
49
|
-
//#region ../types/dist/event-category-
|
|
49
|
+
//#region ../types/dist/event-category-78tcBemo.mjs
|
|
50
50
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
51
51
|
EventCategory["SystemBoot"] = "system.boot";
|
|
52
52
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -167,6 +167,23 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
167
167
|
*/
|
|
168
168
|
EventCategory["AddonLoadRecovered"] = "addon.load-recovered";
|
|
169
169
|
/**
|
|
170
|
+
* An addon is RUNNING although its installed package is below what the
|
|
171
|
+
* running server requires (`camstack.requires.addons` of the server, or the
|
|
172
|
+
* addon's own `requires.server`). Raised once per streak by the unsupported-
|
|
173
|
+
* addon tracker, on the hub and on agents; AlertCenter turns it into one
|
|
174
|
+
* operator alert per node and package. The addon is never held back for it.
|
|
175
|
+
*
|
|
176
|
+
* Payload: `{ packageName, addonId, nodeId, installedVersion, requiredMinimum, serverVersion, unmet }`.
|
|
177
|
+
*/
|
|
178
|
+
EventCategory["AddonUnsupportedVersion"] = "addon.unsupported-version";
|
|
179
|
+
/**
|
|
180
|
+
* The package of an {@link AddonUnsupportedVersion} alert reached a supported
|
|
181
|
+
* version, or is no longer installed on the node. AlertCenter dismisses the matching alert.
|
|
182
|
+
*
|
|
183
|
+
* Payload: `{ packageName, addonId, nodeId }`.
|
|
184
|
+
*/
|
|
185
|
+
EventCategory["AddonUnsupportedResolved"] = "addon.unsupported-resolved";
|
|
186
|
+
/**
|
|
170
187
|
* Monitor scheduled the next retry for a failed addon. Transient —
|
|
171
188
|
* surfaced to the UI for live-updating the "next retry in Ns"
|
|
172
189
|
* countdown on the Addons page row, NOT persisted as an alert.
|
|
@@ -277,7 +294,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
277
294
|
EventCategory["ProcessRestarted"] = "process.restarted";
|
|
278
295
|
/**
|
|
279
296
|
* The SET of storage locations changed — one was created, edited, enabled,
|
|
280
|
-
* disabled or deleted through
|
|
297
|
+
* disabled or deleted through the location instances or the forced-delete action.
|
|
281
298
|
*
|
|
282
299
|
* Telemetry, not a transaction (D8/D11): every consumer that re-resolves on
|
|
283
300
|
* it must also converge on its own periodic path, because a dropped event
|
|
@@ -6042,7 +6059,7 @@ function number(params) {
|
|
|
6042
6059
|
return /* @__PURE__ */ _coercedNumber(ZodNumber, params);
|
|
6043
6060
|
}
|
|
6044
6061
|
//#endregion
|
|
6045
|
-
//#region ../types/dist/sleep-
|
|
6062
|
+
//#region ../types/dist/sleep-AEnTN3b4.mjs
|
|
6046
6063
|
/**
|
|
6047
6064
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
6048
6065
|
* window to float samples (D455).
|
|
@@ -6751,10 +6768,33 @@ function integrationRowsApiOver(api) {
|
|
|
6751
6768
|
};
|
|
6752
6769
|
}
|
|
6753
6770
|
var PREFIX = "records/";
|
|
6771
|
+
/**
|
|
6772
|
+
* Cross-realm brand. An addon bundles its own copy of this module (D15) while
|
|
6773
|
+
* `ctx.records` is the HOST's door, so an error thrown by the host is an
|
|
6774
|
+
* instance of the host's classes, not of the addon's. The brand plus the code
|
|
6775
|
+
* make `instanceof` answer by identity of the failure, not of the copy.
|
|
6776
|
+
*/
|
|
6777
|
+
var RECORDS_ERROR_BRAND = Symbol.for("camstack.records-error");
|
|
6778
|
+
function carriesBrand(value) {
|
|
6779
|
+
return typeof value === "object" && value !== null && Reflect.get(value, RECORDS_ERROR_BRAND) === true;
|
|
6780
|
+
}
|
|
6754
6781
|
/** The base of every records failure. `detail` is the human part of the message. */
|
|
6755
6782
|
var RecordsError = class extends Error {
|
|
6783
|
+
/** The code a subclass stands for; the base stands for every code. */
|
|
6784
|
+
static code = void 0;
|
|
6785
|
+
/**
|
|
6786
|
+
* `instanceof` across copies of this module: any branded error is a
|
|
6787
|
+
* `RecordsError`, and is an instance of a subclass only when its code is the
|
|
6788
|
+
* subclass's code. Same-copy answers are unchanged.
|
|
6789
|
+
*/
|
|
6790
|
+
static [Symbol.hasInstance](value) {
|
|
6791
|
+
if (Function.prototype[Symbol.hasInstance].call(this, value)) return true;
|
|
6792
|
+
if (!carriesBrand(value)) return false;
|
|
6793
|
+
return this.code === void 0 || value.code === this.code;
|
|
6794
|
+
}
|
|
6756
6795
|
code;
|
|
6757
6796
|
detail;
|
|
6797
|
+
[RECORDS_ERROR_BRAND] = true;
|
|
6758
6798
|
constructor(code, detail) {
|
|
6759
6799
|
super(`${PREFIX}${code}: ${detail}`);
|
|
6760
6800
|
this.name = "RecordsError";
|
|
@@ -6763,29 +6803,33 @@ var RecordsError = class extends Error {
|
|
|
6763
6803
|
}
|
|
6764
6804
|
};
|
|
6765
6805
|
/** A write guarded by `ifRev` found another revision (or an existing row for `ifRev: 0`). */
|
|
6766
|
-
var RevConflictError = class extends RecordsError {
|
|
6806
|
+
var RevConflictError = class RevConflictError extends RecordsError {
|
|
6807
|
+
static code = "rev-conflict";
|
|
6767
6808
|
constructor(detail) {
|
|
6768
|
-
super(
|
|
6809
|
+
super(RevConflictError.code, detail);
|
|
6769
6810
|
this.name = "RevConflictError";
|
|
6770
6811
|
}
|
|
6771
6812
|
};
|
|
6772
6813
|
/** The keychain could not store or serve a value: explicit, never an empty string. */
|
|
6773
|
-
var RecordSecretUnavailableError = class extends RecordsError {
|
|
6814
|
+
var RecordSecretUnavailableError = class RecordSecretUnavailableError extends RecordsError {
|
|
6815
|
+
static code = "secret-unavailable";
|
|
6774
6816
|
constructor(detail) {
|
|
6775
|
-
super(
|
|
6817
|
+
super(RecordSecretUnavailableError.code, detail);
|
|
6776
6818
|
this.name = "RecordSecretUnavailableError";
|
|
6777
6819
|
}
|
|
6778
6820
|
};
|
|
6779
|
-
var InvalidRecordError = class extends RecordsError {
|
|
6821
|
+
var InvalidRecordError = class InvalidRecordError extends RecordsError {
|
|
6822
|
+
static code = "invalid-record";
|
|
6780
6823
|
constructor(detail) {
|
|
6781
|
-
super(
|
|
6824
|
+
super(InvalidRecordError.code, detail);
|
|
6782
6825
|
this.name = "InvalidRecordError";
|
|
6783
6826
|
}
|
|
6784
6827
|
};
|
|
6785
6828
|
/** A kind declaration the engine refuses (non-additive change, bad shape, wrong file). */
|
|
6786
|
-
var DeclarationRefusedError = class extends RecordsError {
|
|
6829
|
+
var DeclarationRefusedError = class DeclarationRefusedError extends RecordsError {
|
|
6830
|
+
static code = "declaration-refused";
|
|
6787
6831
|
constructor(detail) {
|
|
6788
|
-
super(
|
|
6832
|
+
super(DeclarationRefusedError.code, detail);
|
|
6789
6833
|
this.name = "DeclarationRefusedError";
|
|
6790
6834
|
}
|
|
6791
6835
|
};
|
|
@@ -7279,17 +7323,35 @@ var RecordIntegrationInstances = class {
|
|
|
7279
7323
|
...kind !== void 0 ? { kind } : {}
|
|
7280
7324
|
});
|
|
7281
7325
|
if (minted === void 0) throw new Error("createInstance needs an id: this provider does not mint one");
|
|
7326
|
+
const initial = this.hooks.initialBody(name, kind);
|
|
7327
|
+
const patch = this.patchOf(values ?? {});
|
|
7328
|
+
if (Object.keys(patch).length > 0) Object.assign(patch, await this.hooks.validateWrite?.({
|
|
7329
|
+
kind,
|
|
7330
|
+
body: {
|
|
7331
|
+
...initial,
|
|
7332
|
+
...patch
|
|
7333
|
+
}
|
|
7334
|
+
}));
|
|
7282
7335
|
await this.handle.put({
|
|
7283
7336
|
id: minted,
|
|
7284
|
-
data:
|
|
7337
|
+
data: initial
|
|
7285
7338
|
}, { ifRev: 0 });
|
|
7286
|
-
const patch = this.patchOf(values ?? {});
|
|
7287
7339
|
if (Object.keys(patch).length > 0) await this.handle.patch(minted, patch);
|
|
7288
7340
|
await this.hooks.onChanged?.(minted, "created");
|
|
7289
7341
|
return { id: minted };
|
|
7290
7342
|
};
|
|
7291
7343
|
updateInstance = async ({ id, name, values }) => {
|
|
7292
7344
|
const patch = this.patchOf(values);
|
|
7345
|
+
if (this.hooks.validateWrite !== void 0 && Object.keys(patch).length > 0) {
|
|
7346
|
+
const stored = await this.handle.get(id);
|
|
7347
|
+
if (stored !== null) Object.assign(patch, await this.hooks.validateWrite({
|
|
7348
|
+
kind: void 0,
|
|
7349
|
+
body: {
|
|
7350
|
+
...stored.data,
|
|
7351
|
+
...patch
|
|
7352
|
+
}
|
|
7353
|
+
}));
|
|
7354
|
+
}
|
|
7293
7355
|
if (name !== void 0) patch[this.nameField] = name;
|
|
7294
7356
|
await this.handle.patch(id, patch);
|
|
7295
7357
|
await this.hooks.onChanged?.(id, "updated");
|
|
@@ -10635,7 +10697,6 @@ var CAP_NAMES = Object.freeze([
|
|
|
10635
10697
|
"notifier",
|
|
10636
10698
|
"numeric-sensor",
|
|
10637
10699
|
"oauth-integration",
|
|
10638
|
-
"oidc-connections",
|
|
10639
10700
|
"osd",
|
|
10640
10701
|
"osd-manager",
|
|
10641
10702
|
"pet-feeder",
|
|
@@ -12527,8 +12588,7 @@ Object.freeze({
|
|
|
12527
12588
|
"device-provider": { "reloadDevice": 18e4 },
|
|
12528
12589
|
"llm": {
|
|
12529
12590
|
"generate": 6e5,
|
|
12530
|
-
"generateVision": 6e5
|
|
12531
|
-
"testProfile": 6e5
|
|
12591
|
+
"generateVision": 6e5
|
|
12532
12592
|
},
|
|
12533
12593
|
"llm-runtime": {
|
|
12534
12594
|
"complete": 6e5,
|
|
@@ -14139,17 +14199,18 @@ function composeInstanceKinds(parts, base) {
|
|
|
14139
14199
|
* message to what the kind supports — callers never special-case a service.
|
|
14140
14200
|
*
|
|
14141
14201
|
* DESIGN DECISIONS (locked):
|
|
14142
|
-
* -
|
|
14143
|
-
*
|
|
14144
|
-
*
|
|
14145
|
-
*
|
|
14146
|
-
*
|
|
14147
|
-
*
|
|
14148
|
-
*
|
|
14149
|
-
*
|
|
14150
|
-
*
|
|
14151
|
-
* routable. `send` / `testTarget` /
|
|
14152
|
-
* `
|
|
14202
|
+
* - A target is an INSTANCE of this function cap (epic #440, step 6): the
|
|
14203
|
+
* providers serve their targets as `integration-instances` records, one
|
|
14204
|
+
* record kind per target kind, and the admin lists, adds, edits, switches
|
|
14205
|
+
* and deletes them through that cap. This cap keeps what an instance cannot
|
|
14206
|
+
* say: the kind catalogue (`listTargetKinds`: capabilities, delivery
|
|
14207
|
+
* parameters, brand icon), dispatch (`send`, `testTarget`) and the form
|
|
14208
|
+
* helpers (`discoverTargets`, `probeTargetConfig`).
|
|
14209
|
+
* - `listTargetKinds` / `discoverTargets` return arrays → the generated
|
|
14210
|
+
* cap-mount auto-`concatCollection`-fans them across every registered
|
|
14211
|
+
* provider so one catalog is routable. `send` / `testTarget` /
|
|
14212
|
+
* `probeTargetConfig` route to ONE provider by the `addonId` the generated
|
|
14213
|
+
* collection router extracts from the call input.
|
|
14153
14214
|
* - `Attachment.bytes` is `Uint8Array`. Transport-safe: superjson (the tRPC
|
|
14154
14215
|
* transformer) + UDS MsgPack both round-trip typed arrays — already used by
|
|
14155
14216
|
* `storage` / `storage-provider` / `recording` caps over the same path. No
|
|
@@ -14394,7 +14455,7 @@ var TargetKindCapsSchema = object({
|
|
|
14394
14455
|
* the union is large and not meant for runtime validation here; the exported
|
|
14395
14456
|
* `TargetKind` type re-tightens `configSchema` to `ConfigUISchema`.
|
|
14396
14457
|
*/
|
|
14397
|
-
var ConfigSchemaPassthrough$
|
|
14458
|
+
var ConfigSchemaPassthrough$3 = unknown();
|
|
14398
14459
|
var TargetKindSchema = object({
|
|
14399
14460
|
kind: string(),
|
|
14400
14461
|
label: string(),
|
|
@@ -14431,7 +14492,7 @@ var TargetKindSchema = object({
|
|
|
14431
14492
|
* its raster path, which is the safe default for an unknown image.
|
|
14432
14493
|
*/
|
|
14433
14494
|
iconMediaType: string().optional(),
|
|
14434
|
-
configSchema: ConfigSchemaPassthrough$
|
|
14495
|
+
configSchema: ConfigSchemaPassthrough$3,
|
|
14435
14496
|
/**
|
|
14436
14497
|
* The config keys that decide WHERE this kind's secrets are sent (server,
|
|
14437
14498
|
* base URL, instance, chat, recipient). A save that changes any of them
|
|
@@ -14453,9 +14514,11 @@ var TargetKindSchema = object({
|
|
|
14453
14514
|
caps: TargetKindCapsSchema
|
|
14454
14515
|
});
|
|
14455
14516
|
/**
|
|
14456
|
-
* A
|
|
14457
|
-
*
|
|
14458
|
-
*
|
|
14517
|
+
* A target as a provider's own code sees it (the notification-center bridge, the
|
|
14518
|
+
* send path): the flat record body split into the name, the switch and the
|
|
14519
|
+
* kind's fields. `config` holds secrets; a reader that serves it to a client
|
|
14520
|
+
* REDACTS secret fields (a presence marker only) — never round-trip a stored
|
|
14521
|
+
* secret to the UI.
|
|
14459
14522
|
*/
|
|
14460
14523
|
var TargetSchema = object({
|
|
14461
14524
|
id: string(),
|
|
@@ -14504,21 +14567,13 @@ var notificationOutputCapability = {
|
|
|
14504
14567
|
mode: "collection",
|
|
14505
14568
|
methods: {
|
|
14506
14569
|
listTargetKinds: method(object({}), array(TargetKindSchema)),
|
|
14507
|
-
listTargets: method(object({}), array(TargetSchema), { auth: "admin" }),
|
|
14508
|
-
/**
|
|
14509
|
-
* One target WITH secrets — admin edit / duplicate hydration only.
|
|
14510
|
-
* `listTargets` stays redacted; the editor loads this so password fields
|
|
14511
|
-
* are filled (masked in the input) and a save can round-trip the token
|
|
14512
|
-
* when a destination changes (Duplicate with a new chatId, etc.).
|
|
14513
|
-
*/
|
|
14514
|
-
getTarget: method(object({ targetId: string() }), TargetSchema, { auth: "admin" }),
|
|
14515
14570
|
discoverTargets: method(object({
|
|
14516
14571
|
kind: string(),
|
|
14517
14572
|
config: record(string(), unknown()).optional(),
|
|
14518
14573
|
/**
|
|
14519
14574
|
* When editing / duplicating, the blank password field never round-trips
|
|
14520
14575
|
* the stored token. Pass the source target id so the provider can restore
|
|
14521
|
-
* secrets server-side before dialling
|
|
14576
|
+
* secrets server-side before dialling.
|
|
14522
14577
|
*/
|
|
14523
14578
|
targetId: string().optional()
|
|
14524
14579
|
}), array(DiscoveredTargetSchema), { auth: "admin" }),
|
|
@@ -14544,30 +14599,6 @@ var notificationOutputCapability = {
|
|
|
14544
14599
|
}), TestResultSchema, {
|
|
14545
14600
|
kind: "mutation",
|
|
14546
14601
|
auth: "admin"
|
|
14547
|
-
}),
|
|
14548
|
-
upsertTarget: method(object({
|
|
14549
|
-
target: TargetSchema,
|
|
14550
|
-
/**
|
|
14551
|
-
* Duplicate flow: create a NEW target id while copying secrets from an
|
|
14552
|
-
* existing row. The UI never holds the stored token; blank / redacted
|
|
14553
|
-
* password fields are restored from this source (D634 still applies if
|
|
14554
|
-
* destinations diverge without a re-typed secret).
|
|
14555
|
-
*/
|
|
14556
|
-
cloneSecretsFrom: string().optional()
|
|
14557
|
-
}), TargetSchema, {
|
|
14558
|
-
kind: "mutation",
|
|
14559
|
-
auth: "admin"
|
|
14560
|
-
}),
|
|
14561
|
-
deleteTarget: method(object({ targetId: string() }), _void(), {
|
|
14562
|
-
kind: "mutation",
|
|
14563
|
-
auth: "admin"
|
|
14564
|
-
}),
|
|
14565
|
-
setTargetEnabled: method(object({
|
|
14566
|
-
targetId: string(),
|
|
14567
|
-
enabled: boolean()
|
|
14568
|
-
}), _void(), {
|
|
14569
|
-
kind: "mutation",
|
|
14570
|
-
auth: "admin"
|
|
14571
14602
|
})
|
|
14572
14603
|
}
|
|
14573
14604
|
};
|
|
@@ -14583,8 +14614,9 @@ var notificationOutputCapability = {
|
|
|
14583
14614
|
*
|
|
14584
14615
|
* Three providers (notifiers, Home Assistant, Alexa) serve the same shape, so the pieces are shared:
|
|
14585
14616
|
* - {@link defineNotificationTargetKind}: the record kind of one `TargetKind` descriptor;
|
|
14586
|
-
* - {@link NotificationTargetStore}: the `Target`-shaped facade the
|
|
14587
|
-
* using, over one handle per kind
|
|
14617
|
+
* - {@link NotificationTargetStore}: the `Target`-shaped facade the provider's own code keeps
|
|
14618
|
+
* using (send, the notification-center bridge), over one handle per kind;
|
|
14619
|
+
* - {@link listNotificationTargets}: the targets as an addon on `ctx.api` reads them;
|
|
14588
14620
|
* - {@link buildNotificationTargetInstances}: the `integration-instances` provider, one kind each;
|
|
14589
14621
|
* - {@link moveTargetRows}: the D987 procedure that flattens the old `config` blobs into the bodies.
|
|
14590
14622
|
*/
|
|
@@ -14841,6 +14873,10 @@ function notificationTargetParts(records, spec) {
|
|
|
14841
14873
|
initialBody: (name) => ({ name }),
|
|
14842
14874
|
mintId: () => spec.mintId(),
|
|
14843
14875
|
configured: () => true,
|
|
14876
|
+
validateWrite: ({ body }) => spec.validate?.({
|
|
14877
|
+
kind: descriptor.kind,
|
|
14878
|
+
config: body
|
|
14879
|
+
}),
|
|
14844
14880
|
test: async ({ id, values }) => {
|
|
14845
14881
|
if (spec.probe === void 0 || !canTest) return {
|
|
14846
14882
|
success: false,
|
|
@@ -23236,7 +23272,6 @@ var SYSTEM_CAP_VOCABULARY = {
|
|
|
23236
23272
|
"notification-output": system("notification delivery — reached through notifier devices and rules"),
|
|
23237
23273
|
"notification-rules": system("notification rules — authored on their own page"),
|
|
23238
23274
|
"oauth-integration": system(IDENTITY),
|
|
23239
|
-
"oidc-connections": system(IDENTITY),
|
|
23240
23275
|
"osd-manager": system(PIPELINE),
|
|
23241
23276
|
"pipeline-executor": system(PIPELINE),
|
|
23242
23277
|
"pipeline-orchestrator": system(PIPELINE),
|
|
@@ -57028,7 +57063,7 @@ method(_void(), array(IntegrationWithStateSchema)), method(object({ id: string()
|
|
|
57028
57063
|
* or the redaction token KEEPS the stored secret; `{ $secretClear: true }`
|
|
57029
57064
|
* clears it.
|
|
57030
57065
|
*/
|
|
57031
|
-
var ConfigSchemaPassthrough$
|
|
57066
|
+
var ConfigSchemaPassthrough$2 = custom();
|
|
57032
57067
|
var IntegrationInstanceIdSchema = string().min(1);
|
|
57033
57068
|
var IntegrationInstanceModeSchema = _enum(["single", "multiple"]);
|
|
57034
57069
|
/**
|
|
@@ -57074,7 +57109,16 @@ var IntegrationInstanceKindSchema = object({
|
|
|
57074
57109
|
/** Relative hub path to start an interactive account link of an instance of this kind. */
|
|
57075
57110
|
connectPath: string().min(1).optional(),
|
|
57076
57111
|
/** Relative hub path to disconnect that account. */
|
|
57077
|
-
disconnectPath: string().min(1).optional()
|
|
57112
|
+
disconnectPath: string().min(1).optional(),
|
|
57113
|
+
/**
|
|
57114
|
+
* Parts of the edit dialog the flat form cannot draw (a node picker, a model source), named by a
|
|
57115
|
+
* GENERIC widget id the client maps to a component; a client that knows none of them shows none.
|
|
57116
|
+
* `connection` widgets write connection values, `model` widgets own the model choice.
|
|
57117
|
+
*/
|
|
57118
|
+
widgets: array(object({
|
|
57119
|
+
id: string().min(1),
|
|
57120
|
+
placement: _enum(["connection", "model"])
|
|
57121
|
+
})).optional()
|
|
57078
57122
|
});
|
|
57079
57123
|
/**
|
|
57080
57124
|
* How devices of an instance are found. `none`: the operator adds them by hand; `lan`: the addon
|
|
@@ -57179,7 +57223,7 @@ var integrationInstancesCapability = {
|
|
|
57179
57223
|
id: IntegrationInstanceIdSchema.nullable(),
|
|
57180
57224
|
/** The kind of the create form (`id: null`) of a provider with several. */
|
|
57181
57225
|
kind: string().min(1).optional()
|
|
57182
|
-
}), ConfigSchemaPassthrough$
|
|
57226
|
+
}), ConfigSchemaPassthrough$2, { auth: "admin" }),
|
|
57183
57227
|
listInstances: method(_void(), array(IntegrationInstanceSchema).readonly(), { auth: "admin" }),
|
|
57184
57228
|
getInstance: method(object({ id: IntegrationInstanceIdSchema }), IntegrationInstanceSchema.nullable(), { auth: "admin" }),
|
|
57185
57229
|
/**
|
|
@@ -58281,12 +58325,12 @@ var LlmModelInfoSchema = object({
|
|
|
58281
58325
|
});
|
|
58282
58326
|
/**
|
|
58283
58327
|
* The provider-specific part of a profile, validated by the provider that owns
|
|
58284
|
-
* the kind (
|
|
58328
|
+
* the kind (saving an instance refuses what it does not accept). A field its
|
|
58285
58329
|
* `connectionSchema` declares `type: 'password'` is a secret: it is held in the
|
|
58286
58330
|
* keychain, never in the row, and reads back as the redaction marker.
|
|
58287
58331
|
*/
|
|
58288
58332
|
var LlmProviderConfigSchema = record(string(), unknown());
|
|
58289
|
-
|
|
58333
|
+
object({
|
|
58290
58334
|
id: string(),
|
|
58291
58335
|
name: string(),
|
|
58292
58336
|
/** The provider-declared kind (`LlmProfileKindDescriptor.kind`). */
|
|
@@ -58380,8 +58424,8 @@ var LlmProviderWidgetSchema = object({
|
|
|
58380
58424
|
/** ConfigUISchema tree passed through untyped on the wire (the
|
|
58381
58425
|
* notification-output `ConfigSchemaPassthrough` precedent at
|
|
58382
58426
|
* notification-output.cap.ts:151); the exported TS type re-tightens it. */
|
|
58383
|
-
var ConfigSchemaPassthrough$
|
|
58384
|
-
|
|
58427
|
+
var ConfigSchemaPassthrough$1 = unknown();
|
|
58428
|
+
object({
|
|
58385
58429
|
kind: LlmProfileKindSchema,
|
|
58386
58430
|
label: string(),
|
|
58387
58431
|
/** A generic icon name (`cloud`, `plug`, `cpu`) — never a glyph or a logo. */
|
|
@@ -58389,9 +58433,9 @@ var LlmProfileKindDescriptorSchema = object({
|
|
|
58389
58433
|
/** Stamped by each provider so the concat-fanned catalog stays routable. */
|
|
58390
58434
|
addonId: string(),
|
|
58391
58435
|
/** The provider's own fields (`providerConfig`); `password` fields are keychain-held. */
|
|
58392
|
-
connectionSchema: ConfigSchemaPassthrough$
|
|
58436
|
+
connectionSchema: ConfigSchemaPassthrough$1,
|
|
58393
58437
|
/** Provider fields that belong under "Advanced" (extra headers, runtime tuning). */
|
|
58394
|
-
advancedSchema: ConfigSchemaPassthrough$
|
|
58438
|
+
advancedSchema: ConfigSchemaPassthrough$1.optional(),
|
|
58395
58439
|
/** The kind's defaults; a model from `listModels` may override any of them. */
|
|
58396
58440
|
features: LlmModelFeaturesSchema,
|
|
58397
58441
|
/** `false` = the provider stamps `supportsVision` itself (from what a node reports). */
|
|
@@ -58520,20 +58564,7 @@ method(LlmGenerateBaseInputSchema, LlmGenerateResultSchema, {
|
|
|
58520
58564
|
}), method(object({
|
|
58521
58565
|
addonId: string().optional(),
|
|
58522
58566
|
requestId: string()
|
|
58523
|
-
}), _void(), { kind: "mutation" }), method(
|
|
58524
|
-
kind: "mutation",
|
|
58525
|
-
auth: "admin"
|
|
58526
|
-
}), method(RawSecretMigrationInputSchema, RawSecretMigrationReportSchema, {
|
|
58527
|
-
kind: "mutation",
|
|
58528
|
-
auth: "admin"
|
|
58529
|
-
}), method(ProfileRefInputSchema, _void(), {
|
|
58530
|
-
kind: "mutation",
|
|
58531
|
-
auth: "admin"
|
|
58532
|
-
}), method(ProfileRefInputSchema, LlmGenerateResultSchema, {
|
|
58533
|
-
kind: "mutation",
|
|
58534
|
-
auth: "admin",
|
|
58535
|
-
timeoutMs: AI_CAP_TRANSPORT_TIMEOUT_MS
|
|
58536
|
-
}), method(LlmListModelsInputSchema, LlmListModelsResultSchema, {
|
|
58567
|
+
}), _void(), { kind: "mutation" }), method(LlmListModelsInputSchema, LlmListModelsResultSchema, {
|
|
58537
58568
|
kind: "mutation",
|
|
58538
58569
|
auth: "admin"
|
|
58539
58570
|
}), method(object({}), array(LlmDefaultSchema)), method(object({
|
|
@@ -59596,20 +59627,7 @@ method(_void(), MeshStatusSchema), method(object({
|
|
|
59596
59627
|
/** Optional hostname override the host should advertise once joined. */
|
|
59597
59628
|
hostname: string().optional() }), object({
|
|
59598
59629
|
/** Authentication URL the operator should open in a browser. */
|
|
59599
|
-
loginUrl: string() }), { kind: "mutation" }), method(_void(), object({ left: literal(true) }), { kind: "mutation" }), method(_void(), object({ loggedOut: literal(true) }), { kind: "mutation" }), method(_void(), object({ peers: array(MeshPeerSchema).readonly() }))
|
|
59600
|
-
/** Optional auth key — when provided, probes the key validity
|
|
59601
|
-
* against the provider's API. Omit when already joined to
|
|
59602
|
-
* just ping the daemon. */
|
|
59603
|
-
authKey: string().optional() }), object({
|
|
59604
|
-
ok: boolean(),
|
|
59605
|
-
/** Provider-side identifier resolved by the probe (tailnet
|
|
59606
|
-
* name for Tailscale, network id for ZeroTier, etc.). */
|
|
59607
|
-
tenant: string().optional(),
|
|
59608
|
-
/** Daemon binary version, when reachable. */
|
|
59609
|
-
daemonVersion: string().optional(),
|
|
59610
|
-
/** Human-readable error when `ok: false`. */
|
|
59611
|
-
error: string().optional()
|
|
59612
|
-
}), { kind: "mutation" });
|
|
59630
|
+
loginUrl: string() }), { kind: "mutation" }), method(_void(), object({ left: literal(true) }), { kind: "mutation" }), method(_void(), object({ loggedOut: literal(true) }), { kind: "mutation" }), method(_void(), object({ peers: array(MeshPeerSchema).readonly() }));
|
|
59613
59631
|
/**
|
|
59614
59632
|
* A monotonic total between resets (D944). Energy uses `power-meter.energy`
|
|
59615
59633
|
* so dashboards keep one series; every other instantaneous reading lands here.
|
|
@@ -69816,61 +69834,6 @@ var OauthIntegrationDescriptorSchema = object({
|
|
|
69816
69834
|
});
|
|
69817
69835
|
method(_void(), OauthIntegrationDescriptorSchema, { auth: "admin" });
|
|
69818
69836
|
/**
|
|
69819
|
-
* `oidc-connections` — CRUD for IdP rows under `auth-oidc` (D828 sibling).
|
|
69820
|
-
*
|
|
69821
|
-
* One hub-only singleton (`auth-oidc`). The Settings UI is a DataTable +
|
|
69822
|
-
* ItemFormDialog; there is no `editable-array` in `globalSettingsSchema`.
|
|
69823
|
-
* Operator-chosen `id` is the URL slug (`/addon/auth-oidc/<id>/…`) and is
|
|
69824
|
-
* immutable after create.
|
|
69825
|
-
*/
|
|
69826
|
-
var ConfigSchemaPassthrough$1 = unknown();
|
|
69827
|
-
var OidcConnectionSchema = object({
|
|
69828
|
-
id: string().min(1),
|
|
69829
|
-
displayName: string(),
|
|
69830
|
-
icon: string(),
|
|
69831
|
-
issuerUrl: string(),
|
|
69832
|
-
clientId: string(),
|
|
69833
|
-
/** Client id + secret present — never the secret value. */
|
|
69834
|
-
configured: boolean(),
|
|
69835
|
-
/**
|
|
69836
|
-
* Values for the connection form schema. `clientSecret` is a keychain
|
|
69837
|
-
* {@link SecretFieldView} or `null` / `''`, never plaintext (D789).
|
|
69838
|
-
*/
|
|
69839
|
-
formValues: record(string(), unknown()).optional()
|
|
69840
|
-
});
|
|
69841
|
-
/**
|
|
69842
|
-
* Patch one connection. Omitted or empty `clientSecret` keeps the stored
|
|
69843
|
-
* secret (D787). `{ $secretClear: true }` clears it. `id` is never renamed.
|
|
69844
|
-
*/
|
|
69845
|
-
var OidcConnectionUpdateInputSchema = object({
|
|
69846
|
-
id: string().min(1),
|
|
69847
|
-
displayName: string().min(1),
|
|
69848
|
-
icon: string().optional(),
|
|
69849
|
-
issuerUrl: string().optional(),
|
|
69850
|
-
clientId: string().optional(),
|
|
69851
|
-
clientSecret: union([string(), object({ $secretClear: literal(true) })]).optional(),
|
|
69852
|
-
redirectUri: string().optional(),
|
|
69853
|
-
scopes: string().optional(),
|
|
69854
|
-
usernameClaim: _enum([
|
|
69855
|
-
"preferred_username",
|
|
69856
|
-
"email",
|
|
69857
|
-
"sub"
|
|
69858
|
-
]).optional()
|
|
69859
|
-
});
|
|
69860
|
-
method(object({}), ConfigSchemaPassthrough$1, { auth: "admin" }), method(object({}), array(OidcConnectionSchema).readonly(), { auth: "admin" }), method(object({
|
|
69861
|
-
id: string().min(1).regex(/^[a-z0-9][a-z0-9-]{0,63}$/, "id must be a lowercase slug"),
|
|
69862
|
-
displayName: string().min(1)
|
|
69863
|
-
}), object({ id: string() }), {
|
|
69864
|
-
kind: "mutation",
|
|
69865
|
-
auth: "admin"
|
|
69866
|
-
}), method(OidcConnectionUpdateInputSchema, object({ ok: literal(true) }), {
|
|
69867
|
-
kind: "mutation",
|
|
69868
|
-
auth: "admin"
|
|
69869
|
-
}), method(object({ id: string().min(1) }), object({ ok: literal(true) }), {
|
|
69870
|
-
kind: "mutation",
|
|
69871
|
-
auth: "admin"
|
|
69872
|
-
});
|
|
69873
|
-
/**
|
|
69874
69837
|
* Generic on-screen-display (video overlay) cap. Each camera exposes
|
|
69875
69838
|
* a firmware-defined list of overlays (channel name, timestamp,
|
|
69876
69839
|
* watermark, logo, …); the cap models them as a homogeneous array of
|
|
@@ -76952,21 +76915,6 @@ method(object({
|
|
|
76952
76915
|
*/
|
|
76953
76916
|
ttlSec: union([number$1().int().positive(), literal("never")]).optional()
|
|
76954
76917
|
}), object({ token: string() }), { auth: "admin" }), method(object({ token: string() }), SsoBridgeClaimsSchema.nullable(), { auth: "admin" });
|
|
76955
|
-
var ProviderListEntrySchema = discriminatedUnion("shouldSaveDiskSpace", [object({
|
|
76956
|
-
providerId: string().min(1),
|
|
76957
|
-
displayName: string().min(1),
|
|
76958
|
-
configSchema: unknown(),
|
|
76959
|
-
nodeLocal: boolean(),
|
|
76960
|
-
shouldSaveDiskSpace: literal(true),
|
|
76961
|
-
minFreePercent: number$1().min(0).max(100)
|
|
76962
|
-
}), object({
|
|
76963
|
-
providerId: string().min(1),
|
|
76964
|
-
displayName: string().min(1),
|
|
76965
|
-
configSchema: unknown(),
|
|
76966
|
-
nodeLocal: boolean(),
|
|
76967
|
-
shouldSaveDiskSpace: literal(false),
|
|
76968
|
-
minFreePercent: literal(null)
|
|
76969
|
-
})]);
|
|
76970
76918
|
method(object({
|
|
76971
76919
|
location: StorageLocationRefSchema,
|
|
76972
76920
|
relativePath: string()
|
|
@@ -77028,42 +76976,7 @@ method(object({
|
|
|
77028
76976
|
}), _instanceof(Uint8Array), { auth: "admin" }), method(object({ downloadId: string() }), _void(), {
|
|
77029
76977
|
kind: "mutation",
|
|
77030
76978
|
auth: "admin"
|
|
77031
|
-
}), method(object({ type: StorageLocationTypeSchema.optional() }), array(StorageLocationSchema).readonly()), method(_void(), array(StorageLocationDeclarationSchema).readonly()), method(
|
|
77032
|
-
createdAt: true,
|
|
77033
|
-
updatedAt: true
|
|
77034
|
-
}), StorageLocationSchema, {
|
|
77035
|
-
kind: "mutation",
|
|
77036
|
-
auth: "admin"
|
|
77037
|
-
}), method(object({
|
|
77038
|
-
id: string(),
|
|
77039
|
-
force: boolean().optional()
|
|
77040
|
-
}), _void(), {
|
|
77041
|
-
kind: "mutation",
|
|
77042
|
-
auth: "admin"
|
|
77043
|
-
}), method(_void(), array(StorageDrainProgressSchema).readonly()), method(object({ id: string() }), object({
|
|
77044
|
-
ok: boolean(),
|
|
77045
|
-
error: string().optional()
|
|
77046
|
-
}), { auth: "admin" }), method(_void(), array(ProviderListEntrySchema).readonly()), method(object({
|
|
77047
|
-
providerId: string(),
|
|
77048
|
-
/**
|
|
77049
|
-
* The location this config is an UNSAVED edit of, when there is one.
|
|
77050
|
-
*
|
|
77051
|
-
* `listLocations` replaces every declared secret with the redaction
|
|
77052
|
-
* sentinel, so the edit modal's form state holds the sentinel for any
|
|
77053
|
-
* credential the operator did not retype — and posting that here
|
|
77054
|
-
* without a way to resolve it makes the provider try to authenticate
|
|
77055
|
-
* as `__camstack_redacted__` and report the operator's own working
|
|
77056
|
-
* password as wrong. Given this id, the orchestrator restores each
|
|
77057
|
-
* sentinel from the stored config (same rule as `upsertLocation`)
|
|
77058
|
-
* before dispatching. Omitted by the "Add location" wizard, where
|
|
77059
|
-
* every value was typed just now and nothing is stored yet.
|
|
77060
|
-
*/
|
|
77061
|
-
locationId: string().optional(),
|
|
77062
|
-
config: record(string(), unknown())
|
|
77063
|
-
}), object({
|
|
77064
|
-
ok: boolean(),
|
|
77065
|
-
error: string().optional()
|
|
77066
|
-
}), { auth: "admin" });
|
|
76979
|
+
}), method(object({ type: StorageLocationTypeSchema.optional() }), array(StorageLocationSchema).readonly()), method(_void(), array(StorageLocationDeclarationSchema).readonly()), method(_void(), array(StorageDrainProgressSchema).readonly());
|
|
77067
76980
|
/** One table of the settings database. */
|
|
77068
76981
|
var StorageTableSchema = object({
|
|
77069
76982
|
/** The table's full name, e.g. `recorder:addon-settings` or `addon-device-settings`. */
|
|
@@ -86949,13 +86862,6 @@ Object.freeze({
|
|
|
86949
86862
|
access: "delete",
|
|
86950
86863
|
role: "admin"
|
|
86951
86864
|
},
|
|
86952
|
-
"llm.deleteProfile": {
|
|
86953
|
-
capName: "llm",
|
|
86954
|
-
capScope: "system",
|
|
86955
|
-
addonId: null,
|
|
86956
|
-
access: "delete",
|
|
86957
|
-
role: "admin"
|
|
86958
|
-
},
|
|
86959
86865
|
"llm.generate": {
|
|
86960
86866
|
capName: "llm",
|
|
86961
86867
|
capScope: "system",
|
|
@@ -87019,20 +86925,6 @@ Object.freeze({
|
|
|
87019
86925
|
access: "view",
|
|
87020
86926
|
role: "admin"
|
|
87021
86927
|
},
|
|
87022
|
-
"llm.listProfileKinds": {
|
|
87023
|
-
capName: "llm",
|
|
87024
|
-
capScope: "system",
|
|
87025
|
-
addonId: null,
|
|
87026
|
-
access: "view",
|
|
87027
|
-
role: "admin"
|
|
87028
|
-
},
|
|
87029
|
-
"llm.listProfiles": {
|
|
87030
|
-
capName: "llm",
|
|
87031
|
-
capScope: "system",
|
|
87032
|
-
addonId: null,
|
|
87033
|
-
access: "view",
|
|
87034
|
-
role: "admin"
|
|
87035
|
-
},
|
|
87036
86928
|
"llm.listRuntimeNodes": {
|
|
87037
86929
|
capName: "llm",
|
|
87038
86930
|
capScope: "system",
|
|
@@ -87040,13 +86932,6 @@ Object.freeze({
|
|
|
87040
86932
|
access: "view",
|
|
87041
86933
|
role: "admin"
|
|
87042
86934
|
},
|
|
87043
|
-
"llm.migrateRawSecrets": {
|
|
87044
|
-
capName: "llm",
|
|
87045
|
-
capScope: "system",
|
|
87046
|
-
addonId: null,
|
|
87047
|
-
access: "create",
|
|
87048
|
-
role: "admin"
|
|
87049
|
-
},
|
|
87050
86935
|
"llm.resolveModelRef": {
|
|
87051
86936
|
capName: "llm",
|
|
87052
86937
|
capScope: "system",
|
|
@@ -87075,20 +86960,6 @@ Object.freeze({
|
|
|
87075
86960
|
access: "create",
|
|
87076
86961
|
role: "admin"
|
|
87077
86962
|
},
|
|
87078
|
-
"llm.testProfile": {
|
|
87079
|
-
capName: "llm",
|
|
87080
|
-
capScope: "system",
|
|
87081
|
-
addonId: null,
|
|
87082
|
-
access: "create",
|
|
87083
|
-
role: "admin"
|
|
87084
|
-
},
|
|
87085
|
-
"llm.upsertProfile": {
|
|
87086
|
-
capName: "llm",
|
|
87087
|
-
capScope: "system",
|
|
87088
|
-
addonId: null,
|
|
87089
|
-
access: "create",
|
|
87090
|
-
role: "admin"
|
|
87091
|
-
},
|
|
87092
86963
|
"llmRuntime.appleAvailability": {
|
|
87093
86964
|
capName: "llm-runtime",
|
|
87094
86965
|
capScope: "system",
|
|
@@ -87593,13 +87464,6 @@ Object.freeze({
|
|
|
87593
87464
|
access: "create",
|
|
87594
87465
|
role: "admin"
|
|
87595
87466
|
},
|
|
87596
|
-
"meshNetwork.testConnection": {
|
|
87597
|
-
capName: "mesh-network",
|
|
87598
|
-
capScope: "system",
|
|
87599
|
-
addonId: null,
|
|
87600
|
-
access: "create",
|
|
87601
|
-
role: "admin"
|
|
87602
|
-
},
|
|
87603
87467
|
"meter.getStatus": {
|
|
87604
87468
|
capName: "meter",
|
|
87605
87469
|
capScope: "device",
|
|
@@ -88258,13 +88122,6 @@ Object.freeze({
|
|
|
88258
88122
|
access: "create",
|
|
88259
88123
|
role: "admin"
|
|
88260
88124
|
},
|
|
88261
|
-
"notificationOutput.deleteTarget": {
|
|
88262
|
-
capName: "notification-output",
|
|
88263
|
-
capScope: "system",
|
|
88264
|
-
addonId: null,
|
|
88265
|
-
access: "delete",
|
|
88266
|
-
role: "admin"
|
|
88267
|
-
},
|
|
88268
88125
|
"notificationOutput.discoverTargets": {
|
|
88269
88126
|
capName: "notification-output",
|
|
88270
88127
|
capScope: "system",
|
|
@@ -88272,13 +88129,6 @@ Object.freeze({
|
|
|
88272
88129
|
access: "view",
|
|
88273
88130
|
role: "admin"
|
|
88274
88131
|
},
|
|
88275
|
-
"notificationOutput.getTarget": {
|
|
88276
|
-
capName: "notification-output",
|
|
88277
|
-
capScope: "system",
|
|
88278
|
-
addonId: null,
|
|
88279
|
-
access: "view",
|
|
88280
|
-
role: "admin"
|
|
88281
|
-
},
|
|
88282
88132
|
"notificationOutput.listTargetKinds": {
|
|
88283
88133
|
capName: "notification-output",
|
|
88284
88134
|
capScope: "system",
|
|
@@ -88286,13 +88136,6 @@ Object.freeze({
|
|
|
88286
88136
|
access: "view",
|
|
88287
88137
|
role: "admin"
|
|
88288
88138
|
},
|
|
88289
|
-
"notificationOutput.listTargets": {
|
|
88290
|
-
capName: "notification-output",
|
|
88291
|
-
capScope: "system",
|
|
88292
|
-
addonId: null,
|
|
88293
|
-
access: "view",
|
|
88294
|
-
role: "admin"
|
|
88295
|
-
},
|
|
88296
88139
|
"notificationOutput.probeTargetConfig": {
|
|
88297
88140
|
capName: "notification-output",
|
|
88298
88141
|
capScope: "system",
|
|
@@ -88307,13 +88150,6 @@ Object.freeze({
|
|
|
88307
88150
|
access: "create",
|
|
88308
88151
|
role: "admin"
|
|
88309
88152
|
},
|
|
88310
|
-
"notificationOutput.setTargetEnabled": {
|
|
88311
|
-
capName: "notification-output",
|
|
88312
|
-
capScope: "system",
|
|
88313
|
-
addonId: null,
|
|
88314
|
-
access: "create",
|
|
88315
|
-
role: "admin"
|
|
88316
|
-
},
|
|
88317
88153
|
"notificationOutput.testTarget": {
|
|
88318
88154
|
capName: "notification-output",
|
|
88319
88155
|
capScope: "system",
|
|
@@ -88321,13 +88157,6 @@ Object.freeze({
|
|
|
88321
88157
|
access: "create",
|
|
88322
88158
|
role: "admin"
|
|
88323
88159
|
},
|
|
88324
|
-
"notificationOutput.upsertTarget": {
|
|
88325
|
-
capName: "notification-output",
|
|
88326
|
-
capScope: "system",
|
|
88327
|
-
addonId: null,
|
|
88328
|
-
access: "create",
|
|
88329
|
-
role: "admin"
|
|
88330
|
-
},
|
|
88331
88160
|
"notificationRules.activateAlarmProfile": {
|
|
88332
88161
|
capName: "notification-rules",
|
|
88333
88162
|
capScope: "system",
|
|
@@ -88587,41 +88416,6 @@ Object.freeze({
|
|
|
88587
88416
|
access: "view",
|
|
88588
88417
|
role: "admin"
|
|
88589
88418
|
},
|
|
88590
|
-
"oidcConnections.connectionFormSchema": {
|
|
88591
|
-
capName: "oidc-connections",
|
|
88592
|
-
capScope: "system",
|
|
88593
|
-
addonId: null,
|
|
88594
|
-
access: "view",
|
|
88595
|
-
role: "admin"
|
|
88596
|
-
},
|
|
88597
|
-
"oidcConnections.createConnection": {
|
|
88598
|
-
capName: "oidc-connections",
|
|
88599
|
-
capScope: "system",
|
|
88600
|
-
addonId: null,
|
|
88601
|
-
access: "create",
|
|
88602
|
-
role: "admin"
|
|
88603
|
-
},
|
|
88604
|
-
"oidcConnections.deleteConnection": {
|
|
88605
|
-
capName: "oidc-connections",
|
|
88606
|
-
capScope: "system",
|
|
88607
|
-
addonId: null,
|
|
88608
|
-
access: "delete",
|
|
88609
|
-
role: "admin"
|
|
88610
|
-
},
|
|
88611
|
-
"oidcConnections.listConnections": {
|
|
88612
|
-
capName: "oidc-connections",
|
|
88613
|
-
capScope: "system",
|
|
88614
|
-
addonId: null,
|
|
88615
|
-
access: "view",
|
|
88616
|
-
role: "admin"
|
|
88617
|
-
},
|
|
88618
|
-
"oidcConnections.updateConnection": {
|
|
88619
|
-
capName: "oidc-connections",
|
|
88620
|
-
capScope: "system",
|
|
88621
|
-
addonId: null,
|
|
88622
|
-
access: "create",
|
|
88623
|
-
role: "admin"
|
|
88624
|
-
},
|
|
88625
88419
|
"osd.getStatus": {
|
|
88626
88420
|
capName: "osd",
|
|
88627
88421
|
capScope: "device",
|
|
@@ -91653,13 +91447,6 @@ Object.freeze({
|
|
|
91653
91447
|
access: "delete",
|
|
91654
91448
|
role: "admin"
|
|
91655
91449
|
},
|
|
91656
|
-
"storage.deleteLocation": {
|
|
91657
|
-
capName: "storage",
|
|
91658
|
-
capScope: "system",
|
|
91659
|
-
addonId: null,
|
|
91660
|
-
access: "delete",
|
|
91661
|
-
role: "admin"
|
|
91662
|
-
},
|
|
91663
91450
|
"storage.endDownload": {
|
|
91664
91451
|
capName: "storage",
|
|
91665
91452
|
capScope: "system",
|
|
@@ -91716,13 +91503,6 @@ Object.freeze({
|
|
|
91716
91503
|
access: "view",
|
|
91717
91504
|
role: "admin"
|
|
91718
91505
|
},
|
|
91719
|
-
"storage.listProviders": {
|
|
91720
|
-
capName: "storage",
|
|
91721
|
-
capScope: "system",
|
|
91722
|
-
addonId: null,
|
|
91723
|
-
access: "view",
|
|
91724
|
-
role: "admin"
|
|
91725
|
-
},
|
|
91726
91506
|
"storage.read": {
|
|
91727
91507
|
capName: "storage",
|
|
91728
91508
|
capScope: "system",
|
|
@@ -91744,27 +91524,6 @@ Object.freeze({
|
|
|
91744
91524
|
access: "view",
|
|
91745
91525
|
role: "admin"
|
|
91746
91526
|
},
|
|
91747
|
-
"storage.testConfig": {
|
|
91748
|
-
capName: "storage",
|
|
91749
|
-
capScope: "system",
|
|
91750
|
-
addonId: null,
|
|
91751
|
-
access: "view",
|
|
91752
|
-
role: "admin"
|
|
91753
|
-
},
|
|
91754
|
-
"storage.testLocation": {
|
|
91755
|
-
capName: "storage",
|
|
91756
|
-
capScope: "system",
|
|
91757
|
-
addonId: null,
|
|
91758
|
-
access: "view",
|
|
91759
|
-
role: "admin"
|
|
91760
|
-
},
|
|
91761
|
-
"storage.upsertLocation": {
|
|
91762
|
-
capName: "storage",
|
|
91763
|
-
capScope: "system",
|
|
91764
|
-
addonId: null,
|
|
91765
|
-
access: "create",
|
|
91766
|
-
role: "admin"
|
|
91767
|
-
},
|
|
91768
91527
|
"storage.write": {
|
|
91769
91528
|
capName: "storage",
|
|
91770
91529
|
capScope: "system",
|
|
@@ -145492,6 +145251,33 @@ function quietLogger$1() {
|
|
|
145492
145251
|
};
|
|
145493
145252
|
return logger;
|
|
145494
145253
|
}
|
|
145254
|
+
/**
|
|
145255
|
+
* The account a target speaks through: the one it names; else the only one there is; else the one
|
|
145256
|
+
* whose Echoes include the target's Echo.
|
|
145257
|
+
*/
|
|
145258
|
+
function pickBroker(brokers, config) {
|
|
145259
|
+
const named = readString(config, "brokerId");
|
|
145260
|
+
if (named.length > 0) return brokers.find((broker) => broker.id === named);
|
|
145261
|
+
if (brokers.length === 1) return brokers[0];
|
|
145262
|
+
const echoId = readString(config, "echoId");
|
|
145263
|
+
const owners = brokers.filter((broker) => broker.devices.some((device) => device.id === echoId));
|
|
145264
|
+
return owners.length === 1 ? owners[0] : void 0;
|
|
145265
|
+
}
|
|
145266
|
+
/**
|
|
145267
|
+
* The save-time rule of an Echo target: an Echo and an account must be picked, and the account is
|
|
145268
|
+
* pinned the moment it is known, so a second account added later cannot silently change where an
|
|
145269
|
+
* existing target speaks. Throws the reason; returns the keys to keep with the write.
|
|
145270
|
+
*/
|
|
145271
|
+
function validateEchoTarget(brokers, config) {
|
|
145272
|
+
if (readString(config, "echoId").length === 0) throw new Error("Pick the Echo that should speak");
|
|
145273
|
+
const owner = pickBroker(brokers, config);
|
|
145274
|
+
if (owner === void 0) {
|
|
145275
|
+
const named = readString(config, "brokerId");
|
|
145276
|
+
if (named.length > 0) throw new Error(`The Amazon account ${named} is not available`);
|
|
145277
|
+
throw new Error(brokers.length === 0 ? "Add an Amazon account first: an Echo speaks through one" : "Pick the Amazon account this Echo belongs to");
|
|
145278
|
+
}
|
|
145279
|
+
return readString(config, "brokerId").length === 0 ? { brokerId: owner.id } : {};
|
|
145280
|
+
}
|
|
145495
145281
|
function readString(config, key) {
|
|
145496
145282
|
const value = config[key];
|
|
145497
145283
|
return typeof value === "string" ? value : "";
|
|
@@ -145521,7 +145307,7 @@ function echoOptionLabel(device) {
|
|
|
145521
145307
|
/**
|
|
145522
145308
|
* The two pickers are not `required`: a required select shows its first option
|
|
145523
145309
|
* while the form still holds no value, so a save would drop the choice. Left
|
|
145524
|
-
* optional they open on "Select", and `
|
|
145310
|
+
* optional they open on "Select", and `validateEchoTarget` refuses an empty pick on save.
|
|
145525
145311
|
*
|
|
145526
145312
|
* The account is a broker pick (existing, or created in place); the Echo list
|
|
145527
145313
|
* is fetched from that account, so a new Echo shows up without a deploy.
|
|
@@ -145613,18 +145399,8 @@ function createAlexaNotificationProvider(ports) {
|
|
|
145613
145399
|
function record(row) {
|
|
145614
145400
|
deliveries = [...deliveries, row];
|
|
145615
145401
|
}
|
|
145616
|
-
/**
|
|
145617
|
-
* The account a target speaks through: the one it names; else the only one
|
|
145618
|
-
* there is; else the one whose Echoes include the target's Echo.
|
|
145619
|
-
*/
|
|
145620
145402
|
function brokerFor(config) {
|
|
145621
|
-
|
|
145622
|
-
const named = readString(config, "brokerId");
|
|
145623
|
-
if (named.length > 0) return all.find((broker) => broker.id === named);
|
|
145624
|
-
if (all.length === 1) return all[0];
|
|
145625
|
-
const echoId = readString(config, "echoId");
|
|
145626
|
-
const owners = all.filter((broker) => broker.devices.some((device) => device.id === echoId));
|
|
145627
|
-
return owners.length === 1 ? owners[0] : void 0;
|
|
145403
|
+
return pickBroker(ports.brokers(), config);
|
|
145628
145404
|
}
|
|
145629
145405
|
async function deliver(target, notification) {
|
|
145630
145406
|
const speech = speechFromNotification(notification);
|
|
@@ -145826,14 +145602,6 @@ function createAlexaNotificationProvider(ports) {
|
|
|
145826
145602
|
async listTargetKinds() {
|
|
145827
145603
|
return [alexaTargetKind()];
|
|
145828
145604
|
},
|
|
145829
|
-
async listTargets() {
|
|
145830
|
-
return [...await ports.loadTargets()];
|
|
145831
|
-
},
|
|
145832
|
-
async getTarget(input) {
|
|
145833
|
-
const found = (await ports.loadTargets()).find((target) => target.id === input.targetId);
|
|
145834
|
-
if (found === void 0) throw new Error(`target not found: ${input.targetId}`);
|
|
145835
|
-
return found;
|
|
145836
|
-
},
|
|
145837
145605
|
async discoverTargets(input) {
|
|
145838
145606
|
for (const broker of ports.brokers()) if (!broker.ready) ports.logger.warn(`alexa echo discovery: no Echo listed for '${broker.name}', the Amazon account is not signed in for this broker`, { tags: { brokerId: broker.id } });
|
|
145839
145607
|
const named = readString(input.config ?? {}, "brokerId");
|
|
@@ -145894,33 +145662,6 @@ function createAlexaNotificationProvider(ports) {
|
|
|
145894
145662
|
format: "text",
|
|
145895
145663
|
priority: 3
|
|
145896
145664
|
});
|
|
145897
|
-
},
|
|
145898
|
-
async upsertTarget(input) {
|
|
145899
|
-
const owner = brokerFor(input.target.config);
|
|
145900
|
-
if (readString(input.target.config, "echoId").length === 0) throw new Error("Pick the Echo that should speak");
|
|
145901
|
-
if (owner === void 0) throw new Error("Pick the Amazon account this Echo belongs to");
|
|
145902
|
-
const pinned = readString(input.target.config, "brokerId").length === 0 ? {
|
|
145903
|
-
...input.target.config,
|
|
145904
|
-
brokerId: owner.id
|
|
145905
|
-
} : input.target.config;
|
|
145906
|
-
const target = {
|
|
145907
|
-
...input.target,
|
|
145908
|
-
config: pinned,
|
|
145909
|
-
addonId: ALEXA_SPEAK_ADDON_ID,
|
|
145910
|
-
kind: ALEXA_SPEAK_KIND
|
|
145911
|
-
};
|
|
145912
|
-
await ports.putTarget(target);
|
|
145913
|
-
return target;
|
|
145914
|
-
},
|
|
145915
|
-
async deleteTarget(input) {
|
|
145916
|
-
await ports.removeTarget(input.targetId);
|
|
145917
|
-
},
|
|
145918
|
-
async setTargetEnabled(input) {
|
|
145919
|
-
const found = (await ports.loadTargets()).find((row) => row.id === input.targetId);
|
|
145920
|
-
if (found !== void 0) await ports.putTarget({
|
|
145921
|
-
...found,
|
|
145922
|
-
enabled: input.enabled
|
|
145923
|
-
});
|
|
145924
145665
|
}
|
|
145925
145666
|
};
|
|
145926
145667
|
}
|
|
@@ -146011,6 +145752,14 @@ function echoTargetProbe(speak) {
|
|
|
146011
145752
|
});
|
|
146012
145753
|
};
|
|
146013
145754
|
}
|
|
145755
|
+
/**
|
|
145756
|
+
* The Echo instance's save-time rule over the accounts now (D1013): the check the removed
|
|
145757
|
+
* `upsertTarget` made, on the instance door. Speech not started yet has no account to name, so the
|
|
145758
|
+
* write is refused with the reason, never accepted blind.
|
|
145759
|
+
*/
|
|
145760
|
+
function echoTargetValidator(brokers) {
|
|
145761
|
+
return ({ config }) => validateEchoTarget(brokers() ?? [], config);
|
|
145762
|
+
}
|
|
146014
145763
|
process.platform, process.env["SystemRoot"];
|
|
146015
145764
|
/**
|
|
146016
145765
|
* Files only their owner may read: the one place a secret-bearing file is
|
|
@@ -146851,8 +146600,6 @@ var AlexaSpeakController = class {
|
|
|
146851
146600
|
now: this.now,
|
|
146852
146601
|
logger: host.logger,
|
|
146853
146602
|
loadTargets: () => host.readTargets(),
|
|
146854
|
-
putTarget: (target) => host.putTarget(target),
|
|
146855
|
-
removeTarget: (targetId) => host.removeTarget(targetId),
|
|
146856
146603
|
speak: (command) => this.utter(command.brokerId, command.mode, command.targets, command.text)
|
|
146857
146604
|
});
|
|
146858
146605
|
}
|
|
@@ -146882,6 +146629,7 @@ var AlexaSpeakController = class {
|
|
|
146882
146629
|
echoFor(brokerId) {
|
|
146883
146630
|
return this.echoes.get(brokerId) ?? null;
|
|
146884
146631
|
}
|
|
146632
|
+
/** The accounts right now, as the provider and the save-time rule see them. */
|
|
146885
146633
|
brokerViews() {
|
|
146886
146634
|
return this.host.listBrokers().map((ref) => {
|
|
146887
146635
|
const echo = this.echoes.get(ref.id);
|
|
@@ -147429,8 +147177,6 @@ var AlexaImportAddon = class extends BaseDeviceProvider {
|
|
|
147429
147177
|
const speak = new AlexaSpeakController({
|
|
147430
147178
|
logger: this.ctx.logger.child("speak"),
|
|
147431
147179
|
readTargets: () => echoStore.list(),
|
|
147432
|
-
putTarget: (target) => echoStore.upsert(target),
|
|
147433
|
-
removeTarget: (targetId) => echoStore.delete(targetId),
|
|
147434
147180
|
listBrokers: () => this.activeBrokers.map((entry) => ({
|
|
147435
147181
|
id: entry.id,
|
|
147436
147182
|
name: entry.name,
|
|
@@ -147532,6 +147278,7 @@ var AlexaImportAddon = class extends BaseDeviceProvider {
|
|
|
147532
147278
|
kinds: alexaNotifyRecordKinds,
|
|
147533
147279
|
mintId: () => randomUUID(),
|
|
147534
147280
|
probe: echoTargetProbe(() => this.speak),
|
|
147281
|
+
validate: echoTargetValidator(() => this.speak?.brokerViews() ?? null),
|
|
147535
147282
|
canProbe: () => true
|
|
147536
147283
|
})
|
|
147537
147284
|
], {
|