@camstack/addon-terminal 0.1.40 → 0.1.42

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
@@ -31,7 +31,7 @@ let node_module = require("node:module");
31
31
  let sharp = require("sharp");
32
32
  sharp = __toESM(sharp);
33
33
  let node_http = require("node:http");
34
- //#region ../types/dist/event-category-CIa_iT6b.mjs
34
+ //#region ../types/dist/event-category-BZL-fdNj.mjs
35
35
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
36
36
  EventCategory["SystemBoot"] = "system.boot";
37
37
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -468,7 +468,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
468
468
  EventCategory["MetricsNodeResourcesSnapshot"] = "metrics.node-resources-snapshot";
469
469
  /**
470
470
  * Periodic per-node process-tree snapshot (camstack-related pids
471
- * with ghost / managed / root classification). Emitted ~0.2 Hz by
471
+ * with root / managed / system classification). Emitted ~0.2 Hz by
472
472
  * the metrics-provider addon. Drives the Cluster → Processes tab
473
473
  * without polling `metricsProvider.listNodeProcesses`.
474
474
  */
@@ -11327,6 +11327,19 @@ var SettingsRecordSchema = object({
11327
11327
  data: record(string(), unknown())
11328
11328
  });
11329
11329
  /**
11330
+ * One record of a BULK insert — {@link SettingsRecordSchema} with the id made
11331
+ * optional.
11332
+ *
11333
+ * A separate schema rather than loosening the shared one: every other method
11334
+ * on this cap addresses a row BY its id, and making that field optional
11335
+ * everywhere would turn a forgotten key into a silently generated one on
11336
+ * `update` and `delete` as well.
11337
+ */
11338
+ var BulkRecordSchema = object({
11339
+ id: string().optional(),
11340
+ data: record(string(), unknown())
11341
+ });
11342
+ /**
11330
11343
  * Column declaration for a structured (SQL-backed) collection.
11331
11344
  *
11332
11345
  * Logical types — the backend translates each to the matching SQLite
@@ -11383,6 +11396,10 @@ method(object({
11383
11396
  collection: string(),
11384
11397
  record: SettingsRecordSchema
11385
11398
  }), _void(), { kind: "mutation" }), method(object({
11399
+ namespace: string().optional(),
11400
+ collection: string(),
11401
+ records: array(BulkRecordSchema).readonly()
11402
+ }), object({ inserted: number().int() }), { kind: "mutation" }), method(object({
11386
11403
  namespace: string().optional(),
11387
11404
  collection: string(),
11388
11405
  id: string(),
@@ -11491,6 +11508,13 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
11491
11508
  }), _void(), {
11492
11509
  kind: "mutation",
11493
11510
  auth: "admin"
11511
+ }), method(object({
11512
+ namespace: string().optional(),
11513
+ collection: string(),
11514
+ records: array(BulkRecordSchema).readonly()
11515
+ }), object({ inserted: number().int() }), {
11516
+ kind: "mutation",
11517
+ auth: "admin"
11494
11518
  }), method(object({
11495
11519
  namespace: string().optional(),
11496
11520
  collection: string(),
@@ -13366,6 +13390,68 @@ method(LogEntrySchema, _void(), { kind: "mutation" }), method(object({
13366
13390
  limit: number().optional(),
13367
13391
  tags: record(string(), string()).optional()
13368
13392
  }), array(LogEntrySchema).readonly());
13393
+ var LoadContributionSchema = object({
13394
+ role: _enum([
13395
+ "decode",
13396
+ "transcode",
13397
+ "recording",
13398
+ "streaming",
13399
+ "detection"
13400
+ ]),
13401
+ /**
13402
+ * The NUMERIC device id — the same value every log line carries as
13403
+ * `tags.deviceId`. `null` means this cost genuinely belongs to no single
13404
+ * camera (a shared pool), NOT that the contributor forgot to look it up: a
13405
+ * contributor that cannot name its camera must not emit the entry at all,
13406
+ * because an unnamed per-camera entry is indistinguishable from a shared one
13407
+ * and would quietly turn one camera's cost into everybody's.
13408
+ */
13409
+ deviceId: number().int().positive().nullable(),
13410
+ attribution: _enum([
13411
+ "measured",
13412
+ "accounted",
13413
+ "unattributable"
13414
+ ]),
13415
+ /**
13416
+ * What ONE entry is, in the contributor's own words — `615/high`,
13417
+ * `617/native`, `cuda:0 shared pool`. Free text because the unit differs per
13418
+ * family and inventing a common one would lose the only information that
13419
+ * makes two entries for the same camera distinguishable.
13420
+ */
13421
+ unit: string(),
13422
+ /**
13423
+ * The OS process this cost lives in, when there is one. Present so a
13424
+ * consumer can (a) tell two generations of the same unit apart across a
13425
+ * restart, and (b) subtract claimed processes from the node's process
13426
+ * snapshot to see what NOBODY claimed. Absent for an entry that owns no
13427
+ * process of its own.
13428
+ */
13429
+ pid: number().int().positive().optional(),
13430
+ /**
13431
+ * When this generation started. The pid's incarnation marker: a consumer
13432
+ * differencing {@link LoadContributionSchema.shape.cpuSeconds} must drop the
13433
+ * window when this changes, because the counter restarted from zero in a new
13434
+ * process.
13435
+ */
13436
+ startedAtMs: number().optional(),
13437
+ /**
13438
+ * CUMULATIVE CPU seconds this unit has consumed since it started — user +
13439
+ * system, read from the child's own `/proc/<pid>/stat` at the moment the
13440
+ * contribution is asked for.
13441
+ *
13442
+ * Cumulative and not a rate on purpose: a rate needs a window, a window
13443
+ * needs a sampler, and a new per-node sampler is the defect half of
13444
+ * `docs/architecture/load-ledger.md` documents. A counter can be differenced
13445
+ * by whoever already keeps a history; a rate cannot be un-averaged.
13446
+ *
13447
+ * Absent — never zero — on a node with no `/proc`, on a read failure, and on
13448
+ * an entry with no process.
13449
+ */
13450
+ cpuSeconds: number().optional(),
13451
+ /** Resident bytes of this unit's process, same source and same rules. */
13452
+ rssBytes: number().optional()
13453
+ });
13454
+ method(_void(), array(LoadContributionSchema).readonly());
13369
13455
  /**
13370
13456
  * `login-method` — collection cap through which auth addons contribute
13371
13457
  * their pre-auth login surfaces to the login page. This is the SINGLE,
@@ -13569,8 +13655,7 @@ var NodeProcessSchema = object({
13569
13655
  classification: _enum([
13570
13656
  "root",
13571
13657
  "managed",
13572
- "system",
13573
- "ghost"
13658
+ "system"
13574
13659
  ]),
13575
13660
  /** `$process` addon binding when `managed`, else null. */
