@camstack/types 1.2.142 → 1.2.144

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.
package/dist/addon.js CHANGED
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_event_category = require("./event-category-BaEgqJNv.js");
3
- const require_sleep = require("./sleep-BDmIj1HV.js");
3
+ const require_sleep = require("./sleep-jdpPltQH.js");
4
4
  const require_err_msg = require("./err-msg-COpsHMw2.js");
5
5
  //#region src/generated/cap-input-defaults.ts
6
6
  /**
package/dist/addon.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { t as EventCategory } from "./event-category-BZL-fdNj.mjs";
2
- import { B as ReadinessRegistry, E as adminUiCapability, L as nodePin, R as readNodePin, St as emitReadiness, T as DeviceType, V as ReadinessTimeoutError, W as scopeKey, _t as DisposerChain, a as asJsonObject, b as deviceOpsCapability, d as BOOT_RECOVERY_BACKOFF_MS, f as DEVICE_SCOPED_CAPS, gt as DATAPLANE_SECRET_HEADER, h as createEventBusSliceSource, j as expandCapMethods, m as createDeviceProxy, p as isDeviceScopedCap, s as asString, t as sleep, u as parseJsonUnknown, vt as BaseAddon, x as viewerUiCapability, yt as normalizeAddonInitResult } from "./sleep-Cwo3fRlv.mjs";
2
+ import { B as ReadinessRegistry, E as adminUiCapability, L as nodePin, R as readNodePin, St as emitReadiness, T as DeviceType, V as ReadinessTimeoutError, W as scopeKey, _t as DisposerChain, a as asJsonObject, b as deviceOpsCapability, d as BOOT_RECOVERY_BACKOFF_MS, f as DEVICE_SCOPED_CAPS, gt as DATAPLANE_SECRET_HEADER, h as createEventBusSliceSource, j as expandCapMethods, m as createDeviceProxy, p as isDeviceScopedCap, s as asString, t as sleep, u as parseJsonUnknown, vt as BaseAddon, x as viewerUiCapability, yt as normalizeAddonInitResult } from "./sleep-B195W080.mjs";
3
3
  import { t as errMsg } from "./err-msg-IQTHeDzc.mjs";
4
4
  //#region src/generated/cap-input-defaults.ts
5
5
  /**
@@ -349,6 +349,13 @@ export declare const deviceManagerCapability: {
349
349
  * `sourceStillLive` names what stayed live; empty is the only value that
350
350
  * means the old hardware is quiet. The migration proceeds either way —
351
351
  * refusing would refuse the case this exists for.
352
+ *
353
+ * **Safe to retry.** A duplicate call while a migration involving either
354
+ * device is in flight is REFUSED, never queued; a repeat of a swap that
355
+ * already completed (matched against the `addonId`/`stableId` fingerprint
356
+ * the swap left on the rows, within 15 min) is a no-op returning the
357
+ * original report. A blind re-run can no longer silently undo the
358
+ * migration it retried.
352
359
  */
353
360
  readonly migrateDevice: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
354
361
  sourceId: z.ZodNumber;
@@ -1358,6 +1365,9 @@ export declare const deviceManagerCapability: {
1358
1365
  uniqueId: z.ZodOptional<z.ZodString>;
1359
1366
  raw: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1360
1367
  }, z.core.$strip>>;
1368
+ alreadyOnboarded: z.ZodOptional<z.ZodBoolean>;
1369
+ onboardedDeviceId: z.ZodOptional<z.ZodNumber>;
1370
+ onboardedName: z.ZodOptional<z.ZodString>;
1361
1371
  }, z.core.$strip>>, "mutation">;
1362
1372
  /** Adopt a discovered device via the device-provider capability. */
1363
1373
  readonly adoptDevice: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
@@ -1373,6 +1383,9 @@ export declare const deviceManagerCapability: {
1373
1383
  uniqueId: z.ZodOptional<z.ZodString>;
1374
1384
  raw: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1375
1385
  }, z.core.$strip>>;
1386
+ alreadyOnboarded: z.ZodOptional<z.ZodBoolean>;
1387
+ onboardedDeviceId: z.ZodOptional<z.ZodNumber>;
1388
+ onboardedName: z.ZodOptional<z.ZodString>;
1376
1389
  }, z.core.$strip>;
1377
1390
  integrationId: z.ZodOptional<z.ZodString>;
