@camstack/addon-provider-petkit 0.2.35 → 0.2.36

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 +255 -25
  2. package/dist/addon.mjs +255 -25
  3. package/package.json +1 -1
package/dist/addon.js CHANGED
@@ -1101,7 +1101,7 @@ var Nodepetkit = class {
1101
1101
  }
1102
1102
  };
1103
1103
  //#endregion
1104
- //#region ../types/dist/event-category-CIa_iT6b.mjs
1104
+ //#region ../types/dist/event-category-BZL-fdNj.mjs
1105
1105
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
1106
1106
  EventCategory["SystemBoot"] = "system.boot";
1107
1107
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -1538,7 +1538,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
1538
1538
  EventCategory["MetricsNodeResourcesSnapshot"] = "metrics.node-resources-snapshot";
1539
1539
  /**
1540
1540
  * Periodic per-node process-tree snapshot (camstack-related pids
1541
- * with ghost / managed / root classification). Emitted ~0.2 Hz by
1541
+ * with root / managed / system classification). Emitted ~0.2 Hz by
1542
1542
  * the metrics-provider addon. Drives the Cluster → Processes tab
1543
1543
  * without polling `metricsProvider.listNodeProcesses`.
1544
1544
  */
@@ -12330,6 +12330,19 @@ var SettingsRecordSchema = object({
12330
12330
  data: record(string(), unknown())
12331
12331
  });
12332
12332
  /**
12333
+ * One record of a BULK insert — {@link SettingsRecordSchema} with the id made
12334
+ * optional.
12335
+ *
12336
+ * A separate schema rather than loosening the shared one: every other method
12337
+ * on this cap addresses a row BY its id, and making that field optional
12338
+ * everywhere would turn a forgotten key into a silently generated one on
12339
+ * `update` and `delete` as well.
12340
+ */
12341
+ var BulkRecordSchema = object({
12342
+ id: string().optional(),
12343
+ data: record(string(), unknown())
12344
+ });
12345
+ /**
12333
12346
  * Column declaration for a structured (SQL-backed) collection.
12334
12347
  *
12335
12348
  * Logical types — the backend translates each to the matching SQLite
@@ -12386,6 +12399,10 @@ method(object({
12386
12399
  collection: string(),
12387
12400
  record: SettingsRecordSchema
12388
12401
  }), _void(), { kind: "mutation" }), method(object({
12402
+ namespace: string().optional(),
12403
+ collection: string(),
12404
+ records: array(BulkRecordSchema).readonly()
12405
+ }), object({ inserted: number().int() }), { kind: "mutation" }), method(object({
12389
12406
  namespace: string().optional(),
12390
12407
  collection: string(),
12391
12408
  id: string(),
@@ -12494,6 +12511,13 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
12494
12511
  }), _void(), {
12495
12512
  kind: "mutation",
12496
12513
  auth: "admin"
12514
+ }), method(object({
12515
+ namespace: string().optional(),
12516
+ collection: string(),
12517
+ records: array(BulkRecordSchema).readonly()
12518
+ }), object({ inserted: number().int() }), {
12519
+ kind: "mutation",
12520
+ auth: "admin"
12497
12521
  }), method(object({
12498
12522
  namespace: string().optional(),
12499
12523
  collection: string(),
@@ -14441,6 +14465,68 @@ method(LogEntrySchema, _void(), { kind: "mutation" }), method(object({
14441
14465
  limit: number().optional(),
14442
14466
  tags: record(string(), string()).optional()
14443
14467
  }), array(LogEntrySchema).readonly());
14468
+ var LoadContributionSchema = object({
14469
+ role: _enum([
14470
+ "decode",
14471
+ "transcode",
14472
+ "recording",
14473
+ "streaming",
14474
+ "detection"
14475
+ ]),
14476
+ /**
14477
+ * The NUMERIC device id — the same value every log line carries as
14478
+ * `tags.deviceId`. `null` means this cost genuinely belongs to no single
14479
+ * camera (a shared pool), NOT that the contributor forgot to look it up: a
14480
+ * contributor that cannot name its camera must not emit the entry at all,
14481
+ * because an unnamed per-camera entry is indistinguishable from a shared one
14482
+ * and would quietly turn one camera's cost into everybody's.
14483
+ */
14484
+ deviceId: number().int().positive().nullable(),
14485
+ attribution: _enum([
14486
+ "measured",
14487
+ "accounted",
14488
+ "unattributable"
14489
+ ]),
14490
+ /**
14491
+ * What ONE entry is, in the contributor's own words — `615/high`,
14492
+ * `617/native`, `cuda:0 shared pool`. Free text because the unit differs per
14493
+ * family and inventing a common one would lose the only information that
14494
+ * makes two entries for the same camera distinguishable.
14495
+ */
14496
+ unit: string(),
14497
+ /**
14498
+ * The OS process this cost lives in, when there is one. Present so a
14499
+ * consumer can (a) tell two generations of the same unit apart across a
14500
+ * restart, and (b) subtract claimed processes from the node's process
14501
+ * snapshot to see what NOBODY claimed. Absent for an entry that owns no
14502
+ * process of its own.
14503
+ */
14504
+ pid: number().int().positive().optional(),
14505
+ /**
14506
+ * When this generation started. The pid's incarnation marker: a consumer
14507
+ * differencing {@link LoadContributionSchema.shape.cpuSeconds} must drop the
14508
+ * window when this changes, because the counter restarted from zero in a new
14509
+ * process.
14510
+ */
14511
+ startedAtMs: number().optional(),
14512
+ /**
14513
+ * CUMULATIVE CPU seconds this unit has consumed since it started — user +
14514
+ * system, read from the child's own `/proc/<pid>/stat` at the moment the
14515
+ * contribution is asked for.
14516
+ *
14517
+ * Cumulative and not a rate on purpose: a rate needs a window, a window
14518
+ * needs a sampler, and a new per-node sampler is the defect half of
14519
+ * `docs/architecture/load-ledger.md` documents. A counter can be differenced
14520
+ * by whoever already keeps a history; a rate cannot be un-averaged.
14521
+ *
14522
+ * Absent — never zero — on a node with no `/proc`, on a read failure, and on
14523
+ * an entry with no process.
14524
+ */
14525
+ cpuSeconds: number().optional(),
14526
+ /** Resident bytes of this unit's process, same source and same rules. */
14527
+ rssBytes: number().optional()
14528
+ });
14529
+ method(_void(), array(LoadContributionSchema).readonly());
14444
14530
  /**
14445
14531
  * `login-method` — collection cap through which auth addons contribute
14446
14532
  * their pre-auth login surfaces to the login page. This is the SINGLE,
@@ -14644,8 +14730,7 @@ var NodeProcessSchema = object({
14644
14730
  classification: _enum([
14645
14731
  "root",
14646
14732
  "managed",
14647
- "system",
14648
- "ghost"
14733
+ "system"
14649
14734
  ]),
14650
14735
  /** `$process` addon binding when `managed`, else null. */
