@camstack/system 1.2.456 → 1.2.458

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 (123) hide show
  1. package/dist/addon-runner.js +259 -37
  2. package/dist/addon-runner.mjs +289 -67
  3. package/dist/{agent-https-fm4AR8XL.mjs → agent-https-CQA3W-3e.mjs} +2 -2
  4. package/dist/{agent-https-yjxdfJDA.js → agent-https-DOELEug8.js} +2 -2
  5. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  6. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  7. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  8. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  9. package/dist/builtins/alerts/alerts.addon.js +2 -2
  10. package/dist/builtins/alerts/alerts.addon.mjs +2 -2
  11. package/dist/builtins/autotrack/index.js +1 -1
  12. package/dist/builtins/autotrack/index.mjs +1 -1
  13. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +2 -2
  14. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +2 -2
  15. package/dist/builtins/calendars/calendars.addon.js +1 -1
  16. package/dist/builtins/calendars/calendars.addon.mjs +1 -1
  17. package/dist/builtins/camera-grid/index.js +1 -1
  18. package/dist/builtins/camera-grid/index.mjs +1 -1
  19. package/dist/builtins/composer/composer.addon.js +2 -2
  20. package/dist/builtins/composer/composer.addon.mjs +2 -2
  21. package/dist/builtins/console-logging/console-destination.d.ts +1 -2
  22. package/dist/builtins/console-logging/index.js +1 -4
  23. package/dist/builtins/console-logging/index.mjs +1 -4
  24. package/dist/builtins/core-blocks/core-blocks.addon.js +2 -2
  25. package/dist/builtins/core-blocks/core-blocks.addon.mjs +2 -2
  26. package/dist/builtins/device-history/capture/capture-engine.d.ts +6 -0
  27. package/dist/builtins/device-history/device-history.addon.d.ts +13 -0
  28. package/dist/builtins/device-history/device-history.addon.js +736 -315
  29. package/dist/builtins/device-history/device-history.addon.mjs +736 -315
  30. package/dist/builtins/device-history/ingest/producer-ingest.d.ts +11 -1
  31. package/dist/builtins/device-history/query/history-query.d.ts +35 -9
  32. package/dist/builtins/device-history/query/point-shape.d.ts +33 -0
  33. package/dist/builtins/device-history/retention/retention.d.ts +1 -1
  34. package/dist/builtins/device-history/rollup/rollup-engine.d.ts +2 -0
  35. package/dist/builtins/device-history/rollup/rollup-math.d.ts +6 -0
  36. package/dist/builtins/device-history/store/history-store.d.ts +7 -0
  37. package/dist/builtins/device-history/store/series-registry.d.ts +26 -1
  38. package/dist/builtins/device-manager/device-manager.addon.js +1 -1
  39. package/dist/builtins/device-manager/device-manager.addon.mjs +1 -1
  40. package/dist/builtins/hub-forwarder/hub-forwarder-destination.d.ts +1 -2
  41. package/dist/builtins/hub-forwarder/index.js +1 -4
  42. package/dist/builtins/hub-forwarder/index.mjs +1 -4
  43. package/dist/builtins/keychain/index.js +4 -4
  44. package/dist/builtins/keychain/index.mjs +4 -4
  45. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  46. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  47. package/dist/builtins/local-auth/local-auth.addon.js +3 -3
  48. package/dist/builtins/local-auth/local-auth.addon.mjs +3 -3
  49. package/dist/builtins/local-network/local-network.addon.js +2 -2
  50. package/dist/builtins/local-network/local-network.addon.mjs +2 -2
  51. package/dist/builtins/loki-logging/index.js +323 -7
  52. package/dist/builtins/loki-logging/index.mjs +323 -7
  53. package/dist/builtins/loki-logging/loki-destination.d.ts +20 -3
  54. package/dist/builtins/loki-logging/loki-read.d.ts +51 -0
  55. package/dist/builtins/native-metrics/native-metrics.addon.js +290 -112
  56. package/dist/builtins/native-metrics/native-metrics.addon.mjs +290 -112
  57. package/dist/builtins/native-metrics/node-metrics-history-recorder.d.ts +106 -35
  58. package/dist/builtins/platform-probe/coral-accelerators.d.ts +26 -9
  59. package/dist/builtins/platform-probe/index.js +11 -68
  60. package/dist/builtins/platform-probe/index.mjs +11 -68
  61. package/dist/builtins/record-entries/index.js +1 -1
  62. package/dist/builtins/record-entries/index.mjs +1 -1
  63. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  64. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  65. package/dist/builtins/snapshot/index.js +1 -1
  66. package/dist/builtins/snapshot/index.mjs +1 -1
  67. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  68. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  69. package/dist/builtins/sqlite-storage/index.js +1 -1
  70. package/dist/builtins/sqlite-storage/index.mjs +1 -1
  71. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +2 -2
  72. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +2 -2
  73. package/dist/builtins/storage-orchestrator/location-history-recorder.d.ts +76 -0
  74. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.d.ts +9 -0
  75. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +144 -1
  76. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +144 -1
  77. package/dist/builtins/system-config/system-config.addon.js +3 -3
  78. package/dist/builtins/system-config/system-config.addon.mjs +3 -3
  79. package/dist/builtins/winston-logging/index.js +165 -3
  80. package/dist/builtins/winston-logging/index.mjs +165 -3
  81. package/dist/builtins/winston-logging/log-file-cursor.d.ts +12 -0
  82. package/dist/builtins/winston-logging/log-file-index-store.d.ts +11 -0
  83. package/dist/builtins/winston-logging/log-file-index.d.ts +77 -0
  84. package/dist/builtins/winston-logging/log-file-read-client.d.ts +44 -0
  85. package/dist/builtins/winston-logging/log-file-read-protocol.d.ts +41 -0
  86. package/dist/builtins/winston-logging/log-file-read-worker.d.ts +1 -0
  87. package/dist/builtins/winston-logging/log-file-reader.d.ts +51 -0
  88. package/dist/builtins/winston-logging/winston-destination.d.ts +20 -2
  89. package/dist/{composition-sources-Ds0Vr6eD.mjs → composition-sources-BVguN7VV.mjs} +1 -1
  90. package/dist/{composition-sources-gB4coDJR.js → composition-sources-DURQNDJ4.js} +1 -1
  91. package/dist/{constants-i5oD_gLB.mjs → constants-FGjnsE2x.mjs} +1 -1
  92. package/dist/{constants-CavyKfHZ.js → constants-Njka8Cv6.js} +1 -1
  93. package/dist/coral-accelerators-Bi_c3Rft.js +175 -0
  94. package/dist/coral-accelerators-DcnZvctM.mjs +162 -0
  95. package/dist/{device-ca-bpoEr0zG.js → device-ca-BrVK_5s3.js} +1 -1
  96. package/dist/{device-ca-qz1Pmeu1.mjs → device-ca-lEaAQ9Xi.mjs} +1 -1
  97. package/dist/{dist-BpqA2CT0.js → dist-BZQjLPiz.js} +526 -57
  98. package/dist/{dist-BSF_C8W2.mjs → dist-B_GRPhnY.mjs} +509 -58
  99. package/dist/file-host-worker.js +1 -1
  100. package/dist/file-host-worker.mjs +1 -1
  101. package/dist/{hub-mdns-ciao-CHaGDzyz.mjs → hub-mdns-ciao-Bg2HfTwP.mjs} +2 -2
  102. package/dist/{hub-mdns-ciao-CZlZRxxA.js → hub-mdns-ciao-nce3TXs_.js} +2 -2
  103. package/dist/index.d.ts +1 -0
  104. package/dist/index.js +140 -48
  105. package/dist/index.mjs +134 -49
  106. package/dist/kernel/config-schema.d.ts +5 -0
  107. package/dist/kernel/hwaccel/hwaccel-resolver.d.ts +7 -3
  108. package/dist/kernel/moleculer/accessory-prune-gate.d.ts +55 -0
  109. package/dist/log-file-read-protocol-B7M3X3bT.mjs +785 -0
  110. package/dist/log-file-read-protocol-D0WcLbIV.js +817 -0
  111. package/dist/log-file-read-worker.js +64 -0
  112. package/dist/log-file-read-worker.mjs +64 -0
  113. package/dist/log-read-filter-Bi066jwU.js +134 -0
  114. package/dist/log-read-filter-D7Ev3zm-.mjs +93 -0
  115. package/dist/logging/log-manager.d.ts +10 -6
  116. package/dist/logging/log-read-filter.d.ts +43 -0
  117. package/dist/{phase6-declare-gate-n-IZRklX.js → phase6-declare-gate-Dag1_WR2.js} +1 -1
  118. package/dist/{phase6-declare-gate-B4yfsf2n.mjs → phase6-declare-gate-Lb-mrVvz.mjs} +1 -1
  119. package/dist/{restore-archive-BGUM4FKf.mjs → restore-archive-C7kLDI_0.mjs} +1 -1
  120. package/dist/{restore-archive-B4QG7XmX.js → restore-archive-FyfZ8YMC.js} +1 -1
  121. package/dist/{wal-maintenance-CNEs_I94.js → wal-maintenance-DfSIOj24.js} +0 -0
  122. package/dist/{wal-maintenance-AerF4XE6.mjs → wal-maintenance-Duejh7Lx.mjs} +0 -0
  123. package/package.json +1 -1