1378
1391
  }, z.core.$strip>, z.ZodObject<{
@@ -1615,6 +1628,9 @@ export declare const deviceManagerCapability: {
1615
1628
  uniqueId: z.ZodOptional<z.ZodString>;
1616
1629
  raw: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1617
1630
  }, z.core.$strip>>;
1631
+ alreadyOnboarded: z.ZodOptional<z.ZodBoolean>;
1632
+ onboardedDeviceId: z.ZodOptional<z.ZodNumber>;
1633
+ onboardedName: z.ZodOptional<z.ZodString>;
1618
1634
  }, z.core.$strip>>>;
1619
1635
  error: z.ZodNullable<z.ZodString>;
1620
1636
  }, z.core.$strip>>>;
@@ -1636,6 +1652,9 @@ export declare const deviceManagerCapability: {
1636
1652
  uniqueId: z.ZodOptional<z.ZodString>;
1637
1653
  raw: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
1638
1654
  }, z.core.$strip>>;
1655
+ alreadyOnboarded: z.ZodOptional<z.ZodBoolean>;
1656
+ onboardedDeviceId: z.ZodOptional<z.ZodNumber>;
1657
+ onboardedName: z.ZodOptional<z.ZodString>;
1639
1658
  }, z.core.$strip>>>;
1640
1659
  }, z.core.$strip>, "mutation">;
1641
1660
  /** The device type a provider creates via manual add (Camera/Container/Hub),
@@ -28,6 +28,9 @@ declare const DiscoveryCandidateSchema: z.ZodObject<{
28
28
  uniqueId: z.ZodOptional<z.ZodString>;
29
29
  raw: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
30
30
  }, z.core.$strip>>;
31
+ alreadyOnboarded: z.ZodOptional<z.ZodBoolean>;
32
+ onboardedDeviceId: z.ZodOptional<z.ZodNumber>;
33
+ onboardedName: z.ZodOptional<z.ZodString>;
31
34
  }, z.core.$strip>;
32
35
  /**
33
36
  * Flat device summary returned by `createDevice` / `adoptDiscoveredDevice`.
@@ -82,6 +85,36 @@ export declare const deviceProviderCapability: {
82
85
  name: z.ZodString;
83
86
  type: z.ZodString;
84
87
  }, z.core.$strip>>, import("./capability-definition.js").CapabilityMethodKind>;
88
+ /**
89
+ * Tear down and reconstruct ONE device in place from its persisted rows —
90
+ * touching no other device this provider owns.
91
+ *
92
+ * The primitive `deviceManager.migrateDevice` uses to flush the two
93
+ * migrated numbers: after `swapIds` the runner's live instance still
94
+ * carries the PRE-swap numeric id (baked into the object, its native-cap
95
+ * registrations and its log tags), and a live object cannot be renumbered.
96
+ * Before this method the only flush was restarting the whole owning addon
97
+ * — which took every camera the provider owns down with it (28 devices
98
+ * for one migrated camera, measured 2026-09-04, and the morning of the
99
+ * same day ~27 devices' native caps did not come back on their own).
100
+ *
101
+ * Keyed by `stableId`, deliberately: the numeric id is exactly the thing
102
+ * that changes. The reply carries the id the device answers on NOW.
103
+ * Implemented once in `BaseDeviceProvider` — decommission the live
104
+ * instance (if any), then re-create from the persisted row: the same
105
+ * teardown/rehydrate pair every graceful shutdown + boot already uses.
106
+ * An RPC, never an event: a dropped event would leave the runner writing
107
+ * against the wrong camera (D8).
108
+ *
109
+ * Construction can dial hardware, and the migrated source is
110
+ * characteristically dead — the timeout covers a full activate window
111
+ * rather than the 60 s default.
112
+ */
113
+ readonly reloadDevice: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{
114
+ stableId: z.ZodString;
115
+ }, z.core.$strip>, z.ZodObject<{
116
+ deviceId: z.ZodNumber;
117
+ }, z.core.$strip>, "mutation">;
85
118
  readonly supportsDiscovery: import("./capability-definition.js").CapabilityMethodSchema<z.ZodObject<{}, z.core.$strip>, z.ZodBoolean, import("./capability-definition.js").CapabilityMethodKind>;