13576
13661
  addonId: string().nullable(),
@@ -13578,22 +13663,39 @@ var NodeProcessSchema = object({
13578
13663
  nodeId: string().nullable(),
13579
13664
  /** Truncated command line. */
13580
13665
  command: string(),
13666
+ /**
13667
+ * `ps pcpu` — CPU averaged over the process's WHOLE LIFETIME, not a rate.
13668
+ * On a runner up for days it barely moves. Fine as a column, useless as a
13669
+ * series: use `cpuMainPercent + cpuGcPercent` for anything time-varying.
13670
+ */
13581
13671
  cpuPercent: number(),
13582
13672
  memoryRssBytes: number(),
13673
+ /**
13674
+ * Instantaneous CPU% of the process's own threads over the last
13675
+ * process-snapshot window, from a `/proc/<pid>/task/*` tick delta.
13676
+ *
13677
+ * `null` = UNKNOWN, never zero: no previous sample yet (first tick after
13678
+ * boot), the pid was recycled, or this node is not Linux.
13679
+ */
13680
+ cpuMainPercent: number().nullable(),
13681
+ /**
13682
+ * Instantaneous CPU% of V8's `V8Worker` platform pool over the same window.
13683
+ *
13684
+ * This is the number that rewrote the 2026-08-27 diagnosis — hub-main 73%,
13685
+ * `stream-broker` 61% (`docs/architecture/load-ledger.md`). A CPU chart that
13686
+ * does not separate it from `cpuMainPercent` shows "busy" where the truth is
13687
+ * "allocating too much".
13688
+ *
13689
+ * Concurrent GC is the dominant tenant of that pool but not the only one
13690
+ * (background compilation runs there too), so it is reported as
13691
+ * "GC / V8 helpers" rather than as pure collection time. `null` has the same
13692
+ * meaning as on `cpuMainPercent`.
13693
+ */
13694
+ cpuGcPercent: number().nullable(),
13695
+ /** Threads seen in the tick scan. `null` under the same conditions. */
13696
+ threadCount: number().nullable(),
13583
13697
  /** Wall-clock uptime (seconds). Parsed from `ps etime`. */
13584
- uptimeSec: number(),
13585
- /** True when ancestor walk reaches `ppid=1` (reparented to init/launchd). */
13586
- orphaned: boolean()
13587
- });
13588
- var KillProcessInputSchema = object({
13589
- pid: number(),
13590
- /** Force = SIGKILL. Default is SIGTERM. */
13591
- force: boolean().optional()
13592
- });
13593
- var KillProcessResultSchema = object({
13594
- success: boolean(),
13595
- reason: string().optional(),
13596
- signal: _enum(["SIGTERM", "SIGKILL"]).optional()
13698
+ uptimeSec: number()
13597
13699
  });
