@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
@@ -16068,6 +16068,478 @@ object({
16068
16068
  path: ["expr"]
16069
16069
  });
16070
16070
  });
16071
+ /**
16072
+ * Identity envelope for a device's upstream-system metadata.
16073
+ *
16074
+ * Two jobs:
16075
+ *
16076
+ * 1. **Dispatch key.** `id` is the natural identifier the SOURCE system
16077
+ * uses to address this device (HA `entity_id`, Reolink MAC, ONVIF
16078
+ * WS-Discovery endpoint UUID, …). Provider code keeps a
16079
+ * `Map<sourceInfo.id, IDevice>` to route inbound push events in O(1)
16080
+ * without round-tripping through `stableId` / `id` mappings.
16081
+ *
16082
+ * 2. **Stability bridge.** `uniqueId` is the *immutable* upstream id when
16083
+ * one exists (HA `entity.unique_id`, Reolink MAC again — same as `id`
16084
+ * for vendors where MAC is the natural key). For systems where the
16085
+ * live dispatch key can be renamed (HA `entity_id` can be edited),
16086
+ * providers detect renames by matching `uniqueId` and patch `id`
16087
+ * in-place so dispatch keeps working.
16088
+ *
16089
+ * **Display unit and precision are NOT stored here.** They are a read-time
16090
+ * preference (D944). A polymorphic reading stores its `quantity` here once,
16091
+ * at adopt, and a date/time value stores `dateTimeShape` the same way —
16092
+ * neither is repeated on each sample. The `device_class` tag is an
16093
+ * HA-specific input consumed at the discovery boundary (`ha-domain-mapping`)
16094
+ * to derive the CamStack `DeviceRole`; it is never stored after that point.
16095
+ *
16096
+ * The `raw` escape hatch carries provider-specific attributes that don't
16097
+ * fit the structured slots (HA `attributes` whitelist, Reolink `deviceCache`
16098
+ * details, …). Providers control what lands here.
16099
+ */
16100
+ var SourceInfoSchema = object({
16101
+ /** Live dispatch key — mutable when the source system allows rename. */
16102
+ id: string(),
16103
+ /** Source system tag — e.g. 'homeassistant' | 'reolink' | 'onvif'. */
16104
+ system: string(),
16105
+ /** Immutable upstream identifier when available (HA `unique_id`, … ).
16106
+ * Used to detect rename when `id` changes. */
16107
+ uniqueId: string().optional(),
16108
+ /** Quantity of a polymorphic reading, written once at adopt (D944). */
16109
+ quantity: ReadingQuantitySchema.optional(),
16110
+ /** Date / time / datetime shape of a string reading, written once at adopt. */
16111
+ dateTimeShape: _enum([
16112
+ "date",
16113
+ "time",
16114
+ "datetime"
16115
+ ]).optional(),
16116
+ /** Provider-specific extras that don't fit the structured slots.
16117
+ * Whitelist what goes here per provider — do NOT dump entire HA
16118
+ * attribute blobs (would explode the meta JSON column). */
16119
+ raw: record(string(), unknown()).optional()
16120
+ });
16121
+ /**
16122
+ * Frozen unit → spec table. `•` in the doc marks each dimension's canonical
16123
+ * unit (`factor: 1, offset: 0`). °F derives from `°C = (°F − 32) × 5/9` ⇒
16124
+ * `factor = 5/9`, `offset = -160/9` (kept as exact expressions, not rounded
16125
+ * decimals). K derives from `°C = K − 273.15`.
16126
+ */
16127
+ var UNIT_TABLE = {
16128
+ "°C": {
16129
+ dimension: "temperature",
16130
+ factor: 1,
16131
+ offset: 0
16132
+ },
16133
+ "°F": {
16134
+ dimension: "temperature",
16135
+ factor: 5 / 9,
16136
+ offset: -160 / 9
16137
+ },
16138
+ K: {
16139
+ dimension: "temperature",
16140
+ factor: 1,
16141
+ offset: -273.15
16142
+ },
16143
+ hPa: {
16144
+ dimension: "pressure",
16145
+ factor: 1,
16146
+ offset: 0
16147
+ },
16148
+ kPa: {
16149
+ dimension: "pressure",
16150
+ factor: 10,
16151
+ offset: 0
16152
+ },
16153
+ Pa: {
16154
+ dimension: "pressure",
16155
+ factor: .01,
16156
+ offset: 0
16157
+ },
16158
+ mbar: {
16159
+ dimension: "pressure",
16160
+ factor: 1,
16161
+ offset: 0
16162
+ },
16163
+ bar: {
16164
+ dimension: "pressure",
16165
+ factor: 1e3,
16166
+ offset: 0
16167
+ },
16168
+ inHg: {
16169
+ dimension: "pressure",
16170
+ factor: 33.8639,
16171
+ offset: 0
16172
+ },
16173
+ mmHg: {
16174
+ dimension: "pressure",
16175
+ factor: 1.33322,
16176
+ offset: 0
16177
+ },
16178
+ psi: {
16179
+ dimension: "pressure",
16180
+ factor: 68.9476,
16181
+ offset: 0
16182
+ },
16183
+ "m/s": {
16184
+ dimension: "speed",
16185
+ factor: 1,
16186
+ offset: 0
16187
+ },
16188
+ "km/h": {
16189
+ dimension: "speed",
16190
+ factor: 1 / 3.6,
16191
+ offset: 0
16192
+ },
16193
+ mph: {
16194
+ dimension: "speed",
16195
+ factor: .44704,
16196
+ offset: 0
16197
+ },
16198
+ kn: {
16199
+ dimension: "speed",
16200
+ factor: .514444,
16201
+ offset: 0
16202
+ },
16203
+ "mm/h": {
16204
+ dimension: "precipitation-rate",
16205
+ factor: 1,
16206
+ offset: 0
16207
+ },
16208
+ "in/h": {
16209
+ dimension: "precipitation-rate",
16210
+ factor: 25.4,
16211
+ offset: 0
16212
+ },
16213
+ m: {
16214
+ dimension: "length",
16215
+ factor: 1,
16216
+ offset: 0
16217
+ },
16218
+ mm: {
16219
+ dimension: "length",
16220
+ factor: .001,
16221
+ offset: 0
16222
+ },
16223
+ cm: {
16224
+ dimension: "length",
16225
+ factor: .01,
16226
+ offset: 0
16227
+ },
16228
+ km: {
16229
+ dimension: "length",
16230
+ factor: 1e3,
16231
+ offset: 0
16232
+ },
16233
+ in: {
16234
+ dimension: "length",
16235
+ factor: .0254,
16236
+ offset: 0
16237
+ },
16238
+ ft: {
16239
+ dimension: "length",
16240
+ factor: .3048,
16241
+ offset: 0
16242
+ },
16243
+ mi: {
16244
+ dimension: "length",
16245
+ factor: 1609.344,
16246
+ offset: 0
16247
+ },
16248
+ "m²": {
16249
+ dimension: "area",
16250
+ factor: 1,
16251
+ offset: 0
16252
+ },
16253
+ lx: {
16254
+ dimension: "illuminance",
16255
+ factor: 1,
16256
+ offset: 0
16257
+ },
16258
+ "W/m²": {
16259
+ dimension: "irradiance",
16260
+ factor: 1,
16261
+ offset: 0
16262
+ },
16263
+ W: {
16264
+ dimension: "power",
16265
+ factor: 1,
16266
+ offset: 0
16267
+ },
16268
+ kW: {
16269
+ dimension: "power",
16270
+ factor: 1e3,
16271
+ offset: 0
16272
+ },
16273
+ VA: {
16274
+ dimension: "apparent-power",
16275
+ factor: 1,
16276
+ offset: 0
16277
+ },
16278
+ Wh: {
16279
+ dimension: "energy",
16280
+ factor: 1,
16281
+ offset: 0
16282
+ },
16283
+ kWh: {
16284
+ dimension: "energy",
16285
+ factor: 1e3,
16286
+ offset: 0
16287
+ },
16288
+ MWh: {
16289
+ dimension: "energy",
16290
+ factor: 1e6,
16291
+ offset: 0
16292
+ },
16293
+ V: {
16294
+ dimension: "voltage",
16295
+ factor: 1,
16296
+ offset: 0
16297
+ },
16298
+ mV: {
16299
+ dimension: "voltage",
16300
+ factor: .001,
16301
+ offset: 0
16302
+ },
16303
+ A: {
16304
+ dimension: "current",
16305
+ factor: 1,
16306
+ offset: 0
16307
+ },
16308
+ mA: {
16309
+ dimension: "current",
16310
+ factor: .001,
16311
+ offset: 0
16312
+ },
16313
+ ppm: {
16314
+ dimension: "concentration-volume",
16315
+ factor: 1,
16316
+ offset: 0
16317
+ },
16318
+ ppb: {
16319
+ dimension: "concentration-volume",
16320
+ factor: .001,
16321
+ offset: 0
16322
+ },
16323
+ "µg/m³": {
16324
+ dimension: "concentration-mass",
16325
+ factor: 1,
16326
+ offset: 0
16327
+ },
16328
+ "mg/m³": {
16329
+ dimension: "concentration-mass",
16330
+ factor: 1e3,
16331
+ offset: 0
16332
+ },
16333
+ kg: {
16334
+ dimension: "mass",
16335
+ factor: 1,
16336
+ offset: 0
16337
+ },
16338
+ g: {
16339
+ dimension: "mass",
16340
+ factor: .001,
16341
+ offset: 0
16342
+ },
16343
+ lb: {
16344
+ dimension: "mass",
16345
+ factor: .453592,
16346
+ offset: 0
16347
+ },
16348
+ oz: {
16349
+ dimension: "mass",
16350
+ factor: .0283495,
16351
+ offset: 0
16352
+ },
16353
+ "%": {
16354
+ dimension: "percentage",
16355
+ factor: 1,
16356
+ offset: 0
16357
+ },
16358
+ L: {
16359
+ dimension: "volume",
16360
+ factor: 1,
16361
+ offset: 0
16362
+ },
16363
+ mL: {
16364
+ dimension: "volume",
16365
+ factor: .001,
16366
+ offset: 0
16367
+ },
16368
+ gal: {
16369
+ dimension: "volume",
16370
+ factor: 3.785411784,
16371
+ offset: 0
16372
+ },
16373
+ s: {
16374
+ dimension: "duration",
16375
+ factor: 1,
16376
+ offset: 0
16377
+ },
16378
+ ms: {
16379
+ dimension: "duration",
16380
+ factor: .001,
16381
+ offset: 0
16382
+ },
16383
+ min: {
16384
+ dimension: "duration",
16385
+ factor: 60,
16386
+ offset: 0
16387
+ },
16388
+ h: {
16389
+ dimension: "duration",
16390
+ factor: 3600,
16391
+ offset: 0
16392
+ },
16393
+ d: {
16394
+ dimension: "duration",
16395
+ factor: 86400,
16396
+ offset: 0
16397
+ },
16398
+ B: {
16399
+ dimension: "information",
16400
+ factor: 1,
16401
+ offset: 0
16402
+ },
16403
+ KiB: {
16404
+ dimension: "information",
16405
+ factor: 1024,
16406
+ offset: 0
16407
+ },
16408
+ MiB: {
16409
+ dimension: "information",
16410
+ factor: 1024 ** 2,
16411
+ offset: 0
16412
+ },
16413
+ GiB: {
16414
+ dimension: "information",
16415
+ factor: 1024 ** 3,
16416
+ offset: 0
16417
+ },
16418
+ TiB: {
16419
+ dimension: "information",
16420
+ factor: 1024 ** 4,
16421
+ offset: 0
16422
+ },
16423
+ kB: {
16424
+ dimension: "information",
16425
+ factor: 1e3,
16426
+ offset: 0
16427
+ },
16428
+ MB: {
16429
+ dimension: "information",
16430
+ factor: 1e6,
16431
+ offset: 0
16432
+ },
16433
+ GB: {
16434
+ dimension: "information",
16435
+ factor: 1e9,
16436
+ offset: 0
16437
+ },
16438
+ "°": {
16439
+ dimension: "angle",
16440
+ factor: 1,
16441
+ offset: 0
16442
+ },
16443
+ dBFS: {
16444
+ dimension: "sound-level",
16445
+ factor: 1,
16446
+ offset: 0
16447
+ },
16448
+ dBm: {
16449
+ dimension: "signal-level",
16450
+ factor: 1,
16451
+ offset: 0
16452
+ },
16453
+ mired: {
16454
+ dimension: "colour-temperature",
16455
+ factor: 1,
16456
+ offset: 0
16457
+ },
16458
+ kbps: {
16459
+ dimension: "bitrate",
16460
+ factor: 1,
16461
+ offset: 0
16462
+ },
16463
+ Mbps: {
16464
+ dimension: "bitrate",
16465
+ factor: 1e3,
16466
+ offset: 0
16467
+ },
16468
+ fps: {
16469
+ dimension: "rate",
16470
+ factor: 1,
16471
+ offset: 0
16472
+ }
16473
+ };
16474
+ /** Resolve a unit's `UnitSpec`, or `undefined` when the spelling is unknown. */
16475
+ function specFor(unit) {
16476
+ return Object.hasOwn(UNIT_TABLE, unit) ? UNIT_TABLE[unit] : void 0;
16477
+ }
16478
+ /** Value in `spec`'s unit → its dimension's canonical unit. */
16479
+ function toCanonical(value, spec) {
16480
+ return value * spec.factor + spec.offset;
16481
+ }
16482
+ /** Canonical-unit value → the unit described by `spec`. */
16483
+ function fromCanonical(canonical, spec) {
16484
+ return (canonical - spec.offset) / spec.factor;
16485
+ }
16486
+ /**
16487
+ * Graceful variant for the render path: returns the converted value, or
16488
+ * `undefined` when the conversion is refused (unknown unit / cross-dimension).
16489
+ * Never throws — a render caller falls back to the raw value + source unit.
16490
+ */
16491
+ function tryConvertUnit(value, from, to) {
16492
+ if (from === to) return value;
16493
+ const fromSpec = specFor(from);
16494
+ if (!fromSpec) return void 0;
16495
+ const toSpec = specFor(to);
16496
+ if (!toSpec) return void 0;
16497
+ if (fromSpec.dimension !== toSpec.dimension) return void 0;
16498
+ return fromCanonical(toCanonical(value, fromSpec), toSpec);
16499
+ }
16500
+ /**
16501
+ * A number a person types for a physical quantity — the input side of the
16502
+ * value + unit contract (D972).
16503
+ *
16504
+ * Readings are stored in the base unit of their quantity (D944); a cap method
16505
+ * param is stored in the unit its input schema DECLARES (`paramMeta`). The
16506
+ * wire pair {@link QuantityValue} says "this number is expressed in this
16507
+ * unit"; {@link convertQuantityInput} brings it to the stored unit and refuses,
16508
+ * with a typed {@link QuantityUnitError}, a unit that cannot be that quantity.
16509
+ */
16510
+ /** A unit that cannot be applied to the number it was given with. */
16511
+ var QuantityUnitError = class extends Error {
16512
+ code;
16513
+ constructor(code, message) {
16514
+ super(`[${code}] ${message}`);
16515
+ this.name = "QuantityUnitError";
16516
+ this.code = code;
16517
+ }
16518
+ };
16519
+ /** The wire pair: `value` is expressed in `unit`. */
16520
+ var QuantityValueSchema = object({
16521
+ value: number(),
16522
+ unit: string().min(1)
16523
+ });
16524
+ /**
16525
+ * Zod `.meta()` bag for a cap METHOD param that is a physical quantity — the
16526
+ * input-side twin of `readingMeta`. The value is carried in `unit` (a gram
16527
+ * portion stays in grams); the unit must belong to the quantity, checked once
16528
+ * when the cap is declared.
16529
+ */
16530
+ function paramMeta(declared) {
16531
+ const base = baseUnitOf(declared.quantity);
16532
+ if (base === void 0) throw new QuantityUnitError("unknown-unit", `quantity "${declared.quantity}" has no unit`);
16533
+ if (tryConvertUnit(1, declared.unit, base) === void 0) throw new QuantityUnitError("cross-dimension", `"${declared.unit}" is not a unit of ${declared.quantity}`);
16534
+ return {
16535
+ quantity: declared.quantity,
16536
+ unit: declared.unit
16537
+ };
16538
+ }
16539
+ object({
16540
+ quantity: ReadingQuantitySchema,
16541
+ unit: string().min(1)
16542
+ });
16071
16543
  /** How a leaf compares a device field to a value. Derived from the field's
16072
16544
  * `kind` in `deviceManager.getWireableFields`, never hand-maintained. */