86
119
  /**
87
120
  * Run a network scan. `params` carries optional provider-specific scan
@@ -102,6 +135,9 @@ export declare const deviceProviderCapability: {
102
135
  uniqueId: z.ZodOptional<z.ZodString>;
103
136
  raw: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
104
137
  }, z.core.$strip>>;
138
+ alreadyOnboarded: z.ZodOptional<z.ZodBoolean>;
139
+ onboardedDeviceId: z.ZodOptional<z.ZodNumber>;
140
+ onboardedName: z.ZodOptional<z.ZodString>;
105
141
  }, z.core.$strip>>, "mutation">;
106
142
  /**
107
143
  * Optional form schema (`ConfigUISchema`) for the EXTRA per-scan inputs a
@@ -131,6 +167,9 @@ export declare const deviceProviderCapability: {
131
167
  uniqueId: z.ZodOptional<z.ZodString>;
132
168
  raw: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
133
169
  }, z.core.$strip>>;
170
+ alreadyOnboarded: z.ZodOptional<z.ZodBoolean>;
171
+ onboardedDeviceId: z.ZodOptional<z.ZodNumber>;
172
+ onboardedName: z.ZodOptional<z.ZodString>;
134
173
  }, z.core.$strip>;
135
174
  }, z.core.$strip>, z.ZodObject<{
136
175
  id: z.ZodNumber;
@@ -4,6 +4,7 @@ import type { ConfigUISchema } from '../interfaces/config-ui.js';
4
4
  import type { IDevice } from './device.js';
5
5
  import type { DeviceConstructor } from './device-context.js';
6
6
  import type { CreateDeviceSpec, SavedDevice } from './device-management.js';
7
+ import type { PermanentRestoreFailure } from './device-restore-retry.js';
7
8
  import { DeviceType } from './device-type.js';
8
9
  import type { SourceInfo } from './source-info.js';
9
10
  export interface DiscoveryCandidate {
@@ -16,6 +17,16 @@ export interface DiscoveryCandidate {
16
17
  * knows the upstream identity ahead of adoption (HA: entity_id +
17
18
  * unit + device_class from `GET /api/states`). */
18
19
  readonly sourceInfo?: SourceInfo;
20
+ /** Set when the provider recognises this candidate as a device it ALREADY
21
+ * owns. A scan usually cannot reproduce the identity a device was onboarded
22
+ * under, so a stableId comparison never matches and an owned device looks
23
+ * addable — re-adopting it overwrites its config with scan-derived values.
24
+ * Absent means "not recognised", NOT "known to be new". */
25
+ readonly alreadyOnboarded?: boolean;
26
+ /** Numeric id of the device this candidate was matched to. Set with `alreadyOnboarded`. */
27
+ readonly onboardedDeviceId?: number;
28
+ /** Operator-facing name of the matched device, so the UI can say WHICH one it is. */
29
+ readonly onboardedName?: string;
19
30
  }
20
31
  export interface DeviceSummary {
21
32
  readonly id: number;
@@ -38,6 +49,19 @@ export interface ProviderStatus {
38
49
  readonly deviceCount: number;
39
50
  readonly error?: string;
40
51
  }
52
+ /**
53
+ * Outcome of an `onRestoreDevices` pass. Optional for back-compat:
54
+ * providers with custom overrides may keep returning `void` — they
55
+ * just don't get the accurate summary log (or the bounded retry the
56
+ * default implementation wires up, see D347).
57
+ */
58
+ export interface DeviceRestoreReport {
59
+ /** Rows registered during the initial pass. */
60
+ readonly restoredCount: number;
61
+ /** Rows that failed the initial pass and were handed to the bounded
62
+ * background retry. */
63
+ readonly failedCount: number;
64
+ }
41
65
  export interface FieldProbeResult {
42
66
  readonly status: 'ok' | 'error';
43
67
  readonly labels?: readonly string[];
@@ -147,6 +171,52 @@ export declare abstract class BaseDeviceProvider<TConfig extends object = Record
147
171
  formValues?: Record<string, unknown>;
148
172
  }): Promise<FieldProbeResult>;
149
173
  restoreDevices(savedDevices: readonly SavedDevice[]): Promise<void>;