14651
14736
  addonId: string().nullable(),
@@ -14653,22 +14738,39 @@ var NodeProcessSchema = object({
14653
14738
  nodeId: string().nullable(),
14654
14739
  /** Truncated command line. */
14655
14740
  command: string(),
14741
+ /**
14742
+ * `ps pcpu` — CPU averaged over the process's WHOLE LIFETIME, not a rate.
14743
+ * On a runner up for days it barely moves. Fine as a column, useless as a
14744
+ * series: use `cpuMainPercent + cpuGcPercent` for anything time-varying.
14745
+ */
14656
14746
  cpuPercent: number(),
14657
14747
  memoryRssBytes: number(),
14748
+ /**
14749
+ * Instantaneous CPU% of the process's own threads over the last
14750
+ * process-snapshot window, from a `/proc/<pid>/task/*` tick delta.
14751
+ *
14752
+ * `null` = UNKNOWN, never zero: no previous sample yet (first tick after
14753
+ * boot), the pid was recycled, or this node is not Linux.
14754
+ */
14755
+ cpuMainPercent: number().nullable(),
14756
+ /**
14757
+ * Instantaneous CPU% of V8's `V8Worker` platform pool over the same window.
14758
+ *
14759
+ * This is the number that rewrote the 2026-08-27 diagnosis — hub-main 73%,
14760
+ * `stream-broker` 61% (`docs/architecture/load-ledger.md`). A CPU chart that
14761
+ * does not separate it from `cpuMainPercent` shows "busy" where the truth is
14762
+ * "allocating too much".
14763
+ *
14764
+ * Concurrent GC is the dominant tenant of that pool but not the only one
14765
+ * (background compilation runs there too), so it is reported as
14766
+ * "GC / V8 helpers" rather than as pure collection time. `null` has the same
14767
+ * meaning as on `cpuMainPercent`.
14768
+ */
14769
+ cpuGcPercent: number().nullable(),
14770
+ /** Threads seen in the tick scan. `null` under the same conditions. */
14771
+ threadCount: number().nullable(),
14658
14772
  /** Wall-clock uptime (seconds). Parsed from `ps etime`. */
14659
- uptimeSec: number(),
14660
- /** True when ancestor walk reaches `ppid=1` (reparented to init/launchd). */
14661
- orphaned: boolean()
14662
- });
14663
- var KillProcessInputSchema = object({
14664
- pid: number(),
14665
- /** Force = SIGKILL. Default is SIGTERM. */
14666
- force: boolean().optional()
14667
- });
14668
- var KillProcessResultSchema = object({
14669
- success: boolean(),
14670
- reason: string().optional(),
14671
- signal: _enum(["SIGTERM", "SIGKILL"]).optional()
14773
+ uptimeSec: number()
14672
14774
  });
