camstack 1.2.188 → 1.2.190
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +356 -38
- package/dist/{launcher-FYTHPW44.js → launcher-ILGFB3AQ.js} +1893 -709
- package/package.json +1 -1
|
@@ -24024,9 +24024,9 @@ var require_zod = __commonJS({
|
|
|
24024
24024
|
}
|
|
24025
24025
|
});
|
|
24026
24026
|
|
|
24027
|
-
// ../system/dist/dist-
|
|
24028
|
-
var
|
|
24029
|
-
"../system/dist/dist-
|
|
24027
|
+
// ../system/dist/dist-Bi4Ioxop.js
|
|
24028
|
+
var require_dist_Bi4Ioxop = __commonJS({
|
|
24029
|
+
"../system/dist/dist-Bi4Ioxop.js"(exports) {
|
|
24030
24030
|
"use strict";
|
|
24031
24031
|
var zod = require_zod();
|
|
24032
24032
|
__require("crypto");
|
|
@@ -24049,6 +24049,7 @@ var require_dist_Ct88catN = __commonJS({
|
|
|
24049
24049
|
EventCategory2["AddonRunnerRefused"] = "addon.runner-refused";
|
|
24050
24050
|
EventCategory2["ProcessStateChanged"] = "process.state-changed";
|
|
24051
24051
|
EventCategory2["SystemRunnerCheck"] = "system.runner-check";
|
|
24052
|
+
EventCategory2["AlertEpisode"] = "alert.episode";
|
|
24052
24053
|
EventCategory2["AddonError"] = "addon.error";
|
|
24053
24054
|
EventCategory2["AddonPageReady"] = "addon.page-ready";
|
|
24054
24055
|
EventCategory2["AddonWidgetReady"] = "addon.widget-ready";
|
|
@@ -32045,7 +32046,14 @@ var require_dist_Ct88catN = __commonJS({
|
|
|
32045
32046
|
]);
|
|
32046
32047
|
var AlertActionSchema = zod.z.object({
|
|
32047
32048
|
label: zod.z.string(),
|
|
32048
|
-
href: zod.z.string().optional()
|
|
32049
|
+
href: zod.z.string().optional(),
|
|
32050
|
+
/**
|
|
32051
|
+
* How `href` is followed. Absent / `app`: an admin-ui route (client-side).
|
|
32052
|
+
* `server`: a route the HUB serves (an addon HTTP route such as an OAuth
|
|
32053
|
+
* start) — the browser must leave the SPA with a full navigation, because
|
|
32054
|
+
* the SPA has no such route and would bounce to the home page.
|
|
32055
|
+
*/
|
|
32056
|
+
navigation: zod.z.enum(["app", "server"]).optional()
|
|
32049
32057
|
});
|
|
32050
32058
|
var AlertStatusSchema = zod.z.enum([
|
|
32051
32059
|
"active",
|
|
@@ -38138,7 +38146,7 @@ var require_dist_Ct88catN = __commonJS({
|
|
|
38138
38146
|
var deviceAdoptionCapability = {
|
|
38139
38147
|
name: "device-adoption",
|
|
38140
38148
|
scope: "system",
|
|
38141
|
-
mode: "
|
|
38149
|
+
mode: "collection",
|
|
38142
38150
|
status: {
|
|
38143
38151
|
schema: AdoptionStatusSchema,
|
|
38144
38152
|
kind: "poll"
|
|
@@ -59424,7 +59432,7 @@ var require_dist_Ct88catN = __commonJS({
|
|
|
59424
59432
|
auth: "admin"
|
|
59425
59433
|
}),
|
|
59426
59434
|
/** List candidate filter chips for an integration via its device-adoption
|
|
59427
|
-
* provider — addonId-routed
|
|
59435
|
+
* provider — addonId-routed via the collection pin. */
|
|
59428
59436
|
adoptionListCandidateFilters: method(zod.z.object({
|
|
59429
59437
|
addonId: zod.z.string(),
|
|
59430
59438
|
integrationId: zod.z.string()
|
|
@@ -62794,6 +62802,9 @@ var require_dist_Ct88catN = __commonJS({
|
|
|
62794
62802
|
"server-updated",
|
|
62795
62803
|
"export-completed",
|
|
62796
62804
|
"backup-completed",
|
|
62805
|
+
"alert-critical",
|
|
62806
|
+
"alert-error",
|
|
62807
|
+
"alert-critical-resolved",
|
|
62797
62808
|
"camera-online",
|
|
62798
62809
|
"camera-offline",
|
|
62799
62810
|
"camera-disabled",
|
|
@@ -71992,6 +72003,18 @@ var require_dist_Ct88catN = __commonJS({
|
|
|
71992
72003
|
*/
|
|
71993
72004
|
movers: method(zod.z.object({}), zod.z.array(StorageMigrationMoverSchema).readonly(), { auth: "admin" }),
|
|
71994
72005
|
/**
|
|
72006
|
+
* May a mover that touches these locations run NOW? One claim per physical
|
|
72007
|
+
* root is owned by the storage orchestrator: a single-location repoint holds
|
|
72008
|
+
* it while it carries its subtree, and a mover (`relocateMedia`,
|
|
72009
|
+
* `relocateFootage`, a migration move) asks here AFTER registering its job and
|
|
72010
|
+
* cancels itself on `clear: false`. The repoint, in turn, refuses while a
|
|
72011
|
+
* registered mover touches its root. Asked, never polled (D3).
|
|
72012
|
+
*/
|
|
72013
|
+
moverClearance: method(zod.z.object({ locationIds: zod.z.array(zod.z.string()).readonly() }), zod.z.object({
|
|
72014
|
+
clear: zod.z.boolean(),
|
|
72015
|
+
repointLocationId: zod.z.string().optional()
|
|
72016
|
+
}), { auth: "admin" }),
|
|
72017
|
+
/**
|
|
71995
72018
|
* What each class's SOURCE still holds, from the archive — never from the
|
|
71996
72019
|
* resident index (D295). Only classes with something left (or something
|
|
71997
72020
|
* unknown) are listed, so an empty list means there is nothing to drain and
|
|
@@ -76209,35 +76232,139 @@ var require_dist_Ct88catN = __commonJS({
|
|
|
76209
76232
|
"error",
|
|
76210
76233
|
"unavailable"
|
|
76211
76234
|
]);
|
|
76235
|
+
var DishwasherOperationStateSchema = zod.z.enum([
|
|
76236
|
+
"Inactive",
|
|
76237
|
+
"Ready",
|
|
76238
|
+
"DelayedStart",
|
|
76239
|
+
"Run",
|
|
76240
|
+
"Pause",
|
|
76241
|
+
"ActionRequired",
|
|
76242
|
+
"Finished",
|
|
76243
|
+
"Error",
|
|
76244
|
+
"Aborting"
|
|
76245
|
+
]);
|
|
76246
|
+
var DishwasherAvailabilitySchema = zod.z.enum([
|
|
76247
|
+
"available",
|
|
76248
|
+
"offline",
|
|
76249
|
+
"description-missing"
|
|
76250
|
+
]);
|
|
76212
76251
|
var DishwasherConsumableLevelSchema = zod.z.enum([
|
|
76213
76252
|
"ok",
|
|
76214
76253
|
"low",
|
|
76215
76254
|
"empty"
|
|
76216
76255
|
]);
|
|
76217
76256
|
var DishwasherStatusSchema = zod.z.object({
|
|
76257
|
+
availability: DishwasherAvailabilitySchema,
|
|
76258
|
+
/** Coarse state for compact surfaces; `unavailable` whenever the appliance state is not known. */
|
|
76218
76259
|
state: DishwasherStateSchema,
|
|
76219
|
-
/**
|
|
76260
|
+
/** The appliance's operation state as reported; null when not known. */
|
|
76261
|
+
operationState: DishwasherOperationStateSchema.nullable(),
|
|
76262
|
+
/** Feature key of the ACTIVE (running) program, or null when none runs / not known. */
|
|
76220
76263
|
program: zod.z.string().nullable(),
|
|
76221
|
-
/**
|
|
76264
|
+
/** Feature key of the SELECTED program (what Start would run), or null when none / not known. */
|
|
76265
|
+
selectedProgram: zod.z.string().nullable(),
|
|
76266
|
+
/** Feature keys of the programs the appliance currently offers — drives the UI selector. */
|
|
76222
76267
|
availablePrograms: zod.z.array(zod.z.string()),
|
|
76223
|
-
/**
|
|
76224
|
-
|
|
76268
|
+
/** Seconds remaining on the active cycle, or null when not running / not known. */
|
|
76269
|
+
remainingSeconds: zod.z.number().int().nonnegative().nullable(),
|
|
76270
|
+
/** Seconds the delayed start is set to (time until the cycle starts), or null. */
|
|
76271
|
+
delayedStartSeconds: zod.z.number().int().nonnegative().nullable(),
|
|
76225
76272
|
/** Cycle completion 0..100, or null when not applicable. */
|
|
76226
76273
|
progressPercent: zod.z.number().min(0).max(100).nullable(),
|
|
76227
|
-
/** True when the door is reported open. */
|
|
76228
|
-
doorOpen: zod.z.boolean(),
|
|
76229
|
-
/** True when
|
|
76230
|
-
|
|
76231
|
-
/**
|
|
76232
|
-
|
|
76274
|
+
/** True when the door is reported open; null when the door state is not known. */
|
|
76275
|
+
doorOpen: zod.z.boolean().nullable(),
|
|
76276
|
+
/** True when the door is latched (locked) during a cycle; null when not reported. */
|
|
76277
|
+
doorLocked: zod.z.boolean().nullable(),
|
|
76278
|
+
/** True when remote start is allowed (door closed, power on, etc.); null when not known. */
|
|
76279
|
+
remoteStartAllowed: zod.z.boolean().nullable(),
|
|
76280
|
+
/** True when the appliance accepts remote control now; null when not known. */
|
|
76281
|
+
remoteControlActive: zod.z.boolean().nullable(),
|
|
76282
|
+
/** True while somebody operates the appliance at its panel; null when not reported. */
|
|
76283
|
+
localControlActive: zod.z.boolean().nullable(),
|
|
76284
|
+
/** Main power / switched-on state; null when not known. */
|
|
76285
|
+
powerOn: zod.z.boolean().nullable(),
|
|
76286
|
+
/** The raw power state (`On`, `Off`, `Standby`, …); null when not known. */
|
|
76287
|
+
powerState: zod.z.string().nullable(),
|
|
76233
76288
|
saltLevel: DishwasherConsumableLevelSchema.nullable(),
|
|
76234
76289
|
rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
|
|
76235
|
-
|
|
76236
|
-
|
|
76290
|
+
/** Option states: null when the appliance does not expose the option or has not said. */
|
|
76291
|
+
halfLoad: zod.z.boolean().nullable(),
|
|
76292
|
+
hygienePlus: zod.z.boolean().nullable(),
|
|
76293
|
+
/** Extra dry option when the appliance exposes it. */
|
|
76294
|
+
extraDry: zod.z.boolean().nullable(),
|
|
76295
|
+
/** Intensive zone (lower basket) when the appliance exposes it. */
|
|
76296
|
+
intensiveZone: zod.z.boolean().nullable(),
|
|
76297
|
+
/** VarioSpeed / VarioSpeed+ when the appliance exposes it. */
|
|
76298
|
+
varioSpeedPlus: zod.z.boolean().nullable(),
|
|
76299
|
+
/** Child lock (controls disabled on the appliance); null when not known. */
|
|
76300
|
+
childLock: zod.z.boolean().nullable(),
|
|
76301
|
+
/** Feature keys of the events currently raised (salt low, rinse aid low, program finished, …). */
|
|
76302
|
+
activeEvents: zod.z.array(zod.z.string()),
|
|
76303
|
+
/** Numeric error code when the appliance reports one; null otherwise. */
|
|
76237
76304
|
errorCode: zod.z.number().nullable(),
|
|
76305
|
+
/** Name of the raised alert-level event while the appliance is in error; null otherwise. */
|
|
76238
76306
|
errorLabel: zod.z.string().nullable(),
|
|
76307
|
+
/** Ms epoch of the last value received from the appliance; 0 = never. */
|
|
76239
76308
|
lastFetchedAt: zod.z.number()
|
|
76240
76309
|
});
|
|
76310
|
+
var DeviceIdSchema = zod.z.number().int().nonnegative();
|
|
76311
|
+
var DishwasherValueSchema = zod.z.union([
|
|
76312
|
+
zod.z.boolean(),
|
|
76313
|
+
zod.z.string(),
|
|
76314
|
+
zod.z.number()
|
|
76315
|
+
]);
|
|
76316
|
+
var DishwasherAccessSchema = zod.z.enum([
|
|
76317
|
+
"none",
|
|
76318
|
+
"read",
|
|
76319
|
+
"readWrite",
|
|
76320
|
+
"writeOnly",
|
|
76321
|
+
"readStatic"
|
|
76322
|
+
]);
|
|
76323
|
+
var DishwasherOptionDescriptorSchema = zod.z.object({
|
|
76324
|
+
/** Feature key (`Dishcare.Dishwasher.Option.ExtraDry`). */
|
|
76325
|
+
key: zod.z.string(),
|
|
76326
|
+
/** Last segment of the key, for display. */
|
|
76327
|
+
name: zod.z.string(),
|
|
76328
|
+
type: zod.z.enum([
|
|
76329
|
+
"boolean",
|
|
76330
|
+
"number",
|
|
76331
|
+
"enum",
|
|
76332
|
+
"string"
|
|
76333
|
+
]),
|
|
76334
|
+
access: DishwasherAccessSchema,
|
|
76335
|
+
/** The appliance reports this entity as currently available. */
|
|
76336
|
+
available: zod.z.boolean(),
|
|
76337
|
+
/** Unit the description declares for a number; null when it declares none. */
|
|
76338
|
+
unit: zod.z.string().nullable(),
|
|
76339
|
+
min: zod.z.number().nullable(),
|
|
76340
|
+
max: zod.z.number().nullable(),
|
|
76341
|
+
step: zod.z.number().nullable(),
|
|
76342
|
+
/** Allowed members of an enum; null for other types. */
|
|
76343
|
+
enumValues: zod.z.array(zod.z.string()).nullable(),
|
|
76344
|
+
defaultValue: DishwasherValueSchema.nullable()
|
|
76345
|
+
});
|
|
76346
|
+
var DishwasherProgramSchema = zod.z.object({
|
|
76347
|
+
/** Feature key (`Dishcare.Dishwasher.Program.Eco50`) — what `setProgram` / `start` take. */
|
|
76348
|
+
key: zod.z.string(),
|
|
76349
|
+
name: zod.z.string(),
|
|
76350
|
+
/** The appliance currently offers this program. */
|
|
76351
|
+
available: zod.z.boolean(),
|
|
76352
|
+
/** The options this program lists, with the program-level access / availability / default. */
|
|
76353
|
+
options: zod.z.array(DishwasherOptionDescriptorSchema)
|
|
76354
|
+
});
|
|
76355
|
+
var DishwasherOptionsSchema = zod.z.object({
|
|
76356
|
+
availability: DishwasherAvailabilitySchema,
|
|
76357
|
+
/** What the appliance can be told to do, from the commands its description declares. */
|
|
76358
|
+
supportsStart: zod.z.boolean(),
|
|
76359
|
+
supportsPause: zod.z.boolean(),
|
|
76360
|
+
supportsResume: zod.z.boolean(),
|
|
76361
|
+
supportsStop: zod.z.boolean(),
|
|
76362
|
+
supportsPower: zod.z.boolean(),
|
|
76363
|
+
/** Every program the description lists, with its options. */
|
|
76364
|
+
programs: zod.z.array(DishwasherProgramSchema),
|
|
76365
|
+
/** Every option and setting entity the description lists (programs reference these by key). */
|
|
76366
|
+
options: zod.z.array(DishwasherOptionDescriptorSchema)
|
|
76367
|
+
});
|
|
76241
76368
|
var dishwasherCapability = {
|
|
76242
76369
|
name: "dishwasher",
|
|
76243
76370
|
scope: "device",
|
|
@@ -76245,58 +76372,102 @@ var require_dist_Ct88catN = __commonJS({
|
|
|
76245
76372
|
mode: "singleton",
|
|
76246
76373
|
deviceTypes: [DeviceType.Dishwasher],
|
|
76247
76374
|
methods: {
|
|
76248
|
-
|
|
76375
|
+
/**
|
|
76376
|
+
* Start a program. Without `program` the selected one starts. `options` are
|
|
76377
|
+
* option feature keys; each is checked against the program's constraints.
|
|
76378
|
+
*/
|
|
76379
|
+
start: method(zod.z.object({
|
|
76380
|
+
deviceId: DeviceIdSchema,
|
|
76381
|
+
program: zod.z.string().min(1).optional(),
|
|
76382
|
+
options: zod.z.record(zod.z.string(), DishwasherValueSchema).optional()
|
|
76383
|
+
}), zod.z.void(), {
|
|
76249
76384
|
kind: "mutation",
|
|
76250
76385
|
auth: "protected"
|
|
76251
76386
|
}),
|
|
76252
|
-
pause: method(zod.z.object({ deviceId:
|
|
76387
|
+
pause: method(zod.z.object({ deviceId: DeviceIdSchema }), zod.z.void(), {
|
|
76253
76388
|
kind: "mutation",
|
|
76254
76389
|
auth: "protected"
|
|
76255
76390
|
}),
|
|
76256
|
-
|
|
76391
|
+
resume: method(zod.z.object({ deviceId: DeviceIdSchema }), zod.z.void(), {
|
|
76392
|
+
kind: "mutation",
|
|
76393
|
+
auth: "protected"
|
|
76394
|
+
}),
|
|
76395
|
+
stop: method(zod.z.object({ deviceId: DeviceIdSchema }), zod.z.void(), {
|
|
76257
76396
|
kind: "mutation",
|
|
76258
76397
|
auth: "protected"
|
|
76259
76398
|
}),
|
|
76399
|
+
/** Select (not start) a program; refused when the appliance does not offer it. */
|
|
76260
76400
|
setProgram: method(zod.z.object({
|
|
76261
|
-
deviceId:
|
|
76401
|
+
deviceId: DeviceIdSchema,
|
|
76262
76402
|
program: zod.z.string().min(1)
|
|
76263
76403
|
}), zod.z.void(), {
|
|
76264
76404
|
kind: "mutation",
|
|
76265
76405
|
auth: "protected"
|
|
76266
76406
|
}),
|
|
76267
76407
|
setPower: method(zod.z.object({
|
|
76268
|
-
deviceId:
|
|
76408
|
+
deviceId: DeviceIdSchema,
|
|
76269
76409
|
on: zod.z.boolean()
|
|
76270
76410
|
}), zod.z.void(), {
|
|
76271
76411
|
kind: "mutation",
|
|
76272
76412
|
auth: "protected"
|
|
76273
76413
|
}),
|
|
76274
76414
|
setHalfLoad: method(zod.z.object({
|
|
76275
|
-
deviceId:
|
|
76415
|
+
deviceId: DeviceIdSchema,
|
|
76276
76416
|
on: zod.z.boolean()
|
|
76277
76417
|
}), zod.z.void(), {
|
|
76278
76418
|
kind: "mutation",
|
|
76279
76419
|
auth: "protected"
|
|
76280
76420
|
}),
|
|
76281
76421
|
setHygienePlus: method(zod.z.object({
|
|
76282
|
-
deviceId:
|
|
76422
|
+
deviceId: DeviceIdSchema,
|
|
76423
|
+
on: zod.z.boolean()
|
|
76424
|
+
}), zod.z.void(), {
|
|
76425
|
+
kind: "mutation",
|
|
76426
|
+
auth: "protected"
|
|
76427
|
+
}),
|
|
76428
|
+
setExtraDry: method(zod.z.object({
|
|
76429
|
+
deviceId: DeviceIdSchema,
|
|
76283
76430
|
on: zod.z.boolean()
|
|
76284
76431
|
}), zod.z.void(), {
|
|
76285
76432
|
kind: "mutation",
|
|
76286
76433
|
auth: "protected"
|
|
76287
76434
|
}),
|
|
76435
|
+
setIntensiveZone: method(zod.z.object({
|
|
76436
|
+
deviceId: DeviceIdSchema,
|
|
76437
|
+
on: zod.z.boolean()
|
|
76438
|
+
}), zod.z.void(), {
|
|
76439
|
+
kind: "mutation",
|
|
76440
|
+
auth: "protected"
|
|
76441
|
+
}),
|
|
76442
|
+
setVarioSpeedPlus: method(zod.z.object({
|
|
76443
|
+
deviceId: DeviceIdSchema,
|
|
76444
|
+
on: zod.z.boolean()
|
|
76445
|
+
}), zod.z.void(), {
|
|
76446
|
+
kind: "mutation",
|
|
76447
|
+
auth: "protected"
|
|
76448
|
+
}),
|
|
76449
|
+
setChildLock: method(zod.z.object({
|
|
76450
|
+
deviceId: DeviceIdSchema,
|
|
76451
|
+
on: zod.z.boolean()
|
|
76452
|
+
}), zod.z.void(), {
|
|
76453
|
+
kind: "mutation",
|
|
76454
|
+
auth: "protected"
|
|
76455
|
+
}),
|
|
76456
|
+
/**
|
|
76457
|
+
* Write any option or setting by feature key. Refused when the description does
|
|
76458
|
+
* not list it, it is not writable or not available now, or the value is outside
|
|
76459
|
+
* its declared range / members.
|
|
76460
|
+
*/
|
|
76288
76461
|
setOption: method(zod.z.object({
|
|
76289
|
-
deviceId:
|
|
76462
|
+
deviceId: DeviceIdSchema,
|
|
76290
76463
|
key: zod.z.string().min(1),
|
|
76291
|
-
value:
|
|
76292
|
-
zod.z.boolean(),
|
|
76293
|
-
zod.z.string(),
|
|
76294
|
-
zod.z.number()
|
|
76295
|
-
])
|
|
76464
|
+
value: DishwasherValueSchema
|
|
76296
76465
|
}), zod.z.void(), {
|
|
76297
76466
|
kind: "mutation",
|
|
76298
76467
|
auth: "protected"
|
|
76299
|
-
})
|
|
76468
|
+
}),
|
|
76469
|
+
/** What this appliance can do, from its own description — the UI is derived from it. */
|
|
76470
|
+
getOptions: method(zod.z.object({ deviceId: DeviceIdSchema }), DishwasherOptionsSchema, { auth: "protected" })
|
|
76300
76471
|
},
|
|
76301
76472
|
status: {
|
|
76302
76473
|
schema: DishwasherStatusSchema,
|
|
@@ -86887,6 +87058,7 @@ var require_dist_Ct88catN = __commonJS({
|
|
|
86887
87058
|
"fan",
|
|
86888
87059
|
"vacuum",
|
|
86889
87060
|
"lawn-mower",
|
|
87061
|
+
"dishwasher",
|
|
86890
87062
|
"light",
|
|
86891
87063
|
"switch",
|
|
86892
87064
|
"siren",
|
|
@@ -89625,6 +89797,12 @@ var require_dist_Ct88catN = __commonJS({
|
|
|
89625
89797
|
addonId: null,
|
|
89626
89798
|
access: "view"
|
|
89627
89799
|
},
|
|
89800
|
+
"dishwasher.getOptions": {
|
|
89801
|
+
capName: "dishwasher",
|
|
89802
|
+
capScope: "device",
|
|
89803
|
+
addonId: null,
|
|
89804
|
+
access: "view"
|
|
89805
|
+
},
|
|
89628
89806
|
"dishwasher.getStatus": {
|
|
89629
89807
|
capName: "dishwasher",
|
|
89630
89808
|
capScope: "device",
|
|
@@ -89637,6 +89815,24 @@ var require_dist_Ct88catN = __commonJS({
|
|
|
89637
89815
|
addonId: null,
|
|
89638
89816
|
access: "create"
|
|
89639
89817
|
},
|
|
89818
|
+
"dishwasher.resume": {
|
|
89819
|
+
capName: "dishwasher",
|
|
89820
|
+
capScope: "device",
|
|
89821
|
+
addonId: null,
|
|
89822
|
+
access: "create"
|
|
89823
|
+
},
|
|
89824
|
+
"dishwasher.setChildLock": {
|
|
89825
|
+
capName: "dishwasher",
|
|
89826
|
+
capScope: "device",
|
|
89827
|
+
addonId: null,
|
|
89828
|
+
access: "create"
|
|
89829
|
+
},
|
|
89830
|
+
"dishwasher.setExtraDry": {
|
|
89831
|
+
capName: "dishwasher",
|
|
89832
|
+
capScope: "device",
|
|
89833
|
+
addonId: null,
|
|
89834
|
+
access: "create"
|
|
89835
|
+
},
|
|
89640
89836
|
"dishwasher.setHalfLoad": {
|
|
89641
89837
|
capName: "dishwasher",
|
|
89642
89838
|
capScope: "device",
|
|
@@ -89649,6 +89845,12 @@ var require_dist_Ct88catN = __commonJS({
|
|
|
89649
89845
|
addonId: null,
|
|
89650
89846
|
access: "create"
|
|
89651
89847
|
},
|
|
89848
|
+
"dishwasher.setIntensiveZone": {
|
|
89849
|
+
capName: "dishwasher",
|
|
89850
|
+
capScope: "device",
|
|
89851
|
+
addonId: null,
|
|
89852
|
+
access: "create"
|
|
89853
|
+
},
|
|
89652
89854
|
"dishwasher.setOption": {
|
|
89653
89855
|
capName: "dishwasher",
|
|
89654
89856
|
capScope: "device",
|
|
@@ -89667,6 +89869,12 @@ var require_dist_Ct88catN = __commonJS({
|
|
|
89667
89869
|
addonId: null,
|
|
89668
89870
|
access: "create"
|
|
89669
89871
|
},
|
|
89872
|
+
"dishwasher.setVarioSpeedPlus": {
|
|
89873
|
+
capName: "dishwasher",
|
|
89874
|
+
capScope: "device",
|
|
89875
|
+
addonId: null,
|
|
89876
|
+
access: "create"
|
|
89877
|
+
},
|
|
89670
89878
|
"dishwasher.start": {
|
|
89671
89879
|
capName: "dishwasher",
|
|
89672
89880
|
capScope: "device",
|
|
@@ -94113,6 +94321,12 @@ var require_dist_Ct88catN = __commonJS({
|
|
|
94113
94321
|
addonId: null,
|
|
94114
94322
|
access: "view"
|
|
94115
94323
|
},
|
|
94324
|
+
"storageMigration.moverClearance": {
|
|
94325
|
+
capName: "storage-migration",
|
|
94326
|
+
capScope: "system",
|
|
94327
|
+
addonId: null,
|
|
94328
|
+
access: "view"
|
|
94329
|
+
},
|
|
94116
94330
|
"storageMigration.movers": {
|
|
94117
94331
|
capName: "storage-migration",
|
|
94118
94332
|
capScope: "system",
|
|
@@ -96563,6 +96777,11 @@ var require_dist_Ct88catN = __commonJS({
|
|
|
96563
96777
|
form: "single",
|
|
96564
96778
|
optional: false
|
|
96565
96779
|
}],
|
|
96780
|
+
"dishwasher.getOptions": [{
|
|
96781
|
+
name: "deviceId",
|
|
96782
|
+
form: "single",
|
|
96783
|
+
optional: false
|
|
96784
|
+
}],
|
|
96566
96785
|
"dishwasher.getStatus": [{
|
|
96567
96786
|
name: "deviceId",
|
|
96568
96787
|
form: "single",
|
|
@@ -96573,6 +96792,21 @@ var require_dist_Ct88catN = __commonJS({
|
|
|
96573
96792
|
form: "single",
|
|
96574
96793
|
optional: false
|
|
96575
96794
|
}],
|
|
96795
|
+
"dishwasher.resume": [{
|
|
96796
|
+
name: "deviceId",
|
|
96797
|
+
form: "single",
|
|
96798
|
+
optional: false
|
|
96799
|
+
}],
|
|
96800
|
+
"dishwasher.setChildLock": [{
|
|
96801
|
+
name: "deviceId",
|
|
96802
|
+
form: "single",
|
|
96803
|
+
optional: false
|
|
96804
|
+
}],
|
|
96805
|
+
"dishwasher.setExtraDry": [{
|
|
96806
|
+
name: "deviceId",
|
|
96807
|
+
form: "single",
|
|
96808
|
+
optional: false
|
|
96809
|
+
}],
|
|
96576
96810
|
"dishwasher.setHalfLoad": [{
|
|
96577
96811
|
name: "deviceId",
|
|
96578
96812
|
form: "single",
|
|
@@ -96583,6 +96817,11 @@ var require_dist_Ct88catN = __commonJS({
|
|
|
96583
96817
|
form: "single",
|
|
96584
96818
|
optional: false
|
|
96585
96819
|
}],
|
|
96820
|
+
"dishwasher.setIntensiveZone": [{
|
|
96821
|
+
name: "deviceId",
|
|
96822
|
+
form: "single",
|
|
96823
|
+
optional: false
|
|
96824
|
+
}],
|
|
96586
96825
|
"dishwasher.setOption": [{
|
|
96587
96826
|
name: "deviceId",
|
|
96588
96827
|
form: "single",
|
|
@@ -96598,6 +96837,11 @@ var require_dist_Ct88catN = __commonJS({
|
|
|
96598
96837
|
form: "single",
|
|
96599
96838
|
optional: false
|
|
96600
96839
|
}],
|
|
96840
|
+
"dishwasher.setVarioSpeedPlus": [{
|
|
96841
|
+
name: "deviceId",
|
|
96842
|
+
form: "single",
|
|
96843
|
+
optional: false
|
|
96844
|
+
}],
|
|
96601
96845
|
"dishwasher.start": [{
|
|
96602
96846
|
name: "deviceId",
|
|
96603
96847
|
form: "single",
|
|
@@ -99126,6 +99370,9 @@ var require_dist_Ct88catN = __commonJS({
|
|
|
99126
99370
|
"wrapper-update-available": "system",
|
|
99127
99371
|
"backup-completed": "system",
|
|
99128
99372
|
"export-completed": "system",
|
|
99373
|
+
"alert-critical": "system",
|
|
99374
|
+
"alert-error": "system",
|
|
99375
|
+
"alert-critical-resolved": "system",
|
|
99129
99376
|
"storage-location-low": "system",
|
|
99130
99377
|
"storage-location-critical": "system",
|
|
99131
99378
|
"storage-location-ok": "system",
|
|
@@ -99250,6 +99497,16 @@ var require_dist_Ct88catN = __commonJS({
|
|
|
99250
99497
|
"storage-location-ok"
|
|
99251
99498
|
]
|
|
99252
99499
|
},
|
|
99500
|
+
{
|
|
99501
|
+
id: "alerts",
|
|
99502
|
+
family: "system",
|
|
99503
|
+
label: "Alerts",
|
|
99504
|
+
kinds: [
|
|
99505
|
+
"alert-critical",
|
|
99506
|
+
"alert-error",
|
|
99507
|
+
"alert-critical-resolved"
|
|
99508
|
+
]
|
|
99509
|
+
},
|
|
99253
99510
|
{
|
|
99254
99511
|
id: "alarm",
|
|
99255
99512
|
family: "alarm",
|
|
@@ -99267,6 +99524,60 @@ var require_dist_Ct88catN = __commonJS({
|
|
|
99267
99524
|
return [[descriptor.kind, field]];
|
|
99268
99525
|
})));
|
|
99269
99526
|
Object.freeze(Object.keys(NC_SENSOR_RAISED_FIELD_BY_KIND));
|
|
99527
|
+
zod.z.object({
|
|
99528
|
+
phase: zod.z.enum(["raised", "resolved"]),
|
|
99529
|
+
episodeId: zod.z.string().min(1),
|
|
99530
|
+
alertId: zod.z.string().min(1),
|
|
99531
|
+
severity: AlertSeveritySchema,
|
|
99532
|
+
category: zod.z.string(),
|
|
99533
|
+
title: zod.z.string(),
|
|
99534
|
+
message: zod.z.string(),
|
|
99535
|
+
sourceType: zod.z.string().optional(),
|
|
99536
|
+
sourceId: zod.z.string().optional(),
|
|
99537
|
+
nodeId: zod.z.string().optional(),
|
|
99538
|
+
/** The alert's own action link (where the operator acts on it), when it has one. */
|
|
99539
|
+
actionUrl: zod.z.string().optional(),
|
|
99540
|
+
at: zod.z.number()
|
|
99541
|
+
});
|
|
99542
|
+
function isAlertEpisodeOpen(status) {
|
|
99543
|
+
return status !== "completed" && status !== "dismissed";
|
|
99544
|
+
}
|
|
99545
|
+
function isAlertEpisodeSeverity(severity) {
|
|
99546
|
+
return severity === "critical" || severity === "error";
|
|
99547
|
+
}
|
|
99548
|
+
function alertEpisodeId(alert) {
|
|
99549
|
+
const minted = alert.metadata?.["episodeId"];
|
|
99550
|
+
return typeof minted === "string" && minted.length > 0 ? minted : `${alert.id}@${String(alert.createdAt)}`;
|
|
99551
|
+
}
|
|
99552
|
+
function alertNodeId(alert) {
|
|
99553
|
+
const direct = alert.metadata?.["nodeId"];
|
|
99554
|
+
if (typeof direct === "string") return direct;
|
|
99555
|
+
const runner = alert.metadata?.["runner"];
|
|
99556
|
+
if (typeof runner === "object" && runner !== null && "nodeId" in runner) {
|
|
99557
|
+
const id = runner.nodeId;
|
|
99558
|
+
if (typeof id === "string") return id;
|
|
99559
|
+
}
|
|
99560
|
+
return alert.source?.type === "node" ? alert.source.id : void 0;
|
|
99561
|
+
}
|
|
99562
|
+
function alertEpisodePayload(alert, phase, at) {
|
|
99563
|
+
const nodeId = alertNodeId(alert);
|
|
99564
|
+
return {
|
|
99565
|
+
phase,
|
|
99566
|
+
episodeId: alertEpisodeId(alert),
|
|
99567
|
+
alertId: alert.id,
|
|
99568
|
+
severity: alert.severity,
|
|
99569
|
+
category: alert.category,
|
|
99570
|
+
title: alert.title,
|
|
99571
|
+
message: alert.message,
|
|
99572
|
+
...alert.source !== void 0 ? {
|
|
99573
|
+
sourceType: alert.source.type,
|
|
99574
|
+
sourceId: alert.source.id
|
|
99575
|
+
} : {},
|
|
99576
|
+
...nodeId !== void 0 ? { nodeId } : {},
|
|
99577
|
+
...alert.action?.href !== void 0 ? { actionUrl: alert.action.href } : {},
|
|
99578
|
+
at
|
|
99579
|
+
};
|
|
99580
|
+
}
|
|
99270
99581
|
var RULE_BODY_ONLY = ["body"];
|
|
99271
99582
|
var RULE_TEXT = ["title", "body"];
|
|
99272
99583
|
var BATTERY = ["device-battery-low", "device-battery-normal"];
|
|
@@ -99276,6 +99587,11 @@ var require_dist_Ct88catN = __commonJS({
|
|
|
99276
99587
|
"device-tank-full",
|
|
99277
99588
|
"device-tank-normal"
|
|
99278
99589
|
];
|
|
99590
|
+
var ALERT_EPISODE = [
|
|
99591
|
+
"alert-critical",
|
|
99592
|
+
"alert-error",
|
|
99593
|
+
"alert-critical-resolved"
|
|
99594
|
+
];
|
|
99279
99595
|
var UPDATES = [
|
|
99280
99596
|
"addon-update-available",
|
|
99281
99597
|
"server-update-available",
|
|
@@ -99465,14 +99781,14 @@ var require_dist_Ct88catN = __commonJS({
|
|
|
99465
99781
|
([...RULE_TEXT], [...CONSUMABLE]),
|
|
99466
99782
|
([...RULE_TEXT], [...TANK]),
|
|
99467
99783
|
[...RULE_TEXT],
|
|
99468
|
-
([...RULE_TEXT], [...UPDATES]),
|
|
99469
|
-
([...RULE_TEXT], [...UPDATES]),
|
|
99470
|
-
[...RULE_TEXT],
|
|
99784
|
+
([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
|
|
99785
|
+
([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
|
|
99471
99786
|
[...RULE_TEXT],
|
|
99472
99787
|
[...RULE_TEXT],
|
|
99473
99788
|
[...RULE_TEXT],
|
|
99474
99789
|
[...RULE_TEXT],
|
|
99475
99790
|
[...RULE_TEXT],
|
|
99791
|
+
([...RULE_TEXT], [...ALERT_EPISODE]),
|
|
99476
99792
|
[...RULE_TEXT],
|
|
99477
99793
|
[...RULE_TEXT],
|
|
99478
99794
|
[...RULE_TEXT],
|
|
@@ -99490,7 +99806,11 @@ var require_dist_Ct88catN = __commonJS({
|
|
|
99490
99806
|
[...RULE_TEXT],
|
|
99491
99807
|
[...RULE_TEXT],
|
|
99492
99808
|
[...RULE_TEXT],
|
|
99493
|
-
[...RULE_TEXT],
|
|
99809
|
+
([...RULE_TEXT], [...ALERT_EPISODE]),
|
|
99810
|
+
([...RULE_TEXT], [...ALERT_EPISODE]),
|
|
99811
|
+
([...RULE_TEXT], [...ALERT_EPISODE]),
|
|
99812
|
+
([...RULE_TEXT], [...ALERT_EPISODE]),
|
|
99813
|
+
([...RULE_TEXT], [...ALERT_EPISODE]),
|
|
99494
99814
|
[...RULE_TEXT],
|
|
99495
99815
|
[...RULE_TEXT],
|
|
99496
99816
|
[...RULE_TEXT],
|
|
@@ -100678,6 +100998,18 @@ var require_dist_Ct88catN = __commonJS({
|
|
|
100678
100998
|
return addonWidgetsCapability;
|
|
100679
100999
|
}
|
|
100680
101000
|
});
|
|
101001
|
+
Object.defineProperty(exports, "alertEpisodeId", {
|
|
101002
|
+
enumerable: true,
|
|
101003
|
+
get: function() {
|
|
101004
|
+
return alertEpisodeId;
|
|
101005
|
+
}
|
|
101006
|
+
});
|
|
101007
|
+
Object.defineProperty(exports, "alertEpisodePayload", {
|
|
101008
|
+
enumerable: true,
|
|
101009
|
+
get: function() {
|
|
101010
|
+
return alertEpisodePayload;
|
|
101011
|
+
}
|
|
101012
|
+
});
|
|
100681
101013
|
Object.defineProperty(exports, "alertsCapability", {
|
|
100682
101014
|
enumerable: true,
|
|
100683
101015
|
get: function() {
|
|
@@ -101164,6 +101496,18 @@ var require_dist_Ct88catN = __commonJS({
|
|
|
101164
101496
|
return interpolate;
|
|
101165
101497
|
}
|
|
101166
101498
|
});
|
|
101499
|
+
Object.defineProperty(exports, "isAlertEpisodeOpen", {
|
|
101500
|
+
enumerable: true,
|
|
101501
|
+
get: function() {
|
|
101502
|
+
return isAlertEpisodeOpen;
|
|
101503
|
+
}
|
|
101504
|
+
});
|
|
101505
|
+
Object.defineProperty(exports, "isAlertEpisodeSeverity", {
|
|
101506
|
+
enumerable: true,
|
|
101507
|
+
get: function() {
|
|
101508
|
+
return isAlertEpisodeSeverity;
|
|
101509
|
+
}
|
|
101510
|
+
});
|
|
101167
101511
|
Object.defineProperty(exports, "isAppLinkBase", {
|
|
101168
101512
|
enumerable: true,
|
|
101169
101513
|
get: function() {
|
|
@@ -113278,11 +113622,11 @@ ${values.join("\n")}` : `${blockName} :`;
|
|
|
113278
113622
|
}
|
|
113279
113623
|
});
|
|
113280
113624
|
|
|
113281
|
-
// ../system/dist/device-ca-
|
|
113282
|
-
var
|
|
113283
|
-
"../system/dist/device-ca-
|
|
113625
|
+
// ../system/dist/device-ca-B3hUVfYk.js
|
|
113626
|
+
var require_device_ca_B3hUVfYk = __commonJS({
|
|
113627
|
+
"../system/dist/device-ca-B3hUVfYk.js"(exports) {
|
|
113284
113628
|
"use strict";
|
|
113285
|
-
var require_dist10 =
|
|
113629
|
+
var require_dist10 = require_dist_Bi4Ioxop();
|
|
113286
113630
|
var require_x509_es = require_x509_es_C4cOo48M();
|
|
113287
113631
|
var node_crypto = __require("crypto");
|
|
113288
113632
|
var SYSTEM_SECRET_OWNER = "system";
|
|
@@ -113697,11 +114041,11 @@ var require_device_ca_75rt3U_U = __commonJS({
|
|
|
113697
114041
|
}
|
|
113698
114042
|
});
|
|
113699
114043
|
|
|
113700
|
-
// ../system/dist/phase6-declare-gate-
|
|
113701
|
-
var
|
|
113702
|
-
"../system/dist/phase6-declare-gate-
|
|
114044
|
+
// ../system/dist/phase6-declare-gate-DwYAep7y.js
|
|
114045
|
+
var require_phase6_declare_gate_DwYAep7y = __commonJS({
|
|
114046
|
+
"../system/dist/phase6-declare-gate-DwYAep7y.js"(exports) {
|
|
113703
114047
|
"use strict";
|
|
113704
|
-
var require_dist10 =
|
|
114048
|
+
var require_dist10 = require_dist_Bi4Ioxop();
|
|
113705
114049
|
function legacyTableRowCountFromList(tables, collection) {
|
|
113706
114050
|
return tables.find((t) => t.name === collection)?.rows ?? 0;
|
|
113707
114051
|
}
|
|
@@ -113795,124 +114139,33 @@ var require_alerts_addon = __commonJS({
|
|
|
113795
114139
|
[Symbol.toStringTag]: { value: "Module" }
|
|
113796
114140
|
});
|
|
113797
114141
|
require_chunk_Cek0wNdY();
|
|
113798
|
-
var require_dist10 =
|
|
114142
|
+
var require_dist10 = require_dist_Bi4Ioxop();
|
|
113799
114143
|
var require_read_all_rows$1 = require_read_all_rows_CVoO1ONM();
|
|
113800
|
-
var require_phase6_declare_gate =
|
|
113801
|
-
|
|
113802
|
-
|
|
113803
|
-
|
|
113804
|
-
|
|
113805
|
-
|
|
113806
|
-
|
|
113807
|
-
return
|
|
113808
|
-
}
|
|
113809
|
-
function
|
|
113810
|
-
|
|
113811
|
-
const
|
|
113812
|
-
|
|
113813
|
-
|
|
113814
|
-
|
|
113815
|
-
|
|
113816
|
-
|
|
113817
|
-
|
|
113818
|
-
|
|
113819
|
-
|
|
113820
|
-
function composeDigest(items) {
|
|
113821
|
-
const first = items[0];
|
|
113822
|
-
if (items.length === 1 && first !== void 0) return {
|
|
113823
|
-
title: first.title,
|
|
113824
|
-
body: first.line
|
|
113825
|
-
};
|
|
113826
|
-
const shown = items.slice(0, MAX_DIGEST_LINES).map((i) => i.line);
|
|
113827
|
-
const more = items.length - shown.length;
|
|
113828
|
-
return {
|
|
113829
|
-
title: `${String(items.length)} addons need attention`,
|
|
113830
|
-
body: [...shown, ...more > 0 ? [`... and ${String(more)} more`] : []].join("\n")
|
|
113831
|
-
};
|
|
113832
|
-
}
|
|
113833
|
-
async function deliverDigest(input) {
|
|
113834
|
-
const out = /* @__PURE__ */ new Map();
|
|
113835
|
-
const work = input.items.filter((i) => !(i.previous !== null && i.previous.key === i.key && i.previous.state !== "pending"));
|
|
113836
|
-
if (work.length === 0) return out;
|
|
113837
|
-
const sameKey = (i) => i.previous !== null && i.previous.key === i.key ? i.previous : null;
|
|
113838
|
-
const attemptsOf = (i) => (sameKey(i)?.attempts ?? 0) + 1;
|
|
113839
|
-
const sentOf = (i) => sameKey(i)?.sentTo ?? [];
|
|
113840
|
-
if (!input.policy.enabled) {
|
|
113841
|
-
for (const i of work) out.set(i.alertId, {
|
|
113842
|
-
state: "disabled",
|
|
113843
|
-
key: i.key,
|
|
113844
|
-
attempts: attemptsOf(i)
|
|
113845
|
-
});
|
|
113846
|
-
return out;
|
|
113847
|
-
}
|
|
113848
|
-
const fail = (error) => {
|
|
113849
|
-
for (const i of work) out.set(i.alertId, {
|
|
113850
|
-
state: "pending",
|
|
113851
|
-
key: i.key,
|
|
113852
|
-
attempts: attemptsOf(i),
|
|
113853
|
-
lastError: error,
|
|
113854
|
-
...sentOf(i).length > 0 ? { sentTo: sentOf(i) } : {}
|
|
113855
|
-
});
|
|
113856
|
-
return out;
|
|
113857
|
-
};
|
|
113858
|
-
let targets;
|
|
113859
|
-
try {
|
|
113860
|
-
targets = selectPushTargets(await input.ports.listTargets(), input.policy);
|
|
113861
|
-
} catch (err) {
|
|
113862
|
-
return fail(`notifiers unavailable: ${err instanceof Error ? err.message : String(err)}`);
|
|
113863
|
-
}
|
|
113864
|
-
if (targets.length === 0) return fail("no eligible notifier target");
|
|
113865
|
-
const sent = new Map(work.map((i) => [i.alertId, [...sentOf(i)]]));
|
|
113866
|
-
const errors = new Map(work.map((i) => [i.alertId, []]));
|
|
113867
|
-
for (const target of targets) {
|
|
113868
|
-
const todo = work.filter((i) => !(sent.get(i.alertId) ?? []).includes(target.id));
|
|
113869
|
-
if (todo.length === 0) continue;
|
|
113870
|
-
let failure = null;
|
|
113871
|
-
try {
|
|
113872
|
-
const result = await input.ports.send(target, composeDigest(todo));
|
|
113873
|
-
if (!result.success) failure = `${target.id}: ${result.error ?? "send failed"}`;
|
|
113874
|
-
} catch (err) {
|
|
113875
|
-
failure = `${target.id}: ${err instanceof Error ? err.message : String(err)}`;
|
|
113876
|
-
}
|
|
113877
|
-
for (const i of todo) if (failure === null) sent.get(i.alertId)?.push(target.id);
|
|
113878
|
-
else errors.get(i.alertId)?.push(failure);
|
|
113879
|
-
}
|
|
113880
|
-
for (const i of work) {
|
|
113881
|
-
const sentTo = sent.get(i.alertId) ?? [];
|
|
113882
|
-
const complete = targets.every((t) => sentTo.includes(t.id));
|
|
113883
|
-
out.set(i.alertId, complete ? {
|
|
113884
|
-
state: "delivered",
|
|
113885
|
-
key: i.key,
|
|
113886
|
-
at: input.now,
|
|
113887
|
-
attempts: attemptsOf(i),
|
|
113888
|
-
sentTo
|
|
113889
|
-
} : {
|
|
113890
|
-
state: "pending",
|
|
113891
|
-
key: i.key,
|
|
113892
|
-
attempts: attemptsOf(i),
|
|
113893
|
-
lastError: (errors.get(i.alertId) ?? []).join("; "),
|
|
113894
|
-
...sentTo.length > 0 ? { sentTo } : {}
|
|
113895
|
-
});
|
|
113896
|
-
}
|
|
113897
|
-
return out;
|
|
114144
|
+
var require_phase6_declare_gate = require_phase6_declare_gate_DwYAep7y();
|
|
114145
|
+
function nextEpisodeId(input) {
|
|
114146
|
+
const { previous } = input;
|
|
114147
|
+
if (previous !== null && require_dist10.isAlertEpisodeOpen(previous.status)) {
|
|
114148
|
+
if (input.incomingKey === void 0 || input.incomingKey === previous.episodeKey) return previous.episodeId;
|
|
114149
|
+
}
|
|
114150
|
+
const minted = `${input.alertId}@${String(input.now)}`;
|
|
114151
|
+
return previous !== null && previous.episodeId === minted ? `${minted}+` : minted;
|
|
114152
|
+
}
|
|
114153
|
+
function episodeEdge(previous, next) {
|
|
114154
|
+
const nextOpen = require_dist10.isAlertEpisodeOpen(next.status);
|
|
114155
|
+
const continues = previous !== null && require_dist10.isAlertEpisodeOpen(previous.status) && previous.episodeId === next.episodeId;
|
|
114156
|
+
if (nextOpen) {
|
|
114157
|
+
if (!require_dist10.isAlertEpisodeSeverity(next.severity)) return null;
|
|
114158
|
+
if (!continues || previous === null) return "raised";
|
|
114159
|
+
if (!require_dist10.isAlertEpisodeSeverity(previous.severity)) return "raised";
|
|
114160
|
+
return previous.severity === "error" && next.severity === "critical" ? "raised" : null;
|
|
114161
|
+
}
|
|
114162
|
+
if (previous !== null && require_dist10.isAlertEpisodeOpen(previous.status) && require_dist10.isAlertEpisodeSeverity(previous.severity)) return "resolved";
|
|
114163
|
+
return null;
|
|
113898
114164
|
}
|
|
113899
114165
|
function episodeKeyFromMetadata(metadata) {
|
|
113900
114166
|
const key = metadata?.["episodeKey"];
|
|
113901
114167
|
return typeof key === "string" ? key : void 0;
|
|
113902
114168
|
}
|
|
113903
|
-
function shouldDropPriorPush(existingStatus) {
|
|
113904
|
-
return existingStatus === "completed";
|
|
113905
|
-
}
|
|
113906
|
-
function alertWithRetainedPush(toStore, existingPush, existingStatus) {
|
|
113907
|
-
if (existingPush === void 0 || shouldDropPriorPush(existingStatus)) return toStore;
|
|
113908
|
-
return {
|
|
113909
|
-
...toStore,
|
|
113910
|
-
metadata: {
|
|
113911
|
-
...toStore.metadata,
|
|
113912
|
-
push: existingPush
|
|
113913
|
-
}
|
|
113914
|
-
};
|
|
113915
|
-
}
|
|
113916
114169
|
function mergeEmitAlert(input) {
|
|
113917
114170
|
const incomingKey = episodeKeyFromMetadata(input.incoming.metadata);
|
|
113918
114171
|
const existingKey = input.existing?.episodeKey;
|
|
@@ -113920,26 +114173,11 @@ var require_alerts_addon = __commonJS({
|
|
|
113920
114173
|
const sameEpisode = incomingKey === void 0 || incomingKey === existingKey;
|
|
113921
114174
|
const priorCompleted = input.existing.status === "completed";
|
|
113922
114175
|
if (sameEpisode && !priorCompleted) return {
|
|
113923
|
-
|
|
113924
|
-
|
|
113925
|
-
read: true
|
|
113926
|
-
},
|
|
113927
|
-
queuePush: false
|
|
114176
|
+
...input.incoming,
|
|
114177
|
+
read: true
|
|
113928
114178
|
};
|
|
113929
114179
|
}
|
|
113930
|
-
|
|
113931
|
-
return {
|
|
113932
|
-
alert: input.incoming,
|
|
113933
|
-
queuePush
|
|
113934
|
-
};
|
|
113935
|
-
}
|
|
113936
|
-
function criticalPushPayload(alert) {
|
|
113937
|
-
const key = episodeKeyFromMetadata(alert.metadata) ?? alert.id;
|
|
113938
|
-
const pushLine = alert.metadata?.["pushLine"];
|
|
113939
|
-
return {
|
|
113940
|
-
key,
|
|
113941
|
-
line: typeof pushLine === "string" ? pushLine : alert.title
|
|
113942
|
-
};
|
|
114180
|
+
return input.incoming;
|
|
113943
114181
|
}
|
|
113944
114182
|
function deviceLabelFromEventData(data) {
|
|
113945
114183
|
const name = stringNonEmpty(data["name"]) ?? stringNonEmpty(data["deviceName"]);
|
|
@@ -114049,13 +114287,13 @@ var require_alerts_addon = __commonJS({
|
|
|
114049
114287
|
switch (record.state) {
|
|
114050
114288
|
case "refused":
|
|
114051
114289
|
return {
|
|
114052
|
-
severity: "
|
|
114290
|
+
severity: "critical",
|
|
114053
114291
|
title: "Addon refused to start",
|
|
114054
114292
|
message: `${where}: refused - ${record.reason ?? "no reason reported"}${record.remedy !== void 0 ? ` ${record.remedy}` : ""}`
|
|
114055
114293
|
};
|
|
114056
114294
|
case "failed":
|
|
114057
114295
|
return {
|
|
114058
|
-
severity: "
|
|
114296
|
+
severity: "critical",
|
|
114059
114297
|
title: "Addon crash loop",
|
|
114060
114298
|
message: `Runner "${where}" gave up${record.crashesInWindow !== void 0 ? ` after ${String(record.crashesInWindow)} crashes` : ""}${record.addonIds.length > 0 ? ` (addons: ${record.addonIds.join(", ")})` : ""} - ${String(record.count)} events`
|
|
114061
114299
|
};
|
|
@@ -114067,22 +114305,6 @@ var require_alerts_addon = __commonJS({
|
|
|
114067
114305
|
};
|
|
114068
114306
|
}
|
|
114069
114307
|
}
|
|
114070
|
-
function isTerminalRunnerState(state) {
|
|
114071
|
-
return state === "failed" || state === "refused";
|
|
114072
|
-
}
|
|
114073
|
-
function hash(text) {
|
|
114074
|
-
let h = 5381;
|
|
114075
|
-
for (let i = 0; i < text.length; i++) h = (h << 5) + h + text.charCodeAt(i) | 0;
|
|
114076
|
-
return (h >>> 0).toString(36);
|
|
114077
|
-
}
|
|
114078
|
-
function runnerPushKey(record) {
|
|
114079
|
-
const cause = record.state === "refused" ? hash(`${record.reason ?? ""}|${record.remedy ?? ""}`) : "breaker";
|
|
114080
|
-
return `runner:${record.state}:${String(record.since)}:${cause}`;
|
|
114081
|
-
}
|
|
114082
|
-
function runnerPushLine(record) {
|
|
114083
|
-
const where = record.nodeId === "hub" ? record.runnerId : `${record.runnerId} on ${record.nodeId}`;
|
|
114084
|
-
return record.state === "refused" ? `${where}: refused to start. ${record.remedy ?? "See the Addons page."}` : `${where}: stopped after repeated crashes. Restart it from the Addons page.`;
|
|
114085
|
-
}
|
|
114086
114308
|
var import_read_all_rows = require_read_all_rows$1.require_read_all_rows();
|
|
114087
114309
|
var ALERTS_COLLECTION = "alerts";
|
|
114088
114310
|
var AlertBodySchema = require_dist10.AlertSchema.omit({ id: true });
|
|
@@ -114374,7 +114596,6 @@ var require_alerts_addon = __commonJS({
|
|
|
114374
114596
|
}
|
|
114375
114597
|
};
|
|
114376
114598
|
var SILENT_TRACKED_CATEGORIES = [
|
|
114377
|
-
"addon.started",
|
|
114378
114599
|
"process.state-changed",
|
|
114379
114600
|
"addon.load-recovered",
|
|
114380
114601
|
"system.liveness-recovered",
|
|
@@ -114425,21 +114646,25 @@ var require_alerts_addon = __commonJS({
|
|
|
114425
114646
|
}
|
|
114426
114647
|
var DEFAULT_CONFIG = {
|
|
114427
114648
|
maxAlerts: 500,
|
|
114428
|
-
retentionDays: 30
|
|
114429
|
-
criticalPushEnabled: true,
|
|
114430
|
-
criticalPushTargetIds: []
|
|
114649
|
+
retentionDays: 30
|
|
114431
114650
|
};
|
|
114432
|
-
function normalizeCriticalPushTargetIds(raw) {
|
|
114433
|
-
if (Array.isArray(raw)) return raw.filter((id) => typeof id === "string" && id.trim().length > 0).map((id) => id.trim());
|
|
114434
|
-
if (typeof raw === "string" && raw.trim().length > 0) return raw.split(",").map((id) => id.trim()).filter((id) => id.length > 0);
|
|
114435
|
-
return [];
|
|
114436
|
-
}
|
|
114437
|
-
var PUSH_COALESCE_MS = 2e3;
|
|
114438
|
-
var PUSH_RECONCILE_ADDONS = /* @__PURE__ */ new Set(["notifiers", "notification-center"]);
|
|
114439
114651
|
var EVENT_SOURCE = {
|
|
114440
114652
|
type: "addon",
|
|
114441
114653
|
id: "alert-center"
|
|
114442
114654
|
};
|
|
114655
|
+
var ADDONS_PAGE_ACTION = {
|
|
114656
|
+
label: "Open Addons",
|
|
114657
|
+
href: "/system/addons"
|
|
114658
|
+
};
|
|
114659
|
+
function episodeViewOf(alert) {
|
|
114660
|
+
const key = episodeKeyFromMetadata(alert.metadata);
|
|
114661
|
+
return {
|
|
114662
|
+
status: alert.status,
|
|
114663
|
+
severity: alert.severity,
|
|
114664
|
+
episodeId: require_dist10.alertEpisodeId(alert),
|
|
114665
|
+
...key !== void 0 ? { episodeKey: key } : {}
|
|
114666
|
+
};
|
|
114667
|
+
}
|
|
114443
114668
|
function toPrunable(record) {
|
|
114444
114669
|
return {
|
|
114445
114670
|
id: record.id,
|
|
@@ -114450,11 +114675,8 @@ var require_alerts_addon = __commonJS({
|
|
|
114450
114675
|
var AlertCenterAddon = class extends require_dist10.BaseAddon {
|
|
114451
114676
|
alertStore = null;
|
|
114452
114677
|
unsubscribers = [];
|
|
114453
|
-
|
|
114454
|
-
pushCoalesceMs;
|
|
114455
|
-
constructor(options) {
|
|
114678
|
+
constructor() {
|
|
114456
114679
|
super({ ...DEFAULT_CONFIG });
|
|
114457
|
-
this.pushCoalesceMs = options?.pushCoalesceMs ?? PUSH_COALESCE_MS;
|
|
114458
114680
|
}
|
|
114459
114681
|
/**
|
|
114460
114682
|
* Per `(category, source.id)` counter used to rate-limit chatty
|
|
@@ -114485,9 +114707,7 @@ var require_alerts_addon = __commonJS({
|
|
|
114485
114707
|
unsubs.push(unsub);
|
|
114486
114708
|
}
|
|
114487
114709
|
this.unsubscribers = unsubs;
|
|
114488
|
-
this.reconcilePendingPushes();
|
|
114489
114710
|
this.dismissLegacyStreamCards(void 0);
|
|
114490
|
-
this.migrateCriticalPushTargetIds();
|
|
114491
114711
|
this.ctx.logger.info("Initialized", { meta: { trackedCategoriesCount: TRACKED_CATEGORIES.length } });
|
|
114492
114712
|
return [{
|
|
114493
114713
|
capability: require_dist10.alertsCapability,
|
|
@@ -114506,46 +114726,29 @@ var require_alerts_addon = __commonJS({
|
|
|
114506
114726
|
description: "Configure alert storage and retention.",
|
|
114507
114727
|
descriptionKey: "server:globalSettings.s_alerts.description",
|
|
114508
114728
|
columns: 1,
|
|
114509
|
-
fields: [
|
|
114510
|
-
|
|
114511
|
-
|
|
114512
|
-
|
|
114513
|
-
|
|
114514
|
-
|
|
114515
|
-
|
|
114516
|
-
|
|
114517
|
-
|
|
114518
|
-
|
|
114519
|
-
|
|
114520
|
-
|
|
114521
|
-
|
|
114522
|
-
|
|
114523
|
-
|
|
114524
|
-
|
|
114525
|
-
|
|
114526
|
-
|
|
114527
|
-
|
|
114528
|
-
|
|
114529
|
-
|
|
114530
|
-
|
|
114531
|
-
|
|
114532
|
-
default: 30
|
|
114533
|
-
}),
|
|
114534
|
-
this.field({
|
|
114535
|
-
type: "boolean",
|
|
114536
|
-
key: "criticalPushEnabled",
|
|
114537
|
-
label: "Push critical system alerts",
|
|
114538
|
-
description: "A runner that failed or refused to start, or a node whose runners are degraded, is pushed straight to the notifier targets \u2014 even when Notification Center is down. This path does not use notification rules.",
|
|
114539
|
-
default: true
|
|
114540
|
-
}),
|
|
114541
|
-
this.field({
|
|
114542
|
-
type: "notification-target-multiselect",
|
|
114543
|
-
key: "criticalPushTargetIds",
|
|
114544
|
-
label: "Critical push targets",
|
|
114545
|
-
description: "Notifier targets that receive critical system alerts. Empty = every enabled shared (not personal) target.",
|
|
114546
|
-
default: []
|
|
114547
|
-
})
|
|
114548
|
-
]
|
|
114729
|
+
fields: [this.field({
|
|
114730
|
+
type: "number",
|
|
114731
|
+
key: "maxAlerts",
|
|
114732
|
+
label: "Maximum stored alerts",
|
|
114733
|
+
labelKey: "server:globalSettings.s_alerts.maxAlerts.label",
|
|
114734
|
+
description: "Oldest read alerts are deleted when this limit is exceeded.",
|
|
114735
|
+
descriptionKey: "server:globalSettings.s_alerts.maxAlerts.description",
|
|
114736
|
+
min: 50,
|
|
114737
|
+
max: 5e3,
|
|
114738
|
+
step: 50,
|
|
114739
|
+
default: 500
|
|
114740
|
+
}), this.field({
|
|
114741
|
+
type: "number",
|
|
114742
|
+
key: "retentionDays",
|
|
114743
|
+
label: "Alert retention (days)",
|
|
114744
|
+
labelKey: "server:globalSettings.s_alerts.retentionDays.label",
|
|
114745
|
+
description: "Alerts older than this are automatically removed.",
|
|
114746
|
+
descriptionKey: "server:globalSettings.s_alerts.retentionDays.description",
|
|
114747
|
+
min: 1,
|
|
114748
|
+
max: 365,
|
|
114749
|
+
step: 1,
|
|
114750
|
+
default: 30
|
|
114751
|
+
})]
|
|
114549
114752
|
}] });
|
|
114550
114753
|
}
|
|
114551
114754
|
async listAlerts(filter) {
|
|
@@ -114584,7 +114787,17 @@ var require_alerts_addon = __commonJS({
|
|
|
114584
114787
|
updatedAt: Date.now()
|
|
114585
114788
|
});
|
|
114586
114789
|
}
|
|
114587
|
-
|
|
114790
|
+
/**
|
|
114791
|
+
* Events are handled one at a time: every handler is a read-modify-write of
|
|
114792
|
+
* an alert, and two concurrent events about one runner would both read "no
|
|
114793
|
+
* alert yet" and open two episodes for it.
|
|
114794
|
+
*/
|
|
114795
|
+
eventChain = Promise.resolve();
|
|
114796
|
+
handleEvent(category, event) {
|
|
114797
|
+
this.eventChain = this.eventChain.then(() => this.processEvent(category, event));
|
|
114798
|
+
return this.eventChain;
|
|
114799
|
+
}
|
|
114800
|
+
async processEvent(category, event) {
|
|
114588
114801
|
try {
|
|
114589
114802
|
if (category === "model.download.progress") {
|
|
114590
114803
|
await this.handleModelDownload(event);
|
|
@@ -114602,11 +114815,6 @@ var require_alerts_addon = __commonJS({
|
|
|
114602
114815
|
await this.handleRunnerCheck(event);
|
|
114603
114816
|
return;
|
|
114604
114817
|
}
|
|
114605
|
-
if (category === require_dist10.EventCategory.AddonStarted) {
|
|
114606
|
-
const addonId = event.data["addonId"];
|
|
114607
|
-
if (typeof addonId === "string" && PUSH_RECONCILE_ADDONS.has(addonId)) await this.reconcilePendingPushes();
|
|
114608
|
-
return;
|
|
114609
|
-
}
|
|
114610
114818
|
if (category === require_dist10.EventCategory.AddonLoadFailed) {
|
|
114611
114819
|
await this.handleAddonLoadFailed(event);
|
|
114612
114820
|
return;
|
|
@@ -114707,11 +114915,8 @@ var require_alerts_addon = __commonJS({
|
|
|
114707
114915
|
type: "runner",
|
|
114708
114916
|
id: record.runnerId
|
|
114709
114917
|
},
|
|
114710
|
-
|
|
114711
|
-
|
|
114712
|
-
pushLine: runnerPushLine(record),
|
|
114713
|
-
...existing?.push !== void 0 ? { push: existing.push } : {}
|
|
114714
|
-
}
|
|
114918
|
+
action: ADDONS_PAGE_ACTION,
|
|
114919
|
+
metadata: { runner: record }
|
|
114715
114920
|
};
|
|
114716
114921
|
await this.persistAlert(alert);
|
|
114717
114922
|
if (previous === null) this.emitAlertCreatedEvent(alert);
|
|
@@ -114720,17 +114925,11 @@ var require_alerts_addon = __commonJS({
|
|
|
114720
114925
|
title: alert.title
|
|
114721
114926
|
});
|
|
114722
114927
|
await this.enforceMaxAlerts();
|
|
114723
|
-
if (isTerminalRunnerState(record.state)) this.queuePush({
|
|
114724
|
-
alertId,
|
|
114725
|
-
key: runnerPushKey(record),
|
|
114726
|
-
title: rendered.title,
|
|
114727
|
-
line: runnerPushLine(record)
|
|
114728
|
-
});
|
|
114729
114928
|
}
|
|
114730
114929
|
/**
|
|
114731
114930
|
* A runner reached `running`: its episode is over. Close the runner alert so a
|
|
114732
|
-
* later failure opens a NEW episode
|
|
114733
|
-
*
|
|
114931
|
+
* later failure opens a NEW episode, instead of folding into a stale
|
|
114932
|
+
* `refused` record whose notification was already sent.
|
|
114734
114933
|
*/
|
|
114735
114934
|
async handleRunnerStateChanged(event) {
|
|
114736
114935
|
if (event.data["state"] !== "running") return;
|
|
@@ -114756,24 +114955,20 @@ var require_alerts_addon = __commonJS({
|
|
|
114756
114955
|
}) : [];
|
|
114757
114956
|
const failedIds = ids(event.data["failed"]);
|
|
114758
114957
|
const missingIds = ids(event.data["missing"]);
|
|
114759
|
-
const
|
|
114958
|
+
const parts = [
|
|
114760
114959
|
...failedIds.length > 0 ? [`failed: ${failedIds.join(", ")}`] : [],
|
|
114761
114960
|
...refusedIds.length > 0 ? [`refused: ${refusedIds.join(", ")}`] : [],
|
|
114762
114961
|
...missingIds.length > 0 ? [`missing: ${missingIds.join(", ")}`] : []
|
|
114763
|
-
]
|
|
114764
|
-
const pushKey = `check:${[
|
|
114765
|
-
...failedIds,
|
|
114766
|
-
...refusedIds,
|
|
114767
|
-
...missingIds
|
|
114768
|
-
].sort().join(",")}`;
|
|
114962
|
+
];
|
|
114769
114963
|
const now = Date.now();
|
|
114770
114964
|
const existing = await this.readAlertRaw(alertId);
|
|
114771
114965
|
const alert = {
|
|
114772
114966
|
id: alertId,
|
|
114773
114967
|
category: "system.runner-check",
|
|
114774
|
-
severity: "
|
|
114968
|
+
severity: "critical",
|
|
114775
114969
|
title: "Runners degraded",
|
|
114776
|
-
message: `${nodeId}: ${summary}`,
|
|
114970
|
+
message: `${nodeId}: ${summary}${parts.length > 0 ? ` (${parts.join("; ")})` : ""}`,
|
|
114971
|
+
action: ADDONS_PAGE_ACTION,
|
|
114777
114972
|
status: "active",
|
|
114778
114973
|
read: false,
|
|
114779
114974
|
createdAt: existing?.createdAt ?? now,
|
|
@@ -114786,19 +114981,11 @@ var require_alerts_addon = __commonJS({
|
|
|
114786
114981
|
nodeId,
|
|
114787
114982
|
failed: event.data["failed"],
|
|
114788
114983
|
refused: event.data["refused"],
|
|
114789
|
-
missing: event.data["missing"]
|
|
114790
|
-
pushLine,
|
|
114791
|
-
...existing?.push !== void 0 ? { push: existing.push } : {}
|
|
114984
|
+
missing: event.data["missing"]
|
|
114792
114985
|
}
|
|
114793
114986
|
};
|
|
114794
114987
|
await this.persistAlert(alert);
|
|
114795
114988
|
this.emitAlertCreatedEvent(alert);
|
|
114796
|
-
this.queuePush({
|
|
114797
|
-
alertId,
|
|
114798
|
-
key: pushKey,
|
|
114799
|
-
title: alert.title,
|
|
114800
|
-
line: pushLine
|
|
114801
|
-
});
|
|
114802
114989
|
}
|
|
114803
114990
|
async readAlertRaw(alertId) {
|
|
114804
114991
|
const store = this.alertStore;
|
|
@@ -114807,155 +114994,19 @@ var require_alerts_addon = __commonJS({
|
|
|
114807
114994
|
if (raw === null) return null;
|
|
114808
114995
|
const rec = Object.fromEntries(Object.entries(raw));
|
|
114809
114996
|
const meta = rec["metadata"];
|
|
114810
|
-
const push = typeof meta === "object" && meta !== null && !Array.isArray(meta) ? meta["push"] : void 0;
|
|
114811
114997
|
const metadata = typeof meta === "object" && meta !== null && !Array.isArray(meta) ? meta : void 0;
|
|
114998
|
+
const parsed = require_dist10.AlertSchema.safeParse({
|
|
114999
|
+
id: alertId,
|
|
115000
|
+
...rec
|
|
115001
|
+
});
|
|
114812
115002
|
return {
|
|
114813
115003
|
...typeof rec["createdAt"] === "number" ? { createdAt: rec["createdAt"] } : {},
|
|
114814
115004
|
...typeof rec["read"] === "boolean" ? { read: rec["read"] } : {},
|
|
114815
115005
|
...typeof rec["status"] === "string" ? { status: rec["status"] } : {},
|
|
114816
|
-
...
|
|
114817
|
-
...
|
|
115006
|
+
...episodeKeyFromMetadata(metadata) !== void 0 ? { episodeKey: episodeKeyFromMetadata(metadata) } : {},
|
|
115007
|
+
...parsed.success ? { episode: episodeViewOf(parsed.data) } : {}
|
|
114818
115008
|
};
|
|
114819
115009
|
}
|
|
114820
|
-
/** Pushes run one at a time so a burst can never send the same state twice. */
|
|
114821
|
-
pushChain = Promise.resolve();
|
|
114822
|
-
/** Findings waiting for the next digest, by alert id. */
|
|
114823
|
-
pushQueue = /* @__PURE__ */ new Map();
|
|
114824
|
-
pushTimer = null;
|
|
114825
|
-
pushPolicy() {
|
|
114826
|
-
return {
|
|
114827
|
-
enabled: this.config.criticalPushEnabled,
|
|
114828
|
-
targetIds: normalizeCriticalPushTargetIds(this.config.criticalPushTargetIds)
|
|
114829
|
-
};
|
|
114830
|
-
}
|
|
114831
|
-
/** Rewrite a legacy CSV `criticalPushTargetIds` string into `string[]`. */
|
|
114832
|
-
async migrateCriticalPushTargetIds() {
|
|
114833
|
-
const raw = this.config.criticalPushTargetIds;
|
|
114834
|
-
if (typeof raw !== "string") return;
|
|
114835
|
-
try {
|
|
114836
|
-
await this.updateGlobalSettings({ criticalPushTargetIds: normalizeCriticalPushTargetIds(raw) });
|
|
114837
|
-
} catch (err) {
|
|
114838
|
-
this.ctx.logger.warn("criticalPushTargetIds CSV migration failed", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
114839
|
-
}
|
|
114840
|
-
}
|
|
114841
|
-
pushPorts() {
|
|
114842
|
-
const api = this.ctx.api;
|
|
114843
|
-
return {
|
|
114844
|
-
listTargets: async () => {
|
|
114845
|
-
return (await api.notificationOutput.listTargets.query({})).map((t) => {
|
|
114846
|
-
const owner = t.config["ownerUserId"];
|
|
114847
|
-
return {
|
|
114848
|
-
id: t.id,
|
|
114849
|
-
addonId: t.addonId,
|
|
114850
|
-
enabled: t.enabled,
|
|
114851
|
-
...typeof owner === "string" && owner.length > 0 ? { ownerUserId: owner } : {}
|
|
114852
|
-
};
|
|
114853
|
-
});
|
|
114854
|
-
},
|
|
114855
|
-
send: async (target, message) => api.notificationOutput.send.mutate({
|
|
114856
|
-
addonId: target.addonId,
|
|
114857
|
-
targetId: target.id,
|
|
114858
|
-
notification: {
|
|
114859
|
-
title: message.title,
|
|
114860
|
-
body: message.body,
|
|
114861
|
-
format: "text",
|
|
114862
|
-
priority: 5
|
|
114863
|
-
}
|
|
114864
|
-
})
|
|
114865
|
-
};
|
|
114866
|
-
}
|
|
114867
|
-
/**
|
|
114868
|
-
* Queue a critical finding for the next digest. A burst (every runner of a boot)
|
|
114869
|
-
* arrives within the coalesce window and leaves as ONE message per target.
|
|
114870
|
-
*/
|
|
114871
|
-
queuePush(item) {
|
|
114872
|
-
this.pushQueue.set(item.alertId, item);
|
|
114873
|
-
if (this.pushTimer !== null) return;
|
|
114874
|
-
this.pushTimer = setTimeout(() => {
|
|
114875
|
-
this.pushTimer = null;
|
|
114876
|
-
this.flushPushes();
|
|
114877
|
-
}, this.pushCoalesceMs);
|
|
114878
|
-
this.pushTimer.unref?.();
|
|
114879
|
-
}
|
|
114880
|
-
/** Send the queued findings now (also the reconcile path). */
|
|
114881
|
-
flushPushes() {
|
|
114882
|
-
this.pushChain = this.pushChain.then(async () => {
|
|
114883
|
-
const queued = [...this.pushQueue.values()];
|
|
114884
|
-
this.pushQueue.clear();
|
|
114885
|
-
if (queued.length === 0) return;
|
|
114886
|
-
try {
|
|
114887
|
-
const items = [];
|
|
114888
|
-
for (const q of queued) {
|
|
114889
|
-
const existing = await this.readAlertRaw(q.alertId);
|
|
114890
|
-
items.push({
|
|
114891
|
-
...q,
|
|
114892
|
-
previous: existing?.push ?? null
|
|
114893
|
-
});
|
|
114894
|
-
}
|
|
114895
|
-
const states = await deliverDigest({
|
|
114896
|
-
items,
|
|
114897
|
-
policy: this.pushPolicy(),
|
|
114898
|
-
ports: this.pushPorts(),
|
|
114899
|
-
now: Date.now()
|
|
114900
|
-
});
|
|
114901
|
-
for (const [alertId, state] of states) {
|
|
114902
|
-
await this.storePushState(alertId, state);
|
|
114903
|
-
this.ctx.logger?.info("critical alert push", { meta: {
|
|
114904
|
-
alertId,
|
|
114905
|
-
state: state.state,
|
|
114906
|
-
attempts: state.attempts,
|
|
114907
|
-
error: state.lastError
|
|
114908
|
-
} });
|
|
114909
|
-
}
|
|
114910
|
-
} catch (err) {
|
|
114911
|
-
this.ctx.logger?.warn("critical alert push failed unexpectedly", { meta: { error: require_dist10.errMsg(err) } });
|
|
114912
|
-
}
|
|
114913
|
-
});
|
|
114914
|
-
return this.pushChain;
|
|
114915
|
-
}
|
|
114916
|
-
async storePushState(alertId, push) {
|
|
114917
|
-
const store = this.alertStore;
|
|
114918
|
-
if (store === null) return;
|
|
114919
|
-
const raw = await store.getData(alertId);
|
|
114920
|
-
if (raw === null) return;
|
|
114921
|
-
const meta = raw["metadata"];
|
|
114922
|
-
const metadata = typeof meta === "object" && meta !== null && !Array.isArray(meta) ? meta : {};
|
|
114923
|
-
await store.mergeUpdate(alertId, { metadata: {
|
|
114924
|
-
...metadata,
|
|
114925
|
-
push
|
|
114926
|
-
} });
|
|
114927
|
-
}
|
|
114928
|
-
/**
|
|
114929
|
-
* Retry every critical alert whose push is still pending - at boot and when
|
|
114930
|
-
* the notifiers or notification-center start. An alert whose state was already
|
|
114931
|
-
* delivered is skipped by its key, so reconciling never sends twice.
|
|
114932
|
-
*/
|
|
114933
|
-
async reconcilePendingPushes() {
|
|
114934
|
-
const store = this.alertStore;
|
|
114935
|
-
if (store === null) return;
|
|
114936
|
-
try {
|
|
114937
|
-
const rows = await store.listRecent(500);
|
|
114938
|
-
for (const row of rows) {
|
|
114939
|
-
const parsed = require_dist10.AlertSchema.safeParse({
|
|
114940
|
-
id: row.id,
|
|
114941
|
-
...row.data
|
|
114942
|
-
});
|
|
114943
|
-
if (!parsed.success || parsed.data.status !== "active") continue;
|
|
114944
|
-
if (!isCriticalPush(parsed.data)) continue;
|
|
114945
|
-
const push = parsed.data.metadata?.["push"];
|
|
114946
|
-
if (!isPushState(push) || push.state !== "pending") continue;
|
|
114947
|
-
this.pushQueue.set(parsed.data.id, {
|
|
114948
|
-
alertId: parsed.data.id,
|
|
114949
|
-
key: push.key,
|
|
114950
|
-
title: parsed.data.title,
|
|
114951
|
-
line: String(parsed.data.metadata?.["pushLine"] ?? parsed.data.title)
|
|
114952
|
-
});
|
|
114953
|
-
}
|
|
114954
|
-
await this.flushPushes();
|
|
114955
|
-
} catch (err) {
|
|
114956
|
-
this.ctx.logger?.warn("pending critical push reconcile failed", { meta: { error: require_dist10.errMsg(err) } });
|
|
114957
|
-
}
|
|
114958
|
-
}
|
|
114959
115010
|
async handleModelDownload(event) {
|
|
114960
115011
|
const data = event.data;
|
|
114961
115012
|
const modelId = data.modelId ?? "unknown";
|
|
@@ -115302,7 +115353,7 @@ var require_alerts_addon = __commonJS({
|
|
|
115302
115353
|
}
|
|
115303
115354
|
async emitAlert(alert) {
|
|
115304
115355
|
const existingRaw = await this.readAlertRaw(alert.id);
|
|
115305
|
-
const
|
|
115356
|
+
const toStore = mergeEmitAlert({
|
|
115306
115357
|
existing: existingRaw === null ? null : {
|
|
115307
115358
|
read: existingRaw.read,
|
|
115308
115359
|
episodeKey: existingRaw.episodeKey,
|
|
@@ -115310,20 +115361,10 @@ var require_alerts_addon = __commonJS({
|
|
|
115310
115361
|
},
|
|
115311
115362
|
incoming: alert
|
|
115312
115363
|
});
|
|
115313
|
-
const stored = alertWithRetainedPush(toStore, existingRaw?.push, existingRaw?.status);
|
|
115314
115364
|
const isNew = existingRaw === null;
|
|
115315
|
-
await this.persistAlert(
|
|
115365
|
+
const stored = await this.persistAlert(toStore);
|
|
115316
115366
|
if (isNew) this.emitAlertCreatedEvent(stored);
|
|
115317
115367
|
else this.emitAlertUpdatedEvent(alert.id, stored);
|
|
115318
|
-
if (queuePush) {
|
|
115319
|
-
const { key, line } = criticalPushPayload(stored);
|
|
115320
|
-
this.queuePush({
|
|
115321
|
-
alertId: stored.id,
|
|
115322
|
-
key,
|
|
115323
|
-
title: stored.title,
|
|
115324
|
-
line
|
|
115325
|
-
});
|
|
115326
|
-
}
|
|
115327
115368
|
await this.enforceMaxAlerts();
|
|
115328
115369
|
await this.enforceRetention();
|
|
115329
115370
|
}
|
|
@@ -115338,15 +115379,73 @@ var require_alerts_addon = __commonJS({
|
|
|
115338
115379
|
* Read-merge-write: SettingsBackend.update() replaces the entire `data` blob,
|
|
115339
115380
|
* so we must read the existing record, merge the patch, and write back.
|
|
115340
115381
|
*/
|
|
115341
|
-
|
|
115382
|
+
/** Alert writes (stamp + store + announce) from any caller, one at a time. */
|
|
115383
|
+
writeChain = Promise.resolve();
|
|
115384
|
+
serializedWrite(write) {
|
|
115385
|
+
const run = this.writeChain.then(write, write);
|
|
115386
|
+
this.writeChain = run.catch(() => void 0);
|
|
115387
|
+
return run;
|
|
115388
|
+
}
|
|
115389
|
+
mergeUpdate(id, patch) {
|
|
115390
|
+
return this.serializedWrite(() => this.mergeUpdateNow(id, patch));
|
|
115391
|
+
}
|
|
115392
|
+
async mergeUpdateNow(id, patch) {
|
|
115342
115393
|
const store = this.alertStore;
|
|
115343
115394
|
if (store === null) return;
|
|
115344
|
-
await
|
|
115395
|
+
const previous = (await this.readAlertRaw(id))?.episode ?? null;
|
|
115396
|
+
const metadata = patch["metadata"];
|
|
115397
|
+
const keepEpisode = previous !== null && typeof metadata === "object" && metadata !== null ? { metadata: {
|
|
115398
|
+
...metadata,
|
|
115399
|
+
episodeId: previous.episodeId
|
|
115400
|
+
} } : {};
|
|
115401
|
+
await store.mergeUpdate(id, {
|
|
115402
|
+
...patch,
|
|
115403
|
+
...keepEpisode
|
|
115404
|
+
});
|
|
115405
|
+
const after = await store.getData(id);
|
|
115406
|
+
const parsed = after === null ? null : require_dist10.AlertSchema.safeParse({
|
|
115407
|
+
id,
|
|
115408
|
+
...after
|
|
115409
|
+
});
|
|
115410
|
+
if (parsed?.success === true) this.announceEpisode(previous, parsed.data);
|
|
115411
|
+
}
|
|
115412
|
+
/**
|
|
115413
|
+
* Store an alert, stamping its episode identity. The stored alert is what a
|
|
115414
|
+
* caller must use afterwards, and the opening or closing of a critical/error
|
|
115415
|
+
* episode is announced here, in the one place every write passes through.
|
|
115416
|
+
*/
|
|
115417
|
+
persistAlert(alert) {
|
|
115418
|
+
return this.serializedWrite(() => this.persistAlertNow(alert));
|
|
115345
115419
|
}
|
|
115346
|
-
async
|
|
115420
|
+
async persistAlertNow(alert) {
|
|
115347
115421
|
const store = this.alertStore;
|
|
115348
|
-
if (store === null) return;
|
|
115349
|
-
await
|
|
115422
|
+
if (store === null) return alert;
|
|
115423
|
+
const previous = (await this.readAlertRaw(alert.id))?.episode ?? null;
|
|
115424
|
+
const episodeId = nextEpisodeId({
|
|
115425
|
+
alertId: alert.id,
|
|
115426
|
+
previous,
|
|
115427
|
+
incomingKey: episodeKeyFromMetadata(alert.metadata),
|
|
115428
|
+
now: Date.now()
|
|
115429
|
+
});
|
|
115430
|
+
const stamped = {
|
|
115431
|
+
...alert,
|
|
115432
|
+
metadata: {
|
|
115433
|
+
...alert.metadata,
|
|
115434
|
+
episodeId
|
|
115435
|
+
}
|
|
115436
|
+
};
|
|
115437
|
+
await store.persist(stamped);
|
|
115438
|
+
this.announceEpisode(previous, stamped);
|
|
115439
|
+
return stamped;
|
|
115440
|
+
}
|
|
115441
|
+
/**
|
|
115442
|
+
* Announce an episode edge on the bus. Telemetry, and it may be dropped
|
|
115443
|
+
* (D8): Notification Center reconciles from the alerts store (D11, D49).
|
|
115444
|
+
*/
|
|
115445
|
+
announceEpisode(previous, alert) {
|
|
115446
|
+
const edge = episodeEdge(previous, episodeViewOf(alert));
|
|
115447
|
+
if (edge === null) return;
|
|
115448
|
+
this.ctx.eventBus?.emit(require_dist10.createEvent(require_dist10.EventCategory.AlertEpisode, EVENT_SOURCE, require_dist10.alertEpisodePayload(alert, edge, Date.now())));
|
|
115350
115449
|
}
|
|
115351
115450
|
emitAlertCreatedEvent(alert) {
|
|
115352
115451
|
this.ctx.eventBus?.emit(require_dist10.createEvent("alert.created", EVENT_SOURCE, {
|
|
@@ -115447,7 +115546,7 @@ var require_calendars_addon = __commonJS({
|
|
|
115447
115546
|
[Symbol.toStringTag]: { value: "Module" }
|
|
115448
115547
|
});
|
|
115449
115548
|
require_chunk_Cek0wNdY();
|
|
115450
|
-
var require_dist10 =
|
|
115549
|
+
var require_dist10 = require_dist_Bi4Ioxop();
|
|
115451
115550
|
var require_settle_sources = require_settle_sources_Bhsy57y();
|
|
115452
115551
|
var zod = require_zod();
|
|
115453
115552
|
var CALENDAR_COLOR_PALETTE = [
|
|
@@ -115665,11 +115764,11 @@ var require_calendars = __commonJS({
|
|
|
115665
115764
|
}
|
|
115666
115765
|
});
|
|
115667
115766
|
|
|
115668
|
-
// ../system/dist/composition-sources-
|
|
115669
|
-
var
|
|
115670
|
-
"../system/dist/composition-sources-
|
|
115767
|
+
// ../system/dist/composition-sources-Cukc78eu.js
|
|
115768
|
+
var require_composition_sources_Cukc78eu = __commonJS({
|
|
115769
|
+
"../system/dist/composition-sources-Cukc78eu.js"(exports) {
|
|
115671
115770
|
"use strict";
|
|
115672
|
-
var require_dist10 =
|
|
115771
|
+
var require_dist10 = require_dist_Bi4Ioxop();
|
|
115673
115772
|
function normalizedNativeOwner(owner) {
|
|
115674
115773
|
const trimmed = owner?.trim();
|
|
115675
115774
|
return trimmed ? trimmed : null;
|
|
@@ -115784,8 +115883,8 @@ var require_composer_addon = __commonJS({
|
|
|
115784
115883
|
[Symbol.toStringTag]: { value: "Module" }
|
|
115785
115884
|
});
|
|
115786
115885
|
require_chunk_Cek0wNdY();
|
|
115787
|
-
var require_dist10 =
|
|
115788
|
-
var require_composition_sources =
|
|
115886
|
+
var require_dist10 = require_dist_Bi4Ioxop();
|
|
115887
|
+
var require_composition_sources = require_composition_sources_Cukc78eu();
|
|
115789
115888
|
var zod = require_zod();
|
|
115790
115889
|
function isRecord$2(value) {
|
|
115791
115890
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -119595,7 +119694,7 @@ var require_console_logging = __commonJS({
|
|
|
119595
119694
|
[Symbol.toStringTag]: { value: "Module" }
|
|
119596
119695
|
});
|
|
119597
119696
|
require_chunk_Cek0wNdY();
|
|
119598
|
-
var require_dist10 =
|
|
119697
|
+
var require_dist10 = require_dist_Bi4Ioxop();
|
|
119599
119698
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
119600
119699
|
var LEVEL_RANK = {
|
|
119601
119700
|
debug: 0,
|
|
@@ -123988,9 +124087,9 @@ var require_core_blocks_addon = __commonJS({
|
|
|
123988
124087
|
"use strict";
|
|
123989
124088
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
123990
124089
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
123991
|
-
var require_dist10 =
|
|
124090
|
+
var require_dist10 = require_dist_Bi4Ioxop();
|
|
123992
124091
|
var require_read_all_rows$1 = require_read_all_rows_CVoO1ONM();
|
|
123993
|
-
var require_composition_sources =
|
|
124092
|
+
var require_composition_sources = require_composition_sources_Cukc78eu();
|
|
123994
124093
|
var require_prefix_range = require_prefix_range_D_KueXbQ();
|
|
123995
124094
|
var require_prefix_walk = require_prefix_walk_Dv6MLZlM();
|
|
123996
124095
|
var zod = require_zod();
|
|
@@ -126190,9 +126289,9 @@ var require_core_blocks = __commonJS({
|
|
|
126190
126289
|
}
|
|
126191
126290
|
});
|
|
126192
126291
|
|
|
126193
|
-
// ../types/dist/event-category-
|
|
126194
|
-
var
|
|
126195
|
-
"../types/dist/event-category-
|
|
126292
|
+
// ../types/dist/event-category-eSqkye-K.js
|
|
126293
|
+
var require_event_category_eSqkye_K = __commonJS({
|
|
126294
|
+
"../types/dist/event-category-eSqkye-K.js"(exports) {
|
|
126196
126295
|
"use strict";
|
|
126197
126296
|
var EventCategory = /* @__PURE__ */ (function(EventCategory2) {
|
|
126198
126297
|
EventCategory2["SystemBoot"] = "system.boot";
|
|
@@ -126213,6 +126312,7 @@ var require_event_category_Hoe_mqbd = __commonJS({
|
|
|
126213
126312
|
EventCategory2["AddonRunnerRefused"] = "addon.runner-refused";
|
|
126214
126313
|
EventCategory2["ProcessStateChanged"] = "process.state-changed";
|
|
126215
126314
|
EventCategory2["SystemRunnerCheck"] = "system.runner-check";
|
|
126315
|
+
EventCategory2["AlertEpisode"] = "alert.episode";
|
|
126216
126316
|
EventCategory2["AddonError"] = "addon.error";
|
|
126217
126317
|
EventCategory2["AddonPageReady"] = "addon.page-ready";
|
|
126218
126318
|
EventCategory2["AddonWidgetReady"] = "addon.widget-ready";
|
|
@@ -126394,11 +126494,11 @@ var require_event_category_Hoe_mqbd = __commonJS({
|
|
|
126394
126494
|
}
|
|
126395
126495
|
});
|
|
126396
126496
|
|
|
126397
|
-
// ../types/dist/sleep
|
|
126398
|
-
var
|
|
126399
|
-
"../types/dist/sleep
|
|
126497
|
+
// ../types/dist/sleep-BE7_6UnC.js
|
|
126498
|
+
var require_sleep_BE7_6UnC = __commonJS({
|
|
126499
|
+
"../types/dist/sleep-BE7_6UnC.js"(exports) {
|
|
126400
126500
|
"use strict";
|
|
126401
|
-
var require_event_category =
|
|
126501
|
+
var require_event_category = require_event_category_eSqkye_K();
|
|
126402
126502
|
var zod = require_zod();
|
|
126403
126503
|
var AUDIO_CHUNK_FORMATS = [
|
|
126404
126504
|
"f32le",
|
|
@@ -131460,14 +131560,19 @@ var require_sleep_L6qY125 = __commonJS({
|
|
|
131460
131560
|
function addonSliceHandleApi(api) {
|
|
131461
131561
|
return api;
|
|
131462
131562
|
}
|
|
131563
|
+
function isCapRecord(value) {
|
|
131564
|
+
if (value === null || Array.isArray(value)) return false;
|
|
131565
|
+
const kind = typeof value;
|
|
131566
|
+
return kind === "object" || kind === "function";
|
|
131567
|
+
}
|
|
131463
131568
|
function isTrpcProcedureLeaf(value) {
|
|
131464
|
-
if (
|
|
131569
|
+
if (!isCapRecord(value)) return false;
|
|
131465
131570
|
const record = value;
|
|
131466
|
-
return
|
|
131571
|
+
return typeof record.query === "function" || typeof record.mutate === "function" || typeof record.subscribe === "function";
|
|
131467
131572
|
}
|
|
131468
131573
|
function readCapRecord(api, capProp) {
|
|
131469
131574
|
const cap = Reflect.get(api, capProp);
|
|
131470
|
-
if (
|
|
131575
|
+
if (!isCapRecord(cap)) return void 0;
|
|
131471
131576
|
return cap;
|
|
131472
131577
|
}
|
|
131473
131578
|
function readTrpcLeaf(api, capProp, method2) {
|
|
@@ -131647,12 +131752,18 @@ var require_sleep_L6qY125 = __commonJS({
|
|
|
131647
131752
|
const dishwasherInterface = {
|
|
131648
131753
|
start: (input) => dispatch("dishwasher", "dishwasher", "start", "mutation", input),
|
|
131649
131754
|
pause: (input) => dispatch("dishwasher", "dishwasher", "pause", "mutation", input),
|
|
131755
|
+
resume: (input) => dispatch("dishwasher", "dishwasher", "resume", "mutation", input),
|
|
131650
131756
|
stop: (input) => dispatch("dishwasher", "dishwasher", "stop", "mutation", input),
|
|
131651
131757
|
setProgram: (input) => dispatch("dishwasher", "dishwasher", "setProgram", "mutation", input),
|
|
131652
131758
|
setPower: (input) => dispatch("dishwasher", "dishwasher", "setPower", "mutation", input),
|
|
131653
131759
|
setHalfLoad: (input) => dispatch("dishwasher", "dishwasher", "setHalfLoad", "mutation", input),
|
|
131654
131760
|
setHygienePlus: (input) => dispatch("dishwasher", "dishwasher", "setHygienePlus", "mutation", input),
|
|
131761
|
+
setExtraDry: (input) => dispatch("dishwasher", "dishwasher", "setExtraDry", "mutation", input),
|
|
131762
|
+
setIntensiveZone: (input) => dispatch("dishwasher", "dishwasher", "setIntensiveZone", "mutation", input),
|
|
131763
|
+
setVarioSpeedPlus: (input) => dispatch("dishwasher", "dishwasher", "setVarioSpeedPlus", "mutation", input),
|
|
131764
|
+
setChildLock: (input) => dispatch("dishwasher", "dishwasher", "setChildLock", "mutation", input),
|
|
131655
131765
|
setOption: (input) => dispatch("dishwasher", "dishwasher", "setOption", "mutation", input),
|
|
131766
|
+
getOptions: (input) => dispatch("dishwasher", "dishwasher", "getOptions", "query", input),
|
|
131656
131767
|
getStatus: (input) => dispatch("dishwasher", "dishwasher", "getStatus", "query", input)
|
|
131657
131768
|
};
|
|
131658
131769
|
const doorbellInterface = { getStatus: (input) => dispatch("doorbell", "doorbell", "getStatus", "query", input) };
|
|
@@ -133950,8 +134061,8 @@ var require_addon = __commonJS({
|
|
|
133950
134061
|
"../types/dist/addon.js"(exports) {
|
|
133951
134062
|
"use strict";
|
|
133952
134063
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
133953
|
-
var require_sleep =
|
|
133954
|
-
var require_event_category =
|
|
134064
|
+
var require_sleep = require_sleep_BE7_6UnC();
|
|
134065
|
+
var require_event_category = require_event_category_eSqkye_K();
|
|
133955
134066
|
var require_err_msg = require_err_msg_BhVbr0NX();
|
|
133956
134067
|
var CAP_INPUT_DEFAULTS = Object.freeze({
|
|
133957
134068
|
"addons": { "getLogs": { "limit": 100 } },
|
|
@@ -134855,6 +134966,15 @@ var require_addon = __commonJS({
|
|
|
134855
134966
|
"valueType": "boolean"
|
|
134856
134967
|
}],
|
|
134857
134968
|
"dishwasher": [
|
|
134969
|
+
{
|
|
134970
|
+
"path": "availability",
|
|
134971
|
+
"valueType": "enum",
|
|
134972
|
+
"enumValues": [
|
|
134973
|
+
"available",
|
|
134974
|
+
"offline",
|
|
134975
|
+
"description-missing"
|
|
134976
|
+
]
|
|
134977
|
+
},
|
|
134858
134978
|
{
|
|
134859
134979
|
"path": "state",
|
|
134860
134980
|
"valueType": "enum",
|
|
@@ -134867,12 +134987,35 @@ var require_addon = __commonJS({
|
|
|
134867
134987
|
"unavailable"
|
|
134868
134988
|
]
|
|
134869
134989
|
},
|
|
134990
|
+
{
|
|
134991
|
+
"path": "operationState",
|
|
134992
|
+
"valueType": "enum",
|
|
134993
|
+
"enumValues": [
|
|
134994
|
+
"Inactive",
|
|
134995
|
+
"Ready",
|
|
134996
|
+
"DelayedStart",
|
|
134997
|
+
"Run",
|
|
134998
|
+
"Pause",
|
|
134999
|
+
"ActionRequired",
|
|
135000
|
+
"Finished",
|
|
135001
|
+
"Error",
|
|
135002
|
+
"Aborting"
|
|
135003
|
+
]
|
|
135004
|
+
},
|
|
134870
135005
|
{
|
|
134871
135006
|
"path": "program",
|
|
134872
135007
|
"valueType": "string"
|
|
134873
135008
|
},
|
|
134874
135009
|
{
|
|
134875
|
-
"path": "
|
|
135010
|
+
"path": "selectedProgram",
|
|
135011
|
+
"valueType": "string"
|
|
135012
|
+
},
|
|
135013
|
+
{
|
|
135014
|
+
"path": "remainingSeconds",
|
|
135015
|
+
"valueType": "number"
|
|
135016
|
+
},
|
|
135017
|
+
{
|
|
135018
|
+
"path": "delayedStartSeconds",
|
|
134876
135019
|
"valueType": "number"
|
|
134877
135020
|
},
|
|
134878
135021
|
{
|
|
@@ -134883,14 +135026,30 @@ var require_addon = __commonJS({
|
|
|
134883
135026
|
"path": "doorOpen",
|
|
134884
135027
|
"valueType": "boolean"
|
|
134885
135028
|
},
|
|
135029
|
+
{
|
|
135030
|
+
"path": "doorLocked",
|
|
135031
|
+
"valueType": "boolean"
|
|
135032
|
+
},
|
|
134886
135033
|
{
|
|
134887
135034
|
"path": "remoteStartAllowed",
|
|
134888
135035
|
"valueType": "boolean"
|
|
134889
135036
|
},
|
|
135037
|
+
{
|
|
135038
|
+
"path": "remoteControlActive",
|
|
135039
|
+
"valueType": "boolean"
|
|
135040
|
+
},
|
|
135041
|
+
{
|
|
135042
|
+
"path": "localControlActive",
|
|
135043
|
+
"valueType": "boolean"
|
|
135044
|
+
},
|
|
134890
135045
|
{
|
|
134891
135046
|
"path": "powerOn",
|
|
134892
135047
|
"valueType": "boolean"
|
|
134893
135048
|
},
|
|
135049
|
+
{
|
|
135050
|
+
"path": "powerState",
|
|
135051
|
+
"valueType": "string"
|
|
135052
|
+
},
|
|
134894
135053
|
{
|
|
134895
135054
|
"path": "saltLevel",
|
|
134896
135055
|
"valueType": "enum",
|
|
@@ -134917,6 +135076,22 @@ var require_addon = __commonJS({
|
|
|
134917
135076
|
"path": "hygienePlus",
|
|
134918
135077
|
"valueType": "boolean"
|
|
134919
135078
|
},
|
|
135079
|
+
{
|
|
135080
|
+
"path": "extraDry",
|
|
135081
|
+
"valueType": "boolean"
|
|
135082
|
+
},
|
|
135083
|
+
{
|
|
135084
|
+
"path": "intensiveZone",
|
|
135085
|
+
"valueType": "boolean"
|
|
135086
|
+
},
|
|
135087
|
+
{
|
|
135088
|
+
"path": "varioSpeedPlus",
|
|
135089
|
+
"valueType": "boolean"
|
|
135090
|
+
},
|
|
135091
|
+
{
|
|
135092
|
+
"path": "childLock",
|
|
135093
|
+
"valueType": "boolean"
|
|
135094
|
+
},
|
|
134920
135095
|
{
|
|
134921
135096
|
"path": "errorCode",
|
|
134922
135097
|
"valueType": "number"
|
|
@@ -136532,7 +136707,7 @@ var require_device_manager_addon = __commonJS({
|
|
|
136532
136707
|
[Symbol.toStringTag]: { value: "Module" }
|
|
136533
136708
|
});
|
|
136534
136709
|
require_chunk_Cek0wNdY();
|
|
136535
|
-
var require_dist10 =
|
|
136710
|
+
var require_dist10 = require_dist_Bi4Ioxop();
|
|
136536
136711
|
var require_read_all_rows$1 = require_read_all_rows_CVoO1ONM();
|
|
136537
136712
|
var require_prefix_range = require_prefix_range_D_KueXbQ();
|
|
136538
136713
|
var require_prefix_walk = require_prefix_walk_Dv6MLZlM();
|
|
@@ -145606,7 +145781,7 @@ var require_hub_forwarder = __commonJS({
|
|
|
145606
145781
|
[Symbol.toStringTag]: { value: "Module" }
|
|
145607
145782
|
});
|
|
145608
145783
|
require_chunk_Cek0wNdY();
|
|
145609
|
-
var require_dist10 =
|
|
145784
|
+
var require_dist10 = require_dist_Bi4Ioxop();
|
|
145610
145785
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
145611
145786
|
var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
|
|
145612
145787
|
var HubForwarderDestination = class {
|
|
@@ -145743,7 +145918,7 @@ var require_liveness_monitor_addon = __commonJS({
|
|
|
145743
145918
|
"use strict";
|
|
145744
145919
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
145745
145920
|
require_chunk_Cek0wNdY();
|
|
145746
|
-
var require_dist10 =
|
|
145921
|
+
var require_dist10 = require_dist_Bi4Ioxop();
|
|
145747
145922
|
var NO_DEVICES = "liveness:no-devices";
|
|
145748
145923
|
var ALL_OFFLINE = "liveness:all-devices-offline";
|
|
145749
145924
|
var NO_FOOTAGE_PREFIX = "liveness:no-footage:";
|
|
@@ -146106,12 +146281,12 @@ var require_local_auth_addon = __commonJS({
|
|
|
146106
146281
|
[Symbol.toStringTag]: { value: "Module" }
|
|
146107
146282
|
});
|
|
146108
146283
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
146109
|
-
var require_dist10 =
|
|
146284
|
+
var require_dist10 = require_dist_Bi4Ioxop();
|
|
146110
146285
|
var require_read_all_rows$1 = require_read_all_rows_CVoO1ONM();
|
|
146111
146286
|
var require_safe_buffer$1 = require_safe_buffer_D3aoa_7X();
|
|
146112
146287
|
var require_ms$1 = require_ms_LB3giGoU();
|
|
146113
|
-
var require_device_ca =
|
|
146114
|
-
var require_phase6_declare_gate =
|
|
146288
|
+
var require_device_ca = require_device_ca_B3hUVfYk();
|
|
146289
|
+
var require_phase6_declare_gate = require_phase6_declare_gate_DwYAep7y();
|
|
146115
146290
|
var zod = require_zod();
|
|
146116
146291
|
var node_crypto = __require("crypto");
|
|
146117
146292
|
node_crypto = require_chunk.__toESM(node_crypto);
|
|
@@ -156906,7 +157081,7 @@ var require_loki_logging = __commonJS({
|
|
|
156906
157081
|
[Symbol.toStringTag]: { value: "Module" }
|
|
156907
157082
|
});
|
|
156908
157083
|
require_chunk_Cek0wNdY();
|
|
156909
|
-
var require_dist10 =
|
|
157084
|
+
var require_dist10 = require_dist_Bi4Ioxop();
|
|
156910
157085
|
function sanitizeLabelName(raw) {
|
|
156911
157086
|
const replaced = raw.replaceAll(/[^a-zA-Z0-9_]/g, "_");
|
|
156912
157087
|
return /^[a-zA-Z_]/.test(replaced) ? replaced : `_${replaced}`;
|
|
@@ -157578,7 +157753,7 @@ var require_native_metrics_addon = __commonJS({
|
|
|
157578
157753
|
[Symbol.toStringTag]: { value: "Module" }
|
|
157579
157754
|
});
|
|
157580
157755
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
157581
|
-
var require_dist10 =
|
|
157756
|
+
var require_dist10 = require_dist_Bi4Ioxop();
|
|
157582
157757
|
var node_fs_promises = __require("fs/promises");
|
|
157583
157758
|
var node_util = __require("util");
|
|
157584
157759
|
var node_os = __require("os");
|
|
@@ -158365,6 +158540,11 @@ var require_native_metrics_addon = __commonJS({
|
|
|
158365
158540
|
}
|
|
158366
158541
|
};
|
|
158367
158542
|
}
|
|
158543
|
+
function refusalCounts(result) {
|
|
158544
|
+
const counts = {};
|
|
158545
|
+
for (const r of result.refused) counts[r.reason] = (counts[r.reason] ?? 0) + r.count;
|
|
158546
|
+
return counts;
|
|
158547
|
+
}
|
|
158368
158548
|
var NodeMetricsHistoryRecorder = class {
|
|
158369
158549
|
deps;
|
|
158370
158550
|
declared = false;
|
|
@@ -158438,7 +158618,15 @@ var require_native_metrics_addon = __commonJS({
|
|
|
158438
158618
|
});
|
|
158439
158619
|
if (points.length === 0) return;
|
|
158440
158620
|
try {
|
|
158441
|
-
await this.deps.deviceHistory.record({ points });
|
|
158621
|
+
const result = await this.deps.deviceHistory.record({ points });
|
|
158622
|
+
if (result.refused.length > 0) {
|
|
158623
|
+
if (result.refused.some((r) => r.reason === "undeclared")) this.declared = false;
|
|
158624
|
+
this.deps.logger.warn("node metrics history points refused", { meta: {
|
|
158625
|
+
nodeId,
|
|
158626
|
+
accepted: result.accepted,
|
|
158627
|
+
refused: refusalCounts(result)
|
|
158628
|
+
} });
|
|
158629
|
+
}
|
|
158442
158630
|
} catch (err) {
|
|
158443
158631
|
this.deps.logger.warn("node metrics history sample not stored", { meta: {
|
|
158444
158632
|
nodeId,
|
|
@@ -159959,7 +160147,7 @@ var require_device_history_addon = __commonJS({
|
|
|
159959
160147
|
[Symbol.toStringTag]: { value: "Module" }
|
|
159960
160148
|
});
|
|
159961
160149
|
require_chunk_Cek0wNdY();
|
|
159962
|
-
var require_dist10 =
|
|
160150
|
+
var require_dist10 = require_dist_Bi4Ioxop();
|
|
159963
160151
|
function subjectIdOf(subject) {
|
|
159964
160152
|
return subject.kind === "device" ? `d:${subject.deviceId}` : `n:${subject.nodeId}`;
|
|
159965
160153
|
}
|
|
@@ -162638,7 +162826,7 @@ var require_filesystem_storage_addon = __commonJS({
|
|
|
162638
162826
|
[Symbol.toStringTag]: { value: "Module" }
|
|
162639
162827
|
});
|
|
162640
162828
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
162641
|
-
var require_dist10 =
|
|
162829
|
+
var require_dist10 = require_dist_Bi4Ioxop();
|
|
162642
162830
|
var node_crypto = __require("crypto");
|
|
162643
162831
|
var node_fs_promises = __require("fs/promises");
|
|
162644
162832
|
var node_path = __require("path");
|
|
@@ -163748,12 +163936,12 @@ var require_lib = __commonJS({
|
|
|
163748
163936
|
}
|
|
163749
163937
|
});
|
|
163750
163938
|
|
|
163751
|
-
// ../system/dist/wal-maintenance-
|
|
163752
|
-
var
|
|
163753
|
-
"../system/dist/wal-maintenance-
|
|
163939
|
+
// ../system/dist/wal-maintenance-Bo_lo3Dh.js
|
|
163940
|
+
var require_wal_maintenance_Bo_lo3Dh = __commonJS({
|
|
163941
|
+
"../system/dist/wal-maintenance-Bo_lo3Dh.js"(exports) {
|
|
163754
163942
|
"use strict";
|
|
163755
163943
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
163756
|
-
var require_dist10 =
|
|
163944
|
+
var require_dist10 = require_dist_Bi4Ioxop();
|
|
163757
163945
|
var require_prefix_range = require_prefix_range_D_KueXbQ();
|
|
163758
163946
|
var node_crypto = __require("crypto");
|
|
163759
163947
|
var node_module = __require("module");
|
|
@@ -164038,7 +164226,9 @@ var require_wal_maintenance_mwCBe3Vr = __commonJS({
|
|
|
164038
164226
|
return {
|
|
164039
164227
|
hasTable: ({ name }) => backend.hasTable(name),
|
|
164040
164228
|
dropRetiredTable: ({ name }) => backend.dropRetiredTable(name),
|
|
164041
|
-
threadId: () => threadId
|
|
164229
|
+
threadId: () => threadId,
|
|
164230
|
+
listPhysicalTables: ({ ownerPrefix }) => backend.listTables(ownerPrefix),
|
|
164231
|
+
readLegacyCollection: (input) => backend.readLegacyCollection(input)
|
|
164042
164232
|
};
|
|
164043
164233
|
}
|
|
164044
164234
|
function callControl(target, op, input) {
|
|
@@ -164689,8 +164879,41 @@ CREATE TABLE IF NOT EXISTS _record_sequences (
|
|
|
164689
164879
|
if (this.schemaReady) {
|
|
164690
164880
|
ensureRecordsSchema(db);
|
|
164691
164881
|
for (const row of loadKinds(db)) this.kinds.set(keyOf(row.owner, row.kind), row);
|
|
164882
|
+
this.correctSequences();
|
|
164692
164883
|
}
|
|
164693
164884
|
}
|
|
164885
|
+
/**
|
|
164886
|
+
* Boot correction: every kind that ever allocated an id has its counter raised
|
|
164887
|
+
* above the highest numeric id it holds. Adopted legacy rows (or any caller
|
|
164888
|
+
* chosen numeric id) kept ids far above a counter that started at 1, and the
|
|
164889
|
+
* upsert would have overwritten another device's row on the first collision.
|
|
164890
|
+
* Runs on the engine's own connection, over the (kind_id, id) unique index.
|
|
164891
|
+
*/
|
|
164892
|
+
correctSequences() {
|
|
164893
|
+
const seq = this.db.prepare("SELECT kind_id FROM _record_sequences");
|
|
164894
|
+
for (const { kind_id: kindId } of seq.all()) {
|
|
164895
|
+
const top = this.db.prepare("SELECT MAX(CAST(id AS INTEGER)) AS m FROM records WHERE kind_id = ? AND id GLOB '[0-9]*'").get(kindId);
|
|
164896
|
+
if (top?.m === null || top === void 0) continue;
|
|
164897
|
+
if (this.db.prepare("UPDATE _record_sequences SET next = ? WHERE kind_id = ? AND next < ?").run(top.m + 1, kindId, top.m + 1).changes > 0) this.options.logger.warn("records: id sequence raised above the highest stored id", { meta: {
|
|
164898
|
+
kindId,
|
|
164899
|
+
next: top.m + 1
|
|
164900
|
+
} });
|
|
164901
|
+
}
|
|
164902
|
+
}
|
|
164903
|
+
/** Ids handed out by allocateId and not yet written: their first write is insert-only. */
|
|
164904
|
+
pendingAllocated = /* @__PURE__ */ new Set();
|
|
164905
|
+
static PENDING_ALLOCATED_MAX = 4096;
|
|
164906
|
+
/** Raise a kind's counter above the numeric ids of a caller-supplied batch (adoption). */
|
|
164907
|
+
raiseSequenceFor(k, records) {
|
|
164908
|
+
let top = -1;
|
|
164909
|
+
for (const r of records) if (/^\d{1,15}$/.test(r.id)) top = Math.max(top, Number(r.id));
|
|
164910
|
+
if (top < 0) return;
|
|
164911
|
+
if (k.declaration.adoptsFrom !== void 0) {
|
|
164912
|
+
this.db.prepare("INSERT INTO _record_sequences(kind_id, next) VALUES (?, ?) ON CONFLICT(kind_id) DO UPDATE SET next = MAX(next, excluded.next)").run(k.kindId, top + 1);
|
|
164913
|
+
return;
|
|
164914
|
+
}
|
|
164915
|
+
this.db.prepare("UPDATE _record_sequences SET next = ? WHERE kind_id = ? AND next < ?").run(top + 1, k.kindId, top + 1);
|
|
164916
|
+
}
|
|
164694
164917
|
schemaReady;
|
|
164695
164918
|
kindOf(owner, kind) {
|
|
164696
164919
|
const row = this.kinds.get(keyOf(owner, kind));
|
|
@@ -164829,6 +165052,17 @@ CREATE TABLE IF NOT EXISTS _record_sequences (
|
|
|
164829
165052
|
/** One row, inside the caller's transaction. */
|
|
164830
165053
|
writeRecord(owner, k, rec, ifRev, nowMs) {
|
|
164831
165054
|
const header = validateHeader(k.kind, k.declaration, rec, nowMs);
|
|
165055
|
+
const allocatedKey = `${k.kindId}:${rec.id}`;
|
|
165056
|
+
if (this.pendingAllocated.has(allocatedKey) && this.storedRow(k, rec.id) !== void 0) {
|
|
165057
|
+
this.options.logger.warn("records: an allocated id collided with a stored row; write refused", {
|
|
165058
|
+
tags: { deviceId: rec.deviceId },
|
|
165059
|
+
meta: {
|
|
165060
|
+
kind: k.kind,
|
|
165061
|
+
id: rec.id
|
|
165062
|
+
}
|
|
165063
|
+
});
|
|
165064
|
+
throw new require_dist10.RevConflictError(`${k.kind}/${rec.id}: an allocated id is insert-only and a row already holds it`);
|
|
165065
|
+
}
|
|
164832
165066
|
const stored = k.declaration.secretPaths.length > 0 || ifRev !== void 0 ? this.storedRow(k, rec.id) : void 0;
|
|
164833
165067
|
if (ifRev !== void 0) {
|
|
164834
165068
|
if (ifRev === 0 && stored !== void 0) throw new require_dist10.RevConflictError(`${k.kind}/${rec.id}: the row exists (ifRev 0 means "must not exist")`);
|
|
@@ -164842,6 +165076,7 @@ CREATE TABLE IF NOT EXISTS _record_sequences (
|
|
|
164842
165076
|
} }), nowMs);
|
|
164843
165077
|
const row = this.wrapWrite(k, () => this.db.prepare(this.upsertSql(k.kindId)).get(header.id, header.deviceId, header.at, header.expiresAt, nowMs, json));
|
|
164844
165078
|
if (row === void 0) throw new Error("records: the upsert returned no revision");
|
|
165079
|
+
this.pendingAllocated.delete(allocatedKey);
|
|
164845
165080
|
return {
|
|
164846
165081
|
rev: row.rev,
|
|
164847
165082
|
releasedRefs: checked.releasedRefs
|
|
@@ -164866,6 +165101,7 @@ CREATE TABLE IF NOT EXISTS _record_sequences (
|
|
|
164866
165101
|
const released = [];
|
|
164867
165102
|
this.timed("putMany", input.kind, () => this.db.transaction(() => {
|
|
164868
165103
|
for (const rec of input.records) released.push(...this.writeRecord(input.owner, k, rec, void 0, nowMs).releasedRefs);
|
|
165104
|
+
this.raiseSequenceFor(k, input.records);
|
|
164869
165105
|
})());
|
|
164870
165106
|
this.afterWrite(k, input.records.map((r) => r.deviceId));
|
|
164871
165107
|
return {
|
|
@@ -164988,6 +165224,11 @@ CREATE TABLE IF NOT EXISTS _record_sequences (
|
|
|
164988
165224
|
const k = this.kindOf(input.owner, input.kind);
|
|
164989
165225
|
const row = this.db.prepare("INSERT INTO _record_sequences(kind_id, next) VALUES (?, 2) ON CONFLICT(kind_id) DO UPDATE SET next = next + 1 RETURNING next - 1 AS id").get(k.kindId);
|
|
164990
165226
|
if (row === void 0) throw new Error("records: the sequence returned no id");
|
|
165227
|
+
this.pendingAllocated.add(`${k.kindId}:${row.id}`);
|
|
165228
|
+
if (this.pendingAllocated.size > RecordsEngine2.PENDING_ALLOCATED_MAX) {
|
|
165229
|
+
const oldest = this.pendingAllocated.values().next();
|
|
165230
|
+
if (oldest.done !== true) this.pendingAllocated.delete(oldest.value);
|
|
165231
|
+
}
|
|
164991
165232
|
return { id: row.id };
|
|
164992
165233
|
}
|
|
164993
165234
|
/**
|
|
@@ -165155,7 +165396,9 @@ CREATE TABLE IF NOT EXISTS _record_sequences (
|
|
|
165155
165396
|
var CONTROL_OPS = [
|
|
165156
165397
|
"hasTable",
|
|
165157
165398
|
"dropRetiredTable",
|
|
165158
|
-
"threadId"
|
|
165399
|
+
"threadId",
|
|
165400
|
+
"listPhysicalTables",
|
|
165401
|
+
"readLegacyCollection"
|
|
165159
165402
|
];
|
|
165160
165403
|
function isDataStoreOp(op) {
|
|
165161
165404
|
return DATA_STORE_OPS.some((known) => known === op);
|
|
@@ -166332,13 +166575,24 @@ CREATE TABLE IF NOT EXISTS _record_sequences (
|
|
|
166332
166575
|
*/
|
|
166333
166576
|
listTables(ownerPrefix) {
|
|
166334
166577
|
const db = this.getDb();
|
|
166335
|
-
const
|
|
166578
|
+
const entries = db.prepare("SELECT name, sql FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%' ORDER BY name").all();
|
|
166336
166579
|
const out = [];
|
|
166337
|
-
for (const name of
|
|
166580
|
+
for (const { name, sql } of entries) {
|
|
166581
|
+
if (sql !== null && sql.toUpperCase().startsWith("CREATE VIRTUAL")) continue;
|
|
166338
166582
|
const colon = name.indexOf(":");
|
|
166339
166583
|
const owner = colon > 0 ? name.slice(0, colon) : null;
|
|
166340
166584
|
if (ownerPrefix !== void 0 && owner !== ownerPrefix) continue;
|
|
166341
|
-
|
|
166585
|
+
let rows = 0;
|
|
166586
|
+
try {
|
|
166587
|
+
rows = db.prepare(`SELECT COUNT(*) AS c FROM "${name}"`).get()?.c ?? 0;
|
|
166588
|
+
} catch (err) {
|
|
166589
|
+
this.logger?.warn("listTables: skipped a table whose COUNT failed", { meta: {
|
|
166590
|
+
table: name,
|
|
166591
|
+
database: this.options.databaseId,
|
|
166592
|
+
error: err instanceof Error ? err.message : String(err)
|
|
166593
|
+
} });
|
|
166594
|
+
continue;
|
|
166595
|
+
}
|
|
166342
166596
|
let bytes = null;
|
|
166343
166597
|
try {
|
|
166344
166598
|
bytes = db.prepare("SELECT SUM(pgsize) AS b FROM dbstat WHERE name = ?").get(name)?.b ?? null;
|
|
@@ -167937,9 +168191,9 @@ var require_sqlite_settings_addon = __commonJS({
|
|
|
167937
168191
|
[Symbol.toStringTag]: { value: "Module" }
|
|
167938
168192
|
});
|
|
167939
168193
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
167940
|
-
var require_dist10 =
|
|
168194
|
+
var require_dist10 = require_dist_Bi4Ioxop();
|
|
167941
168195
|
var require_retired_settings_keys = require_retired_settings_keys_D_VwZiDt();
|
|
167942
|
-
var require_wal_maintenance =
|
|
168196
|
+
var require_wal_maintenance = require_wal_maintenance_Bo_lo3Dh();
|
|
167943
168197
|
var require_sqlite_snapshot_protocol = require_sqlite_snapshot_protocol_B9OndqZv();
|
|
167944
168198
|
var require_wal_checkpoint_policy = require_wal_checkpoint_policy_d2z2qPqx();
|
|
167945
168199
|
var node_fs_promises = __require("fs/promises");
|
|
@@ -168822,6 +169076,12 @@ var require_sqlite_settings_addon = __commonJS({
|
|
|
168822
169076
|
async hasTable(name) {
|
|
168823
169077
|
return require_wal_maintenance.callControl(require_wal_maintenance.controlTargetOf(this.backend, 0), "hasTable", { name });
|
|
168824
169078
|
}
|
|
169079
|
+
listPhysicalTables(ownerPrefix) {
|
|
169080
|
+
return Promise.resolve(require_wal_maintenance.callControl(require_wal_maintenance.controlTargetOf(this.backend, 0), "listPhysicalTables", { ownerPrefix }));
|
|
169081
|
+
}
|
|
169082
|
+
readLegacyCollection(input) {
|
|
169083
|
+
return Promise.resolve(require_wal_maintenance.callControl(require_wal_maintenance.controlTargetOf(this.backend, 0), "readLegacyCollection", input));
|
|
169084
|
+
}
|
|
168825
169085
|
async dropRetiredTable(name) {
|
|
168826
169086
|
return require_wal_maintenance.callControl(require_wal_maintenance.controlTargetOf(this.backend, 0), "dropRetiredTable", { name });
|
|
168827
169087
|
}
|
|
@@ -168875,6 +169135,12 @@ var require_sqlite_settings_addon = __commonJS({
|
|
|
168875
169135
|
hasTable(name) {
|
|
168876
169136
|
return this.client.control("hasTable", { name });
|
|
168877
169137
|
}
|
|
169138
|
+
listPhysicalTables(ownerPrefix) {
|
|
169139
|
+
return this.client.control("listPhysicalTables", { ownerPrefix });
|
|
169140
|
+
}
|
|
169141
|
+
readLegacyCollection(input) {
|
|
169142
|
+
return this.client.control("readLegacyCollection", input);
|
|
169143
|
+
}
|
|
168878
169144
|
dropRetiredTable(name) {
|
|
168879
169145
|
return this.client.control("dropRetiredTable", { name });
|
|
168880
169146
|
}
|
|
@@ -169449,11 +169715,13 @@ var require_sqlite_settings_addon = __commonJS({
|
|
|
169449
169715
|
logger;
|
|
169450
169716
|
installedOwners;
|
|
169451
169717
|
records;
|
|
169452
|
-
|
|
169718
|
+
peerFiles;
|
|
169719
|
+
constructor(backend, logger, installedOwners, records, peerFiles = async () => []) {
|
|
169453
169720
|
this.backend = backend;
|
|
169454
169721
|
this.logger = logger;
|
|
169455
169722
|
this.installedOwners = installedOwners;
|
|
169456
169723
|
this.records = records;
|
|
169724
|
+
this.peerFiles = peerFiles;
|
|
169457
169725
|
}
|
|
169458
169726
|
listKinds(input) {
|
|
169459
169727
|
return this.records.listKinds(input);
|
|
@@ -169467,8 +169735,25 @@ var require_sqlite_settings_addon = __commonJS({
|
|
|
169467
169735
|
isAdoptedLegacyTable(input) {
|
|
169468
169736
|
return this.records.isAdoptedLegacyTable(input.collection).then((adopted) => ({ adopted }));
|
|
169469
169737
|
}
|
|
169470
|
-
readLegacyCollection(input) {
|
|
169471
|
-
|
|
169738
|
+
async readLegacyCollection(input) {
|
|
169739
|
+
if (this.backend.hasTable(input.collection)) {
|
|
169740
|
+
const page = this.backend.readLegacyCollection(input);
|
|
169741
|
+
return {
|
|
169742
|
+
rows: [...page.rows],
|
|
169743
|
+
nextCursor: page.nextCursor
|
|
169744
|
+
};
|
|
169745
|
+
}
|
|
169746
|
+
for (const file of await this.peerFiles()) if (await file.hasTable(input.collection)) {
|
|
169747
|
+
const page = await file.readLegacyCollection(input);
|
|
169748
|
+
return {
|
|
169749
|
+
rows: [...page.rows],
|
|
169750
|
+
nextCursor: page.nextCursor
|
|
169751
|
+
};
|
|
169752
|
+
}
|
|
169753
|
+
return {
|
|
169754
|
+
rows: [],
|
|
169755
|
+
nextCursor: null
|
|
169756
|
+
};
|
|
169472
169757
|
}
|
|
169473
169758
|
/** May this table be dropped AT ALL? Throws with the reason when not. */
|
|
169474
169759
|
async assertDroppable(collection) {
|
|
@@ -169484,12 +169769,14 @@ var require_sqlite_settings_addon = __commonJS({
|
|
|
169484
169769
|
if (installed.has(owner) && !await this.records.isAdoptedLegacyTable(collection)) throw new Error(`drop refused: "${collection}" belongs to the installed addon "${owner}"`);
|
|
169485
169770
|
}
|
|
169486
169771
|
async listTables(input) {
|
|
169487
|
-
const tables = this.backend.listTables(input.ownerPrefix);
|
|
169772
|
+
const tables = [...this.backend.listTables(input.ownerPrefix)];
|
|
169773
|
+
for (const file of await this.peerFiles()) tables.push(...await file.listPhysicalTables(input.ownerPrefix));
|
|
169774
|
+
tables.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
|
|
169488
169775
|
this.logger.info("storage-admin: listed tables", { meta: {
|
|
169489
169776
|
tables: tables.length,
|
|
169490
169777
|
ownerPrefix: input.ownerPrefix ?? null
|
|
169491
169778
|
} });
|
|
169492
|
-
return { tables
|
|
169779
|
+
return { tables };
|
|
169493
169780
|
}
|
|
169494
169781
|
async dropCollection(input) {
|
|
169495
169782
|
try {
|
|
@@ -169673,7 +169960,7 @@ var require_sqlite_settings_addon = __commonJS({
|
|
|
169673
169960
|
},
|
|
169674
169961
|
{
|
|
169675
169962
|
capability: require_dist10.storageAdminCapability,
|
|
169676
|
-
provider: new StorageAdminProvider(settings.backend, this.ctx.logger.child("StorageAdmin"), async () => new Set((await this.ctx.api.addons.list.query()).map((addon) => addon.manifest.id)), records)
|
|
169963
|
+
provider: new StorageAdminProvider(settings.backend, this.ctx.logger.child("StorageAdmin"), async () => new Set((await this.ctx.api.addons.list.query()).map((addon) => addon.manifest.id)), records, async () => router.openFiles().filter((file) => file.databaseId !== "settings"))
|
|
169677
169964
|
}
|
|
169678
169965
|
];
|
|
169679
169966
|
}
|
|
@@ -169763,7 +170050,7 @@ var require_sqlite_storage = __commonJS({
|
|
|
169763
170050
|
});
|
|
169764
170051
|
require_chunk_Cek0wNdY();
|
|
169765
170052
|
var require_builtins_sqlite_storage_filesystem_storage_addon = require_filesystem_storage_addon();
|
|
169766
|
-
var require_wal_maintenance =
|
|
170053
|
+
var require_wal_maintenance = require_wal_maintenance_Bo_lo3Dh();
|
|
169767
170054
|
var require_builtins_sqlite_storage_sqlite_settings_addon = require_sqlite_settings_addon();
|
|
169768
170055
|
var ConfigStore = class {
|
|
169769
170056
|
db;
|
|
@@ -169847,7 +170134,7 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
169847
170134
|
[Symbol.toStringTag]: { value: "Module" }
|
|
169848
170135
|
});
|
|
169849
170136
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
169850
|
-
var require_dist10 =
|
|
170137
|
+
var require_dist10 = require_dist_Bi4Ioxop();
|
|
169851
170138
|
var require_read_all_rows$1 = require_read_all_rows_CVoO1ONM();
|
|
169852
170139
|
var zod = require_zod();
|
|
169853
170140
|
var node_crypto = __require("crypto");
|
|
@@ -169871,6 +170158,7 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
169871
170158
|
mode: require_dist10.StorageLocationModeSchema.optional(),
|
|
169872
170159
|
isDefault: zod.z.boolean().optional()
|
|
169873
170160
|
});
|
|
170161
|
+
var StorageSeedMarkerBodySchema = zod.z.object({ seededAt: zod.z.number() });
|
|
169874
170162
|
var StorageDrainStateBodySchema = zod.z.object({
|
|
169875
170163
|
locationId: zod.z.string(),
|
|
169876
170164
|
startedAtMs: zod.z.number(),
|
|
@@ -169895,6 +170183,14 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
169895
170183
|
retention: { none: "operator delete or declaration prune only" },
|
|
169896
170184
|
adoptsFrom: STORAGE_LOCATIONS
|
|
169897
170185
|
},
|
|
170186
|
+
"seed-markers": {
|
|
170187
|
+
schema: StorageSeedMarkerBodySchema,
|
|
170188
|
+
class: "config",
|
|
170189
|
+
writeTrigger: "a declared location type was seeded (or found already present on an existing install); the id is the type",
|
|
170190
|
+
device: "none",
|
|
170191
|
+
at: "none",
|
|
170192
|
+
retention: { none: "one row per location type ever seeded \u2014 what makes an operator delete stick" }
|
|
170193
|
+
},
|
|
169898
170194
|
"drain-state": {
|
|
169899
170195
|
schema: StorageDrainStateBodySchema,
|
|
169900
170196
|
class: "config",
|
|
@@ -169974,9 +170270,27 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
169974
170270
|
store;
|
|
169975
170271
|
declared = false;
|
|
169976
170272
|
locationsKind;
|
|
169977
|
-
constructor(store, locationsKind = null) {
|
|
170273
|
+
constructor(store, locationsKind = null, seedMarkersKind = null) {
|
|
169978
170274
|
this.store = store;
|
|
169979
170275
|
this.locationsKind = locationsKind;
|
|
170276
|
+
this.seedMarkersKind = seedMarkersKind;
|
|
170277
|
+
}
|
|
170278
|
+
seedMarkersKind;
|
|
170279
|
+
static seedMarkersOf(records) {
|
|
170280
|
+
return records.kind(storageOrchestratorRecordKinds["seed-markers"]);
|
|
170281
|
+
}
|
|
170282
|
+
async loadSeededTypes() {
|
|
170283
|
+
const kind = this.seedMarkersKind;
|
|
170284
|
+
if (kind === null) return [];
|
|
170285
|
+
return (await (0, import_read_all_rows.readAllRows)(kind)).map((r) => r.id);
|
|
170286
|
+
}
|
|
170287
|
+
async markTypeSeeded(type) {
|
|
170288
|
+
const kind = this.seedMarkersKind;
|
|
170289
|
+
if (kind === null) return;
|
|
170290
|
+
await kind.put({
|
|
170291
|
+
id: type,
|
|
170292
|
+
data: { seededAt: Date.now() }
|
|
170293
|
+
});
|
|
169980
170294
|
}
|
|
169981
170295
|
static recordStoresOf(records) {
|
|
169982
170296
|
return records.kind(storageOrchestratorRecordKinds.locations);
|
|
@@ -170943,20 +171257,77 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
170943
171257
|
}
|
|
170944
171258
|
};
|
|
170945
171259
|
}
|
|
170946
|
-
|
|
171260
|
+
var STORAGE_CLASS_SUBTREES = {
|
|
171261
|
+
eventMedia: ["events"],
|
|
171262
|
+
recordingsLow: ["low"],
|
|
171263
|
+
recordings: ["high", "mid"]
|
|
171264
|
+
};
|
|
171265
|
+
function isDotEntry(name) {
|
|
171266
|
+
return name.startsWith(".");
|
|
171267
|
+
}
|
|
171268
|
+
async function dirHasAnyEntry(dir) {
|
|
171269
|
+
let handle;
|
|
171270
|
+
try {
|
|
171271
|
+
handle = await (0, node_fs_promises.opendir)(dir);
|
|
171272
|
+
} catch (err) {
|
|
171273
|
+
if (err.code === "ENOENT") return false;
|
|
171274
|
+
throw err;
|
|
171275
|
+
}
|
|
171276
|
+
try {
|
|
171277
|
+
return await handle.read() !== null;
|
|
171278
|
+
} finally {
|
|
171279
|
+
await handle.close();
|
|
171280
|
+
}
|
|
171281
|
+
}
|
|
171282
|
+
async function probeLocalDirectoryOccupancy(input) {
|
|
171283
|
+
let names;
|
|
171284
|
+
try {
|
|
171285
|
+
names = await (0, node_fs_promises.readdir)(input.basePath);
|
|
171286
|
+
} catch (err) {
|
|
171287
|
+
if (err.code === "ENOENT") return "empty";
|
|
171288
|
+
return "unknown";
|
|
171289
|
+
}
|
|
171290
|
+
const visible = names.filter((name) => !isDotEntry(name));
|
|
171291
|
+
const subtrees = STORAGE_CLASS_SUBTREES[input.type];
|
|
171292
|
+
if (subtrees === void 0) return visible.length > 0 ? "occupied" : "empty";
|
|
171293
|
+
try {
|
|
171294
|
+
for (const camera of visible) for (const subtree of subtrees) if (await dirHasAnyEntry(node_path.default.join(input.basePath, camera, subtree))) return "occupied";
|
|
171295
|
+
} catch {
|
|
171296
|
+
return "unknown";
|
|
171297
|
+
}
|
|
171298
|
+
return "empty";
|
|
171299
|
+
}
|
|
171300
|
+
var STORAGE_CLASS_ROOT_SUBTREES = { homekitClips: ["homekit-clips"] };
|
|
171301
|
+
function classifyPath(type, relativePath) {
|
|
171302
|
+
const rootSubtrees = STORAGE_CLASS_ROOT_SUBTREES[type];
|
|
171303
|
+
const cameraSubtrees = STORAGE_CLASS_SUBTREES[type];
|
|
171304
|
+
if (rootSubtrees === void 0 && cameraSubtrees === void 0) return "own";
|
|
171305
|
+
const segments = relativePath.split("/").filter((segment) => segment.length > 0);
|
|
171306
|
+
if (rootSubtrees !== void 0) {
|
|
171307
|
+
const top = segments[0];
|
|
171308
|
+
return top !== void 0 && rootSubtrees.includes(top) ? "own" : "foreign";
|
|
171309
|
+
}
|
|
171310
|
+
if (segments.length < 2) return "descend";
|
|
171311
|
+
const subtree = segments[1];
|
|
171312
|
+
return subtree !== void 0 && cameraSubtrees?.includes(subtree) === true ? "own" : "foreign";
|
|
171313
|
+
}
|
|
171314
|
+
async function collectFiles(io, scope, prefix) {
|
|
170947
171315
|
const entries = await io.list(prefix);
|
|
170948
171316
|
const files = [];
|
|
170949
171317
|
for (const entry of entries) {
|
|
171318
|
+
const verdict = scope(entry);
|
|
171319
|
+
if (verdict === "foreign") continue;
|
|
170950
171320
|
if ((await io.list(entry)).length > 0) {
|
|
170951
|
-
files.push(...await collectFiles(io, entry));
|
|
171321
|
+
files.push(...await collectFiles(io, scope, entry));
|
|
170952
171322
|
continue;
|
|
170953
171323
|
}
|
|
170954
|
-
files.push(entry);
|
|
171324
|
+
if (verdict === "own") files.push(entry);
|
|
170955
171325
|
}
|
|
170956
171326
|
return files;
|
|
170957
171327
|
}
|
|
170958
|
-
|
|
170959
|
-
|
|
171328
|
+
var WHOLE_ROOT = () => "own";
|
|
171329
|
+
async function moveLocationTree(io, scope = WHOLE_ROOT) {
|
|
171330
|
+
const candidates = await collectFiles(io, scope);
|
|
170960
171331
|
const copied = [];
|
|
170961
171332
|
let bytes = 0;
|
|
170962
171333
|
for (const relativePath of candidates) {
|
|
@@ -170978,6 +171349,118 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
170978
171349
|
bytes
|
|
170979
171350
|
};
|
|
170980
171351
|
}
|
|
171352
|
+
var RepointRefusedError = class extends Error {
|
|
171353
|
+
reason;
|
|
171354
|
+
name = "RepointRefusedError";
|
|
171355
|
+
constructor(reason, message) {
|
|
171356
|
+
super(message);
|
|
171357
|
+
this.reason = reason;
|
|
171358
|
+
}
|
|
171359
|
+
};
|
|
171360
|
+
function rootsOverlap(a, b) {
|
|
171361
|
+
if (a === b) return true;
|
|
171362
|
+
const within = (inner, outer) => inner.startsWith(outer.endsWith("/") ? outer : `${outer}/`);
|
|
171363
|
+
return within(a, b) || within(b, a);
|
|
171364
|
+
}
|
|
171365
|
+
function basePathOf$1(config) {
|
|
171366
|
+
const raw = config["basePath"];
|
|
171367
|
+
return typeof raw === "string" && raw.length > 0 ? raw : null;
|
|
171368
|
+
}
|
|
171369
|
+
var LocationRepointer = class {
|
|
171370
|
+
deps;
|
|
171371
|
+
claims = /* @__PURE__ */ new Set();
|
|
171372
|
+
constructor(deps) {
|
|
171373
|
+
this.deps = deps;
|
|
171374
|
+
}
|
|
171375
|
+
/**
|
|
171376
|
+
* Move `stored`'s own subtree to `next`'s root, then run `commit` (the row
|
|
171377
|
+
* save) while the claim is still held. Throws {@link RepointRefusedError}
|
|
171378
|
+
* with NOTHING copied or deleted when a mover is on the root.
|
|
171379
|
+
*/
|
|
171380
|
+
async run(stored, next, commit) {
|
|
171381
|
+
const claim = await this.claim(stored, next);
|
|
171382
|
+
try {
|
|
171383
|
+
await this.refuseWhileMovers(claim, stored);
|
|
171384
|
+
const moved = await moveLocationTree(await this.deps.ioFor(stored, next), (path) => classifyPath(stored.type, path));
|
|
171385
|
+
this.logMoved(stored, next, moved);
|
|
171386
|
+
return await commit();
|
|
171387
|
+
} finally {
|
|
171388
|
+
this.claims.delete(claim);
|
|
171389
|
+
}
|
|
171390
|
+
}
|
|
171391
|
+
/**
|
|
171392
|
+
* May a mover that touches `locationIds` run? Refuses while a repoint holds
|
|
171393
|
+
* an overlapping root. Called by the owning addon AFTER its job is
|
|
171394
|
+
* registered, so the repoint's mover listing and this check cannot both miss.
|
|
171395
|
+
*/
|
|
171396
|
+
async clearance(locationIds) {
|
|
171397
|
+
const keys = await this.keysOf(locationIds);
|
|
171398
|
+
for (const claim of this.claims) if (claim.keys.some((held) => keys.some((key) => rootsOverlap(held, key)))) return {
|
|
171399
|
+
clear: false,
|
|
171400
|
+
reason: "repoint-active",
|
|
171401
|
+
repointLocationId: claim.locationId
|
|
171402
|
+
};
|
|
171403
|
+
return { clear: true };
|
|
171404
|
+
}
|
|
171405
|
+
async claim(stored, next) {
|
|
171406
|
+
const paths = [basePathOf$1(stored.config), basePathOf$1(next.config)].filter((path) => path !== null);
|
|
171407
|
+
const keys = await Promise.all(paths.map((path) => this.deps.resolveKey(path)));
|
|
171408
|
+
for (const other of this.claims) if (other.keys.some((held) => keys.some((key) => rootsOverlap(held, key)))) this.refuse(stored, "repoint-active", `a repoint of "${other.locationId}" holds the same root`);
|
|
171409
|
+
const claim = {
|
|
171410
|
+
locationId: stored.id,
|
|
171411
|
+
keys
|
|
171412
|
+
};
|
|
171413
|
+
this.claims.add(claim);
|
|
171414
|
+
return claim;
|
|
171415
|
+
}
|
|
171416
|
+
async refuseWhileMovers(claim, stored) {
|
|
171417
|
+
let movers;
|
|
171418
|
+
try {
|
|
171419
|
+
movers = await this.deps.listMovers();
|
|
171420
|
+
} catch (err) {
|
|
171421
|
+
this.claims.delete(claim);
|
|
171422
|
+
this.refuse(stored, "movers-unreadable", `the active movers could not be listed (${err instanceof Error ? err.message : String(err)})`);
|
|
171423
|
+
}
|
|
171424
|
+
for (const mover of movers) {
|
|
171425
|
+
if (mover.job.state !== "queued" && mover.job.state !== "running") continue;
|
|
171426
|
+
const touched = await this.keysOf(this.locationsTouchedBy(mover));
|
|
171427
|
+
if (claim.keys.some((held) => touched.some((key) => rootsOverlap(held, key)))) {
|
|
171428
|
+
this.claims.delete(claim);
|
|
171429
|
+
this.refuse(stored, "mover-active", `${mover.lane} mover ${mover.job.jobId} (${mover.job.fromLocationId} -> ${mover.job.toLocationId}) touches the same physical root`, {
|
|
171430
|
+
jobId: mover.job.jobId,
|
|
171431
|
+
lane: mover.lane
|
|
171432
|
+
});
|
|
171433
|
+
}
|
|
171434
|
+
}
|
|
171435
|
+
}
|
|
171436
|
+
locationsTouchedBy(mover) {
|
|
171437
|
+
return [mover.job.fromLocationId, mover.job.toLocationId];
|
|
171438
|
+
}
|
|
171439
|
+
/** `*` is the media mover's "from wherever the rows are": every eventMedia location. */
|
|
171440
|
+
async keysOf(locationIds) {
|
|
171441
|
+
const paths = locationIds.flatMap((id) => id === "*" ? this.deps.locationIdsOfType("eventMedia") : [id]).map((id) => this.deps.locationBasePath(id)).filter((path) => path !== null);
|
|
171442
|
+
return Promise.all(paths.map((path) => this.deps.resolveKey(path)));
|
|
171443
|
+
}
|
|
171444
|
+
refuse(stored, reason, detail, meta = {}) {
|
|
171445
|
+
this.deps.logger.warn("storage-orchestrator: REFUSING to re-point a location \u2014 nothing was moved", { meta: {
|
|
171446
|
+
id: stored.id,
|
|
171447
|
+
type: stored.type,
|
|
171448
|
+
reason,
|
|
171449
|
+
detail,
|
|
171450
|
+
...meta
|
|
171451
|
+
} });
|
|
171452
|
+
throw new RepointRefusedError(reason, `re-point of "${stored.id}" refused (${reason}): ${detail}`);
|
|
171453
|
+
}
|
|
171454
|
+
logMoved(stored, next, moved) {
|
|
171455
|
+
this.deps.logger.info("storage-orchestrator: singleton location re-pointed \u2014 its data was carried over", { meta: {
|
|
171456
|
+
id: stored.id,
|
|
171457
|
+
type: stored.type,
|
|
171458
|
+
from: basePathOf$1(stored.config),
|
|
171459
|
+
to: basePathOf$1(next.config),
|
|
171460
|
+
...moved
|
|
171461
|
+
} });
|
|
171462
|
+
}
|
|
171463
|
+
};
|
|
170981
171464
|
function resolveRefusalFor(location, locality) {
|
|
170982
171465
|
if (locality !== false) return null;
|
|
170983
171466
|
return `storage.resolve is a request for a path this node can open with node:fs, and location "${location.id}" is served by the remote provider "${location.providerId}" (nodeLocal: false) \u2014 the path it would return exists on the remote host, not here. Read and write this location through the storage cap (read/write, or beginUpload/writeChunk/finalizeUpload) instead.`;
|
|
@@ -171287,46 +171770,6 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
171287
171770
|
args: envelope.args
|
|
171288
171771
|
}, { timeout: HUB_SETTINGS_FORWARD_TIMEOUT_MS }));
|
|
171289
171772
|
}
|
|
171290
|
-
var STORAGE_CLASS_SUBTREES = {
|
|
171291
|
-
eventMedia: ["events"],
|
|
171292
|
-
recordingsLow: ["low"],
|
|
171293
|
-
recordings: ["high", "mid"]
|
|
171294
|
-
};
|
|
171295
|
-
function isDotEntry(name) {
|
|
171296
|
-
return name.startsWith(".");
|
|
171297
|
-
}
|
|
171298
|
-
async function dirHasAnyEntry(dir) {
|
|
171299
|
-
let handle;
|
|
171300
|
-
try {
|
|
171301
|
-
handle = await (0, node_fs_promises.opendir)(dir);
|
|
171302
|
-
} catch (err) {
|
|
171303
|
-
if (err.code === "ENOENT") return false;
|
|
171304
|
-
throw err;
|
|
171305
|
-
}
|
|
171306
|
-
try {
|
|
171307
|
-
return await handle.read() !== null;
|
|
171308
|
-
} finally {
|
|
171309
|
-
await handle.close();
|
|
171310
|
-
}
|
|
171311
|
-
}
|
|
171312
|
-
async function probeLocalDirectoryOccupancy(input) {
|
|
171313
|
-
let names;
|
|
171314
|
-
try {
|
|
171315
|
-
names = await (0, node_fs_promises.readdir)(input.basePath);
|
|
171316
|
-
} catch (err) {
|
|
171317
|
-
if (err.code === "ENOENT") return "empty";
|
|
171318
|
-
return "unknown";
|
|
171319
|
-
}
|
|
171320
|
-
const visible = names.filter((name) => !isDotEntry(name));
|
|
171321
|
-
const subtrees = STORAGE_CLASS_SUBTREES[input.type];
|
|
171322
|
-
if (subtrees === void 0) return visible.length > 0 ? "occupied" : "empty";
|
|
171323
|
-
try {
|
|
171324
|
-
for (const camera of visible) for (const subtree of subtrees) if (await dirHasAnyEntry(node_path.default.join(input.basePath, camera, subtree))) return "occupied";
|
|
171325
|
-
} catch {
|
|
171326
|
-
return "unknown";
|
|
171327
|
-
}
|
|
171328
|
-
return "empty";
|
|
171329
|
-
}
|
|
171330
171773
|
var DEFAULT_STALE_AFTER_MS = 6e4;
|
|
171331
171774
|
var LocationOccupancySlice = class {
|
|
171332
171775
|
deps;
|
|
@@ -171827,6 +172270,44 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
171827
172270
|
getLocalNodeId() {
|
|
171828
172271
|
return this.localNode;
|
|
171829
172272
|
}
|
|
172273
|
+
/**
|
|
172274
|
+
* Whether a seed must wait for an ANSWERED read of the store (D49). True on a
|
|
172275
|
+
* node whose locations live in a store: seeding before that read lands writes
|
|
172276
|
+
* defaults the store's own rows (not yet adopted, or not yet read) then
|
|
172277
|
+
* contradict. False on a node that has no store by design — it seeds in memory
|
|
172278
|
+
* at every boot.
|
|
172279
|
+
*/
|
|
172280
|
+
storeRequiredForSeed = false;
|
|
172281
|
+
setStoreRequiredForSeed(required) {
|
|
172282
|
+
this.storeRequiredForSeed = required;
|
|
172283
|
+
}
|
|
172284
|
+
/**
|
|
172285
|
+
* The location types a default was ever seeded for — null when the store
|
|
172286
|
+
* cannot remember (then a type with no row is seeded, as before). What makes
|
|
172287
|
+
* an operator's delete of a seeded default STICK: zero rows today is not
|
|
172288
|
+
* "fresh install", it is only fresh when nothing was ever seeded.
|
|
172289
|
+
*/
|
|
172290
|
+
seededTypes = null;
|
|
172291
|
+
/** The store held locations but no seed memory: an install older than the memory. */
|
|
172292
|
+
installPredatesSeedMemory = false;
|
|
172293
|
+
async loadSeedMemory(store, rowCount) {
|
|
172294
|
+
if (!store.loadSeededTypes) return;
|
|
172295
|
+
const types = await store.loadSeededTypes();
|
|
172296
|
+
this.seededTypes = new Set(types);
|
|
172297
|
+
this.installPredatesSeedMemory = types.length === 0 && rowCount > 0;
|
|
172298
|
+
}
|
|
172299
|
+
rememberSeeded(type) {
|
|
172300
|
+
const seeded = this.seededTypes;
|
|
172301
|
+
const store = this.locationStore;
|
|
172302
|
+
if (seeded === null || seeded.has(type) || !store?.markTypeSeeded) return;
|
|
172303
|
+
seeded.add(type);
|
|
172304
|
+
store.markTypeSeeded(type).catch((err) => {
|
|
172305
|
+
this.logger.error("storage-orchestrator: persisting the seed memory failed", { meta: {
|
|
172306
|
+
type,
|
|
172307
|
+
error: err instanceof Error ? err.message : String(err)
|
|
172308
|
+
} });
|
|
172309
|
+
});
|
|
172310
|
+
}
|
|
171830
172311
|
/** True once a persistence store is wired (constructor or {@link attachStore}). */
|
|
171831
172312
|
hasStore() {
|
|
171832
172313
|
return this.locationStore !== null;
|
|
@@ -171860,6 +172341,7 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
171860
172341
|
async attachStore(store) {
|
|
171861
172342
|
if (this.locationStore) return;
|
|
171862
172343
|
const rows = await store.loadAll();
|
|
172344
|
+
await this.loadSeedMemory(store, rows.length);
|
|
171863
172345
|
this.locationStore = store;
|
|
171864
172346
|
const dbIds = new Set(rows.map((r) => r.id));
|
|
171865
172347
|
for (const loc of rows) this.locations.set(loc.id, loc);
|
|
@@ -171998,6 +172480,7 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
171998
172480
|
async initialize() {
|
|
171999
172481
|
if (!this.locationStore) return;
|
|
172000
172482
|
const rows = await this.locationStore.loadAll();
|
|
172483
|
+
await this.loadSeedMemory(this.locationStore, rows.length);
|
|
172001
172484
|
for (const loc of rows) this.locations.set(loc.id, loc);
|
|
172002
172485
|
this.logger.info("storage-orchestrator: hydrated locations from store", { meta: { loaded: this.locations.size } });
|
|
172003
172486
|
this.migrateOntoTheWriteSet(rows);
|
|
@@ -172450,14 +172933,35 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
172450
172933
|
* directory for derivative slots like `recordingsLow` → `recordings`).
|
|
172451
172934
|
*/
|
|
172452
172935
|
seedDefaults(input) {
|
|
172936
|
+
if (this.storeRequiredForSeed && this.locationStore === null) {
|
|
172937
|
+
this.logger.warn("storage-orchestrator: seed deferred \u2014 the location store has not answered a read yet (not wired, adoption pending, or the read failed); seeding now could shadow the operator's existing locations");
|
|
172938
|
+
return {
|
|
172939
|
+
added: 0,
|
|
172940
|
+
deferred: "store-not-answered"
|
|
172941
|
+
};
|
|
172942
|
+
}
|
|
172453
172943
|
let added = 0;
|
|
172944
|
+
let deferredProvider = false;
|
|
172454
172945
|
const declById = new Map(input.declarations.map((d) => [d.id, d]));
|
|
172455
172946
|
const rootFor = (d) => {
|
|
172456
172947
|
const dedicated = d.defaultRoot === "media" ? input.mediaBasePath : d.defaultRoot === "backup" ? input.backupBasePath : void 0;
|
|
172457
172948
|
return node_path.join(dedicated ?? input.basePath, d.id);
|
|
172458
172949
|
};
|
|
172459
172950
|
for (const d of input.declarations) {
|
|
172460
|
-
if (this.hasAnyLocationOfType(d.id))
|
|
172951
|
+
if (this.hasAnyLocationOfType(d.id)) {
|
|
172952
|
+
this.rememberSeeded(d.id);
|
|
172953
|
+
continue;
|
|
172954
|
+
}
|
|
172955
|
+
if (this.seededTypes?.has(d.id)) continue;
|
|
172956
|
+
if (this.installPredatesSeedMemory) {
|
|
172957
|
+
this.logger.info("storage-orchestrator: existing install \u2014 not re-creating a default the operator may have removed", { meta: { type: d.id } });
|
|
172958
|
+
this.rememberSeeded(d.id);
|
|
172959
|
+
continue;
|
|
172960
|
+
}
|
|
172961
|
+
if (this.nodeLocalResolver !== null && this.nodeLocalResolver(input.providerId) === void 0) {
|
|
172962
|
+
deferredProvider = true;
|
|
172963
|
+
continue;
|
|
172964
|
+
}
|
|
172461
172965
|
const base = d.defaultsTo ? this.getLocationById(`${d.defaultsTo}:default`)?.config["basePath"] ?? rootFor(declById.get(d.defaultsTo) ?? d) : rootFor(d);
|
|
172462
172966
|
this.upsertLocation({
|
|
172463
172967
|
id: `${d.id}:default`,
|
|
@@ -172468,12 +172972,18 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
172468
172972
|
enabled: true,
|
|
172469
172973
|
isSystem: false
|
|
172470
172974
|
});
|
|
172975
|
+
this.rememberSeeded(d.id);
|
|
172471
172976
|
added++;
|
|
172472
172977
|
}
|
|
172473
172978
|
if (added > 0) this.logger.info("storage-orchestrator: seeded default locations", { meta: {
|
|
172474
172979
|
added,
|
|
172475
172980
|
basePath: input.basePath
|
|
172476
172981
|
} });
|
|
172982
|
+
if (deferredProvider) this.logger.info("storage-orchestrator: seed deferred for some types \u2014 provider not classified yet", { meta: { providerId: input.providerId } });
|
|
172983
|
+
return deferredProvider ? {
|
|
172984
|
+
added,
|
|
172985
|
+
deferred: "provider-unclassified"
|
|
172986
|
+
} : { added };
|
|
172477
172987
|
}
|
|
172478
172988
|
/**
|
|
172479
172989
|
* The same-type physical-root refusal (D389).
|
|
@@ -172805,29 +173315,69 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
172805
173315
|
lowPercent: 15,
|
|
172806
173316
|
criticalPercent: 5
|
|
172807
173317
|
};
|
|
172808
|
-
|
|
172809
|
-
|
|
172810
|
-
|
|
172811
|
-
|
|
172812
|
-
|
|
172813
|
-
|
|
172814
|
-
|
|
172815
|
-
|
|
172816
|
-
|
|
172817
|
-
|
|
172818
|
-
|
|
172819
|
-
|
|
173318
|
+
var UNMANAGED_HYSTERESIS_POINTS = 2;
|
|
173319
|
+
var MANAGED_LOW_ENTER = 0.8;
|
|
173320
|
+
var MANAGED_LOW_EXIT = 0.9;
|
|
173321
|
+
var MANAGED_CRITICAL_ENTER = 0.5;
|
|
173322
|
+
var MANAGED_CRITICAL_EXIT = 0.6;
|
|
173323
|
+
var MANAGED_LOW_GRACE_MS = 10 * 6e4;
|
|
173324
|
+
function boundsOf(floorPercent, config) {
|
|
173325
|
+
if (floorPercent === void 0) return {
|
|
173326
|
+
lowEnter: config.lowPercent,
|
|
173327
|
+
lowExit: config.lowPercent + UNMANAGED_HYSTERESIS_POINTS,
|
|
173328
|
+
criticalEnter: config.criticalPercent,
|
|
173329
|
+
criticalExit: config.criticalPercent + UNMANAGED_HYSTERESIS_POINTS,
|
|
173330
|
+
lowGraceMs: 0,
|
|
173331
|
+
lowReason: "free-below-warn",
|
|
173332
|
+
criticalReason: "free-below-critical"
|
|
172820
173333
|
};
|
|
172821
173334
|
return {
|
|
172822
|
-
|
|
172823
|
-
|
|
173335
|
+
lowEnter: floorPercent * MANAGED_LOW_ENTER,
|
|
173336
|
+
lowExit: floorPercent * MANAGED_LOW_EXIT,
|
|
173337
|
+
criticalEnter: floorPercent * MANAGED_CRITICAL_ENTER,
|
|
173338
|
+
criticalExit: floorPercent * MANAGED_CRITICAL_EXIT,
|
|
173339
|
+
lowGraceMs: MANAGED_LOW_GRACE_MS,
|
|
173340
|
+
lowReason: "free-below-floor",
|
|
173341
|
+
criticalReason: "free-below-hard-bound"
|
|
172824
173342
|
};
|
|
172825
173343
|
}
|
|
172826
173344
|
var StorageLocationBandMonitor = class {
|
|
172827
173345
|
config;
|
|
173346
|
+
now;
|
|
172828
173347
|
band = /* @__PURE__ */ new Map();
|
|
172829
|
-
|
|
173348
|
+
/** When free first went under `lowEnter` and has stayed there. */
|
|
173349
|
+
belowLowSince = /* @__PURE__ */ new Map();
|
|
173350
|
+
constructor(config = DEFAULT_STORAGE_LOCATION_BAND_CONFIG, now = Date.now) {
|
|
172830
173351
|
this.config = config;
|
|
173352
|
+
this.now = now;
|
|
173353
|
+
}
|
|
173354
|
+
nextBand(locationId, previous, free, b) {
|
|
173355
|
+
if (free < b.criticalEnter || previous === "critical" && free < b.criticalExit) return {
|
|
173356
|
+
band: "critical",
|
|
173357
|
+
reason: b.criticalReason
|
|
173358
|
+
};
|
|
173359
|
+
const lowActive = previous === "low" || previous === "critical";
|
|
173360
|
+
if (free < b.lowEnter || lowActive && free < b.lowExit) {
|
|
173361
|
+
if (lowActive) return {
|
|
173362
|
+
band: "low",
|
|
173363
|
+
reason: b.lowReason
|
|
173364
|
+
};
|
|
173365
|
+
const since = this.belowLowSince.get(locationId) ?? this.now();
|
|
173366
|
+
this.belowLowSince.set(locationId, since);
|
|
173367
|
+
if (this.now() - since >= b.lowGraceMs) return {
|
|
173368
|
+
band: "low",
|
|
173369
|
+
reason: b.lowReason
|
|
173370
|
+
};
|
|
173371
|
+
return {
|
|
173372
|
+
band: previous ?? "ok",
|
|
173373
|
+
reason: "free-ok"
|
|
173374
|
+
};
|
|
173375
|
+
}
|
|
173376
|
+
this.belowLowSince.delete(locationId);
|
|
173377
|
+
return {
|
|
173378
|
+
band: "ok",
|
|
173379
|
+
reason: "free-ok"
|
|
173380
|
+
};
|
|
172831
173381
|
}
|
|
172832
173382
|
/**
|
|
172833
173383
|
* Observe one sweep of managed locations. Locations missing from `samples`
|
|
@@ -172838,8 +173388,9 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
172838
173388
|
const out = [];
|
|
172839
173389
|
for (const sample of samples) {
|
|
172840
173390
|
seen.add(sample.locationId);
|
|
172841
|
-
|
|
173391
|
+
if (sample.freePercent === null) continue;
|
|
172842
173392
|
const previous = this.band.get(sample.locationId) ?? null;
|
|
173393
|
+
const { band, reason } = this.nextBand(sample.locationId, previous, sample.freePercent, boundsOf(sample.floorPercent, this.config));
|
|
172843
173394
|
if (previous === band) continue;
|
|
172844
173395
|
this.band.set(sample.locationId, band);
|
|
172845
173396
|
if (previous === null && band === "ok") continue;
|
|
@@ -172849,11 +173400,17 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
172849
173400
|
...sample.locationName !== void 0 ? { locationName: sample.locationName } : {},
|
|
172850
173401
|
band,
|
|
172851
173402
|
freePercent: sample.freePercent,
|
|
173403
|
+
...sample.floorPercent !== void 0 ? { floorPercent: sample.floorPercent } : {},
|
|
173404
|
+
...sample.freeBytes !== void 0 ? { freeBytes: sample.freeBytes } : {},
|
|
173405
|
+
...sample.floorBytes !== void 0 ? { floorBytes: sample.floorBytes } : {},
|
|
172852
173406
|
reason,
|
|
172853
173407
|
previous
|
|
172854
173408
|
});
|
|
172855
173409
|
}
|
|
172856
|
-
for (const id of [...this.band.keys()]) if (!seen.has(id))
|
|
173410
|
+
for (const id of [...this.band.keys()]) if (!seen.has(id)) {
|
|
173411
|
+
this.band.delete(id);
|
|
173412
|
+
this.belowLowSince.delete(id);
|
|
173413
|
+
}
|
|
172857
173414
|
return out;
|
|
172858
173415
|
}
|
|
172859
173416
|
};
|
|
@@ -172866,6 +173423,7 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
172866
173423
|
var CAP_PROVIDER_REGISTERED_CATEGORY = "capability:provider-registered";
|
|
172867
173424
|
var StorageOrchestratorAddon = class extends require_dist10.BaseAddon {
|
|
172868
173425
|
locationsKind = null;
|
|
173426
|
+
seedMarkersKind = null;
|
|
172869
173427
|
drainStateKind = null;
|
|
172870
173428
|
service = null;
|
|
172871
173429
|
pressureManager = null;
|
|
@@ -172891,6 +173449,8 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
172891
173449
|
pressureTimer = null;
|
|
172892
173450
|
pressureSweepInFlight = false;
|
|
172893
173451
|
migration = null;
|
|
173452
|
+
/** Guards every single-location repoint and arbitrates movers per physical root. */
|
|
173453
|
+
repointer = null;
|
|
172894
173454
|
/**
|
|
172895
173455
|
* Cached `providerId → nodeLocal` snapshot (SP1). Backs the orchestrator's
|
|
172896
173456
|
* synchronous `NodeLocalResolver` — `getProviderInfo()` is async, so we
|
|
@@ -172927,6 +173487,7 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
172927
173487
|
if (records !== void 0) {
|
|
172928
173488
|
await records.declare(storageOrchestratorRecordKinds);
|
|
172929
173489
|
this.locationsKind = SqliteLocationStore.recordStoresOf(records);
|
|
173490
|
+
this.seedMarkersKind = SqliteLocationStore.seedMarkersOf(records);
|
|
172930
173491
|
this.drainStateKind = SqliteDrainStateStore.recordStoresOf(records);
|
|
172931
173492
|
}
|
|
172932
173493
|
const getProviders = () => {
|
|
@@ -172946,6 +173507,7 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
172946
173507
|
return proxy;
|
|
172947
173508
|
});
|
|
172948
173509
|
this.service = service;
|
|
173510
|
+
service.setStoreRequiredForSeed(this.locationsKind !== null);
|
|
172949
173511
|
service.setNodeLocalResolver((providerId) => this.nodeLocalByProvider.get(providerId));
|
|
172950
173512
|
service.setOccupancyProbe((location) => this.locationOccupancy(location));
|
|
172951
173513
|
await service.initialize();
|
|
@@ -172969,8 +173531,7 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
172969
173531
|
...input,
|
|
172970
173532
|
config: keychained
|
|
172971
173533
|
};
|
|
172972
|
-
await this.
|
|
172973
|
-
const saved = service.upsertLocation(next);
|
|
173534
|
+
const saved = await this.upsertCarryingData(stored, next, () => service.upsertLocation(next));
|
|
172974
173535
|
this.announceLocationsChanged(saved.id, saved.type, "upsert");
|
|
172975
173536
|
return this.redacted(saved);
|
|
172976
173537
|
},
|
|
@@ -173180,6 +173741,49 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
173180
173741
|
deviceKeyOf: (locationId) => this.locationDeviceKey(locationId)
|
|
173181
173742
|
});
|
|
173182
173743
|
this.migration = migration;
|
|
173744
|
+
this.repointer = new LocationRepointer({
|
|
173745
|
+
logger: this.ctx.logger,
|
|
173746
|
+
resolveKey: async (basePath) => {
|
|
173747
|
+
try {
|
|
173748
|
+
return await node_fs_promises.realpath(basePath);
|
|
173749
|
+
} catch {
|
|
173750
|
+
return node_path.resolve(basePath);
|
|
173751
|
+
}
|
|
173752
|
+
},
|
|
173753
|
+
locationBasePath: (id) => this.locationBasePath(id),
|
|
173754
|
+
locationIdsOfType: (type) => service.listLocations({ type }).map((loc) => loc.id),
|
|
173755
|
+
listMovers: () => migration.movers(),
|
|
173756
|
+
ioFor: async (stored, next) => {
|
|
173757
|
+
const target = {
|
|
173758
|
+
...stored,
|
|
173759
|
+
config: next.config
|
|
173760
|
+
};
|
|
173761
|
+
const [source, destination] = await Promise.all([service.getProviderFor(stored), service.getProviderFor(target)]);
|
|
173762
|
+
return {
|
|
173763
|
+
list: (prefix) => source.list(prefix === void 0 ? { location: stored } : {
|
|
173764
|
+
location: stored,
|
|
173765
|
+
prefix
|
|
173766
|
+
}),
|
|
173767
|
+
read: (relativePath) => source.read({
|
|
173768
|
+
location: stored,
|
|
173769
|
+
relativePath
|
|
173770
|
+
}),
|
|
173771
|
+
write: (relativePath, data) => destination.write({
|
|
173772
|
+
location: target,
|
|
173773
|
+
relativePath,
|
|
173774
|
+
data
|
|
173775
|
+
}),
|
|
173776
|
+
readBack: (relativePath) => destination.read({
|
|
173777
|
+
location: target,
|
|
173778
|
+
relativePath
|
|
173779
|
+
}),
|
|
173780
|
+
deleteSource: (relativePath) => source.delete({
|
|
173781
|
+
location: stored,
|
|
173782
|
+
relativePath
|
|
173783
|
+
})
|
|
173784
|
+
};
|
|
173785
|
+
}
|
|
173786
|
+
});
|
|
173183
173787
|
const cleanup = new StorageCleanupCoordinator({
|
|
173184
173788
|
locations: service,
|
|
173185
173789
|
state: this.state("storage-cleanup", require_dist10.StorageCleanupJobSchema.nullable(), null),
|
|
@@ -173215,6 +173819,13 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
173215
173819
|
status: ({ jobId }) => migration.status(jobId),
|
|
173216
173820
|
cancel: async ({ jobId }) => ({ cancelled: await migration.cancel(jobId) }),
|
|
173217
173821
|
movers: () => migration.movers(),
|
|
173822
|
+
moverClearance: async ({ locationIds }) => {
|
|
173823
|
+
const verdict = await this.requireRepointer().clearance(locationIds);
|
|
173824
|
+
return verdict.clear ? { clear: true } : {
|
|
173825
|
+
clear: false,
|
|
173826
|
+
repointLocationId: verdict.repointLocationId
|
|
173827
|
+
};
|
|
173828
|
+
},
|
|
173218
173829
|
residue: () => migration.residue(),
|
|
173219
173830
|
drain: async (input) => ({ jobId: await migration.drain(input) }),
|
|
173220
173831
|
cleanupStart: async (input) => ({ jobId: await cleanup.start(input) }),
|
|
@@ -173342,7 +173953,7 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
173342
173953
|
else this.ctx.logger.info("storage-orchestrator: this node boots no data-store engine \u2014 storage locations are seeded from addon declarations at every boot, and node-pinned locations live on the hub");
|
|
173343
173954
|
return null;
|
|
173344
173955
|
}
|
|
173345
|
-
return new SqliteLocationStore(engine, this.locationsKind);
|
|
173956
|
+
return new SqliteLocationStore(engine, this.locationsKind, this.seedMarkersKind);
|
|
173346
173957
|
}
|
|
173347
173958
|
/**
|
|
173348
173959
|
* Late-wire the persistence store once a `data-store-provider` engine
|
|
@@ -173354,12 +173965,26 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
173354
173965
|
* restart — the service never hydrates from / persists to SQLite.
|
|
173355
173966
|
*/
|
|
173356
173967
|
storeWireInFlight = null;
|
|
173968
|
+
/** True while the locations kind is empty and its legacy table still holds rows. */
|
|
173969
|
+
async adoptionIsPending() {
|
|
173970
|
+
const records = this.ctx.records;
|
|
173971
|
+
if (records === void 0 || this.locationsKind === null) return false;
|
|
173972
|
+
try {
|
|
173973
|
+
await records.declare(storageOrchestratorRecordKinds);
|
|
173974
|
+
return false;
|
|
173975
|
+
} catch (err) {
|
|
173976
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
173977
|
+
this.ctx.logger.warn("storage-orchestrator: persistence NOT wired \u2014 the storage-locations kind is not authoritative yet (adoption pending or the check failed); seeding is deferred", { meta: { error: message } });
|
|
173978
|
+
return true;
|
|
173979
|
+
}
|
|
173980
|
+
}
|
|
173357
173981
|
async ensureStoreWired() {
|
|
173358
173982
|
const service = this.service;
|
|
173359
173983
|
if (!service || service.hasStore()) return;
|
|
173360
173984
|
if (this.storeWireInFlight) return this.storeWireInFlight;
|
|
173361
173985
|
const store = this.resolveLocationStore(true);
|
|
173362
173986
|
if (!store) return;
|
|
173987
|
+
if (await this.adoptionIsPending()) return;
|
|
173363
173988
|
this.ctx.logger.info("storage-orchestrator: data-store engine now available \u2014 wiring persistence");
|
|
173364
173989
|
this.storeWireInFlight = service.attachStore(store).then(() => this.seedFromDeclarations()).catch((err) => {
|
|
173365
173990
|
this.ctx.logger.error("storage-orchestrator: attachStore failed", { meta: { error: err instanceof Error ? err.message : String(err) } });
|
|
@@ -173388,7 +174013,7 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
173388
174013
|
}
|
|
173389
174014
|
/**
|
|
173390
174015
|
* Sample free space for every managed location and emit NC band edges.
|
|
173391
|
-
* A failed capacity read stays `null`
|
|
174016
|
+
* A failed capacity read stays `null` and changes no band — never folded to 0 (D393).
|
|
173392
174017
|
*/
|
|
173393
174018
|
async emitLocationBandEvents() {
|
|
173394
174019
|
const svc = this.service;
|
|
@@ -173404,11 +174029,18 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
173404
174029
|
};
|
|
173405
174030
|
const capacity = await this.volumeCapacityOf(locationId).catch(() => null);
|
|
173406
174031
|
const freePercent = capacity === null ? null : freePercentOf(capacity);
|
|
174032
|
+
if (capacity === null) ctx.logger.debug("storage: location capacity unreadable \u2014 band unchanged", { meta: { locationId } });
|
|
174033
|
+
const floorPercent = thresholds.get(locationId);
|
|
173407
174034
|
return {
|
|
173408
174035
|
locationId,
|
|
173409
174036
|
nodeId: loc.nodeId,
|
|
173410
174037
|
locationName: loc.displayName,
|
|
173411
|
-
freePercent
|
|
174038
|
+
freePercent,
|
|
174039
|
+
...floorPercent !== void 0 ? { floorPercent } : {},
|
|
174040
|
+
...capacity !== null ? {
|
|
174041
|
+
freeBytes: capacity.availableBytes,
|
|
174042
|
+
...floorPercent !== void 0 ? { floorBytes: Math.round(capacity.totalBytes * floorPercent / 100) } : {}
|
|
174043
|
+
} : {}
|
|
173412
174044
|
};
|
|
173413
174045
|
}));
|
|
173414
174046
|
for (const edge of this.locationBandMonitor.observe(samples)) {
|
|
@@ -173417,6 +174049,9 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
173417
174049
|
locationId: edge.locationId,
|
|
173418
174050
|
band: edge.band,
|
|
173419
174051
|
freePercent: edge.freePercent,
|
|
174052
|
+
floorPercent: edge.floorPercent ?? null,
|
|
174053
|
+
freeBytes: edge.freeBytes ?? null,
|
|
174054
|
+
floorBytes: edge.floorBytes ?? null,
|
|
173420
174055
|
reason: edge.reason
|
|
173421
174056
|
} });
|
|
173422
174057
|
ctx.eventBus.emit({
|
|
@@ -173531,50 +174166,19 @@ var require_storage_orchestrator_addon = __commonJS({
|
|
|
173531
174166
|
* A no-op for everything else — a rename, a mode change, a `multi` kind, or a
|
|
173532
174167
|
* location being created for the first time.
|
|
173533
174168
|
*/
|
|
173534
|
-
async
|
|
173535
|
-
if (stored === void 0) return;
|
|
174169
|
+
async upsertCarryingData(stored, next, commit) {
|
|
174170
|
+
if (stored === void 0) return commit();
|
|
173536
174171
|
const service = this.service;
|
|
173537
|
-
if (service === null) return;
|
|
173538
|
-
if (service.listDeclarations().find((entry) => entry.id === next.type)?.cardinality !== "single") return;
|
|
174172
|
+
if (service === null) return commit();
|
|
174173
|
+
if (service.listDeclarations().find((entry) => entry.id === next.type)?.cardinality !== "single") return commit();
|
|
173539
174174
|
const from = stored.config["basePath"];
|
|
173540
174175
|
const to = next.config["basePath"];
|
|
173541
|
-
if (typeof from !== "string" || typeof to !== "string" || from === to) return;
|
|
173542
|
-
|
|
173543
|
-
|
|
173544
|
-
|
|
173545
|
-
|
|
173546
|
-
|
|
173547
|
-
const destination = await service.getProviderFor(target);
|
|
173548
|
-
const moved = await moveLocationTree({
|
|
173549
|
-
list: (prefix) => source.list(prefix === void 0 ? { location: stored } : {
|
|
173550
|
-
location: stored,
|
|
173551
|
-
prefix
|
|
173552
|
-
}),
|
|
173553
|
-
read: (relativePath) => source.read({
|
|
173554
|
-
location: stored,
|
|
173555
|
-
relativePath
|
|
173556
|
-
}),
|
|
173557
|
-
write: (relativePath, data) => destination.write({
|
|
173558
|
-
location: target,
|
|
173559
|
-
relativePath,
|
|
173560
|
-
data
|
|
173561
|
-
}),
|
|
173562
|
-
readBack: (relativePath) => destination.read({
|
|
173563
|
-
location: target,
|
|
173564
|
-
relativePath
|
|
173565
|
-
}),
|
|
173566
|
-
deleteSource: (relativePath) => source.delete({
|
|
173567
|
-
location: stored,
|
|
173568
|
-
relativePath
|
|
173569
|
-
})
|
|
173570
|
-
});
|
|
173571
|
-
this.ctx.logger.info("storage-orchestrator: singleton location re-pointed \u2014 its data was carried over", { meta: {
|
|
173572
|
-
id: stored.id,
|
|
173573
|
-
type: stored.type,
|
|
173574
|
-
from,
|
|
173575
|
-
to,
|
|
173576
|
-
...moved
|
|
173577
|
-
} });
|
|
174176
|
+
if (typeof from !== "string" || typeof to !== "string" || from === to) return commit();
|
|
174177
|
+
return this.requireRepointer().run(stored, next, commit);
|
|
174178
|
+
}
|
|
174179
|
+
requireRepointer() {
|
|
174180
|
+
if (this.repointer === null) throw new Error("storage-orchestrator: not initialized");
|
|
174181
|
+
return this.repointer;
|
|
173578
174182
|
}
|
|
173579
174183
|
secretKeysFor(providerId, config) {
|
|
173580
174184
|
return secretKeysForConfig(config, this.declaredSecretKeys(providerId));
|
|
@@ -173978,11 +174582,11 @@ var require_storage_orchestrator = __commonJS({
|
|
|
173978
174582
|
}
|
|
173979
174583
|
});
|
|
173980
174584
|
|
|
173981
|
-
// ../system/dist/constants-
|
|
173982
|
-
var
|
|
173983
|
-
"../system/dist/constants-
|
|
174585
|
+
// ../system/dist/constants-DBGG6Zu5.js
|
|
174586
|
+
var require_constants_DBGG6Zu5 = __commonJS({
|
|
174587
|
+
"../system/dist/constants-DBGG6Zu5.js"(exports) {
|
|
173984
174588
|
"use strict";
|
|
173985
|
-
var MESH_CA_KEY_REF =
|
|
174589
|
+
var MESH_CA_KEY_REF = require_dist_Bi4Ioxop().buildSecretRef({
|
|
173986
174590
|
owner: "system",
|
|
173987
174591
|
scope: { kind: "global" },
|
|
173988
174592
|
fieldPath: "meshCaKey"
|
|
@@ -174045,14 +174649,14 @@ var require_constants_BPWA_r_Y = __commonJS({
|
|
|
174045
174649
|
}
|
|
174046
174650
|
});
|
|
174047
174651
|
|
|
174048
|
-
// ../system/dist/agent-https-
|
|
174049
|
-
var
|
|
174050
|
-
"../system/dist/agent-https-
|
|
174652
|
+
// ../system/dist/agent-https-B7IjRRzT.js
|
|
174653
|
+
var require_agent_https_B7IjRRzT = __commonJS({
|
|
174654
|
+
"../system/dist/agent-https-B7IjRRzT.js"(exports) {
|
|
174051
174655
|
"use strict";
|
|
174052
174656
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
174053
|
-
var require_dist10 =
|
|
174657
|
+
var require_dist10 = require_dist_Bi4Ioxop();
|
|
174054
174658
|
var require_x509_es = require_x509_es_C4cOo48M();
|
|
174055
|
-
var require_constants15 =
|
|
174659
|
+
var require_constants15 = require_constants_DBGG6Zu5();
|
|
174056
174660
|
var zod = require_zod();
|
|
174057
174661
|
var node_crypto = __require("crypto");
|
|
174058
174662
|
var _camstack_types_node = require_node();
|
|
@@ -192795,11 +193399,11 @@ var require_system_config_addon = __commonJS({
|
|
|
192795
193399
|
[Symbol.toStringTag]: { value: "Module" }
|
|
192796
193400
|
});
|
|
192797
193401
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
192798
|
-
var require_dist10 =
|
|
193402
|
+
var require_dist10 = require_dist_Bi4Ioxop();
|
|
192799
193403
|
var require_safe_buffer$1 = require_safe_buffer_D3aoa_7X();
|
|
192800
193404
|
var require_x509_es = require_x509_es_C4cOo48M();
|
|
192801
|
-
var require_constants$8 =
|
|
192802
|
-
var require_agent_https =
|
|
193405
|
+
var require_constants$8 = require_constants_DBGG6Zu5();
|
|
193406
|
+
var require_agent_https = require_agent_https_B7IjRRzT();
|
|
192803
193407
|
var require_src$1 = require_src_CnAqG6EF();
|
|
192804
193408
|
var zod = require_zod();
|
|
192805
193409
|
var node_crypto = __require("crypto");
|
|
@@ -272512,7 +273116,7 @@ var require_winston_logging = __commonJS({
|
|
|
272512
273116
|
[Symbol.toStringTag]: { value: "Module" }
|
|
272513
273117
|
});
|
|
272514
273118
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
272515
|
-
var require_dist10 =
|
|
273119
|
+
var require_dist10 = require_dist_Bi4Ioxop();
|
|
272516
273120
|
var require_formatter = require_formatter_DqAKDlvN();
|
|
272517
273121
|
var node_path = __require("path");
|
|
272518
273122
|
node_path = require_chunk.__toESM(node_path);
|
|
@@ -280162,14 +280766,14 @@ var require_lib_8oZrELLm = __commonJS({
|
|
|
280162
280766
|
}
|
|
280163
280767
|
});
|
|
280164
280768
|
|
|
280165
|
-
// ../system/dist/hub-mdns-ciao-
|
|
280166
|
-
var
|
|
280167
|
-
"../system/dist/hub-mdns-ciao-
|
|
280769
|
+
// ../system/dist/hub-mdns-ciao-2FzLWfbD.js
|
|
280770
|
+
var require_hub_mdns_ciao_2FzLWfbD = __commonJS({
|
|
280771
|
+
"../system/dist/hub-mdns-ciao-2FzLWfbD.js"(exports) {
|
|
280168
280772
|
"use strict";
|
|
280169
280773
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
280170
|
-
var require_dist10 =
|
|
280774
|
+
var require_dist10 = require_dist_Bi4Ioxop();
|
|
280171
280775
|
var require_x509_es = require_x509_es_C4cOo48M();
|
|
280172
|
-
var require_agent_https =
|
|
280776
|
+
var require_agent_https = require_agent_https_B7IjRRzT();
|
|
280173
280777
|
var node_crypto = __require("crypto");
|
|
280174
280778
|
var _camstack_types_node = require_node();
|
|
280175
280779
|
var node_fs_promises = __require("fs/promises");
|
|
@@ -281168,12 +281772,12 @@ var require_platform_key_source_Di7HrlGR = __commonJS({
|
|
|
281168
281772
|
}
|
|
281169
281773
|
});
|
|
281170
281774
|
|
|
281171
|
-
// ../system/dist/restore-archive-
|
|
281172
|
-
var
|
|
281173
|
-
"../system/dist/restore-archive-
|
|
281775
|
+
// ../system/dist/restore-archive-C0ymYQk7.js
|
|
281776
|
+
var require_restore_archive_C0ymYQk7 = __commonJS({
|
|
281777
|
+
"../system/dist/restore-archive-C0ymYQk7.js"(exports) {
|
|
281174
281778
|
"use strict";
|
|
281175
281779
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
281176
|
-
var require_dist10 =
|
|
281780
|
+
var require_dist10 = require_dist_Bi4Ioxop();
|
|
281177
281781
|
var require_read_all_rows$1 = require_read_all_rows_CVoO1ONM();
|
|
281178
281782
|
var zod = require_zod();
|
|
281179
281783
|
var node_crypto = __require("crypto");
|
|
@@ -292494,9 +293098,9 @@ var require_dist3 = __commonJS({
|
|
|
292494
293098
|
"use strict";
|
|
292495
293099
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
292496
293100
|
var require_chunk = require_chunk_Cek0wNdY();
|
|
292497
|
-
var require_dist10 =
|
|
293101
|
+
var require_dist10 = require_dist_Bi4Ioxop();
|
|
292498
293102
|
var require_read_all_rows$1 = require_read_all_rows_CVoO1ONM();
|
|
292499
|
-
var require_device_ca =
|
|
293103
|
+
var require_device_ca = require_device_ca_B3hUVfYk();
|
|
292500
293104
|
var require_builtins_alerts_alerts_addon = require_alerts_addon();
|
|
292501
293105
|
require_alerts();
|
|
292502
293106
|
var require_builtins_calendars_calendars_addon = require_calendars_addon();
|
|
@@ -292521,21 +293125,21 @@ var require_dist3 = __commonJS({
|
|
|
292521
293125
|
var require_builtins_native_metrics_native_metrics_addon = require_native_metrics_addon();
|
|
292522
293126
|
var require_builtins_device_history_device_history_addon = require_device_history_addon();
|
|
292523
293127
|
var require_builtins_sqlite_storage_filesystem_storage_addon = require_filesystem_storage_addon();
|
|
292524
|
-
var require_wal_maintenance =
|
|
293128
|
+
var require_wal_maintenance = require_wal_maintenance_Bo_lo3Dh();
|
|
292525
293129
|
var require_builtins_sqlite_storage_sqlite_settings_addon = require_sqlite_settings_addon();
|
|
292526
293130
|
var require_builtins_sqlite_storage_index = require_sqlite_storage();
|
|
292527
293131
|
var require_builtins_storage_orchestrator_storage_orchestrator_addon = require_storage_orchestrator_addon();
|
|
292528
293132
|
require_storage_orchestrator();
|
|
292529
|
-
var require_constants15 =
|
|
292530
|
-
var require_agent_https =
|
|
293133
|
+
var require_constants15 = require_constants_DBGG6Zu5();
|
|
293134
|
+
var require_agent_https = require_agent_https_B7IjRRzT();
|
|
292531
293135
|
var require_builtins_system_config_system_config_addon = require_system_config_addon();
|
|
292532
293136
|
require_system_config();
|
|
292533
293137
|
var require_builtins_winston_logging_index = require_winston_logging();
|
|
292534
293138
|
var require_custom_action_registry = require_custom_action_registry_COyb49zm();
|
|
292535
|
-
var require_hub_mdns_ciao =
|
|
293139
|
+
var require_hub_mdns_ciao = require_hub_mdns_ciao_2FzLWfbD();
|
|
292536
293140
|
var require_platform_key_source = require_platform_key_source_Di7HrlGR();
|
|
292537
293141
|
var require_resource_monitor = require_resource_monitor_mio9dSCT();
|
|
292538
|
-
var require_restore_archive =
|
|
293142
|
+
var require_restore_archive = require_restore_archive_C0ymYQk7();
|
|
292539
293143
|
var zod = require_zod();
|
|
292540
293144
|
var node_crypto = __require("crypto");
|
|
292541
293145
|
node_crypto = require_chunk.__toESM(node_crypto);
|
|
@@ -301599,8 +302203,16 @@ var require_dist3 = __commonJS({
|
|
|
301599
302203
|
const nodeId = typeof picked2.nodeId === "string" ? picked2.nodeId : void 0;
|
|
301600
302204
|
const topLevelAddonId = typeof picked2.addonId === "string" ? picked2.addonId : void 0;
|
|
301601
302205
|
const canRecoverNestedAddonId = !require_dist10.isArrayOutputSchema(method.schema.output) && !require_dist10.objectInputDeclaresAddonId(method.schema.input);
|
|
301602
|
-
|
|
301603
|
-
|
|
302206
|
+
let addonId = topLevelAddonId ?? (canRecoverNestedAddonId ? require_dist10.extractNestedAddonId(rest2) : void 0);
|
|
302207
|
+
const resolveAndInvoke = async () => {
|
|
302208
|
+
let refusePin = topLevelAddonId;
|
|
302209
|
+
if (addonId === void 0 && !method.isArrayOutput && services.inferCollectionAddonPin) {
|
|
302210
|
+
addonId = await Promise.resolve(services.inferCollectionAddonPin(capName, method.name, rest2));
|
|
302211
|
+
if (addonId !== void 0) refusePin = addonId;
|
|
302212
|
+
}
|
|
302213
|
+
return invokeCapMethod(resolveProviderForCall(capName, nodeId, () => getLocal(ctx, addonId), services, refusePin), method, method.callerRequired ? injectCaller(rest2, ctx, capName, method.name, services) : rest2, capName, isCollection, services);
|
|
302214
|
+
};
|
|
302215
|
+
return resolveAndInvoke();
|
|
301604
302216
|
}
|
|
301605
302217
|
const { rest, picked } = stripKeys(input, ["nodeId"]);
|
|
301606
302218
|
return invokeCapMethod(resolveProviderForCall(capName, typeof picked.nodeId === "string" ? picked.nodeId : void 0, () => getLocal(ctx), services), method, method.callerRequired ? injectCaller(rest, ctx, capName, method.name, services) : rest, capName, isCollection, services);
|
|
@@ -315973,7 +316585,7 @@ var require_enums = __commonJS({
|
|
|
315973
316585
|
"../types/dist/enums.js"(exports) {
|
|
315974
316586
|
"use strict";
|
|
315975
316587
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
315976
|
-
var require_event_category =
|
|
316588
|
+
var require_event_category = require_event_category_eSqkye_K();
|
|
315977
316589
|
var EventSourceType = /* @__PURE__ */ (function(EventSourceType2) {
|
|
315978
316590
|
EventSourceType2["Addon"] = "addon";
|
|
315979
316591
|
EventSourceType2["Core"] = "core";
|
|
@@ -315993,8 +316605,8 @@ var require_dist4 = __commonJS({
|
|
|
315993
316605
|
"../types/dist/index.js"(exports) {
|
|
315994
316606
|
"use strict";
|
|
315995
316607
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
315996
|
-
var require_sleep =
|
|
315997
|
-
var require_event_category =
|
|
316608
|
+
var require_sleep = require_sleep_BE7_6UnC();
|
|
316609
|
+
var require_event_category = require_event_category_eSqkye_K();
|
|
315998
316610
|
var require_composition = require_composition_eoYYVfOp();
|
|
315999
316611
|
var require_node_color2 = require_node_color();
|
|
316000
316612
|
var require_err_msg = require_err_msg_BhVbr0NX();
|
|
@@ -318405,6 +319017,31 @@ var require_dist4 = __commonJS({
|
|
|
318405
319017
|
error: zod.z.string().nullable()
|
|
318406
319018
|
});
|
|
318407
319019
|
var StorageCleanupStatusInputSchema = zod.z.object({ jobId: zod.z.string().optional() });
|
|
319020
|
+
async function startMoverUnderClearance(deps) {
|
|
319021
|
+
const refuse = (detail) => {
|
|
319022
|
+
throw new Error(`mover refused: ${detail}`);
|
|
319023
|
+
};
|
|
319024
|
+
const ask = async () => {
|
|
319025
|
+
try {
|
|
319026
|
+
return await deps.clearance(deps.locationIds);
|
|
319027
|
+
} catch (err) {
|
|
319028
|
+
return refuse(`the storage orchestrator could not be asked (${err instanceof Error ? err.message : String(err)})`);
|
|
319029
|
+
}
|
|
319030
|
+
};
|
|
319031
|
+
const blocked = (answer) => `a re-point of "${answer.repointLocationId ?? "a location"}" holds an overlapping storage root`;
|
|
319032
|
+
const before = await ask();
|
|
319033
|
+
if (!before.clear) return refuse(blocked(before));
|
|
319034
|
+
const jobId = deps.start();
|
|
319035
|
+
const after = await ask().catch((err) => {
|
|
319036
|
+
deps.cancel(jobId);
|
|
319037
|
+
throw err;
|
|
319038
|
+
});
|
|
319039
|
+
if (!after.clear) {
|
|
319040
|
+
deps.cancel(jobId);
|
|
319041
|
+
return refuse(blocked(after));
|
|
319042
|
+
}
|
|
319043
|
+
return jobId;
|
|
319044
|
+
}
|
|
318408
319045
|
var SUB_DETECTION_TYPES = ["face", "plate"];
|
|
318409
319046
|
var RECOGNITION_TYPES = [
|
|
318410
319047
|
"face",
|
|
@@ -321402,7 +322039,14 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
321402
322039
|
]);
|
|
321403
322040
|
var AlertActionSchema = zod.z.object({
|
|
321404
322041
|
label: zod.z.string(),
|
|
321405
|
-
href: zod.z.string().optional()
|
|
322042
|
+
href: zod.z.string().optional(),
|
|
322043
|
+
/**
|
|
322044
|
+
* How `href` is followed. Absent / `app`: an admin-ui route (client-side).
|
|
322045
|
+
* `server`: a route the HUB serves (an addon HTTP route such as an OAuth
|
|
322046
|
+
* start) — the browser must leave the SPA with a full navigation, because
|
|
322047
|
+
* the SPA has no such route and would bounce to the home page.
|
|
322048
|
+
*/
|
|
322049
|
+
navigation: zod.z.enum(["app", "server"]).optional()
|
|
321406
322050
|
});
|
|
321407
322051
|
var AlertStatusSchema = zod.z.enum([
|
|
321408
322052
|
"active",
|
|
@@ -327702,7 +328346,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
327702
328346
|
var deviceAdoptionCapability = {
|
|
327703
328347
|
name: "device-adoption",
|
|
327704
328348
|
scope: "system",
|
|
327705
|
-
mode: "
|
|
328349
|
+
mode: "collection",
|
|
327706
328350
|
status: {
|
|
327707
328351
|
schema: AdoptionStatusSchema,
|
|
327708
328352
|
kind: "poll"
|
|
@@ -349070,7 +349714,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
349070
349714
|
auth: "admin"
|
|
349071
349715
|
}),
|
|
349072
349716
|
/** List candidate filter chips for an integration via its device-adoption
|
|
349073
|
-
* provider — addonId-routed
|
|
349717
|
+
* provider — addonId-routed via the collection pin. */
|
|
349074
349718
|
adoptionListCandidateFilters: require_sleep.method(zod.z.object({
|
|
349075
349719
|
addonId: zod.z.string(),
|
|
349076
349720
|
integrationId: zod.z.string()
|
|
@@ -352917,6 +353561,9 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
352917
353561
|
"server-updated",
|
|
352918
353562
|
"export-completed",
|
|
352919
353563
|
"backup-completed",
|
|
353564
|
+
"alert-critical",
|
|
353565
|
+
"alert-error",
|
|
353566
|
+
"alert-critical-resolved",
|
|
352920
353567
|
"camera-online",
|
|
352921
353568
|
"camera-offline",
|
|
352922
353569
|
"camera-disabled",
|
|
@@ -354055,6 +354702,18 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
354055
354702
|
value: "backup-completed",
|
|
354056
354703
|
label: "Backup completed"
|
|
354057
354704
|
},
|
|
354705
|
+
{
|
|
354706
|
+
value: "alert-critical",
|
|
354707
|
+
label: "Critical alert raised"
|
|
354708
|
+
},
|
|
354709
|
+
{
|
|
354710
|
+
value: "alert-error",
|
|
354711
|
+
label: "Error alert raised"
|
|
354712
|
+
},
|
|
354713
|
+
{
|
|
354714
|
+
value: "alert-critical-resolved",
|
|
354715
|
+
label: "Critical alert resolved"
|
|
354716
|
+
},
|
|
354058
354717
|
{
|
|
354059
354718
|
value: "alarm-arm-refused",
|
|
354060
354719
|
label: "Alarm arm refused"
|
|
@@ -363041,6 +363700,18 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
363041
363700
|
*/
|
|
363042
363701
|
movers: require_sleep.method(zod.z.object({}), zod.z.array(StorageMigrationMoverSchema).readonly(), { auth: "admin" }),
|
|
363043
363702
|
/**
|
|
363703
|
+
* May a mover that touches these locations run NOW? One claim per physical
|
|
363704
|
+
* root is owned by the storage orchestrator: a single-location repoint holds
|
|
363705
|
+
* it while it carries its subtree, and a mover (`relocateMedia`,
|
|
363706
|
+
* `relocateFootage`, a migration move) asks here AFTER registering its job and
|
|
363707
|
+
* cancels itself on `clear: false`. The repoint, in turn, refuses while a
|
|
363708
|
+
* registered mover touches its root. Asked, never polled (D3).
|
|
363709
|
+
*/
|
|
363710
|
+
moverClearance: require_sleep.method(zod.z.object({ locationIds: zod.z.array(zod.z.string()).readonly() }), zod.z.object({
|
|
363711
|
+
clear: zod.z.boolean(),
|
|
363712
|
+
repointLocationId: zod.z.string().optional()
|
|
363713
|
+
}), { auth: "admin" }),
|
|
363714
|
+
/**
|
|
363044
363715
|
* What each class's SOURCE still holds, from the archive — never from the
|
|
363045
363716
|
* resident index (D295). Only classes with something left (or something
|
|
363046
363717
|
* unknown) are listed, so an empty list means there is nothing to drain and
|
|
@@ -367380,35 +368051,139 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
367380
368051
|
"error",
|
|
367381
368052
|
"unavailable"
|
|
367382
368053
|
]);
|
|
368054
|
+
var DishwasherOperationStateSchema = zod.z.enum([
|
|
368055
|
+
"Inactive",
|
|
368056
|
+
"Ready",
|
|
368057
|
+
"DelayedStart",
|
|
368058
|
+
"Run",
|
|
368059
|
+
"Pause",
|
|
368060
|
+
"ActionRequired",
|
|
368061
|
+
"Finished",
|
|
368062
|
+
"Error",
|
|
368063
|
+
"Aborting"
|
|
368064
|
+
]);
|
|
368065
|
+
var DishwasherAvailabilitySchema = zod.z.enum([
|
|
368066
|
+
"available",
|
|
368067
|
+
"offline",
|
|
368068
|
+
"description-missing"
|
|
368069
|
+
]);
|
|
367383
368070
|
var DishwasherConsumableLevelSchema = zod.z.enum([
|
|
367384
368071
|
"ok",
|
|
367385
368072
|
"low",
|
|
367386
368073
|
"empty"
|
|
367387
368074
|
]);
|
|
367388
368075
|
var DishwasherStatusSchema = zod.z.object({
|
|
368076
|
+
availability: DishwasherAvailabilitySchema,
|
|
368077
|
+
/** Coarse state for compact surfaces; `unavailable` whenever the appliance state is not known. */
|
|
367389
368078
|
state: DishwasherStateSchema,
|
|
367390
|
-
/**
|
|
368079
|
+
/** The appliance's operation state as reported; null when not known. */
|
|
368080
|
+
operationState: DishwasherOperationStateSchema.nullable(),
|
|
368081
|
+
/** Feature key of the ACTIVE (running) program, or null when none runs / not known. */
|
|
367391
368082
|
program: zod.z.string().nullable(),
|
|
367392
|
-
/**
|
|
368083
|
+
/** Feature key of the SELECTED program (what Start would run), or null when none / not known. */
|
|
368084
|
+
selectedProgram: zod.z.string().nullable(),
|
|
368085
|
+
/** Feature keys of the programs the appliance currently offers — drives the UI selector. */
|
|
367393
368086
|
availablePrograms: zod.z.array(zod.z.string()),
|
|
367394
|
-
/**
|
|
367395
|
-
|
|
368087
|
+
/** Seconds remaining on the active cycle, or null when not running / not known. */
|
|
368088
|
+
remainingSeconds: zod.z.number().int().nonnegative().nullable(),
|
|
368089
|
+
/** Seconds the delayed start is set to (time until the cycle starts), or null. */
|
|
368090
|
+
delayedStartSeconds: zod.z.number().int().nonnegative().nullable(),
|
|
367396
368091
|
/** Cycle completion 0..100, or null when not applicable. */
|
|
367397
368092
|
progressPercent: zod.z.number().min(0).max(100).nullable(),
|
|
367398
|
-
/** True when the door is reported open. */
|
|
367399
|
-
doorOpen: zod.z.boolean(),
|
|
367400
|
-
/** True when
|
|
367401
|
-
|
|
367402
|
-
/**
|
|
367403
|
-
|
|
368093
|
+
/** True when the door is reported open; null when the door state is not known. */
|
|
368094
|
+
doorOpen: zod.z.boolean().nullable(),
|
|
368095
|
+
/** True when the door is latched (locked) during a cycle; null when not reported. */
|
|
368096
|
+
doorLocked: zod.z.boolean().nullable(),
|
|
368097
|
+
/** True when remote start is allowed (door closed, power on, etc.); null when not known. */
|
|
368098
|
+
remoteStartAllowed: zod.z.boolean().nullable(),
|
|
368099
|
+
/** True when the appliance accepts remote control now; null when not known. */
|
|
368100
|
+
remoteControlActive: zod.z.boolean().nullable(),
|
|
368101
|
+
/** True while somebody operates the appliance at its panel; null when not reported. */
|
|
368102
|
+
localControlActive: zod.z.boolean().nullable(),
|
|
368103
|
+
/** Main power / switched-on state; null when not known. */
|
|
368104
|
+
powerOn: zod.z.boolean().nullable(),
|
|
368105
|
+
/** The raw power state (`On`, `Off`, `Standby`, …); null when not known. */
|
|
368106
|
+
powerState: zod.z.string().nullable(),
|
|
367404
368107
|
saltLevel: DishwasherConsumableLevelSchema.nullable(),
|
|
367405
368108
|
rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
|
|
367406
|
-
|
|
367407
|
-
|
|
368109
|
+
/** Option states: null when the appliance does not expose the option or has not said. */
|
|
368110
|
+
halfLoad: zod.z.boolean().nullable(),
|
|
368111
|
+
hygienePlus: zod.z.boolean().nullable(),
|
|
368112
|
+
/** Extra dry option when the appliance exposes it. */
|
|
368113
|
+
extraDry: zod.z.boolean().nullable(),
|
|
368114
|
+
/** Intensive zone (lower basket) when the appliance exposes it. */
|
|
368115
|
+
intensiveZone: zod.z.boolean().nullable(),
|
|
368116
|
+
/** VarioSpeed / VarioSpeed+ when the appliance exposes it. */
|
|
368117
|
+
varioSpeedPlus: zod.z.boolean().nullable(),
|
|
368118
|
+
/** Child lock (controls disabled on the appliance); null when not known. */
|
|
368119
|
+
childLock: zod.z.boolean().nullable(),
|
|
368120
|
+
/** Feature keys of the events currently raised (salt low, rinse aid low, program finished, …). */
|
|
368121
|
+
activeEvents: zod.z.array(zod.z.string()),
|
|
368122
|
+
/** Numeric error code when the appliance reports one; null otherwise. */
|
|
367408
368123
|
errorCode: zod.z.number().nullable(),
|
|
368124
|
+
/** Name of the raised alert-level event while the appliance is in error; null otherwise. */
|
|
367409
368125
|
errorLabel: zod.z.string().nullable(),
|
|
368126
|
+
/** Ms epoch of the last value received from the appliance; 0 = never. */
|
|
367410
368127
|
lastFetchedAt: zod.z.number()
|
|
367411
368128
|
});
|
|
368129
|
+
var DeviceIdSchema = zod.z.number().int().nonnegative();
|
|
368130
|
+
var DishwasherValueSchema = zod.z.union([
|
|
368131
|
+
zod.z.boolean(),
|
|
368132
|
+
zod.z.string(),
|
|
368133
|
+
zod.z.number()
|
|
368134
|
+
]);
|
|
368135
|
+
var DishwasherAccessSchema = zod.z.enum([
|
|
368136
|
+
"none",
|
|
368137
|
+
"read",
|
|
368138
|
+
"readWrite",
|
|
368139
|
+
"writeOnly",
|
|
368140
|
+
"readStatic"
|
|
368141
|
+
]);
|
|
368142
|
+
var DishwasherOptionDescriptorSchema = zod.z.object({
|
|
368143
|
+
/** Feature key (`Dishcare.Dishwasher.Option.ExtraDry`). */
|
|
368144
|
+
key: zod.z.string(),
|
|
368145
|
+
/** Last segment of the key, for display. */
|
|
368146
|
+
name: zod.z.string(),
|
|
368147
|
+
type: zod.z.enum([
|
|
368148
|
+
"boolean",
|
|
368149
|
+
"number",
|
|
368150
|
+
"enum",
|
|
368151
|
+
"string"
|
|
368152
|
+
]),
|
|
368153
|
+
access: DishwasherAccessSchema,
|
|
368154
|
+
/** The appliance reports this entity as currently available. */
|
|
368155
|
+
available: zod.z.boolean(),
|
|
368156
|
+
/** Unit the description declares for a number; null when it declares none. */
|
|
368157
|
+
unit: zod.z.string().nullable(),
|
|
368158
|
+
min: zod.z.number().nullable(),
|
|
368159
|
+
max: zod.z.number().nullable(),
|
|
368160
|
+
step: zod.z.number().nullable(),
|
|
368161
|
+
/** Allowed members of an enum; null for other types. */
|
|
368162
|
+
enumValues: zod.z.array(zod.z.string()).nullable(),
|
|
368163
|
+
defaultValue: DishwasherValueSchema.nullable()
|
|
368164
|
+
});
|
|
368165
|
+
var DishwasherProgramSchema = zod.z.object({
|
|
368166
|
+
/** Feature key (`Dishcare.Dishwasher.Program.Eco50`) — what `setProgram` / `start` take. */
|
|
368167
|
+
key: zod.z.string(),
|
|
368168
|
+
name: zod.z.string(),
|
|
368169
|
+
/** The appliance currently offers this program. */
|
|
368170
|
+
available: zod.z.boolean(),
|
|
368171
|
+
/** The options this program lists, with the program-level access / availability / default. */
|
|
368172
|
+
options: zod.z.array(DishwasherOptionDescriptorSchema)
|
|
368173
|
+
});
|
|
368174
|
+
var DishwasherOptionsSchema = zod.z.object({
|
|
368175
|
+
availability: DishwasherAvailabilitySchema,
|
|
368176
|
+
/** What the appliance can be told to do, from the commands its description declares. */
|
|
368177
|
+
supportsStart: zod.z.boolean(),
|
|
368178
|
+
supportsPause: zod.z.boolean(),
|
|
368179
|
+
supportsResume: zod.z.boolean(),
|
|
368180
|
+
supportsStop: zod.z.boolean(),
|
|
368181
|
+
supportsPower: zod.z.boolean(),
|
|
368182
|
+
/** Every program the description lists, with its options. */
|
|
368183
|
+
programs: zod.z.array(DishwasherProgramSchema),
|
|
368184
|
+
/** Every option and setting entity the description lists (programs reference these by key). */
|
|
368185
|
+
options: zod.z.array(DishwasherOptionDescriptorSchema)
|
|
368186
|
+
});
|
|
367412
368187
|
var dishwasherCapability = {
|
|
367413
368188
|
name: "dishwasher",
|
|
367414
368189
|
scope: "device",
|
|
@@ -367416,58 +368191,102 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
367416
368191
|
mode: "singleton",
|
|
367417
368192
|
deviceTypes: [require_err_msg.DeviceType.Dishwasher],
|
|
367418
368193
|
methods: {
|
|
367419
|
-
|
|
368194
|
+
/**
|
|
368195
|
+
* Start a program. Without `program` the selected one starts. `options` are
|
|
368196
|
+
* option feature keys; each is checked against the program's constraints.
|
|
368197
|
+
*/
|
|
368198
|
+
start: require_sleep.method(zod.z.object({
|
|
368199
|
+
deviceId: DeviceIdSchema,
|
|
368200
|
+
program: zod.z.string().min(1).optional(),
|
|
368201
|
+
options: zod.z.record(zod.z.string(), DishwasherValueSchema).optional()
|
|
368202
|
+
}), zod.z.void(), {
|
|
367420
368203
|
kind: "mutation",
|
|
367421
368204
|
auth: "protected"
|
|
367422
368205
|
}),
|
|
367423
|
-
pause: require_sleep.method(zod.z.object({ deviceId:
|
|
368206
|
+
pause: require_sleep.method(zod.z.object({ deviceId: DeviceIdSchema }), zod.z.void(), {
|
|
367424
368207
|
kind: "mutation",
|
|
367425
368208
|
auth: "protected"
|
|
367426
368209
|
}),
|
|
367427
|
-
|
|
368210
|
+
resume: require_sleep.method(zod.z.object({ deviceId: DeviceIdSchema }), zod.z.void(), {
|
|
368211
|
+
kind: "mutation",
|
|
368212
|
+
auth: "protected"
|
|
368213
|
+
}),
|
|
368214
|
+
stop: require_sleep.method(zod.z.object({ deviceId: DeviceIdSchema }), zod.z.void(), {
|
|
367428
368215
|
kind: "mutation",
|
|
367429
368216
|
auth: "protected"
|
|
367430
368217
|
}),
|
|
368218
|
+
/** Select (not start) a program; refused when the appliance does not offer it. */
|
|
367431
368219
|
setProgram: require_sleep.method(zod.z.object({
|
|
367432
|
-
deviceId:
|
|
368220
|
+
deviceId: DeviceIdSchema,
|
|
367433
368221
|
program: zod.z.string().min(1)
|
|
367434
368222
|
}), zod.z.void(), {
|
|
367435
368223
|
kind: "mutation",
|
|
367436
368224
|
auth: "protected"
|
|
367437
368225
|
}),
|
|
367438
368226
|
setPower: require_sleep.method(zod.z.object({
|
|
367439
|
-
deviceId:
|
|
368227
|
+
deviceId: DeviceIdSchema,
|
|
367440
368228
|
on: zod.z.boolean()
|
|
367441
368229
|
}), zod.z.void(), {
|
|
367442
368230
|
kind: "mutation",
|
|
367443
368231
|
auth: "protected"
|
|
367444
368232
|
}),
|
|
367445
368233
|
setHalfLoad: require_sleep.method(zod.z.object({
|
|
367446
|
-
deviceId:
|
|
368234
|
+
deviceId: DeviceIdSchema,
|
|
367447
368235
|
on: zod.z.boolean()
|
|
367448
368236
|
}), zod.z.void(), {
|
|
367449
368237
|
kind: "mutation",
|
|
367450
368238
|
auth: "protected"
|
|
367451
368239
|
}),
|
|
367452
368240
|
setHygienePlus: require_sleep.method(zod.z.object({
|
|
367453
|
-
deviceId:
|
|
368241
|
+
deviceId: DeviceIdSchema,
|
|
368242
|
+
on: zod.z.boolean()
|
|
368243
|
+
}), zod.z.void(), {
|
|
368244
|
+
kind: "mutation",
|
|
368245
|
+
auth: "protected"
|
|
368246
|
+
}),
|
|
368247
|
+
setExtraDry: require_sleep.method(zod.z.object({
|
|
368248
|
+
deviceId: DeviceIdSchema,
|
|
367454
368249
|
on: zod.z.boolean()
|
|
367455
368250
|
}), zod.z.void(), {
|
|
367456
368251
|
kind: "mutation",
|
|
367457
368252
|
auth: "protected"
|
|
367458
368253
|
}),
|
|
368254
|
+
setIntensiveZone: require_sleep.method(zod.z.object({
|
|
368255
|
+
deviceId: DeviceIdSchema,
|
|
368256
|
+
on: zod.z.boolean()
|
|
368257
|
+
}), zod.z.void(), {
|
|
368258
|
+
kind: "mutation",
|
|
368259
|
+
auth: "protected"
|
|
368260
|
+
}),
|
|
368261
|
+
setVarioSpeedPlus: require_sleep.method(zod.z.object({
|
|
368262
|
+
deviceId: DeviceIdSchema,
|
|
368263
|
+
on: zod.z.boolean()
|
|
368264
|
+
}), zod.z.void(), {
|
|
368265
|
+
kind: "mutation",
|
|
368266
|
+
auth: "protected"
|
|
368267
|
+
}),
|
|
368268
|
+
setChildLock: require_sleep.method(zod.z.object({
|
|
368269
|
+
deviceId: DeviceIdSchema,
|
|
368270
|
+
on: zod.z.boolean()
|
|
368271
|
+
}), zod.z.void(), {
|
|
368272
|
+
kind: "mutation",
|
|
368273
|
+
auth: "protected"
|
|
368274
|
+
}),
|
|
368275
|
+
/**
|
|
368276
|
+
* Write any option or setting by feature key. Refused when the description does
|
|
368277
|
+
* not list it, it is not writable or not available now, or the value is outside
|
|
368278
|
+
* its declared range / members.
|
|
368279
|
+
*/
|
|
367459
368280
|
setOption: require_sleep.method(zod.z.object({
|
|
367460
|
-
deviceId:
|
|
368281
|
+
deviceId: DeviceIdSchema,
|
|
367461
368282
|
key: zod.z.string().min(1),
|
|
367462
|
-
value:
|
|
367463
|
-
zod.z.boolean(),
|
|
367464
|
-
zod.z.string(),
|
|
367465
|
-
zod.z.number()
|
|
367466
|
-
])
|
|
368283
|
+
value: DishwasherValueSchema
|
|
367467
368284
|
}), zod.z.void(), {
|
|
367468
368285
|
kind: "mutation",
|
|
367469
368286
|
auth: "protected"
|
|
367470
|
-
})
|
|
368287
|
+
}),
|
|
368288
|
+
/** What this appliance can do, from its own description — the UI is derived from it. */
|
|
368289
|
+
getOptions: require_sleep.method(zod.z.object({ deviceId: DeviceIdSchema }), DishwasherOptionsSchema, { auth: "protected" })
|
|
367471
368290
|
},
|
|
367472
368291
|
status: {
|
|
367473
368292
|
schema: DishwasherStatusSchema,
|
|
@@ -379588,6 +380407,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
379588
380407
|
"fan",
|
|
379589
380408
|
"vacuum",
|
|
379590
380409
|
"lawn-mower",
|
|
380410
|
+
"dishwasher",
|
|
379591
380411
|
"light",
|
|
379592
380412
|
"switch",
|
|
379593
380413
|
"siren",
|
|
@@ -382486,6 +383306,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
382486
383306
|
addonId: null,
|
|
382487
383307
|
access: "view"
|
|
382488
383308
|
},
|
|
383309
|
+
"dishwasher.getOptions": {
|
|
383310
|
+
capName: "dishwasher",
|
|
383311
|
+
capScope: "device",
|
|
383312
|
+
addonId: null,
|
|
383313
|
+
access: "view"
|
|
383314
|
+
},
|
|
382489
383315
|
"dishwasher.getStatus": {
|
|
382490
383316
|
capName: "dishwasher",
|
|
382491
383317
|
capScope: "device",
|
|
@@ -382498,6 +383324,24 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
382498
383324
|
addonId: null,
|
|
382499
383325
|
access: "create"
|
|
382500
383326
|
},
|
|
383327
|
+
"dishwasher.resume": {
|
|
383328
|
+
capName: "dishwasher",
|
|
383329
|
+
capScope: "device",
|
|
383330
|
+
addonId: null,
|
|
383331
|
+
access: "create"
|
|
383332
|
+
},
|
|
383333
|
+
"dishwasher.setChildLock": {
|
|
383334
|
+
capName: "dishwasher",
|
|
383335
|
+
capScope: "device",
|
|
383336
|
+
addonId: null,
|
|
383337
|
+
access: "create"
|
|
383338
|
+
},
|
|
383339
|
+
"dishwasher.setExtraDry": {
|
|
383340
|
+
capName: "dishwasher",
|
|
383341
|
+
capScope: "device",
|
|
383342
|
+
addonId: null,
|
|
383343
|
+
access: "create"
|
|
383344
|
+
},
|
|
382501
383345
|
"dishwasher.setHalfLoad": {
|
|
382502
383346
|
capName: "dishwasher",
|
|
382503
383347
|
capScope: "device",
|
|
@@ -382510,6 +383354,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
382510
383354
|
addonId: null,
|
|
382511
383355
|
access: "create"
|
|
382512
383356
|
},
|
|
383357
|
+
"dishwasher.setIntensiveZone": {
|
|
383358
|
+
capName: "dishwasher",
|
|
383359
|
+
capScope: "device",
|
|
383360
|
+
addonId: null,
|
|
383361
|
+
access: "create"
|
|
383362
|
+
},
|
|
382513
383363
|
"dishwasher.setOption": {
|
|
382514
383364
|
capName: "dishwasher",
|
|
382515
383365
|
capScope: "device",
|
|
@@ -382528,6 +383378,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
382528
383378
|
addonId: null,
|
|
382529
383379
|
access: "create"
|
|
382530
383380
|
},
|
|
383381
|
+
"dishwasher.setVarioSpeedPlus": {
|
|
383382
|
+
capName: "dishwasher",
|
|
383383
|
+
capScope: "device",
|
|
383384
|
+
addonId: null,
|
|
383385
|
+
access: "create"
|
|
383386
|
+
},
|
|
382531
383387
|
"dishwasher.start": {
|
|
382532
383388
|
capName: "dishwasher",
|
|
382533
383389
|
capScope: "device",
|
|
@@ -386974,6 +387830,12 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
386974
387830
|
addonId: null,
|
|
386975
387831
|
access: "view"
|
|
386976
387832
|
},
|
|
387833
|
+
"storageMigration.moverClearance": {
|
|
387834
|
+
capName: "storage-migration",
|
|
387835
|
+
capScope: "system",
|
|
387836
|
+
addonId: null,
|
|
387837
|
+
access: "view"
|
|
387838
|
+
},
|
|
386977
387839
|
"storageMigration.movers": {
|
|
386978
387840
|
capName: "storage-migration",
|
|
386979
387841
|
capScope: "system",
|
|
@@ -392322,6 +393184,11 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
392322
393184
|
form: "single",
|
|
392323
393185
|
optional: false
|
|
392324
393186
|
}],
|
|
393187
|
+
"dishwasher.getOptions": [{
|
|
393188
|
+
name: "deviceId",
|
|
393189
|
+
form: "single",
|
|
393190
|
+
optional: false
|
|
393191
|
+
}],
|
|
392325
393192
|
"dishwasher.getStatus": [{
|
|
392326
393193
|
name: "deviceId",
|
|
392327
393194
|
form: "single",
|
|
@@ -392332,6 +393199,21 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
392332
393199
|
form: "single",
|
|
392333
393200
|
optional: false
|
|
392334
393201
|
}],
|
|
393202
|
+
"dishwasher.resume": [{
|
|
393203
|
+
name: "deviceId",
|
|
393204
|
+
form: "single",
|
|
393205
|
+
optional: false
|
|
393206
|
+
}],
|
|
393207
|
+
"dishwasher.setChildLock": [{
|
|
393208
|
+
name: "deviceId",
|
|
393209
|
+
form: "single",
|
|
393210
|
+
optional: false
|
|
393211
|
+
}],
|
|
393212
|
+
"dishwasher.setExtraDry": [{
|
|
393213
|
+
name: "deviceId",
|
|
393214
|
+
form: "single",
|
|
393215
|
+
optional: false
|
|
393216
|
+
}],
|
|
392335
393217
|
"dishwasher.setHalfLoad": [{
|
|
392336
393218
|
name: "deviceId",
|
|
392337
393219
|
form: "single",
|
|
@@ -392342,6 +393224,11 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
392342
393224
|
form: "single",
|
|
392343
393225
|
optional: false
|
|
392344
393226
|
}],
|
|
393227
|
+
"dishwasher.setIntensiveZone": [{
|
|
393228
|
+
name: "deviceId",
|
|
393229
|
+
form: "single",
|
|
393230
|
+
optional: false
|
|
393231
|
+
}],
|
|
392345
393232
|
"dishwasher.setOption": [{
|
|
392346
393233
|
name: "deviceId",
|
|
392347
393234
|
form: "single",
|
|
@@ -392357,6 +393244,11 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
392357
393244
|
form: "single",
|
|
392358
393245
|
optional: false
|
|
392359
393246
|
}],
|
|
393247
|
+
"dishwasher.setVarioSpeedPlus": [{
|
|
393248
|
+
name: "deviceId",
|
|
393249
|
+
form: "single",
|
|
393250
|
+
optional: false
|
|
393251
|
+
}],
|
|
392360
393252
|
"dishwasher.start": [{
|
|
392361
393253
|
name: "deviceId",
|
|
392362
393254
|
form: "single",
|
|
@@ -395946,6 +396838,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
395946
396838
|
status: (input) => dispatch("storageMigration", "status", "query", input),
|
|
395947
396839
|
cancel: (input) => dispatch("storageMigration", "cancel", "mutation", input),
|
|
395948
396840
|
movers: (input) => dispatch("storageMigration", "movers", "query", input),
|
|
396841
|
+
moverClearance: (input) => dispatch("storageMigration", "moverClearance", "query", input),
|
|
395949
396842
|
residue: (input) => dispatch("storageMigration", "residue", "query", input),
|
|
395950
396843
|
drain: (input) => dispatch("storageMigration", "drain", "mutation", input),
|
|
395951
396844
|
cleanupStart: (input) => dispatch("storageMigration", "cleanupStart", "mutation", input),
|
|
@@ -396483,7 +397376,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
396483
397376
|
case "deviceTypes":
|
|
396484
397377
|
return kind.startsWith("device-") || kind === "detection-blind";
|
|
396485
397378
|
case "nodeIds":
|
|
396486
|
-
return kind.startsWith("node-") || kind === "addon-crash-loop" || kind === "addon-update-available" || kind === "addon-updated" || kind === "server-update-available" || kind === "wrapper-update-available" || kind === "server-updated" || kind.startsWith("storage-location-");
|
|
397379
|
+
return kind.startsWith("node-") || kind === "addon-crash-loop" || kind === "addon-update-available" || kind === "addon-updated" || kind === "server-update-available" || kind === "wrapper-update-available" || kind === "server-updated" || kind.startsWith("storage-location-") || kind.startsWith("alert-");
|
|
396487
397380
|
case "packageNames":
|
|
396488
397381
|
return kind.endsWith("update-available") || kind === "addon-updated" || kind === "node-updating" || kind === "server-updated";
|
|
396489
397382
|
case "consumableLowPercent":
|
|
@@ -396532,6 +397425,9 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
396532
397425
|
"wrapper-update-available": "system",
|
|
396533
397426
|
"backup-completed": "system",
|
|
396534
397427
|
"export-completed": "system",
|
|
397428
|
+
"alert-critical": "system",
|
|
397429
|
+
"alert-error": "system",
|
|
397430
|
+
"alert-critical-resolved": "system",
|
|
396535
397431
|
"storage-location-low": "system",
|
|
396536
397432
|
"storage-location-critical": "system",
|
|
396537
397433
|
"storage-location-ok": "system",
|
|
@@ -396667,6 +397563,16 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
396667
397563
|
"storage-location-ok"
|
|
396668
397564
|
]
|
|
396669
397565
|
},
|
|
397566
|
+
{
|
|
397567
|
+
id: "alerts",
|
|
397568
|
+
family: "system",
|
|
397569
|
+
label: "Alerts",
|
|
397570
|
+
kinds: [
|
|
397571
|
+
"alert-critical",
|
|
397572
|
+
"alert-error",
|
|
397573
|
+
"alert-critical-resolved"
|
|
397574
|
+
]
|
|
397575
|
+
},
|
|
396670
397576
|
{
|
|
396671
397577
|
id: "alarm",
|
|
396672
397578
|
family: "alarm",
|
|
@@ -397739,6 +398645,69 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
397739
398645
|
return sensorKinds.every((kind) => NC_SENSOR_TRANSITION_KINDS.includes(normaliseKind(kind)));
|
|
397740
398646
|
}
|
|
397741
398647
|
var NC_SENSOR_TRANSITION_UNSUPPORTED_REASON = "Only a sensor that raises and clears (water, smoke, gas, CO, vibration, tamper, motion, contact) can fire on one edge. Pick only such sensor kinds, or the rule fires on every change.";
|
|
398648
|
+
var AlertEpisodePayloadSchema = zod.z.object({
|
|
398649
|
+
phase: zod.z.enum(["raised", "resolved"]),
|
|
398650
|
+
episodeId: zod.z.string().min(1),
|
|
398651
|
+
alertId: zod.z.string().min(1),
|
|
398652
|
+
severity: AlertSeveritySchema,
|
|
398653
|
+
category: zod.z.string(),
|
|
398654
|
+
title: zod.z.string(),
|
|
398655
|
+
message: zod.z.string(),
|
|
398656
|
+
sourceType: zod.z.string().optional(),
|
|
398657
|
+
sourceId: zod.z.string().optional(),
|
|
398658
|
+
nodeId: zod.z.string().optional(),
|
|
398659
|
+
/** The alert's own action link (where the operator acts on it), when it has one. */
|
|
398660
|
+
actionUrl: zod.z.string().optional(),
|
|
398661
|
+
at: zod.z.number()
|
|
398662
|
+
});
|
|
398663
|
+
function parseAlertEpisodePayload(data) {
|
|
398664
|
+
const parsed = AlertEpisodePayloadSchema.safeParse(data);
|
|
398665
|
+
return parsed.success ? parsed.data : null;
|
|
398666
|
+
}
|
|
398667
|
+
function isAlertEpisodeOpen(status) {
|
|
398668
|
+
return status !== "completed" && status !== "dismissed";
|
|
398669
|
+
}
|
|
398670
|
+
function isAlertEpisodeSeverity(severity) {
|
|
398671
|
+
return severity === "critical" || severity === "error";
|
|
398672
|
+
}
|
|
398673
|
+
function alertEpisodeId(alert) {
|
|
398674
|
+
const minted = alert.metadata?.["episodeId"];
|
|
398675
|
+
return typeof minted === "string" && minted.length > 0 ? minted : `${alert.id}@${String(alert.createdAt)}`;
|
|
398676
|
+
}
|
|
398677
|
+
function alertNodeId(alert) {
|
|
398678
|
+
const direct = alert.metadata?.["nodeId"];
|
|
398679
|
+
if (typeof direct === "string") return direct;
|
|
398680
|
+
const runner = alert.metadata?.["runner"];
|
|
398681
|
+
if (typeof runner === "object" && runner !== null && "nodeId" in runner) {
|
|
398682
|
+
const id = runner.nodeId;
|
|
398683
|
+
if (typeof id === "string") return id;
|
|
398684
|
+
}
|
|
398685
|
+
return alert.source?.type === "node" ? alert.source.id : void 0;
|
|
398686
|
+
}
|
|
398687
|
+
function alertEpisodeKind(severity, phase) {
|
|
398688
|
+
if (severity === "critical") return phase === "raised" ? "alert-critical" : "alert-critical-resolved";
|
|
398689
|
+
if (severity === "error" && phase === "raised") return "alert-error";
|
|
398690
|
+
return null;
|
|
398691
|
+
}
|
|
398692
|
+
function alertEpisodePayload(alert, phase, at) {
|
|
398693
|
+
const nodeId = alertNodeId(alert);
|
|
398694
|
+
return {
|
|
398695
|
+
phase,
|
|
398696
|
+
episodeId: alertEpisodeId(alert),
|
|
398697
|
+
alertId: alert.id,
|
|
398698
|
+
severity: alert.severity,
|
|
398699
|
+
category: alert.category,
|
|
398700
|
+
title: alert.title,
|
|
398701
|
+
message: alert.message,
|
|
398702
|
+
...alert.source !== void 0 ? {
|
|
398703
|
+
sourceType: alert.source.type,
|
|
398704
|
+
sourceId: alert.source.id
|
|
398705
|
+
} : {},
|
|
398706
|
+
...nodeId !== void 0 ? { nodeId } : {},
|
|
398707
|
+
...alert.action?.href !== void 0 ? { actionUrl: alert.action.href } : {},
|
|
398708
|
+
at
|
|
398709
|
+
};
|
|
398710
|
+
}
|
|
397742
398711
|
var RULE_BODY_ONLY = ["body"];
|
|
397743
398712
|
var RULE_TEXT = ["title", "body"];
|
|
397744
398713
|
var BATTERY = ["device-battery-low", "device-battery-normal"];
|
|
@@ -397748,6 +398717,11 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
397748
398717
|
"device-tank-full",
|
|
397749
398718
|
"device-tank-normal"
|
|
397750
398719
|
];
|
|
398720
|
+
var ALERT_EPISODE = [
|
|
398721
|
+
"alert-critical",
|
|
398722
|
+
"alert-error",
|
|
398723
|
+
"alert-critical-resolved"
|
|
398724
|
+
];
|
|
397751
398725
|
var UPDATES = [
|
|
397752
398726
|
"addon-update-available",
|
|
397753
398727
|
"server-update-available",
|
|
@@ -398269,7 +399243,8 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
398269
399243
|
"server-updated",
|
|
398270
399244
|
"storage-location-low",
|
|
398271
399245
|
"storage-location-critical",
|
|
398272
|
-
"storage-location-ok"
|
|
399246
|
+
"storage-location-ok",
|
|
399247
|
+
...ALERT_EPISODE
|
|
398273
399248
|
]
|
|
398274
399249
|
},
|
|
398275
399250
|
{
|
|
@@ -398291,7 +399266,8 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
398291
399266
|
"server-updated",
|
|
398292
399267
|
"storage-location-low",
|
|
398293
399268
|
"storage-location-critical",
|
|
398294
|
-
"storage-location-ok"
|
|
399269
|
+
"storage-location-ok",
|
|
399270
|
+
...ALERT_EPISODE
|
|
398295
399271
|
]
|
|
398296
399272
|
},
|
|
398297
399273
|
{
|
|
@@ -398358,7 +399334,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
398358
399334
|
families: ["rule"],
|
|
398359
399335
|
fields: [...RULE_TEXT],
|
|
398360
399336
|
kinds: ["system"],
|
|
398361
|
-
systemEventKinds: ["recording-degraded"]
|
|
399337
|
+
systemEventKinds: ["recording-degraded", ...ALERT_EPISODE]
|
|
398362
399338
|
},
|
|
398363
399339
|
{
|
|
398364
399340
|
name: "locationName",
|
|
@@ -398555,13 +399531,53 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
398555
399531
|
},
|
|
398556
399532
|
{
|
|
398557
399533
|
name: "title",
|
|
398558
|
-
label: "Export title",
|
|
399534
|
+
label: "Export or alert title",
|
|
398559
399535
|
example: "Ingresso 08:00",
|
|
398560
399536
|
group: "system",
|
|
398561
399537
|
families: ["rule"],
|
|
398562
399538
|
fields: [...RULE_TEXT],
|
|
398563
399539
|
kinds: ["system"],
|
|
398564
|
-
systemEventKinds: ["export-completed"]
|
|
399540
|
+
systemEventKinds: ["export-completed", ...ALERT_EPISODE]
|
|
399541
|
+
},
|
|
399542
|
+
{
|
|
399543
|
+
name: "severity",
|
|
399544
|
+
label: "Alert severity",
|
|
399545
|
+
example: "critical",
|
|
399546
|
+
group: "system",
|
|
399547
|
+
families: ["rule"],
|
|
399548
|
+
fields: [...RULE_TEXT],
|
|
399549
|
+
kinds: ["system"],
|
|
399550
|
+
systemEventKinds: [...ALERT_EPISODE]
|
|
399551
|
+
},
|
|
399552
|
+
{
|
|
399553
|
+
name: "category",
|
|
399554
|
+
label: "Alert category",
|
|
399555
|
+
example: "addon.runner-failed",
|
|
399556
|
+
group: "system",
|
|
399557
|
+
families: ["rule"],
|
|
399558
|
+
fields: [...RULE_TEXT],
|
|
399559
|
+
kinds: ["system"],
|
|
399560
|
+
systemEventKinds: [...ALERT_EPISODE]
|
|
399561
|
+
},
|
|
399562
|
+
{
|
|
399563
|
+
name: "source",
|
|
399564
|
+
label: "Alert source (addon, node or runner)",
|
|
399565
|
+
example: "recorder",
|
|
399566
|
+
group: "system",
|
|
399567
|
+
families: ["rule"],
|
|
399568
|
+
fields: [...RULE_TEXT],
|
|
399569
|
+
kinds: ["system"],
|
|
399570
|
+
systemEventKinds: [...ALERT_EPISODE]
|
|
399571
|
+
},
|
|
399572
|
+
{
|
|
399573
|
+
name: "actionUrl",
|
|
399574
|
+
label: "Alert action link",
|
|
399575
|
+
example: "/system/addons",
|
|
399576
|
+
group: "system",
|
|
399577
|
+
families: ["rule"],
|
|
399578
|
+
fields: [...RULE_TEXT],
|
|
399579
|
+
kinds: ["system"],
|
|
399580
|
+
systemEventKinds: [...ALERT_EPISODE]
|
|
398565
399581
|
},
|
|
398566
399582
|
{
|
|
398567
399583
|
name: "exportId",
|
|
@@ -398757,7 +399773,10 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
398757
399773
|
"device-tank-full",
|
|
398758
399774
|
"device-tank-normal",
|
|
398759
399775
|
"node-restarting",
|
|
398760
|
-
"node-updating"
|
|
399776
|
+
"node-updating",
|
|
399777
|
+
"alert-critical",
|
|
399778
|
+
"alert-error",
|
|
399779
|
+
"alert-critical-resolved"
|
|
398761
399780
|
];
|
|
398762
399781
|
function servedTemplateVars() {
|
|
398763
399782
|
return NC_TEMPLATE_VARS.filter((d) => !isHeldBackTemplateVar(d)).map((d) => d.systemEventKinds === void 0 ? d : {
|
|
@@ -401958,6 +402977,52 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
401958
402977
|
}
|
|
401959
402978
|
current[parts[parts.length - 1]] = value;
|
|
401960
402979
|
}
|
|
402980
|
+
var OAUTH_LANDING_PATH = "/sso-complete";
|
|
402981
|
+
var OAUTH_LANDING_REASONS = [
|
|
402982
|
+
"access_denied",
|
|
402983
|
+
"invalid_state",
|
|
402984
|
+
"invalid_request",
|
|
402985
|
+
"unknown_broker",
|
|
402986
|
+
"not_configured",
|
|
402987
|
+
"exchange_failed",
|
|
402988
|
+
"no_refresh_token",
|
|
402989
|
+
"unavailable",
|
|
402990
|
+
"unknown"
|
|
402991
|
+
];
|
|
402992
|
+
function isOauthLandingReason(value) {
|
|
402993
|
+
return OAUTH_LANDING_REASONS.some((reason) => reason === value);
|
|
402994
|
+
}
|
|
402995
|
+
function oauthLandingUrl(origin, outcome) {
|
|
402996
|
+
const params = new URLSearchParams({
|
|
402997
|
+
return: "oauth",
|
|
402998
|
+
status: outcome.status
|
|
402999
|
+
});
|
|
403000
|
+
if (outcome.addonId !== void 0) params.set("addon", outcome.addonId);
|
|
403001
|
+
if (outcome.brokerId !== void 0) params.set("broker", outcome.brokerId);
|
|
403002
|
+
if (outcome.integration !== void 0) params.set("integration", outcome.integration);
|
|
403003
|
+
if (outcome.status === "error") params.set("reason", outcome.reason ?? "unknown");
|
|
403004
|
+
if (outcome.action === "disconnect") params.set("action", "disconnect");
|
|
403005
|
+
return `${origin === null ? "" : origin.replace(/\/+$/, "")}${OAUTH_LANDING_PATH}#${params.toString()}`;
|
|
403006
|
+
}
|
|
403007
|
+
function parseOauthLandingFragment(hash) {
|
|
403008
|
+
if (!hash.startsWith("#")) return null;
|
|
403009
|
+
const params = new URLSearchParams(hash.slice(1));
|
|
403010
|
+
if (params.get("return") !== "oauth") return null;
|
|
403011
|
+
const status = params.get("status");
|
|
403012
|
+
if (status !== "success" && status !== "error") return null;
|
|
403013
|
+
const addonId = params.get("addon");
|
|
403014
|
+
const brokerId = params.get("broker");
|
|
403015
|
+
const integration = params.get("integration");
|
|
403016
|
+
const reasonRaw = params.get("reason");
|
|
403017
|
+
return {
|
|
403018
|
+
status,
|
|
403019
|
+
...addonId !== null && addonId.length > 0 ? { addonId } : {},
|
|
403020
|
+
...brokerId !== null && brokerId.length > 0 ? { brokerId } : {},
|
|
403021
|
+
...integration !== null && integration.length > 0 ? { integration } : {},
|
|
403022
|
+
...status === "error" ? { reason: isOauthLandingReason(reasonRaw) ? reasonRaw : "unknown" } : {},
|
|
403023
|
+
...params.get("action") === "disconnect" ? { action: "disconnect" } : {}
|
|
403024
|
+
};
|
|
403025
|
+
}
|
|
401961
403026
|
var MB = 1024 * 1024;
|
|
401962
403027
|
var DEFAULT_POOL_MEMORY_POLICY = {
|
|
401963
403028
|
sampleIntervalMs: 6e4,
|
|
@@ -402810,6 +403875,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
402810
403875
|
exports.AlarmArmModeSchema = AlarmArmModeSchema;
|
|
402811
403876
|
exports.AlarmPanelStatusSchema = AlarmPanelStatusSchema;
|
|
402812
403877
|
exports.AlarmStateSchema = AlarmStateSchema;
|
|
403878
|
+
exports.AlertEpisodePayloadSchema = AlertEpisodePayloadSchema;
|
|
402813
403879
|
exports.AlertSchema = AlertSchema;
|
|
402814
403880
|
exports.AlertSeveritySchema = AlertSeveritySchema;
|
|
402815
403881
|
exports.AlertSourceSchema = AlertSourceSchema;
|
|
@@ -403288,9 +404354,16 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
403288
404354
|
exports.DiscoveredChildStatusSchema = DiscoveredChildStatusSchema;
|
|
403289
404355
|
exports.DiscoveredDeviceSchema = DiscoveredDeviceSchema;
|
|
403290
404356
|
exports.DiscoveredTargetSchema = DiscoveredTargetSchema;
|
|
404357
|
+
exports.DishwasherAccessSchema = DishwasherAccessSchema;
|
|
404358
|
+
exports.DishwasherAvailabilitySchema = DishwasherAvailabilitySchema;
|
|
403291
404359
|
exports.DishwasherConsumableLevelSchema = DishwasherConsumableLevelSchema;
|
|
404360
|
+
exports.DishwasherOperationStateSchema = DishwasherOperationStateSchema;
|
|
404361
|
+
exports.DishwasherOptionDescriptorSchema = DishwasherOptionDescriptorSchema;
|
|
404362
|
+
exports.DishwasherOptionsSchema = DishwasherOptionsSchema;
|
|
404363
|
+
exports.DishwasherProgramSchema = DishwasherProgramSchema;
|
|
403292
404364
|
exports.DishwasherStateSchema = DishwasherStateSchema;
|
|
403293
404365
|
exports.DishwasherStatusSchema = DishwasherStatusSchema;
|
|
404366
|
+
exports.DishwasherValueSchema = DishwasherValueSchema;
|
|
403294
404367
|
exports.DiskReconcileJobSchema = DiskReconcileJobSchema;
|
|
403295
404368
|
exports.DisposerChain = require_sleep.DisposerChain;
|
|
403296
404369
|
exports.DoorbellPressEventSchema = DoorbellPressEventSchema;
|
|
@@ -403958,6 +405031,8 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
403958
405031
|
exports.NotificationSchema = NotificationSchema;
|
|
403959
405032
|
exports.NotifierStatusSchema = NotifierStatusSchema;
|
|
403960
405033
|
exports.NumericSensorStatusSchema = NumericSensorStatusSchema;
|
|
405034
|
+
exports.OAUTH_LANDING_PATH = OAUTH_LANDING_PATH;
|
|
405035
|
+
exports.OAUTH_LANDING_REASONS = OAUTH_LANDING_REASONS;
|
|
403961
405036
|
exports.OPERATOR_WRITTEN_STALE_MS = OPERATOR_WRITTEN_STALE_MS;
|
|
403962
405037
|
exports.OPS_LOG_DEFAULT_LIMIT = OPS_LOG_DEFAULT_LIMIT;
|
|
403963
405038
|
exports.OPS_LOG_RING_DEFAULT_MAX = OPS_LOG_RING_DEFAULT_MAX;
|
|
@@ -404638,6 +405713,10 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
404638
405713
|
exports.alarmPanelCapability = alarmPanelCapability;
|
|
404639
405714
|
exports.alarmPatchLanded = alarmPatchLanded;
|
|
404640
405715
|
exports.alarmProfileById = alarmProfileById;
|
|
405716
|
+
exports.alertEpisodeId = alertEpisodeId;
|
|
405717
|
+
exports.alertEpisodeKind = alertEpisodeKind;
|
|
405718
|
+
exports.alertEpisodePayload = alertEpisodePayload;
|
|
405719
|
+
exports.alertNodeId = alertNodeId;
|
|
404641
405720
|
exports.alertsCapability = alertsCapability;
|
|
404642
405721
|
exports.allDoActions = allDoActions;
|
|
404643
405722
|
exports.allowedSuppliedEffect = allowedSuppliedEffect;
|
|
@@ -404994,6 +406073,8 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
404994
406073
|
exports.invocationFromEncodeProfile = require_composition.invocationFromEncodeProfile;
|
|
404995
406074
|
exports.isAgentOnlyPlacement = isAgentOnlyPlacement;
|
|
404996
406075
|
exports.isAlarmControllableCap = isAlarmControllableCap;
|
|
406076
|
+
exports.isAlertEpisodeOpen = isAlertEpisodeOpen;
|
|
406077
|
+
exports.isAlertEpisodeSeverity = isAlertEpisodeSeverity;
|
|
404997
406078
|
exports.isAppLinkBase = isAppLinkBase;
|
|
404998
406079
|
exports.isAppStartRefusal = isAppStartRefusal;
|
|
404999
406080
|
exports.isArrayOutputSchema = isArrayOutputSchema;
|
|
@@ -405029,6 +406110,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
405029
406110
|
exports.isLocationEnabled = isLocationEnabled;
|
|
405030
406111
|
exports.isMediaOwnerType = isMediaOwnerType;
|
|
405031
406112
|
exports.isNode = isNode;
|
|
406113
|
+
exports.isOauthLandingReason = isOauthLandingReason;
|
|
405032
406114
|
exports.isObjectInput = isObjectInput;
|
|
405033
406115
|
exports.isOccupancyRule = isOccupancyRule;
|
|
405034
406116
|
exports.isOwnerOnlyEventCategory = require_event_category.isOwnerOnlyEventCategory;
|
|
@@ -405152,6 +406234,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
405152
406234
|
exports.notifierCapability = notifierCapability;
|
|
405153
406235
|
exports.numericSensorCapability = numericSensorCapability;
|
|
405154
406236
|
exports.oauthIntegrationCapability = oauthIntegrationCapability;
|
|
406237
|
+
exports.oauthLandingUrl = oauthLandingUrl;
|
|
405155
406238
|
exports.objectInputDeclaresAddonId = objectInputDeclaresAddonId;
|
|
405156
406239
|
exports.objectInputDeclaresRequiredDeviceId = objectInputDeclaresRequiredDeviceId;
|
|
405157
406240
|
exports.occupancyScope = occupancyScope;
|
|
@@ -405164,6 +406247,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
405164
406247
|
exports.overlayClusterStepSettings = overlayClusterStepSettings;
|
|
405165
406248
|
exports.packagePickerItems = packagePickerItems;
|
|
405166
406249
|
exports.parseAdminBase = parseAdminBase;
|
|
406250
|
+
exports.parseAlertEpisodePayload = parseAlertEpisodePayload;
|
|
405167
406251
|
exports.parseAppAuthCallback = parseAppAuthCallback;
|
|
405168
406252
|
exports.parseAppFlowRequest = parseAppFlowRequest;
|
|
405169
406253
|
exports.parseAppPageLang = parseAppPageLang;
|
|
@@ -405174,6 +406258,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
405174
406258
|
exports.parseJsonObject = require_sleep.parseJsonObject;
|
|
405175
406259
|
exports.parseJsonUnknown = require_sleep.parseJsonUnknown;
|
|
405176
406260
|
exports.parseMediaOwnerKey = parseMediaOwnerKey;
|
|
406261
|
+
exports.parseOauthLandingFragment = parseOauthLandingFragment;
|
|
405177
406262
|
exports.parseOccupancyScope = parseOccupancyScope;
|
|
405178
406263
|
exports.parseProcStatus = parseProcStatus;
|
|
405179
406264
|
exports.parseProfileBrokerId = require_sleep.parseProfileBrokerId;
|
|
@@ -405376,6 +406461,7 @@ ${recipe.triggers.map((t, i) => emitTrigger(t, i)).join("\n\n")}
|
|
|
405376
406461
|
exports.snapshotCapability = snapshotCapability;
|
|
405377
406462
|
exports.splitTranslationRef = splitTranslationRef;
|
|
405378
406463
|
exports.ssoBridgeCapability = ssoBridgeCapability;
|
|
406464
|
+
exports.startMoverUnderClearance = startMoverUnderClearance;
|
|
405379
406465
|
exports.startReachabilityPoll = startReachabilityPoll;
|
|
405380
406466
|
exports.stateLabel = stateLabel;
|
|
405381
406467
|
exports.stateVocabularyFor = stateVocabularyFor;
|
|
@@ -571574,6 +572660,10 @@ var require_app_page_shell = __commonJS({
|
|
|
571574
572660
|
`.error:empty{display:none}`,
|
|
571575
572661
|
`.btn:focus-visible,.link:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px}`,
|
|
571576
572662
|
`code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;overflow-wrap:anywhere}`,
|
|
572663
|
+
`.field{display:flex;flex-direction:column;gap:var(--spacing-md)}`,
|
|
572664
|
+
`.field label{font-size:12px;line-height:16px;font-weight:500;color:var(--color-foreground-muted)}`,
|
|
572665
|
+
`input[type=url],input[type=text]{width:100%;min-height:44px;padding:10px 12px;border:1px solid var(--color-border);border-radius:var(--radius-lg);background:var(--color-background);color:var(--color-foreground);font:inherit}`,
|
|
572666
|
+
`input[type=url]:focus-visible,input[type=text]:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px}`,
|
|
571577
572667
|
`form{display:contents}`,
|
|
571578
572668
|
`.actions{display:flex;flex-direction:column;gap:var(--spacing-md)}`
|
|
571579
572669
|
].join("");
|
|
@@ -571717,6 +572807,7 @@ var require_oauth2_routes = __commonJS({
|
|
|
571717
572807
|
exports.isRedirectUriAllowed = isRedirectUriAllowed;
|
|
571718
572808
|
exports.summariseScopes = summariseScopes;
|
|
571719
572809
|
exports.registerOauth2Routes = registerOauth2Routes;
|
|
572810
|
+
var types_1 = require_dist4();
|
|
571720
572811
|
var session_cookie_js_1 = require_session_cookie();
|
|
571721
572812
|
var app_page_strings_js_1 = require_app_page_strings();
|
|
571722
572813
|
var consent_page_js_1 = require_consent_page();
|
|
@@ -571863,7 +572954,7 @@ var require_oauth2_routes = __commonJS({
|
|
|
571863
572954
|
}
|
|
571864
572955
|
return scopes.map((s) => s.type).join(", ") || "no permissions";
|
|
571865
572956
|
}
|
|
571866
|
-
function refuseAuthorize(reply, logger, method, call, refusal) {
|
|
572957
|
+
function refuseAuthorize(request, reply, logger, method, call, refusal) {
|
|
571867
572958
|
logger.warn(`oauth2 authorize refused: ${refusal.error}`, {
|
|
571868
572959
|
meta: {
|
|
571869
572960
|
method,
|
|
@@ -571876,7 +572967,18 @@ var require_oauth2_routes = __commonJS({
|
|
|
571876
572967
|
if (refusal.retryAfterSec !== void 0) {
|
|
571877
572968
|
void reply.header("Retry-After", String(refusal.retryAfterSec));
|
|
571878
572969
|
}
|
|
571879
|
-
return reply
|
|
572970
|
+
return answerRefusal(request, reply, refusal.status, { error: refusal.error, ...refusal.detail }, refusal.status === 503 ? "unavailable" : "invalid_request", typeof refusal.detail?.received === "string" ? refusal.detail.received : void 0);
|
|
572971
|
+
}
|
|
572972
|
+
function answerRefusal(request, reply, status, body, reason, integration) {
|
|
572973
|
+
const accept = request.headers.accept;
|
|
572974
|
+
if (typeof accept === "string" && accept.includes("text/html")) {
|
|
572975
|
+
return reply.redirect((0, types_1.oauthLandingUrl)(null, {
|
|
572976
|
+
status: "error",
|
|
572977
|
+
reason,
|
|
572978
|
+
...integration !== void 0 && /^[A-Za-z0-9._-]{1,64}$/.test(integration) ? { integration } : {}
|
|
572979
|
+
}));
|
|
572980
|
+
}
|
|
572981
|
+
return reply.status(status).send(body);
|
|
571880
572982
|
}
|
|
571881
572983
|
function refuseUnauthenticated(request, reply, logger, call, reason) {
|
|
571882
572984
|
const redirected = (0, session_cookie_js_1.shouldRedirectToLogin)(request.method, request.headers.accept);
|
|
@@ -571925,13 +573027,13 @@ var require_oauth2_routes = __commonJS({
|
|
|
571925
573027
|
}
|
|
571926
573028
|
const registry = deps.getRegistry();
|
|
571927
573029
|
if (!registry) {
|
|
571928
|
-
return reply
|
|
573030
|
+
return answerRefusal(request, reply, 503, { error: "service_unavailable" }, "unavailable");
|
|
571929
573031
|
}
|
|
571930
573032
|
const { descriptors, pendingAddons } = await readIntegrationRegistry(registry);
|
|
571931
573033
|
const query = request.query;
|
|
571932
573034
|
const v = validateAuthorizeQuery(query, descriptors, pendingAddons);
|
|
571933
573035
|
if (!v.ok) {
|
|
571934
|
-
return refuseAuthorize(reply, deps.logger, "GET", call, v);
|
|
573036
|
+
return refuseAuthorize(request, reply, deps.logger, "GET", call, v);
|
|
571935
573037
|
}
|
|
571936
573038
|
const descriptor = descriptors.get(v.integration);
|
|
571937
573039
|
if (!isRedirectUriAllowed(v.redirectUri, descriptor.allowedRedirectPrefixes, descriptor.allowedPrivateHostPaths ?? [])) {
|
|
@@ -571945,7 +573047,7 @@ var require_oauth2_routes = __commonJS({
|
|
|
571945
573047
|
allowedPrivateHostPaths: descriptor.allowedPrivateHostPaths ?? []
|
|
571946
573048
|
}
|
|
571947
573049
|
});
|
|
571948
|
-
return reply
|
|
573050
|
+
return answerRefusal(request, reply, 400, { error: "invalid_request \u2014 redirect_uri not allowed for this integration" }, "invalid_request", v.integration);
|
|
571949
573051
|
}
|
|
571950
573052
|
const html = (0, consent_page_js_1.renderConsentPage)({
|
|
571951
573053
|
lang: (0, app_page_strings_js_1.resolveAppPageLang)({
|
|
@@ -572002,7 +573104,7 @@ var require_oauth2_routes = __commonJS({
|
|
|
572002
573104
|
}
|
|
572003
573105
|
const registry = deps.getRegistry();
|
|
572004
573106
|
if (!registry) {
|
|
572005
|
-
return reply
|
|
573107
|
+
return answerRefusal(request, reply, 503, { error: "service_unavailable" }, "unavailable");
|
|
572006
573108
|
}
|
|
572007
573109
|
const { descriptors, pendingAddons } = await readIntegrationRegistry(registry);
|
|
572008
573110
|
const body = request.body;
|
|
@@ -572016,7 +573118,7 @@ var require_oauth2_routes = __commonJS({
|
|
|
572016
573118
|
};
|
|
572017
573119
|
const v = validateAuthorizeQuery(formQuery, descriptors, pendingAddons);
|
|
572018
573120
|
if (!v.ok) {
|
|
572019
|
-
return refuseAuthorize(reply, deps.logger, "POST", call, v);
|
|
573121
|
+
return refuseAuthorize(request, reply, deps.logger, "POST", call, v);
|
|
572020
573122
|
}
|
|
572021
573123
|
const descriptor = descriptors.get(v.integration);
|
|
572022
573124
|
if (!isRedirectUriAllowed(v.redirectUri, descriptor.allowedRedirectPrefixes, descriptor.allowedPrivateHostPaths ?? [])) {
|
|
@@ -572030,7 +573132,7 @@ var require_oauth2_routes = __commonJS({
|
|
|
572030
573132
|
allowedPrivateHostPaths: descriptor.allowedPrivateHostPaths ?? []
|
|
572031
573133
|
}
|
|
572032
573134
|
});
|
|
572033
|
-
return reply
|
|
573135
|
+
return answerRefusal(request, reply, 400, { error: "invalid_request \u2014 redirect_uri not allowed for this integration" }, "invalid_request", v.integration);
|
|
572034
573136
|
}
|
|
572035
573137
|
if (body.consent !== "allow") {
|
|
572036
573138
|
return reply.redirect(`${v.redirectUri}?error=access_denied&state=${encodeURIComponent(v.state)}`);
|
|
@@ -581597,6 +582699,40 @@ var require_cap_router_runtime = __commonJS({
|
|
|
581597
582699
|
iterableSubscription: trpc_middleware_js_1.iterableSubscription
|
|
581598
582700
|
};
|
|
581599
582701
|
}
|
|
582702
|
+
async function inferDeviceAdoptionCollectionAddonPin(methodName, input, deps) {
|
|
582703
|
+
const integrationId = typeof input.integrationId === "string" && input.integrationId.length > 0 ? input.integrationId : void 0;
|
|
582704
|
+
const camDeviceId = typeof input.camDeviceId === "number" && Number.isInteger(input.camDeviceId) ? input.camDeviceId : void 0;
|
|
582705
|
+
if (methodName === "resync" || camDeviceId !== void 0 && integrationId === void 0) {
|
|
582706
|
+
if (camDeviceId === void 0) {
|
|
582707
|
+
throw new server_1.TRPCError({
|
|
582708
|
+
code: "BAD_REQUEST",
|
|
582709
|
+
message: "deviceAdoption.resync requires camDeviceId (owning addon is resolved from it) or an explicit addonId pin."
|
|
582710
|
+
});
|
|
582711
|
+
}
|
|
582712
|
+
const resolved = deps.resolveDeviceAddonId ? await Promise.resolve(deps.resolveDeviceAddonId(camDeviceId)) : null;
|
|
582713
|
+
if (resolved === null || resolved === "") {
|
|
582714
|
+
throw new server_1.TRPCError({
|
|
582715
|
+
code: "BAD_REQUEST",
|
|
582716
|
+
message: `deviceAdoption.${methodName}: device ${camDeviceId} not found \u2014 pass addonId explicitly.`
|
|
582717
|
+
});
|
|
582718
|
+
}
|
|
582719
|
+
return resolved;
|
|
582720
|
+
}
|
|
582721
|
+
if (integrationId !== void 0) {
|
|
582722
|
+
const resolved = deps.resolveIntegrationAddonId ? await Promise.resolve(deps.resolveIntegrationAddonId(integrationId)) : null;
|
|
582723
|
+
if (resolved === null || resolved === "") {
|
|
582724
|
+
throw new server_1.TRPCError({
|
|
582725
|
+
code: "BAD_REQUEST",
|
|
582726
|
+
message: `deviceAdoption.${methodName}: unknown integrationId "${integrationId}" \u2014 pass addonId explicitly.`
|
|
582727
|
+
});
|
|
582728
|
+
}
|
|
582729
|
+
return resolved;
|
|
582730
|
+
}
|
|
582731
|
+
throw new server_1.TRPCError({
|
|
582732
|
+
code: "BAD_REQUEST",
|
|
582733
|
+
message: `deviceAdoption.${methodName} requires addonId (top-level pin) or integrationId to resolve the owning provider.`
|
|
582734
|
+
});
|
|
582735
|
+
}
|
|
581600
582736
|
function createCapRouterServices(deps) {
|
|
581601
582737
|
const reg = deps.capabilityRegistry;
|
|
581602
582738
|
const remoteProxy = (capName, nodeId) => deps.moleculer.createCapabilityProxy(capName, nodeId);
|
|
@@ -581645,10 +582781,16 @@ var require_cap_router_runtime = __commonJS({
|
|
|
581645
582781
|
message: `Capability "${capName}" has no provider with addonId "${addonId}". Valid addonId(s): ${known.join(", ")}. An unresolvable addonId is refused rather than answered by another provider.`
|
|
581646
582782
|
});
|
|
581647
582783
|
};
|
|
582784
|
+
const inferCollectionAddonPin = (capName, methodName, methodInput) => {
|
|
582785
|
+
if (capName !== "device-adoption")
|
|
582786
|
+
return void 0;
|
|
582787
|
+
return inferDeviceAdoptionCollectionAddonPin(methodName, methodInput, deps);
|
|
582788
|
+
};
|
|
581648
582789
|
return {
|
|
581649
582790
|
getLocalProvider,
|
|
581650
582791
|
remoteProxy,
|
|
581651
582792
|
rejectUnresolvedAddonPin,
|
|
582793
|
+
inferCollectionAddonPin,
|
|
581652
582794
|
noProvider: (capName, nodeId) => {
|
|
581653
582795
|
if (nodeId !== void 0 && nodeId !== "hub") {
|
|
581654
582796
|
throw new server_1.TRPCError({
|
|
@@ -581846,11 +582988,18 @@ var require_trpc_router = __commonJS({
|
|
|
581846
582988
|
};
|
|
581847
582989
|
}
|
|
581848
582990
|
function buildCapabilityRouters(services) {
|
|
582991
|
+
const integrationRegistry = services.addonRegistry.getIntegrationRegistry();
|
|
582992
|
+
const deviceRegistry = services.addonRegistry.getDeviceRegistry();
|
|
581849
582993
|
const dynamicCaps = (0, cap_router_runtime_js_1.buildRuntimeCapRouters)({
|
|
581850
582994
|
capabilityRegistry: services.capabilityRegistry,
|
|
581851
582995
|
moleculer: services.moleculer,
|
|
581852
582996
|
serverProviders: buildServerProviders(services),
|
|
581853
|
-
logger: services.loggingService.createLogger("cap-router")
|
|
582997
|
+
logger: services.loggingService.createLogger("cap-router"),
|
|
582998
|
+
resolveIntegrationAddonId: integrationRegistry ? async (integrationId) => {
|
|
582999
|
+
const row = await integrationRegistry.getIntegration(integrationId);
|
|
583000
|
+
return row?.addonId ?? null;
|
|
583001
|
+
} : void 0,
|
|
583002
|
+
resolveDeviceAddonId: (camDeviceId) => deviceRegistry.getAddonId(camDeviceId)
|
|
581854
583003
|
});
|
|
581855
583004
|
return {
|
|
581856
583005
|
// ── Runtime-built cap routers: EVERY cap whose mount is
|
|
@@ -583353,6 +584502,28 @@ var require_addon_process_view = __commonJS({
|
|
|
583353
584502
|
}
|
|
583354
584503
|
});
|
|
583355
584504
|
|
|
584505
|
+
// ../../server/backend/dist/core/addon/hub-addon-api.js
|
|
584506
|
+
var require_hub_addon_api = __commonJS({
|
|
584507
|
+
"../../server/backend/dist/core/addon/hub-addon-api.js"(exports) {
|
|
584508
|
+
"use strict";
|
|
584509
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
584510
|
+
exports.createHubAddonApi = createHubAddonApi;
|
|
584511
|
+
var client_1 = require_dist2();
|
|
584512
|
+
var system_1 = require_dist3();
|
|
584513
|
+
function createHubAddonApi(options) {
|
|
584514
|
+
const observerOpts = {
|
|
584515
|
+
callerAddonId: options.callerAddonId,
|
|
584516
|
+
providerAddonIdForCap: () => null,
|
|
584517
|
+
observer: () => void 0
|
|
584518
|
+
};
|
|
584519
|
+
const client = (0, client_1.createTRPCClient)({
|
|
584520
|
+
links: [(0, system_1.localProviderLink)(options.resolver, observerOpts), ...options.links]
|
|
584521
|
+
});
|
|
584522
|
+
return client;
|
|
584523
|
+
}
|
|
584524
|
+
}
|
|
584525
|
+
});
|
|
584526
|
+
|
|
583356
584527
|
// ../../server/backend/dist/core/addon/addon-call-gateway.js
|
|
583357
584528
|
var require_addon_call_gateway = __commonJS({
|
|
583358
584529
|
"../../server/backend/dist/core/addon/addon-call-gateway.js"(exports) {
|
|
@@ -584199,6 +585370,7 @@ var require_addon_registry_service = __commonJS({
|
|
|
584199
585370
|
var system_1 = require_dist3();
|
|
584200
585371
|
var types_1 = require_dist4();
|
|
584201
585372
|
var client_1 = require_dist2();
|
|
585373
|
+
var hub_addon_api_js_1 = require_hub_addon_api();
|
|
584202
585374
|
var addon_call_gateway_js_1 = require_addon_call_gateway();
|
|
584203
585375
|
var addon_row_manifest_1 = require_addon_row_manifest();
|
|
584204
585376
|
var addon_settings_provider_js_1 = require_addon_settings_provider();
|
|
@@ -584409,29 +585581,41 @@ var require_addon_registry_service = __commonJS({
|
|
|
584409
585581
|
*/
|
|
584410
585582
|
getBrokerApi() {
|
|
584411
585583
|
if (!this.brokerApi) {
|
|
584412
|
-
|
|
584413
|
-
const resolver = {
|
|
584414
|
-
getByName: (capName) => reg.getSingleton(capName) ?? reg.getAllProviders(capName)[0] ?? null
|
|
584415
|
-
};
|
|
584416
|
-
const client = (0, client_1.createTRPCClient)({
|
|
584417
|
-
links: [
|
|
584418
|
-
(0, system_1.localProviderLink)(resolver),
|
|
584419
|
-
// Device-scoped caps go through the hub's CapRouteResolver, which is
|
|
584420
|
-
// the only authority that can route `(cap, deviceId)` into a FORKED
|
|
584421
|
-
// child — and forked children are broker-less, so the Moleculer
|
|
584422
|
-
// lookup below cannot see them at all. Without this an in-process
|
|
584423
|
-
// addon asking `ptz.getOptions({deviceId})` got
|
|
584424
|
-
// `Service 'ptz.ptz.getOptions' is not found`, which is how the
|
|
584425
|
-
// autotrack builtin came up switched on and unable to move a camera
|
|
584426
|
-
// (2026-09-18).
|
|
584427
|
-
(0, system_1.deviceCapResolverLink)((capName, method, input) => this.moleculer.callCapabilityOnNode(this.moleculer.broker.nodeID, capName, method, input), isDeviceScopedCapName),
|
|
584428
|
-
(0, system_1.brokerTransportLink)(this.moleculer.broker)
|
|
584429
|
-
]
|
|
584430
|
-
});
|
|
584431
|
-
this.brokerApi = client;
|
|
585584
|
+
this.brokerApi = this.buildBrokerApi(void 0);
|
|
584432
585585
|
}
|
|
584433
585586
|
return this.brokerApi;
|
|
584434
585587
|
}
|
|
585588
|
+
/**
|
|
585589
|
+
* The `ctx.api` of one in-process addon. Same chain as {@link getBrokerApi},
|
|
585590
|
+
* but its `localProviderLink` knows WHO is calling, so a caller-stamped cap
|
|
585591
|
+
* (`device-history`, keychain, records) can identify the addon. A shared
|
|
585592
|
+
* client cannot: `metrics-native` was refused `declareSeries` ("the caller
|
|
585593
|
+
* addon could not be identified") on every sample.
|
|
585594
|
+
*/
|
|
585595
|
+
getAddonApi(addonId) {
|
|
585596
|
+
const cached = this.addonApis.get(addonId);
|
|
585597
|
+
if (cached)
|
|
585598
|
+
return cached;
|
|
585599
|
+
const api = this.buildBrokerApi(addonId);
|
|
585600
|
+
this.addonApis.set(addonId, api);
|
|
585601
|
+
return api;
|
|
585602
|
+
}
|
|
585603
|
+
addonApis = /* @__PURE__ */ new Map();
|
|
585604
|
+
buildBrokerApi(callerAddonId) {
|
|
585605
|
+
const reg = this.capabilityRegistry;
|
|
585606
|
+
const resolver = {
|
|
585607
|
+
getByName: (capName) => reg.getSingleton(capName) ?? reg.getAllProviders(capName)[0] ?? null
|
|
585608
|
+
};
|
|
585609
|
+
const links = [
|
|
585610
|
+
(0, system_1.deviceCapResolverLink)((capName, method, input) => this.moleculer.callCapabilityOnNode(this.moleculer.broker.nodeID, capName, method, input), isDeviceScopedCapName),
|
|
585611
|
+
(0, system_1.brokerTransportLink)(this.moleculer.broker)
|
|
585612
|
+
];
|
|
585613
|
+
if (callerAddonId !== void 0) {
|
|
585614
|
+
return (0, hub_addon_api_js_1.createHubAddonApi)({ resolver, callerAddonId, links });
|
|
585615
|
+
}
|
|
585616
|
+
const client = (0, client_1.createTRPCClient)({ links: [(0, system_1.localProviderLink)(resolver), ...links] });
|
|
585617
|
+
return client;
|
|
585618
|
+
}
|
|
584435
585619
|
// Common settings resolver (3-level: defaults → global → per-device).
|
|
584436
585620
|
// Lazily constructed on first call to `getSettingsResolver()` so tests
|
|
584437
585621
|
// that don't exercise the settings API can instantiate the service
|
|
@@ -586418,7 +587602,7 @@ var require_addon_registry_service = __commonJS({
|
|
|
586418
587602
|
dataPlane: dataPlaneFacility.dataPlane,
|
|
586419
587603
|
peerBytes: peerBytesFacility.peerBytes,
|
|
586420
587604
|
get api() {
|
|
586421
|
-
return registry.
|
|
587605
|
+
return registry.getAddonApi(addonId);
|
|
586422
587606
|
},
|
|
586423
587607
|
integrationRegistry: this.integrationRegistry ?? void 0,
|
|
586424
587608
|
// Live capability-collection accessor used by addons like stream-broker
|
|
@@ -591935,7 +593119,7 @@ var require_manual_boot = __commonJS({
|
|
|
591935
593119
|
throw new Error("the process service did not answer");
|
|
591936
593120
|
return rows;
|
|
591937
593121
|
},
|
|
591938
|
-
// The verdict reaches the alert centre (one
|
|
593122
|
+
// The verdict reaches the alert centre (one critical alert).
|
|
591939
593123
|
onResult: (check) => {
|
|
591940
593124
|
eventBusService.emit({
|
|
591941
593125
|
id: (0, node_crypto_1.randomUUID)(),
|