174
+ /** Retry schedule. Overridable (tests use millisecond delays). */
175
+ protected readonly restoreRetryDelaysMs: readonly number[];
176
+ /** Retry lane width. See `device-restore-retry.ts` for why retries
177
+ * never re-stampede full-width while the initial pass does (D167). */
178
+ protected readonly restoreRetryConcurrency: number;
179
+ private _restoreRetryScheduler;
180
+ private _restoreRetryCompletion;
181
+ private readonly _permanentRestoreFailures;
182
+ /** Settles when the background retry rounds finish (or `null` when
183
+ * nothing failed). Exposed for tests and subclass diagnostics —
184
+ * boot NEVER awaits this: the runner's post-init handshake goes out
185
+ * with the devices that restored, and a late success is announced
186
+ * through the `native-cap-change` → `updateCaps` path. */
187
+ protected get restoreRetryCompletion(): Promise<void> | null;
188
+ /** Devices that exhausted the retry bound this process lifetime. */
189
+ protected get permanentRestoreFailures(): readonly PermanentRestoreFailure[];
190
+ /** One-line operator-facing summary for `getStatus().error`, or
191
+ * `null` when every device restored. */
192
+ protected restoreFailureSummary(): string | null;
193
+ private cancelRestoreRetries;
194
+ private recordPermanentRestoreFailure;
195
+ private scheduleRestoreRetries;
196
+ /**
197
+ * Tear down and reconstruct ONE device from its persisted rows — the
198
+ * `deviceProvider.reloadDevice` cap method. Persistence is never touched,
199
+ * and no other device this provider owns is disturbed.
200
+ *
201
+ * Keyed by `stableId` because the caller's whole reason to be here is that
202
+ * the NUMERIC id changed (`deviceManager.migrateDevice` swapped it): the
203
+ * fresh instance resolves its id through `allocateDeviceId`, which returns
204
+ * whatever number the row carries NOW. The teardown is `decommission` —
205
+ * exactly what a graceful shutdown runs per device (fires `removeDevice()`,
206
+ * unregisters native caps, drops the registry entry) — and the rebuild is
207
+ * the boot restore's own `create()` path, including its pass 2: first-class
208
+ * children (hub-adopted cameras under an NVR) are decommissioned with the
209
+ * parent by the cascade and must be re-created explicitly, because only
210
+ * accessory children come back through `getAccessoryChildren()`.
211
+ *
212
+ * Reloading an accessory child directly is refused (no device class) —
213
+ * reload its parent instead.
214
+ */
215
+ reloadDevice(input: {
216
+ stableId: string;
217
+ }): Promise<{
218
+ deviceId: number;
219
+ }>;
150
220
  /**
151
221
  * Concrete device classes this provider can spawn, keyed by
152
222
  * `DeviceType`. Used by:
@@ -196,8 +266,30 @@ export declare abstract class BaseDeviceProvider<TConfig extends object = Record
196
266
  * accessory-spawn flow handles via the parent's
197
267
  * `getAccessoryChildren()`. Override only when the default doesn't
198
268
  * fit.
269
+ *
270
+ * A row that fails either pass is NOT terminal (D347): it is handed
271
+ * to a bounded background retry (`DeviceRestoreRetryScheduler`).
272
+ * Only after the bound is exhausted is the device marked permanently
273
+ * failed — logged at ERROR with `tags.deviceId` and surfaced via
274
+ * `getStatus().error`.
275
+ */
276
+ /**
277
+ * Repair a row's PERSISTED config blob immediately before it is restored.
278
+ * Default: no-op — most providers have nothing to heal.
279
+ *
280
+ * This exists because a restored device self-hydrates from the DB: `create()`
281
+ * passes `{}` and `BaseDevice` parses the stored blob against the device
282
+ * schema. A blob that lost a REQUIRED field therefore fails restore forever,
283
+ * and no later pass revisits it — a hub-adopted Reolink camera whose blob had
284
+ * been emptied failed all four bounded attempts against fields
285
+ * (`host`, `password`) it inherits from its parent and never dials itself.
286
+ *
287
+ * Implementations get every saved row, so a child can read its parent's blob.
288
+ * A heal that throws is treated like any other restore failure: retried under
289
+ * the bound, then reported — never swallowed.
199
290
  */
200
- protected onRestoreDevices(savedDevices: readonly SavedDevice[]): Promise<void>;
291
+ protected healSavedConfig(_saved: SavedDevice, _allSaved: readonly SavedDevice[]): Promise<void>;
292
+ protected onRestoreDevices(savedDevices: readonly SavedDevice[]): Promise<DeviceRestoreReport | void>;
201
293
  /** Convert an IDevice to the flat DeviceSummary for the cap router. */