14673
14775
  var DumpHeapSnapshotInputSchema = object({
14674
14776
  /** The addon whose runner should dump a heap snapshot. */
@@ -14681,6 +14783,104 @@ var DumpHeapSnapshotResultSchema = object({
14681
14783
  pid: number().optional(),
14682
14784
  reason: string().optional()
14683
14785
  });
14786
+ /**
14787
+ * One point of one function's series.
14788
+ *
14789
+ * The unsuffixed fields are the bucket's **MAXIMUM**, and that choice is the
14790
+ * point of the whole surface. The two obvious reductions both lie: a mean per
14791
+ * bucket smears a spike away, and taking every Nth sample skips it outright.
14792
+ * Either would give us a tool built to find peaks that does not show peaks.
14793
+ * `...Min` carries the other end, `samples` says how many raw snapshots folded
14794
+ * into the bucket, and a mean stays derivable where it is wanted.
14795
+ *
14796
+ * An UNREDUCED point is a one-sample bucket: `samples === 1` and each `...Min`
14797
+ * equals its unsuffixed twin. Reduced and unreduced are the same shape, so a
14798
+ * caller cannot tell which it received — which is what "one reader" means.
14799
+ */
14800
+ var LoadPointSchema = object({
14801
+ /** Bucket START, or the snapshot's own timestamp when unreduced. */
14802
+ atMs: number(),
14803
+ /** Raw snapshots in this bucket. Never 0 — AN EMPTY BUCKET IS ABSENT. */
14804
+ samples: number().int(),
14805
+ /**
14806
+ * `null` = UNKNOWN and it PROPAGATES: a bucket is null unless every process
14807
+ * of every snapshot in it reported a thread split. A partial sum is a
14808
+ * smaller number that looks exactly as real as a complete one.
14809
+ */
14810
+ cpuMainPercent: number().nullable(),
14811
+ cpuMainPercentMin: number().nullable(),
14812
+ cpuGcPercent: number().nullable(),
14813
+ cpuGcPercentMin: number().nullable(),
14814
+ /** Lifetime-average CPU%, summed. Always known — and never a rate. */
14815
+ cpuLifetimePercent: number(),
14816
+ cpuLifetimePercentMin: number(),
14817
+ memoryRssBytes: number(),
14818
+ memoryRssBytesMin: number(),
14819
+ processCount: number().int(),
14820
+ processCountMin: number().int()
14821
+ });
14822
+ /** One function's series. `key` is an addonId, `__root__` or `__unattributed__`. */
14823
+ var LoadFunctionSeriesSchema = object({
14824
+ key: string(),
14825
+ kind: _enum([
14826
+ "addon",
14827
+ "root",
14828
+ "unattributed"
14829
+ ]),
14830
+ /** Oldest-first. A missing interval is MISSING — never zero-filled. */
14831
+ points: array(LoadPointSchema).readonly()
14832
+ });
14833
+ var NodeLoadSeriesSchema = object({
14834
+ nodeId: string(),
14835
+ /** One entry per function seen in the window, heaviest-first. */
14836
+ series: array(LoadFunctionSeriesSchema).readonly(),
14837
+ /**
14838
+ * Width of one returned bucket, in ms. Equals the sampling cadence when no
14839
+ * reduction was needed — so a caller can always say what one point covers
14840
+ * without having to know whether it was reduced.
14841
+ */
14842
+ bucketMs: number(),
14843
+ /** Raw snapshots that went into this answer, across both tiers. */
14844
+ retainedSamples: number(),
14845
+ /** Oldest snapshot represented, or `null` when nothing is retained. */
14846
+ oldestAtMs: number().nullable(),
14847
+ /** The fixed sampling cadence in force on the cluster, in ms. */
14848
+ cadenceMs: number(),
14849
+ /**
14850
+ * Did the DURABLE tier contribute? `false` means the answer is the hot ring
14851
+ * alone — an agent (which holds no table), or a store that refused.
14852
+ * Reported because "the last hour" and "the last six hours" are different
14853
+ * questions and an operator must not have to guess which was answered.
14854
+ */
14855
+ durable: boolean()
14856
+ });
14857
+ var GetLoadSeriesInputSchema = object({
14858
+ /**
14859
+ * The node whose series is wanted.
14860
+ *
14861
+ * NOT named `nodeId`: the generated cap router strips a top-level
14862
+ * `nodeId` from every method input and uses it to ROUTE the call to
14863
+ * that node's provider (`generated-cap-routers.ts`). A series target
14864
+ * called `nodeId` would silently become a routing pin and never reach
14865
+ * the provider. The hub holds every node it hears from, so the
14866
+ * ordinary call is unpinned — answered by the hub, for any node.
14867
+ */
14868
+ forNodeId: string(),
14869
+ /**
14870
+ * EXCLUSIVE lower bound. A caller passes the newest `atMs` it already
14871
+ * holds and receives only what it is missing, so seeding a live chart
14872
+ * from this method cannot double a point already drawn.
14873
+ */
14874
+ sinceMs: number().optional(),
14875
+ /**
14876
+ * Most points the caller wants PER FUNCTION. The window is reduced to fit,
14877
+ * preserving min and max per bucket.
14878
+ *
14879
+ * Absent means NO reduction — legitimate for a short window and a trap for a
14880
+ * long one, which is why a chart passes its own pixel width.
14881
+ */
14882
+ maxPoints: number().int().positive().optional()
14883
+ });
14684
14884
  var SystemMetricsSchema = object({
14685
14885
  cpuPercent: number(),
14686
14886
  memoryPercent: number(),
@@ -14691,10 +14891,7 @@ var SystemMetricsSchema = object({
14691
14891
  gpuPercent: number().optional(),
14692
14892
  gpuMemoryPercent: number().optional()
14693
14893
  });
14694
- 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, {
14695
- kind: "mutation",
14696
- auth: "admin"
14697
- }), method(DumpHeapSnapshotInputSchema, DumpHeapSnapshotResultSchema, {
14894
+ 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, {
14698
14895
  kind: "mutation",
14699
14896
  auth: "admin"
14700
14897
  });
@@ -30032,6 +30229,15 @@ var LoggingSettingsPatchSchema = object({
30032
30229
  * authority over the whole hierarchy and answers for every layer, so the
30033
30230
  * layer selector needs a name the transport does not already own.
30034
30231
  */
30232
+ /**
30233
+ * One contribution, plus WHO reported it.
30234
+ *
30235
+ * The addon and node are added by the hub as it enumerates providers, never by
30236
+ * the contributor: an addon reporting its own identity could report somebody
30237
+ * else's, and the whole point of this surface is that no claim is made by
30238
+ * anyone but its owner.
30239
+ */
30240
+ var ReportedLoadContributionSchema = LoadContributionSchema.extend({ addonId: string() });
30035
30241
  var GetLoggingSettingsInputSchema = object({
30036
30242
  scopeNodeId: string().optional(),
30037
30243
  /**
@@ -30090,7 +30296,7 @@ method(_void(), FeatureManifestSchema), method(_void(), HealthStatusSchema), met
30090
30296
  }), method(_void(), SiteLocationStatusSchema, {
30091
30297
  kind: "mutation",
30092
30298
  auth: "admin"
30093
- }), method(_void(), RequestCensusStatusSchema, { auth: "admin" }), method(GetLoggingSettingsInputSchema, LoggingSettingsStateSchema, { auth: "admin" }), method(SetLoggingSettingsInputSchema, LoggingSettingsStateSchema, {
30299
+ }), method(_void(), RequestCensusStatusSchema, { auth: "admin" }), method(_void(), array(ReportedLoadContributionSchema).readonly(), { auth: "admin" }), method(GetLoggingSettingsInputSchema, LoggingSettingsStateSchema, { auth: "admin" }), method(SetLoggingSettingsInputSchema, LoggingSettingsStateSchema, {
30094
30300
  kind: "mutation",
30095
30301
  auth: "admin"
30096
30302
  });
@@ -33114,6 +33320,12 @@ Object.freeze({
33114
33320
  addonId: null,
33115
33321
  access: "create"
33116
33322
  },
33323
+ "dataStoreProvider.insertMany": {
33324
+ capName: "data-store-provider",
33325
+ capScope: "system",
33326
+ addonId: null,
33327
+ access: "create"
33328
+ },
33117
33329
  "dataStoreProvider.isEmpty": {
33118
33330
  capName: "data-store-provider",
33119
33331
  capScope: "system",
@@ -34428,6 +34640,12 @@ Object.freeze({
34428
34640
  addonId: null,
34429
34641
  access: "create"
34430
34642
  },
34643
+ "loadContribution.list": {
34644
+ capName: "load-contribution",
34645
+ capScope: "system",
34646
+ addonId: null,
34647
+ access: "view"
34648
+ },
34431
34649
  "localNetwork.downloadCa": {
34432
34650
  capName: "local-network",
34433
34651
  capScope: "system",
@@ -34728,17 +34946,17 @@ Object.freeze({
34728
34946
  addonId: null,
34729
34947
  access: "view"
34730
34948
  },
34731
- "metricsProvider.getProcessStats": {
34949
+ "metricsProvider.getLoadSeries": {
34732
34950
  capName: "metrics-provider",
34733
34951
  capScope: "system",
34734
34952
  addonId: null,
34735
34953
  access: "view"
34736
34954
  },
34737
- "metricsProvider.killProcess": {
34955
+ "metricsProvider.getProcessStats": {
34738
34956
  capName: "metrics-provider",
34739
34957
  capScope: "system",
34740
34958
  addonId: null,
34741
- access: "create"
34959
+ access: "view"
34742
34960
  },
34743
34961
  "metricsProvider.listAddonInstances": {
34744
34962
  capName: "metrics-provider",
@@ -36750,6 +36968,12 @@ Object.freeze({
36750
36968
  addonId: null,
36751
36969
  access: "create"
36752
36970
  },
36971
+ "settingsStore.insertMany": {
36972
+ capName: "settings-store",
36973
+ capScope: "system",
36974
+ addonId: null,
36975
+ access: "create"
36976
+ },
36753
36977
  "settingsStore.isEmpty": {
36754
36978
  capName: "settings-store",
36755
36979
  capScope: "system",
@@ -37362,6 +37586,12 @@ Object.freeze({
37362
37586
  addonId: null,
37363
37587
  access: "create"
37364
37588
  },
37589
+ "system.getLoadContributions": {
37590
+ capName: "system",
37591
+ capScope: "system",
37592
+ addonId: null,
37593
+ access: "view"
37594
+ },
37365
37595
  "system.getLoggingSettings": {
37366
37596
  capName: "system",
37367
37597
  capScope: "system",
package/dist/addon.mjs CHANGED
@@ -1100,7 +1100,7 @@ var Nodepetkit = class {
1100
1100
  }
1101
1101
  };
1102
1102
  //#endregion
1103
- //#region ../types/dist/event-category-CIa_iT6b.mjs
1103
+ //#region ../types/dist/event-category-BZL-fdNj.mjs
1104
1104
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
1105
1105
  EventCategory["SystemBoot"] = "system.boot";
1106
1106
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -1537,7 +1537,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
1537
1537
  EventCategory["MetricsNodeResourcesSnapshot"] = "metrics.node-resources-snapshot";
1538
1538
  /**
1539
1539
  * Periodic per-node process-tree snapshot (camstack-related pids
1540
- * with ghost / managed / root classification). Emitted ~0.2 Hz by
1540
+ * with root / managed / system classification). Emitted ~0.2 Hz by
1541
1541
  * the metrics-provider addon. Drives the Cluster → Processes tab
1542
1542
  * without polling `metricsProvider.listNodeProcesses`.
1543
1543
  */
@@ -12329,6 +12329,19 @@ var SettingsRecordSchema = object({
12329
12329
  data: record(string(), unknown())
12330
12330
  });
12331
12331
  /**
12332
+ * One record of a BULK insert — {@link SettingsRecordSchema} with the id made
12333
+ * optional.
12334
+ *
12335
+ * A separate schema rather than loosening the shared one: every other method
12336
+ * on this cap addresses a row BY its id, and making that field optional
12337
+ * everywhere would turn a forgotten key into a silently generated one on
12338
+ * `update` and `delete` as well.
12339
+ */
12340
+ var BulkRecordSchema = object({
12341
+ id: string().optional(),
12342
+ data: record(string(), unknown())
12343
+ });
12344
+ /**
12332
12345
  * Column declaration for a structured (SQL-backed) collection.
12333
12346
  *
12334
12347
  * Logical types — the backend translates each to the matching SQLite
@@ -12385,6 +12398,10 @@ method(object({
12385
12398
  collection: string(),
12386
12399
  record: SettingsRecordSchema
12387
12400
  }), _void(), { kind: "mutation" }), method(object({
12401
+ namespace: string().optional(),
12402
+ collection: string(),
12403
+ records: array(BulkRecordSchema).readonly()
12404
+ }), object({ inserted: number().int() }), { kind: "mutation" }), method(object({
12388
12405
  namespace: string().optional(),
12389
12406
  collection: string(),
12390
12407
  id: string(),
@@ -12493,6 +12510,13 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
12493
12510
  }), _void(), {
12494
12511
  kind: "mutation",
12495
12512
  auth: "admin"
12513
+ }), method(object({
12514
+ namespace: string().optional(),
12515
+ collection: string(),
12516
+ records: array(BulkRecordSchema).readonly()
12517
+ }), object({ inserted: number().int() }), {
12518
+ kind: "mutation",
12519
+ auth: "admin"
12496
12520
  }), method(object({
12497
12521
  namespace: string().optional(),
12498
12522
  collection: string(),
@@ -14440,6 +14464,68 @@ method(LogEntrySchema, _void(), { kind: "mutation" }), method(object({
14440
14464
  limit: number().optional(),
14441
14465
  tags: record(string(), string()).optional()
14442
14466
  }), array(LogEntrySchema).readonly());
14467
+ var LoadContributionSchema = object({
14468
+ role: _enum([
14469
+ "decode",
14470
+ "transcode",
14471
+ "recording",
14472
+ "streaming",
14473
+ "detection"
14474
+ ]),
14475
+ /**
14476
+ * The NUMERIC device id — the same value every log line carries as
14477
+ * `tags.deviceId`. `null` means this cost genuinely belongs to no single
14478
+ * camera (a shared pool), NOT that the contributor forgot to look it up: a
14479
+ * contributor that cannot name its camera must not emit the entry at all,
14480
+ * because an unnamed per-camera entry is indistinguishable from a shared one
14481
+ * and would quietly turn one camera's cost into everybody's.
14482
+ */
14483
+ deviceId: number().int().positive().nullable(),
14484
+ attribution: _enum([
14485
+ "measured",
14486
+ "accounted",
14487
+ "unattributable"
14488
+ ]),
14489
+ /**
14490
+ * What ONE entry is, in the contributor's own words — `615/high`,
14491
+ * `617/native`, `cuda:0 shared pool`. Free text because the unit differs per
14492
+ * family and inventing a common one would lose the only information that
14493
+ * makes two entries for the same camera distinguishable.
14494
+ */
14495
+ unit: string(),
14496
+ /**
14497
+ * The OS process this cost lives in, when there is one. Present so a
14498
+ * consumer can (a) tell two generations of the same unit apart across a
14499
+ * restart, and (b) subtract claimed processes from the node's process
14500
+ * snapshot to see what NOBODY claimed. Absent for an entry that owns no
14501
+ * process of its own.
14502
+ */
14503
+ pid: number().int().positive().optional(),
14504
+ /**
14505
+ * When this generation started. The pid's incarnation marker: a consumer
14506
+ * differencing {@link LoadContributionSchema.shape.cpuSeconds} must drop the
14507
+ * window when this changes, because the counter restarted from zero in a new
14508
+ * process.
14509
+ */
14510
+ startedAtMs: number().optional(),
14511
+ /**
14512
+ * CUMULATIVE CPU seconds this unit has consumed since it started — user +
14513
+ * system, read from the child's own `/proc/<pid>/stat` at the moment the
14514
+ * contribution is asked for.
14515
+ *
14516
+ * Cumulative and not a rate on purpose: a rate needs a window, a window
14517
+ * needs a sampler, and a new per-node sampler is the defect half of
14518
+ * `docs/architecture/load-ledger.md` documents. A counter can be differenced
14519
+ * by whoever already keeps a history; a rate cannot be un-averaged.
14520
+ *
14521
+ * Absent — never zero — on a node with no `/proc`, on a read failure, and on
14522
+ * an entry with no process.
14523
+ */
14524
+ cpuSeconds: number().optional(),
14525
+ /** Resident bytes of this unit's process, same source and same rules. */
14526
+ rssBytes: number().optional()
14527
+ });
14528
+ method(_void(), array(LoadContributionSchema).readonly());
14443
14529
  /**
14444
14530
  * `login-method` — collection cap through which auth addons contribute
14445
14531
  * their pre-auth login surfaces to the login page. This is the SINGLE,
@@ -14643,8 +14729,7 @@ var NodeProcessSchema = object({
14643
14729
  classification: _enum([
14644
14730
  "root",
14645
14731
  "managed",
14646
- "system",
14647
- "ghost"
14732
+ "system"
14648
14733
  ]),
14649
14734
  /** `$process` addon binding when `managed`, else null. */
14650
14735
  addonId: string().nullable(),
@@ -14652,22 +14737,39 @@ var NodeProcessSchema = object({
14652
14737
  nodeId: string().nullable(),
14653
14738
  /** Truncated command line. */
14654
14739
  command: string(),
14740
+ /**
14741
+ * `ps pcpu` — CPU averaged over the process's WHOLE LIFETIME, not a rate.
14742
+ * On a runner up for days it barely moves. Fine as a column, useless as a
14743
+ * series: use `cpuMainPercent + cpuGcPercent` for anything time-varying.
14744
+ */
14655
14745
  cpuPercent: number(),
14656
14746
  memoryRssBytes: number(),
14747
+ /**
14748
+ * Instantaneous CPU% of the process's own threads over the last
14749
+ * process-snapshot window, from a `/proc/<pid>/task/*` tick delta.
14750
+ *
14751
+ * `null` = UNKNOWN, never zero: no previous sample yet (first tick after
14752
+ * boot), the pid was recycled, or this node is not Linux.
14753
+ */
14754
+ cpuMainPercent: number().nullable(),
14755
+ /**
14756
+ * Instantaneous CPU% of V8's `V8Worker` platform pool over the same window.
14757
+ *
14758
+ * This is the number that rewrote the 2026-08-27 diagnosis — hub-main 73%,
14759
+ * `stream-broker` 61% (`docs/architecture/load-ledger.md`). A CPU chart that
14760
+ * does not separate it from `cpuMainPercent` shows "busy" where the truth is
14761
+ * "allocating too much".
14762
+ *
14763
+ * Concurrent GC is the dominant tenant of that pool but not the only one
14764
+ * (background compilation runs there too), so it is reported as
14765
+ * "GC / V8 helpers" rather than as pure collection time. `null` has the same
14766
+ * meaning as on `cpuMainPercent`.
14767
+ */
14768
+ cpuGcPercent: number().nullable(),
14769
+ /** Threads seen in the tick scan. `null` under the same conditions. */
14770
+ threadCount: number().nullable(),
14657
14771
  /** Wall-clock uptime (seconds). Parsed from `ps etime`. */
14658
- uptimeSec: number(),
14659
- /** True when ancestor walk reaches `ppid=1` (reparented to init/launchd). */
14660
- orphaned: boolean()
14661
- });
14662
- var KillProcessInputSchema = object({
14663
- pid: number(),
14664
- /** Force = SIGKILL. Default is SIGTERM. */
14665
- force: boolean().optional()
14666
- });
14667
- var KillProcessResultSchema = object({
14668
- success: boolean(),
14669
- reason: string().optional(),
14670
- signal: _enum(["SIGTERM", "SIGKILL"]).optional()
14772
+ uptimeSec: number()
14671
14773
  });
14672
14774
  var DumpHeapSnapshotInputSchema = object({
14673
14775
  /** The addon whose runner should dump a heap snapshot. */
@@ -14680,6 +14782,104 @@ var DumpHeapSnapshotResultSchema = object({
14680
14782
  pid: number().optional(),
14681
14783
  reason: string().optional()
14682
14784
  });
14785
+ /**
14786
+ * One point of one function's series.
14787
+ *
14788
+ * The unsuffixed fields are the bucket's **MAXIMUM**, and that choice is the
14789
+ * point of the whole surface. The two obvious reductions both lie: a mean per
14790
+ * bucket smears a spike away, and taking every Nth sample skips it outright.
14791
+ * Either would give us a tool built to find peaks that does not show peaks.
14792
+ * `...Min` carries the other end, `samples` says how many raw snapshots folded
14793
+ * into the bucket, and a mean stays derivable where it is wanted.
14794
+ *
14795
+ * An UNREDUCED point is a one-sample bucket: `samples === 1` and each `...Min`
14796
+ * equals its unsuffixed twin. Reduced and unreduced are the same shape, so a
14797
+ * caller cannot tell which it received — which is what "one reader" means.
14798
+ */
14799
+ var LoadPointSchema = object({
14800
+ /** Bucket START, or the snapshot's own timestamp when unreduced. */
14801
+ atMs: number(),
14802
+ /** Raw snapshots in this bucket. Never 0 — AN EMPTY BUCKET IS ABSENT. */
14803
+ samples: number().int(),
14804
+ /**
14805
+ * `null` = UNKNOWN and it PROPAGATES: a bucket is null unless every process
14806
+ * of every snapshot in it reported a thread split. A partial sum is a
14807
+ * smaller number that looks exactly as real as a complete one.
14808
+ */
14809
+ cpuMainPercent: number().nullable(),
14810
+ cpuMainPercentMin: number().nullable(),
14811
+ cpuGcPercent: number().nullable(),
14812
+ cpuGcPercentMin: number().nullable(),
14813
+ /** Lifetime-average CPU%, summed. Always known — and never a rate. */
14814
+ cpuLifetimePercent: number(),
14815
+ cpuLifetimePercentMin: number(),
14816
+ memoryRssBytes: number(),
14817
+ memoryRssBytesMin: number(),
14818
+ processCount: number().int(),
14819
+ processCountMin: number().int()
14820
+ });
14821
+ /** One function's series. `key` is an addonId, `__root__` or `__unattributed__`. */
14822
+ var LoadFunctionSeriesSchema = object({
14823
+ key: string(),
14824
+ kind: _enum([
14825
+ "addon",
14826
+ "root",
14827
+ "unattributed"
14828
+ ]),
14829
+ /** Oldest-first. A missing interval is MISSING — never zero-filled. */
14830
+ points: array(LoadPointSchema).readonly()
14831
+ });
14832
+ var NodeLoadSeriesSchema = object({
14833
+ nodeId: string(),
14834
+ /** One entry per function seen in the window, heaviest-first. */
14835
+ series: array(LoadFunctionSeriesSchema).readonly(),
14836
+ /**
14837
+ * Width of one returned bucket, in ms. Equals the sampling cadence when no
14838
+ * reduction was needed — so a caller can always say what one point covers
14839
+ * without having to know whether it was reduced.
14840
+ */
14841
+ bucketMs: number(),
14842
+ /** Raw snapshots that went into this answer, across both tiers. */
14843
+ retainedSamples: number(),
14844
+ /** Oldest snapshot represented, or `null` when nothing is retained. */
14845
+ oldestAtMs: number().nullable(),
14846
+ /** The fixed sampling cadence in force on the cluster, in ms. */
14847
+ cadenceMs: number(),
14848
+ /**
14849
+ * Did the DURABLE tier contribute? `false` means the answer is the hot ring
14850
+ * alone — an agent (which holds no table), or a store that refused.
14851
+ * Reported because "the last hour" and "the last six hours" are different
14852
+ * questions and an operator must not have to guess which was answered.
14853
+ */
14854
+ durable: boolean()
14855
+ });
14856
+ var GetLoadSeriesInputSchema = object({
14857
+ /**
14858
+ * The node whose series is wanted.
14859
+ *
14860
+ * NOT named `nodeId`: the generated cap router strips a top-level
14861
+ * `nodeId` from every method input and uses it to ROUTE the call to
14862
+ * that node's provider (`generated-cap-routers.ts`). A series target
14863
+ * called `nodeId` would silently become a routing pin and never reach
14864
+ * the provider. The hub holds every node it hears from, so the
14865
+ * ordinary call is unpinned — answered by the hub, for any node.
14866
+ */
14867
+ forNodeId: string(),
14868
+ /**
14869
+ * EXCLUSIVE lower bound. A caller passes the newest `atMs` it already
14870
+ * holds and receives only what it is missing, so seeding a live chart
14871
+ * from this method cannot double a point already drawn.
14872
+ */
14873
+ sinceMs: number().optional(),
14874
+ /**
14875
+ * Most points the caller wants PER FUNCTION. The window is reduced to fit,
14876
+ * preserving min and max per bucket.
14877
+ *
14878
+ * Absent means NO reduction — legitimate for a short window and a trap for a
14879
+ * long one, which is why a chart passes its own pixel width.
14880
+ */
14881
+ maxPoints: number().int().positive().optional()
14882
+ });
14683
14883
  var SystemMetricsSchema = object({
14684
14884
  cpuPercent: number(),
14685
14885
  memoryPercent: number(),
@@ -14690,10 +14890,7 @@ var SystemMetricsSchema = object({
14690
14890
  gpuPercent: number().optional(),
14691
14891
  gpuMemoryPercent: number().optional()
14692
14892
  });
14693
- 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, {
14694
- kind: "mutation",
14695
- auth: "admin"
14696
- }), method(DumpHeapSnapshotInputSchema, DumpHeapSnapshotResultSchema, {
14893
+ 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, {
14697
14894
  kind: "mutation",
14698
14895
  auth: "admin"
14699
14896
  });
@@ -30031,6 +30228,15 @@ var LoggingSettingsPatchSchema = object({
30031
30228
  * authority over the whole hierarchy and answers for every layer, so the
30032
30229
  * layer selector needs a name the transport does not already own.
30033
30230
  */
30231
+ /**
30232
+ * One contribution, plus WHO reported it.
30233
+ *
30234
+ * The addon and node are added by the hub as it enumerates providers, never by
30235
+ * the contributor: an addon reporting its own identity could report somebody
30236
+ * else's, and the whole point of this surface is that no claim is made by
30237
+ * anyone but its owner.
30238
+ */
30239
+ var ReportedLoadContributionSchema = LoadContributionSchema.extend({ addonId: string() });
30034
30240
  var GetLoggingSettingsInputSchema = object({
30035
30241
  scopeNodeId: string().optional(),
30036
30242
  /**
@@ -30089,7 +30295,7 @@ method(_void(), FeatureManifestSchema), method(_void(), HealthStatusSchema), met
30089
30295
  }), method(_void(), SiteLocationStatusSchema, {
30090
30296
  kind: "mutation",
30091
30297
  auth: "admin"
30092
- }), method(_void(), RequestCensusStatusSchema, { auth: "admin" }), method(GetLoggingSettingsInputSchema, LoggingSettingsStateSchema, { auth: "admin" }), method(SetLoggingSettingsInputSchema, LoggingSettingsStateSchema, {
30298
+ }), method(_void(), RequestCensusStatusSchema, { auth: "admin" }), method(_void(), array(ReportedLoadContributionSchema).readonly(), { auth: "admin" }), method(GetLoggingSettingsInputSchema, LoggingSettingsStateSchema, { auth: "admin" }), method(SetLoggingSettingsInputSchema, LoggingSettingsStateSchema, {
30093
30299
  kind: "mutation",
30094
30300
  auth: "admin"
30095
30301
  });
@@ -33113,6 +33319,12 @@ Object.freeze({
33113
33319
  addonId: null,
33114
33320
  access: "create"
33115
33321
  },
33322
+ "dataStoreProvider.insertMany": {
33323
+ capName: "data-store-provider",
33324
+ capScope: "system",
33325
+ addonId: null,
33326
+ access: "create"
33327
+ },
33116
33328
  "dataStoreProvider.isEmpty": {
33117
33329
  capName: "data-store-provider",
33118
33330
  capScope: "system",
@@ -34427,6 +34639,12 @@ Object.freeze({
34427
34639
  addonId: null,
34428
34640
  access: "create"
34429
34641
  },
34642
+ "loadContribution.list": {
34643
+ capName: "load-contribution",
34644
+ capScope: "system",
34645
+ addonId: null,
34646
+ access: "view"
34647
+ },
34430
34648
  "localNetwork.downloadCa": {
34431
34649
  capName: "local-network",
34432
34650
  capScope: "system",
@@ -34727,17 +34945,17 @@ Object.freeze({
34727
34945
  addonId: null,
34728
34946
  access: "view"
34729
34947
  },
34730
- "metricsProvider.getProcessStats": {
34948
+ "metricsProvider.getLoadSeries": {
34731
34949
  capName: "metrics-provider",
34732
34950
  capScope: "system",
34733
34951
  addonId: null,
34734
34952
  access: "view"
34735
34953
  },
34736
- "metricsProvider.killProcess": {
34954
+ "metricsProvider.getProcessStats": {
34737
34955
  capName: "metrics-provider",
34738
34956
  capScope: "system",
34739
34957
  addonId: null,
34740
- access: "create"
34958
+ access: "view"
34741
34959
  },
34742
34960
  "metricsProvider.listAddonInstances": {
34743
34961
  capName: "metrics-provider",
@@ -36749,6 +36967,12 @@ Object.freeze({
36749
36967
  addonId: null,
36750
36968
  access: "create"
36751
36969
  },
36970
+ "settingsStore.insertMany": {
36971
+ capName: "settings-store",
36972
+ capScope: "system",
36973
+ addonId: null,
36974
+ access: "create"
36975
+ },
36752
36976
  "settingsStore.isEmpty": {
36753
36977
  capName: "settings-store",
36754
36978
  capScope: "system",
@@ -37361,6 +37585,12 @@ Object.freeze({
37361
37585
  addonId: null,
37362
37586
  access: "create"
37363
37587
  },
37588
+ "system.getLoadContributions": {
37589
+ capName: "system",
37590
+ capScope: "system",
37591
+ addonId: null,
37592
+ access: "view"
37593
+ },
37364
37594
  "system.getLoggingSettings": {
37365
37595
  capName: "system",
37366
37596
  capScope: "system",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-provider-petkit",
3
- "version": "0.2.35",
3
+ "version": "0.2.36",
4
4
  "description": "PetKit smart-feeder device-provider addon for CamStack — wraps the @apocaliss92/nodepetkit PetKit cloud client",
5
5
  "keywords": [
6
6
  "camstack",