@camstack/addon-provider-homeassistant 1.2.48 → 1.2.50

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/addon.js CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_dist = require("./dist-D_G71rhM.js");
2
+ const require_dist = require("./dist-C0k9HqhA.js");
3
3
  let node_crypto = require("node:crypto");
4
4
  let node_zlib = require("node:zlib");
5
5
  //#region src/ha-device-source.ts
package/dist/addon.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as presenceCapability, A as controlCapability, At as EventCategory, B as humiditySensorCapability, C as buildAddonRouteProvider, Ct as number, D as colorCapability, Dt as union, E as climateControlCapability, Et as string, F as eventEmitterCapability, G as motionCapability, H as lawnMowerControlCapability, I as fanControlCapability, J as notifierCapability, K as normalizeUnit, L as floodCapability, M as deviceAdoptionCapability, O as connectivityCapability, Ot as unknown, P as enumSensorCapability, Q as prepareNotification, R as gasCapability, S as brokerCapability, St as literal, T as carbonMonoxideCapability, Tt as record, U as lockControlCapability, V as imageCapability, W as mediaPlayerCapability, Y as numericSensorCapability, Z as powerMeterCapability, _ as automationControlCapability, _t as createEvent, at as temperatureSensorCapability, b as binaryCapability, bt as array, ct as valveCapability, d as TargetSchema, dt as weatherCapability, et as pressureSensorCapability, f as accessoriesCapability, ft as errMsg, g as ambientLightSensorCapability, gt as DeviceType, h as alarmPanelCapability, ht as DeviceRole, it as tamperCapability, j as coverCapability, k as contactCapability, kt as url, lt as vibrationCapability, m as airQualitySensorCapability, mt as DeviceFeature, n as BaseDevice, nt as smokeCapability, ot as updateCapability, p as addonRoutesCapability, q as notificationOutputCapability, r as BaseDeviceProvider, rt as switchCapability, s as EnumSensorDateTimeFormatSchema, st as vacuumControlCapability, tt as scriptRunnerCapability, ut as waterHeaterCapability, v as batteryCapability, w as buttonCapability, wt as object, x as brightnessCapability, xt as discriminatedUnion, y as bestLocationMatch, yt as _enum, z as humidifierCapability } from "./dist-DlrKePv3.mjs";
1
+ import { $ as presenceCapability, A as controlCapability, At as EventCategory, B as humiditySensorCapability, C as buildAddonRouteProvider, Ct as number, D as colorCapability, Dt as union, E as climateControlCapability, Et as string, F as eventEmitterCapability, G as motionCapability, H as lawnMowerControlCapability, I as fanControlCapability, J as notifierCapability, K as normalizeUnit, L as floodCapability, M as deviceAdoptionCapability, O as connectivityCapability, Ot as unknown, P as enumSensorCapability, Q as prepareNotification, R as gasCapability, S as brokerCapability, St as literal, T as carbonMonoxideCapability, Tt as record, U as lockControlCapability, V as imageCapability, W as mediaPlayerCapability, Y as numericSensorCapability, Z as powerMeterCapability, _ as automationControlCapability, _t as createEvent, at as temperatureSensorCapability, b as binaryCapability, bt as array, ct as valveCapability, d as TargetSchema, dt as weatherCapability, et as pressureSensorCapability, f as accessoriesCapability, ft as errMsg, g as ambientLightSensorCapability, gt as DeviceType, h as alarmPanelCapability, ht as DeviceRole, it as tamperCapability, j as coverCapability, k as contactCapability, kt as url, lt as vibrationCapability, m as airQualitySensorCapability, mt as DeviceFeature, n as BaseDevice, nt as smokeCapability, ot as updateCapability, p as addonRoutesCapability, q as notificationOutputCapability, r as BaseDeviceProvider, rt as switchCapability, s as EnumSensorDateTimeFormatSchema, st as vacuumControlCapability, tt as scriptRunnerCapability, ut as waterHeaterCapability, v as batteryCapability, w as buttonCapability, wt as object, x as brightnessCapability, xt as discriminatedUnion, y as bestLocationMatch, yt as _enum, z as humidifierCapability } from "./dist-D-btrtuv.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { brotliCompressSync, deflateSync, gzipSync } from "node:zlib";
4
4
  //#region src/ha-device-source.ts
@@ -1,4 +1,4 @@
1
- //#region ../types/dist/event-category-CIa_iT6b.mjs
1
+ //#region ../types/dist/event-category-BZL-fdNj.mjs
2
2
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
3
3
  EventCategory["SystemBoot"] = "system.boot";
4
4
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -435,7 +435,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
435
435
  EventCategory["MetricsNodeResourcesSnapshot"] = "metrics.node-resources-snapshot";
436
436
  /**
437
437
  * Periodic per-node process-tree snapshot (camstack-related pids
438
- * with ghost / managed / root classification). Emitted ~0.2 Hz by
438
+ * with root / managed / system classification). Emitted ~0.2 Hz by
439
439
  * the metrics-provider addon. Drives the Cluster → Processes tab
440
440
  * without polling `metricsProvider.listNodeProcesses`.
441
441
  */
@@ -11499,6 +11499,19 @@ var SettingsRecordSchema = object({
11499
11499
  data: record(string(), unknown())
11500
11500
  });