13598
13700
  var DumpHeapSnapshotInputSchema = object({
13599
13701
  /** The addon whose runner should dump a heap snapshot. */
@@ -13606,6 +13708,104 @@ var DumpHeapSnapshotResultSchema = object({
13606
13708
  pid: number().optional(),
13607
13709
  reason: string().optional()
13608
13710
  });
13711
+ /**
13712
+ * One point of one function's series.
13713
+ *
13714
+ * The unsuffixed fields are the bucket's **MAXIMUM**, and that choice is the
13715
+ * point of the whole surface. The two obvious reductions both lie: a mean per
13716
+ * bucket smears a spike away, and taking every Nth sample skips it outright.
13717
+ * Either would give us a tool built to find peaks that does not show peaks.
13718
+ * `...Min` carries the other end, `samples` says how many raw snapshots folded
13719
+ * into the bucket, and a mean stays derivable where it is wanted.
13720
+ *
13721
+ * An UNREDUCED point is a one-sample bucket: `samples === 1` and each `...Min`
13722
+ * equals its unsuffixed twin. Reduced and unreduced are the same shape, so a
13723
+ * caller cannot tell which it received — which is what "one reader" means.
13724
+ */
13725
+ var LoadPointSchema = object({
13726
+ /** Bucket START, or the snapshot's own timestamp when unreduced. */
13727
+ atMs: number(),
13728
+ /** Raw snapshots in this bucket. Never 0 — AN EMPTY BUCKET IS ABSENT. */
13729
+ samples: number().int(),
13730
+ /**
13731
+ * `null` = UNKNOWN and it PROPAGATES: a bucket is null unless every process
13732
+ * of every snapshot in it reported a thread split. A partial sum is a
13733
+ * smaller number that looks exactly as real as a complete one.
13734
+ */
13735
+ cpuMainPercent: number().nullable(),
13736
+ cpuMainPercentMin: number().nullable(),
13737
+ cpuGcPercent: number().nullable(),
13738
+ cpuGcPercentMin: number().nullable(),
13739
+ /** Lifetime-average CPU%, summed. Always known — and never a rate. */
13740
+ cpuLifetimePercent: number(),
13741
+ cpuLifetimePercentMin: number(),
13742
+ memoryRssBytes: number(),
13743
+ memoryRssBytesMin: number(),
13744
+ processCount: number().int(),
13745
+ processCountMin: number().int()
13746
+ });
13747
+ /** One function's series. `key` is an addonId, `__root__` or `__unattributed__`. */
13748
+ var LoadFunctionSeriesSchema = object({
13749
+ key: string(),
13750
+ kind: _enum([
13751
+ "addon",
13752
+ "root",
13753
+ "unattributed"
13754
+ ]),
13755
+ /** Oldest-first. A missing interval is MISSING — never zero-filled. */
13756
+ points: array(LoadPointSchema).readonly()
13757
+ });
13758
+ var NodeLoadSeriesSchema = object({
13759
+ nodeId: string(),
13760
+ /** One entry per function seen in the window, heaviest-first. */
13761
+ series: array(LoadFunctionSeriesSchema).readonly(),
13762
+ /**
13763
+ * Width of one returned bucket, in ms. Equals the sampling cadence when no
13764
+ * reduction was needed — so a caller can always say what one point covers
13765
+ * without having to know whether it was reduced.
13766
+ */
13767
+ bucketMs: number(),
13768
+ /** Raw snapshots that went into this answer, across both tiers. */
13769
+ retainedSamples: number(),
13770
+ /** Oldest snapshot represented, or `null` when nothing is retained. */
13771
+ oldestAtMs: number().nullable(),
13772
+ /** The fixed sampling cadence in force on the cluster, in ms. */
13773
+ cadenceMs: number(),
13774
+ /**
13775
+ * Did the DURABLE tier contribute? `false` means the answer is the hot ring
13776
+ * alone — an agent (which holds no table), or a store that refused.
13777
+ * Reported because "the last hour" and "the last six hours" are different
13778
+ * questions and an operator must not have to guess which was answered.
13779
+ */
13780
+ durable: boolean()
13781
+ });
13782
+ var GetLoadSeriesInputSchema = object({
13783
+ /**
13784
+ * The node whose series is wanted.
13785
+ *
13786
+ * NOT named `nodeId`: the generated cap router strips a top-level
13787
+ * `nodeId` from every method input and uses it to ROUTE the call to
13788
+ * that node's provider (`generated-cap-routers.ts`). A series target
13789
+ * called `nodeId` would silently become a routing pin and never reach
13790
+ * the provider. The hub holds every node it hears from, so the
13791
+ * ordinary call is unpinned — answered by the hub, for any node.
13792
+ */
13793
+ forNodeId: string(),
13794
+ /**
13795
+ * EXCLUSIVE lower bound. A caller passes the newest `atMs` it already
13796
+ * holds and receives only what it is missing, so seeding a live chart
13797
+ * from this method cannot double a point already drawn.
13798
+ */
13799
+ sinceMs: number().optional(),
13800
+ /**
13801
+ * Most points the caller wants PER FUNCTION. The window is reduced to fit,
13802
+ * preserving min and max per bucket.
13803
+ *
13804
+ * Absent means NO reduction — legitimate for a short window and a trap for a
13805
+ * long one, which is why a chart passes its own pixel width.
13806
+ */
13807
+ maxPoints: number().int().positive().optional()
13808
+ });
13609
13809
  var SystemMetricsSchema = object({
13610
13810
  cpuPercent: number(),
13611
13811
  memoryPercent: number(),
@@ -13616,10 +13816,7 @@ var SystemMetricsSchema = object({
13616
13816
  gpuPercent: number().optional(),
13617
13817
  gpuMemoryPercent: number().optional()
13618
13818
  });
13619
- 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, {
13620
- kind: "mutation",
13621
- auth: "admin"
13622
- }), method(DumpHeapSnapshotInputSchema, DumpHeapSnapshotResultSchema, {
13819
+ 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, {
13623
13820
  kind: "mutation",
13624
13821
  auth: "admin"
13625
13822
  });
@@ -29097,6 +29294,15 @@ var LoggingSettingsPatchSchema = object({
29097
29294
  * authority over the whole hierarchy and answers for every layer, so the
29098
29295
  * layer selector needs a name the transport does not already own.
29099
29296
  */
29297
+ /**
29298
+ * One contribution, plus WHO reported it.
29299
+ *
29300
+ * The addon and node are added by the hub as it enumerates providers, never by
29301
+ * the contributor: an addon reporting its own identity could report somebody
29302
+ * else's, and the whole point of this surface is that no claim is made by
29303
+ * anyone but its owner.
29304
+ */
29305
+ var ReportedLoadContributionSchema = LoadContributionSchema.extend({ addonId: string() });
29100
29306
  var GetLoggingSettingsInputSchema = object({
29101
29307
  scopeNodeId: string().optional(),
29102
29308
  /**
@@ -29155,7 +29361,7 @@ method(_void(), FeatureManifestSchema), method(_void(), HealthStatusSchema), met
29155
29361
  }), method(_void(), SiteLocationStatusSchema, {
29156
29362
  kind: "mutation",
29157
29363
  auth: "admin"
29158
- }), method(_void(), RequestCensusStatusSchema, { auth: "admin" }), method(GetLoggingSettingsInputSchema, LoggingSettingsStateSchema, { auth: "admin" }), method(SetLoggingSettingsInputSchema, LoggingSettingsStateSchema, {
29364
+ }), method(_void(), RequestCensusStatusSchema, { auth: "admin" }), method(_void(), array(ReportedLoadContributionSchema).readonly(), { auth: "admin" }), method(GetLoggingSettingsInputSchema, LoggingSettingsStateSchema, { auth: "admin" }), method(SetLoggingSettingsInputSchema, LoggingSettingsStateSchema, {
29159
29365
  kind: "mutation",
29160
29366
  auth: "admin"
29161
29367
  });
@@ -32177,6 +32383,12 @@ Object.freeze({
32177
32383
  addonId: null,
32178
32384
  access: "create"
32179
32385
  },
32386
+ "dataStoreProvider.insertMany": {
32387
+ capName: "data-store-provider",
32388
+ capScope: "system",
32389
+ addonId: null,
32390
+ access: "create"
32391
+ },
32180
32392
  "dataStoreProvider.isEmpty": {
32181
32393
  capName: "data-store-provider",
32182
32394
  capScope: "system",
@@ -33491,6 +33703,12 @@ Object.freeze({
33491
33703
  addonId: null,
33492
33704
  access: "create"
33493
33705
  },
33706
+ "loadContribution.list": {
33707
+ capName: "load-contribution",
33708
+ capScope: "system",
33709
+ addonId: null,
33710
+ access: "view"
33711
+ },
33494
33712
  "localNetwork.downloadCa": {
33495
33713
  capName: "local-network",
33496
33714
  capScope: "system",
@@ -33791,17 +34009,17 @@ Object.freeze({
33791
34009
  addonId: null,
33792
34010
  access: "view"
33793
34011
  },
33794
- "metricsProvider.getProcessStats": {
34012
+ "metricsProvider.getLoadSeries": {
33795
34013
  capName: "metrics-provider",
33796
34014
  capScope: "system",
33797
34015
  addonId: null,
33798
34016
  access: "view"
33799
34017
  },
33800
- "metricsProvider.killProcess": {
34018
+ "metricsProvider.getProcessStats": {
33801
34019
  capName: "metrics-provider",
33802
34020
  capScope: "system",
33803
34021
  addonId: null,
33804
- access: "create"
34022
+ access: "view"
33805
34023
  },
33806
34024
  "metricsProvider.listAddonInstances": {
33807
34025
  capName: "metrics-provider",
@@ -35813,6 +36031,12 @@ Object.freeze({
35813
36031
  addonId: null,
35814
36032
  access: "create"
35815
36033
  },
36034
+ "settingsStore.insertMany": {
36035
+ capName: "settings-store",
36036
+ capScope: "system",
36037
+ addonId: null,
36038
+ access: "create"
36039
+ },
35816
36040
  "settingsStore.isEmpty": {
35817
36041
  capName: "settings-store",
35818
36042
  capScope: "system",
@@ -36425,6 +36649,12 @@ Object.freeze({
36425
36649
  addonId: null,
36426
36650
  access: "create"
36427
36651
  },
36652
+ "system.getLoadContributions": {
36653
+ capName: "system",
36654
+ capScope: "system",
36655
+ addonId: null,
36656
+ access: "view"
36657
+ },
36428
36658
  "system.getLoggingSettings": {
36429
36659
  capName: "system",
36430
36660
  capScope: "system",
package/dist/addon.mjs CHANGED
@@ -8,7 +8,7 @@ import { createServer } from "node:http";
8
8
  //#region \0rolldown/runtime.js
9
9
  var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
10
10
  //#endregion
11
- //#region ../types/dist/event-category-CIa_iT6b.mjs
11
+ //#region ../types/dist/event-category-BZL-fdNj.mjs
12
12
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
13
13
  EventCategory["SystemBoot"] = "system.boot";
14
14
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -445,7 +445,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
445
445
  EventCategory["MetricsNodeResourcesSnapshot"] = "metrics.node-resources-snapshot";
446
446
  /**
447
447
  * Periodic per-node process-tree snapshot (camstack-related pids
448
- * with ghost / managed / root classification). Emitted ~0.2 Hz by
448
+ * with root / managed / system classification). Emitted ~0.2 Hz by
449
449
  * the metrics-provider addon. Drives the Cluster → Processes tab
450
450
  * without polling `metricsProvider.listNodeProcesses`.
451
451
  */
@@ -11304,6 +11304,19 @@ var SettingsRecordSchema = object({
11304
11304
  data: record(string(), unknown())
11305
11305
  });
11306
11306
  /**
11307
+ * One record of a BULK insert — {@link SettingsRecordSchema} with the id made
11308
+ * optional.
11309
+ *
11310
+ * A separate schema rather than loosening the shared one: every other method
11311
+ * on this cap addresses a row BY its id, and making that field optional
11312
+ * everywhere would turn a forgotten key into a silently generated one on
11313
+ * `update` and `delete` as well.
11314
+ */
11315
+ var BulkRecordSchema = object({
11316
+ id: string().optional(),
11317
+ data: record(string(), unknown())
11318
+ });
11319
+ /**
11307
11320
  * Column declaration for a structured (SQL-backed) collection.
11308
11321
  *
11309
11322
  * Logical types — the backend translates each to the matching SQLite
@@ -11360,6 +11373,10 @@ method(object({
11360
11373
  collection: string(),
11361
11374
  record: SettingsRecordSchema
11362
11375
  }), _void(), { kind: "mutation" }), method(object({
11376
+ namespace: string().optional(),
11377
+ collection: string(),
11378
+ records: array(BulkRecordSchema).readonly()
11379
+ }), object({ inserted: number().int() }), { kind: "mutation" }), method(object({
11363
11380
  namespace: string().optional(),
11364
11381
  collection: string(),
11365
11382
  id: string(),
@@ -11468,6 +11485,13 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
11468
11485
  }), _void(), {
11469
11486
  kind: "mutation",
11470
11487
  auth: "admin"
11488
+ }), method(object({
11489
+ namespace: string().optional(),
11490
+ collection: string(),
11491
+ records: array(BulkRecordSchema).readonly()
11492
+ }), object({ inserted: number().int() }), {
11493
+ kind: "mutation",
11494
+ auth: "admin"
11471
11495
  }), method(object({
11472
11496
  namespace: string().optional(),
11473
11497
  collection: string(),
@@ -13343,6 +13367,68 @@ method(LogEntrySchema, _void(), { kind: "mutation" }), method(object({
13343
13367
  limit: number().optional(),
13344
13368
  tags: record(string(), string()).optional()
13345
13369
  }), array(LogEntrySchema).readonly());
13370
+ var LoadContributionSchema = object({
13371
+ role: _enum([
13372
+ "decode",
13373
+ "transcode",
13374
+ "recording",
13375
+ "streaming",
13376
+ "detection"
13377
+ ]),
13378
+ /**
13379
+ * The NUMERIC device id — the same value every log line carries as
13380
+ * `tags.deviceId`. `null` means this cost genuinely belongs to no single
13381
+ * camera (a shared pool), NOT that the contributor forgot to look it up: a
13382
+ * contributor that cannot name its camera must not emit the entry at all,
13383
+ * because an unnamed per-camera entry is indistinguishable from a shared one
13384
+ * and would quietly turn one camera's cost into everybody's.
13385
+ */
13386
+ deviceId: number().int().positive().nullable(),
13387
+ attribution: _enum([
13388
+ "measured",
13389
+ "accounted",
13390
+ "unattributable"
13391
+ ]),
13392
+ /**
13393
+ * What ONE entry is, in the contributor's own words — `615/high`,
13394
+ * `617/native`, `cuda:0 shared pool`. Free text because the unit differs per
13395
+ * family and inventing a common one would lose the only information that
13396
+ * makes two entries for the same camera distinguishable.
13397
+ */
13398
+ unit: string(),
13399
+ /**
13400
+ * The OS process this cost lives in, when there is one. Present so a
13401
+ * consumer can (a) tell two generations of the same unit apart across a
13402
+ * restart, and (b) subtract claimed processes from the node's process
13403
+ * snapshot to see what NOBODY claimed. Absent for an entry that owns no
13404
+ * process of its own.
13405
+ */
13406
+ pid: number().int().positive().optional(),
13407
+ /**
13408
+ * When this generation started. The pid's incarnation marker: a consumer
13409
+ * differencing {@link LoadContributionSchema.shape.cpuSeconds} must drop the
13410
+ * window when this changes, because the counter restarted from zero in a new
13411
+ * process.
13412
+ */
13413
+ startedAtMs: number().optional(),
13414
+ /**
13415
+ * CUMULATIVE CPU seconds this unit has consumed since it started — user +
13416
+ * system, read from the child's own `/proc/<pid>/stat` at the moment the
13417
+ * contribution is asked for.
13418
+ *
13419
+ * Cumulative and not a rate on purpose: a rate needs a window, a window
13420
+ * needs a sampler, and a new per-node sampler is the defect half of
13421
+ * `docs/architecture/load-ledger.md` documents. A counter can be differenced
13422
+ * by whoever already keeps a history; a rate cannot be un-averaged.
13423
+ *
13424
+ * Absent — never zero — on a node with no `/proc`, on a read failure, and on
13425
+ * an entry with no process.
13426
+ */
13427
+ cpuSeconds: number().optional(),
13428
+ /** Resident bytes of this unit's process, same source and same rules. */
13429
+ rssBytes: number().optional()
13430
+ });
13431
+ method(_void(), array(LoadContributionSchema).readonly());
13346
13432
  /**
13347
13433
  * `login-method` — collection cap through which auth addons contribute
13348
13434
  * their pre-auth login surfaces to the login page. This is the SINGLE,
@@ -13546,8 +13632,7 @@ var NodeProcessSchema = object({
13546
13632
  classification: _enum([
13547
13633
  "root",
13548
13634
  "managed",
13549
- "system",
13550
- "ghost"
13635
+ "system"
13551
13636
  ]),
13552
13637
  /** `$process` addon binding when `managed`, else null. */
13553
13638
  addonId: string().nullable(),
@@ -13555,22 +13640,39 @@ var NodeProcessSchema = object({
13555
13640
  nodeId: string().nullable(),
13556
13641
  /** Truncated command line. */
13557
13642
  command: string(),
13643
+ /**
13644
+ * `ps pcpu` — CPU averaged over the process's WHOLE LIFETIME, not a rate.
13645
+ * On a runner up for days it barely moves. Fine as a column, useless as a
13646
+ * series: use `cpuMainPercent + cpuGcPercent` for anything time-varying.
13647
+ */
13558
13648
  cpuPercent: number(),
13559
13649
  memoryRssBytes: number(),
13650
+ /**
13651
+ * Instantaneous CPU% of the process's own threads over the last
13652
+ * process-snapshot window, from a `/proc/<pid>/task/*` tick delta.
13653
+ *
13654
+ * `null` = UNKNOWN, never zero: no previous sample yet (first tick after
13655
+ * boot), the pid was recycled, or this node is not Linux.
13656
+ */
13657
+ cpuMainPercent: number().nullable(),
13658
+ /**
13659
+ * Instantaneous CPU% of V8's `V8Worker` platform pool over the same window.
13660
+ *
13661
+ * This is the number that rewrote the 2026-08-27 diagnosis — hub-main 73%,
13662
+ * `stream-broker` 61% (`docs/architecture/load-ledger.md`). A CPU chart that
13663
+ * does not separate it from `cpuMainPercent` shows "busy" where the truth is
13664
+ * "allocating too much".
13665
+ *
13666
+ * Concurrent GC is the dominant tenant of that pool but not the only one
13667
+ * (background compilation runs there too), so it is reported as
13668
+ * "GC / V8 helpers" rather than as pure collection time. `null` has the same
13669
+ * meaning as on `cpuMainPercent`.
13670
+ */
13671
+ cpuGcPercent: number().nullable(),
13672
+ /** Threads seen in the tick scan. `null` under the same conditions. */
13673
+ threadCount: number().nullable(),
13560
13674
  /** Wall-clock uptime (seconds). Parsed from `ps etime`. */
13561
- uptimeSec: number(),
13562
- /** True when ancestor walk reaches `ppid=1` (reparented to init/launchd). */
13563
- orphaned: boolean()
13564
- });
13565
- var KillProcessInputSchema = object({
13566
- pid: number(),
13567
- /** Force = SIGKILL. Default is SIGTERM. */
13568
- force: boolean().optional()
13569
- });
13570
- var KillProcessResultSchema = object({
13571
- success: boolean(),
13572
- reason: string().optional(),
13573
- signal: _enum(["SIGTERM", "SIGKILL"]).optional()
13675
+ uptimeSec: number()
13574
13676
  });
13575
13677
  var DumpHeapSnapshotInputSchema = object({
13576
13678
  /** The addon whose runner should dump a heap snapshot. */
@@ -13583,6 +13685,104 @@ var DumpHeapSnapshotResultSchema = object({
13583
13685
  pid: number().optional(),
13584
13686
  reason: string().optional()
13585
13687
  });
13688
+ /**
13689
+ * One point of one function's series.
13690
+ *
13691
+ * The unsuffixed fields are the bucket's **MAXIMUM**, and that choice is the
13692
+ * point of the whole surface. The two obvious reductions both lie: a mean per
13693
+ * bucket smears a spike away, and taking every Nth sample skips it outright.
13694
+ * Either would give us a tool built to find peaks that does not show peaks.
13695
+ * `...Min` carries the other end, `samples` says how many raw snapshots folded
13696
+ * into the bucket, and a mean stays derivable where it is wanted.
13697
+ *
13698
+ * An UNREDUCED point is a one-sample bucket: `samples === 1` and each `...Min`
13699
+ * equals its unsuffixed twin. Reduced and unreduced are the same shape, so a
13700
+ * caller cannot tell which it received — which is what "one reader" means.
13701
+ */
13702
+ var LoadPointSchema = object({
13703
+ /** Bucket START, or the snapshot's own timestamp when unreduced. */
13704
+ atMs: number(),
13705
+ /** Raw snapshots in this bucket. Never 0 — AN EMPTY BUCKET IS ABSENT. */
13706
+ samples: number().int(),
13707
+ /**
13708
+ * `null` = UNKNOWN and it PROPAGATES: a bucket is null unless every process
13709
+ * of every snapshot in it reported a thread split. A partial sum is a
13710
+ * smaller number that looks exactly as real as a complete one.
13711
+ */
13712
+ cpuMainPercent: number().nullable(),
13713
+ cpuMainPercentMin: number().nullable(),
13714
+ cpuGcPercent: number().nullable(),
13715
+ cpuGcPercentMin: number().nullable(),
13716
+ /** Lifetime-average CPU%, summed. Always known — and never a rate. */
13717
+ cpuLifetimePercent: number(),
13718
+ cpuLifetimePercentMin: number(),
13719
+ memoryRssBytes: number(),
13720
+ memoryRssBytesMin: number(),
13721
+ processCount: number().int(),
13722
+ processCountMin: number().int()
13723
+ });
13724
+ /** One function's series. `key` is an addonId, `__root__` or `__unattributed__`. */
13725
+ var LoadFunctionSeriesSchema = object({
13726
+ key: string(),
13727
+ kind: _enum([
13728
+ "addon",
13729
+ "root",
13730
+ "unattributed"
13731
+ ]),
13732
+ /** Oldest-first. A missing interval is MISSING — never zero-filled. */
13733
+ points: array(LoadPointSchema).readonly()
13734
+ });
13735
+ var NodeLoadSeriesSchema = object({
13736
+ nodeId: string(),
13737
+ /** One entry per function seen in the window, heaviest-first. */
13738
+ series: array(LoadFunctionSeriesSchema).readonly(),
13739
+ /**
13740
+ * Width of one returned bucket, in ms. Equals the sampling cadence when no
13741
+ * reduction was needed — so a caller can always say what one point covers
13742
+ * without having to know whether it was reduced.
13743
+ */
13744
+ bucketMs: number(),
13745
+ /** Raw snapshots that went into this answer, across both tiers. */
13746
+ retainedSamples: number(),
13747
+ /** Oldest snapshot represented, or `null` when nothing is retained. */
13748
+ oldestAtMs: number().nullable(),
13749
+ /** The fixed sampling cadence in force on the cluster, in ms. */
13750
+ cadenceMs: number(),
13751
+ /**
13752
+ * Did the DURABLE tier contribute? `false` means the answer is the hot ring
13753
+ * alone — an agent (which holds no table), or a store that refused.
13754
+ * Reported because "the last hour" and "the last six hours" are different
13755
+ * questions and an operator must not have to guess which was answered.
13756
+ */
13757
+ durable: boolean()
13758
+ });
13759
+ var GetLoadSeriesInputSchema = object({
13760
+ /**
13761
+ * The node whose series is wanted.
13762
+ *
13763
+ * NOT named `nodeId`: the generated cap router strips a top-level
13764
+ * `nodeId` from every method input and uses it to ROUTE the call to
13765
+ * that node's provider (`generated-cap-routers.ts`). A series target
13766
+ * called `nodeId` would silently become a routing pin and never reach
13767
+ * the provider. The hub holds every node it hears from, so the
13768
+ * ordinary call is unpinned — answered by the hub, for any node.
13769
+ */
13770
+ forNodeId: string(),
13771
+ /**
13772
+ * EXCLUSIVE lower bound. A caller passes the newest `atMs` it already
13773
+ * holds and receives only what it is missing, so seeding a live chart
13774
+ * from this method cannot double a point already drawn.
13775
+ */
13776
+ sinceMs: number().optional(),
13777
+ /**
13778
+ * Most points the caller wants PER FUNCTION. The window is reduced to fit,
13779
+ * preserving min and max per bucket.
13780
+ *
13781
+ * Absent means NO reduction — legitimate for a short window and a trap for a
13782
+ * long one, which is why a chart passes its own pixel width.
13783
+ */
13784
+ maxPoints: number().int().positive().optional()
13785
+ });
13586
13786
  var SystemMetricsSchema = object({
13587
13787
  cpuPercent: number(),
13588
13788
  memoryPercent: number(),
@@ -13593,10 +13793,7 @@ var SystemMetricsSchema = object({
13593
13793
  gpuPercent: number().optional(),
13594
13794
  gpuMemoryPercent: number().optional()
13595
13795
  });
13596
- 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, {
13597
- kind: "mutation",
13598
- auth: "admin"
13599
- }), method(DumpHeapSnapshotInputSchema, DumpHeapSnapshotResultSchema, {
13796
+ 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, {
13600
13797
  kind: "mutation",
13601
13798
  auth: "admin"
13602
13799
  });
@@ -29074,6 +29271,15 @@ var LoggingSettingsPatchSchema = object({
29074
29271
  * authority over the whole hierarchy and answers for every layer, so the
29075
29272
  * layer selector needs a name the transport does not already own.
29076
29273
  */
29274
+ /**
29275
+ * One contribution, plus WHO reported it.
29276
+ *
29277
+ * The addon and node are added by the hub as it enumerates providers, never by
29278
+ * the contributor: an addon reporting its own identity could report somebody
29279
+ * else's, and the whole point of this surface is that no claim is made by
29280
+ * anyone but its owner.
29281
+ */
29282
+ var ReportedLoadContributionSchema = LoadContributionSchema.extend({ addonId: string() });
29077
29283
  var GetLoggingSettingsInputSchema = object({
29078
29284
  scopeNodeId: string().optional(),
29079
29285
  /**
@@ -29132,7 +29338,7 @@ method(_void(), FeatureManifestSchema), method(_void(), HealthStatusSchema), met
29132
29338
  }), method(_void(), SiteLocationStatusSchema, {
29133
29339
  kind: "mutation",
29134
29340
  auth: "admin"
29135
- }), method(_void(), RequestCensusStatusSchema, { auth: "admin" }), method(GetLoggingSettingsInputSchema, LoggingSettingsStateSchema, { auth: "admin" }), method(SetLoggingSettingsInputSchema, LoggingSettingsStateSchema, {
29341
+ }), method(_void(), RequestCensusStatusSchema, { auth: "admin" }), method(_void(), array(ReportedLoadContributionSchema).readonly(), { auth: "admin" }), method(GetLoggingSettingsInputSchema, LoggingSettingsStateSchema, { auth: "admin" }), method(SetLoggingSettingsInputSchema, LoggingSettingsStateSchema, {
29136
29342
  kind: "mutation",
29137
29343
  auth: "admin"
29138
29344
  });
@@ -32154,6 +32360,12 @@ Object.freeze({
32154
32360
  addonId: null,
32155
32361
  access: "create"
32156
32362
  },
32363
+ "dataStoreProvider.insertMany": {
32364
+ capName: "data-store-provider",
32365
+ capScope: "system",
32366
+ addonId: null,
32367
+ access: "create"
32368
+ },
32157
32369
  "dataStoreProvider.isEmpty": {
32158
32370
  capName: "data-store-provider",
32159
32371
  capScope: "system",
@@ -33468,6 +33680,12 @@ Object.freeze({
33468
33680
  addonId: null,
33469
33681
  access: "create"
33470
33682
  },
33683
+ "loadContribution.list": {
33684
+ capName: "load-contribution",
33685
+ capScope: "system",
33686
+ addonId: null,
33687
+ access: "view"
33688
+ },
33471
33689
  "localNetwork.downloadCa": {
33472
33690
  capName: "local-network",
33473
33691
  capScope: "system",
@@ -33768,17 +33986,17 @@ Object.freeze({
33768
33986
  addonId: null,
33769
33987
  access: "view"
33770
33988
  },
33771
- "metricsProvider.getProcessStats": {
33989
+ "metricsProvider.getLoadSeries": {
33772
33990
  capName: "metrics-provider",
33773
33991
  capScope: "system",
33774
33992
  addonId: null,
33775
33993
  access: "view"
33776
33994
  },
33777
- "metricsProvider.killProcess": {
33995
+ "metricsProvider.getProcessStats": {
33778
33996
  capName: "metrics-provider",
33779
33997
  capScope: "system",
33780
33998
  addonId: null,
33781
- access: "create"
33999
+ access: "view"
33782
34000
  },
33783
34001
  "metricsProvider.listAddonInstances": {
33784
34002
  capName: "metrics-provider",
@@ -35790,6 +36008,12 @@ Object.freeze({
35790
36008
  addonId: null,
35791
36009
  access: "create"
35792
36010
  },
36011
+ "settingsStore.insertMany": {
36012
+ capName: "settings-store",
36013
+ capScope: "system",
36014
+ addonId: null,
36015
+ access: "create"
36016
+ },
35793
36017
  "settingsStore.isEmpty": {
35794
36018
  capName: "settings-store",
35795
36019
  capScope: "system",
@@ -36402,6 +36626,12 @@ Object.freeze({
36402
36626
  addonId: null,
36403
36627
  access: "create"
36404
36628
  },
36629
+ "system.getLoadContributions": {
36630
+ capName: "system",
36631
+ capScope: "system",
36632
+ addonId: null,
36633
+ access: "view"
36634
+ },
36405
36635
  "system.getLoggingSettings": {
36406
36636
  capName: "system",
36407
36637
  capScope: "system",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-terminal",
3
- "version": "0.1.40",
3
+ "version": "0.1.42",
4
4
  "description": "Interactive terminal sessions (pty + xterm) as a CamStack addon",
5
5
  "keywords": [
6
6
  "camstack",