@@ -745,7 +745,7 @@ var EventCategory = /* @__PURE__ */ function(EventCategory) {
745
745
  return EventCategory;
746
746
  }({});
747
747
  //#endregion
748
- //#region ../types/dist/sleep-yKL5gfrH.mjs
748
+ //#region ../types/dist/sleep-BSuCCFjf.mjs
749
749
  /**
750
750
  * The audio chunk plane's byte format, and the ONE expansion from a coded
751
751
  * window to float samples (D455).
@@ -17748,11 +17748,30 @@ var DeviceHistorySubjectSchema = zod.z.discriminatedUnion("kind", [zod.z.object(
17748
17748
  kind: zod.z.literal("node"),
17749
17749
  nodeId: zod.z.string().min(1)
17750
17750
  })]);
17751
+ /**
17752
+ * `enum` stores a STATE as the ordinal of its value in the series' value list
17753
+ * (`DeviceHistorySeriesInfo.values`, append-only, so an ordinal never changes
17754
+ * meaning); a rollup keeps the time spent in each state (`states`).
17755
+ */
17751
17756
  var DeviceHistoryKindSchema = zod.z.enum([
17757
+ "gauge",
17758
+ "counter",
17759
+ "boolean",
17760
+ "enum"
17761
+ ]);
17762
+ /** What a PRODUCER may declare. `enum` is cap-only: its value list is the cap field's. */
17763
+ var DeviceHistoryProducerKindSchema = zod.z.enum([
17752
17764
  "gauge",
17753
17765
  "counter",
17754
17766
  "boolean"
17755
17767
  ]);
