@camstack/addon-model-studio 1.1.321 → 1.1.323

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.
Files changed (19) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/{MotionZonesSettings-Bb_BJah5.mjs → MotionZonesSettings-CBVJdmZ_.mjs} +2 -2
  3. package/dist/{PrivacyMaskSettings-kCHid95c.mjs → PrivacyMaskSettings-CFuZa1xW.mjs} +4 -4
  4. package/dist/{SceneMonitorEditor-BqNgh047.mjs → SceneMonitorEditor-DHYl0WUF.mjs} +3 -3
  5. package/dist/_stub.js +1298 -1264
  6. package/dist/{_virtual_mf-localSharedImportMap___mfe_internal__addon_model_studio_page-_UWN0dyv.mjs → _virtual_mf-localSharedImportMap___mfe_internal__addon_model_studio_page-DiTB72W6.mjs} +3 -3
  7. package/dist/_virtual_mf___mfe_internal__addon_model_studio_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-B3TmOWWR.mjs +26 -0
  8. package/dist/{hostInit-DuXRhYzb.mjs → hostInit-BL6ZxXXr.mjs} +2 -2
  9. package/dist/model-studio.addon.js +584 -67
  10. package/dist/model-studio.addon.mjs +584 -67
  11. package/dist/{player-overlays-CNVhS2-N.mjs → player-overlays-CDEmtjZg.mjs} +1 -1
  12. package/dist/remoteEntry.js +1 -1
  13. package/dist/{responsive-oPhme86z.mjs → responsive-B_pKmFhb.mjs} +1 -1
  14. package/dist/{scene-monitor-copy-Ct1WyOQx.mjs → scene-monitor-copy-KV9Ti6_0.mjs} +1 -1
  15. package/dist/{square-WmNfgZ5W.mjs → square-ByW1TPIi.mjs} +1 -1
  16. package/dist/{trash-2-BUJwssR_.mjs → trash-2-9gFkA-Zu.mjs} +1 -1
  17. package/dist/{virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_model_studio_page__remoteEntry_js-CYL3AKrE.mjs → virtual_mf-REMOTE_ENTRY_ID___mfe_internal__addon_model_studio_page__remoteEntry_js-B880BvK0.mjs} +1 -1
  18. package/package.json +1 -1
  19. package/dist/_virtual_mf___mfe_internal__addon_model_studio_page__loadShare___mf_0_camstack_mf_1_types__loadShare__.js-DF4vj9Lw.mjs +0 -26
@@ -16042,6 +16042,478 @@ object({
16042
16042
  path: ["expr"]
16043
16043
  });
16044
16044
  });
