@camstack/addon-decoder-nodeav 1.2.34 → 1.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/index.js +255 -25
  2. package/dist/index.mjs +255 -25
  3. package/package.json +3 -2
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  let node_crypto = require("node:crypto");
6
- //#region ../types/dist/event-category-CIa_iT6b.mjs
6
+ //#region ../types/dist/event-category-BZL-fdNj.mjs
7
7
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
8
8
  EventCategory["SystemBoot"] = "system.boot";
9
9
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -440,7 +440,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
440
440
  EventCategory["MetricsNodeResourcesSnapshot"] = "metrics.node-resources-snapshot";
441
441
  /**
442
442
  * Periodic per-node process-tree snapshot (camstack-related pids
443
- * with ghost / managed / root classification). Emitted ~0.2 Hz by
443
+ * with root / managed / system classification). Emitted ~0.2 Hz by
444
444
  * the metrics-provider addon. Drives the Cluster → Processes tab
445
445
  * without polling `metricsProvider.listNodeProcesses`.
446
446
  */
@@ -11163,6 +11163,19 @@ var SettingsRecordSchema = object({
11163
11163
  data: record(string(), unknown())
11164
11164
  });
11165
11165
  /**
11166
+ * One record of a BULK insert — {@link SettingsRecordSchema} with the id made
11167
+ * optional.
11168
+ *
11169
+ * A separate schema rather than loosening the shared one: every other method
11170
+ * on this cap addresses a row BY its id, and making that field optional
11171
+ * everywhere would turn a forgotten key into a silently generated one on
11172
+ * `update` and `delete` as well.
11173
+ */
11174
+ var BulkRecordSchema = object({
11175
+ id: string().optional(),
11176
+ data: record(string(), unknown())
11177
+ });
11178
+ /**
11166
11179
  * Column declaration for a structured (SQL-backed) collection.
11167
11180
  *
11168
11181
  * Logical types — the backend translates each to the matching SQLite
@@ -11219,6 +11232,10 @@ method(object({
11219
11232
  collection: string(),
11220
11233
  record: SettingsRecordSchema
11221
11234
  }), _void(), { kind: "mutation" }), method(object({
11235
+ namespace: string().optional(),
11236
+ collection: string(),
11237
+ records: array(BulkRecordSchema).readonly()
11238
+ }), object({ inserted: number().int() }), { kind: "mutation" }), method(object({
11222
11239
  namespace: string().optional(),
11223
11240
  collection: string(),
11224
11241
  id: string(),
@@ -11327,6 +11344,13 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
11327
11344
  }), _void(), {
11328
11345
  kind: "mutation",
11329
11346
  auth: "admin"
11347
+ }), method(object({
11348
+ namespace: string().optional(),
11349
+ collection: string(),
11350
+ records: array(BulkRecordSchema).readonly()
11351
+ }), object({ inserted: number().int() }), {
11352
+ kind: "mutation",
11353
+ auth: "admin"
11330
11354
  }), method(object({
11331
11355
  namespace: string().optional(),
11332
11356
  collection: string(),
@@ -13188,6 +13212,68 @@ method(LogEntrySchema, _void(), { kind: "mutation" }), method(object({
13188
13212
  limit: number().optional(),
13189
13213
  tags: record(string(), string()).optional()
13190
13214
  }), array(LogEntrySchema).readonly());
13215
+ var LoadContributionSchema = object({
13216
+ role: _enum([
13217
+ "decode",
13218
+ "transcode",
13219
+ "recording",
13220
+ "streaming",
13221
+ "detection"
13222
+ ]),
13223
+ /**
13224
+ * The NUMERIC device id — the same value every log line carries as
13225
+ * `tags.deviceId`. `null` means this cost genuinely belongs to no single
13226
+ * camera (a shared pool), NOT that the contributor forgot to look it up: a
13227
+ * contributor that cannot name its camera must not emit the entry at all,
13228
+ * because an unnamed per-camera entry is indistinguishable from a shared one
13229
+ * and would quietly turn one camera's cost into everybody's.
13230
+ */
13231
+ deviceId: number().int().positive().nullable(),
13232
+ attribution: _enum([
13233
+ "measured",
13234
+ "accounted",
13235
+ "unattributable"
13236
+ ]),
13237
+ /**
13238
+ * What ONE entry is, in the contributor's own words — `615/high`,
13239
+ * `617/native`, `cuda:0 shared pool`. Free text because the unit differs per
13240
+ * family and inventing a common one would lose the only information that
13241
+ * makes two entries for the same camera distinguishable.
13242
+ */
13243
+ unit: string(),
13244
+ /**
13245
+ * The OS process this cost lives in, when there is one. Present so a
13246
+ * consumer can (a) tell two generations of the same unit apart across a
13247
+ * restart, and (b) subtract claimed processes from the node's process
13248
+ * snapshot to see what NOBODY claimed. Absent for an entry that owns no
13249
+ * process of its own.
13250
+ */
13251
+ pid: number().int().positive().optional(),
13252
+ /**
13253
+ * When this generation started. The pid's incarnation marker: a consumer
13254
+ * differencing {@link LoadContributionSchema.shape.cpuSeconds} must drop the
13255
+ * window when this changes, because the counter restarted from zero in a new
13256
+ * process.
13257
+ */
13258
+ startedAtMs: number().optional(),
13259
+ /**
13260
+ * CUMULATIVE CPU seconds this unit has consumed since it started — user +
13261
+ * system, read from the child's own `/proc/<pid>/stat` at the moment the
13262
+ * contribution is asked for.
13263
+ *
13264
+ * Cumulative and not a rate on purpose: a rate needs a window, a window
13265
+ * needs a sampler, and a new per-node sampler is the defect half of
13266
+ * `docs/architecture/load-ledger.md` documents. A counter can be differenced
13267
+ * by whoever already keeps a history; a rate cannot be un-averaged.
13268
+ *
13269
+ * Absent — never zero — on a node with no `/proc`, on a read failure, and on
13270
+ * an entry with no process.
13271
+ */
13272
+ cpuSeconds: number().optional(),
13273
+ /** Resident bytes of this unit's process, same source and same rules. */
13274
+ rssBytes: number().optional()
13275
+ });
13276
+ method(_void(), array(LoadContributionSchema).readonly());
13191
13277
  /**
13192
13278
  * `login-method` — collection cap through which auth addons contribute
13193
13279
  * their pre-auth login surfaces to the login page. This is the SINGLE,
@@ -13391,8 +13477,7 @@ var NodeProcessSchema = object({
13391
13477
  classification: _enum([
13392
13478
  "root",
13393
13479
  "managed",
13394
- "system",
13395
- "ghost"
13480
+ "system"
13396
13481
  ]),
13397
13482
  /** `$process` addon binding when `managed`, else null. */
