@camstack/system 1.2.85 → 1.2.87

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 (54) hide show
  1. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
  2. package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
  3. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
  4. package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
  5. package/dist/builtins/alerts/alerts.addon.js +1 -1
  6. package/dist/builtins/alerts/alerts.addon.mjs +1 -1
  7. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +1 -1
  8. package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +1 -1
  9. package/dist/builtins/console-logging/index.js +1 -1
  10. package/dist/builtins/console-logging/index.mjs +1 -1
  11. package/dist/builtins/core-blocks/core-blocks.addon.js +1 -1
  12. package/dist/builtins/core-blocks/core-blocks.addon.mjs +1 -1
  13. package/dist/builtins/device-manager/device-manager.addon.js +155 -18
  14. package/dist/builtins/device-manager/device-manager.addon.mjs +155 -18
  15. package/dist/builtins/device-manager/device-state-mirror.d.ts +51 -6
  16. package/dist/builtins/device-manager/runtime-state-persist-gate.d.ts +32 -0
  17. package/dist/builtins/doorbell/virtual-doorbell.addon.js +1 -1
  18. package/dist/builtins/doorbell/virtual-doorbell.addon.mjs +1 -1
  19. package/dist/builtins/hub-forwarder/index.js +1 -1
  20. package/dist/builtins/hub-forwarder/index.mjs +1 -1
  21. package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
  22. package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
  23. package/dist/builtins/local-auth/local-auth.addon.js +1 -1
  24. package/dist/builtins/local-auth/local-auth.addon.mjs +1 -1
  25. package/dist/builtins/local-network/local-network.addon.js +1 -1
  26. package/dist/builtins/local-network/local-network.addon.mjs +1 -1
  27. package/dist/builtins/loki-logging/index.js +1 -1
  28. package/dist/builtins/loki-logging/index.mjs +1 -1
  29. package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
  30. package/dist/builtins/native-metrics/native-metrics.addon.mjs +1 -1
  31. package/dist/builtins/platform-probe/index.js +1 -1
  32. package/dist/builtins/platform-probe/index.mjs +1 -1
  33. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
  34. package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
  35. package/dist/builtins/snapshot/index.js +1 -1
  36. package/dist/builtins/snapshot/index.mjs +1 -1
  37. package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
  38. package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
  39. package/dist/builtins/sqlite-storage/sqlite-settings-backend.d.ts +15 -0
  40. package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +37 -1
  41. package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +37 -1
  42. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
  43. package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
  44. package/dist/builtins/system-config/system-config.addon.js +1 -1
  45. package/dist/builtins/system-config/system-config.addon.mjs +1 -1
  46. package/dist/builtins/winston-logging/index.js +1 -1
  47. package/dist/builtins/winston-logging/index.mjs +1 -1
  48. package/dist/{dist-DWuNENzg.mjs → dist-CuAaqtdt.mjs} +996 -109
  49. package/dist/{dist-DiScsb8j.js → dist-D4nuaPdd.js} +1001 -108
  50. package/dist/index.js +38 -20
  51. package/dist/index.mjs +38 -20
  52. package/dist/kernel/addon-installer.d.ts +7 -15
  53. package/dist/kernel/config-manager.d.ts +32 -0
  54. package/package.json +1 -1
@@ -1,7 +1,14 @@
1
1
  import { AddonContext } from '@camstack/types';
2
2
  import { DeviceManagerSettings } from './device-meta-store.js';
