@camstack/addon-import-alexa 0.2.194 → 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 +7 -0
- package/dist/addon.js +128 -408
- package/dist/addon.mjs +128 -408
- package/package.json +2 -2
package/dist/addon.js
CHANGED
|
@@ -48,7 +48,7 @@ node_fs = __toESM(node_fs, 1);
|
|
|
48
48
|
let node_child_process = require("node:child_process");
|
|
49
49
|
require("node:zlib");
|
|
50
50
|
let node_url = require("node:url");
|
|
51
|
-
//#region ../types/dist/event-category-
|
|
51
|
+
//#region ../types/dist/event-category-78tcBemo.mjs
|
|
52
52
|
var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
53
53
|
EventCategory["SystemBoot"] = "system.boot";
|
|
54
54
|
EventCategory["SystemAddonsReady"] = "system.addons-ready";
|
|
@@ -169,6 +169,23 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
169
169
|
*/
|
|
170
170
|
EventCategory["AddonLoadRecovered"] = "addon.load-recovered";
|
|
171
171
|
/**
|
|
172
|
+
* An addon is RUNNING although its installed package is below what the
|
|
173
|
+
* running server requires (`camstack.requires.addons` of the server, or the
|
|
174
|
+
* addon's own `requires.server`). Raised once per streak by the unsupported-
|
|
175
|
+
* addon tracker, on the hub and on agents; AlertCenter turns it into one
|
|
176
|
+
* operator alert per node and package. The addon is never held back for it.
|
|
177
|
+
*
|
|
178
|
+
* Payload: `{ packageName, addonId, nodeId, installedVersion, requiredMinimum, serverVersion, unmet }`.
|
|
179
|
+
*/
|
|
180
|
+
EventCategory["AddonUnsupportedVersion"] = "addon.unsupported-version";
|
|
181
|
+
/**
|
|
182
|
+
* The package of an {@link AddonUnsupportedVersion} alert reached a supported
|
|
183
|
+
* version, or is no longer installed on the node. AlertCenter dismisses the matching alert.
|
|
184
|
+
*
|
|
185
|
+
* Payload: `{ packageName, addonId, nodeId }`.
|
|
186
|
+
*/
|
|
187
|
+
EventCategory["AddonUnsupportedResolved"] = "addon.unsupported-resolved";
|
|
188
|
+
/**
|
|
172
189
|
* Monitor scheduled the next retry for a failed addon. Transient —
|
|
173
190
|
* surfaced to the UI for live-updating the "next retry in Ns"
|
|
174
191
|
* countdown on the Addons page row, NOT persisted as an alert.
|
|
@@ -279,7 +296,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
|
|
|
279
296
|
EventCategory["ProcessRestarted"] = "process.restarted";
|
|
280
297
|
/**
|
|
281
298
|
* The SET of storage locations changed — one was created, edited, enabled,
|
|
282
|
-
* disabled or deleted through
|
|
299
|
+
* disabled or deleted through the location instances or the forced-delete action.
|
|
283
300
|
*
|
|
284
301
|
* Telemetry, not a transaction (D8/D11): every consumer that re-resolves on
|
|
285
302
|
* it must also converge on its own periodic path, because a dropped event
|
|
@@ -6044,7 +6061,7 @@ function number(params) {
|
|
|
6044
6061
|
return /* @__PURE__ */ _coercedNumber(ZodNumber, params);
|
|
6045
6062
|
}
|
|
6046
6063
|
//#endregion
|
|
6047
|
-
//#region ../types/dist/sleep-
|
|
6064
|
+
//#region ../types/dist/sleep-AEnTN3b4.mjs
|
|
6048
6065
|
/**
|
|
6049
6066
|
* The audio chunk plane's byte format, and the ONE expansion from a coded
|
|
6050
6067
|
* window to float samples (D455).
|
|
@@ -7308,17 +7325,35 @@ var RecordIntegrationInstances = class {
|
|
|
7308
7325
|
...kind !== void 0 ? { kind } : {}
|
|
7309
7326
|
});
|
|
7310
7327
|
if (minted === void 0) throw new Error("createInstance needs an id: this provider does not mint one");
|
|
7328
|
+
const initial = this.hooks.initialBody(name, kind);
|
|
7329
|
+
const patch = this.patchOf(values ?? {});
|
|
7330
|
+
if (Object.keys(patch).length > 0) Object.assign(patch, await this.hooks.validateWrite?.({
|
|
7331
|
+
kind,
|
|
7332
|
+
body: {
|
|
7333
|
+
...initial,
|
|
7334
|
+
...patch
|
|
7335
|
+
}
|
|
7336
|
+
}));
|
|
7311
7337
|
await this.handle.put({
|
|
7312
7338
|
id: minted,
|
|
7313
|
-
data:
|
|
7339
|
+
data: initial
|
|
7314
7340
|
}, { ifRev: 0 });
|
|
7315
|
-
const patch = this.patchOf(values ?? {});
|
|
7316
7341
|
if (Object.keys(patch).length > 0) await this.handle.patch(minted, patch);
|
|
7317
7342
|
await this.hooks.onChanged?.(minted, "created");
|
|
7318
7343
|
return { id: minted };
|
|
7319
7344
|
};
|
|
7320
7345
|
updateInstance = async ({ id, name, values }) => {
|
|
7321
7346
|
const patch = this.patchOf(values);
|
|
7347
|
+
if (this.hooks.validateWrite !== void 0 && Object.keys(patch).length > 0) {
|
|
7348
|
+
const stored = await this.handle.get(id);
|
|
7349
|
+
if (stored !== null) Object.assign(patch, await this.hooks.validateWrite({
|
|
7350
|
+
kind: void 0,
|
|
7351
|
+
body: {
|
|
7352
|
+
...stored.data,
|
|
7353
|
+
...patch
|
|
7354
|
+
}
|
|
7355
|
+
}));
|
|
7356
|
+
}
|
|
7322
7357
|
if (name !== void 0) patch[this.nameField] = name;
|
|
7323
7358
|
await this.handle.patch(id, patch);
|
|
7324
7359
|
await this.hooks.onChanged?.(id, "updated");
|
|
@@ -10664,7 +10699,6 @@ var CAP_NAMES = Object.freeze([
|
|
|
10664
10699
|
"notifier",
|
|
10665
10700
|
"numeric-sensor",
|
|
10666
10701
|
"oauth-integration",
|
|
10667
|
-
"oidc-connections",
|
|
10668
10702
|
"osd",
|
|
10669
10703
|
"osd-manager",
|
|
10670
10704
|
"pet-feeder",
|
|
@@ -12556,8 +12590,7 @@ Object.freeze({
|
|
|
12556
12590
|
"device-provider": { "reloadDevice": 18e4 },
|
|
12557
12591
|
"llm": {
|
|
12558
12592
|
"generate": 6e5,
|
|
12559
|
-
"generateVision": 6e5
|
|
12560
|
-
"testProfile": 6e5
|
|
12593
|
+
"generateVision": 6e5
|
|
12561
12594
|
},
|
|
12562
12595
|
"llm-runtime": {
|
|
12563
12596
|
"complete": 6e5,
|
|
@@ -14168,17 +14201,18 @@ function composeInstanceKinds(parts, base) {
|
|
|
14168
14201
|
* message to what the kind supports — callers never special-case a service.
|
|
14169
14202
|
*
|
|
14170
14203
|
* DESIGN DECISIONS (locked):
|
|
14171
|
-
* -
|
|
14172
|
-
*
|
|
14173
|
-
*
|
|
14174
|
-
*
|
|
14175
|
-
*
|
|
14176
|
-
*
|
|
14177
|
-
*
|
|
14178
|
-
*
|
|
14179
|
-
*
|
|
14180
|
-
* routable. `send` / `testTarget` /
|
|
14181
|
-
* `
|
|
14204
|
+
* - A target is an INSTANCE of this function cap (epic #440, step 6): the
|
|
14205
|
+
* providers serve their targets as `integration-instances` records, one
|
|
14206
|
+
* record kind per target kind, and the admin lists, adds, edits, switches
|
|
14207
|
+
* and deletes them through that cap. This cap keeps what an instance cannot
|
|
14208
|
+
* say: the kind catalogue (`listTargetKinds`: capabilities, delivery
|
|
14209
|
+
* parameters, brand icon), dispatch (`send`, `testTarget`) and the form
|
|
14210
|
+
* helpers (`discoverTargets`, `probeTargetConfig`).
|
|
14211
|
+
* - `listTargetKinds` / `discoverTargets` return arrays → the generated
|
|
14212
|
+
* cap-mount auto-`concatCollection`-fans them across every registered
|
|
14213
|
+
* provider so one catalog is routable. `send` / `testTarget` /
|
|
14214
|
+
* `probeTargetConfig` route to ONE provider by the `addonId` the generated
|
|
14215
|
+
* collection router extracts from the call input.
|
|
14182
14216
|
* - `Attachment.bytes` is `Uint8Array`. Transport-safe: superjson (the tRPC
|
|
14183
14217
|
* transformer) + UDS MsgPack both round-trip typed arrays — already used by
|
|
14184
14218
|
* `storage` / `storage-provider` / `recording` caps over the same path. No
|
|
@@ -14423,7 +14457,7 @@ var TargetKindCapsSchema = object({
|
|
|
14423
14457
|
* the union is large and not meant for runtime validation here; the exported
|
|
14424
14458
|
* `TargetKind` type re-tightens `configSchema` to `ConfigUISchema`.
|
|
14425
14459
|
*/
|
|
14426
|
-
var ConfigSchemaPassthrough$
|
|
14460
|
+
var ConfigSchemaPassthrough$3 = unknown();
|
|
14427
14461
|
var TargetKindSchema = object({
|
|
14428
14462
|
kind: string(),
|
|
14429
14463
|
label: string(),
|
|
@@ -14460,7 +14494,7 @@ var TargetKindSchema = object({
|
|
|
14460
14494
|
* its raster path, which is the safe default for an unknown image.
|
|
14461
14495
|
*/
|
|
14462
14496
|
iconMediaType: string().optional(),
|
|
14463
|
-
configSchema: ConfigSchemaPassthrough$
|
|
14497
|
+
configSchema: ConfigSchemaPassthrough$3,
|
|
14464
14498
|
/**
|
|
14465
14499
|
* The config keys that decide WHERE this kind's secrets are sent (server,
|
|
14466
14500
|
* base URL, instance, chat, recipient). A save that changes any of them
|
|
@@ -14482,9 +14516,11 @@ var TargetKindSchema = object({
|
|
|
14482
14516
|
caps: TargetKindCapsSchema
|
|
14483
14517
|
});
|
|
14484
14518
|
/**
|
|
14485
|
-
* A
|
|
14486
|
-
*
|
|
14487
|
-
*
|
|
14519
|
+
* A target as a provider's own code sees it (the notification-center bridge, the
|
|
14520
|
+
* send path): the flat record body split into the name, the switch and the
|
|
14521
|
+
* kind's fields. `config` holds secrets; a reader that serves it to a client
|
|
14522
|
+
* REDACTS secret fields (a presence marker only) — never round-trip a stored
|
|
14523
|
+
* secret to the UI.
|
|
14488
14524
|
*/
|
|
14489
14525
|
var TargetSchema = object({
|
|
14490
14526
|
id: string(),
|
|
@@ -14533,21 +14569,13 @@ var notificationOutputCapability = {
|
|
|
14533
14569
|
mode: "collection",
|
|
14534
14570
|
methods: {
|
|
14535
14571
|
listTargetKinds: method(object({}), array(TargetKindSchema)),
|
|
14536
|
-
listTargets: method(object({}), array(TargetSchema), { auth: "admin" }),
|
|
14537
|
-
/**
|
|
14538
|
-
* One target WITH secrets — admin edit / duplicate hydration only.
|
|
14539
|
-
* `listTargets` stays redacted; the editor loads this so password fields
|
|
14540
|
-
* are filled (masked in the input) and a save can round-trip the token
|
|
14541
|
-
* when a destination changes (Duplicate with a new chatId, etc.).
|
|
14542
|
-
*/
|
|
14543
|
-
getTarget: method(object({ targetId: string() }), TargetSchema, { auth: "admin" }),
|
|
14544
14572
|
discoverTargets: method(object({
|
|
14545
14573
|
kind: string(),
|
|
14546
14574
|
config: record(string(), unknown()).optional(),
|
|
14547
14575
|
/**
|
|
14548
14576
|
* When editing / duplicating, the blank password field never round-trips
|
|
14549
14577
|
* the stored token. Pass the source target id so the provider can restore
|
|
14550
|
-
* secrets server-side before dialling
|
|
14578
|
+
* secrets server-side before dialling.
|
|
14551
14579
|
*/
|
|
14552
14580
|
targetId: string().optional()
|
|
14553
14581
|
}), array(DiscoveredTargetSchema), { auth: "admin" }),
|
|
@@ -14573,30 +14601,6 @@ var notificationOutputCapability = {
|
|
|
14573
14601
|
}), TestResultSchema, {
|
|
14574
14602
|
kind: "mutation",
|
|
14575
14603
|
auth: "admin"
|
|
14576
|
-
}),
|
|
14577
|
-
upsertTarget: method(object({
|
|
14578
|
-
target: TargetSchema,
|
|
14579
|
-
/**
|
|
14580
|
-
* Duplicate flow: create a NEW target id while copying secrets from an
|
|
14581
|
-
* existing row. The UI never holds the stored token; blank / redacted
|
|
14582
|
-
* password fields are restored from this source (D634 still applies if
|
|
14583
|
-
* destinations diverge without a re-typed secret).
|
|
14584
|
-
*/
|
|
14585
|
-
cloneSecretsFrom: string().optional()
|
|
14586
|
-
}), TargetSchema, {
|
|
14587
|
-
kind: "mutation",
|
|
14588
|
-
auth: "admin"
|
|
14589
|
-
}),
|
|
14590
|
-
deleteTarget: method(object({ targetId: string() }), _void(), {
|
|
14591
|
-
kind: "mutation",
|
|
14592
|
-
auth: "admin"
|
|
14593
|
-
}),
|
|
14594
|
-
setTargetEnabled: method(object({
|
|
14595
|
-
targetId: string(),
|
|
14596
|
-
enabled: boolean()
|
|
14597
|
-
}), _void(), {
|
|
14598
|
-
kind: "mutation",
|
|
14599
|
-
auth: "admin"
|
|
14600
14604
|
})
|
|
14601
14605
|
}
|
|
14602
14606
|
};
|
|
@@ -14612,8 +14616,9 @@ var notificationOutputCapability = {
|
|
|
14612
14616
|
*
|
|
14613
14617
|
* Three providers (notifiers, Home Assistant, Alexa) serve the same shape, so the pieces are shared:
|
|
14614
14618
|
* - {@link defineNotificationTargetKind}: the record kind of one `TargetKind` descriptor;
|
|
14615
|
-
* - {@link NotificationTargetStore}: the `Target`-shaped facade the
|
|
14616
|
-
* using, over one handle per kind
|
|
14619
|
+
* - {@link NotificationTargetStore}: the `Target`-shaped facade the provider's own code keeps
|
|
14620
|
+
* using (send, the notification-center bridge), over one handle per kind;
|
|
14621
|
+
* - {@link listNotificationTargets}: the targets as an addon on `ctx.api` reads them;
|
|
14617
14622
|
* - {@link buildNotificationTargetInstances}: the `integration-instances` provider, one kind each;
|
|
14618
14623
|
* - {@link moveTargetRows}: the D987 procedure that flattens the old `config` blobs into the bodies.
|
|
14619
14624
|
*/
|
|
@@ -14870,6 +14875,10 @@ function notificationTargetParts(records, spec) {
|
|
|
14870
14875
|
initialBody: (name) => ({ name }),
|
|
14871
14876
|
mintId: () => spec.mintId(),
|
|
14872
14877
|
configured: () => true,
|
|
14878
|
+
validateWrite: ({ body }) => spec.validate?.({
|
|
14879
|
+
kind: descriptor.kind,
|
|
14880
|
+
config: body
|
|
14881
|
+
}),
|
|
14873
14882
|
test: async ({ id, values }) => {
|
|
14874
14883
|
if (spec.probe === void 0 || !canTest) return {
|
|
14875
14884
|
success: false,
|
|
@@ -23265,7 +23274,6 @@ var SYSTEM_CAP_VOCABULARY = {
|
|
|
23265
23274
|
"notification-output": system("notification delivery — reached through notifier devices and rules"),
|
|
23266
23275
|
"notification-rules": system("notification rules — authored on their own page"),
|
|
23267
23276
|
"oauth-integration": system(IDENTITY),
|
|
23268
|
-
"oidc-connections": system(IDENTITY),
|
|
23269
23277
|
"osd-manager": system(PIPELINE),
|
|
23270
23278
|
"pipeline-executor": system(PIPELINE),
|
|
23271
23279
|
"pipeline-orchestrator": system(PIPELINE),
|
|
@@ -57057,7 +57065,7 @@ method(_void(), array(IntegrationWithStateSchema)), method(object({ id: string()
|
|
|
57057
57065
|
* or the redaction token KEEPS the stored secret; `{ $secretClear: true }`
|
|
57058
57066
|
* clears it.
|
|
57059
57067
|
*/
|
|
57060
|
-
var ConfigSchemaPassthrough$
|
|
57068
|
+
var ConfigSchemaPassthrough$2 = custom();
|
|
57061
57069
|
var IntegrationInstanceIdSchema = string().min(1);
|
|
57062
57070
|
var IntegrationInstanceModeSchema = _enum(["single", "multiple"]);
|
|
57063
57071
|
/**
|
|
@@ -57103,7 +57111,16 @@ var IntegrationInstanceKindSchema = object({
|
|
|
57103
57111
|
/** Relative hub path to start an interactive account link of an instance of this kind. */
|
|
57104
57112
|
connectPath: string().min(1).optional(),
|
|
57105
57113
|
/** Relative hub path to disconnect that account. */
|
|
57106
|
-
disconnectPath: string().min(1).optional()
|
|
57114
|
+
disconnectPath: string().min(1).optional(),
|
|
57115
|
+
/**
|
|
57116
|
+
* Parts of the edit dialog the flat form cannot draw (a node picker, a model source), named by a
|
|
57117
|
+
* GENERIC widget id the client maps to a component; a client that knows none of them shows none.
|
|
57118
|
+
* `connection` widgets write connection values, `model` widgets own the model choice.
|
|
57119
|
+
*/
|
|
57120
|
+
widgets: array(object({
|
|
57121
|
+
id: string().min(1),
|
|
57122
|
+
placement: _enum(["connection", "model"])
|
|
57123
|
+
})).optional()
|
|
57107
57124
|
});
|
|
57108
57125
|
/**
|
|
57109
57126
|
* How devices of an instance are found. `none`: the operator adds them by hand; `lan`: the addon
|
|
@@ -57208,7 +57225,7 @@ var integrationInstancesCapability = {
|
|
|
57208
57225
|
id: IntegrationInstanceIdSchema.nullable(),
|
|
57209
57226
|
/** The kind of the create form (`id: null`) of a provider with several. */
|
|
57210
57227
|
kind: string().min(1).optional()
|
|
57211
|
-
}), ConfigSchemaPassthrough$
|
|
57228
|
+
}), ConfigSchemaPassthrough$2, { auth: "admin" }),
|
|
57212
57229
|
listInstances: method(_void(), array(IntegrationInstanceSchema).readonly(), { auth: "admin" }),
|
|
57213
57230
|
getInstance: method(object({ id: IntegrationInstanceIdSchema }), IntegrationInstanceSchema.nullable(), { auth: "admin" }),
|
|
57214
57231
|
/**
|
|
@@ -58310,12 +58327,12 @@ var LlmModelInfoSchema = object({
|
|
|
58310
58327
|
});
|
|
58311
58328
|
/**
|
|
58312
58329
|
* The provider-specific part of a profile, validated by the provider that owns
|
|
58313
|
-
* the kind (
|
|
58330
|
+
* the kind (saving an instance refuses what it does not accept). A field its
|
|
58314
58331
|
* `connectionSchema` declares `type: 'password'` is a secret: it is held in the
|
|
58315
58332
|
* keychain, never in the row, and reads back as the redaction marker.
|
|
58316
58333
|
*/
|
|
58317
58334
|
var LlmProviderConfigSchema = record(string(), unknown());
|
|
58318
|
-
|
|
58335
|
+
object({
|
|
58319
58336
|
id: string(),
|
|
58320
58337
|
name: string(),
|
|
58321
58338
|
/** The provider-declared kind (`LlmProfileKindDescriptor.kind`). */
|
|
@@ -58409,8 +58426,8 @@ var LlmProviderWidgetSchema = object({
|
|
|
58409
58426
|
/** ConfigUISchema tree passed through untyped on the wire (the
|
|
58410
58427
|
* notification-output `ConfigSchemaPassthrough` precedent at
|
|
58411
58428
|
* notification-output.cap.ts:151); the exported TS type re-tightens it. */
|
|
58412
|
-
var ConfigSchemaPassthrough$
|
|
58413
|
-
|
|
58429
|
+
var ConfigSchemaPassthrough$1 = unknown();
|
|
58430
|
+
object({
|
|
58414
58431
|
kind: LlmProfileKindSchema,
|
|
58415
58432
|
label: string(),
|
|
58416
58433
|
/** A generic icon name (`cloud`, `plug`, `cpu`) — never a glyph or a logo. */
|
|
@@ -58418,9 +58435,9 @@ var LlmProfileKindDescriptorSchema = object({
|
|
|
58418
58435
|
/** Stamped by each provider so the concat-fanned catalog stays routable. */
|
|
58419
58436
|
addonId: string(),
|
|
58420
58437
|
/** The provider's own fields (`providerConfig`); `password` fields are keychain-held. */
|
|
58421
|
-
connectionSchema: ConfigSchemaPassthrough$
|
|
58438
|
+
connectionSchema: ConfigSchemaPassthrough$1,
|
|
58422
58439
|
/** Provider fields that belong under "Advanced" (extra headers, runtime tuning). */
|
|
58423
|
-
advancedSchema: ConfigSchemaPassthrough$
|
|
58440
|
+
advancedSchema: ConfigSchemaPassthrough$1.optional(),
|
|
58424
58441
|
/** The kind's defaults; a model from `listModels` may override any of them. */
|
|
58425
58442
|
features: LlmModelFeaturesSchema,
|
|
58426
58443
|
/** `false` = the provider stamps `supportsVision` itself (from what a node reports). */
|
|
@@ -58549,20 +58566,7 @@ method(LlmGenerateBaseInputSchema, LlmGenerateResultSchema, {
|
|
|
58549
58566
|
}), method(object({
|
|
58550
58567
|
addonId: string().optional(),
|
|
58551
58568
|
requestId: string()
|
|
58552
|
-
}), _void(), { kind: "mutation" }), method(
|
|
58553
|
-
kind: "mutation",
|
|
58554
|
-
auth: "admin"
|
|
58555
|
-
}), method(RawSecretMigrationInputSchema, RawSecretMigrationReportSchema, {
|
|
58556
|
-
kind: "mutation",
|
|
58557
|
-
auth: "admin"
|
|
58558
|
-
}), method(ProfileRefInputSchema, _void(), {
|
|
58559
|
-
kind: "mutation",
|
|
58560
|
-
auth: "admin"
|
|
58561
|
-
}), method(ProfileRefInputSchema, LlmGenerateResultSchema, {
|
|
58562
|
-
kind: "mutation",
|
|
58563
|
-
auth: "admin",
|
|
58564
|
-
timeoutMs: AI_CAP_TRANSPORT_TIMEOUT_MS
|
|
58565
|
-
}), method(LlmListModelsInputSchema, LlmListModelsResultSchema, {
|
|
58569
|
+
}), _void(), { kind: "mutation" }), method(LlmListModelsInputSchema, LlmListModelsResultSchema, {
|
|
58566
58570
|
kind: "mutation",
|
|
58567
58571
|
auth: "admin"
|
|
58568
58572
|
}), method(object({}), array(LlmDefaultSchema)), method(object({
|
|
@@ -59625,20 +59629,7 @@ method(_void(), MeshStatusSchema), method(object({
|
|
|
59625
59629
|
/** Optional hostname override the host should advertise once joined. */
|
|
59626
59630
|
hostname: string().optional() }), object({
|
|
59627
59631
|
/** Authentication URL the operator should open in a browser. */
|
|
59628
|
-
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() }))
|
|
59629
|
-
/** Optional auth key — when provided, probes the key validity
|
|
59630
|
-
* against the provider's API. Omit when already joined to
|
|
59631
|
-
* just ping the daemon. */
|
|
59632
|
-
authKey: string().optional() }), object({
|
|
59633
|
-
ok: boolean(),
|
|
59634
|
-
/** Provider-side identifier resolved by the probe (tailnet
|
|
59635
|
-
* name for Tailscale, network id for ZeroTier, etc.). */
|
|
59636
|
-
tenant: string().optional(),
|
|
59637
|
-
/** Daemon binary version, when reachable. */
|
|
59638
|
-
daemonVersion: string().optional(),
|
|
59639
|
-
/** Human-readable error when `ok: false`. */
|
|
59640
|
-
error: string().optional()
|
|
59641
|
-
}), { kind: "mutation" });
|
|
59632
|
+
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() }));
|
|
59642
59633
|
/**
|
|
59643
59634
|
* A monotonic total between resets (D944). Energy uses `power-meter.energy`
|
|
59644
59635
|
* so dashboards keep one series; every other instantaneous reading lands here.
|
|
@@ -69845,61 +69836,6 @@ var OauthIntegrationDescriptorSchema = object({
|
|
|
69845
69836
|
});
|
|
69846
69837
|
method(_void(), OauthIntegrationDescriptorSchema, { auth: "admin" });
|
|
69847
69838
|
/**
|
|
69848
|
-
* `oidc-connections` — CRUD for IdP rows under `auth-oidc` (D828 sibling).
|
|
69849
|
-
*
|
|
69850
|
-
* One hub-only singleton (`auth-oidc`). The Settings UI is a DataTable +
|
|
69851
|
-
* ItemFormDialog; there is no `editable-array` in `globalSettingsSchema`.
|
|
69852
|
-
* Operator-chosen `id` is the URL slug (`/addon/auth-oidc/<id>/…`) and is
|
|
69853
|
-
* immutable after create.
|
|
69854
|
-
*/
|
|
69855
|
-
var ConfigSchemaPassthrough$1 = unknown();
|
|
69856
|
-
var OidcConnectionSchema = object({
|
|
69857
|
-
id: string().min(1),
|
|
69858
|
-
displayName: string(),
|
|
69859
|
-
icon: string(),
|
|
69860
|
-
issuerUrl: string(),
|
|
69861
|
-
clientId: string(),
|
|
69862
|
-
/** Client id + secret present — never the secret value. */
|
|
69863
|
-
configured: boolean(),
|
|
69864
|
-
/**
|
|
69865
|
-
* Values for the connection form schema. `clientSecret` is a keychain
|
|
69866
|
-
* {@link SecretFieldView} or `null` / `''`, never plaintext (D789).
|
|
69867
|
-
*/
|
|
69868
|
-
formValues: record(string(), unknown()).optional()
|
|
69869
|
-
});
|
|
69870
|
-
/**
|
|
69871
|
-
* Patch one connection. Omitted or empty `clientSecret` keeps the stored
|
|
69872
|
-
* secret (D787). `{ $secretClear: true }` clears it. `id` is never renamed.
|
|
69873
|
-
*/
|
|
69874
|
-
var OidcConnectionUpdateInputSchema = object({
|
|
69875
|
-
id: string().min(1),
|
|
69876
|
-
displayName: string().min(1),
|
|
69877
|
-
icon: string().optional(),
|
|
69878
|
-
issuerUrl: string().optional(),
|
|
69879
|
-
clientId: string().optional(),
|
|
69880
|
-
clientSecret: union([string(), object({ $secretClear: literal(true) })]).optional(),
|
|
69881
|
-
redirectUri: string().optional(),
|
|
69882
|
-
scopes: string().optional(),
|
|
69883
|
-
usernameClaim: _enum([
|
|
69884
|
-
"preferred_username",
|
|
69885
|
-
"email",
|
|
69886
|
-
"sub"
|
|
69887
|
-
]).optional()
|
|
69888
|
-
});
|
|
69889
|
-
method(object({}), ConfigSchemaPassthrough$1, { auth: "admin" }), method(object({}), array(OidcConnectionSchema).readonly(), { auth: "admin" }), method(object({
|
|
69890
|
-
id: string().min(1).regex(/^[a-z0-9][a-z0-9-]{0,63}$/, "id must be a lowercase slug"),
|
|
69891
|
-
displayName: string().min(1)
|
|
69892
|
-
}), object({ id: string() }), {
|
|
69893
|
-
kind: "mutation",
|
|
69894
|
-
auth: "admin"
|
|
69895
|
-
}), method(OidcConnectionUpdateInputSchema, object({ ok: literal(true) }), {
|
|
69896
|
-
kind: "mutation",
|
|
69897
|
-
auth: "admin"
|
|
69898
|
-
}), method(object({ id: string().min(1) }), object({ ok: literal(true) }), {
|
|
69899
|
-
kind: "mutation",
|
|
69900
|
-
auth: "admin"
|
|
69901
|
-
});
|
|
69902
|
-
/**
|
|
69903
69839
|
* Generic on-screen-display (video overlay) cap. Each camera exposes
|
|
69904
69840
|
* a firmware-defined list of overlays (channel name, timestamp,
|
|
69905
69841
|
* watermark, logo, …); the cap models them as a homogeneous array of
|
|
@@ -76981,21 +76917,6 @@ method(object({
|
|
|
76981
76917
|
*/
|
|
76982
76918
|
ttlSec: union([number$1().int().positive(), literal("never")]).optional()
|
|
76983
76919
|
}), object({ token: string() }), { auth: "admin" }), method(object({ token: string() }), SsoBridgeClaimsSchema.nullable(), { auth: "admin" });
|
|
76984
|
-
var ProviderListEntrySchema = discriminatedUnion("shouldSaveDiskSpace", [object({
|
|
76985
|
-
providerId: string().min(1),
|
|
76986
|
-
displayName: string().min(1),
|
|
76987
|
-
configSchema: unknown(),
|
|
76988
|
-
nodeLocal: boolean(),
|
|
76989
|
-
shouldSaveDiskSpace: literal(true),
|
|
76990
|
-
minFreePercent: number$1().min(0).max(100)
|
|
76991
|
-
}), object({
|
|
76992
|
-
providerId: string().min(1),
|
|
76993
|
-
displayName: string().min(1),
|
|
76994
|
-
configSchema: unknown(),
|
|
76995
|
-
nodeLocal: boolean(),
|
|
76996
|
-
shouldSaveDiskSpace: literal(false),
|
|
76997
|
-
minFreePercent: literal(null)
|
|
76998
|
-
})]);
|
|
76999
76920
|
method(object({
|
|
77000
76921
|
location: StorageLocationRefSchema,
|
|
77001
76922
|
relativePath: string()
|
|
@@ -77057,42 +76978,7 @@ method(object({
|
|
|
77057
76978
|
}), _instanceof(Uint8Array), { auth: "admin" }), method(object({ downloadId: string() }), _void(), {
|
|
77058
76979
|
kind: "mutation",
|
|
77059
76980
|
auth: "admin"
|
|
77060
|
-
}), method(object({ type: StorageLocationTypeSchema.optional() }), array(StorageLocationSchema).readonly()), method(_void(), array(StorageLocationDeclarationSchema).readonly()), method(
|
|
77061
|
-
createdAt: true,
|
|
77062
|
-
updatedAt: true
|
|
77063
|
-
}), StorageLocationSchema, {
|
|
77064
|
-
kind: "mutation",
|
|
77065
|
-
auth: "admin"
|
|
77066
|
-
}), method(object({
|
|
77067
|
-
id: string(),
|
|
77068
|
-
force: boolean().optional()
|
|
77069
|
-
}), _void(), {
|
|
77070
|
-
kind: "mutation",
|
|
77071
|
-
auth: "admin"
|
|
77072
|
-
}), method(_void(), array(StorageDrainProgressSchema).readonly()), method(object({ id: string() }), object({
|
|
77073
|
-
ok: boolean(),
|
|
77074
|
-
error: string().optional()
|
|
77075
|
-
}), { auth: "admin" }), method(_void(), array(ProviderListEntrySchema).readonly()), method(object({
|
|
77076
|
-
providerId: string(),
|
|
77077
|
-
/**
|
|
77078
|
-
* The location this config is an UNSAVED edit of, when there is one.
|
|
77079
|
-
*
|
|
77080
|
-
* `listLocations` replaces every declared secret with the redaction
|
|
77081
|
-
* sentinel, so the edit modal's form state holds the sentinel for any
|
|
77082
|
-
* credential the operator did not retype — and posting that here
|
|
77083
|
-
* without a way to resolve it makes the provider try to authenticate
|
|
77084
|
-
* as `__camstack_redacted__` and report the operator's own working
|
|
77085
|
-
* password as wrong. Given this id, the orchestrator restores each
|
|
77086
|
-
* sentinel from the stored config (same rule as `upsertLocation`)
|
|
77087
|
-
* before dispatching. Omitted by the "Add location" wizard, where
|
|
77088
|
-
* every value was typed just now and nothing is stored yet.
|
|
77089
|
-
*/
|
|
77090
|
-
locationId: string().optional(),
|
|
77091
|
-
config: record(string(), unknown())
|
|
77092
|
-
}), object({
|
|
77093
|
-
ok: boolean(),
|
|
77094
|
-
error: string().optional()
|
|
77095
|
-
}), { auth: "admin" });
|
|
76981
|
+
}), method(object({ type: StorageLocationTypeSchema.optional() }), array(StorageLocationSchema).readonly()), method(_void(), array(StorageLocationDeclarationSchema).readonly()), method(_void(), array(StorageDrainProgressSchema).readonly());
|
|
77096
76982
|
/** One table of the settings database. */
|
|
77097
76983
|
var StorageTableSchema = object({
|
|
77098
76984
|
/** The table's full name, e.g. `recorder:addon-settings` or `addon-device-settings`. */
|
|
@@ -86978,13 +86864,6 @@ Object.freeze({
|
|
|
86978
86864
|
access: "delete",
|
|
86979
86865
|
role: "admin"
|
|
86980
86866
|
},
|
|
86981
|
-
"llm.deleteProfile": {
|
|
86982
|
-
capName: "llm",
|
|
86983
|
-
capScope: "system",
|
|
86984
|
-
addonId: null,
|
|
86985
|
-
access: "delete",
|
|
86986
|
-
role: "admin"
|
|
86987
|
-
},
|
|
86988
86867
|
"llm.generate": {
|
|
86989
86868
|
capName: "llm",
|
|
86990
86869
|
capScope: "system",
|
|
@@ -87048,20 +86927,6 @@ Object.freeze({
|
|
|
87048
86927
|
access: "view",
|
|
87049
86928
|
role: "admin"
|
|
87050
86929
|
},
|
|
87051
|
-
"llm.listProfileKinds": {
|
|
87052
|
-
capName: "llm",
|
|
87053
|
-
capScope: "system",
|
|
87054
|
-
addonId: null,
|
|
87055
|
-
access: "view",
|
|
87056
|
-
role: "admin"
|
|
87057
|
-
},
|
|
87058
|
-
"llm.listProfiles": {
|
|
87059
|
-
capName: "llm",
|
|
87060
|
-
capScope: "system",
|
|
87061
|
-
addonId: null,
|
|
87062
|
-
access: "view",
|
|
87063
|
-
role: "admin"
|
|
87064
|
-
},
|
|
87065
86930
|
"llm.listRuntimeNodes": {
|
|
87066
86931
|
capName: "llm",
|
|
87067
86932
|
capScope: "system",
|
|
@@ -87069,13 +86934,6 @@ Object.freeze({
|
|
|
87069
86934
|
access: "view",
|
|
87070
86935
|
role: "admin"
|
|
87071
86936
|
},
|
|
87072
|
-
"llm.migrateRawSecrets": {
|
|
87073
|
-
capName: "llm",
|
|
87074
|
-
capScope: "system",
|
|
87075
|
-
addonId: null,
|
|
87076
|
-
access: "create",
|
|
87077
|
-
role: "admin"
|
|
87078
|
-
},
|
|
87079
86937
|
"llm.resolveModelRef": {
|
|
87080
86938
|
capName: "llm",
|
|
87081
86939
|
capScope: "system",
|
|
@@ -87104,20 +86962,6 @@ Object.freeze({
|
|
|
87104
86962
|
access: "create",
|
|
87105
86963
|
role: "admin"
|
|
87106
86964
|
},
|
|
87107
|
-
"llm.testProfile": {
|
|
87108
|
-
capName: "llm",
|
|
87109
|
-
capScope: "system",
|
|
87110
|
-
addonId: null,
|
|
87111
|
-
access: "create",
|
|
87112
|
-
role: "admin"
|
|
87113
|
-
},
|
|
87114
|
-
"llm.upsertProfile": {
|
|
87115
|
-
capName: "llm",
|
|
87116
|
-
capScope: "system",
|
|
87117
|
-
addonId: null,
|
|
87118
|
-
access: "create",
|
|
87119
|
-
role: "admin"
|
|
87120
|
-
},
|
|
87121
86965
|
"llmRuntime.appleAvailability": {
|
|
87122
86966
|
capName: "llm-runtime",
|
|
87123
86967
|
capScope: "system",
|
|
@@ -87622,13 +87466,6 @@ Object.freeze({
|
|
|
87622
87466
|
access: "create",
|
|
87623
87467
|
role: "admin"
|
|
87624
87468
|
},
|
|
87625
|
-
"meshNetwork.testConnection": {
|
|
87626
|
-
capName: "mesh-network",
|
|
87627
|
-
capScope: "system",
|
|
87628
|
-
addonId: null,
|
|
87629
|
-
access: "create",
|
|
87630
|
-
role: "admin"
|
|
87631
|
-
},
|
|
87632
87469
|
"meter.getStatus": {
|
|
87633
87470
|
capName: "meter",
|
|
87634
87471
|
capScope: "device",
|
|
@@ -88287,13 +88124,6 @@ Object.freeze({
|
|
|
88287
88124
|
access: "create",
|
|
88288
88125
|
role: "admin"
|
|
88289
88126
|
},
|
|
88290
|
-
"notificationOutput.deleteTarget": {
|
|
88291
|
-
capName: "notification-output",
|
|
88292
|
-
capScope: "system",
|
|
88293
|
-
addonId: null,
|
|
88294
|
-
access: "delete",
|
|
88295
|
-
role: "admin"
|
|
88296
|
-
},
|
|
88297
88127
|
"notificationOutput.discoverTargets": {
|
|
88298
88128
|
capName: "notification-output",
|
|
88299
88129
|
capScope: "system",
|
|
@@ -88301,13 +88131,6 @@ Object.freeze({
|
|
|
88301
88131
|
access: "view",
|
|
88302
88132
|
role: "admin"
|
|
88303
88133
|
},
|
|
88304
|
-
"notificationOutput.getTarget": {
|
|
88305
|
-
capName: "notification-output",
|
|
88306
|
-
capScope: "system",
|
|
88307
|
-
addonId: null,
|
|
88308
|
-
access: "view",
|
|
88309
|
-
role: "admin"
|
|
88310
|
-
},
|
|
88311
88134
|
"notificationOutput.listTargetKinds": {
|
|
88312
88135
|
capName: "notification-output",
|
|
88313
88136
|
capScope: "system",
|
|
@@ -88315,13 +88138,6 @@ Object.freeze({
|
|
|
88315
88138
|
access: "view",
|
|
88316
88139
|
role: "admin"
|
|
88317
88140
|
},
|
|
88318
|
-
"notificationOutput.listTargets": {
|
|
88319
|
-
capName: "notification-output",
|
|
88320
|
-
capScope: "system",
|
|
88321
|
-
addonId: null,
|
|
88322
|
-
access: "view",
|
|
88323
|
-
role: "admin"
|
|
88324
|
-
},
|
|
88325
88141
|
"notificationOutput.probeTargetConfig": {
|
|
88326
88142
|
capName: "notification-output",
|
|
88327
88143
|
capScope: "system",
|
|
@@ -88336,13 +88152,6 @@ Object.freeze({
|
|
|
88336
88152
|
access: "create",
|
|
88337
88153
|
role: "admin"
|
|
88338
88154
|
},
|
|
88339
|
-
"notificationOutput.setTargetEnabled": {
|
|
88340
|
-
capName: "notification-output",
|
|
88341
|
-
capScope: "system",
|
|
88342
|
-
addonId: null,
|
|
88343
|
-
access: "create",
|
|
88344
|
-
role: "admin"
|
|
88345
|
-
},
|
|
88346
88155
|
"notificationOutput.testTarget": {
|
|
88347
88156
|
capName: "notification-output",
|
|
88348
88157
|
capScope: "system",
|
|
@@ -88350,13 +88159,6 @@ Object.freeze({
|
|
|
88350
88159
|
access: "create",
|
|
88351
88160
|
role: "admin"
|
|
88352
88161
|
},
|
|
88353
|
-
"notificationOutput.upsertTarget": {
|
|
88354
|
-
capName: "notification-output",
|
|
88355
|
-
capScope: "system",
|
|
88356
|
-
addonId: null,
|
|
88357
|
-
access: "create",
|
|
88358
|
-
role: "admin"
|
|
88359
|
-
},
|
|
88360
88162
|
"notificationRules.activateAlarmProfile": {
|
|
88361
88163
|
capName: "notification-rules",
|
|
88362
88164
|
capScope: "system",
|
|
@@ -88616,41 +88418,6 @@ Object.freeze({
|
|
|
88616
88418
|
access: "view",
|
|
88617
88419
|
role: "admin"
|
|
88618
88420
|
},
|
|
88619
|
-
"oidcConnections.connectionFormSchema": {
|
|
88620
|
-
capName: "oidc-connections",
|
|
88621
|
-
capScope: "system",
|
|
88622
|
-
addonId: null,
|
|
88623
|
-
access: "view",
|
|
88624
|
-
role: "admin"
|
|
88625
|
-
},
|
|
88626
|
-
"oidcConnections.createConnection": {
|
|
88627
|
-
capName: "oidc-connections",
|
|
88628
|
-
capScope: "system",
|
|
88629
|
-
addonId: null,
|
|
88630
|
-
access: "create",
|
|
88631
|
-
role: "admin"
|
|
88632
|
-
},
|
|
88633
|
-
"oidcConnections.deleteConnection": {
|
|
88634
|
-
capName: "oidc-connections",
|
|
88635
|
-
capScope: "system",
|
|
88636
|
-
addonId: null,
|
|
88637
|
-
access: "delete",
|
|
88638
|
-
role: "admin"
|
|
88639
|
-
},
|
|
88640
|
-
"oidcConnections.listConnections": {
|
|
88641
|
-
capName: "oidc-connections",
|
|
88642
|
-
capScope: "system",
|
|
88643
|
-
addonId: null,
|
|
88644
|
-
access: "view",
|
|
88645
|
-
role: "admin"
|
|
88646
|
-
},
|
|
88647
|
-
"oidcConnections.updateConnection": {
|
|
88648
|
-
capName: "oidc-connections",
|
|
88649
|
-
capScope: "system",
|
|
88650
|
-
addonId: null,
|
|
88651
|
-
access: "create",
|
|
88652
|
-
role: "admin"
|
|
88653
|
-
},
|
|
88654
88421
|
"osd.getStatus": {
|
|
88655
88422
|
capName: "osd",
|
|
88656
88423
|
capScope: "device",
|
|
@@ -91682,13 +91449,6 @@ Object.freeze({
|
|
|
91682
91449
|
access: "delete",
|
|
91683
91450
|
role: "admin"
|
|
91684
91451
|
},
|
|
91685
|
-
"storage.deleteLocation": {
|
|
91686
|
-
capName: "storage",
|
|
91687
|
-
capScope: "system",
|
|
91688
|
-
addonId: null,
|
|
91689
|
-
access: "delete",
|
|
91690
|
-
role: "admin"
|
|
91691
|
-
},
|
|
91692
91452
|
"storage.endDownload": {
|
|
91693
91453
|
capName: "storage",
|
|
91694
91454
|
capScope: "system",
|
|
@@ -91745,13 +91505,6 @@ Object.freeze({
|
|
|
91745
91505
|
access: "view",
|
|
91746
91506
|
role: "admin"
|
|
91747
91507
|
},
|
|
91748
|
-
"storage.listProviders": {
|
|
91749
|
-
capName: "storage",
|
|
91750
|
-
capScope: "system",
|
|
91751
|
-
addonId: null,
|
|
91752
|
-
access: "view",
|
|
91753
|
-
role: "admin"
|
|
91754
|
-
},
|
|
91755
91508
|
"storage.read": {
|
|
91756
91509
|
capName: "storage",
|
|
91757
91510
|
capScope: "system",
|
|
@@ -91773,27 +91526,6 @@ Object.freeze({
|
|
|
91773
91526
|
access: "view",
|
|
91774
91527
|
role: "admin"
|
|
91775
91528
|
},
|
|
91776
|
-
"storage.testConfig": {
|
|
91777
|
-
capName: "storage",
|
|
91778
|
-
capScope: "system",
|
|
91779
|
-
addonId: null,
|
|
91780
|
-
access: "view",
|
|
91781
|
-
role: "admin"
|
|
91782
|
-
},
|
|
91783
|
-
"storage.testLocation": {
|
|
91784
|
-
capName: "storage",
|
|
91785
|
-
capScope: "system",
|
|
91786
|
-
addonId: null,
|
|
91787
|
-
access: "view",
|
|
91788
|
-
role: "admin"
|
|
91789
|
-
},
|
|
91790
|
-
"storage.upsertLocation": {
|
|
91791
|
-
capName: "storage",
|
|
91792
|
-
capScope: "system",
|
|
91793
|
-
addonId: null,
|
|
91794
|
-
access: "create",
|
|
91795
|
-
role: "admin"
|
|
91796
|
-
},
|
|
91797
91529
|
"storage.write": {
|
|
91798
91530
|
capName: "storage",
|
|
91799
91531
|
capScope: "system",
|
|
@@ -145521,6 +145253,33 @@ function quietLogger$1() {
|
|
|
145521
145253
|
};
|
|
145522
145254
|
return logger;
|
|
145523
145255
|
}
|
|
145256
|
+
/**
|
|
145257
|
+
* The account a target speaks through: the one it names; else the only one there is; else the one
|
|
145258
|
+
* whose Echoes include the target's Echo.
|
|
145259
|
+
*/
|
|
145260
|
+
function pickBroker(brokers, config) {
|
|
145261
|
+
const named = readString(config, "brokerId");
|
|
145262
|
+
if (named.length > 0) return brokers.find((broker) => broker.id === named);
|
|
145263
|
+
if (brokers.length === 1) return brokers[0];
|
|
145264
|
+
const echoId = readString(config, "echoId");
|
|
145265
|
+
const owners = brokers.filter((broker) => broker.devices.some((device) => device.id === echoId));
|
|
145266
|
+
return owners.length === 1 ? owners[0] : void 0;
|
|
145267
|
+
}
|
|
145268
|
+
/**
|
|
145269
|
+
* The save-time rule of an Echo target: an Echo and an account must be picked, and the account is
|
|
145270
|
+
* pinned the moment it is known, so a second account added later cannot silently change where an
|
|
145271
|
+
* existing target speaks. Throws the reason; returns the keys to keep with the write.
|
|
145272
|
+
*/
|
|
145273
|
+
function validateEchoTarget(brokers, config) {
|
|
145274
|
+
if (readString(config, "echoId").length === 0) throw new Error("Pick the Echo that should speak");
|
|
145275
|
+
const owner = pickBroker(brokers, config);
|
|
145276
|
+
if (owner === void 0) {
|
|
145277
|
+
const named = readString(config, "brokerId");
|
|
145278
|
+
if (named.length > 0) throw new Error(`The Amazon account ${named} is not available`);
|
|
145279
|
+
throw new Error(brokers.length === 0 ? "Add an Amazon account first: an Echo speaks through one" : "Pick the Amazon account this Echo belongs to");
|
|
145280
|
+
}
|
|
145281
|
+
return readString(config, "brokerId").length === 0 ? { brokerId: owner.id } : {};
|
|
145282
|
+
}
|
|
145524
145283
|
function readString(config, key) {
|
|
145525
145284
|
const value = config[key];
|
|
145526
145285
|
return typeof value === "string" ? value : "";
|
|
@@ -145550,7 +145309,7 @@ function echoOptionLabel(device) {
|
|
|
145550
145309
|
/**
|
|
145551
145310
|
* The two pickers are not `required`: a required select shows its first option
|
|
145552
145311
|
* while the form still holds no value, so a save would drop the choice. Left
|
|
145553
|
-
* optional they open on "Select", and `
|
|
145312
|
+
* optional they open on "Select", and `validateEchoTarget` refuses an empty pick on save.
|
|
145554
145313
|
*
|
|
145555
145314
|
* The account is a broker pick (existing, or created in place); the Echo list
|
|
145556
145315
|
* is fetched from that account, so a new Echo shows up without a deploy.
|
|
@@ -145642,18 +145401,8 @@ function createAlexaNotificationProvider(ports) {
|
|
|
145642
145401
|
function record(row) {
|
|
145643
145402
|
deliveries = [...deliveries, row];
|
|
145644
145403
|
}
|
|
145645
|
-
/**
|
|
145646
|
-
* The account a target speaks through: the one it names; else the only one
|
|
145647
|
-
* there is; else the one whose Echoes include the target's Echo.
|
|
145648
|
-
*/
|
|
145649
145404
|
function brokerFor(config) {
|
|
145650
|
-
|
|
145651
|
-
const named = readString(config, "brokerId");
|
|
145652
|
-
if (named.length > 0) return all.find((broker) => broker.id === named);
|
|
145653
|
-
if (all.length === 1) return all[0];
|
|
145654
|
-
const echoId = readString(config, "echoId");
|
|
145655
|
-
const owners = all.filter((broker) => broker.devices.some((device) => device.id === echoId));
|
|
145656
|
-
return owners.length === 1 ? owners[0] : void 0;
|
|
145405
|
+
return pickBroker(ports.brokers(), config);
|
|
145657
145406
|
}
|
|
145658
145407
|
async function deliver(target, notification) {
|
|
145659
145408
|
const speech = speechFromNotification(notification);
|
|
@@ -145855,14 +145604,6 @@ function createAlexaNotificationProvider(ports) {
|
|
|
145855
145604
|
async listTargetKinds() {
|
|
145856
145605
|
return [alexaTargetKind()];
|
|
145857
145606
|
},
|
|
145858
|
-
async listTargets() {
|
|
145859
|
-
return [...await ports.loadTargets()];
|
|
145860
|
-
},
|
|
145861
|
-
async getTarget(input) {
|
|
145862
|
-
const found = (await ports.loadTargets()).find((target) => target.id === input.targetId);
|
|
145863
|
-
if (found === void 0) throw new Error(`target not found: ${input.targetId}`);
|
|
145864
|
-
return found;
|
|
145865
|
-
},
|
|
145866
145607
|
async discoverTargets(input) {
|
|
145867
145608
|
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 } });
|
|
145868
145609
|
const named = readString(input.config ?? {}, "brokerId");
|
|
@@ -145923,33 +145664,6 @@ function createAlexaNotificationProvider(ports) {
|
|
|
145923
145664
|
format: "text",
|
|
145924
145665
|
priority: 3
|
|
145925
145666
|
});
|
|
145926
|
-
},
|
|
145927
|
-
async upsertTarget(input) {
|
|
145928
|
-
const owner = brokerFor(input.target.config);
|
|
145929
|
-
if (readString(input.target.config, "echoId").length === 0) throw new Error("Pick the Echo that should speak");
|
|
145930
|
-
if (owner === void 0) throw new Error("Pick the Amazon account this Echo belongs to");
|
|
145931
|
-
const pinned = readString(input.target.config, "brokerId").length === 0 ? {
|
|
145932
|
-
...input.target.config,
|
|
145933
|
-
brokerId: owner.id
|
|
145934
|
-
} : input.target.config;
|
|
145935
|
-
const target = {
|
|
145936
|
-
...input.target,
|
|
145937
|
-
config: pinned,
|
|
145938
|
-
addonId: ALEXA_SPEAK_ADDON_ID,
|
|
145939
|
-
kind: ALEXA_SPEAK_KIND
|
|
145940
|
-
};
|
|
145941
|
-
await ports.putTarget(target);
|
|
145942
|
-
return target;
|
|
145943
|
-
},
|
|
145944
|
-
async deleteTarget(input) {
|
|
145945
|
-
await ports.removeTarget(input.targetId);
|
|
145946
|
-
},
|
|
145947
|
-
async setTargetEnabled(input) {
|
|
145948
|
-
const found = (await ports.loadTargets()).find((row) => row.id === input.targetId);
|
|
145949
|
-
if (found !== void 0) await ports.putTarget({
|
|
145950
|
-
...found,
|
|
145951
|
-
enabled: input.enabled
|
|
145952
|
-
});
|
|
145953
145667
|
}
|
|
145954
145668
|
};
|
|
145955
145669
|
}
|
|
@@ -146040,6 +145754,14 @@ function echoTargetProbe(speak) {
|
|
|
146040
145754
|
});
|
|
146041
145755
|
};
|
|
146042
145756
|
}
|
|
145757
|
+
/**
|
|
145758
|
+
* The Echo instance's save-time rule over the accounts now (D1013): the check the removed
|
|
145759
|
+
* `upsertTarget` made, on the instance door. Speech not started yet has no account to name, so the
|
|
145760
|
+
* write is refused with the reason, never accepted blind.
|
|
145761
|
+
*/
|
|
145762
|
+
function echoTargetValidator(brokers) {
|
|
145763
|
+
return ({ config }) => validateEchoTarget(brokers() ?? [], config);
|
|
145764
|
+
}
|
|
146043
145765
|
process.platform, process.env["SystemRoot"];
|
|
146044
145766
|
/**
|
|
146045
145767
|
* Files only their owner may read: the one place a secret-bearing file is
|
|
@@ -146880,8 +146602,6 @@ var AlexaSpeakController = class {
|
|
|
146880
146602
|
now: this.now,
|
|
146881
146603
|
logger: host.logger,
|
|
146882
146604
|
loadTargets: () => host.readTargets(),
|
|
146883
|
-
putTarget: (target) => host.putTarget(target),
|
|
146884
|
-
removeTarget: (targetId) => host.removeTarget(targetId),
|
|
146885
146605
|
speak: (command) => this.utter(command.brokerId, command.mode, command.targets, command.text)
|
|
146886
146606
|
});
|
|
146887
146607
|
}
|
|
@@ -146911,6 +146631,7 @@ var AlexaSpeakController = class {
|
|
|
146911
146631
|
echoFor(brokerId) {
|
|
146912
146632
|
return this.echoes.get(brokerId) ?? null;
|
|
146913
146633
|
}
|
|
146634
|
+
/** The accounts right now, as the provider and the save-time rule see them. */
|
|
146914
146635
|
brokerViews() {
|
|
146915
146636
|
return this.host.listBrokers().map((ref) => {
|
|
146916
146637
|
const echo = this.echoes.get(ref.id);
|
|
@@ -147458,8 +147179,6 @@ var AlexaImportAddon = class extends BaseDeviceProvider {
|
|
|
147458
147179
|
const speak = new AlexaSpeakController({
|
|
147459
147180
|
logger: this.ctx.logger.child("speak"),
|
|
147460
147181
|
readTargets: () => echoStore.list(),
|
|
147461
|
-
putTarget: (target) => echoStore.upsert(target),
|
|
147462
|
-
removeTarget: (targetId) => echoStore.delete(targetId),
|
|
147463
147182
|
listBrokers: () => this.activeBrokers.map((entry) => ({
|
|
147464
147183
|
id: entry.id,
|
|
147465
147184
|
name: entry.name,
|
|
@@ -147561,6 +147280,7 @@ var AlexaImportAddon = class extends BaseDeviceProvider {
|
|
|
147561
147280
|
kinds: alexaNotifyRecordKinds,
|
|
147562
147281
|
mintId: () => (0, node_crypto.randomUUID)(),
|
|
147563
147282
|
probe: echoTargetProbe(() => this.speak),
|
|
147283
|
+
validate: echoTargetValidator(() => this.speak?.brokerViews() ?? null),
|
|
147564
147284
|
canProbe: () => true
|
|
147565
147285
|
})
|
|
147566
147286
|
], {
|