11501
11501
  /**
11502
+ * One record of a BULK insert — {@link SettingsRecordSchema} with the id made
11503
+ * optional.
11504
+ *
11505
+ * A separate schema rather than loosening the shared one: every other method
11506
+ * on this cap addresses a row BY its id, and making that field optional
11507
+ * everywhere would turn a forgotten key into a silently generated one on
11508
+ * `update` and `delete` as well.
11509
+ */
11510
+ var BulkRecordSchema = object({
11511
+ id: string().optional(),
11512
+ data: record(string(), unknown())
11513
+ });
11514
+ /**
11502
11515
  * Column declaration for a structured (SQL-backed) collection.
11503
11516
  *
11504
11517
  * Logical types — the backend translates each to the matching SQLite
@@ -11555,6 +11568,10 @@ method(object({
11555
11568
  collection: string(),
11556
11569
  record: SettingsRecordSchema
11557
11570
  }), _void(), { kind: "mutation" }), method(object({
11571
+ namespace: string().optional(),
11572
+ collection: string(),
11573
+ records: array(BulkRecordSchema).readonly()
11574
+ }), object({ inserted: number().int() }), { kind: "mutation" }), method(object({
11558
11575
  namespace: string().optional(),
11559
11576
  collection: string(),
11560
11577
  id: string(),
@@ -11663,6 +11680,13 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
11663
11680
  }), _void(), {
11664
11681
  kind: "mutation",
11665
11682
  auth: "admin"
11683
+ }), method(object({
11684
+ namespace: string().optional(),
11685
+ collection: string(),
11686
+ records: array(BulkRecordSchema).readonly()
11687
+ }), object({ inserted: number().int() }), {
11688
+ kind: "mutation",
11689
+ auth: "admin"
11666
11690
  }), method(object({
11667
11691
  namespace: string().optional(),
11668
11692
  collection: string(),
@@ -13680,6 +13704,68 @@ method(LogEntrySchema, _void(), { kind: "mutation" }), method(object({
13680
13704
  limit: number().optional(),
13681
13705
  tags: record(string(), string()).optional()
13682
13706
  }), array(LogEntrySchema).readonly());
13707
+ var LoadContributionSchema = object({
13708
+ role: _enum([
13709
+ "decode",
13710
+ "transcode",
13711
+ "recording",
13712
+ "streaming",
13713
+ "detection"
13714
+ ]),
13715
+ /**
13716
+ * The NUMERIC device id — the same value every log line carries as
13717
+ * `tags.deviceId`. `null` means this cost genuinely belongs to no single
13718
+ * camera (a shared pool), NOT that the contributor forgot to look it up: a
13719
+ * contributor that cannot name its camera must not emit the entry at all,
13720
+ * because an unnamed per-camera entry is indistinguishable from a shared one
13721
+ * and would quietly turn one camera's cost into everybody's.
13722
+ */
13723
+ deviceId: number().int().positive().nullable(),
13724
+ attribution: _enum([
13725
+ "measured",
13726
+ "accounted",
13727
+ "unattributable"
13728
+ ]),
13729
+ /**
13730
+ * What ONE entry is, in the contributor's own words — `615/high`,
13731
+ * `617/native`, `cuda:0 shared pool`. Free text because the unit differs per
13732
+ * family and inventing a common one would lose the only information that
13733
+ * makes two entries for the same camera distinguishable.
13734
+ */
13735
+ unit: string(),
13736
+ /**
13737
+ * The OS process this cost lives in, when there is one. Present so a
13738
+ * consumer can (a) tell two generations of the same unit apart across a
13739
+ * restart, and (b) subtract claimed processes from the node's process
13740
+ * snapshot to see what NOBODY claimed. Absent for an entry that owns no
13741
+ * process of its own.
13742
+ */
13743
+ pid: number().int().positive().optional(),
13744
+ /**
13745
+ * When this generation started. The pid's incarnation marker: a consumer
13746
+ * differencing {@link LoadContributionSchema.shape.cpuSeconds} must drop the
13747
+ * window when this changes, because the counter restarted from zero in a new
13748
+ * process.
13749
+ */
13750
+ startedAtMs: number().optional(),
13751
+ /**
13752
+ * CUMULATIVE CPU seconds this unit has consumed since it started — user +
13753
+ * system, read from the child's own `/proc/<pid>/stat` at the moment the
13754
+ * contribution is asked for.
13755
+ *
13756
+ * Cumulative and not a rate on purpose: a rate needs a window, a window
13757
+ * needs a sampler, and a new per-node sampler is the defect half of
13758
+ * `docs/architecture/load-ledger.md` documents. A counter can be differenced
13759
+ * by whoever already keeps a history; a rate cannot be un-averaged.
13760
+ *
13761
+ * Absent — never zero — on a node with no `/proc`, on a read failure, and on
13762
+ * an entry with no process.
13763
+ */
13764
+ cpuSeconds: number().optional(),
13765
+ /** Resident bytes of this unit's process, same source and same rules. */
13766
+ rssBytes: number().optional()
13767
+ });
13768
+ method(_void(), array(LoadContributionSchema).readonly());
13683
13769
  /**
13684
13770
  * `login-method` — collection cap through which auth addons contribute
13685
13771
  * their pre-auth login surfaces to the login page. This is the SINGLE,
@@ -13883,8 +13969,7 @@ var NodeProcessSchema = object({
13883
13969
  classification: _enum([
13884
13970
  "root",
13885
13971
  "managed",
13886
- "system",
13887
- "ghost"
13972
+ "system"
13888
13973
  ]),
13889
13974
  /** `$process` addon binding when `managed`, else null. */
13890
13975
  addonId: string().nullable(),