202
294
  protected toSummary(device: IDevice): DeviceSummary;
203
295
  }
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Bounded retry for failed per-device boot restores (D347).
3
+ *
4
+ * WHY: a provider runner's boot restore is a full-width fan-out of
5
+ * independent `kernel.devices.create()` dials (D167). When the hub is
6
+ * briefly busy (a migration holding device-manager, a starved event
7
+ * loop) whole batches of those dials time out together at the UDS
8
+ * transport's 60 s default — and until D347 a failed restore was
9
+ * TERMINAL: the device's native caps never entered the worker map,
10
+ * `updateCaps` never announced them, and every route answered
11
+ * "binding not yet in LocalChildRegistry" for the life of the process.
12
+ * 27 cameras were off the air for 20 minutes on 2026-09-04 because of
13
+ * exactly this; the devices were healthy and merely lost a race.
14
+ *
15
+ * The scheduler distinguishes "not yet" from "never":
16
+ * - **not yet** — a bounded number of retries with growing delays
17
+ * (`DEVICE_RESTORE_RETRY_DELAYS_MS`). A retry that succeeds flows
18
+ * through the runner's `native-cap-change` listener, so the
19
+ * device's caps are announced via `updateCaps` even though the
20
+ * post-init handshake has long passed.
21
+ * - **never** — after the last round the device is handed to
22
+ * `onPermanentFailure` with its attempt count and last error, and
23
+ * nothing retries it again (CrashSupervisor's discipline, D6:
24
+ * bounded, then terminally failed and VISIBLE — the provider
25
+ * surfaces it via `getStatus().error` and an ERROR log tagged
26
+ * `deviceId`).
27
+ *
28
+ * Retry width is bounded (`DEVICE_RESTORE_RETRY_CONCURRENCY`): the
29
+ * devices being retried already failed TOGETHER, which is evidence of
30
+ * hub congestion — re-stampeding the full set recreates the collision.
31
+ * The INITIAL fan-out stays full-width (D167 measured a lane cap
32
+ * costing 6.5 min on a healthy boot); only the retry lanes are capped,
33
+ * so a large fleet's happy-path boot is byte-for-byte unchanged.
34
+ *
35
+ * Cancellation (`cancel()`) is for shutdown: pending entries are NOT
36
+ * marked permanently failed — the process is going away and the next
37
+ * boot re-runs the restore from the persisted rows.
38
+ */
39
+ import type { IScopedLogger } from '../interfaces/logging.js';
40
+ import type { SavedDevice } from './device-management.js';
41
+ /**
42
+ * Delays before retry rounds 1..N — the round count IS the bound.
43
+ * 10 s catches "the hub was busy for a moment"; the full schedule
44
+ * (10 + 30 + 90 s of waiting, plus up to one 60 s transport timeout
45
+ * per attempt) covers a device-manager lock held for minutes — the
46
+ * 2026-09-04 outage's migration hold was ~3.5 min.
47
+ */
48
+ export declare const DEVICE_RESTORE_RETRY_DELAYS_MS: readonly number[];
49
+ /** Lane width for retry rounds. See module docblock — retries are
50
+ * evidence of congestion, so they never re-stampede full-width. */
51
+ export declare const DEVICE_RESTORE_RETRY_CONCURRENCY = 4;
52
+ /** One device that failed its initial restore attempt. */
53
+ export interface InitialRestoreFailure {
54
+ readonly saved: SavedDevice;
55
+ readonly error: string;
56
+ }
57
+ /** A device that exhausted the retry bound. Kept by the provider for
58
+ * the life of the process and surfaced via `getStatus().error`. */
59
+ export interface PermanentRestoreFailure {
60
+ readonly deviceId: number;
61
+ readonly stableId: string;
62
+ readonly type: string;
63
+ /** Total attempts made, including the initial restore. */
64
+ readonly attempts: number;
65
+ readonly lastError: string;
66
+ /** Epoch ms of the final failed attempt. */
67
+ readonly failedAt: number;
68
+ }
69
+ /** Attempts one device restore. Throws on failure; resolving means the
70
+ * device is registered (or already was). */
71
+ export type RestoreAttemptFn = (saved: SavedDevice) => Promise<void>;
72
+ export type PermanentRestoreFailureHandler = (failure: PermanentRestoreFailure) => void;
73
+ export interface DeviceRestoreRetrySchedulerOptions {
74
+ readonly logger: IScopedLogger;
75
+ readonly attempt: RestoreAttemptFn;
76
+ readonly onPermanentFailure: PermanentRestoreFailureHandler;
77
+ readonly delaysMs?: readonly number[];
78
+ readonly concurrency?: number;
79
+ readonly now?: () => number;
80
+ }
81
+ export declare class DeviceRestoreRetryScheduler {
82
+ #private;
83
+ constructor(options: DeviceRestoreRetrySchedulerOptions);
84
+ /** Stop retrying (shutdown). Pending entries are NOT marked
85
+ * permanently failed — the next boot restores them from disk. */
86
+ cancel(): void;
87
+ /**
88
+ * Run the bounded retry rounds. Resolves when every entry has either
89
+ * restored, been marked permanently failed, or the scheduler was
90
+ * cancelled. Never rejects.
91
+ */
92
+ run(initialFailures: readonly InitialRestoreFailure[]): Promise<readonly PermanentRestoreFailure[]>;
93
+ }
@@ -1,8 +1,10 @@
1
1
  export { ACCESSORY_LABEL, AccessoryKind, type AccessoryKindValue, accessoryStableId, } from './accessory.js';