16045
+ /**
16046
+ * Identity envelope for a device's upstream-system metadata.
16047
+ *
16048
+ * Two jobs:
16049
+ *
16050
+ * 1. **Dispatch key.** `id` is the natural identifier the SOURCE system
16051
+ * uses to address this device (HA `entity_id`, Reolink MAC, ONVIF
16052
+ * WS-Discovery endpoint UUID, …). Provider code keeps a
16053
+ * `Map<sourceInfo.id, IDevice>` to route inbound push events in O(1)
16054
+ * without round-tripping through `stableId` / `id` mappings.
16055
+ *
16056
+ * 2. **Stability bridge.** `uniqueId` is the *immutable* upstream id when
16057
+ * one exists (HA `entity.unique_id`, Reolink MAC again — same as `id`
16058
+ * for vendors where MAC is the natural key). For systems where the
16059
+ * live dispatch key can be renamed (HA `entity_id` can be edited),
16060
+ * providers detect renames by matching `uniqueId` and patch `id`
16061
+ * in-place so dispatch keeps working.
16062
+ *
16063
+ * **Display unit and precision are NOT stored here.** They are a read-time
16064
+ * preference (D944). A polymorphic reading stores its `quantity` here once,
16065
+ * at adopt, and a date/time value stores `dateTimeShape` the same way —
16066
+ * neither is repeated on each sample. The `device_class` tag is an
16067
+ * HA-specific input consumed at the discovery boundary (`ha-domain-mapping`)
16068
+ * to derive the CamStack `DeviceRole`; it is never stored after that point.
16069
+ *
16070
+ * The `raw` escape hatch carries provider-specific attributes that don't
16071
+ * fit the structured slots (HA `attributes` whitelist, Reolink `deviceCache`
16072
+ * details, …). Providers control what lands here.
16073
+ */
16074
+ var SourceInfoSchema = object({
16075
+ /** Live dispatch key — mutable when the source system allows rename. */
16076
+ id: string(),
16077
+ /** Source system tag — e.g. 'homeassistant' | 'reolink' | 'onvif'. */
16078
+ system: string(),
16079
+ /** Immutable upstream identifier when available (HA `unique_id`, … ).
16080
+ * Used to detect rename when `id` changes. */
16081
+ uniqueId: string().optional(),
16082
+ /** Quantity of a polymorphic reading, written once at adopt (D944). */
16083
+ quantity: ReadingQuantitySchema.optional(),
16084
+ /** Date / time / datetime shape of a string reading, written once at adopt. */
16085
+ dateTimeShape: _enum([
16086
+ "date",
16087
+ "time",
16088
+ "datetime"
16089
+ ]).optional(),
16090
+ /** Provider-specific extras that don't fit the structured slots.
16091
+ * Whitelist what goes here per provider — do NOT dump entire HA
16092
+ * attribute blobs (would explode the meta JSON column). */
16093
+ raw: record(string(), unknown()).optional()
16094
+ });
16095
+ /**
16096
+ * Frozen unit → spec table. `•` in the doc marks each dimension's canonical
16097
+ * unit (`factor: 1, offset: 0`). °F derives from `°C = (°F − 32) × 5/9` ⇒
16098
+ * `factor = 5/9`, `offset = -160/9` (kept as exact expressions, not rounded
16099
+ * decimals). K derives from `°C = K − 273.15`.
16100
+ */
16101
+ var UNIT_TABLE = {
16102
+ "°C": {
16103
+ dimension: "temperature",
16104
+ factor: 1,
16105
+ offset: 0
16106
+ },
16107
+ "°F": {
16108
+ dimension: "temperature",
16109
+ factor: 5 / 9,
16110
+ offset: -160 / 9
16111
+ },
16112
+ K: {
16113
+ dimension: "temperature",
16114
+ factor: 1,
16115
+ offset: -273.15
16116
+ },
16117
+ hPa: {
16118
+ dimension: "pressure",
16119
+ factor: 1,
16120
+ offset: 0
16121
+ },
16122
+ kPa: {
16123
+ dimension: "pressure",
16124
+ factor: 10,
16125
+ offset: 0
16126
+ },
16127
+ Pa: {
16128
+ dimension: "pressure",
16129
+ factor: .01,
16130
+ offset: 0
16131
+ },
16132
+ mbar: {
16133
+ dimension: "pressure",
16134
+ factor: 1,
16135
+ offset: 0
16136
+ },
16137
+ bar: {
16138
+ dimension: "pressure",
16139
+ factor: 1e3,
16140
+ offset: 0
16141
+ },
16142
+ inHg: {
16143
+ dimension: "pressure",
16144
+ factor: 33.8639,
16145
+ offset: 0
16146
+ },
16147
+ mmHg: {
16148
+ dimension: "pressure",
16149
+ factor: 1.33322,
16150
+ offset: 0
16151
+ },
16152
+ psi: {
16153
+ dimension: "pressure",
16154
+ factor: 68.9476,
16155
+ offset: 0
16156
+ },
16157
+ "m/s": {
16158
+ dimension: "speed",
16159
+ factor: 1,
16160
+ offset: 0
16161
+ },
16162
+ "km/h": {
16163
+ dimension: "speed",
16164
+ factor: 1 / 3.6,
16165
+ offset: 0
16166
+ },
16167
+ mph: {
16168
+ dimension: "speed",
16169
+ factor: .44704,
16170
+ offset: 0
16171
+ },
16172
+ kn: {
16173
+ dimension: "speed",
16174
+ factor: .514444,
16175
+ offset: 0
16176
+ },
16177
+ "mm/h": {
16178
+ dimension: "precipitation-rate",
16179
+ factor: 1,
16180
+ offset: 0
16181
+ },
16182
+ "in/h": {
16183
+ dimension: "precipitation-rate",
16184
+ factor: 25.4,
16185
+ offset: 0
16186
+ },
16187
+ m: {
16188
+ dimension: "length",
16189
+ factor: 1,
16190
+ offset: 0
16191
+ },
16192
+ mm: {
16193
+ dimension: "length",
16194
+ factor: .001,
16195
+ offset: 0
16196
+ },
16197
+ cm: {
16198
+ dimension: "length",
16199
+ factor: .01,
16200
+ offset: 0
16201
+ },
16202
+ km: {
16203
+ dimension: "length",
16204
+ factor: 1e3,
16205
+ offset: 0
16206
+ },
16207
+ in: {
16208
+ dimension: "length",
16209
+ factor: .0254,
16210
+ offset: 0
16211
+ },
16212
+ ft: {
16213
+ dimension: "length",
16214
+ factor: .3048,
16215
+ offset: 0
16216
+ },
16217
+ mi: {
16218
+ dimension: "length",
16219
+ factor: 1609.344,
16220
+ offset: 0
16221
+ },
16222
+ "m²": {
16223
+ dimension: "area",
16224
+ factor: 1,
16225
+ offset: 0
16226
+ },
16227
+ lx: {
16228
+ dimension: "illuminance",
16229
+ factor: 1,
16230
+ offset: 0
16231
+ },
16232
+ "W/m²": {
16233
+ dimension: "irradiance",
16234
+ factor: 1,
16235
+ offset: 0
16236
+ },
16237
+ W: {
16238
+ dimension: "power",
16239
+ factor: 1,
16240
+ offset: 0
16241
+ },
16242
+ kW: {
16243
+ dimension: "power",
16244
+ factor: 1e3,
16245
+ offset: 0
16246
+ },
16247
+ VA: {
16248
+ dimension: "apparent-power",
16249
+ factor: 1,
16250
+ offset: 0
16251
+ },
16252
+ Wh: {
16253
+ dimension: "energy",
16254
+ factor: 1,
16255
+ offset: 0
16256
+ },
16257
+ kWh: {
16258
+ dimension: "energy",
16259
+ factor: 1e3,
16260
+ offset: 0
16261
+ },
16262
+ MWh: {
16263
+ dimension: "energy",
16264
+ factor: 1e6,
16265
+ offset: 0
16266
+ },
16267
+ V: {
16268
+ dimension: "voltage",
16269
+ factor: 1,
16270
+ offset: 0
16271
+ },
16272
+ mV: {
16273
+ dimension: "voltage",
16274
+ factor: .001,
16275
+ offset: 0
16276
+ },
16277
+ A: {
16278
+ dimension: "current",
16279
+ factor: 1,
16280
+ offset: 0
16281
+ },
16282
+ mA: {
16283
+ dimension: "current",
16284
+ factor: .001,
16285
+ offset: 0
16286
+ },
16287
+ ppm: {
16288
+ dimension: "concentration-volume",
16289
+ factor: 1,
16290
+ offset: 0
16291
+ },
16292
+ ppb: {
16293
+ dimension: "concentration-volume",
16294
+ factor: .001,
16295
+ offset: 0
16296
+ },
16297
+ "µg/m³": {
16298
+ dimension: "concentration-mass",
16299
+ factor: 1,
16300
+ offset: 0
16301
+ },
16302
+ "mg/m³": {
16303
+ dimension: "concentration-mass",
16304
+ factor: 1e3,
16305
+ offset: 0
16306
+ },
16307
+ kg: {
16308
+ dimension: "mass",
16309
+ factor: 1,
16310
+ offset: 0
16311
+ },
16312
+ g: {
16313
+ dimension: "mass",
16314
+ factor: .001,
16315
+ offset: 0
16316
+ },
16317
+ lb: {
16318
+ dimension: "mass",
16319
+ factor: .453592,
16320
+ offset: 0
16321
+ },
16322
+ oz: {
16323
+ dimension: "mass",
16324
+ factor: .0283495,
16325
+ offset: 0
16326
+ },
16327
+ "%": {
16328
+ dimension: "percentage",
16329
+ factor: 1,
16330
+ offset: 0
16331
+ },
16332
+ L: {
16333
+ dimension: "volume",
16334
+ factor: 1,
16335
+ offset: 0
16336
+ },
16337
+ mL: {
16338
+ dimension: "volume",
16339
+ factor: .001,
16340
+ offset: 0
16341
+ },
16342
+ gal: {
16343
+ dimension: "volume",
16344
+ factor: 3.785411784,
16345
+ offset: 0
16346
+ },
16347
+ s: {
16348
+ dimension: "duration",
16349
+ factor: 1,
16350
+ offset: 0
16351
+ },
16352
+ ms: {
16353
+ dimension: "duration",
16354
+ factor: .001,
16355
+ offset: 0
16356
+ },
16357
+ min: {
16358
+ dimension: "duration",
16359
+ factor: 60,
16360
+ offset: 0
16361
+ },
16362
+ h: {
16363
+ dimension: "duration",
16364
+ factor: 3600,
16365
+ offset: 0
16366
+ },
16367
+ d: {
16368
+ dimension: "duration",
16369
+ factor: 86400,
16370
+ offset: 0
16371
+ },
16372
+ B: {
16373
+ dimension: "information",
16374
+ factor: 1,
16375
+ offset: 0
16376
+ },
16377
+ KiB: {
16378
+ dimension: "information",
16379
+ factor: 1024,
16380
+ offset: 0
16381
+ },
16382
+ MiB: {
16383
+ dimension: "information",
16384
+ factor: 1024 ** 2,
16385
+ offset: 0
16386
+ },
16387
+ GiB: {
16388
+ dimension: "information",
16389
+ factor: 1024 ** 3,
16390
+ offset: 0
16391
+ },
16392
+ TiB: {
16393
+ dimension: "information",
16394
+ factor: 1024 ** 4,
16395
+ offset: 0
16396
+ },
16397
+ kB: {
16398
+ dimension: "information",
16399
+ factor: 1e3,
16400
+ offset: 0
16401
+ },
16402
+ MB: {
16403
+ dimension: "information",
16404
+ factor: 1e6,
16405
+ offset: 0
16406
+ },
16407
+ GB: {
16408
+ dimension: "information",
16409
+ factor: 1e9,
16410
+ offset: 0
16411
+ },
16412
+ "°": {
16413
+ dimension: "angle",
16414
+ factor: 1,
16415
+ offset: 0
16416
+ },
16417
+ dBFS: {
16418
+ dimension: "sound-level",
16419
+ factor: 1,
16420
+ offset: 0
16421
+ },
16422
+ dBm: {
16423
+ dimension: "signal-level",
16424
+ factor: 1,
16425
+ offset: 0
16426
+ },
16427
+ mired: {
16428
+ dimension: "colour-temperature",
16429
+ factor: 1,
16430
+ offset: 0
16431
+ },
16432
+ kbps: {
16433
+ dimension: "bitrate",
16434
+ factor: 1,
16435
+ offset: 0
16436
+ },
16437
+ Mbps: {
16438
+ dimension: "bitrate",
16439
+ factor: 1e3,
16440
+ offset: 0
16441
+ },
16442
+ fps: {
16443
+ dimension: "rate",
16444
+ factor: 1,
16445
+ offset: 0
16446
+ }
16447
+ };
16448
+ /** Resolve a unit's `UnitSpec`, or `undefined` when the spelling is unknown. */
16449
+ function specFor(unit) {
16450
+ return Object.hasOwn(UNIT_TABLE, unit) ? UNIT_TABLE[unit] : void 0;
16451
+ }
16452
+ /** Value in `spec`'s unit → its dimension's canonical unit. */
16453
+ function toCanonical(value, spec) {
16454
+ return value * spec.factor + spec.offset;
16455
+ }
16456
+ /** Canonical-unit value → the unit described by `spec`. */
16457
+ function fromCanonical(canonical, spec) {
16458
+ return (canonical - spec.offset) / spec.factor;
16459
+ }
16460
+ /**
16461
+ * Graceful variant for the render path: returns the converted value, or
16462
+ * `undefined` when the conversion is refused (unknown unit / cross-dimension).
16463
+ * Never throws — a render caller falls back to the raw value + source unit.
16464
+ */
16465
+ function tryConvertUnit(value, from, to) {
16466
+ if (from === to) return value;
16467
+ const fromSpec = specFor(from);
16468
+ if (!fromSpec) return void 0;
16469
+ const toSpec = specFor(to);
16470
+ if (!toSpec) return void 0;
16471
+ if (fromSpec.dimension !== toSpec.dimension) return void 0;
16472
+ return fromCanonical(toCanonical(value, fromSpec), toSpec);
16473
+ }
16474
+ /**
16475
+ * A number a person types for a physical quantity — the input side of the
16476
+ * value + unit contract (D972).
16477
+ *
16478
+ * Readings are stored in the base unit of their quantity (D944); a cap method
16479
+ * param is stored in the unit its input schema DECLARES (`paramMeta`). The
16480
+ * wire pair {@link QuantityValue} says "this number is expressed in this
16481
+ * unit"; {@link convertQuantityInput} brings it to the stored unit and refuses,
16482
+ * with a typed {@link QuantityUnitError}, a unit that cannot be that quantity.
16483
+ */
16484
+ /** A unit that cannot be applied to the number it was given with. */
16485
+ var QuantityUnitError = class extends Error {
16486
+ code;
16487
+ constructor(code, message) {
16488
+ super(`[${code}] ${message}`);
16489
+ this.name = "QuantityUnitError";
16490
+ this.code = code;
16491
+ }
16492
+ };
16493
+ /** The wire pair: `value` is expressed in `unit`. */
16494
+ var QuantityValueSchema = object({
16495
+ value: number(),
16496
+ unit: string().min(1)
16497
+ });
16498
+ /**
16499
+ * Zod `.meta()` bag for a cap METHOD param that is a physical quantity — the
16500
+ * input-side twin of `readingMeta`. The value is carried in `unit` (a gram
16501
+ * portion stays in grams); the unit must belong to the quantity, checked once
16502
+ * when the cap is declared.
16503
+ */
16504
+ function paramMeta(declared) {
16505
+ const base = baseUnitOf(declared.quantity);
16506
+ if (base === void 0) throw new QuantityUnitError("unknown-unit", `quantity "${declared.quantity}" has no unit`);
16507
+ if (tryConvertUnit(1, declared.unit, base) === void 0) throw new QuantityUnitError("cross-dimension", `"${declared.unit}" is not a unit of ${declared.quantity}`);
16508
+ return {
16509
+ quantity: declared.quantity,
16510
+ unit: declared.unit
16511
+ };
16512
+ }
16513
+ object({
16514
+ quantity: ReadingQuantitySchema,
16515
+ unit: string().min(1)
16516
+ });
16045
16517
  /** How a leaf compares a device field to a value. Derived from the field's
16046
16518
  * `kind` in `deviceManager.getWireableFields`, never hand-maintained. */