@@ -13892,22 +13977,39 @@ var NodeProcessSchema = object({
13892
13977
  nodeId: string().nullable(),
13893
13978
  /** Truncated command line. */
13894
13979
  command: string(),
13980
+ /**
13981
+ * `ps pcpu` — CPU averaged over the process's WHOLE LIFETIME, not a rate.
13982
+ * On a runner up for days it barely moves. Fine as a column, useless as a
13983
+ * series: use `cpuMainPercent + cpuGcPercent` for anything time-varying.
13984
+ */
13895
13985
  cpuPercent: number(),
13896
13986
  memoryRssBytes: number(),
13987
+ /**
13988
+ * Instantaneous CPU% of the process's own threads over the last
13989
+ * process-snapshot window, from a `/proc/<pid>/task/*` tick delta.
13990
+ *
13991
+ * `null` = UNKNOWN, never zero: no previous sample yet (first tick after
13992
+ * boot), the pid was recycled, or this node is not Linux.
13993
+ */
13994
+ cpuMainPercent: number().nullable(),
13995
+ /**
13996
+ * Instantaneous CPU% of V8's `V8Worker` platform pool over the same window.
13997
+ *
13998
+ * This is the number that rewrote the 2026-08-27 diagnosis — hub-main 73%,
13999
+ * `stream-broker` 61% (`docs/architecture/load-ledger.md`). A CPU chart that
14000
+ * does not separate it from `cpuMainPercent` shows "busy" where the truth is
14001
+ * "allocating too much".
14002
+ *
14003
+ * Concurrent GC is the dominant tenant of that pool but not the only one
14004
+ * (background compilation runs there too), so it is reported as
14005
+ * "GC / V8 helpers" rather than as pure collection time. `null` has the same
14006
+ * meaning as on `cpuMainPercent`.
14007
+ */
14008
+ cpuGcPercent: number().nullable(),
14009
+ /** Threads seen in the tick scan. `null` under the same conditions. */
14010
+ threadCount: number().nullable(),
13897
14011
  /** Wall-clock uptime (seconds). Parsed from `ps etime`. */
13898
- uptimeSec: number(),
13899
- /** True when ancestor walk reaches `ppid=1` (reparented to init/launchd). */
13900
- orphaned: boolean()
13901
- });
13902
- var KillProcessInputSchema = object({
13903
- pid: number(),
13904
- /** Force = SIGKILL. Default is SIGTERM. */
13905
- force: boolean().optional()
13906
- });
13907
- var KillProcessResultSchema = object({
13908
- success: boolean(),
13909
- reason: string().optional(),
13910
- signal: _enum(["SIGTERM", "SIGKILL"]).optional()
14012
+ uptimeSec: number()
13911
14013
  });