13398
13483
  addonId: string().nullable(),
@@ -13400,22 +13485,39 @@ var NodeProcessSchema = object({
13400
13485
  nodeId: string().nullable(),
13401
13486
  /** Truncated command line. */
13402
13487
  command: string(),
13488
+ /**
13489
+ * `ps pcpu` — CPU averaged over the process's WHOLE LIFETIME, not a rate.
13490
+ * On a runner up for days it barely moves. Fine as a column, useless as a
13491
+ * series: use `cpuMainPercent + cpuGcPercent` for anything time-varying.
13492
+ */
13403
13493
  cpuPercent: number(),
13404
13494
  memoryRssBytes: number(),
13495
+ /**
13496
+ * Instantaneous CPU% of the process's own threads over the last
13497
+ * process-snapshot window, from a `/proc/<pid>/task/*` tick delta.
13498
+ *
13499
+ * `null` = UNKNOWN, never zero: no previous sample yet (first tick after
13500
+ * boot), the pid was recycled, or this node is not Linux.
13501
+ */
13502
+ cpuMainPercent: number().nullable(),
13503
+ /**
13504
+ * Instantaneous CPU% of V8's `V8Worker` platform pool over the same window.
13505
+ *
13506
+ * This is the number that rewrote the 2026-08-27 diagnosis — hub-main 73%,
13507
+ * `stream-broker` 61% (`docs/architecture/load-ledger.md`). A CPU chart that
13508
+ * does not separate it from `cpuMainPercent` shows "busy" where the truth is
13509
+ * "allocating too much".
13510
+ *
13511
+ * Concurrent GC is the dominant tenant of that pool but not the only one
13512
+ * (background compilation runs there too), so it is reported as
13513
+ * "GC / V8 helpers" rather than as pure collection time. `null` has the same
13514
+ * meaning as on `cpuMainPercent`.
13515
+ */
13516
+ cpuGcPercent: number().nullable(),
13517
+ /** Threads seen in the tick scan. `null` under the same conditions. */
13518
+ threadCount: number().nullable(),
13405
13519
  /** Wall-clock uptime (seconds). Parsed from `ps etime`. */
13406
- uptimeSec: number(),
13407
- /** True when ancestor walk reaches `ppid=1` (reparented to init/launchd). */
13408
- orphaned: boolean()
13409
- });
13410
- var KillProcessInputSchema = object({
13411
- pid: number(),
13412
- /** Force = SIGKILL. Default is SIGTERM. */
13413
- force: boolean().optional()
13414
- });
13415
- var KillProcessResultSchema = object({
13416
- success: boolean(),
13417
- reason: string().optional(),
13418
- signal: _enum(["SIGTERM", "SIGKILL"]).optional()
13520
+ uptimeSec: number()
13419
13521
  });
