@camstack/addon-terminal 0.1.148 → 0.1.150

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 (3) hide show
  1. package/dist/addon.js +193 -123
  2. package/dist/addon.mjs +193 -123
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -5463,7 +5463,7 @@ var ZodIssueCode = {
5463
5463
  var ZodFirstPartyTypeKind;
5464
5464
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5465
5465
  //#endregion
5466
- //#region ../types/dist/sleep-DJFUfKvA.mjs
5466
+ //#region ../types/dist/sleep-CUp20JkO.mjs
5467
5467
  /**
5468
5468
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5469
5469
  * window to float samples (D455).
@@ -8414,7 +8414,11 @@ var ContributionSectionSchema = object({
8414
8414
  literal(4)
8415
8415
  ]).optional(),
8416
8416
  tab: string().optional(),
8417
- location: _enum(["settings", "top-tab"]).optional(),
8417
+ location: _enum([
8418
+ "settings",
8419
+ "top-tab",
8420
+ "hero"
8421
+ ]).optional(),
8418
8422
  order: number().optional(),
8419
8423
  fields: array(any())
8420
8424
  });
@@ -13379,7 +13383,11 @@ var ConfigSectionWithValuesSchema = object({
13379
13383
  literal(4)
13380
13384
  ]).optional(),
13381
13385
  tab: string().optional(),
13382
- location: _enum(["settings", "top-tab"]).optional(),
13386
+ location: _enum([
13387
+ "settings",
13388
+ "top-tab",
13389
+ "hero"
13390
+ ]).optional(),
13383
13391
  order: number().optional(),
13384
13392
  fields: array(any())
13385
13393
  });
@@ -17259,6 +17267,52 @@ var TierStatusSchema = object({
17259
17267
  countedAt: number().nullable()
17260
17268
  });
17261
17269
  /** Operator/diagnostic view: rows per tier, last runs, refusals and drops since boot. */
17270
+ /**
17271
+ * Why a series is orphan. `device-gone`: its device is absent from the
17272
+ * successful device listings (the departure clock). `undeclared`: its `cap:`
17273
+ * key is declared by no capability any more (a field a cap removed).
17274
+ */
17275
+ var DeviceHistoryOrphanReasonSchema = _enum(["device-gone", "undeclared"]);
17276
+ /** Rows held per stored tier. */
17277
+ var TierRowsSchema = object({
17278
+ raw: number().int(),
17279
+ "5m": number().int(),
17280
+ "1h": number().int(),
17281
+ "1d": number().int()
17282
+ });
17283
+ var OrphanSeriesSchema = object({
17284
+ seriesId: number().int(),
17285
+ deviceId: number().int(),
17286
+ key: string(),
17287
+ scope: string(),
17288
+ /** The metric's display name; `null` when its metric row is gone too. */
17289
+ displayName: string().nullable(),
17290
+ reason: DeviceHistoryOrphanReasonSchema,
17291
+ /** `device-gone`: since when the device has been absent; `null` otherwise. */
17292
+ missingSince: number().nullable(),
17293
+ firstTs: number(),
17294
+ lastTs: number(),
17295
+ rows: TierRowsSchema
17296
+ });
17297
+ var DeviceHistoryOrphanDeleteRefusalSchema = _enum([
17298
+ "not-found",
17299
+ "not-orphan",
17300
+ "failed"
17301
+ ]);
17302
+ var OrphanDeleteEntrySchema = discriminatedUnion("ok", [object({
17303
+ seriesId: number().int(),
17304
+ ok: literal(true),
17305
+ deleted: TierRowsSchema
17306
+ }), object({
17307
+ seriesId: number().int(),
17308
+ ok: literal(false),
17309
+ reason: DeviceHistoryOrphanDeleteRefusalSchema
17310
+ })]);
17311
+ var OrphanListSchema = object({
17312
+ series: array(OrphanSeriesSchema).readonly(),
17313
+ /** More orphans exist than {@link DEVICE_HISTORY_ORPHAN_LIST_MAX}. */
17314
+ truncated: boolean()
17315
+ });
17262
17316
  var DeviceHistoryStatusSchema = object({
17263
17317
  startedAt: number(),
17264
17318
  /** The store is declared, series loaded and the first reconcile has answered. */
@@ -17356,7 +17410,10 @@ method(object({ deviceId: number().int() }), array(SeriesInfoSchema).readonly())
17356
17410
  }), object({ enabled: boolean() }), {
17357
17411
  kind: "mutation",
17358
17412
  auth: "admin"
17359
- }), method(object({}), DeviceHistoryStatusSchema, { auth: "admin" });
17413
+ }), method(object({}), DeviceHistoryStatusSchema, { auth: "admin" }), method(object({}), OrphanListSchema, { auth: "admin" }), method(object({ seriesIds: array(number().int()).min(1).max(50) }), object({ results: array(OrphanDeleteEntrySchema).readonly() }), {
17414
+ kind: "mutation",
17415
+ auth: "admin"
17416
+ });
17360
17417
  var DeviceCaStatusSchema = discriminatedUnion("state", [
17361
17418
  object({ state: literal("absent") }),
17362
17419
  object({
@@ -47986,7 +48043,6 @@ var RecommendationReasonSchema = discriminatedUnion("kind", [
47986
48043
  modelId: string()
47987
48044
  }),
47988
48045
  object({ kind: literal("cpu-device") }),
47989
- object({ kind: literal("coral-untouched") }),
47990
48046
  object({ kind: literal("device-disabled") }),
47991
48047
  object({ kind: literal("device-unavailable") }),
47992
48048
  object({ kind: literal("node-offline") }),
@@ -48084,11 +48140,6 @@ var AutoTuneWarningSchema = discriminatedUnion("kind", [
48084
48140
  kind: literal("detector-store-unreadable"),
48085
48141
  error: string()
48086
48142
  }),
48087
- object({
48088
- kind: literal("coral-enabled"),
48089
- nodeId: string(),
48090
- deviceKey: string()
48091
- }),
48092
48143
  object({
48093
48144
  kind: literal("custom-pin-kept"),
48094
48145
  nodeId: string(),
@@ -55272,17 +55323,69 @@ var connectivityCapability = {
55272
55323
  volatileStateFields: ["lastChangedAt"]
55273
55324
  };
55274
55325
  /**
55275
- * Generic device-consumables capability — surfaces a device's
55276
- * maintenance items (vacuum filters/brushes, replaceable cartridges,
55277
- * descaling cycles, …) with their remaining life and an optional
55278
- * "Replaced" reset action. Device-agnostic: any provider that knows its
55279
- * device tracks consumables can register it; the cap declares no
55280
- * vocabulary of its own — the provider names each item verbatim.
55326
+ * Generic device-consumables capability — the ONE place a device reports what
55327
+ * it uses up or fills: wear parts (vacuum filters/brushes, cartridges,
55328
+ * descaling cycles), supplies it draws from (a vacuum's clean-water tank and
55329
+ * detergent, a dishwasher's salt and rinse aid) and waste it collects (a dirty
55330
+ * water tank, a dust bin). Each item carries its remaining life or fill and an
55331
+ * optional "Replaced" reset action. Device-agnostic: any provider that knows
55332
+ * its device tracks consumables registers it; the provider names each item
55333
+ * verbatim and says which `kind` it is.
55334
+ *
55335
+ * The admin UI renders it as ONE collapsible section directly under the
55336
+ * device page's hero card (`placement: 'hero'`), for every device bound to
55337
+ * this cap — never drawn by a device type's hero card itself (D915).
55281
55338
  *
55282
55339
  * Like `childLayout`, the cap is INERT until a provider sets items: no
55283
55340
  * provider populates it by guessing (no HA inference). The UI renders a
55284
55341
  * "No consumables reported" placeholder when `items` is empty.
55285
55342
  */
55343
+ /**
55344
+ * What an item IS, which decides which direction is bad:
55345
+ * - `wear` — a part that wears out (a brush, a filter); low life is bad.
55346
+ * - `supply` — something the device draws from (clean water, detergent,
55347
+ * salt, rinse aid); low or empty is bad.
55348
+ * - `waste` — something the device fills (dirty water, a dust bin); full is
55349
+ * bad.
55350
+ * Absent = `wear`.
55351
+ */
55352
+ var ConsumableKindSchema = _enum([
55353
+ "wear",
55354
+ "supply",
55355
+ "waste"
55356
+ ]);
55357
+ /**
55358
+ * What an item LOOKS like, which decides how a client draws it — independent
55359
+ * of `kind`, which decides which direction is bad:
55360
+ * - `part` — a part that wears (a brush, a filter, a mop pad): a wear bar,
55361
+ * remaining time and a reset.
55362
+ * - `tank` — a container of liquid (clean water, dirty water): a fill gauge.
55363
+ * - `product` — something bought and refilled (detergent, salt, rinse aid):
55364
+ * a stepped level and "refill".
55365
+ * - `bin` — a container that collects waste (a dust bin): a fill gauge
55366
+ * that warns when full.
55367
+ * Absent = derived from the kind ({@link consumableFormOf}).
55368
+ */
55369
+ var ConsumableFormSchema = _enum([
55370
+ "part",
55371
+ "tank",
55372
+ "product",
55373
+ "bin"
55374
+ ]);
55375
+ /** The provider's own discrete verdict on an item. */
55376
+ var ConsumableStatusSchema = _enum([
55377
+ "ok",
55378
+ "low",
55379
+ "empty",
55380
+ "full",
55381
+ "replace"
55382
+ ]);
55383
+ _enum([
55384
+ "ok",
55385
+ "low",
55386
+ "empty",
55387
+ "full"
55388
+ ]);
55286
55389
  /** Units a remaining-life counter is reported in. Closed: the panel renders
55287
55390
  * each. */
55288
55391
  var ConsumableRemainingUnitSchema = _enum([
@@ -55297,18 +55400,23 @@ var ConsumableRemainingSchema = object({
55297
55400
  unit: ConsumableRemainingUnitSchema
55298
55401
  });
55299
55402
  /** A single consumable item. Either a continuous `level` (remaining
55300
- * life %) or a discrete `status` may be known — both may be null when a
55301
- * provider only knows the item exists. `level` and `status` are not
55302
- * mutually exclusive; a provider may report both. */
55403
+ * life %, or fill % for a `supply` / `waste` item) or a discrete `status`
55404
+ * may be known — both may be null when a provider only knows the item
55405
+ * exists. `level` and `status` are not mutually exclusive; a provider may
55406
+ * report both. */
55303
55407
  var ConsumableItemSchema = object({
55304
55408
  /** Stable id, e.g. 'main-brush'. */
55305
55409
  key: string().min(1),
55306
55410
  /** Display name. */
55307
55411
  label: string().min(1),
55308
- /** Remaining life % when known (0..100). */
55412
+ /** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
55309
55413
  level: number().min(0).max(100).nullable(),
55310
- /** Discrete state when known (binary mode). */
55311
- status: _enum(["ok", "replace"]).nullable(),
55414
+ /** The provider's discrete verdict when known (binary mode). */
55415
+ status: ConsumableStatusSchema.nullable(),
55416
+ /** What the item is — decides whether low or full is bad. Absent = `wear`. */
55417
+ kind: ConsumableKindSchema.optional(),
55418
+ /** How the item is drawn (part, tank, product, bin). Absent = derived from `kind`. */
55419
+ form: ConsumableFormSchema.optional(),
55312
55420
  /** Ms epoch of the last replace, when known. */
55313
55421
  lastResetAt: number().nullable(),
55314
55422
  /** Whether `reset()` is meaningful for this item. */
@@ -55331,7 +55439,7 @@ var consumablesCapability = {
55331
55439
  kind: "widget",
55332
55440
  widgetId: "host/consumables-panel",
55333
55441
  tab: "consumables",
55334
- topTab: true,
55442
+ placement: "hero",
55335
55443
  label: "Consumables",
55336
55444
  order: 5
55337
55445
  } },
@@ -55392,9 +55500,37 @@ reset: method(object({
55392
55500
  */
55393
55501
  durability: "restored",
55394
55502
  /**
55395
- * History (D850): none — `items` is an array keyed by runtime ids; a history path never enters it.
55503
+ * History (D850, D917): one series per (item field, item `key`) — the item key
55504
+ * is the series scope, the item `label` names it. A vacuum tank's fill, a
55505
+ * brush's remaining life and a dishwasher's salt are each recorded the moment
55506
+ * their provider reports them; an item that appears later gets its series.
55396
55507
  */
55397
- history: "none",
55508
+ history: {
55509
+ fields: {},
55510
+ items: {
55511
+ path: "items",
55512
+ key: "key",
55513
+ label: "label",
55514
+ fields: {
55515
+ level: {
55516
+ kind: "gauge",
55517
+ unit: "%",
55518
+ deadband: 2,
55519
+ displayName: "Level"
55520
+ },
55521
+ status: {
55522
+ kind: "enum",
55523
+ displayName: "Status"
55524
+ },
55525
+ "remaining.value": {
55526
+ kind: "gauge",
55527
+ unitFrom: "remaining.unit",
55528
+ deadband: 1,
55529
+ displayName: "Remaining"
55530
+ }
55531
+ }
55532
+ }
55533
+ },
55398
55534
  /** Clocks, not content: a re-read that changed no item costs no commit. */
55399
55535
  volatileStateFields: ["lastChangedAt", "lastFetchedAt"]
55400
55536
  };
@@ -55809,8 +55945,9 @@ onStatusChanged: { data: object({
55809
55945
  volatileStateFields: ["lastChangedAt"]
55810
55946
  };
55811
55947
  /**
55812
- * Smart-dishwasher cap — program lifecycle, door / remote-start gates,
55813
- * consumable levels (salt, rinse aid) and common program options.
55948
+ * Smart-dishwasher cap — program lifecycle, door / remote-start gates and
55949
+ * common program options. Salt and rinse aid are NOT here: they are items of
55950
+ * the device's `consumables` cap, like every other device's (D915).
55814
55951
  *
55815
55952
  * Sources: native Bosch Home Connect (`dishwasher` device type). Reusable
55816
55953
  * by any integration that exposes the same program / option surface.
@@ -55858,11 +55995,6 @@ var DishwasherAvailabilitySchema = _enum([
55858
55995
  "offline",
55859
55996
  "description-missing"
55860
55997
  ]);
55861
- var DishwasherConsumableLevelSchema = _enum([
55862
- "ok",
55863
- "low",
55864
- "empty"
55865
- ]);
55866
55998
  var DishwasherStatusSchema = object({
55867
55999
  availability: DishwasherAvailabilitySchema,
55868
56000
  /** Coarse state for compact surfaces; `unavailable` whenever the appliance state is not known. */
@@ -55895,8 +56027,6 @@ var DishwasherStatusSchema = object({
55895
56027
  powerOn: boolean().nullable(),
55896
56028
  /** The raw power state (`On`, `Off`, `Standby`, …); null when not known. */
55897
56029
  powerState: string().nullable(),
55898
- saltLevel: DishwasherConsumableLevelSchema.nullable(),
55899
- rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
55900
56030
  /**
55901
56031
  * True while the appliance asks for its filter to be cleaned (smart-filter, filter-system or
55902
56032
  * combined care-and-filter reminder raised); false when every such reminder reads clear; null
@@ -64712,60 +64842,17 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
64712
64842
  auth: "admin",
64713
64843
  access: "delete"
64714
64844
  });
64715
- /**
64716
- * Robot-vacuum cap. Models HA `vacuum.*` entities — anything with a
64717
- * cleaning lifecycle plus a return-to-base / locate surface and an
64718
- * optional fan-speed selector.
64719
- *
64720
- * State follows HA's canonical vacuum lifecycle: `idle` / `cleaning` /
64721
- * `paused` / `returning` / `docked` / `error`. `batteryLevel`
64722
- * (0..100) is nullable — some vacuums don't report a battery
64723
- * percentage. `fanSpeed` is the current speed token (provider-verbatim,
64724
- * e.g. `'standard'` / `'turbo'`) and `availableFanSpeeds` lists the
64725
- * tokens the hardware accepts so the UI renders only supported choices.
64726
- *
64727
- * The `setFanSpeed` method takes the bare `speed` token — the provider
64728
- * validates it against the vacuum's own list. `locate` triggers the
64729
- * find-me chirp; `returnToBase` sends it home.
64730
- *
64731
- * Consumable / waste tanks: `cleanWater` / `dirtyWater` / `detergent` /
64732
- * `dustBin` each carry a nullable `{ level (0..100 %), status ('ok' |
64733
- * 'low' | 'full') }` reading. Native providers (e.g. Dreame, Roborock)
64734
- * SHOULD populate whichever tanks the hardware has — leave a field `null`
64735
- * only when the device has no such tank at all, and use a `TankStatus`
64736
- * with both inner fields `null` when the tank exists but its level is
64737
- * currently unknown. HA `vacuum.*` entities expose no per-tank telemetry,
64738
- * so the HA provider leaves all four `null`.
64739
- */
64740
- var VacuumStateSchema = _enum([
64741
- "idle",
64742
- "cleaning",
64743
- "paused",
64744
- "returning",
64745
- "docked",
64746
- "drying",
64747
- "error"
64748
- ]);
64749
- /**
64750
- * One consumable / waste tank on a robot vacuum (clean-water, dirty-water,
64751
- * detergent or dust-bin). A tank can report a numeric fill `level` (0..100),
64752
- * a discrete `status` (binary-style hardware), or both. Both `null` means the
64753
- * level is currently unknown; the OWNING field being `null` means the
64754
- * hardware has no such tank at all.
64755
- */
64756
- var TankStatusSchema = object({
64757
- /** Numeric fill 0..100 when the hardware reports a percentage; null otherwise. */
64758
- level: number().min(0).max(100).nullable(),
64759
- /** Discrete state when the hardware is binary-mode; null otherwise. */
64760
- status: _enum([
64761
- "ok",
64762
- "low",
64763
- "full"
64764
- ]).nullable()
64765
- });
64766
64845
  var VacuumControlStatusSchema = object({
64767
64846
  /** Lifecycle state of the vacuum. */
64768
- state: VacuumStateSchema,
64847
+ state: _enum([
64848
+ "idle",
64849
+ "cleaning",
64850
+ "paused",
64851
+ "returning",
64852
+ "docked",
64853
+ "drying",
64854
+ "error"
64855
+ ]),
64769
64856
  /** 0..100 battery percentage. Null when the device has no battery
64770
64857
  * reading. */
64771
64858
  batteryLevel: number().min(0).max(100).nullable(),
@@ -64774,14 +64861,6 @@ var VacuumControlStatusSchema = object({
64774
64861
  fanSpeed: string().nullable(),
64775
64862
  /** Speed tokens the hardware accepts — drives the UI selector. */
64776
64863
  availableFanSpeeds: array(string()),
64777
- /** Clean-water (mop) tank. Null when the hardware has no clean-water tank. */
64778
- cleanWater: TankStatusSchema.nullable(),
64779
- /** Dirty-water (recovery) tank. Null when the hardware has no dirty-water tank. */
64780
- dirtyWater: TankStatusSchema.nullable(),
64781
- /** Detergent tank. Null when the hardware has no detergent tank. */
64782
- detergent: TankStatusSchema.nullable(),
64783
- /** Dust bin. Null when the hardware has no dust bin. */
64784
- dustBin: TankStatusSchema.nullable(),
64785
64864
  /** 0..100 cleaning-completion percentage of the current task, or null. */
64786
64865
  progressPercent: number().min(0).max(100).nullable(),
64787
64866
  /** Current error code (0 / null = no error). */
@@ -64843,35 +64922,14 @@ var vacuumControlCapability = {
64843
64922
  */
64844
64923
  durability: "session",
64845
64924
  /**
64846
- * History (D850): recorded series. Tank levels are fixed-object paths (`cleanWater.level`, ...).
64925
+ * History (D850): recorded series. The tanks moved to `consumables` (D915), whose
64926
+ * items are keyed by runtime ids and record no history.
64847
64927
  */
64848
- history: { fields: {
64849
- batteryLevel: {
64850
- kind: "gauge",
64851
- unit: "%",
64852
- deadband: 2
64853
- },
64854
- "cleanWater.level": {
64855
- kind: "gauge",
64856
- unit: "%",
64857
- deadband: 2
64858
- },
64859
- "dirtyWater.level": {
64860
- kind: "gauge",
64861
- unit: "%",
64862
- deadband: 2
64863
- },
64864
- "detergent.level": {
64865
- kind: "gauge",
64866
- unit: "%",
64867
- deadband: 2
64868
- },
64869
- "dustBin.level": {
64870
- kind: "gauge",
64871
- unit: "%",
64872
- deadband: 2
64873
- }
64874
- } }
64928
+ history: { fields: { batteryLevel: {
64929
+ kind: "gauge",
64930
+ unit: "%",
64931
+ deadband: 2
64932
+ } } }
64875
64933
  };
64876
64934
  var ValveStatusSchema = object({
64877
64935
  /** Lifecycle state of the valve. */
@@ -68782,6 +68840,12 @@ Object.freeze({
68782
68840
  addonId: null,
68783
68841
  access: "create"
68784
68842
  },
68843
+ "deviceHistory.deleteOrphanSeries": {
68844
+ capName: "device-history",
68845
+ capScope: "system",
68846
+ addonId: null,
68847
+ access: "delete"
68848
+ },
68785
68849
  "deviceHistory.getDeviceEnabled": {
68786
68850
  capName: "device-history",
68787
68851
  capScope: "system",
@@ -68800,6 +68864,12 @@ Object.freeze({
68800
68864
  addonId: null,
68801
68865
  access: "view"
68802
68866
  },
68867
+ "deviceHistory.listOrphanSeries": {
68868
+ capName: "device-history",
68869
+ capScope: "system",
68870
+ addonId: null,
68871
+ access: "view"
68872
+ },
68803
68873
  "deviceHistory.listSeries": {
68804
68874
  capName: "device-history",
68805
68875
  capScope: "system",
@@ -78805,7 +78875,7 @@ var STATE_SUMMARY_VARS = [
78805
78875
  ([...RULE_TEXT], [...COMBINED_ALARM]),
78806
78876
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
78807
78877
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
78808
- ([...RULE_TEXT], [...CONSUMABLE]),
78878
+ ([...RULE_TEXT], [...CONSUMABLE, ...TANK]),
78809
78879
  ([...RULE_TEXT], [...TANK]),
78810
78880
  [...RULE_TEXT],
78811
78881
  ([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
package/dist/addon.mjs CHANGED
@@ -5440,7 +5440,7 @@ var ZodIssueCode = {
5440
5440
  var ZodFirstPartyTypeKind;
5441
5441
  ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {});
5442
5442
  //#endregion
5443
- //#region ../types/dist/sleep-DJFUfKvA.mjs
5443
+ //#region ../types/dist/sleep-CUp20JkO.mjs
5444
5444
  /**
5445
5445
  * The audio chunk plane's byte format, and the ONE expansion from a coded
5446
5446
  * window to float samples (D455).
@@ -8391,7 +8391,11 @@ var ContributionSectionSchema = object({
8391
8391
  literal(4)
8392
8392
  ]).optional(),
8393
8393
  tab: string().optional(),
8394
- location: _enum(["settings", "top-tab"]).optional(),
8394
+ location: _enum([
8395
+ "settings",
8396
+ "top-tab",
8397
+ "hero"
8398
+ ]).optional(),
8395
8399
  order: number().optional(),
8396
8400
  fields: array(any())
8397
8401
  });
@@ -13356,7 +13360,11 @@ var ConfigSectionWithValuesSchema = object({
13356
13360
  literal(4)
13357
13361
  ]).optional(),
13358
13362
  tab: string().optional(),
13359
- location: _enum(["settings", "top-tab"]).optional(),
13363
+ location: _enum([
13364
+ "settings",
13365
+ "top-tab",
13366
+ "hero"
13367
+ ]).optional(),
13360
13368
  order: number().optional(),
13361
13369
  fields: array(any())
13362
13370
  });
@@ -17236,6 +17244,52 @@ var TierStatusSchema = object({
17236
17244
  countedAt: number().nullable()
17237
17245
  });
17238
17246
  /** Operator/diagnostic view: rows per tier, last runs, refusals and drops since boot. */
17247
+ /**
17248
+ * Why a series is orphan. `device-gone`: its device is absent from the
17249
+ * successful device listings (the departure clock). `undeclared`: its `cap:`
17250
+ * key is declared by no capability any more (a field a cap removed).
17251
+ */
17252
+ var DeviceHistoryOrphanReasonSchema = _enum(["device-gone", "undeclared"]);
17253
+ /** Rows held per stored tier. */
17254
+ var TierRowsSchema = object({
17255
+ raw: number().int(),
17256
+ "5m": number().int(),
17257
+ "1h": number().int(),
17258
+ "1d": number().int()
17259
+ });
17260
+ var OrphanSeriesSchema = object({
17261
+ seriesId: number().int(),
17262
+ deviceId: number().int(),
17263
+ key: string(),
17264
+ scope: string(),
17265
+ /** The metric's display name; `null` when its metric row is gone too. */
17266
+ displayName: string().nullable(),
17267
+ reason: DeviceHistoryOrphanReasonSchema,
17268
+ /** `device-gone`: since when the device has been absent; `null` otherwise. */
17269
+ missingSince: number().nullable(),
17270
+ firstTs: number(),
17271
+ lastTs: number(),
17272
+ rows: TierRowsSchema
17273
+ });
17274
+ var DeviceHistoryOrphanDeleteRefusalSchema = _enum([
17275
+ "not-found",
17276
+ "not-orphan",
17277
+ "failed"
17278
+ ]);
17279
+ var OrphanDeleteEntrySchema = discriminatedUnion("ok", [object({
17280
+ seriesId: number().int(),
17281
+ ok: literal(true),
17282
+ deleted: TierRowsSchema
17283
+ }), object({
17284
+ seriesId: number().int(),
17285
+ ok: literal(false),
17286
+ reason: DeviceHistoryOrphanDeleteRefusalSchema
17287
+ })]);
17288
+ var OrphanListSchema = object({
17289
+ series: array(OrphanSeriesSchema).readonly(),
17290
+ /** More orphans exist than {@link DEVICE_HISTORY_ORPHAN_LIST_MAX}. */
17291
+ truncated: boolean()
17292
+ });
17239
17293
  var DeviceHistoryStatusSchema = object({
17240
17294
  startedAt: number(),
17241
17295
  /** The store is declared, series loaded and the first reconcile has answered. */
@@ -17333,7 +17387,10 @@ method(object({ deviceId: number().int() }), array(SeriesInfoSchema).readonly())
17333
17387
  }), object({ enabled: boolean() }), {
17334
17388
  kind: "mutation",
17335
17389
  auth: "admin"
17336
- }), method(object({}), DeviceHistoryStatusSchema, { auth: "admin" });
17390
+ }), method(object({}), DeviceHistoryStatusSchema, { auth: "admin" }), method(object({}), OrphanListSchema, { auth: "admin" }), method(object({ seriesIds: array(number().int()).min(1).max(50) }), object({ results: array(OrphanDeleteEntrySchema).readonly() }), {
17391
+ kind: "mutation",
17392
+ auth: "admin"
17393
+ });
17337
17394
  var DeviceCaStatusSchema = discriminatedUnion("state", [
17338
17395
  object({ state: literal("absent") }),
17339
17396
  object({
@@ -47963,7 +48020,6 @@ var RecommendationReasonSchema = discriminatedUnion("kind", [
47963
48020
  modelId: string()
47964
48021
  }),
47965
48022
  object({ kind: literal("cpu-device") }),
47966
- object({ kind: literal("coral-untouched") }),
47967
48023
  object({ kind: literal("device-disabled") }),
47968
48024
  object({ kind: literal("device-unavailable") }),
47969
48025
  object({ kind: literal("node-offline") }),
@@ -48061,11 +48117,6 @@ var AutoTuneWarningSchema = discriminatedUnion("kind", [
48061
48117
  kind: literal("detector-store-unreadable"),
48062
48118
  error: string()
48063
48119
  }),
48064
- object({
48065
- kind: literal("coral-enabled"),
48066
- nodeId: string(),
48067
- deviceKey: string()
48068
- }),
48069
48120
  object({
48070
48121
  kind: literal("custom-pin-kept"),
48071
48122
  nodeId: string(),
@@ -55249,17 +55300,69 @@ var connectivityCapability = {
55249
55300
  volatileStateFields: ["lastChangedAt"]
55250
55301
  };
55251
55302
  /**
55252
- * Generic device-consumables capability — surfaces a device's
55253
- * maintenance items (vacuum filters/brushes, replaceable cartridges,
55254
- * descaling cycles, …) with their remaining life and an optional
55255
- * "Replaced" reset action. Device-agnostic: any provider that knows its
55256
- * device tracks consumables can register it; the cap declares no
55257
- * vocabulary of its own — the provider names each item verbatim.
55303
+ * Generic device-consumables capability — the ONE place a device reports what
55304
+ * it uses up or fills: wear parts (vacuum filters/brushes, cartridges,
55305
+ * descaling cycles), supplies it draws from (a vacuum's clean-water tank and
55306
+ * detergent, a dishwasher's salt and rinse aid) and waste it collects (a dirty
55307
+ * water tank, a dust bin). Each item carries its remaining life or fill and an
55308
+ * optional "Replaced" reset action. Device-agnostic: any provider that knows
55309
+ * its device tracks consumables registers it; the provider names each item
55310
+ * verbatim and says which `kind` it is.
55311
+ *
55312
+ * The admin UI renders it as ONE collapsible section directly under the
55313
+ * device page's hero card (`placement: 'hero'`), for every device bound to
55314
+ * this cap — never drawn by a device type's hero card itself (D915).
55258
55315
  *
55259
55316
  * Like `childLayout`, the cap is INERT until a provider sets items: no
55260
55317
  * provider populates it by guessing (no HA inference). The UI renders a
55261
55318
  * "No consumables reported" placeholder when `items` is empty.
55262
55319
  */
55320
+ /**
55321
+ * What an item IS, which decides which direction is bad:
55322
+ * - `wear` — a part that wears out (a brush, a filter); low life is bad.
55323
+ * - `supply` — something the device draws from (clean water, detergent,
55324
+ * salt, rinse aid); low or empty is bad.
55325
+ * - `waste` — something the device fills (dirty water, a dust bin); full is
55326
+ * bad.
55327
+ * Absent = `wear`.
55328
+ */
55329
+ var ConsumableKindSchema = _enum([
55330
+ "wear",
55331
+ "supply",
55332
+ "waste"
55333
+ ]);
55334
+ /**
55335
+ * What an item LOOKS like, which decides how a client draws it — independent
55336
+ * of `kind`, which decides which direction is bad:
55337
+ * - `part` — a part that wears (a brush, a filter, a mop pad): a wear bar,
55338
+ * remaining time and a reset.
55339
+ * - `tank` — a container of liquid (clean water, dirty water): a fill gauge.
55340
+ * - `product` — something bought and refilled (detergent, salt, rinse aid):
55341
+ * a stepped level and "refill".
55342
+ * - `bin` — a container that collects waste (a dust bin): a fill gauge
55343
+ * that warns when full.
55344
+ * Absent = derived from the kind ({@link consumableFormOf}).
55345
+ */
55346
+ var ConsumableFormSchema = _enum([
55347
+ "part",
55348
+ "tank",
55349
+ "product",
55350
+ "bin"
55351
+ ]);
55352
+ /** The provider's own discrete verdict on an item. */
55353
+ var ConsumableStatusSchema = _enum([
55354
+ "ok",
55355
+ "low",
55356
+ "empty",
55357
+ "full",
55358
+ "replace"
55359
+ ]);
55360
+ _enum([
55361
+ "ok",
55362
+ "low",
55363
+ "empty",
55364
+ "full"
55365
+ ]);
55263
55366
  /** Units a remaining-life counter is reported in. Closed: the panel renders
55264
55367
  * each. */
55265
55368
  var ConsumableRemainingUnitSchema = _enum([
@@ -55274,18 +55377,23 @@ var ConsumableRemainingSchema = object({
55274
55377
  unit: ConsumableRemainingUnitSchema
55275
55378
  });
55276
55379
  /** A single consumable item. Either a continuous `level` (remaining
55277
- * life %) or a discrete `status` may be known — both may be null when a
55278
- * provider only knows the item exists. `level` and `status` are not
55279
- * mutually exclusive; a provider may report both. */
55380
+ * life %, or fill % for a `supply` / `waste` item) or a discrete `status`
55381
+ * may be known — both may be null when a provider only knows the item
55382
+ * exists. `level` and `status` are not mutually exclusive; a provider may
55383
+ * report both. */
55280
55384
  var ConsumableItemSchema = object({
55281
55385
  /** Stable id, e.g. 'main-brush'. */
55282
55386
  key: string().min(1),
55283
55387
  /** Display name. */
55284
55388
  label: string().min(1),
55285
- /** Remaining life % when known (0..100). */
55389
+ /** Remaining life % (`wear`) or fill % (`supply`, `waste`) when known (0..100). */
55286
55390
  level: number().min(0).max(100).nullable(),
55287
- /** Discrete state when known (binary mode). */
55288
- status: _enum(["ok", "replace"]).nullable(),
55391
+ /** The provider's discrete verdict when known (binary mode). */
55392
+ status: ConsumableStatusSchema.nullable(),
55393
+ /** What the item is — decides whether low or full is bad. Absent = `wear`. */
55394
+ kind: ConsumableKindSchema.optional(),
55395
+ /** How the item is drawn (part, tank, product, bin). Absent = derived from `kind`. */
55396
+ form: ConsumableFormSchema.optional(),
55289
55397
  /** Ms epoch of the last replace, when known. */
55290
55398
  lastResetAt: number().nullable(),
55291
55399
  /** Whether `reset()` is meaningful for this item. */
@@ -55308,7 +55416,7 @@ var consumablesCapability = {
55308
55416
  kind: "widget",
55309
55417
  widgetId: "host/consumables-panel",
55310
55418
  tab: "consumables",
55311
- topTab: true,
55419
+ placement: "hero",
55312
55420
  label: "Consumables",
55313
55421
  order: 5
55314
55422
  } },
@@ -55369,9 +55477,37 @@ reset: method(object({
55369
55477
  */
55370
55478
  durability: "restored",
55371
55479
  /**
55372
- * History (D850): none — `items` is an array keyed by runtime ids; a history path never enters it.
55480
+ * History (D850, D917): one series per (item field, item `key`) — the item key
55481
+ * is the series scope, the item `label` names it. A vacuum tank's fill, a
55482
+ * brush's remaining life and a dishwasher's salt are each recorded the moment
55483
+ * their provider reports them; an item that appears later gets its series.
55373
55484
  */
55374
- history: "none",
55485
+ history: {
55486
+ fields: {},
55487
+ items: {
55488
+ path: "items",
55489
+ key: "key",
55490
+ label: "label",
55491
+ fields: {
55492
+ level: {
55493
+ kind: "gauge",
55494
+ unit: "%",
55495
+ deadband: 2,
55496
+ displayName: "Level"
55497
+ },
55498
+ status: {
55499
+ kind: "enum",
55500
+ displayName: "Status"
55501
+ },
55502
+ "remaining.value": {
55503
+ kind: "gauge",
55504
+ unitFrom: "remaining.unit",
55505
+ deadband: 1,
55506
+ displayName: "Remaining"
55507
+ }
55508
+ }
55509
+ }
55510
+ },
55375
55511
  /** Clocks, not content: a re-read that changed no item costs no commit. */
55376
55512
  volatileStateFields: ["lastChangedAt", "lastFetchedAt"]
55377
55513
  };
@@ -55786,8 +55922,9 @@ onStatusChanged: { data: object({
55786
55922
  volatileStateFields: ["lastChangedAt"]
55787
55923
  };
55788
55924
  /**
55789
- * Smart-dishwasher cap — program lifecycle, door / remote-start gates,
55790
- * consumable levels (salt, rinse aid) and common program options.
55925
+ * Smart-dishwasher cap — program lifecycle, door / remote-start gates and
55926
+ * common program options. Salt and rinse aid are NOT here: they are items of
55927
+ * the device's `consumables` cap, like every other device's (D915).
55791
55928
  *
55792
55929
  * Sources: native Bosch Home Connect (`dishwasher` device type). Reusable
55793
55930
  * by any integration that exposes the same program / option surface.
@@ -55835,11 +55972,6 @@ var DishwasherAvailabilitySchema = _enum([
55835
55972
  "offline",
55836
55973
  "description-missing"
55837
55974
  ]);
55838
- var DishwasherConsumableLevelSchema = _enum([
55839
- "ok",
55840
- "low",
55841
- "empty"
55842
- ]);
55843
55975
  var DishwasherStatusSchema = object({
55844
55976
  availability: DishwasherAvailabilitySchema,
55845
55977
  /** Coarse state for compact surfaces; `unavailable` whenever the appliance state is not known. */
@@ -55872,8 +56004,6 @@ var DishwasherStatusSchema = object({
55872
56004
  powerOn: boolean().nullable(),
55873
56005
  /** The raw power state (`On`, `Off`, `Standby`, …); null when not known. */
55874
56006
  powerState: string().nullable(),
55875
- saltLevel: DishwasherConsumableLevelSchema.nullable(),
55876
- rinseAidLevel: DishwasherConsumableLevelSchema.nullable(),
55877
56007
  /**
55878
56008
  * True while the appliance asks for its filter to be cleaned (smart-filter, filter-system or
55879
56009
  * combined care-and-filter reminder raised); false when every such reminder reads clear; null
@@ -64689,60 +64819,17 @@ method(_void(), array(UserSummarySchema), { auth: "admin" }), method(CreateUserI
64689
64819
  auth: "admin",
64690
64820
  access: "delete"
64691
64821
  });
64692
- /**
64693
- * Robot-vacuum cap. Models HA `vacuum.*` entities — anything with a
64694
- * cleaning lifecycle plus a return-to-base / locate surface and an
64695
- * optional fan-speed selector.
64696
- *
64697
- * State follows HA's canonical vacuum lifecycle: `idle` / `cleaning` /
64698
- * `paused` / `returning` / `docked` / `error`. `batteryLevel`
64699
- * (0..100) is nullable — some vacuums don't report a battery
64700
- * percentage. `fanSpeed` is the current speed token (provider-verbatim,
64701
- * e.g. `'standard'` / `'turbo'`) and `availableFanSpeeds` lists the
64702
- * tokens the hardware accepts so the UI renders only supported choices.
64703
- *
64704
- * The `setFanSpeed` method takes the bare `speed` token — the provider
64705
- * validates it against the vacuum's own list. `locate` triggers the
64706
- * find-me chirp; `returnToBase` sends it home.
64707
- *
64708
- * Consumable / waste tanks: `cleanWater` / `dirtyWater` / `detergent` /
64709
- * `dustBin` each carry a nullable `{ level (0..100 %), status ('ok' |
64710
- * 'low' | 'full') }` reading. Native providers (e.g. Dreame, Roborock)
64711
- * SHOULD populate whichever tanks the hardware has — leave a field `null`
64712
- * only when the device has no such tank at all, and use a `TankStatus`
64713
- * with both inner fields `null` when the tank exists but its level is
64714
- * currently unknown. HA `vacuum.*` entities expose no per-tank telemetry,
64715
- * so the HA provider leaves all four `null`.
64716
- */
64717
- var VacuumStateSchema = _enum([
64718
- "idle",
64719
- "cleaning",
64720
- "paused",
64721
- "returning",
64722
- "docked",
64723
- "drying",
64724
- "error"
64725
- ]);
64726
- /**
64727
- * One consumable / waste tank on a robot vacuum (clean-water, dirty-water,
64728
- * detergent or dust-bin). A tank can report a numeric fill `level` (0..100),
64729
- * a discrete `status` (binary-style hardware), or both. Both `null` means the
64730
- * level is currently unknown; the OWNING field being `null` means the
64731
- * hardware has no such tank at all.
64732
- */
64733
- var TankStatusSchema = object({
64734
- /** Numeric fill 0..100 when the hardware reports a percentage; null otherwise. */
64735
- level: number().min(0).max(100).nullable(),
64736
- /** Discrete state when the hardware is binary-mode; null otherwise. */
64737
- status: _enum([
64738
- "ok",
64739
- "low",
64740
- "full"
64741
- ]).nullable()
64742
- });
64743
64822
  var VacuumControlStatusSchema = object({
64744
64823
  /** Lifecycle state of the vacuum. */
64745
- state: VacuumStateSchema,
64824
+ state: _enum([
64825
+ "idle",
64826
+ "cleaning",
64827
+ "paused",
64828
+ "returning",
64829
+ "docked",
64830
+ "drying",
64831
+ "error"
64832
+ ]),
64746
64833
  /** 0..100 battery percentage. Null when the device has no battery
64747
64834
  * reading. */
64748
64835
  batteryLevel: number().min(0).max(100).nullable(),
@@ -64751,14 +64838,6 @@ var VacuumControlStatusSchema = object({
64751
64838
  fanSpeed: string().nullable(),
64752
64839
  /** Speed tokens the hardware accepts — drives the UI selector. */
64753
64840
  availableFanSpeeds: array(string()),
64754
- /** Clean-water (mop) tank. Null when the hardware has no clean-water tank. */
64755
- cleanWater: TankStatusSchema.nullable(),
64756
- /** Dirty-water (recovery) tank. Null when the hardware has no dirty-water tank. */
64757
- dirtyWater: TankStatusSchema.nullable(),
64758
- /** Detergent tank. Null when the hardware has no detergent tank. */
64759
- detergent: TankStatusSchema.nullable(),
64760
- /** Dust bin. Null when the hardware has no dust bin. */
64761
- dustBin: TankStatusSchema.nullable(),
64762
64841
  /** 0..100 cleaning-completion percentage of the current task, or null. */
64763
64842
  progressPercent: number().min(0).max(100).nullable(),
64764
64843
  /** Current error code (0 / null = no error). */
@@ -64820,35 +64899,14 @@ var vacuumControlCapability = {
64820
64899
  */
64821
64900
  durability: "session",
64822
64901
  /**
64823
- * History (D850): recorded series. Tank levels are fixed-object paths (`cleanWater.level`, ...).
64902
+ * History (D850): recorded series. The tanks moved to `consumables` (D915), whose
64903
+ * items are keyed by runtime ids and record no history.
64824
64904
  */
64825
- history: { fields: {
64826
- batteryLevel: {
64827
- kind: "gauge",
64828
- unit: "%",
64829
- deadband: 2
64830
- },
64831
- "cleanWater.level": {
64832
- kind: "gauge",
64833
- unit: "%",
64834
- deadband: 2
64835
- },
64836
- "dirtyWater.level": {
64837
- kind: "gauge",
64838
- unit: "%",
64839
- deadband: 2
64840
- },
64841
- "detergent.level": {
64842
- kind: "gauge",
64843
- unit: "%",
64844
- deadband: 2
64845
- },
64846
- "dustBin.level": {
64847
- kind: "gauge",
64848
- unit: "%",
64849
- deadband: 2
64850
- }
64851
- } }
64905
+ history: { fields: { batteryLevel: {
64906
+ kind: "gauge",
64907
+ unit: "%",
64908
+ deadband: 2
64909
+ } } }
64852
64910
  };
64853
64911
  var ValveStatusSchema = object({
64854
64912
  /** Lifecycle state of the valve. */
@@ -68759,6 +68817,12 @@ Object.freeze({
68759
68817
  addonId: null,
68760
68818
  access: "create"
68761
68819
  },
68820
+ "deviceHistory.deleteOrphanSeries": {
68821
+ capName: "device-history",
68822
+ capScope: "system",
68823
+ addonId: null,
68824
+ access: "delete"
68825
+ },
68762
68826
  "deviceHistory.getDeviceEnabled": {
68763
68827
  capName: "device-history",
68764
68828
  capScope: "system",
@@ -68777,6 +68841,12 @@ Object.freeze({
68777
68841
  addonId: null,
68778
68842
  access: "view"
68779
68843
  },
68844
+ "deviceHistory.listOrphanSeries": {
68845
+ capName: "device-history",
68846
+ capScope: "system",
68847
+ addonId: null,
68848
+ access: "view"
68849
+ },
68780
68850
  "deviceHistory.listSeries": {
68781
68851
  capName: "device-history",
68782
68852
  capScope: "system",
@@ -78782,7 +78852,7 @@ var STATE_SUMMARY_VARS = [
78782
78852
  ([...RULE_TEXT], [...COMBINED_ALARM]),
78783
78853
  ([...RULE_TEXT], [...DEVICE_EVENTS]),
78784
78854
  ([...RULE_TEXT], [...BATTERY, ...CONSUMABLE]),
78785
- ([...RULE_TEXT], [...CONSUMABLE]),
78855
+ ([...RULE_TEXT], [...CONSUMABLE, ...TANK]),
78786
78856
  ([...RULE_TEXT], [...TANK]),
78787
78857
  [...RULE_TEXT],
78788
78858
  ([...RULE_TEXT], [...UPDATES, ...ALERT_EPISODE]),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-terminal",
3
- "version": "0.1.148",
3
+ "version": "0.1.150",
4
4
  "description": "Interactive terminal sessions (pty + xterm) as a CamStack addon",
5
5
  "keywords": [
6
6
  "camstack",