3
+ import { RuntimeStatePolicyLookup } from './runtime-state-persist-gate.js';
3
4
  export declare class DeviceStateMirror {
4
5
  private readonly ctx;
6
+ /**
7
+ * Per-cap durability + volatile-field policy. Defaults to the codegen'd
8
+ * projection of every `*.cap.ts` (D4: the cap declares, the kernel reads).
9
+ * Injectable so a spec can exercise the gate without the real cap set.
10
+ */
11
+ private readonly policyFor;
5
12
  /**
6
13
  * Hub-side mirror of every device's cap-keyed runtime state.
7
14
  * Key: deviceId. Value: per-cap slice map. Empty by default —
@@ -15,7 +22,28 @@ export declare class DeviceStateMirror {
15
22
  */
16
23
  private readonly runtimeStateDebounce;
17
24
  private static readonly RUNTIME_STATE_DEBOUNCE_MS;
18
- constructor(ctx: AddonContext);
25
+ /**
26
+ * What is believed to be ON DISK for each device — the persistable projection
27
+ * of the last blob actually written (or seeded at boot). The effective-change
28
+ * gate compares against THIS, not against the previous mirror state: two
29
+ * clock-only ticks in a row must not add up to a write just because each was
30
+ * compared with its immediate predecessor.
31
+ */
32
+ private readonly lastPersisted;
33
+ /**
34
+ * Per-device count of writes the effective-change gate skipped since the last
35
+ * real one. Reported on the next write that DOES happen, so the log says how
36
+ * much churn the gate absorbed instead of saying nothing at all — a branch
37
+ * that drops work silently reads as "never happened".
38
+ */
39
+ private readonly skippedSinceWrite;
40
+ constructor(ctx: AddonContext,
41
+ /**
42
+ * Per-cap durability + volatile-field policy. Defaults to the codegen'd
43
+ * projection of every `*.cap.ts` (D4: the cap declares, the kernel reads).
44
+ * Injectable so a spec can exercise the gate without the real cap set.
45
+ */
46
+ policyFor?: RuntimeStatePolicyLookup);
19
47
  /**
20
48
  * Single-cap mirror update — diff against the current mirror,
21
49
  * persist the new slice in-memory, emit `DeviceStateChanged` for
@@ -30,13 +58,30 @@ export declare class DeviceStateMirror {
30
58
  */
31
59
  applySingleCapUpdate(deviceId: number, capName: string, slice: Record<string, unknown>): boolean;
32
60
  /**
33
- * Debounced disk writer. Coalesces frequent writes (motion phase
34
- * transitions, battery pushes) into one `writeDeviceRuntimeState`
35
- * per `RUNTIME_STATE_DEBOUNCE_MS` window. Reads the per-device
36
- * blob from the live mirror at flush time so the disk picture is
61
+ * Debounced disk writer, behind two gates.
62
+ *
63
+ * GATE — DURABILITY: a change to a `durability: 'session'` cap never even
64
+ * arms the timer. That is where the fleet's write rate goes: `audio-metrics`
65
+ * and `zone-analytics` are ~90 % of the offered 12–19 writes/s, they change
66
+ * genuinely every second, and their restored value is worthless.
67
+ *
68
+ * GATE — EFFECTIVE CHANGE (at flush): the persistable blob is compared with
69
+ * what is believed to be on disk, ignoring the clock fields each cap declared
70
+ * volatile. `battery` wrote its blob 526 times in 25 minutes without one
71
+ * percentage moving; this is the gate that turns those into one write.
72
+ *
73
+ * The blob is read from the live mirror at flush time, so the disk picture is
37
74
  * always the latest state — no risk of writing a stale snapshot.
38
75
  */
39
- scheduleRuntimeStateDiskWrite(deviceId: number, settings: DeviceManagerSettings): void;
76
+ scheduleRuntimeStateDiskWrite(deviceId: number, settings: DeviceManagerSettings, changedCap: string): void;
77
+ /**
78
+ * True when `blob` differs from what is believed to be on disk only in fields
79
+ * the owning caps declared volatile. Counts the skip so the next real write
80
+ * can report how much churn was absorbed.
81
+ */
82
+ private isAlreadyPersisted;
83
+ /** The device's mirror, restricted to the slices that may reach disk. */
84
+ private persistableForDevice;
40
85
  /**
41
86
  * One-shot mirror seed used by `loadRuntimeState` at boot so the
42
87
  * hub knows about every persisted slice without waiting for the
@@ -0,0 +1,32 @@
1
+ import { RuntimeStatePolicy } from '@camstack/types';
2
+ /** Resolves the declared policy for a cap name. */
3
+ export type RuntimeStatePolicyLookup = (capName: string) => RuntimeStatePolicy;
4
+ /** A device's cap-keyed slice map, as mirrored and as persisted. */
5
+ export type RuntimeStateBlob = Readonly<Record<string, Readonly<Record<string, unknown>>>>;
6
+ /**
7
+ * The subset of `blob` that is allowed on disk: slices whose capability
8
+ * declared `durability: 'restored'`.
9
+ *
10
+ * A cap the lookup does not know resolves to `'session'` and is dropped. That
11
+ * direction is deliberate: the cost of losing a session value is a cold window
12
+ * until the provider republishes; the cost of persisting an unasked-for one is
13
+ * a commit per second on the fleet's busiest write path.
14
+ */
15
+ export declare function persistableBlob(blob: RuntimeStateBlob, policyFor: RuntimeStatePolicyLookup): Record<string, Record<string, unknown>>;
16
+ /**
17
+ * Are two slices the same, ignoring the fields the cap declared volatile?
18
+ *
19
+ * A volatile field is still WRITTEN — it simply does not, on its own, justify
20
+ * the write. A field the cap did NOT declare volatile is content, even when its
21
+ * name looks like a clock: the capability is the only authority on which of its
22
+ * fields carry meaning (D4), and the guard makes an undeclared clock visible in
23
+ * the diff rather than assuming it.
24
+ */
25
+ export declare function sliceEffectivelyEqual(a: Readonly<Record<string, unknown>>, b: Readonly<Record<string, unknown>>, volatileFields: readonly string[]): boolean;
26
+ /**
27
+ * Is the whole persistable blob unchanged in every way that matters?
28
+ *
29
+ * A cap slice APPEARING or DISAPPEARING is always a change — the write is a
30
+ * whole-blob replace, so a dropped slice only leaves disk if the write happens.
31
+ */
32
+ export declare function effectivelyEqual(before: RuntimeStateBlob, after: RuntimeStateBlob, policyFor: RuntimeStatePolicyLookup): boolean;
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-DiScsb8j.js");
6
+ const require_dist = require("../../dist-D4nuaPdd.js");
7
7
  //#region src/builtins/doorbell/trigger-engine.ts
8
8
  /**
9
9
  * Pure trigger logic for the virtual-doorbell builtin — edge detection over
@@ -1,4 +1,4 @@
1
- import { Ht as EventCategory, P as doorbellCapability, St as DeviceType, U as isSameAddonId, gt as BaseAddon, ht as errMsg, kt as createEvent, w as bareAddonId } from "../../dist-DWuNENzg.mjs";
1
+ import { At as createEvent, Ct as DeviceType, P as doorbellCapability, U as isSameAddonId, Ut as EventCategory, _t as BaseAddon, gt as errMsg, w as bareAddonId } from "../../dist-CuAaqtdt.mjs";
2
2
  //#region src/builtins/doorbell/trigger-engine.ts
3
3
  /**
4
4
  * Pure trigger logic for the virtual-doorbell builtin — edge detection over
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-DiScsb8j.js");
6
+ const require_dist = require("../../dist-D4nuaPdd.js");
7
7
  const require_formatter = require("../../formatter-DqAKDlvN.js");
8
8
  //#region src/builtins/hub-forwarder/hub-forwarder-destination.ts
9
9
  var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
@@ -1,4 +1,4 @@
1
- import { J as logDestinationCapability, gt as BaseAddon } from "../../dist-DWuNENzg.mjs";
1
+ import { J as logDestinationCapability, _t as BaseAddon } from "../../dist-CuAaqtdt.mjs";
2
2
  import { t as formatLogLine } from "../../formatter-B7qW8bPJ.mjs";
3
3
  //#region src/builtins/hub-forwarder/hub-forwarder-destination.ts
4
4
  var DEFAULT_OUTBOUND_BUFFER_SIZE = 500;
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  require("../../chunk-Cek0wNdY.js");
3
- const require_dist = require("../../dist-DiScsb8j.js");
3
+ const require_dist = require("../../dist-D4nuaPdd.js");
4
4
  //#region src/builtins/liveness-monitor/liveness-checks.ts
5
5
  var NO_DEVICES = "liveness:no-devices";
6
6
  var ALL_OFFLINE = "liveness:all-devices-offline";
@@ -1,4 +1,4 @@
1
- import { Ht as EventCategory, gt as BaseAddon, ht as errMsg, kt as createEvent } from "../../dist-DWuNENzg.mjs";
1
+ import { At as createEvent, Ut as EventCategory, _t as BaseAddon, gt as errMsg } from "../../dist-CuAaqtdt.mjs";
2
2
  //#region src/builtins/liveness-monitor/liveness-checks.ts
3
3
  var NO_DEVICES = "liveness:no-devices";
4
4
  var ALL_OFFLINE = "liveness:all-devices-offline";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-DiScsb8j.js");
6
+ const require_dist = require("../../dist-D4nuaPdd.js");
7
7
  let node_crypto = require("node:crypto");
8
8
  node_crypto = require_chunk.__toESM(node_crypto);
9
9
  let crypto$1 = require("crypto");
@@ -1,5 +1,5 @@
1
1
  import { i as __require, o as __toESM, t as __commonJSMin } from "../../chunk-CNf5ZN-e.mjs";
2
- import { S as authProviderCapability, _ as UserRecordSchema, ft as userManagementCapability, gt as BaseAddon, m as ScopedTokenSchema, r as ApiKeyRecordSchema } from "../../dist-DWuNENzg.mjs";
2
+ import { S as authProviderCapability, _ as UserRecordSchema, _t as BaseAddon, m as ScopedTokenSchema, pt as userManagementCapability, r as ApiKeyRecordSchema } from "../../dist-CuAaqtdt.mjs";
3
3
  import * as crypto$2 from "node:crypto";
4
4
  import { createHash, randomUUID, timingSafeEqual } from "node:crypto";
5
5
  import nodeCrypto from "crypto";
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_chunk = require("../../chunk-Cek0wNdY.js");
3
- const require_dist = require("../../dist-DiScsb8j.js");
3
+ const require_dist = require("../../dist-D4nuaPdd.js");
4
4
  let node_os = require("node:os");
5
5
  node_os = require_chunk.__toESM(node_os);
6
6
  //#region src/builtins/local-network/local-network.addon.ts
@@ -1,4 +1,4 @@
1
- import { Ht as EventCategory, gt as BaseAddon, q as localNetworkCapability } from "../../dist-DWuNENzg.mjs";
1
+ import { Ut as EventCategory, _t as BaseAddon, q as localNetworkCapability } from "../../dist-CuAaqtdt.mjs";
2
2
  import * as os from "node:os";
3
3
  //#region src/builtins/local-network/local-network.addon.ts
4
4
  /**
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-DiScsb8j.js");
6
+ const require_dist = require("../../dist-D4nuaPdd.js");
7
7
  //#region src/builtins/loki-logging/loki-payload.ts
8
8
  /**
9
9
  * Loki rejects a label name that is not a valid Prometheus label
@@ -1,4 +1,4 @@
1
- import { J as logDestinationCapability, gt as BaseAddon } from "../../dist-DWuNENzg.mjs";
1
+ import { J as logDestinationCapability, _t as BaseAddon } from "../../dist-CuAaqtdt.mjs";
2
2
  //#region src/builtins/loki-logging/loki-payload.ts
3
3
  /**
4
4
  * Loki rejects a label name that is not a valid Prometheus label
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-DiScsb8j.js");
6
+ const require_dist = require("../../dist-D4nuaPdd.js");
7
7
  let node_child_process = require("node:child_process");
8
8
  let node_util = require("node:util");
9
9
  let node_os = require("node:os");
@@ -1,4 +1,4 @@
1
- import { Ht as EventCategory, Z as metricsProviderCapability, gt as BaseAddon, kt as createEvent } from "../../dist-DWuNENzg.mjs";
1
+ import { At as createEvent, Ut as EventCategory, Z as metricsProviderCapability, _t as BaseAddon } from "../../dist-CuAaqtdt.mjs";
2
2
  import { execFile, execFileSync } from "node:child_process";
3
3
  import { promisify } from "node:util";
4
4
  import * as os from "node:os";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-DiScsb8j.js");
6
+ const require_dist = require("../../dist-D4nuaPdd.js");
7
7
  let node_child_process = require("node:child_process");
8
8
  let node_util = require("node:util");
9
9
  let node_os = require("node:os");
@@ -1,5 +1,5 @@
1
1
  import { o as __toESM } from "../../chunk-CNf5ZN-e.mjs";
2
- import { F as enumerateInferenceDevices, Ht as EventCategory, at as scoreRuntimes, gt as BaseAddon, ht as errMsg, jt as emitReadiness, tt as platformProbeCapability } from "../../dist-DWuNENzg.mjs";
2
+ import { F as enumerateInferenceDevices, Mt as emitReadiness, Ut as EventCategory, _t as BaseAddon, gt as errMsg, ot as scoreRuntimes, tt as platformProbeCapability } from "../../dist-CuAaqtdt.mjs";
3
3
  import { execFile } from "node:child_process";
4
4
  import { promisify } from "node:util";
5
5
  import * as os from "node:os";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-DiScsb8j.js");
6
+ const require_dist = require("../../dist-D4nuaPdd.js");
7
7
  //#region src/builtins/remote-access-orchestrator/enabled-providers-reconcile.ts
8
8
  /**
9
9
  * Reconcile the durable `enabledProviders` set against authoritative
@@ -1,4 +1,4 @@
1
- import { Ht as EventCategory, gt as BaseAddon } from "../../dist-DWuNENzg.mjs";
1
+ import { Ut as EventCategory, _t as BaseAddon } from "../../dist-CuAaqtdt.mjs";
2
2
  //#region src/builtins/remote-access-orchestrator/enabled-providers-reconcile.ts
3
3
  /**
4
4
  * Reconcile the durable `enabledProviders` set against authoritative
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-DiScsb8j.js");
6
+ const require_dist = require("../../dist-D4nuaPdd.js");
7
7
  let zod = require("zod");
8
8
  let node_crypto = require("node:crypto");
9
9
  let _camstack_types_node = require("@camstack/types/node");
@@ -1,4 +1,4 @@
1
- import { Ft as nodePin, Ht as EventCategory, St as DeviceType, bt as DeviceFeature, dt as streamQualityLabel, gt as BaseAddon, ht as errMsg, i as BatteryStatusSchema, st as snapshotCapability, w as bareAddonId } from "../../dist-DWuNENzg.mjs";
1
+ import { Ct as DeviceType, It as nodePin, Ut as EventCategory, _t as BaseAddon, ct as snapshotCapability, ft as streamQualityLabel, gt as errMsg, i as BatteryStatusSchema, w as bareAddonId, xt as DeviceFeature } from "../../dist-CuAaqtdt.mjs";
2
2
  import { z } from "zod";
3
3
  import { randomUUID } from "node:crypto";
4
4
  import { signExpiringUrl, verifyExpiringUrl } from "@camstack/types/node";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-DiScsb8j.js");
6
+ const require_dist = require("../../dist-D4nuaPdd.js");
7
7
  let node_crypto = require("node:crypto");
8
8
  let node_fs_promises = require("node:fs/promises");
9
9
  let node_path = require("node:path");
@@ -1,4 +1,4 @@
1
- import { gt as BaseAddon, ut as storageProviderCapability, z as filesystemBrowseCapability } from "../../dist-DWuNENzg.mjs";
1
+ import { _t as BaseAddon, dt as storageProviderCapability, z as filesystemBrowseCapability } from "../../dist-CuAaqtdt.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import { mkdir, readdir, realpath, statfs } from "node:fs/promises";
4
4
  import * as path$1 from "node:path";
@@ -138,6 +138,21 @@ export declare class SqliteSettingsBackend implements ISettingsBackend {
138
138
  getAddonDevice(addonId: string, deviceId: string): Record<string, unknown>;
139
139
  setAddonDevice(addonId: string, deviceId: string, values: Record<string, unknown>): void;
140
140
  clearAddonDevice(addonId: string, deviceId: string): void;
141
+ private static readonly LEGACY_RUNTIME_STATE_ADDON_ID;
142
+ /**
143
+ * The device's whole cap-slice map. Canonical row first, legacy prefix as the
144
+ * fallback. `{}` — never null — when the device has never persisted a slice,
145
+ * because every caller treats the result as a cap map to iterate.
146
+ */
147
+ getDeviceRuntimeState(deviceId: string): Record<string, unknown>;
148
+ /**
149
+ * Replace the device's whole cap-slice map. Replace, not merge — the caller
150
+ * always hands over the full persistable blob, and merging would resurrect a
151
+ * slice the durability policy has since stopped persisting.
152
+ */
153
+ setDeviceRuntimeState(deviceId: string, blob: Record<string, unknown>): void;
154
+ /** Forget the device's runtime state in BOTH stores (device removal). */
155
+ clearDeviceRuntimeState(deviceId: string): void;
141
156
  /** Seed system-settings with runtime defaults (first boot) */
142
157
  private seedDefaults;
143
158
  /**
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-DiScsb8j.js");
6
+ const require_dist = require("../../dist-D4nuaPdd.js");
7
7
  let node_crypto = require("node:crypto");
8
8
  let node_fs = require("node:fs");
9
9
  let node_module = require("node:module");
@@ -961,6 +961,42 @@ var SqliteSettingsBackend = class SqliteSettingsBackend {
961
961
  const where = this.prefixWhere(`${addonId}:${deviceId}.`);
962
962
  this.getDb().prepare(`DELETE FROM "addon-device-settings" WHERE ${where.sql}`).run(...where.params);
963
963
  }
964
+ static LEGACY_RUNTIME_STATE_ADDON_ID = "__device-state";
965
+ /**
966
+ * The device's whole cap-slice map. Canonical row first, legacy prefix as the
967
+ * fallback. `{}` — never null — when the device has never persisted a slice,
968
+ * because every caller treats the result as a cap map to iterate.
969
+ */
970
+ getDeviceRuntimeState(deviceId) {
971
+ this.requireDeclared("device-runtime-state");
972
+ const row = this.getDb().prepare("SELECT data FROM \"device-runtime-state\" WHERE id = ?").get(deviceId);
973
+ if (row) return parseRowData(row.data);
974
+ return this.getAddonDevice(SqliteSettingsBackend.LEGACY_RUNTIME_STATE_ADDON_ID, deviceId);
975
+ }
976
+ /**
977
+ * Replace the device's whole cap-slice map. Replace, not merge — the caller
978
+ * always hands over the full persistable blob, and merging would resurrect a
979
+ * slice the durability policy has since stopped persisting.
980
+ */
981
+ setDeviceRuntimeState(deviceId, blob) {
982
+ this.requireDeclared("device-runtime-state");
983
+ this.requireDeclared("addon-device-settings");
984
+ const db = this.getDb();
985
+ const upsert = db.prepare(`INSERT INTO "device-runtime-state" (id, data) VALUES (?, ?)
986
+ ON CONFLICT(id) DO UPDATE SET data = excluded.data`);
987
+ const legacy = this.prefixWhere(`${SqliteSettingsBackend.LEGACY_RUNTIME_STATE_ADDON_ID}:${deviceId}.`);
988
+ const retire = db.prepare(`DELETE FROM "addon-device-settings" WHERE ${legacy.sql}`);
989
+ db.transaction(() => {
990
+ upsert.run(deviceId, JSON.stringify(blob));
991
+ retire.run(...legacy.params);
992
+ })();
993
+ }
994
+ /** Forget the device's runtime state in BOTH stores (device removal). */
995
+ clearDeviceRuntimeState(deviceId) {
996
+ this.requireDeclared("device-runtime-state");
997
+ this.getDb().prepare("DELETE FROM \"device-runtime-state\" WHERE id = ?").run(deviceId);
998
+ this.clearAddonDevice(SqliteSettingsBackend.LEGACY_RUNTIME_STATE_ADDON_ID, deviceId);
999
+ }
964
1000
  /** Seed system-settings with runtime defaults (first boot) */
965
1001
  async seedDefaults() {
966
1002
  this.requireDeclared("system-settings");
@@ -1,4 +1,4 @@
1
- import { A as decodeVectorBase64, Et as asJsonObject, Lt as parseJsonUnknown, f as RUNTIME_DEFAULTS, gt as BaseAddon, ht as errMsg, k as dataStoreProviderCapability, mt as vectorStoreCapability, pt as vectorDimFromBase64, w as bareAddonId } from "../../dist-DWuNENzg.mjs";
1
+ import { A as decodeVectorBase64, Dt as asJsonObject, Rt as parseJsonUnknown, _t as BaseAddon, f as RUNTIME_DEFAULTS, gt as errMsg, ht as vectorStoreCapability, k as dataStoreProviderCapability, mt as vectorDimFromBase64, w as bareAddonId } from "../../dist-CuAaqtdt.mjs";
2
2
  import { createRequire } from "node:module";
3
3
  import { randomUUID } from "node:crypto";
4
4
  import { statSync } from "node:fs";
@@ -955,6 +955,42 @@ var SqliteSettingsBackend = class SqliteSettingsBackend {
955
955
  const where = this.prefixWhere(`${addonId}:${deviceId}.`);
956
956
  this.getDb().prepare(`DELETE FROM "addon-device-settings" WHERE ${where.sql}`).run(...where.params);
957
957
  }
958
+ static LEGACY_RUNTIME_STATE_ADDON_ID = "__device-state";
959
+ /**
960
+ * The device's whole cap-slice map. Canonical row first, legacy prefix as the
961
+ * fallback. `{}` — never null — when the device has never persisted a slice,
962
+ * because every caller treats the result as a cap map to iterate.
963
+ */
964
+ getDeviceRuntimeState(deviceId) {
965
+ this.requireDeclared("device-runtime-state");
966
+ const row = this.getDb().prepare("SELECT data FROM \"device-runtime-state\" WHERE id = ?").get(deviceId);
967
+ if (row) return parseRowData(row.data);
968
+ return this.getAddonDevice(SqliteSettingsBackend.LEGACY_RUNTIME_STATE_ADDON_ID, deviceId);
969
+ }
970
+ /**
971
+ * Replace the device's whole cap-slice map. Replace, not merge — the caller
972
+ * always hands over the full persistable blob, and merging would resurrect a
973
+ * slice the durability policy has since stopped persisting.
974
+ */
975
+ setDeviceRuntimeState(deviceId, blob) {
976
+ this.requireDeclared("device-runtime-state");
977
+ this.requireDeclared("addon-device-settings");
978
+ const db = this.getDb();
979
+ const upsert = db.prepare(`INSERT INTO "device-runtime-state" (id, data) VALUES (?, ?)
980
+ ON CONFLICT(id) DO UPDATE SET data = excluded.data`);
981
+ const legacy = this.prefixWhere(`${SqliteSettingsBackend.LEGACY_RUNTIME_STATE_ADDON_ID}:${deviceId}.`);
982
+ const retire = db.prepare(`DELETE FROM "addon-device-settings" WHERE ${legacy.sql}`);
983
+ db.transaction(() => {
984
+ upsert.run(deviceId, JSON.stringify(blob));
985
+ retire.run(...legacy.params);
986
+ })();
987
+ }
988
+ /** Forget the device's runtime state in BOTH stores (device removal). */
989
+ clearDeviceRuntimeState(deviceId) {
990
+ this.requireDeclared("device-runtime-state");
991
+ this.getDb().prepare("DELETE FROM \"device-runtime-state\" WHERE id = ?").run(deviceId);
992
+ this.clearAddonDevice(SqliteSettingsBackend.LEGACY_RUNTIME_STATE_ADDON_ID, deviceId);
993
+ }
958
994
  /** Seed system-settings with runtime defaults (first boot) */
959
995
  async seedDefaults() {
960
996
  this.requireDeclared("system-settings");
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-DiScsb8j.js");
6
+ const require_dist = require("../../dist-D4nuaPdd.js");
7
7
  let node_crypto = require("node:crypto");
8
8
  let node_fs_promises = require("node:fs/promises");
9
9
  node_fs_promises = require_chunk.__toESM(node_fs_promises);
@@ -1,4 +1,4 @@
1
- import { It as parseJsonObject, ct as storageCapability, g as StorageMigrationJobSchema, gt as BaseAddon, h as StorageLocationTypeSchema, lt as storageMigrationCapability, ot as settingsStoreCapability } from "../../dist-DWuNENzg.mjs";
1
+ import { Lt as parseJsonObject, _t as BaseAddon, g as StorageMigrationJobSchema, h as StorageLocationTypeSchema, lt as storageCapability, st as settingsStoreCapability, ut as storageMigrationCapability } from "../../dist-CuAaqtdt.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import * as fs from "node:fs/promises";
4
4
  import * as path$1 from "node:path";
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-DiScsb8j.js");
6
+ const require_dist = require("../../dist-D4nuaPdd.js");
7
7
  //#region src/builtins/system-config/system-config.addon.ts
8
8
  /**
9
9
  * Built-in `system-config` addon — Phase 4 of the settings redesign.
@@ -1,4 +1,4 @@
1
- import { Nt as hydrateSchema, gt as BaseAddon, ht as errMsg } from "../../dist-DWuNENzg.mjs";
1
+ import { Pt as hydrateSchema, _t as BaseAddon, gt as errMsg } from "../../dist-CuAaqtdt.mjs";
2
2
  //#region src/builtins/system-config/system-config.addon.ts
3
3
  /**
4
4
  * Built-in `system-config` addon — Phase 4 of the settings redesign.
@@ -3,7 +3,7 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_chunk = require("../../chunk-Cek0wNdY.js");
6
- const require_dist = require("../../dist-DiScsb8j.js");
6
+ const require_dist = require("../../dist-D4nuaPdd.js");
7
7
  const require_formatter = require("../../formatter-DqAKDlvN.js");
8
8
  let node_path = require("node:path");
9
9
  node_path = require_chunk.__toESM(node_path);
@@ -1,4 +1,4 @@
1
- import { J as logDestinationCapability, gt as BaseAddon } from "../../dist-DWuNENzg.mjs";
1
+ import { J as logDestinationCapability, _t as BaseAddon } from "../../dist-CuAaqtdt.mjs";
2
2
  import { t as formatLogLine } from "../../formatter-B7qW8bPJ.mjs";
3
3
  import * as path$1 from "node:path";
4
4
  import path from "node:path";