13912
14014
  var DumpHeapSnapshotInputSchema = object({
13913
14015
  /** The addon whose runner should dump a heap snapshot. */
@@ -13920,6 +14022,104 @@ var DumpHeapSnapshotResultSchema = object({
13920
14022
  pid: number().optional(),
13921
14023
  reason: string().optional()
13922
14024
  });
14025
+ /**
14026
+ * One point of one function's series.
14027
+ *
14028
+ * The unsuffixed fields are the bucket's **MAXIMUM**, and that choice is the
14029
+ * point of the whole surface. The two obvious reductions both lie: a mean per
14030
+ * bucket smears a spike away, and taking every Nth sample skips it outright.
14031
+ * Either would give us a tool built to find peaks that does not show peaks.
14032
+ * `...Min` carries the other end, `samples` says how many raw snapshots folded
14033
+ * into the bucket, and a mean stays derivable where it is wanted.
14034
+ *
14035
+ * An UNREDUCED point is a one-sample bucket: `samples === 1` and each `...Min`
14036
+ * equals its unsuffixed twin. Reduced and unreduced are the same shape, so a
14037
+ * caller cannot tell which it received — which is what "one reader" means.
14038
+ */
14039
+ var LoadPointSchema = object({
14040
+ /** Bucket START, or the snapshot's own timestamp when unreduced. */
14041
+ atMs: number(),
14042
+ /** Raw snapshots in this bucket. Never 0 — AN EMPTY BUCKET IS ABSENT. */
14043
+ samples: number().int(),
14044
+ /**
14045
+ * `null` = UNKNOWN and it PROPAGATES: a bucket is null unless every process
14046
+ * of every snapshot in it reported a thread split. A partial sum is a
14047
+ * smaller number that looks exactly as real as a complete one.
14048
+ */
14049
+ cpuMainPercent: number().nullable(),
14050
+ cpuMainPercentMin: number().nullable(),
14051
+ cpuGcPercent: number().nullable(),
14052
+ cpuGcPercentMin: number().nullable(),
14053
+ /** Lifetime-average CPU%, summed. Always known — and never a rate. */
14054
+ cpuLifetimePercent: number(),
14055
+ cpuLifetimePercentMin: number(),
14056
+ memoryRssBytes: number(),
14057
+ memoryRssBytesMin: number(),
14058
+ processCount: number().int(),
14059
+ processCountMin: number().int()
14060
+ });
14061
+ /** One function's series. `key` is an addonId, `__root__` or `__unattributed__`. */
14062
+ var LoadFunctionSeriesSchema = object({
14063
+ key: string(),
14064
+ kind: _enum([
14065
+ "addon",
14066
+ "root",
14067
+ "unattributed"
14068
+ ]),
14069
+ /** Oldest-first. A missing interval is MISSING — never zero-filled. */
14070
+ points: array(LoadPointSchema).readonly()
14071
+ });
14072
+ var NodeLoadSeriesSchema = object({
14073
+ nodeId: string(),
14074
+ /** One entry per function seen in the window, heaviest-first. */
14075
+ series: array(LoadFunctionSeriesSchema).readonly(),
14076
+ /**
14077
+ * Width of one returned bucket, in ms. Equals the sampling cadence when no
14078
+ * reduction was needed — so a caller can always say what one point covers
14079
+ * without having to know whether it was reduced.
14080
+ */
14081
+ bucketMs: number(),
14082
+ /** Raw snapshots that went into this answer, across both tiers. */
14083
+ retainedSamples: number(),
14084
+ /** Oldest snapshot represented, or `null` when nothing is retained. */
14085
+ oldestAtMs: number().nullable(),
14086
+ /** The fixed sampling cadence in force on the cluster, in ms. */
14087
+ cadenceMs: number(),
14088
+ /**
14089
+ * Did the DURABLE tier contribute? `false` means the answer is the hot ring
14090
+ * alone — an agent (which holds no table), or a store that refused.
14091
+ * Reported because "the last hour" and "the last six hours" are different
14092
+ * questions and an operator must not have to guess which was answered.
14093
+ */
14094
+ durable: boolean()
14095
+ });
14096
+ var GetLoadSeriesInputSchema = object({
14097
+ /**
14098
+ * The node whose series is wanted.
14099
+ *
14100
+ * NOT named `nodeId`: the generated cap router strips a top-level
14101
+ * `nodeId` from every method input and uses it to ROUTE the call to
14102
+ * that node's provider (`generated-cap-routers.ts`). A series target
14103
+ * called `nodeId` would silently become a routing pin and never reach
14104
+ * the provider. The hub holds every node it hears from, so the
14105
+ * ordinary call is unpinned — answered by the hub, for any node.
14106
+ */
14107
+ forNodeId: string(),
14108
+ /**
14109
+ * EXCLUSIVE lower bound. A caller passes the newest `atMs` it already
14110
+ * holds and receives only what it is missing, so seeding a live chart
14111
+ * from this method cannot double a point already drawn.
14112
+ */
14113
+ sinceMs: number().optional(),
14114
+ /**
14115
+ * Most points the caller wants PER FUNCTION. The window is reduced to fit,
14116
+ * preserving min and max per bucket.
14117
+ *
14118
+ * Absent means NO reduction — legitimate for a short window and a trap for a
14119
+ * long one, which is why a chart passes its own pixel width.
14120
+ */
14121
+ maxPoints: number().int().positive().optional()
14122
+ });
13923
14123
  var SystemMetricsSchema = object({
13924
14124
  cpuPercent: number(),
13925
14125
  memoryPercent: number(),
@@ -13930,10 +14130,7 @@ var SystemMetricsSchema = object({
13930
14130
  gpuPercent: number().optional(),
13931
14131
  gpuMemoryPercent: number().optional()
13932
14132
  });
13933
- method(_void(), SystemResourceSnapshotSchema), method(_void(), SystemResourceSnapshotSchema.nullable()), method(_void(), SystemMetricsSchema), method(object({ dirPath: string() }), DiskSpaceInfoSchema), method(_void(), MetricsGpuInfoSchema.nullable()), method(_void(), number().nullable()), method(object({ pids: array(number()) }), array(PidResourceStatsSchema)), method(_void(), array(AddonInstanceSchema).readonly()), method(object({ addonId: string() }), PidResourceStatsSchema.nullable()), method(_void(), array(NodeProcessSchema).readonly()), method(KillProcessInputSchema, KillProcessResultSchema, {
13934
- kind: "mutation",
13935
- auth: "admin"
13936
- }), method(DumpHeapSnapshotInputSchema, DumpHeapSnapshotResultSchema, {
14133
+ method(_void(), SystemResourceSnapshotSchema), method(_void(), SystemResourceSnapshotSchema.nullable()), method(_void(), SystemMetricsSchema), method(object({ dirPath: string() }), DiskSpaceInfoSchema), method(_void(), MetricsGpuInfoSchema.nullable()), method(_void(), number().nullable()), method(object({ pids: array(number()) }), array(PidResourceStatsSchema)), method(_void(), array(AddonInstanceSchema).readonly()), method(object({ addonId: string() }), PidResourceStatsSchema.nullable()), method(_void(), array(NodeProcessSchema).readonly()), method(GetLoadSeriesInputSchema, NodeLoadSeriesSchema), method(DumpHeapSnapshotInputSchema, DumpHeapSnapshotResultSchema, {
13937
14134
  kind: "mutation",
13938
14135
  auth: "admin"
13939
14136
  });
@@ -29382,6 +29579,15 @@ var LoggingSettingsPatchSchema = object({
29382
29579
  * authority over the whole hierarchy and answers for every layer, so the
29383
29580
  * layer selector needs a name the transport does not already own.
29384
29581
  */
29582
+ /**
29583
+ * One contribution, plus WHO reported it.
29584
+ *
29585
+ * The addon and node are added by the hub as it enumerates providers, never by
29586
+ * the contributor: an addon reporting its own identity could report somebody
29587
+ * else's, and the whole point of this surface is that no claim is made by
29588
+ * anyone but its owner.
29589
+ */
29590
+ var ReportedLoadContributionSchema = LoadContributionSchema.extend({ addonId: string() });
29385
29591
  var GetLoggingSettingsInputSchema = object({
29386
29592
  scopeNodeId: string().optional(),
29387
29593
  /**
@@ -29440,7 +29646,7 @@ method(_void(), FeatureManifestSchema), method(_void(), HealthStatusSchema), met
29440
29646
  }), method(_void(), SiteLocationStatusSchema, {
29441
29647
  kind: "mutation",
29442
29648
  auth: "admin"
29443
- }), method(_void(), RequestCensusStatusSchema, { auth: "admin" }), method(GetLoggingSettingsInputSchema, LoggingSettingsStateSchema, { auth: "admin" }), method(SetLoggingSettingsInputSchema, LoggingSettingsStateSchema, {
29649
+ }), method(_void(), RequestCensusStatusSchema, { auth: "admin" }), method(_void(), array(ReportedLoadContributionSchema).readonly(), { auth: "admin" }), method(GetLoggingSettingsInputSchema, LoggingSettingsStateSchema, { auth: "admin" }), method(SetLoggingSettingsInputSchema, LoggingSettingsStateSchema, {
29444
29650
  kind: "mutation",
29445
29651
  auth: "admin"
29446
29652
  });
@@ -32464,6 +32670,12 @@ Object.freeze({
32464
32670
  addonId: null,
32465
32671
  access: "create"
32466
32672
  },
32673
+ "dataStoreProvider.insertMany": {
32674
+ capName: "data-store-provider",
32675
+ capScope: "system",
32676
+ addonId: null,
32677
+ access: "create"
32678
+ },
32467
32679
  "dataStoreProvider.isEmpty": {
32468
32680
  capName: "data-store-provider",
32469
32681
  capScope: "system",
@@ -33778,6 +33990,12 @@ Object.freeze({
33778
33990
  addonId: null,
33779
33991
  access: "create"
33780
33992
  },
33993
+ "loadContribution.list": {
33994
+ capName: "load-contribution",
33995
+ capScope: "system",
33996
+ addonId: null,
33997
+ access: "view"
33998
+ },
33781
33999
  "localNetwork.downloadCa": {
33782
34000
  capName: "local-network",
33783
34001
  capScope: "system",
@@ -34078,17 +34296,17 @@ Object.freeze({
34078
34296
  addonId: null,
34079
34297
  access: "view"
34080
34298
  },
34081
- "metricsProvider.getProcessStats": {
34299
+ "metricsProvider.getLoadSeries": {
34082
34300
  capName: "metrics-provider",
34083
34301
  capScope: "system",
34084
34302
  addonId: null,
34085
34303
  access: "view"
34086
34304
  },
34087
- "metricsProvider.killProcess": {
34305
+ "metricsProvider.getProcessStats": {
34088
34306
  capName: "metrics-provider",
34089
34307
  capScope: "system",
34090
34308
  addonId: null,
34091
- access: "create"
34309
+ access: "view"
34092
34310
  },
34093
34311
  "metricsProvider.listAddonInstances": {
34094
34312
  capName: "metrics-provider",
@@ -36100,6 +36318,12 @@ Object.freeze({
36100
36318
  addonId: null,
36101
36319
  access: "create"
36102
36320
  },
36321
+ "settingsStore.insertMany": {
36322
+ capName: "settings-store",
36323
+ capScope: "system",
36324
+ addonId: null,
36325
+ access: "create"
36326
+ },
36103
36327
  "settingsStore.isEmpty": {
36104
36328
  capName: "settings-store",
36105
36329
  capScope: "system",
@@ -36712,6 +36936,12 @@ Object.freeze({
36712
36936
  addonId: null,
36713
36937
  access: "create"
36714
36938
  },
36939
+ "system.getLoadContributions": {
36940
+ capName: "system",
36941
+ capScope: "system",
36942
+ addonId: null,
36943
+ access: "view"
36944
+ },
36715
36945
  "system.getLoggingSettings": {
36716
36946
  capName: "system",
36717
36947
  capScope: "system",
@@ -1,4 +1,4 @@
1
- //#region ../types/dist/event-category-CIa_iT6b.mjs
1
+ //#region ../types/dist/event-category-BZL-fdNj.mjs
2
2
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
3
3
  EventCategory["SystemBoot"] = "system.boot";
4
4
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -435,7 +435,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
435
435
  EventCategory["MetricsNodeResourcesSnapshot"] = "metrics.node-resources-snapshot";
436
436
  /**
437
437
  * Periodic per-node process-tree snapshot (camstack-related pids
438
- * with ghost / managed / root classification). Emitted ~0.2 Hz by
438
+ * with root / managed / system classification). Emitted ~0.2 Hz by
439
439
  * the metrics-provider addon. Drives the Cluster → Processes tab
440
440
  * without polling `metricsProvider.listNodeProcesses`.
441
441
  */
@@ -11499,6 +11499,19 @@ var SettingsRecordSchema = object({
11499
11499
  data: record(string(), unknown())
11500
11500
  });
11501
11501
  /**
11502
+ * One record of a BULK insert — {@link SettingsRecordSchema} with the id made
11503
+ * optional.
11504
+ *
11505
+ * A separate schema rather than loosening the shared one: every other method
11506
+ * on this cap addresses a row BY its id, and making that field optional
11507
+ * everywhere would turn a forgotten key into a silently generated one on
11508
+ * `update` and `delete` as well.
11509
+ */
11510
+ var BulkRecordSchema = object({
11511
+ id: string().optional(),
11512
+ data: record(string(), unknown())
11513
+ });
11514
+ /**
11502
11515
  * Column declaration for a structured (SQL-backed) collection.
11503
11516
  *
11504
11517
  * Logical types — the backend translates each to the matching SQLite
@@ -11555,6 +11568,10 @@ method(object({
11555
11568
  collection: string(),
11556
11569
  record: SettingsRecordSchema
11557
11570
  }), _void(), { kind: "mutation" }), method(object({
11571
+ namespace: string().optional(),
11572
+ collection: string(),
11573
+ records: array(BulkRecordSchema).readonly()
11574
+ }), object({ inserted: number().int() }), { kind: "mutation" }), method(object({
11558
11575
  namespace: string().optional(),
11559
11576
  collection: string(),
11560
11577
  id: string(),
@@ -11663,6 +11680,13 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
11663
11680
  }), _void(), {
11664
11681
  kind: "mutation",
11665
11682
  auth: "admin"
11683
+ }), method(object({
11684
+ namespace: string().optional(),
11685
+ collection: string(),
11686
+ records: array(BulkRecordSchema).readonly()
11687
+ }), object({ inserted: number().int() }), {
11688
+ kind: "mutation",
11689
+ auth: "admin"
11666
11690
  }), method(object({
11667
11691
  namespace: string().optional(),
11668
11692
  collection: string(),
@@ -13680,6 +13704,68 @@ method(LogEntrySchema, _void(), { kind: "mutation" }), method(object({
13680
13704
  limit: number().optional(),
13681
13705
  tags: record(string(), string()).optional()
13682
13706
  }), array(LogEntrySchema).readonly());
13707
+ var LoadContributionSchema = object({
13708
+ role: _enum([
13709
+ "decode",
13710
+ "transcode",
13711
+ "recording",
13712
+ "streaming",
13713
+ "detection"
13714
+ ]),
13715
+ /**
13716
+ * The NUMERIC device id — the same value every log line carries as
13717
+ * `tags.deviceId`. `null` means this cost genuinely belongs to no single
13718
+ * camera (a shared pool), NOT that the contributor forgot to look it up: a
13719
+ * contributor that cannot name its camera must not emit the entry at all,
13720
+ * because an unnamed per-camera entry is indistinguishable from a shared one
13721
+ * and would quietly turn one camera's cost into everybody's.
13722
+ */
13723
+ deviceId: number().int().positive().nullable(),
13724
+ attribution: _enum([
13725
+ "measured",
13726
+ "accounted",
13727
+ "unattributable"
13728
+ ]),
13729
+ /**
13730
+ * What ONE entry is, in the contributor's own words — `615/high`,
13731
+ * `617/native`, `cuda:0 shared pool`. Free text because the unit differs per
13732
+ * family and inventing a common one would lose the only information that
13733
+ * makes two entries for the same camera distinguishable.
13734
+ */
13735
+ unit: string(),
13736
+ /**
13737
+ * The OS process this cost lives in, when there is one. Present so a
13738
+ * consumer can (a) tell two generations of the same unit apart across a
13739
+ * restart, and (b) subtract claimed processes from the node's process
13740
+ * snapshot to see what NOBODY claimed. Absent for an entry that owns no
13741
+ * process of its own.
13742
+ */
13743
+ pid: number().int().positive().optional(),
13744
+ /**
13745
+ * When this generation started. The pid's incarnation marker: a consumer
13746
+ * differencing {@link LoadContributionSchema.shape.cpuSeconds} must drop the
13747
+ * window when this changes, because the counter restarted from zero in a new
13748
+ * process.
13749
+ */
13750
+ startedAtMs: number().optional(),
13751
+ /**
13752
+ * CUMULATIVE CPU seconds this unit has consumed since it started — user +
13753
+ * system, read from the child's own `/proc/<pid>/stat` at the moment the
13754
+ * contribution is asked for.
13755
+ *
13756
+ * Cumulative and not a rate on purpose: a rate needs a window, a window
13757
+ * needs a sampler, and a new per-node sampler is the defect half of
13758
+ * `docs/architecture/load-ledger.md` documents. A counter can be differenced
13759
+ * by whoever already keeps a history; a rate cannot be un-averaged.
13760
+ *
13761
+ * Absent — never zero — on a node with no `/proc`, on a read failure, and on
13762
+ * an entry with no process.
13763
+ */
13764
+ cpuSeconds: number().optional(),
13765
+ /** Resident bytes of this unit's process, same source and same rules. */
13766
+ rssBytes: number().optional()
13767
+ });
13768
+ method(_void(), array(LoadContributionSchema).readonly());
13683
13769
  /**
13684
13770
  * `login-method` — collection cap through which auth addons contribute
13685
13771
  * their pre-auth login surfaces to the login page. This is the SINGLE,
@@ -13883,8 +13969,7 @@ var NodeProcessSchema = object({
13883
13969
  classification: _enum([
13884
13970
  "root",
13885
13971
  "managed",
13886
- "system",
13887
- "ghost"
13972
+ "system"
13888
13973
  ]),
13889
13974
  /** `$process` addon binding when `managed`, else null. */
13890
13975
  addonId: string().nullable(),
@@ -13892,22 +13977,39 @@ var NodeProcessSchema = object({
13892
13977
  nodeId: string().nullable(),
13893
13978
  /** Truncated command line. */
13894
13979
  command: string(),
13980
+ /**
13981
+ * `ps pcpu` — CPU averaged over the process's WHOLE LIFETIME, not a rate.
13982
+ * On a runner up for days it barely moves. Fine as a column, useless as a
13983
+ * series: use `cpuMainPercent + cpuGcPercent` for anything time-varying.
13984
+ */
13895
13985
  cpuPercent: number(),
13896
13986
  memoryRssBytes: number(),
13987
+ /**
13988
+ * Instantaneous CPU% of the process's own threads over the last
13989
+ * process-snapshot window, from a `/proc/<pid>/task/*` tick delta.
13990
+ *
13991
+ * `null` = UNKNOWN, never zero: no previous sample yet (first tick after
13992
+ * boot), the pid was recycled, or this node is not Linux.
13993
+ */
13994
+ cpuMainPercent: number().nullable(),
13995
+ /**
13996
+ * Instantaneous CPU% of V8's `V8Worker` platform pool over the same window.
13997
+ *
13998
+ * This is the number that rewrote the 2026-08-27 diagnosis — hub-main 73%,
13999
+ * `stream-broker` 61% (`docs/architecture/load-ledger.md`). A CPU chart that
14000
+ * does not separate it from `cpuMainPercent` shows "busy" where the truth is
14001
+ * "allocating too much".
14002
+ *
14003
+ * Concurrent GC is the dominant tenant of that pool but not the only one
14004
+ * (background compilation runs there too), so it is reported as
14005
+ * "GC / V8 helpers" rather than as pure collection time. `null` has the same
14006
+ * meaning as on `cpuMainPercent`.
14007
+ */
14008
+ cpuGcPercent: number().nullable(),
14009
+ /** Threads seen in the tick scan. `null` under the same conditions. */
14010
+ threadCount: number().nullable(),
13897
14011
  /** Wall-clock uptime (seconds). Parsed from `ps etime`. */
13898
- uptimeSec: number(),
13899
- /** True when ancestor walk reaches `ppid=1` (reparented to init/launchd). */
13900
- orphaned: boolean()
13901
- });
13902
- var KillProcessInputSchema = object({
13903
- pid: number(),
13904
- /** Force = SIGKILL. Default is SIGTERM. */
13905
- force: boolean().optional()
13906
- });
13907
- var KillProcessResultSchema = object({
13908
- success: boolean(),
13909
- reason: string().optional(),
13910
- signal: _enum(["SIGTERM", "SIGKILL"]).optional()
14012
+ uptimeSec: number()
13911
14013
  });
13912
14014
  var DumpHeapSnapshotInputSchema = object({
13913
14015
  /** The addon whose runner should dump a heap snapshot. */
@@ -13920,6 +14022,104 @@ var DumpHeapSnapshotResultSchema = object({
13920
14022
  pid: number().optional(),
13921
14023
  reason: string().optional()
13922
14024
  });
14025
+ /**
14026
+ * One point of one function's series.
14027
+ *
14028
+ * The unsuffixed fields are the bucket's **MAXIMUM**, and that choice is the
14029
+ * point of the whole surface. The two obvious reductions both lie: a mean per
14030
+ * bucket smears a spike away, and taking every Nth sample skips it outright.
14031
+ * Either would give us a tool built to find peaks that does not show peaks.
14032
+ * `...Min` carries the other end, `samples` says how many raw snapshots folded
14033
+ * into the bucket, and a mean stays derivable where it is wanted.
14034
+ *
14035
+ * An UNREDUCED point is a one-sample bucket: `samples === 1` and each `...Min`
14036
+ * equals its unsuffixed twin. Reduced and unreduced are the same shape, so a
14037
+ * caller cannot tell which it received — which is what "one reader" means.
14038
+ */
14039
+ var LoadPointSchema = object({
14040
+ /** Bucket START, or the snapshot's own timestamp when unreduced. */
14041
+ atMs: number(),
14042
+ /** Raw snapshots in this bucket. Never 0 — AN EMPTY BUCKET IS ABSENT. */
14043
+ samples: number().int(),
14044
+ /**
14045
+ * `null` = UNKNOWN and it PROPAGATES: a bucket is null unless every process
14046
+ * of every snapshot in it reported a thread split. A partial sum is a
14047
+ * smaller number that looks exactly as real as a complete one.
14048
+ */
14049
+ cpuMainPercent: number().nullable(),
14050
+ cpuMainPercentMin: number().nullable(),
14051
+ cpuGcPercent: number().nullable(),
14052
+ cpuGcPercentMin: number().nullable(),
14053
+ /** Lifetime-average CPU%, summed. Always known — and never a rate. */
14054
+ cpuLifetimePercent: number(),
14055
+ cpuLifetimePercentMin: number(),
14056
+ memoryRssBytes: number(),
14057
+ memoryRssBytesMin: number(),
14058
+ processCount: number().int(),
14059
+ processCountMin: number().int()
14060
+ });
14061
+ /** One function's series. `key` is an addonId, `__root__` or `__unattributed__`. */
14062
+ var LoadFunctionSeriesSchema = object({
14063
+ key: string(),
14064
+ kind: _enum([
14065
+ "addon",
14066
+ "root",
14067
+ "unattributed"
14068
+ ]),
14069
+ /** Oldest-first. A missing interval is MISSING — never zero-filled. */
14070
+ points: array(LoadPointSchema).readonly()
14071
+ });
14072
+ var NodeLoadSeriesSchema = object({
14073
+ nodeId: string(),
14074
+ /** One entry per function seen in the window, heaviest-first. */
14075
+ series: array(LoadFunctionSeriesSchema).readonly(),
14076
+ /**
14077
+ * Width of one returned bucket, in ms. Equals the sampling cadence when no
14078
+ * reduction was needed — so a caller can always say what one point covers
14079
+ * without having to know whether it was reduced.
14080
+ */
14081
+ bucketMs: number(),
14082
+ /** Raw snapshots that went into this answer, across both tiers. */
14083
+ retainedSamples: number(),
14084
+ /** Oldest snapshot represented, or `null` when nothing is retained. */
14085
+ oldestAtMs: number().nullable(),
14086
+ /** The fixed sampling cadence in force on the cluster, in ms. */
14087
+ cadenceMs: number(),
14088
+ /**
14089
+ * Did the DURABLE tier contribute? `false` means the answer is the hot ring
14090
+ * alone — an agent (which holds no table), or a store that refused.
14091
+ * Reported because "the last hour" and "the last six hours" are different
14092
+ * questions and an operator must not have to guess which was answered.
14093
+ */
14094
+ durable: boolean()
14095
+ });
14096
+ var GetLoadSeriesInputSchema = object({
14097
+ /**
14098
+ * The node whose series is wanted.
14099
+ *
14100
+ * NOT named `nodeId`: the generated cap router strips a top-level
14101
+ * `nodeId` from every method input and uses it to ROUTE the call to
14102
+ * that node's provider (`generated-cap-routers.ts`). A series target
14103
+ * called `nodeId` would silently become a routing pin and never reach
14104
+ * the provider. The hub holds every node it hears from, so the
14105
+ * ordinary call is unpinned — answered by the hub, for any node.
14106
+ */
14107
+ forNodeId: string(),
14108
+ /**
14109
+ * EXCLUSIVE lower bound. A caller passes the newest `atMs` it already
14110
+ * holds and receives only what it is missing, so seeding a live chart
14111
+ * from this method cannot double a point already drawn.
14112
+ */
14113
+ sinceMs: number().optional(),
14114
+ /**
14115
+ * Most points the caller wants PER FUNCTION. The window is reduced to fit,
14116
+ * preserving min and max per bucket.
14117
+ *
14118
+ * Absent means NO reduction — legitimate for a short window and a trap for a
14119
+ * long one, which is why a chart passes its own pixel width.
14120
+ */
14121
+ maxPoints: number().int().positive().optional()
14122
+ });
13923
14123
  var SystemMetricsSchema = object({
13924
14124
  cpuPercent: number(),
13925
14125
  memoryPercent: number(),
@@ -13930,10 +14130,7 @@ var SystemMetricsSchema = object({
13930
14130
  gpuPercent: number().optional(),
13931
14131
  gpuMemoryPercent: number().optional()
13932
14132
  });
13933
- method(_void(), SystemResourceSnapshotSchema), method(_void(), SystemResourceSnapshotSchema.nullable()), method(_void(), SystemMetricsSchema), method(object({ dirPath: string() }), DiskSpaceInfoSchema), method(_void(), MetricsGpuInfoSchema.nullable()), method(_void(), number().nullable()), method(object({ pids: array(number()) }), array(PidResourceStatsSchema)), method(_void(), array(AddonInstanceSchema).readonly()), method(object({ addonId: string() }), PidResourceStatsSchema.nullable()), method(_void(), array(NodeProcessSchema).readonly()), method(KillProcessInputSchema, KillProcessResultSchema, {
13934
- kind: "mutation",
13935
- auth: "admin"
13936
- }), method(DumpHeapSnapshotInputSchema, DumpHeapSnapshotResultSchema, {
14133
+ method(_void(), SystemResourceSnapshotSchema), method(_void(), SystemResourceSnapshotSchema.nullable()), method(_void(), SystemMetricsSchema), method(object({ dirPath: string() }), DiskSpaceInfoSchema), method(_void(), MetricsGpuInfoSchema.nullable()), method(_void(), number().nullable()), method(object({ pids: array(number()) }), array(PidResourceStatsSchema)), method(_void(), array(AddonInstanceSchema).readonly()), method(object({ addonId: string() }), PidResourceStatsSchema.nullable()), method(_void(), array(NodeProcessSchema).readonly()), method(GetLoadSeriesInputSchema, NodeLoadSeriesSchema), method(DumpHeapSnapshotInputSchema, DumpHeapSnapshotResultSchema, {
13937
14134
  kind: "mutation",
13938
14135
  auth: "admin"
13939
14136
  });
@@ -29382,6 +29579,15 @@ var LoggingSettingsPatchSchema = object({
29382
29579
  * authority over the whole hierarchy and answers for every layer, so the
29383
29580
  * layer selector needs a name the transport does not already own.
29384
29581
  */
29582
+ /**
29583
+ * One contribution, plus WHO reported it.
29584
+ *
29585
+ * The addon and node are added by the hub as it enumerates providers, never by
29586
+ * the contributor: an addon reporting its own identity could report somebody
29587
+ * else's, and the whole point of this surface is that no claim is made by
29588
+ * anyone but its owner.
29589
+ */
29590
+ var ReportedLoadContributionSchema = LoadContributionSchema.extend({ addonId: string() });
29385
29591
  var GetLoggingSettingsInputSchema = object({
29386
29592
  scopeNodeId: string().optional(),
29387
29593
  /**
@@ -29440,7 +29646,7 @@ method(_void(), FeatureManifestSchema), method(_void(), HealthStatusSchema), met
29440
29646
  }), method(_void(), SiteLocationStatusSchema, {
29441
29647
  kind: "mutation",
29442
29648
  auth: "admin"
29443
- }), method(_void(), RequestCensusStatusSchema, { auth: "admin" }), method(GetLoggingSettingsInputSchema, LoggingSettingsStateSchema, { auth: "admin" }), method(SetLoggingSettingsInputSchema, LoggingSettingsStateSchema, {
29649
+ }), method(_void(), RequestCensusStatusSchema, { auth: "admin" }), method(_void(), array(ReportedLoadContributionSchema).readonly(), { auth: "admin" }), method(GetLoggingSettingsInputSchema, LoggingSettingsStateSchema, { auth: "admin" }), method(SetLoggingSettingsInputSchema, LoggingSettingsStateSchema, {
29444
29650
  kind: "mutation",
29445
29651
  auth: "admin"
29446
29652
  });
@@ -32464,6 +32670,12 @@ Object.freeze({
32464
32670
  addonId: null,
32465
32671
  access: "create"
32466
32672
  },
32673
+ "dataStoreProvider.insertMany": {
32674
+ capName: "data-store-provider",
32675
+ capScope: "system",
32676
+ addonId: null,
32677
+ access: "create"
32678
+ },
32467
32679
  "dataStoreProvider.isEmpty": {
32468
32680
  capName: "data-store-provider",
32469
32681
  capScope: "system",
@@ -33778,6 +33990,12 @@ Object.freeze({
33778
33990
  addonId: null,
33779
33991
  access: "create"
33780
33992
  },
33993
+ "loadContribution.list": {
33994
+ capName: "load-contribution",
33995
+ capScope: "system",
33996
+ addonId: null,
33997
+ access: "view"
33998
+ },
33781
33999
  "localNetwork.downloadCa": {
33782
34000
  capName: "local-network",
33783
34001
  capScope: "system",
@@ -34078,17 +34296,17 @@ Object.freeze({
34078
34296
  addonId: null,
34079
34297
  access: "view"
34080
34298
  },
34081
- "metricsProvider.getProcessStats": {
34299
+ "metricsProvider.getLoadSeries": {
34082
34300
  capName: "metrics-provider",
34083
34301
  capScope: "system",
34084
34302
  addonId: null,
34085
34303
  access: "view"
34086
34304
  },
34087
- "metricsProvider.killProcess": {
34305
+ "metricsProvider.getProcessStats": {
34088
34306
  capName: "metrics-provider",
34089
34307
  capScope: "system",
34090
34308
  addonId: null,
34091
- access: "create"
34309
+ access: "view"
34092
34310
  },
34093
34311
  "metricsProvider.listAddonInstances": {
34094
34312
  capName: "metrics-provider",
@@ -36100,6 +36318,12 @@ Object.freeze({
36100
36318
  addonId: null,
36101
36319
  access: "create"
36102
36320
  },
36321
+ "settingsStore.insertMany": {
36322
+ capName: "settings-store",
36323
+ capScope: "system",
36324
+ addonId: null,
36325
+ access: "create"
36326
+ },
36103
36327
  "settingsStore.isEmpty": {
36104
36328
  capName: "settings-store",
36105
36329
  capScope: "system",
@@ -36712,6 +36936,12 @@ Object.freeze({
36712
36936
  addonId: null,
36713
36937
  access: "create"
36714
36938
  },
36939
+ "system.getLoadContributions": {
36940
+ capName: "system",
36941
+ capScope: "system",
36942
+ addonId: null,
36943
+ access: "view"
36944
+ },
36715
36945
  "system.getLoggingSettings": {
36716
36946
  capName: "system",
36717
36947
  capScope: "system",
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  //#endregion
6
- const require_dist = require("../dist-D_G71rhM.js");
6
+ const require_dist = require("../dist-C0k9HqhA.js");
7
7
  let node_crypto = require("node:crypto");
8
8
  //#region src/ha-export/topics.ts
9
9
  /**
@@ -1,4 +1,4 @@
1
- import { At as EventCategory, C as buildAddonRouteProvider, Et as string, N as deviceExportCapability, X as oauthIntegrationCapability, a as COCO_TO_MACRO, c as FanDirectionSchema, i as CAMERA_SWITCH_ORDER, l as HvacModeSchema, o as CameraSwitchIdSchema, p as addonRoutesCapability, pt as BaseAddon, t as AlarmArmModeSchema, u as MediaPlayerRepeatSchema, vt as nodePin } from "../dist-DlrKePv3.mjs";
1
+ import { At as EventCategory, C as buildAddonRouteProvider, Et as string, N as deviceExportCapability, X as oauthIntegrationCapability, a as COCO_TO_MACRO, c as FanDirectionSchema, i as CAMERA_SWITCH_ORDER, l as HvacModeSchema, o as CameraSwitchIdSchema, p as addonRoutesCapability, pt as BaseAddon, t as AlarmArmModeSchema, u as MediaPlayerRepeatSchema, vt as nodePin } from "../dist-D-btrtuv.mjs";
2
2
  import { createHmac, timingSafeEqual } from "node:crypto";
3
3
  //#region src/ha-export/topics.ts
4
4
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-homeassistant",
3
- "version": "1.2.48",
3
+ "version": "1.2.50",
4
4
  "description": "Home Assistant device provider addon for CamStack",
5
5
  "keywords": [
6
6
  "camstack",