17768
+ /**
17769
+ * A key computed at READ time from stored series of the same device, never
17770
+ * stored itself. Energy (kWh per bucket) comes from the power meter's
17771
+ * `kwhTotal` counter when the device has one, else from integrating its
17772
+ * `watts` gauge over time.
17773
+ */
17774
+ var DEVICE_HISTORY_ENERGY_KEY = "derived:energy.kwh";
17756
17775
  var DeviceHistoryResolutionSchema = zod.z.enum([
17757
17776
  "raw",
17758
17777
  "5m",
@@ -17785,7 +17804,13 @@ var SeriesInfoSchema = zod.z.object({
17785
17804
  /** `null` is unknown (a `unitFrom` series whose device does not state a unit right now), never a guess. */
17786
17805
  unit: zod.z.string().nullable(),
17787
17806
  displayName: zod.z.string(),
17788
- source: zod.z.enum(["cap", "addon"]),
17807
+ source: zod.z.enum([
17808
+ "cap",
17809
+ "addon",
17810
+ "derived"
17811
+ ]),
17812
+ /** `enum`: the value of each ordinal (index = ordinal); `null` for every other kind. */
17813
+ values: zod.z.array(zod.z.string()).readonly().nullable(),
17789
17814
  firstTs: zod.z.number(),
17790
17815
  lastTs: zod.z.number()
17791
17816
  });
@@ -17799,17 +17824,31 @@ var QueryPointSchema = zod.z.object({
17799
17824
  twMean: zod.z.number().nullable(),
17800
17825
  min: zod.z.number(),
17801
17826
  max: zod.z.number(),
17802
- /** `null` is unknown, never zero (D393). */
17803
- last: zod.z.number().nullable()
17827
+ /** `null` is unknown, never zero (D393). For an `enum` series: the ordinal of {@link state}. */
17828
+ last: zod.z.number().nullable(),
17829
+ /**
17830
+ * The increase over the point: a `counter`'s growth since the previous point
17831
+ * or bucket (a drop is a reset, counted from zero), and for
17832
+ * {@link DEVICE_HISTORY_ENERGY_KEY} the kWh used in the bucket. `null` for
17833
+ * every other kind, and when it cannot be known.
17834
+ */
17835
+ delta: zod.z.number().nullable(),
17836
+ /** `enum`: the state in force at the end of the point (the name of `last`); `null` otherwise. */
17837
+ state: zod.z.string().nullable(),
17838
+ /** `enum` rollup: milliseconds spent in each state inside the bucket; `null` for raw points and other kinds. */
17839
+ states: zod.z.record(zod.z.string(), zod.z.number()).nullable()
17804
17840
  });
17805
17841
  var QuerySeriesSchema = zod.z.object({
17806
17842
  scope: zod.z.string(),
17807
17843
  /** The last point STRICTLY BEFORE `from` in the chosen tier, so a step chart can start at the held value. */
17808
17844
  before: zod.z.object({
17809
17845
  t: zod.z.number(),
17810
- value: zod.z.number().nullable()
17846
+ value: zod.z.number().nullable(),
17847
+ state: zod.z.string().nullable()
17811
17848
  }).nullable(),
17812
- points: zod.z.array(QueryPointSchema).readonly()
17849
+ points: zod.z.array(QueryPointSchema).readonly(),
17850
+ /** A derived key: the stored key its points were computed from; `null` for a stored series. */
17851
+ derivedFrom: zod.z.string().nullable()
17813
17852
  });
17814
17853
  /** The window part of a query, shared by the device and node forms. */
17815
17854
  var QueryWindowShape = {
@@ -17825,6 +17864,23 @@ var QueryResultSchema = zod.z.object({
17825
17864
  series: zod.z.array(QuerySeriesSchema).readonly(),
17826
17865
  truncated: zod.z.boolean()
17827
17866
  });
17867
+ /** One read of a batch: a device's key or a node's key (exactly one subject). */
17868
+ var QueryManyItemSchema = zod.z.union([zod.z.object({
17869
+ deviceId: zod.z.number().int(),
17870
+ key: zod.z.string(),
17871
+ scope: zod.z.string().optional()
17872
+ }), zod.z.object({
17873
+ forNodeId: zod.z.string().min(1),
17874
+ key: zod.z.string(),
17875
+ scope: zod.z.string().optional()
17876
+ })]);
17877
+ var QueryManyEntrySchema = zod.z.discriminatedUnion("ok", [zod.z.object({
17878
+ ok: zod.z.literal(true),
17879
+ result: QueryResultSchema
17880
+ }), zod.z.object({
17881
+ ok: zod.z.literal(false),
17882
+ error: zod.z.string()
17883
+ })]);
17828
17884
  var TierStatusSchema = zod.z.object({
17829
17885
  tier: DeviceHistoryResolutionSchema,
17830
17886
  /** `null` until the first background count answered. */
@@ -17893,26 +17949,45 @@ var deviceHistoryCapability = {
17893
17949
  * `listNodeSeries` / `queryNode`.
17894
17950
  */
17895
17951
  listSeries: method(zod.z.object({ deviceId: zod.z.number().int() }), zod.z.array(SeriesInfoSchema).readonly()),
17896
- listNodeSeries: method(zod.z.object({ nodeId: zod.z.string().min(1) }), zod.z.array(SeriesInfoSchema).readonly(), { auth: "admin" }),
17952
+ /**
17953
+ * A NODE's series. The subject is `forNodeId`, never `nodeId`: a top-level
17954
+ * `nodeId` is the cap ROUTING key, and `nodeId: 'little-unraid'` sent the
17955
+ * read to that agent, which hosts no device-history.
17956
+ */
17957
+ listNodeSeries: method(zod.z.object({ forNodeId: zod.z.string().min(1) }), zod.z.array(SeriesInfoSchema).readonly(), { auth: "admin" }),
17897
17958
  /**
17898
17959
  * One series (or every scope of it) at one resolution. `auto` picks the
17899
17960
  * finest tier whose retention covers `from` and whose point count fits
17900
17961
  * `maxPoints`; when even the coarsest tier does not fit, the newest
17901
- * `maxPoints` points are returned and `truncated` is true.
17962
+ * `maxPoints` points are returned and `truncated` is true. A series fed by
17963
+ * closed buckets has no raw rows, so `auto` never answers it from raw; nor
17964
+ * {@link DEVICE_HISTORY_ENERGY_KEY}, which is computed from rollups.
17902
17965
  */
17903
17966
  query: method(zod.z.object({
17904
17967
  deviceId: zod.z.number().int(),
17905
17968
  ...QueryWindowShape
17906
17969
  }), QueryResultSchema),
17907
17970
  queryNode: method(zod.z.object({
17908
- nodeId: zod.z.string().min(1),
17971
+ forNodeId: zod.z.string().min(1),
17909
17972
  ...QueryWindowShape
17910
17973
  }), QueryResultSchema, { auth: "admin" }),
17974
+ /**
17975
+ * Several reads over ONE window, answered in order (one entry per item).
17976
+ * Admin-only: its subjects are nested in `items`, where the device scope
17977
+ * gate cannot see them — a principal limited to one device uses `query`.
17978
+ */
17979
+ queryMany: method(zod.z.object({
17980
+ items: zod.z.array(QueryManyItemSchema).min(1).max(24),
17981
+ from: QueryWindowShape.from,
17982
+ to: QueryWindowShape.to,
17983
+ resolution: QueryWindowShape.resolution,
17984
+ maxPoints: QueryWindowShape.maxPoints
17985
+ }), zod.z.object({ results: zod.z.array(QueryManyEntrySchema).readonly() }), { auth: "admin" }),
17911
17986
  /** Producer: declare (idempotent) a series key this addon owns: `addon:<callerAddonId>/<name>`. */
17912
17987
  declareSeries: method(zod.z.object({
17913
17988
  name: zod.z.string().regex(/^[a-z0-9-]+$/),
17914
17989
  subjectKind: zod.z.enum(["device", "node"]),
17915
- kind: DeviceHistoryKindSchema,
17990
+ kind: DeviceHistoryProducerKindSchema,
17916
17991
  unit: zod.z.string().optional(),
17917
17992
  displayName: zod.z.string().min(1),
17918
17993
  ingest: zod.z.enum(["points", "buckets"])
@@ -42839,6 +42914,103 @@ var LogEntrySchema = zod.z.object({
42839
42914
  meta: zod.z.record(zod.z.string(), zod.z.unknown()).optional(),
42840
42915
  tags: zod.z.record(zod.z.string(), zod.z.string()).optional()
42841
42916
  });
42917
+ /**
42918
+ * A history READ against one destination (D898).
42919
+ *
42920
+ * Every filter is applied by the PROVIDER, before the limit — a filter the
42921
+ * browser applied after the limit is what made a rare device's lines
42922
+ * unreachable behind a busy one's. `before` / `after` are cursors the provider
42923
+ * minted (opaque to everyone else): a file position for the rotated files, a
42924
+ * nanosecond timestamp for Loki.
42925
+ *
42926
+ * A read is BOUNDED by `budgetMs`: a filter that matches nothing on a 30-day
42927
+ * store answers `done: false` with the cursor it reached and the bytes it
42928
+ * scanned, and the caller decides whether to go on. That is what makes a long
42929
+ * scan show progress and stop when asked — `cancelRead` ends the slice in
42930
+ * flight, and not asking for the next slice ends the scan.
42931
+ */
42932
+ var LogReadQuerySchema = zod.z.object({
42933
+ /** Correlates `cancelRead`. Caller-chosen, unique per in-flight read. */
42934
+ requestId: zod.z.string().min(1).max(64).optional(),
42935
+ /** The device the line is about (`tags.deviceId`, numeric). */
42936
+ deviceId: zod.z.number().int().optional(),
42937
+ /**
42938
+ * The emitting addon — bare manifest id; `@<version>` / `::<sub>` suffixes
42939
+ * match. Not `addonId`: a cap router reads that name as "which provider".
42940
+ */
42941
+ fromAddonId: zod.z.string().min(1).max(200).optional(),
42942
+ /**
42943
+ * The emitting node: matches the agent that emitted the line, the node
42944
+ * itself, or a worker under it (`<agent>/<runner>`) — the `agentId`
42945
+ * semantics of `matchesLogTags`. Not `nodeId`: a cap router reads that
42946
+ * name as "which node's provider".
42947
+ */
42948
+ fromNodeId: zod.z.string().min(1).max(200).optional(),
42949
+ /** Any other tag, exact match (AND). */
42950
+ tags: zod.z.record(zod.z.string(), zod.z.union([zod.z.string(), zod.z.number()])).optional(),
42951
+ /** Severity FLOOR: this level and above. */
42952
+ level: LogLevelSchema.optional(),
42953
+ /** Case-insensitive substring over message, scope, tag values and meta values. */
42954
+ text: zod.z.string().min(1).max(200).optional(),
42955
+ /** Epoch ms, inclusive. */
42956
+ since: zod.z.number().optional(),
42957
+ /** Epoch ms, inclusive. */
42958
+ until: zod.z.number().optional(),
42959
+ /** Older than this cursor (exclusive). Absent with `after` absent ⇒ from the newest. */
42960
+ before: zod.z.string().min(1).max(1024).optional(),
42961
+ /** Newer than this cursor (exclusive). */
42962
+ after: zod.z.string().min(1).max(1024).optional(),
42963
+ limit: zod.z.number().int().min(1).max(1e3).optional(),
42964
+ /** Wall-clock bound of this slice. The provider caps it. */
42965
+ budgetMs: zod.z.number().int().min(50).max(1e4).optional()
42966
+ });
42967
+ var LogReadEntrySchema = zod.z.object({
42968
+ /** `<bootId>.<seq>` minted by the emitting LogManager — the dedupe key. */
42969
+ id: zod.z.string().optional(),
42970
+ /** Epoch ms. */
42971
+ timestamp: zod.z.number(),
42972
+ level: LogLevelSchema,
42973
+ scope: zod.z.string().optional(),
42974
+ message: zod.z.string(),
42975
+ tags: zod.z.record(zod.z.string(), zod.z.union([zod.z.string(), zod.z.number()])).optional(),
42976
+ meta: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
42977
+ });
42978
+ var LogReadResultSchema = zod.z.object({
42979
+ /** Newest first. */
42980
+ entries: zod.z.array(LogReadEntrySchema),
42981
+ /** Pass as `before` for the next older page; null when nothing older exists. */
42982
+ nextBefore: zod.z.string().nullable(),
42983
+ /** Pass as `after` to read what arrived since; null when unknown. */
42984
+ nextAfter: zod.z.string().nullable(),
42985
+ /** Bytes this slice read (files) or received (remote). Progress, not a promise. */
42986
+ scannedBytes: zod.z.number().int().nonnegative(),
42987
+ /**
42988
+ * True when the scan in this direction reached the end of the store.
42989
+ * False with fewer than `limit` entries means the budget ran out first —
42990
+ * call again with `nextBefore` to go on.
42991
+ */
42992
+ done: zod.z.boolean(),
42993
+ /** True when `cancelRead` ended this slice early. */
42994
+ cancelled: zod.z.boolean().optional()
42995
+ });
42996
+ var LogReadCapabilitiesSchema = zod.z.object({
42997
+ /** False ⇒ this destination only ships lines (console, forwarder, an unconfigured Loki). */
42998
+ readable: zod.z.boolean(),
42999
+ /** Why not, when `readable` is false — rendered next to the source. */
43000
+ reason: zod.z.string().nullable(),
43001
+ /** Filters the provider applies itself. A false one is applied by nobody. */
43002
+ filters: zod.z.object({
43003
+ deviceId: zod.z.boolean(),
43004
+ addonId: zod.z.boolean(),
43005
+ nodeId: zod.z.boolean(),
43006
+ tags: zod.z.boolean(),
43007
+ level: zod.z.boolean(),
43008
+ text: zod.z.boolean(),
43009
+ timeRange: zod.z.boolean()
43010
+ }),
43011
+ /** How far back the store reaches, when the provider knows (days). */
43012
+ retentionDays: zod.z.number().nullable()
43013
+ });
42842
43014
  var logDestinationCapability = {
42843
43015
  name: "log-destination",
42844
43016
  scope: "system",
@@ -42846,14 +43018,13 @@ var logDestinationCapability = {
42846
43018
  internal: true,
42847
43019
  methods: {
42848
43020
  write: method(LogEntrySchema, zod.z.void(), { kind: "mutation" }),
42849
- query: method(zod.z.object({
42850
- scope: zod.z.array(zod.z.string()).optional(),
42851
- level: LogLevelSchema.optional(),
42852
- since: zod.z.date().optional(),
42853
- until: zod.z.date().optional(),
42854
- limit: zod.z.number().optional(),
42855
- tags: zod.z.record(zod.z.string(), zod.z.string()).optional()
42856
- }), zod.z.array(LogEntrySchema).readonly())
43021
+ /** Absent ⇒ the destination cannot read back (same as `readable: false`). */
43022
+ describeRead: optionalMethod(zod.z.void(), LogReadCapabilitiesSchema, { auth: "admin" }),
43023
+ read: optionalMethod(LogReadQuerySchema, LogReadResultSchema, { auth: "admin" }),
43024
+ cancelRead: optionalMethod(zod.z.object({ requestId: zod.z.string().min(1).max(64) }), zod.z.object({ cancelled: zod.z.boolean() }), {
43025
+ kind: "mutation",
43026
+ auth: "admin"
43027
+ })
42857
43028
  },
42858
43029
  /** BIG PLAN 2: declarative mount hint — read by `@camstack/system` `buildCapRouters`. */
42859
43030
  mount: { kind: "skip" }
@@ -44763,9 +44934,11 @@ var alarmPanelCapability = {
44763
44934
  */
44764
44935
  durability: "restored",
44765
44936
  /**
44766
- * History (D850): none — enum state; arm/disarm history belongs in the events ledger.
44937
+ * History (D850): the panel's lifecycle state as an `enum` series —
44938
+ * change-only, no floor, so an `arming -> pending -> triggered` sequence of a
44939
+ * few seconds keeps every step. Who armed it stays in the events ledger.
44767
44940
  */
44768
- history: "none",
44941
+ history: { fields: { state: { kind: "enum" } } },
44769
44942
  /** Clock fields: written, but excluded from the compare that decides
44770
44943
  * whether persisting is worth a SQLite commit. */
44771
44944
  volatileStateFields: ["lastChangedAt"]
@@ -45656,6 +45829,33 @@ var NcRuleTargetSchema = zod.z.object({
45656
45829
  params: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
45657
45830
  });
45658
45831
  /**
45832
+ * WHAT THE NOTIFICATION'S PICTURE IS (D897) — the ONE media choice of a rule.
45833
+ *
45834
+ * Every mode starts from the same CLEAN source frame of the trigger moment
45835
+ * (keyFrame → sceneFrame → lastSceneFrame, narrowed to the trigger instant and
45836
+ * to the zone that fired the rule) and renders it once at send time:
45837
+ * - `scene-boxes` — the whole scene, the subject outlined thick in the accent
45838
+ * colour and every OTHER track visible at that instant outlined thin, each
45839
+ * labelled with class and confidence ("dog 87%").
45840
+ * - `crop` — the subject cut out of that frame around its box at that instant.
45841
+ * - `clean` — the whole scene with nothing drawn on it.
45842
+ * - `none` — no picture.
45843
+ *
45844
+ * A mode that cannot be honoured (no box at that instant, a photograph with no
45845
+ * tracked subject) ships `clean` and names the reason in the log, per camera.
45846
+ * It replaces the `attach` × `frame` × `zoneCrop` triple, which let one rule
45847
+ * ship a crop on one event and a boxed scene on the next depending on which
45848
+ * stored kind had landed.
45849
+ */
45850
+ var NcMediaImageSchema = zod.z.enum([
45851
+ "scene-boxes",
45852
+ "crop",
45853
+ "clean",
45854
+ "none"
45855
+ ]);
45856
+ /**
45857
+ * @deprecated Read only by `normalizeNcMediaPolicy` (D897) — see {@link NcMediaImageSchema}.
45858
+ *
45659
45859
  * Media attachment policy (P1 still-image subset).
45660
45860
  * - `best` — the best AVAILABLE subject image at dispatch time (D-3).
45661
45861
  * - `best-matching` — the media that explains WHY the rule fired: a rule
@@ -45669,6 +45869,8 @@ var NcRuleTargetSchema = zod.z.object({
45669
45869
  * - `none` — no attachment.
45670
45870
  */
45671
45871
  /**
45872
+ * @deprecated Read only by `normalizeNcMediaPolicy` (D897) — see {@link NcMediaImageSchema}.
45873
+ *
45672
45874
  * WHAT THE PICTURE SHOWS — chosen explicitly, because the implicit ladders
45673
45875
  * conflate it with the selection strategy and betray the request: asking for
45674
45876
  * the clean scene frame on an object-event owner used to start at
@@ -45697,16 +45899,29 @@ var NcMediaFrameSchema = zod.z.enum([
45697
45899
  */
45698
45900
  var NcLinkedCameraModeSchema = zod.z.enum(["mosaic", "each"]);
45699
45901
  var NcMediaPolicySchema = zod.z.object({
45902
+ /**
45903
+ * The picture — see {@link NcMediaImageSchema}. Absent on a rule nobody has
45904
+ * saved since D897: `normalizeNcMediaPolicy` derives it from the legacy
45905
+ * triple below, at load and at every write, and the store keeps only this.
45906
+ */
45907
+ image: NcMediaImageSchema.optional(),
45908
+ /**
45909
+ * Draw the zone that FIRED the rule on the picture (`scene-boxes` / `clean`;
45910
+ * a `crop` never shows it). Valid only on a rule whose trigger is a zone —
45911
+ * `conditions.zones` or an occupancy zone — and refused on save otherwise.
45912
+ * Replaces `zoneCrop`.
45913
+ */
45914
+ showTriggerZone: zod.z.boolean().optional(),
45915
+ /** @deprecated D897 — accepted from an editor that predates `image`, folded into it on save. */
45700
45916
  attach: zod.z.enum([
45701
45917
  "best",
45702
45918
  "best-matching",
45703
45919
  "keyFrame",
45704
45920
  "none"
45705
- ]).default("best"),
45706
- /** What the still shows. Absent = `cropped` (the historical `best` shape). */
45921
+ ]).optional(),
45922
+ /** @deprecated D897 — accepted from an editor that predates `image`, folded into it on save. */
45707
45923
  frame: NcMediaFrameSchema.optional(),
45708
- /** Crop the attached still to the rule's condition-zone bbox (padded) —
45709
- * "show me the ZONE", not the whole scene or the subject crop. */
45924
+ /** @deprecated D897 — folded into `image: 'clean'` + `showTriggerZone` on save. */
45710
45925
  zoneCrop: zod.z.boolean().optional(),
45711
45926
  /**
45712
45927
  * Also attach a short GIF cut from the stream broker's clip ring around the
@@ -45878,7 +46093,9 @@ var NcRuleInputSchema = zod.z.object({
45878
46093
  * targets.
45879
46094
  */
45880
46095
  targetUsers: zod.z.array(zod.z.string()).optional(),
45881
- media: NcMediaPolicySchema.default({ attach: "best" }),
46096
+ /** Absent = the kind's default picture (`resolveNcMediaImage`): the subject crop for a
46097
+ * detection, the clean scene for a sensor or a sound. Set explicitly on save (D897). */
46098
+ media: NcMediaPolicySchema.default({}),
45882
46099
  throttle: NcThrottleSchema.default({
45883
46100
  cooldownSec: 60,
45884
46101
  scope: "rule-device"
@@ -46836,13 +47053,37 @@ var NcAlarmModeOpeningsSchema = zod.z.object({
46836
47053
  /** Covered devices whose state could not be read (D49): neither open nor closed. */
46837
47054
  unknown: zod.z.array(zod.z.number().int())
46838
47055
  });
47056
+ /**
47057
+ * One alarm INPUT — a (rule, device) pair — the operator bypassed until the
47058
+ * next disarm ("Bypass this input until disarm" on a trigger notification, or
47059
+ * `nc.bypassAlarmInput`). Reported so an armed alarm with a silenced input
47060
+ * never looks fully armed (D62: off must never look like broken).
47061
+ */
47062
+ var NcAlarmInputBypassViewSchema = zod.z.object({
47063
+ ruleId: zod.z.string(),
47064
+ /** The rule's current name (its frozen name when the rule is gone). */
47065
+ ruleName: zod.z.string(),
47066
+ /** The input: the sensor of the match, else its camera. */
47067
+ deviceId: zod.z.number().int(),
47068
+ /** The input's current name. */
47069
+ name: zod.z.string(),
47070
+ /** When it was bypassed (ms epoch). */
47071
+ since: zod.z.number(),
47072
+ /** Triggers from this input dropped since. */
47073
+ dropped: zod.z.number().int().min(0)
47074
+ });
46839
47075
  var NcAlarmLiveSchema = zod.z.object({
46840
47076
  state: AlarmStateSchema,
46841
47077
  /** The mode being armed into (exit delay) or held; null when disarmed. */
46842
47078
  targetMode: AlarmArmModeSchema.nullable(),
46843
47079
  availableModes: zod.z.array(AlarmArmModeSchema),
46844
47080
  openings: zod.z.array(NcAlarmModeOpeningsSchema),
46845
- exclusions: zod.z.array(NcAlarmExclusionViewSchema)
47081
+ exclusions: zod.z.array(NcAlarmExclusionViewSchema),
47082
+ /**
47083
+ * Inputs bypassed for the rest of this arm session; cleared on disarm.
47084
+ * Defaulted so an older hub answer still parses (as "none known").
47085
+ */
47086
+ bypassedInputs: zod.z.array(NcAlarmInputBypassViewSchema).default([])
46846
47087
  });
46847
47088
  var NcAlarmConfigSchema = zod.z.object({
46848
47089
  /**
@@ -60737,9 +60978,11 @@ var connectivityCapability = {
60737
60978
  */
60738
60979
  durability: "restored",
60739
60980
  /**
60740
- * History (D850): none — duplicates device-status.online (one authority for availability).
60981
+ * History (D850): `connected` as a boolean series — change-only, no floor. It
60982
+ * is the upstream entity's own link (a HA connectivity sensor), not the
60983
+ * device's reachability, which stays `device-status.online`.
60741
60984
  */
60742
- history: "none",
60985
+ history: { fields: { connected: { kind: "boolean" } } },
60743
60986
  /** Clock fields: written, but excluded from the compare that decides
60744
60987
  * whether persisting is worth a SQLite commit. */
60745
60988
  volatileStateFields: ["lastChangedAt"]
@@ -61609,11 +61852,22 @@ var dishwasherCapability = {
61609
61852
  },
61610
61853
  runtimeState: DishwasherStatusSchema,
61611
61854
  durability: "session",
61612
- history: { fields: { progressPercent: {
61613
- kind: "gauge",
61614
- unit: "%",
61615
- deadband: 2
61616
- } } }
61855
+ history: { fields: {
61856
+ progressPercent: {
61857
+ kind: "gauge",
61858
+ unit: "%",
61859
+ deadband: 2
61860
+ },
61861
+ state: { kind: "enum" },
61862
+ operationState: { kind: "enum" },
61863
+ remainingSeconds: {
61864
+ kind: "gauge",
61865
+ unit: "s",
61866
+ minIntervalMs: 6e4
61867
+ },
61868
+ doorOpen: { kind: "boolean" },
61869
+ powerOn: { kind: "boolean" }
61870
+ } }
61617
61871
  };
61618
61872
  var DoorbellStatusSchema = zod.z.object({
61619
61873
  /** Ms epoch of the last press. null = never observed since this provider started. */
@@ -61730,9 +61984,15 @@ var enumSensorCapability = {
61730
61984
  */
61731
61985
  durability: "restored",
61732
61986
  /**
61733
- * History (D850): none — text/enum state has no history (non-goal).
61987
+ * History (D850): the value as an `enum` series (an appliance's program or
61988
+ * operation state, an HVAC action). The option set is per device, so the
61989
+ * value list is LEARNED as values are first seen (bounded). A sensor with a
61990
+ * `format` carries a timestamp, not a state, and is not recorded.
61734
61991
  */
61735
- history: "none",
61992
+ history: { fields: { value: {
61993
+ kind: "enum",
61994
+ skipWhenSet: "format"
61995
+ } } },
61736
61996
  /** Clock fields: written, but excluded from the compare that decides
61737
61997
  * whether persisting is worth a SQLite commit. */
61738
61998
  volatileStateFields: ["lastFetchedAt"]
@@ -63954,9 +64214,10 @@ var lockControlCapability = {
63954
64214
  */
63955
64215
  durability: "restored",
63956
64216
  /**
63957
- * History (D850): none — enum state; lock events belong in the events ledger.
64217
+ * History (D850): the lock's state as an `enum` series — change-only, no
64218
+ * floor: a jam or an unlock lasting seconds is the edge an operator looks for.
63958
64219
  */
63959
- history: "none",
64220
+ history: { fields: { state: { kind: "enum" } } },
63960
64221
  /** Clock fields: written, but excluded from the compare that decides
63961
64222
  * whether persisting is worth a SQLite commit. */
63962
64223
  volatileStateFields: ["lastChangedAt"]
@@ -64130,9 +64391,18 @@ var mediaPlayerCapability = {
64130
64391
  */
64131
64392
  durability: "session",
64132
64393
  /**
64133
- * History (D850): none — `positionMs` moves continuously while playing; volume is transient.
64394
+ * History (D850): volume (a level an operator or an automation sets; the
64395
+ * default 10 s floor folds a slider drag into its end value) and mute.
64396
+ * `positionMs` is not recorded: it moves continuously while playing.
64134
64397
  */
64135
- history: "none"
64398
+ history: { fields: {
64399
+ volumeLevel: {
64400
+ kind: "gauge",
64401
+ unit: "%",
64402
+ deadband: 1
64403
+ },
64404
+ isMuted: { kind: "boolean" }
64405
+ } }
64136
64406
  };
64137
64407
  /**
64138
64408
  * mesh-network — collection cap for mesh-VPN providers.
@@ -66573,9 +66843,24 @@ var NpuInfoSchema = zod.z.object({
66573
66843
  name: zod.z.string().optional(),
66574
66844
  generation: zod.z.enum(["xdna1", "xdna2"]).optional()
66575
66845
  });
66846
+ var CoralBusSchema = zod.z.enum(["usb", "pci"]);
66576
66847
  var CoralInfoSchema = zod.z.object({
66577
66848
  type: zod.z.literal("coral-edgetpu"),
66578
- bus: zod.z.string().optional()
66849
+ /** Legacy single-bus report (older nodes) — read via `coralUsableUnits`. */
66850
+ bus: zod.z.string().optional(),
66851
+ /** Legacy USB unit count (older nodes) — read via `coralUsableUnits`. */
66852
+ count: zod.z.number().int().nonnegative().optional(),
66853
+ /** Usable units per bus — each one is its own `edgetpu:<bus>[:N]` device. */
66854
+ units: zod.z.array(zod.z.object({
66855
+ bus: CoralBusSchema,
66856
+ count: zod.z.number().int().nonnegative()
66857
+ })).readonly().optional(),
66858
+ /** Present-but-unusable units, each with its typed reason (never "absent"). */
66859
+ unavailable: zod.z.array(zod.z.object({
66860
+ bus: CoralBusSchema,
66861
+ count: zod.z.number().int().nonnegative(),
66862
+ reason: zod.z.enum(["driver-missing", "device-not-accessible"])
66863
+ })).readonly().optional()
66579
66864
  });
66580
66865
  var HardwareInfoSchema = zod.z.object({
66581
66866
  platform: HardwarePlatformSchema,
@@ -70278,9 +70563,29 @@ var streamParamsCapability = {
70278
70563
  */
70279
70564
  durability: "restored",
70280
70565
  /**
70281
- * History (D850): none — encoder configuration.
70566
+ * History (D850): the configured bitrate and frame rate of the main and sub
70567
+ * profiles. Configuration, so change-only on the default floor: a point is an
70568
+ * operator's (or a tuner's) edit, which is exactly what a chart of a stream's
70569
+ * quality over time must show.
70282
70570
  */
70283
- history: "none",
70571
+ history: { fields: {
70572
+ "main.bitrate": {
70573
+ kind: "gauge",
70574
+ unit: "kbps"
70575
+ },
70576
+ "main.framerate": {
70577
+ kind: "gauge",
70578
+ unit: "fps"
70579
+ },
70580
+ "sub.bitrate": {
70581
+ kind: "gauge",
70582
+ unit: "kbps"
70583
+ },
70584
+ "sub.framerate": {
70585
+ kind: "gauge",
70586
+ unit: "fps"
70587
+ }
70588
+ } },
70284
70589
  /** Clock fields: written, but excluded from the compare that decides
70285
70590
  * whether persisting is worth a SQLite commit. */
70286
70591
  volatileStateFields: ["lastFetchedAt"]
@@ -74483,6 +74788,15 @@ var BaseDevice = class {
74483
74788
  * Drivers can use the `getProbeFlags()` helper to read the flag bag
74484
74789
  * with a typed cast.
74485
74790
  *
74791
+ * Answer what you KNOW. A plain array is read as the complete list only
74792
+ * while this device is `online` and probed; return
74793
+ * `accessoryChildrenUnknown(reason)` whenever you cannot know the list right
74794
+ * now (no credentials, parent not connected, a failed or partial read) —
74795
+ * the kernel then deletes nothing. Return `accessoryChildrenComplete(list)`
74796
+ * to say "connected, and this is the complete list" explicitly. A shrink is
74797
+ * deleted only after a second agreeing complete read on a later probe (D49;
74798
+ * `packages/system/src/kernel/moleculer/accessory-prune-gate.ts`).
74799
+ *
74486
74800
  * Default: no children.
74487
74801
  */
74488
74802
  getAccessoryChildren() {
@@ -78392,7 +78706,19 @@ var METHOD_ACCESS_MAP = Object.freeze({
78392
78706
  addonId: null,
78393
78707
  access: "view"
78394
78708
  },
78395
- "logDestination.query": {
78709
+ "logDestination.cancelRead": {
78710
+ capName: "log-destination",
78711
+ capScope: "system",
78712
+ addonId: null,
78713
+ access: "create"
78714
+ },
78715
+ "logDestination.describeRead": {
78716
+ capName: "log-destination",
78717
+ capScope: "system",
78718
+ addonId: null,
78719
+ access: "view"
78720
+ },
78721
+ "logDestination.read": {
78396
78722
  capName: "log-destination",
78397
78723
  capScope: "system",
78398
78724
  addonId: null,
@@ -84670,6 +84996,11 @@ Object.freeze({
84670
84996
  form: "single",
84671
84997
  optional: false
84672
84998
  }],
84999
+ "logDestination.read": [{
85000
+ name: "deviceId",
85001
+ form: "single",
85002
+ optional: true
85003
+ }],
84673
85004
  "mediaPlayer.getStatus": [{
84674
85005
  name: "deviceId",
84675
85006
  form: "single",
@@ -86678,7 +87009,7 @@ var SESSION_ONLY_POLICY = {
86678
87009
  };
86679
87010
  /**
86680
87011
  * Cap history catalog, projected from every `*.cap.ts` `history` block.
86681
- * 34 caps with series (62 series), 37 caps answered `'none'`.
87012
+ * 40 caps with series (77 series), 31 caps answered `'none'`.
86682
87013
  * Field keys are `runtimeState` paths (`a.b` into fixed objects only).
86683
87014
  */
86684
87015
  var HISTORY_CATALOG = {
@@ -86709,6 +87040,21 @@ var HISTORY_CATALOG = {
86709
87040
  deadband: 1
86710
87041
  }
86711
87042
  },
87043
+ "alarm-panel": { "state": {
87044
+ kind: "enum",
87045
+ values: [
87046
+ "disarmed",
87047
+ "armed_home",
87048
+ "armed_away",
87049
+ "armed_night",
87050
+ "armed_vacation",
87051
+ "armed_custom_bypass",
87052
+ "arming",
87053
+ "disarming",
87054
+ "pending",
87055
+ "triggered"
87056
+ ]
87057
+ } },
86712
87058
  "ambient-light-sensor": { "lux": {
86713
87059
  kind: "gauge",
86714
87060
  unit: "lx",
@@ -86753,6 +87099,7 @@ var HISTORY_CATALOG = {
86753
87099
  minIntervalMs: 0
86754
87100
  }
86755
87101
  },
87102
+ "connectivity": { "connected": { kind: "boolean" } },
86756
87103
  "contact": { "entryOpen": { kind: "boolean" } },
86757
87104
  "cover": { "position": {
86758
87105
  kind: "gauge",
@@ -86760,10 +87107,48 @@ var HISTORY_CATALOG = {
86760
87107
  minIntervalMs: 0
86761
87108
  } },
86762
87109
  "device-status": { "online": { kind: "boolean" } },
86763
- "dishwasher": { "progressPercent": {
86764
- kind: "gauge",
86765
- unit: "%",
86766
- deadband: 2
87110
+ "dishwasher": {
87111
+ "progressPercent": {
87112
+ kind: "gauge",
87113
+ unit: "%",
87114
+ deadband: 2
87115
+ },
87116
+ "state": {
87117
+ kind: "enum",
87118
+ values: [
87119
+ "idle",
87120
+ "running",
87121
+ "paused",
87122
+ "finished",
87123
+ "error",
87124
+ "unavailable"
87125
+ ]
87126
+ },
87127
+ "operationState": {
87128
+ kind: "enum",
87129
+ values: [
87130
+ "Inactive",
87131
+ "Ready",
87132
+ "DelayedStart",
87133
+ "Run",
87134
+ "Pause",
87135
+ "ActionRequired",
87136
+ "Finished",
87137
+ "Error",
87138
+ "Aborting"
87139
+ ]
87140
+ },
87141
+ "remainingSeconds": {
87142
+ kind: "gauge",
87143
+ unit: "s",
87144
+ minIntervalMs: 6e4
87145
+ },
87146
+ "doorOpen": { kind: "boolean" },
87147
+ "powerOn": { kind: "boolean" }
87148
+ },
87149
+ "enum-sensor": { "value": {
87150
+ kind: "enum",
87151
+ skipWhenSet: "format"
86767
87152
  } },
86768
87153
  "fan-control": {
86769
87154
  "percentage": {
@@ -86798,6 +87183,24 @@ var HISTORY_CATALOG = {
86798
87183
  unit: "%",
86799
87184
  deadband: 2
86800
87185
  } },
87186
+ "lock-control": { "state": {
87187
+ kind: "enum",
87188
+ values: [
87189
+ "locked",
87190
+ "unlocked",
87191
+ "locking",
87192
+ "unlocking",
87193
+ "jammed"
87194
+ ]
87195
+ } },
87196
+ "media-player": {
87197
+ "volumeLevel": {
87198
+ kind: "gauge",
87199
+ unit: "%",
87200
+ deadband: 1
87201
+ },
87202
+ "isMuted": { kind: "boolean" }
87203
+ },
86801
87204
  "motion": { "detected": {
86802
87205
  kind: "boolean",
86803
87206
  excludeDeviceTypes: [DeviceType.Camera]
@@ -86884,6 +87287,24 @@ var HISTORY_CATALOG = {
86884
87287
  deadband: .1
86885
87288
  } },
86886
87289
  "smoke": { "detected": { kind: "boolean" } },
87290
+ "stream-params": {
87291
+ "main.bitrate": {
87292
+ kind: "gauge",
87293
+ unit: "kbps"
87294
+ },
87295
+ "main.framerate": {
87296
+ kind: "gauge",
87297
+ unit: "fps"
87298
+ },
87299
+ "sub.bitrate": {
87300
+ kind: "gauge",
87301
+ unit: "kbps"
87302
+ },
87303
+ "sub.framerate": {
87304
+ kind: "gauge",
87305
+ unit: "fps"
87306
+ }
87307
+ },
86887
87308
  "switch": { "on": { kind: "boolean" } },
86888
87309
  "tamper": { "tampered": { kind: "boolean" } },
86889
87310
  "temperature-sensor": { "celsius": {
@@ -88173,6 +88594,29 @@ function decodeVectorBase64(encoded) {
88173
88594
  function vectorDimFromBase64(encoded) {
88174
88595
  return Math.floor(Buffer.from(encoded, "base64").byteLength / 4);
88175
88596
  }
88597
+ /** Bus order of the enumeration: USB first (the historical key), then PCIe. */
88598
+ var BUS_ORDER = ["usb", "pci"];
88599
+ function unitDevice(bus, index) {
88600
+ return index === 0 ? bus : `${bus}:${index}`;
88601
+ }
88602
+ function countOn(coral, bus) {
88603
+ if (coral.units !== void 0) return coral.units.filter((u) => u.bus === bus).reduce((n, u) => n + Math.max(0, u.count), 0);
88604
+ return bus === (coral.bus === "pci" ? "pci" : "usb") ? Math.max(1, coral.count ?? 1) : 0;
88605
+ }
88606
+ /** Every usable Coral unit on a node, USB first then PCIe, in ordinal order. */
88607
+ function coralUsableUnits(coral) {
88608
+ if (coral == null) return [];
88609
+ const out = [];
88610
+ for (const bus of BUS_ORDER) {
88611
+ const count = countOn(coral, bus);
88612
+ for (let index = 0; index < count; index++) out.push({
88613
+ bus,
88614
+ index,
88615
+ device: unitDevice(bus, index)
88616
+ });
88617
+ }
88618
+ return out;
88619
+ }
88176
88620
  var AUTO = {
88177
88621
  value: "auto",
88178
88622
  label: "Auto"
@@ -88185,6 +88629,14 @@ var USB = {
88185
88629
  value: "usb",
88186
88630
  label: "Coral USB"
88187
88631
  };
88632
+ function coralUnitOption(unit) {
88633
+ const bus = unit.bus === "pci" ? "PCIe" : "USB";
88634
+ const label = unit.index === 0 ? `Coral ${bus}` : `Coral ${bus} ${unit.index + 1}`;
88635
+ return {
88636
+ value: unit.device,
88637
+ label
88638
+ };
88639
+ }
88188
88640
  var RUNTIMES = [
88189
88641
  {
88190
88642
  id: "onnx",
@@ -88251,8 +88703,11 @@ var RUNTIMES = [
88251
88703
  },
88252
88704
  {
88253
88705
  id: "edgetpu",
88254
- supports: (hw) => hw?.coral != null,
88255
- devices: () => [USB],
88706
+ supports: (hw) => coralUsableUnits(hw?.coral).length > 0,
88707
+ devices: (hw) => {
88708
+ const units = coralUsableUnits(hw?.coral);
88709
+ return units.length > 0 ? units.map(coralUnitOption) : [USB];
88710
+ },
88256
88711
  defaultDevice: "usb"
88257
88712
  }
88258
88713
  ];
@@ -88270,7 +88725,7 @@ function supportedRuntimes(hw) {
88270
88725
  * - coreml: score 95, darwin+arm64
88271
88726
  * - cuda: score 85, nvidia gpu
88272
88727
  * - openvino: score 90 if intel-npu present, else 80 if intel gpu
88273
- * - edgetpu: score 70, coral usb present
88728
+ * - edgetpu: score 70, a usable Coral unit (USB or PCIe)
88274
88729
  * - cpu: score 50 (universal floor, always included)
88275
88730
  *
88276
88731
  * All hardware-matched entries are `available: true`.
@@ -88324,7 +88779,7 @@ function scoreRuntimes(hw) {
88324
88779
  available: true
88325
88780
  });
88326
88781
  }
88327
- if (hw.coral != null) scores.push({
88782
+ if (coralUsableUnits(hw.coral).length > 0) scores.push({
88328
88783
  runtime: "python",
88329
88784
  backend: "edgetpu",
88330
88785
  format: "tflite",
@@ -88383,11 +88838,7 @@ function enumerateInferenceDevices(hw) {
88383
88838
  continue;
88384
88839
  }
88385
88840
  if (s.backend === "edgetpu") {
88386
- const coralCount = Math.max(1, hw.coral?.count ?? 1);
88387
- for (let i = 0; i < coralCount; i++) {
88388
- const dev = i === 0 ? "usb" : `usb:${i}`;
88389
- out.push(device("edgetpu", dev, s.format, s.score));
88390
- }
88841
+ for (const unit of coralUsableUnits(hw.coral)) out.push(device("edgetpu", unit.device, s.format, s.score));
88391
88842
  continue;
88392
88843
  }
88393
88844
  if (s.backend === "onnx" && s.reason.startsWith("ONNX WebGPU")) {
@@ -88662,6 +89113,12 @@ Object.defineProperty(exports, "DEVICE_ENROLLMENT_TTL_MS", {
88662
89113
  return DEVICE_ENROLLMENT_TTL_MS;
88663
89114
  }
88664
89115
  });
89116
+ Object.defineProperty(exports, "DEVICE_HISTORY_ENERGY_KEY", {
89117
+ enumerable: true,
89118
+ get: function() {
89119
+ return DEVICE_HISTORY_ENERGY_KEY;
89120
+ }
89121
+ });
88665
89122
  Object.defineProperty(exports, "DEVICE_NONCE_TTL_MS", {
88666
89123
  enumerable: true,
88667
89124
  get: function() {
@@ -88944,6 +89401,12 @@ Object.defineProperty(exports, "REMOVE_LEAF", {
88944
89401
  return REMOVE_LEAF;
88945
89402
  }
88946
89403
  });
89404
+ Object.defineProperty(exports, "ROOT_BUCKET_KEY", {
89405
+ enumerable: true,
89406
+ get: function() {
89407
+ return ROOT_BUCKET_KEY;
89408
+ }
89409
+ });
88947
89410
  Object.defineProperty(exports, "RUNTIME_DEFAULTS", {
88948
89411
  enumerable: true,
88949
89412
  get: function() {
@@ -89076,6 +89539,12 @@ Object.defineProperty(exports, "TokenScopeSchema", {
89076
89539
  return TokenScopeSchema;
89077
89540
  }
89078
89541
  });
89542
+ Object.defineProperty(exports, "UNATTRIBUTED_BUCKET_KEY", {
89543
+ enumerable: true,
89544
+ get: function() {
89545
+ return UNATTRIBUTED_BUCKET_KEY;
89546
+ }
89547
+ });
89079
89548
  Object.defineProperty(exports, "UnindexedFilterError", {
89080
89549
  enumerable: true,
89081
89550
  get: function() {