16073
16545
  var AutomationConditionOperatorSchema = _enum([
@@ -16090,8 +16562,10 @@ var AutomationConditionLeafSchema = object({
16090
16562
  string(),
16091
16563
  number(),
16092
16564
  boolean(),
16093
- array(union([string(), number()]))
16094
- ])
16565
+ array(union([string(), number()])),
16566
+ QuantityValueSchema
16567
+ ]),
16568
+ unit: string().min(1).optional()
16095
16569
  });
16096
16570
  var AutomationConditionStationaryPresentSchema = object({
16097
16571
  kind: literal("stationary-present"),
@@ -16244,7 +16718,13 @@ var AutomationCapStepSchema = object({
16244
16718
  /** Values may carry `{{vars.x}}` slots, or be exactly `{ $var: 'name' }`, which
16245
16719
  * SUBSTITUTE and do not evaluate (§3.2.3). Anything beyond substitution is
16246
16720
  * the expression leaf. */
16247
- args: record(string(), unknown()).optional()
16721
+ args: record(string(), unknown()).optional(),
16722
+ /**
16723
+ * The unit the person picked per arg (display only). `args` always hold the
16724
+ * value in the unit the method's input DECLARES (`paramMeta`); on a write an
16725
+ * arg may be a {@link QuantityValue}, which the save boundary converts.
16726
+ */
16727
+ argUnits: record(string(), string().min(1)).optional()
16248
16728
  });
16249
16729
  /**
16250
16730
  * The steps an internal Action may contain: cap and wait, and nothing that can
@@ -16624,6 +17104,16 @@ object({
16624
17104
  lastRunAt: number().nullable(),
16625
17105
  lastError: string().nullable()
16626
17106
  });
17107
+ /** A bare number accepted as a base unit — the save succeeded, say so. */
17108
+ var UnitWarningSchema = object({
17109
+ /** Where in the saved record, e.g. `conditions.children.0` or `steps.2.args.grams`. */
17110
+ path: string(),
17111
+ deviceId: number().int().optional(),
17112
+ field: string(),
17113
+ value: number(),
17114
+ assumedUnit: string(),
17115
+ message: string()
17116
+ });
16627
17117
  /**
16628
17118
  * notification-output — canonical, capability-gated notification delivery.
16629
17119
  *
@@ -21996,56 +22486,6 @@ var DeviceAdminLinkSchema = object({
21996
22486
  });
21997
22487
  method(object({ deviceId: number().int().nonnegative() }), DeviceAdminLinkSchema.nullable(), { auth: "admin" });
21998
22488
  /**
21999
- * Identity envelope for a device's upstream-system metadata.
22000
- *
22001
- * Two jobs:
22002
- *
22003
- * 1. **Dispatch key.** `id` is the natural identifier the SOURCE system
22004
- * uses to address this device (HA `entity_id`, Reolink MAC, ONVIF
22005
- * WS-Discovery endpoint UUID, …). Provider code keeps a
22006
- * `Map<sourceInfo.id, IDevice>` to route inbound push events in O(1)
22007
- * without round-tripping through `stableId` / `id` mappings.
22008
- *
22009
- * 2. **Stability bridge.** `uniqueId` is the *immutable* upstream id when
22010
- * one exists (HA `entity.unique_id`, Reolink MAC again — same as `id`
22011
- * for vendors where MAC is the natural key). For systems where the
22012
- * live dispatch key can be renamed (HA `entity_id` can be edited),
22013
- * providers detect renames by matching `uniqueId` and patch `id`
22014
- * in-place so dispatch keeps working.
22015
- *
22016
- * **Display unit and precision are NOT stored here.** They are a read-time
22017
- * preference (D944). A polymorphic reading stores its `quantity` here once,
22018
- * at adopt, and a date/time value stores `dateTimeShape` the same way —
22019
- * neither is repeated on each sample. The `device_class` tag is an
22020
- * HA-specific input consumed at the discovery boundary (`ha-domain-mapping`)
22021
- * to derive the CamStack `DeviceRole`; it is never stored after that point.
22022
- *
22023
- * The `raw` escape hatch carries provider-specific attributes that don't
22024
- * fit the structured slots (HA `attributes` whitelist, Reolink `deviceCache`
22025
- * details, …). Providers control what lands here.
22026
- */
22027
- var SourceInfoSchema = object({
22028
- /** Live dispatch key — mutable when the source system allows rename. */
22029
- id: string(),
22030
- /** Source system tag — e.g. 'homeassistant' | 'reolink' | 'onvif'. */
22031
- system: string(),
22032
- /** Immutable upstream identifier when available (HA `unique_id`, … ).
22033
- * Used to detect rename when `id` changes. */
22034
- uniqueId: string().optional(),
22035
- /** Quantity of a polymorphic reading, written once at adopt (D944). */
22036
- quantity: ReadingQuantitySchema.optional(),
22037
- /** Date / time / datetime shape of a string reading, written once at adopt. */
22038
- dateTimeShape: _enum([
22039
- "date",
22040
- "time",
22041
- "datetime"
22042
- ]).optional(),
22043
- /** Provider-specific extras that don't fit the structured slots.
22044
- * Whitelist what goes here per provider — do NOT dump entire HA
22045
- * attribute blobs (would explode the meta JSON column). */
22046
- raw: record(string(), unknown()).optional()
22047
- });
22048
- /**
22049
22489
  * device-discovery — device-scoped capability for parents that host /
22050
22490
  * enumerate child devices (Reolink Hub / NVR, ONVIF gateway, future
22051
22491
  * integrations). The parent advertises a list of discoverable children,
@@ -54798,11 +55238,13 @@ var ImageContractSchema = object({
54798
55238
  * The shell verdict (see {@link WrapperKindSchema}) with the proofs that
54799
55239
  * produced it.
54800
55240
  *
54801
- * There is deliberately NO `canSelfUpdate` and no apply action: a wrapper
54802
- * update is an ANNOUNCEMENT. The notification body carries the exact command
54803
- * for a `docker` shell and says the app restarts into the new build for
54804
- * `electron`, and that sentence is chosen from `kind` alone — a boolean
54805
- * nothing reads is the defect this repo keeps paying for.
55241
+ * There is deliberately NO `canSelfUpdate` boolean: a wrapper update is an
55242
+ * ANNOUNCEMENT. The notification body carries the exact command for a `docker`
55243
+ * shell and says the app restarts into the new build for `electron`, and that
55244
+ * sentence is chosen from `kind` alone — a boolean nothing reads is the defect
55245
+ * this repo keeps paying for. The one shell that CAN be acted on is the
55246
+ * Electron app, and only through `installDesktopUpdate` (see
55247
+ * {@link DesktopAppStatusSchema} for what the node reads from the app first).
54806
55248
  */
54807
55249
  var WrapperIdentitySchema = object({
54808
55250
  kind: _enum([
@@ -54850,6 +55292,49 @@ var ServerRollbackInfoSchema = object({
54850
55292
  reason: string()
54851
55293
  });
54852
55294
  /**
55295
+ * What the native desktop app (Electron) that hosts this node says about
55296
+ * itself, read from `<dataDir>/server-root/desktop-app-state.json` (ADR-0971).
55297
+ * Absent on the status = no desktop app, or it never wrote the file.
55298
+ *
55299
+ * `stale` is the honest answer to an app that stopped writing (closed, hung,
55300
+ * crashed): the update facts are then the LAST ones known, not current ones,
55301
+ * and a consumer must not read `update.available: false` from a stale record
55302
+ * as "no update". `stateAtMs` is when the app last wrote.
55303
+ */
55304
+ var DesktopAppStatusSchema = object({
55305
+ /** The Electron app's own version (not the node closure's). */
55306
+ version: string(),
55307
+ update: object({
55308
+ available: boolean(),
55309
+ /** The new build is downloaded and `installDesktopUpdate` can apply it. */
55310
+ downloaded: boolean(),
55311
+ version: string().nullable(),
55312
+ checking: boolean(),
55313
+ /** Why the app's last update check produced no answer; `null` when it did. */
55314
+ error: string().nullable()
55315
+ }),
55316
+ stateAtMs: number(),
55317
+ stale: boolean()
55318
+ });
55319
+ /**
55320
+ * Why `installDesktopUpdate` did nothing. Stable names a UI maps to a sentence:
55321
+ * - `not-electron` — this node does not run inside the desktop app.
55322
+ * - `no-app-state` — the app never published its state (or the file is unreadable).
55323
+ * - `app-state-stale` — the app stopped writing; it is probably not running.
55324
+ * - `not-downloaded` — no update is downloaded yet; nothing to install.
55325
+ */
55326
+ var InstallDesktopUpdateReasonSchema = _enum([
55327
+ "not-electron",
55328
+ "no-app-state",
55329
+ "app-state-stale",
55330
+ "not-downloaded"
55331
+ ]);
55332
+ var InstallDesktopUpdateResultSchema = object({
55333
+ accepted: boolean(),
55334
+ /** Non-null exactly when `accepted` is false. */
55335
+ reason: InstallDesktopUpdateReasonSchema.nullable()
55336
+ });
55337
+ /**
54853
55338
  * The runner boot check (D877): the runners this node PLANNED (hub: one per
54854
55339
  * `resolveRunnerId` over its forked addons; agent: the runners its process
54855
55340
  * service holds, because only the hub plans) against the states the process
@@ -54953,7 +55438,12 @@ var ServerPackageStatusSchema = object({
54953
55438
  * on a provider that predates it. Absent is "not checked yet", never "all
54954
55439
  * well": a consumer that needs the answer treats it as pending.
54955
55440
  */
54956
- runners: RunnerBootCheckSchema.optional()
55441
+ runners: RunnerBootCheckSchema.optional(),
55442
+ /**
55443
+ * The desktop app hosting this node (see {@link DesktopAppStatusSchema}).
55444
+ * Optional for version skew AND because most nodes have no desktop app.
55445
+ */
55446
+ desktopApp: DesktopAppStatusSchema.optional()
54957
55447
  });
54958
55448
  var ServerUpdateCheckResultSchema = object({
54959
55449
  packageName: string(),
@@ -55058,6 +55548,9 @@ method(_void(), ServerPackageStatusSchema, { auth: "admin" }), method(_void(), S
55058
55548
  kind: "mutation",
55059
55549
  auth: "admin",
55060
55550
  timeoutMs: 16 * 6e4
55551
+ }), method(_void(), InstallDesktopUpdateResultSchema, {
55552
+ kind: "mutation",
55553
+ auth: "admin"
55061
55554
  }), method(_void(), ServerUpdateActionResultSchema, {
55062
55555
  kind: "mutation",
55063
55556
  auth: "admin"
@@ -58005,13 +58498,19 @@ method(object({}), array(ActionEntrySchema), { auth: "admin" }), method(object({
58005
58498
  }), method(ActionIdInput, _void(), {
58006
58499
  kind: "mutation",
58007
58500
  auth: "admin"
58008
- }), method(ActionIdInput, object({ traces: array(AutomationRunTraceSchema) }), { auth: "admin" }), method(object({ action: ActionInputSchema }), object({ action: ActionEntrySchema }), {
58501
+ }), method(ActionIdInput, object({ traces: array(AutomationRunTraceSchema) }), { auth: "admin" }), method(object({ action: ActionInputSchema }), object({
58502
+ action: ActionEntrySchema,
58503
+ warnings: array(UnitWarningSchema).optional()
58504
+ }), {
58009
58505
  kind: "mutation",
58010
58506
  auth: "admin"
58011
58507
  }), method(object({
58012
58508
  actionId: string().min(1),
58013
58509
  action: ActionInputSchema.partial()
58014
- }), object({ action: ActionEntrySchema }), {
58510
+ }), object({
58511
+ action: ActionEntrySchema,
58512
+ warnings: array(UnitWarningSchema).optional()
58513
+ }), {
58015
58514
  kind: "mutation",
58016
58515
  auth: "admin"
58017
58516
  }), method(ActionIdInput, _void(), {
@@ -62658,6 +63157,14 @@ var PetFeederDeviceStatusSchema = _enum([
62658
63157
  "on_batteries"
62659
63158
  ]);
62660
63159
  var gramsPortion = number().int().min(4).max(200);
63160
+ /** A portion REQUESTED of the feeder is a mass the method takes in GRAMS (the
63161
+ * hardware's own unit). The bounds are grams; a caller entering another unit
63162
+ * converts to grams first (`paramMeta`, D972). The STATUS fields above stay
63163
+ * plain grams — they are not readings in the kilogram base. */
63164
+ var gramsParam = gramsPortion.meta(paramMeta({
63165
+ quantity: "mass",
63166
+ unit: "g"
63167
+ }));
62661
63168
  object({
62662
63169
  /** Food in the TANK (hopper), as the feeder's own sensor reports it
62663
63170
  * (`state.food`). A coarse level code, not grams — `0` is empty. The
@@ -62732,9 +63239,9 @@ object({
62732
63239
  });
62733
63240
  DeviceType.PetFeeder, method(object({
62734
63241
  deviceId: number().int().nonnegative(),
62735
- grams: gramsPortion.optional(),
62736
- hopper1: gramsPortion.optional(),
62737
- hopper2: gramsPortion.optional()
63242
+ grams: gramsParam.optional(),
63243
+ hopper1: gramsParam.optional(),
63244
+ hopper2: gramsParam.optional()
62738
63245
  }), _void(), {
62739
63246
  kind: "mutation",
62740
63247
  auth: "protected"
@@ -75514,6 +76021,13 @@ Object.freeze({
75514
76021
  access: "view",
75515
76022
  role: "admin"
75516
76023
  },
76024
+ "serverManagement.installDesktopUpdate": {
76025
+ capName: "server-management",
76026
+ capScope: "system",
76027
+ addonId: null,
76028
+ access: "create",
76029
+ role: "admin"
76030
+ },
75517
76031
  "serverManagement.restartServer": {
75518
76032
  capName: "server-management",
75519
76033
  capScope: "system",
@@ -79424,7 +79938,8 @@ var APPLIANCE_CAP_VOCABULARY = {
79424
79938
  min: 4,
79425
79939
  max: 200,
79426
79940
  step: 1,
79427
- unit: "g"
79941
+ unit: "g",
79942
+ quantity: "mass"
79428
79943
  },
79429
79944
  optional: true
79430
79945
  }]
@@ -79443,7 +79958,8 @@ var APPLIANCE_CAP_VOCABULARY = {
79443
79958
  min: 4,
79444
79959
  max: 200,
79445
79960
  step: 1,
79446
- unit: "g"
79961
+ unit: "g",
79962
+ quantity: "mass"
79447
79963
  },
79448
79964
  optional: true
79449
79965
  }, {
@@ -79454,7 +79970,8 @@ var APPLIANCE_CAP_VOCABULARY = {
79454
79970
  min: 4,
79455
79971
  max: 200,
79456
79972
  step: 1,
79457
- unit: "g"
79973
+ unit: "g",
79974
+ quantity: "mass"
79458
79975
  },
79459
79976
  optional: true
79460
79977
  }]