16047
16519
  var AutomationConditionOperatorSchema = _enum([
@@ -16064,8 +16536,10 @@ var AutomationConditionLeafSchema = object({
16064
16536
  string(),
16065
16537
  number(),
16066
16538
  boolean(),
16067
- array(union([string(), number()]))
16068
- ])
16539
+ array(union([string(), number()])),
16540
+ QuantityValueSchema
16541
+ ]),
16542
+ unit: string().min(1).optional()
16069
16543
  });
16070
16544
  var AutomationConditionStationaryPresentSchema = object({
16071
16545
  kind: literal("stationary-present"),
@@ -16218,7 +16692,13 @@ var AutomationCapStepSchema = object({
16218
16692
  /** Values may carry `{{vars.x}}` slots, or be exactly `{ $var: 'name' }`, which
16219
16693
  * SUBSTITUTE and do not evaluate (§3.2.3). Anything beyond substitution is
16220
16694
  * the expression leaf. */
16221
- args: record(string(), unknown()).optional()
16695
+ args: record(string(), unknown()).optional(),
16696
+ /**
16697
+ * The unit the person picked per arg (display only). `args` always hold the
16698
+ * value in the unit the method's input DECLARES (`paramMeta`); on a write an
16699
+ * arg may be a {@link QuantityValue}, which the save boundary converts.
16700
+ */
16701
+ argUnits: record(string(), string().min(1)).optional()
16222
16702
  });
16223
16703
  /**
16224
16704
  * The steps an internal Action may contain: cap and wait, and nothing that can
@@ -16598,6 +17078,16 @@ object({
16598
17078
  lastRunAt: number().nullable(),
16599
17079
  lastError: string().nullable()
16600
17080
  });
17081
+ /** A bare number accepted as a base unit — the save succeeded, say so. */
17082
+ var UnitWarningSchema = object({
17083
+ /** Where in the saved record, e.g. `conditions.children.0` or `steps.2.args.grams`. */
17084
+ path: string(),
17085
+ deviceId: number().int().optional(),
17086
+ field: string(),
17087
+ value: number(),
17088
+ assumedUnit: string(),
17089
+ message: string()
17090
+ });
16601
17091
  /**
16602
17092
  * notification-output — canonical, capability-gated notification delivery.
16603
17093
  *
@@ -21970,56 +22460,6 @@ var DeviceAdminLinkSchema = object({
21970
22460
  });
21971
22461
  method(object({ deviceId: number().int().nonnegative() }), DeviceAdminLinkSchema.nullable(), { auth: "admin" });
21972
22462
  /**
21973
- * Identity envelope for a device's upstream-system metadata.
21974
- *
21975
- * Two jobs:
21976
- *
21977
- * 1. **Dispatch key.** `id` is the natural identifier the SOURCE system
21978
- * uses to address this device (HA `entity_id`, Reolink MAC, ONVIF
21979
- * WS-Discovery endpoint UUID, …). Provider code keeps a
21980
- * `Map<sourceInfo.id, IDevice>` to route inbound push events in O(1)
21981
- * without round-tripping through `stableId` / `id` mappings.
21982
- *
21983
- * 2. **Stability bridge.** `uniqueId` is the *immutable* upstream id when
21984
- * one exists (HA `entity.unique_id`, Reolink MAC again — same as `id`
21985
- * for vendors where MAC is the natural key). For systems where the
21986
- * live dispatch key can be renamed (HA `entity_id` can be edited),
21987
- * providers detect renames by matching `uniqueId` and patch `id`
21988
- * in-place so dispatch keeps working.
21989
- *
21990
- * **Display unit and precision are NOT stored here.** They are a read-time
21991
- * preference (D944). A polymorphic reading stores its `quantity` here once,
21992
- * at adopt, and a date/time value stores `dateTimeShape` the same way —
21993
- * neither is repeated on each sample. The `device_class` tag is an
21994
- * HA-specific input consumed at the discovery boundary (`ha-domain-mapping`)
21995
- * to derive the CamStack `DeviceRole`; it is never stored after that point.
21996
- *
21997
- * The `raw` escape hatch carries provider-specific attributes that don't
21998
- * fit the structured slots (HA `attributes` whitelist, Reolink `deviceCache`
21999
- * details, …). Providers control what lands here.
22000
- */
22001
- var SourceInfoSchema = object({
22002
- /** Live dispatch key — mutable when the source system allows rename. */
22003
- id: string(),
22004
- /** Source system tag — e.g. 'homeassistant' | 'reolink' | 'onvif'. */
22005
- system: string(),
22006
- /** Immutable upstream identifier when available (HA `unique_id`, … ).
22007
- * Used to detect rename when `id` changes. */
22008
- uniqueId: string().optional(),
22009
- /** Quantity of a polymorphic reading, written once at adopt (D944). */
22010
- quantity: ReadingQuantitySchema.optional(),
22011
- /** Date / time / datetime shape of a string reading, written once at adopt. */
22012
- dateTimeShape: _enum([
22013
- "date",
22014
- "time",
22015
- "datetime"
22016
- ]).optional(),
22017
- /** Provider-specific extras that don't fit the structured slots.
22018
- * Whitelist what goes here per provider — do NOT dump entire HA
22019
- * attribute blobs (would explode the meta JSON column). */
22020
- raw: record(string(), unknown()).optional()
22021
- });
22022
- /**
22023
22463
  * device-discovery — device-scoped capability for parents that host /
22024
22464
  * enumerate child devices (Reolink Hub / NVR, ONVIF gateway, future
22025
22465
  * integrations). The parent advertises a list of discoverable children,
@@ -54772,11 +55212,13 @@ var ImageContractSchema = object({
54772
55212
  * The shell verdict (see {@link WrapperKindSchema}) with the proofs that
54773
55213
  * produced it.
54774
55214
  *
54775
- * There is deliberately NO `canSelfUpdate` and no apply action: a wrapper
54776
- * update is an ANNOUNCEMENT. The notification body carries the exact command
54777
- * for a `docker` shell and says the app restarts into the new build for
54778
- * `electron`, and that sentence is chosen from `kind` alone — a boolean
54779
- * nothing reads is the defect this repo keeps paying for.
55215
+ * There is deliberately NO `canSelfUpdate` boolean: a wrapper update is an
55216
+ * ANNOUNCEMENT. The notification body carries the exact command for a `docker`
55217
+ * shell and says the app restarts into the new build for `electron`, and that
55218
+ * sentence is chosen from `kind` alone — a boolean nothing reads is the defect
55219
+ * this repo keeps paying for. The one shell that CAN be acted on is the
55220
+ * Electron app, and only through `installDesktopUpdate` (see
55221
+ * {@link DesktopAppStatusSchema} for what the node reads from the app first).
54780
55222
  */
54781
55223
  var WrapperIdentitySchema = object({
54782
55224
  kind: _enum([
@@ -54824,6 +55266,49 @@ var ServerRollbackInfoSchema = object({
54824
55266
  reason: string()
54825
55267
  });
54826
55268
  /**
55269
+ * What the native desktop app (Electron) that hosts this node says about
55270
+ * itself, read from `<dataDir>/server-root/desktop-app-state.json` (ADR-0971).
55271
+ * Absent on the status = no desktop app, or it never wrote the file.
55272
+ *
55273
+ * `stale` is the honest answer to an app that stopped writing (closed, hung,
55274
+ * crashed): the update facts are then the LAST ones known, not current ones,
55275
+ * and a consumer must not read `update.available: false` from a stale record
55276
+ * as "no update". `stateAtMs` is when the app last wrote.
55277
+ */
55278
+ var DesktopAppStatusSchema = object({
55279
+ /** The Electron app's own version (not the node closure's). */
55280
+ version: string(),
55281
+ update: object({
55282
+ available: boolean(),
55283
+ /** The new build is downloaded and `installDesktopUpdate` can apply it. */
55284
+ downloaded: boolean(),
55285
+ version: string().nullable(),
55286
+ checking: boolean(),
55287
+ /** Why the app's last update check produced no answer; `null` when it did. */
55288
+ error: string().nullable()
55289
+ }),
55290
+ stateAtMs: number(),
55291
+ stale: boolean()
55292
+ });
55293
+ /**
55294
+ * Why `installDesktopUpdate` did nothing. Stable names a UI maps to a sentence:
55295
+ * - `not-electron` — this node does not run inside the desktop app.
55296
+ * - `no-app-state` — the app never published its state (or the file is unreadable).
55297
+ * - `app-state-stale` — the app stopped writing; it is probably not running.
55298
+ * - `not-downloaded` — no update is downloaded yet; nothing to install.
55299
+ */
55300
+ var InstallDesktopUpdateReasonSchema = _enum([
55301
+ "not-electron",
55302
+ "no-app-state",
55303
+ "app-state-stale",
55304
+ "not-downloaded"
55305
+ ]);
55306
+ var InstallDesktopUpdateResultSchema = object({
55307
+ accepted: boolean(),
55308
+ /** Non-null exactly when `accepted` is false. */
55309
+ reason: InstallDesktopUpdateReasonSchema.nullable()
55310
+ });
55311
+ /**
54827
55312
  * The runner boot check (D877): the runners this node PLANNED (hub: one per
54828
55313
  * `resolveRunnerId` over its forked addons; agent: the runners its process
54829
55314
  * service holds, because only the hub plans) against the states the process
@@ -54927,7 +55412,12 @@ var ServerPackageStatusSchema = object({
54927
55412
  * on a provider that predates it. Absent is "not checked yet", never "all
54928
55413
  * well": a consumer that needs the answer treats it as pending.
54929
55414
  */
54930
- runners: RunnerBootCheckSchema.optional()
55415
+ runners: RunnerBootCheckSchema.optional(),
55416
+ /**
55417
+ * The desktop app hosting this node (see {@link DesktopAppStatusSchema}).
55418
+ * Optional for version skew AND because most nodes have no desktop app.
55419
+ */
55420
+ desktopApp: DesktopAppStatusSchema.optional()
54931
55421
  });
54932
55422
  var ServerUpdateCheckResultSchema = object({
54933
55423
  packageName: string(),
@@ -55032,6 +55522,9 @@ method(_void(), ServerPackageStatusSchema, { auth: "admin" }), method(_void(), S
55032
55522
  kind: "mutation",
55033
55523
  auth: "admin",
55034
55524
  timeoutMs: 16 * 6e4
55525
+ }), method(_void(), InstallDesktopUpdateResultSchema, {
55526
+ kind: "mutation",
55527
+ auth: "admin"
55035
55528
  }), method(_void(), ServerUpdateActionResultSchema, {
55036
55529
  kind: "mutation",
55037
55530
  auth: "admin"
@@ -57979,13 +58472,19 @@ method(object({}), array(ActionEntrySchema), { auth: "admin" }), method(object({
57979
58472
  }), method(ActionIdInput, _void(), {
57980
58473
  kind: "mutation",
57981
58474
  auth: "admin"
57982
- }), method(ActionIdInput, object({ traces: array(AutomationRunTraceSchema) }), { auth: "admin" }), method(object({ action: ActionInputSchema }), object({ action: ActionEntrySchema }), {
58475
+ }), method(ActionIdInput, object({ traces: array(AutomationRunTraceSchema) }), { auth: "admin" }), method(object({ action: ActionInputSchema }), object({
58476
+ action: ActionEntrySchema,
58477
+ warnings: array(UnitWarningSchema).optional()
58478
+ }), {
57983
58479
  kind: "mutation",
57984
58480
  auth: "admin"
57985
58481
  }), method(object({
57986
58482
  actionId: string().min(1),
57987
58483
  action: ActionInputSchema.partial()
57988
- }), object({ action: ActionEntrySchema }), {
58484
+ }), object({
58485
+ action: ActionEntrySchema,
58486
+ warnings: array(UnitWarningSchema).optional()
58487
+ }), {
57989
58488
  kind: "mutation",
57990
58489
  auth: "admin"
57991
58490
  }), method(ActionIdInput, _void(), {
@@ -62632,6 +63131,14 @@ var PetFeederDeviceStatusSchema = _enum([
62632
63131
  "on_batteries"
62633
63132
  ]);
62634
63133
  var gramsPortion = number().int().min(4).max(200);
63134
+ /** A portion REQUESTED of the feeder is a mass the method takes in GRAMS (the
63135
+ * hardware's own unit). The bounds are grams; a caller entering another unit
63136
+ * converts to grams first (`paramMeta`, D972). The STATUS fields above stay
63137
+ * plain grams — they are not readings in the kilogram base. */
63138
+ var gramsParam = gramsPortion.meta(paramMeta({
63139
+ quantity: "mass",
63140
+ unit: "g"
63141
+ }));
62635
63142
  object({
62636
63143
  /** Food in the TANK (hopper), as the feeder's own sensor reports it
62637
63144
  * (`state.food`). A coarse level code, not grams — `0` is empty. The
@@ -62706,9 +63213,9 @@ object({
62706
63213
  });
62707
63214
  DeviceType.PetFeeder, method(object({
62708
63215
  deviceId: number().int().nonnegative(),
62709
- grams: gramsPortion.optional(),
62710
- hopper1: gramsPortion.optional(),
62711
- hopper2: gramsPortion.optional()
63216
+ grams: gramsParam.optional(),
63217
+ hopper1: gramsParam.optional(),
63218
+ hopper2: gramsParam.optional()
62712
63219
  }), _void(), {
62713
63220
  kind: "mutation",
62714
63221
  auth: "protected"
@@ -75488,6 +75995,13 @@ Object.freeze({
75488
75995
  access: "view",
75489
75996
  role: "admin"
75490
75997
  },
75998
+ "serverManagement.installDesktopUpdate": {
75999
+ capName: "server-management",
76000
+ capScope: "system",
76001
+ addonId: null,
76002
+ access: "create",
76003
+ role: "admin"
76004
+ },
75491
76005
  "serverManagement.restartServer": {
75492
76006
  capName: "server-management",
75493
76007
  capScope: "system",
@@ -79398,7 +79912,8 @@ var APPLIANCE_CAP_VOCABULARY = {
79398
79912
  min: 4,
79399
79913
  max: 200,
79400
79914
  step: 1,
79401
- unit: "g"
79915
+ unit: "g",
79916
+ quantity: "mass"
79402
79917
  },
79403
79918
  optional: true
79404
79919
  }]
@@ -79417,7 +79932,8 @@ var APPLIANCE_CAP_VOCABULARY = {
79417
79932
  min: 4,
79418
79933
  max: 200,
79419
79934
  step: 1,
79420
- unit: "g"
79935
+ unit: "g",
79936
+ quantity: "mass"
79421
79937
  },
79422
79938
  optional: true
79423
79939
  }, {
@@ -79428,7 +79944,8 @@ var APPLIANCE_CAP_VOCABULARY = {
79428
79944
  min: 4,
79429
79945
  max: 200,
79430
79946
  step: 1,
79431
- unit: "g"
79947
+ unit: "g",
79948
+ quantity: "mass"
79432
79949
  },
79433
79950
  optional: true
79434
79951
  }]