2
2
  export type { AccessoryChildSpec } from './base-device.js';
3
3
  export { BaseDevice } from './base-device.js';
4
- export type { DeviceSummary, DiscoveryCandidate, FieldProbeResult, ProviderStatus, } from './base-device-provider.js';
4
+ export type { DeviceRestoreReport, DeviceSummary, DiscoveryCandidate, FieldProbeResult, ProviderStatus, } from './base-device-provider.js';
5
5
  export { BaseDeviceProvider, toDeviceSummary } from './base-device-provider.js';
6
+ export type { DeviceRestoreRetrySchedulerOptions, InitialRestoreFailure, PermanentRestoreFailure, PermanentRestoreFailureHandler, RestoreAttemptFn, } from './device-restore-retry.js';
7
+ export { DEVICE_RESTORE_RETRY_CONCURRENCY, DEVICE_RESTORE_RETRY_DELAYS_MS, DeviceRestoreRetryScheduler, } from './device-restore-retry.js';
6
8
  export type { ICameraDevice, StreamSourceEntry } from './camera-device.js';
7
9
  export type { DeclarationPlacement, DeclaredDeviceOutcome, DeclaredDevicePorts, DeclaredDeviceRow, DeclaredDevicesResult, DeclaredDevicesSpec, DeclaredIntegrationRow, DeviceDeclaration, } from './declared-device.js';
8
10
  export { DECLARED_DEVICE_SWEEP_LIMIT, DECLARED_INTEGRATION_FIXED_KEY, DeclaredDevices, declarationOwnerNodeId, } from './declared-device.js';
@@ -2695,6 +2695,13 @@ export type AppRouter = TrpcCoreRouter<{
2695
2695
  output: z.infer<typeof deviceProviderCapability.methods.getDevices.output>;
2696
2696
  meta: object;
2697
2697
  }>;