13420
13522
  var DumpHeapSnapshotInputSchema = object({
13421
13523
  /** The addon whose runner should dump a heap snapshot. */
@@ -13428,6 +13530,104 @@ var DumpHeapSnapshotResultSchema = object({
13428
13530
  pid: number().optional(),
13429
13531
  reason: string().optional()
13430
13532
  });
13533
+ /**
13534
+ * One point of one function's series.
13535
+ *
13536
+ * The unsuffixed fields are the bucket's **MAXIMUM**, and that choice is the
13537
+ * point of the whole surface. The two obvious reductions both lie: a mean per
13538
+ * bucket smears a spike away, and taking every Nth sample skips it outright.
13539
+ * Either would give us a tool built to find peaks that does not show peaks.
13540
+ * `...Min` carries the other end, `samples` says how many raw snapshots folded
13541
+ * into the bucket, and a mean stays derivable where it is wanted.
13542
+ *
13543
+ * An UNREDUCED point is a one-sample bucket: `samples === 1` and each `...Min`
13544
+ * equals its unsuffixed twin. Reduced and unreduced are the same shape, so a
13545
+ * caller cannot tell which it received — which is what "one reader" means.
13546
+ */
13547
+ var LoadPointSchema = object({
13548
+ /** Bucket START, or the snapshot's own timestamp when unreduced. */
13549
+ atMs: number(),
13550
+ /** Raw snapshots in this bucket. Never 0 — AN EMPTY BUCKET IS ABSENT. */
13551
+ samples: number().int(),
13552
+ /**
13553
+ * `null` = UNKNOWN and it PROPAGATES: a bucket is null unless every process
13554
+ * of every snapshot in it reported a thread split. A partial sum is a
13555
+ * smaller number that looks exactly as real as a complete one.
13556
+ */
13557
+ cpuMainPercent: number().nullable(),
13558
+ cpuMainPercentMin: number().nullable(),
13559
+ cpuGcPercent: number().nullable(),
13560
+ cpuGcPercentMin: number().nullable(),
13561
+ /** Lifetime-average CPU%, summed. Always known — and never a rate. */
13562
+ cpuLifetimePercent: number(),
13563
+ cpuLifetimePercentMin: number(),
13564
+ memoryRssBytes: number(),
13565
+ memoryRssBytesMin: number(),
13566
+ processCount: number().int(),
13567
+ processCountMin: number().int()
13568
+ });
13569
+ /** One function's series. `key` is an addonId, `__root__` or `__unattributed__`. */
13570
+ var LoadFunctionSeriesSchema = object({
13571
+ key: string(),
13572
+ kind: _enum([
13573
+ "addon",
13574
+ "root",
13575
+ "unattributed"
13576
+ ]),
13577
+ /** Oldest-first. A missing interval is MISSING — never zero-filled. */
13578
+ points: array(LoadPointSchema).readonly()
13579
+ });
13580
+ var NodeLoadSeriesSchema = object({
13581
+ nodeId: string(),
13582
+ /** One entry per function seen in the window, heaviest-first. */
13583
+ series: array(LoadFunctionSeriesSchema).readonly(),
13584
+ /**
13585
+ * Width of one returned bucket, in ms. Equals the sampling cadence when no
13586
+ * reduction was needed — so a caller can always say what one point covers
13587
+ * without having to know whether it was reduced.
13588
+ */
13589
+ bucketMs: number(),
13590
+ /** Raw snapshots that went into this answer, across both tiers. */
13591
+ retainedSamples: number(),
13592
+ /** Oldest snapshot represented, or `null` when nothing is retained. */
13593
+ oldestAtMs: number().nullable(),
13594
+ /** The fixed sampling cadence in force on the cluster, in ms. */
13595
+ cadenceMs: number(),
13596
+ /**
13597
+ * Did the DURABLE tier contribute? `false` means the answer is the hot ring
13598
+ * alone — an agent (which holds no table), or a store that refused.
13599
+ * Reported because "the last hour" and "the last six hours" are different
13600
+ * questions and an operator must not have to guess which was answered.
13601
+ */
13602
+ durable: boolean()
13603
+ });
13604
+ var GetLoadSeriesInputSchema = object({
13605
+ /**
13606
+ * The node whose series is wanted.
13607
+ *
13608
+ * NOT named `nodeId`: the generated cap router strips a top-level
13609
+ * `nodeId` from every method input and uses it to ROUTE the call to
13610
+ * that node's provider (`generated-cap-routers.ts`). A series target
13611
+ * called `nodeId` would silently become a routing pin and never reach
13612
+ * the provider. The hub holds every node it hears from, so the
13613
+ * ordinary call is unpinned — answered by the hub, for any node.
13614
+ */
13615
+ forNodeId: string(),
13616
+ /**
13617
+ * EXCLUSIVE lower bound. A caller passes the newest `atMs` it already
13618
+ * holds and receives only what it is missing, so seeding a live chart
13619
+ * from this method cannot double a point already drawn.
13620
+ */
13621
+ sinceMs: number().optional(),
13622
+ /**
13623
+ * Most points the caller wants PER FUNCTION. The window is reduced to fit,
13624
+ * preserving min and max per bucket.
13625
+ *
13626
+ * Absent means NO reduction — legitimate for a short window and a trap for a
13627
+ * long one, which is why a chart passes its own pixel width.
13628
+ */
13629
+ maxPoints: number().int().positive().optional()
13630
+ });
13431
13631
  var SystemMetricsSchema = object({
13432
13632
  cpuPercent: number(),
13433
13633
  memoryPercent: number(),
@@ -13438,10 +13638,7 @@ var SystemMetricsSchema = object({
13438
13638
  gpuPercent: number().optional(),
13439
13639
  gpuMemoryPercent: number().optional()
13440
13640
  });
13441
- 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, {
13442
- kind: "mutation",
13443
- auth: "admin"
13444
- }), method(DumpHeapSnapshotInputSchema, DumpHeapSnapshotResultSchema, {
13641
+ 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, {
13445
13642
  kind: "mutation",
13446
13643
  auth: "admin"
13447
13644
  });
@@ -26744,6 +26941,15 @@ var LoggingSettingsPatchSchema = object({
26744
26941
  * authority over the whole hierarchy and answers for every layer, so the
26745
26942
  * layer selector needs a name the transport does not already own.
26746
26943
  */
26944
+ /**
26945
+ * One contribution, plus WHO reported it.
26946
+ *
26947
+ * The addon and node are added by the hub as it enumerates providers, never by
26948
+ * the contributor: an addon reporting its own identity could report somebody
26949
+ * else's, and the whole point of this surface is that no claim is made by
26950
+ * anyone but its owner.
26951
+ */
26952
+ var ReportedLoadContributionSchema = LoadContributionSchema.extend({ addonId: string() });
26747
26953
  var GetLoggingSettingsInputSchema = object({
26748
26954
  scopeNodeId: string().optional(),
26749
26955
  /**
@@ -26802,7 +27008,7 @@ method(_void(), FeatureManifestSchema), method(_void(), HealthStatusSchema), met
26802
27008
  }), method(_void(), SiteLocationStatusSchema, {
26803
27009
  kind: "mutation",
26804
27010
  auth: "admin"
26805
- }), method(_void(), RequestCensusStatusSchema, { auth: "admin" }), method(GetLoggingSettingsInputSchema, LoggingSettingsStateSchema, { auth: "admin" }), method(SetLoggingSettingsInputSchema, LoggingSettingsStateSchema, {
27011
+ }), method(_void(), RequestCensusStatusSchema, { auth: "admin" }), method(_void(), array(ReportedLoadContributionSchema).readonly(), { auth: "admin" }), method(GetLoggingSettingsInputSchema, LoggingSettingsStateSchema, { auth: "admin" }), method(SetLoggingSettingsInputSchema, LoggingSettingsStateSchema, {
26806
27012
  kind: "mutation",
26807
27013
  auth: "admin"
26808
27014
  });
@@ -28418,6 +28624,12 @@ Object.freeze({
28418
28624
  addonId: null,
28419
28625
  access: "create"
28420
28626
  },
28627
+ "dataStoreProvider.insertMany": {
28628
+ capName: "data-store-provider",
28629
+ capScope: "system",
28630
+ addonId: null,
28631
+ access: "create"
28632
+ },
28421
28633
  "dataStoreProvider.isEmpty": {
28422
28634
  capName: "data-store-provider",
28423
28635
  capScope: "system",
@@ -29732,6 +29944,12 @@ Object.freeze({
29732
29944
  addonId: null,
29733
29945
  access: "create"
29734
29946
  },
29947
+ "loadContribution.list": {
29948
+ capName: "load-contribution",
29949
+ capScope: "system",
29950
+ addonId: null,
29951
+ access: "view"
29952
+ },
29735
29953
  "localNetwork.downloadCa": {
29736
29954
  capName: "local-network",
29737
29955
  capScope: "system",
@@ -30032,17 +30250,17 @@ Object.freeze({
30032
30250
  addonId: null,
30033
30251
  access: "view"
30034
30252
  },
30035
- "metricsProvider.getProcessStats": {
30253
+ "metricsProvider.getLoadSeries": {
30036
30254
  capName: "metrics-provider",
30037
30255
  capScope: "system",
30038
30256
  addonId: null,
30039
30257
  access: "view"
30040
30258
  },
30041
- "metricsProvider.killProcess": {
30259
+ "metricsProvider.getProcessStats": {
30042
30260
  capName: "metrics-provider",
30043
30261
  capScope: "system",
30044
30262
  addonId: null,
30045
- access: "create"
30263
+ access: "view"
30046
30264
  },
30047
30265
  "metricsProvider.listAddonInstances": {
30048
30266
  capName: "metrics-provider",
@@ -32054,6 +32272,12 @@ Object.freeze({
32054
32272
  addonId: null,
32055
32273
  access: "create"
32056
32274
  },
32275
+ "settingsStore.insertMany": {
32276
+ capName: "settings-store",
32277
+ capScope: "system",
32278
+ addonId: null,
32279
+ access: "create"
32280
+ },
32057
32281
  "settingsStore.isEmpty": {
32058
32282
  capName: "settings-store",
32059
32283
  capScope: "system",
@@ -32666,6 +32890,12 @@ Object.freeze({
32666
32890
  addonId: null,
32667
32891
  access: "create"
32668
32892
  },
32893
+ "system.getLoadContributions": {
32894
+ capName: "system",
32895
+ capScope: "system",
32896
+ addonId: null,
32897
+ access: "view"
32898
+ },
32669
32899
  "system.getLoggingSettings": {
32670
32900
  capName: "system",
32671
32901
  capScope: "system",
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { randomUUID } from "node:crypto";
2
- //#region ../types/dist/event-category-CIa_iT6b.mjs
2
+ //#region ../types/dist/event-category-BZL-fdNj.mjs
3
3
  var EventCategory = /* @__PURE__ */ function(EventCategory) {
4
4
  EventCategory["SystemBoot"] = "system.boot";
5
5
  EventCategory["SystemAddonsReady"] = "system.addons-ready";
@@ -436,7 +436,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
436
436
  EventCategory["MetricsNodeResourcesSnapshot"] = "metrics.node-resources-snapshot";
437
437
  /**
438
438
  * Periodic per-node process-tree snapshot (camstack-related pids
439
- * with ghost / managed / root classification). Emitted ~0.2 Hz by
439
+ * with root / managed / system classification). Emitted ~0.2 Hz by
440
440
  * the metrics-provider addon. Drives the Cluster → Processes tab
441
441
  * without polling `metricsProvider.listNodeProcesses`.
442
442
  */
@@ -11159,6 +11159,19 @@ var SettingsRecordSchema = object({
11159
11159
  data: record(string(), unknown())
11160
11160
  });
11161
11161
  /**
11162
+ * One record of a BULK insert — {@link SettingsRecordSchema} with the id made
11163
+ * optional.
11164
+ *
11165
+ * A separate schema rather than loosening the shared one: every other method
11166
+ * on this cap addresses a row BY its id, and making that field optional
11167
+ * everywhere would turn a forgotten key into a silently generated one on
11168
+ * `update` and `delete` as well.
11169
+ */
11170
+ var BulkRecordSchema = object({
11171
+ id: string().optional(),
11172
+ data: record(string(), unknown())
11173
+ });
11174
+ /**
11162
11175
  * Column declaration for a structured (SQL-backed) collection.
11163
11176
  *
11164
11177
  * Logical types — the backend translates each to the matching SQLite
@@ -11215,6 +11228,10 @@ method(object({
11215
11228
  collection: string(),
11216
11229
  record: SettingsRecordSchema
11217
11230
  }), _void(), { kind: "mutation" }), method(object({
11231
+ namespace: string().optional(),
11232
+ collection: string(),
11233
+ records: array(BulkRecordSchema).readonly()
11234
+ }), object({ inserted: number().int() }), { kind: "mutation" }), method(object({
11218
11235
  namespace: string().optional(),
11219
11236
  collection: string(),
11220
11237
  id: string(),
@@ -11323,6 +11340,13 @@ method(_void(), EngineInfoSchema, { auth: "admin" }), method(object({
11323
11340
  }), _void(), {
11324
11341
  kind: "mutation",
11325
11342
  auth: "admin"
11343
+ }), method(object({
11344
+ namespace: string().optional(),
11345
+ collection: string(),
11346
+ records: array(BulkRecordSchema).readonly()
11347
+ }), object({ inserted: number().int() }), {
11348
+ kind: "mutation",
11349
+ auth: "admin"
11326
11350
  }), method(object({
11327
11351
  namespace: string().optional(),
11328
11352
  collection: string(),
@@ -13184,6 +13208,68 @@ method(LogEntrySchema, _void(), { kind: "mutation" }), method(object({
13184
13208
  limit: number().optional(),
13185
13209
  tags: record(string(), string()).optional()
13186
13210
  }), array(LogEntrySchema).readonly());
13211
+ var LoadContributionSchema = object({
13212
+ role: _enum([
13213
+ "decode",
13214
+ "transcode",
13215
+ "recording",
13216
+ "streaming",
13217
+ "detection"
13218
+ ]),
13219
+ /**
13220
+ * The NUMERIC device id — the same value every log line carries as
13221
+ * `tags.deviceId`. `null` means this cost genuinely belongs to no single
13222
+ * camera (a shared pool), NOT that the contributor forgot to look it up: a
13223
+ * contributor that cannot name its camera must not emit the entry at all,
13224
+ * because an unnamed per-camera entry is indistinguishable from a shared one
13225
+ * and would quietly turn one camera's cost into everybody's.
13226
+ */
13227
+ deviceId: number().int().positive().nullable(),
13228
+ attribution: _enum([
13229
+ "measured",
13230
+ "accounted",
13231
+ "unattributable"
13232
+ ]),
13233
+ /**
13234
+ * What ONE entry is, in the contributor's own words — `615/high`,
13235
+ * `617/native`, `cuda:0 shared pool`. Free text because the unit differs per
13236
+ * family and inventing a common one would lose the only information that
13237
+ * makes two entries for the same camera distinguishable.
13238
+ */
13239
+ unit: string(),
13240
+ /**
13241
+ * The OS process this cost lives in, when there is one. Present so a
13242
+ * consumer can (a) tell two generations of the same unit apart across a
13243
+ * restart, and (b) subtract claimed processes from the node's process
13244
+ * snapshot to see what NOBODY claimed. Absent for an entry that owns no
13245
+ * process of its own.
13246
+ */
13247
+ pid: number().int().positive().optional(),
13248
+ /**
13249
+ * When this generation started. The pid's incarnation marker: a consumer
13250
+ * differencing {@link LoadContributionSchema.shape.cpuSeconds} must drop the
13251
+ * window when this changes, because the counter restarted from zero in a new
13252
+ * process.
13253
+ */
13254
+ startedAtMs: number().optional(),
13255
+ /**
13256
+ * CUMULATIVE CPU seconds this unit has consumed since it started — user +
13257
+ * system, read from the child's own `/proc/<pid>/stat` at the moment the
13258
+ * contribution is asked for.
13259
+ *
13260
+ * Cumulative and not a rate on purpose: a rate needs a window, a window
13261
+ * needs a sampler, and a new per-node sampler is the defect half of
13262
+ * `docs/architecture/load-ledger.md` documents. A counter can be differenced
13263
+ * by whoever already keeps a history; a rate cannot be un-averaged.
13264
+ *
13265
+ * Absent — never zero — on a node with no `/proc`, on a read failure, and on
13266
+ * an entry with no process.
13267
+ */
13268
+ cpuSeconds: number().optional(),
13269
+ /** Resident bytes of this unit's process, same source and same rules. */
13270
+ rssBytes: number().optional()
13271
+ });
13272
+ method(_void(), array(LoadContributionSchema).readonly());
13187
13273
  /**
13188
13274
  * `login-method` — collection cap through which auth addons contribute
13189
13275
  * their pre-auth login surfaces to the login page. This is the SINGLE,
@@ -13387,8 +13473,7 @@ var NodeProcessSchema = object({
13387
13473
  classification: _enum([
13388
13474
  "root",
13389
13475
  "managed",
13390
- "system",
13391
- "ghost"
13476
+ "system"
13392
13477
  ]),
13393
13478
  /** `$process` addon binding when `managed`, else null. */
13394
13479
  addonId: string().nullable(),
@@ -13396,22 +13481,39 @@ var NodeProcessSchema = object({
13396
13481
  nodeId: string().nullable(),
13397
13482
  /** Truncated command line. */
13398
13483
  command: string(),
13484
+ /**
13485
+ * `ps pcpu` — CPU averaged over the process's WHOLE LIFETIME, not a rate.
13486
+ * On a runner up for days it barely moves. Fine as a column, useless as a
13487
+ * series: use `cpuMainPercent + cpuGcPercent` for anything time-varying.
13488
+ */
13399
13489
  cpuPercent: number(),
13400
13490
  memoryRssBytes: number(),
13491
+ /**
13492
+ * Instantaneous CPU% of the process's own threads over the last
13493
+ * process-snapshot window, from a `/proc/<pid>/task/*` tick delta.
13494
+ *
13495
+ * `null` = UNKNOWN, never zero: no previous sample yet (first tick after
13496
+ * boot), the pid was recycled, or this node is not Linux.
13497
+ */
13498
+ cpuMainPercent: number().nullable(),
13499
+ /**
13500
+ * Instantaneous CPU% of V8's `V8Worker` platform pool over the same window.
13501
+ *
13502
+ * This is the number that rewrote the 2026-08-27 diagnosis — hub-main 73%,
13503
+ * `stream-broker` 61% (`docs/architecture/load-ledger.md`). A CPU chart that
13504
+ * does not separate it from `cpuMainPercent` shows "busy" where the truth is
13505
+ * "allocating too much".
13506
+ *
13507
+ * Concurrent GC is the dominant tenant of that pool but not the only one
13508
+ * (background compilation runs there too), so it is reported as
13509
+ * "GC / V8 helpers" rather than as pure collection time. `null` has the same
13510
+ * meaning as on `cpuMainPercent`.
13511
+ */
13512
+ cpuGcPercent: number().nullable(),
13513
+ /** Threads seen in the tick scan. `null` under the same conditions. */
13514
+ threadCount: number().nullable(),
13401
13515
  /** Wall-clock uptime (seconds). Parsed from `ps etime`. */
13402
- uptimeSec: number(),
13403
- /** True when ancestor walk reaches `ppid=1` (reparented to init/launchd). */
13404
- orphaned: boolean()
13405
- });
13406
- var KillProcessInputSchema = object({
13407
- pid: number(),
13408
- /** Force = SIGKILL. Default is SIGTERM. */
13409
- force: boolean().optional()
13410
- });
13411
- var KillProcessResultSchema = object({
13412
- success: boolean(),
13413
- reason: string().optional(),
13414
- signal: _enum(["SIGTERM", "SIGKILL"]).optional()
13516
+ uptimeSec: number()
13415
13517
  });
13416
13518
  var DumpHeapSnapshotInputSchema = object({
13417
13519
  /** The addon whose runner should dump a heap snapshot. */
@@ -13424,6 +13526,104 @@ var DumpHeapSnapshotResultSchema = object({
13424
13526
  pid: number().optional(),
13425
13527
  reason: string().optional()
13426
13528
  });
13529
+ /**
13530
+ * One point of one function's series.
13531
+ *
13532
+ * The unsuffixed fields are the bucket's **MAXIMUM**, and that choice is the
13533
+ * point of the whole surface. The two obvious reductions both lie: a mean per
13534
+ * bucket smears a spike away, and taking every Nth sample skips it outright.
13535
+ * Either would give us a tool built to find peaks that does not show peaks.
13536
+ * `...Min` carries the other end, `samples` says how many raw snapshots folded
13537
+ * into the bucket, and a mean stays derivable where it is wanted.
13538
+ *
13539
+ * An UNREDUCED point is a one-sample bucket: `samples === 1` and each `...Min`
13540
+ * equals its unsuffixed twin. Reduced and unreduced are the same shape, so a
13541
+ * caller cannot tell which it received — which is what "one reader" means.
13542
+ */
13543
+ var LoadPointSchema = object({
13544
+ /** Bucket START, or the snapshot's own timestamp when unreduced. */
13545
+ atMs: number(),
13546
+ /** Raw snapshots in this bucket. Never 0 — AN EMPTY BUCKET IS ABSENT. */
13547
+ samples: number().int(),
13548
+ /**
13549
+ * `null` = UNKNOWN and it PROPAGATES: a bucket is null unless every process
13550
+ * of every snapshot in it reported a thread split. A partial sum is a
13551
+ * smaller number that looks exactly as real as a complete one.
13552
+ */
13553
+ cpuMainPercent: number().nullable(),
13554
+ cpuMainPercentMin: number().nullable(),
13555
+ cpuGcPercent: number().nullable(),
13556
+ cpuGcPercentMin: number().nullable(),
13557
+ /** Lifetime-average CPU%, summed. Always known — and never a rate. */
13558
+ cpuLifetimePercent: number(),
13559
+ cpuLifetimePercentMin: number(),
13560
+ memoryRssBytes: number(),
13561
+ memoryRssBytesMin: number(),
13562
+ processCount: number().int(),
13563
+ processCountMin: number().int()
13564
+ });
13565
+ /** One function's series. `key` is an addonId, `__root__` or `__unattributed__`. */
13566
+ var LoadFunctionSeriesSchema = object({
13567
+ key: string(),
13568
+ kind: _enum([
13569
+ "addon",
13570
+ "root",
13571
+ "unattributed"
13572
+ ]),
13573
+ /** Oldest-first. A missing interval is MISSING — never zero-filled. */
13574
+ points: array(LoadPointSchema).readonly()
13575
+ });
13576
+ var NodeLoadSeriesSchema = object({
13577
+ nodeId: string(),
13578
+ /** One entry per function seen in the window, heaviest-first. */
13579
+ series: array(LoadFunctionSeriesSchema).readonly(),
13580
+ /**
13581
+ * Width of one returned bucket, in ms. Equals the sampling cadence when no
13582
+ * reduction was needed — so a caller can always say what one point covers
13583
+ * without having to know whether it was reduced.
13584
+ */
13585
+ bucketMs: number(),
13586
+ /** Raw snapshots that went into this answer, across both tiers. */
13587
+ retainedSamples: number(),
13588
+ /** Oldest snapshot represented, or `null` when nothing is retained. */
13589
+ oldestAtMs: number().nullable(),
13590
+ /** The fixed sampling cadence in force on the cluster, in ms. */
13591
+ cadenceMs: number(),
13592
+ /**
13593
+ * Did the DURABLE tier contribute? `false` means the answer is the hot ring
13594
+ * alone — an agent (which holds no table), or a store that refused.
13595
+ * Reported because "the last hour" and "the last six hours" are different
13596
+ * questions and an operator must not have to guess which was answered.
13597
+ */
13598
+ durable: boolean()
13599
+ });
13600
+ var GetLoadSeriesInputSchema = object({
13601
+ /**
13602
+ * The node whose series is wanted.
13603
+ *
13604
+ * NOT named `nodeId`: the generated cap router strips a top-level
13605
+ * `nodeId` from every method input and uses it to ROUTE the call to
13606
+ * that node's provider (`generated-cap-routers.ts`). A series target
13607
+ * called `nodeId` would silently become a routing pin and never reach
13608
+ * the provider. The hub holds every node it hears from, so the
13609
+ * ordinary call is unpinned — answered by the hub, for any node.
13610
+ */
13611
+ forNodeId: string(),
13612
+ /**
13613
+ * EXCLUSIVE lower bound. A caller passes the newest `atMs` it already
13614
+ * holds and receives only what it is missing, so seeding a live chart
13615
+ * from this method cannot double a point already drawn.
13616
+ */
13617
+ sinceMs: number().optional(),
13618
+ /**
13619
+ * Most points the caller wants PER FUNCTION. The window is reduced to fit,
13620
+ * preserving min and max per bucket.
13621
+ *
13622
+ * Absent means NO reduction — legitimate for a short window and a trap for a
13623
+ * long one, which is why a chart passes its own pixel width.
13624
+ */
13625
+ maxPoints: number().int().positive().optional()
13626
+ });
13427
13627
  var SystemMetricsSchema = object({
13428
13628
  cpuPercent: number(),
13429
13629
  memoryPercent: number(),
@@ -13434,10 +13634,7 @@ var SystemMetricsSchema = object({
13434
13634
  gpuPercent: number().optional(),
13435
13635
  gpuMemoryPercent: number().optional()
13436
13636
  });
13437
- 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, {
13438
- kind: "mutation",
13439
- auth: "admin"
13440
- }), method(DumpHeapSnapshotInputSchema, DumpHeapSnapshotResultSchema, {
13637
+ 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, {
13441
13638
  kind: "mutation",
13442
13639
  auth: "admin"
13443
13640
  });
@@ -26740,6 +26937,15 @@ var LoggingSettingsPatchSchema = object({
26740
26937
  * authority over the whole hierarchy and answers for every layer, so the
26741
26938
  * layer selector needs a name the transport does not already own.
26742
26939
  */
26940
+ /**
26941
+ * One contribution, plus WHO reported it.
26942
+ *
26943
+ * The addon and node are added by the hub as it enumerates providers, never by
26944
+ * the contributor: an addon reporting its own identity could report somebody
26945
+ * else's, and the whole point of this surface is that no claim is made by
26946
+ * anyone but its owner.
26947
+ */
26948
+ var ReportedLoadContributionSchema = LoadContributionSchema.extend({ addonId: string() });
26743
26949
  var GetLoggingSettingsInputSchema = object({
26744
26950
  scopeNodeId: string().optional(),
26745
26951
  /**
@@ -26798,7 +27004,7 @@ method(_void(), FeatureManifestSchema), method(_void(), HealthStatusSchema), met
26798
27004
  }), method(_void(), SiteLocationStatusSchema, {
26799
27005
  kind: "mutation",
26800
27006
  auth: "admin"
26801
- }), method(_void(), RequestCensusStatusSchema, { auth: "admin" }), method(GetLoggingSettingsInputSchema, LoggingSettingsStateSchema, { auth: "admin" }), method(SetLoggingSettingsInputSchema, LoggingSettingsStateSchema, {
27007
+ }), method(_void(), RequestCensusStatusSchema, { auth: "admin" }), method(_void(), array(ReportedLoadContributionSchema).readonly(), { auth: "admin" }), method(GetLoggingSettingsInputSchema, LoggingSettingsStateSchema, { auth: "admin" }), method(SetLoggingSettingsInputSchema, LoggingSettingsStateSchema, {
26802
27008
  kind: "mutation",
26803
27009
  auth: "admin"
26804
27010
  });
@@ -28414,6 +28620,12 @@ Object.freeze({
28414
28620
  addonId: null,
28415
28621
  access: "create"
28416
28622
  },
28623
+ "dataStoreProvider.insertMany": {
28624
+ capName: "data-store-provider",
28625
+ capScope: "system",
28626
+ addonId: null,
28627
+ access: "create"
28628
+ },
28417
28629
  "dataStoreProvider.isEmpty": {
28418
28630
  capName: "data-store-provider",
28419
28631
  capScope: "system",
@@ -29728,6 +29940,12 @@ Object.freeze({
29728
29940
  addonId: null,
29729
29941
  access: "create"
29730
29942
  },
29943
+ "loadContribution.list": {
29944
+ capName: "load-contribution",
29945
+ capScope: "system",
29946
+ addonId: null,
29947
+ access: "view"
29948
+ },
29731
29949
  "localNetwork.downloadCa": {
29732
29950
  capName: "local-network",
29733
29951
  capScope: "system",
@@ -30028,17 +30246,17 @@ Object.freeze({
30028
30246
  addonId: null,
30029
30247
  access: "view"
30030
30248
  },
30031
- "metricsProvider.getProcessStats": {
30249
+ "metricsProvider.getLoadSeries": {
30032
30250
  capName: "metrics-provider",
30033
30251
  capScope: "system",
30034
30252
  addonId: null,
30035
30253
  access: "view"
30036
30254
  },
30037
- "metricsProvider.killProcess": {
30255
+ "metricsProvider.getProcessStats": {
30038
30256
  capName: "metrics-provider",
30039
30257
  capScope: "system",
30040
30258
  addonId: null,
30041
- access: "create"
30259
+ access: "view"
30042
30260
  },
30043
30261
  "metricsProvider.listAddonInstances": {
30044
30262
  capName: "metrics-provider",
@@ -32050,6 +32268,12 @@ Object.freeze({
32050
32268
  addonId: null,
32051
32269
  access: "create"
32052
32270
  },
32271
+ "settingsStore.insertMany": {
32272
+ capName: "settings-store",
32273
+ capScope: "system",
32274
+ addonId: null,
32275
+ access: "create"
32276
+ },
32053
32277
  "settingsStore.isEmpty": {
32054
32278
  capName: "settings-store",
32055
32279
  capScope: "system",
@@ -32662,6 +32886,12 @@ Object.freeze({
32662
32886
  addonId: null,
32663
32887
  access: "create"
32664
32888
  },
32889
+ "system.getLoadContributions": {
32890
+ capName: "system",
32891
+ capScope: "system",
32892
+ addonId: null,
32893
+ access: "view"
32894
+ },
32665
32895
  "system.getLoggingSettings": {
32666
32896
  capName: "system",
32667
32897
  capScope: "system",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-decoder-nodeav",
3
- "version": "1.2.34",
3
+ "version": "1.2.36",
4
4
  "description": "Standalone in-process node-av decoder addon for CamStack",
5
5
  "keywords": [
6
6
  "camstack",
@@ -39,7 +39,8 @@
39
39
  "entry": "./dist/index.js",
40
40
  "execution": {
41
41
  "placement": "any-node",
42
- "heapProfile": "heavy"
42
+ "heapProfile": "heavy",
43
+ "rssBudgetMb": 1536
43
44
  },
44
45
  "capabilities": [
45
46
  {