2698
+ reloadDevice: TRPCMutationProcedure<{
2699
+ input: {
2700
+ [x: string]: unknown;
2701
+ } & z.input<typeof deviceProviderCapability.methods.reloadDevice.input>;
2702
+ output: z.infer<typeof deviceProviderCapability.methods.reloadDevice.output>;
2703
+ meta: object;
2704
+ }>;
2698
2705
  supportsDiscovery: TRPCQueryProcedure<{
2699
2706
  input: {
2700
2707
  [x: string]: unknown;
@@ -87,6 +87,7 @@ import type { cameraPipelineConfigCapability } from '../capabilities/camera-pipe
87
87
  import type { deviceAdoptionCapability } from '../capabilities/device-adoption.cap.js';
88
88
  import type { deviceExportCapability } from '../capabilities/device-export.cap.js';
89
89
  import type { deviceManagerCapability } from '../capabilities/device-manager.cap.js';
90
+ import type { deviceProviderCapability } from '../capabilities/device-provider.cap.js';
90
91
  import type { deviceStateCapability } from '../capabilities/device-state.cap.js';
91
92
  import type { faceGalleryCapability } from '../capabilities/face-gallery.cap.js';
92
93
  import type { networkQualityCapability } from '../capabilities/network-quality.cap.js';
@@ -272,6 +273,7 @@ export interface DeviceProxy {
272
273
  readonly deviceAdoption: Pick<InferDeviceProxyCap<typeof deviceAdoptionCapability>, 'getStatus'>;
273
274
  readonly deviceExport: Pick<InferDeviceProxyCap<typeof deviceExportCapability>, 'getDeviceSettingsContribution' | 'getDeviceLiveContribution' | 'applyDeviceSettingsPatch'>;
274
275
  readonly deviceManager: Pick<InferDeviceProxyCap<typeof deviceManagerCapability>, 'loadConfig' | 'loadRuntimeState' | 'loadMeta' | 'setName' | 'setLocation' | 'setType' | 'setIntegrationId' | 'setLinkDeviceId' | 'setPrimaryChildEntityId' | 'setChildLayout' | 'setDisplay' | 'getWireableFields' | 'setRole' | 'applyInitialMeta' | 'setMetadata' | 'setDisabled' | 'getDevice' | 'getLinkedDevices' | 'getStreamSources' | 'getConfigSchema' | 'getSettingsSchema' | 'updateConfig' | 'enable' | 'disable' | 'remove' | 'getStreamProfileMap' | 'setStreamProfileMap' | 'probeStreams' | 'getBindings' | 'setWrapperActive' | 'getDeviceSettingsAggregate' | 'getDeviceLiveInfoAggregate' | 'getDeviceAggregate' | 'runDeviceAction' | 'updateDeviceField' | 'updateDeviceFieldsBatch' | 'testField' | 'getDeviceStatusAggregate' | 'getDeviceSettingsContribution' | 'getDeviceLiveContribution' | 'applyDeviceSettingsPatch'>;
276
+ readonly deviceProvider: Pick<InferDeviceProxyCap<typeof deviceProviderCapability>, 'reloadDevice'>;
275
277
  readonly deviceState: Pick<InferDeviceProxyCap<typeof deviceStateCapability>, 'getSnapshot' | 'getCapSlice' | 'setCapSlice'>;
276
278
  readonly faceGallery: Pick<InferDeviceProxyCap<typeof faceGalleryCapability>, 'listRecentFaces' | 'getFaceByTrack'>;
277
279
  readonly networkQuality: Pick<InferDeviceProxyCap<typeof networkQualityCapability>, 'getDeviceStats' | 'reportClientStats'>;
@@ -6,7 +6,7 @@
6
6
  * scope+access check inside `protectedProcedure` (see
7
7
  * `server/backend/src/api/trpc/trpc.middleware.ts`).
8
8
  *
9
- * Coverage: 1005 method paths across 126 capabilities.
9
+ * Coverage: 1006 method paths across 126 capabilities.
10
10
  */
11
11
  import type { CapabilityMethodAccess } from '../capabilities/capability-definition.js';
12
12
  export interface MethodAccessRecord {
package/dist/index.d.ts CHANGED
@@ -141,8 +141,10 @@ export type { AccessoryKindValue } from './device/accessory.js';
141
141
  export { ACCESSORY_LABEL, AccessoryKind, accessoryStableId, } from './device/accessory.js';
142
142
  export type { AccessoryChildSpec } from './device/base-device.js';
143
143
  export { BaseDevice } from './device/base-device.js';
144
- export type { DeviceSummary, DiscoveryCandidate, FieldProbeResult, } from './device/base-device-provider.js';
144
+ export type { DeviceRestoreReport, DeviceSummary, DiscoveryCandidate, FieldProbeResult, } from './device/base-device-provider.js';
145
145
  export { BaseDeviceProvider, toDeviceSummary } from './device/base-device-provider.js';
146
+ export type { DeviceRestoreRetrySchedulerOptions, InitialRestoreFailure, PermanentRestoreFailure, PermanentRestoreFailureHandler, RestoreAttemptFn, } from './device/device-restore-retry.js';
147
+ export { DEVICE_RESTORE_RETRY_CONCURRENCY, DEVICE_RESTORE_RETRY_DELAYS_MS, DeviceRestoreRetryScheduler, } from './device/device-restore-retry.js';
146
148
  export type { BatteryPresence, BatteryPresenceInput } from './device/battery-presence.js';
147
149
  export { BATTERY_UNREACHABLE_AFTER_MS, deriveBatteryPresence, isBatteryPresenceFault, } from './device/battery-presence.js';
148
150
  export type { ICameraDevice, StreamSourceEntry } from './device/camera-device.js';