@camstack/addon-remote-storage 1.2.69 → 1.2.70

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/s3.addon.js CHANGED
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_shared = require("./shared-wJVLo41v.js");
5
+ const require_shared = require("./shared-DiZPvkCY.js");
6
6
  let node_stream = require("node:stream");
7
7
  let _aws_sdk_client_s3 = require("@aws-sdk/client-s3");
8
8
  let _aws_sdk_lib_storage = require("@aws-sdk/lib-storage");
package/dist/s3.addon.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { c as BaseAddon, i as rearmIdleAbort, n as getOptionalBasePath, o as scheduleIdleAbort, s as storageProviderCapability, t as createSessionId } from "./shared-C1oHNHV8.mjs";
1
+ import { c as BaseAddon, i as rearmIdleAbort, n as getOptionalBasePath, o as scheduleIdleAbort, s as storageProviderCapability, t as createSessionId } from "./shared-Dg4Fpj1Q.mjs";
2
2
  import { PassThrough } from "node:stream";
3
3
  import { DeleteObjectCommand, GetObjectCommand, HeadBucketCommand, HeadObjectCommand, ListObjectsV2Command, PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
4
4
  import { Upload } from "@aws-sdk/lib-storage";
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_shared = require("./shared-wJVLo41v.js");
5
+ const require_shared = require("./shared-DiZPvkCY.js");
6
6
  let ssh2 = require("ssh2");
7
7
  let node_path = require("node:path");
8
8
  node_path = require_shared.__toESM(node_path);
@@ -1,4 +1,4 @@
1
- import { a as safeJoinRemotePath, c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, r as getRequiredBasePath, s as storageProviderCapability, t as createSessionId } from "./shared-C1oHNHV8.mjs";
1
+ import { a as safeJoinRemotePath, c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, r as getRequiredBasePath, s as storageProviderCapability, t as createSessionId } from "./shared-Dg4Fpj1Q.mjs";
2
2
  import { Client } from "ssh2";
3
3
  import * as path from "node:path";
4
4
  //#region src/providers/sftp/sftp-config-schema.ts
@@ -26860,6 +26860,203 @@ DeviceType.Camera, method(object({ deviceId: number() }), PtzAutotrackStatusSche
26860
26860
  deviceId: number(),
26861
26861
  status: PtzAutotrackStatusSchema
26862
26862
  });
26863
+ /**
26864
+ * `navigation` — a device-scoped capability that natively expresses the FULL
26865
+ * navigation / action surface of a robot that DRIVES ITSELF and carries an
26866
+ * on-board camera (the Dreame robot-vacuum camera is the first provider).
26867
+ *
26868
+ * Why a NEW cap rather than overloading `ptz`:
26869
+ * - `ptz` moves a *gimbal* on a fixed camera (pan/tilt/zoom of the lens). A
26870
+ * robot vacuum has no gimbal — the whole chassis drives, turns and spins.
26871
+ * The two are different physical models: PTZ is absolute-position + presets,
26872
+ * navigation is momentary drive nudges + discrete robot ACTIONS
26873
+ * (dock / spot-clean / follow-pet / go-to-point / …).
26874
+ * - This cap is the SOURCE OF TRUTH. Two consumers adapt from it rather than
26875
+ * the reverse:
26876
+ * 1. a native CamStack navigation panel (data-driven from `listActions`
26877
+ * / `getOptions`), and
26878
+ * 2. the PTZ surface — a thin adapter mimics `ptz` from `navigation` so a
26879
+ * robot camera shows up in the existing PTZ control path without every
26880
+ * PTZ provider learning about robots. The mapping lives in the adapter,
26881
+ * not here (see the addon design note):
26882
+ * ptz.continuousMove({pan,tilt}) → navigation.move({pan,tilt})
26883
+ * ptz.stop() → navigation.stop()
26884
+ * ptz.goHome() → navigation.runAction('goHome')
26885
+ * ptz.getPresets() → navigation.listActions() (id→preset)
26886
+ * ptz.goToPreset(id) → navigation.runAction(id)
26887
+ *
26888
+ * ## Continuous drive
26889
+ *
26890
+ * `move` is MOMENTARY. Fluid navigation comes from the UI (or the PTZ adapter)
26891
+ * sending `move({pan,tilt})` REPEATEDLY at ~1 Hz while a direction is held, and
26892
+ * one `stop()` on release — exactly like the robot app's remote-drive joystick.
26893
+ * The provider forwards EACH `move` to one drive write; it must NOT debounce or
26894
+ * coalesce them. The UI owns the cadence.
26895
+ *
26896
+ * ## The action dictionary
26897
+ *
26898
+ * The discrete controls (dock / locate / spot-clean / follow / flash / sounds)
26899
+ * are a DATA-DRIVEN dictionary the cap exposes via `listActions()`. Each entry
26900
+ * carries `{ id, kind, label, icon }` (plus `soundId` for sound entries) so the
26901
+ * native panel AND the PTZ mimic render buttons WITHOUT hardcoding a
26902
+ * vendor-specific list. `kind: 'action'` entries are triggered with
26903
+ * `runAction({ actionId })`; `kind: 'sound'` entries with `playSound({ soundId })`
26904
+ * (the entry carries the `soundId` to pass). The general primitives — `move`,
26905
+ * `stop`, `goToPoint` — stay as first-class methods, not dictionary entries.
26906
+ *
26907
+ * NOTE (provider wiring): the first provider (Dreame) drives this with the RAW
26908
+ * `callAction(siid,aiid,in)` / `setProperty({siid,piid,value})` MIoT primitives
26909
+ * that the currently-published `@apocaliss92/nodedreame` already exposes on
26910
+ * every device handle. A future nodedreame publish adds a typed
26911
+ * `DreameCameraController` (drive / playPetSound / spotClean / findPet / …); the
26912
+ * provider can then swap the raw calls for the typed methods with no change to
26913
+ * THIS contract.
26914
+ */
26915
+ /**
26916
+ * A momentary drive nudge. The robot MOVES (no gimbal) for as long as the caller
26917
+ * keeps sending nudges (~1 Hz); an explicit `stop` (or letting the nudges lapse)
26918
+ * halts it.
26919
+ *
26920
+ * - `pan` — turn: negative = left, positive = right, 0 = straight.
26921
+ * - `tilt` — throttle: positive = forward, negative = spin / turn-around.
26922
+ * - `speed` — optional intensity hint [0, 1]; the provider may scale the drive
26923
+ * vector by it (drivers without proportional drive ignore it).
26924
+ *
26925
+ * `pan` / `tilt` are normalized [-1, 1]. Both optional so a caller can nudge one
26926
+ * axis alone; an all-undefined nudge is a no-op.
26927
+ */
26928
+ var NavigationMoveCommandSchema = object({
26929
+ pan: number().min(-1).max(1).optional(),
26930
+ tilt: number().min(-1).max(1).optional(),
26931
+ speed: number().min(0).max(1).optional()
26932
+ });
26933
+ /**
26934
+ * The enumerated discrete actions a navigation-capable robot can perform via
26935
+ * `runAction`. This is the CLOSED vocabulary; a given device advertises the
26936
+ * subset it supports through `listActions`. Sounds are NOT here — they go through
26937
+ * `playSound` (see the `sound` dictionary entries).
26938
+ */
26939
+ var NavigationActionIdSchema = _enum([
26940
+ "goHome",
26941
+ "locate",
26942
+ "spotClean",
26943
+ "findPet",
26944
+ "personFollow",
26945
+ "stop",
26946
+ "startClean",
26947
+ "pauseClean",
26948
+ "dockWash",
26949
+ "autoEmpty",
26950
+ "flashOn",
26951
+ "flashOff"
26952
+ ]);
26953
+ /** Whether a dictionary entry is a `runAction` action or a `playSound` sound. */
26954
+ var NavigationEntryKindSchema = _enum(["action", "sound"]);
26955
+ /**
26956
+ * One entry in the navigation action dictionary — the DATA-DRIVEN unit both the
26957
+ * native panel and the PTZ mimic render as a button.
26958
+ *
26959
+ * - `id` — stable id. For `kind:'action'` it is a {@link NavigationActionId}
26960
+ * (pass to `runAction`); for `kind:'sound'` it is a namespaced id
26961
+ * (`sound:meow`) whose `soundId` is passed to `playSound`.
26962
+ * - `icon` — icon HINT (lucide-style name; the UI maps it to its own set).
26963
+ * - `label` — operator-facing English label.
26964
+ * - `soundId` — wire sound id, present only on `kind:'sound'` entries.
26965
+ * - `enabled` — per-device FEATURE FLAG. `listActions` reports it so the UI /
26966
+ * PTZ render ONLY enabled entries. Data-driven: the provider
26967
+ * flips it from config, never by editing code.
26968
+ */
26969
+ var NavigationActionEntrySchema = object({
26970
+ id: string(),
26971
+ kind: NavigationEntryKindSchema,
26972
+ label: string(),
26973
+ icon: string(),
26974
+ /** Present only on `kind:'sound'` entries — the id to pass to `playSound`. */
26975
+ soundId: number().int().optional(),
26976
+ /** Per-device feature flag — render this entry only when true. */
26977
+ enabled: boolean()
26978
+ });
26979
+ /** Coordinates for `goToPoint` — a point on the robot's live map. */
26980
+ var NavigationPointSchema = object({
26981
+ x: number(),
26982
+ y: number()
26983
+ });
26984
+ /**
26985
+ * Per-device FEATURE-FLAG report for the general (non-dictionary) primitives.
26986
+ * The cap reports which are enabled so the UI / PTZ render only the controls
26987
+ * that are turned on for THIS device. Data-driven: the provider derives these
26988
+ * from config + probe, never hardcoded in the UI. The per-DICTIONARY-entry flags
26989
+ * live on {@link NavigationActionEntrySchema.enabled}; these gate the primitives
26990
+ * that are not dictionary entries.
26991
+ *
26992
+ * - `move` / `stop` — the momentary drive joystick.
26993
+ * - `goToPoint` — send-to-map-coordinate. Ships OFF on Dreame until the
26994
+ * map-coordinate plumbing is wired.
26995
+ * - `runAction` — the discrete action buttons (dictionary `kind:'action'`).
26996
+ * - `playSound` — the sound buttons (dictionary `kind:'sound'`).
26997
+ * - `light` — the on/off fill-light toggle (works anytime).
26998
+ * - `lightMode` — the auto/manual selector + manual level slider (a
26999
+ * camera-service control; needs an active stream).
27000
+ */
27001
+ var NavigationFeaturesSchema = object({
27002
+ move: boolean(),
27003
+ stop: boolean(),
27004
+ goToPoint: boolean(),
27005
+ runAction: boolean(),
27006
+ playSound: boolean(),
27007
+ light: boolean(),
27008
+ lightMode: boolean()
27009
+ });
27010
+ /** Light mode: `auto` lets the camera choose brightness; `manual` uses `level`. */
27011
+ var NavigationLightModeSchema = _enum(["auto", "manual"]);
27012
+ /**
27013
+ * Live navigation state so the UI can reflect what the robot is doing:
27014
+ * - `mode` — coarse activity (idle / cleaning / following / …).
27015
+ * - `following` — person/pet follow is currently armed.
27016
+ * - `flash` — the on-camera fill light is on.
27017
+ * - `lightMode` — auto vs manual fill-light mode.
27018
+ * - `lightLevel` — manual fill-light level (40..100); meaningful when
27019
+ * `lightMode === 'manual'`.
27020
+ */
27021
+ var NavigationStatusSchema = object({
27022
+ mode: _enum([
27023
+ "idle",
27024
+ "cleaning",
27025
+ "spot",
27026
+ "following",
27027
+ "goto",
27028
+ "returning",
27029
+ "paused",
27030
+ "unknown"
27031
+ ]),
27032
+ following: boolean(),
27033
+ flash: boolean(),
27034
+ lightMode: NavigationLightModeSchema,
27035
+ lightLevel: number().min(40).max(100),
27036
+ /** Ms epoch when the slice was last updated. */
27037
+ lastChangedAt: number()
27038
+ });
27039
+ NavigationStatusSchema.extend({ lastFetchedAt: number() });
27040
+ DeviceType.Camera, method(NavigationMoveCommandSchema.extend({ deviceId: number() }), _void(), { kind: "mutation" }), method(object({ deviceId: number() }), _void(), { kind: "mutation" }), method(NavigationPointSchema.extend({ deviceId: number() }), _void(), { kind: "mutation" }), method(object({ deviceId: number() }), array(NavigationActionEntrySchema)), method(object({
27041
+ deviceId: number(),
27042
+ actionId: NavigationActionIdSchema
27043
+ }), _void(), { kind: "mutation" }), method(object({
27044
+ deviceId: number(),
27045
+ soundId: number().int()
27046
+ }), _void(), { kind: "mutation" }), method(object({
27047
+ deviceId: number(),
27048
+ on: boolean()
27049
+ }), _void(), { kind: "mutation" }), method(object({
27050
+ deviceId: number(),
27051
+ mode: NavigationLightModeSchema,
27052
+ level: number().min(40).max(100).optional()
27053
+ }), _void(), { kind: "mutation" }), method(object({
27054
+ deviceId: number(),
27055
+ level: number().min(40).max(100)
27056
+ }), _void(), { kind: "mutation" }), method(object({ deviceId: number() }), NavigationFeaturesSchema), object({
27057
+ deviceId: number(),
27058
+ status: NavigationStatusSchema
27059
+ });
26863
27060
  DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceId: number().int().nonnegative() }), object({ success: literal(true) }), {
26864
27061
  kind: "mutation",
26865
27062
  auth: "admin"
@@ -31924,6 +32121,66 @@ Object.freeze({
31924
32121
  addonId: null,
31925
32122
  access: "create"
31926
32123
  },
32124
+ "navigation.getFeatures": {
32125
+ capName: "navigation",
32126
+ capScope: "device",
32127
+ addonId: null,
32128
+ access: "view"
32129
+ },
32130
+ "navigation.goToPoint": {
32131
+ capName: "navigation",
32132
+ capScope: "device",
32133
+ addonId: null,
32134
+ access: "create"
32135
+ },
32136
+ "navigation.listActions": {
32137
+ capName: "navigation",
32138
+ capScope: "device",
32139
+ addonId: null,
32140
+ access: "view"
32141
+ },
32142
+ "navigation.move": {
32143
+ capName: "navigation",
32144
+ capScope: "device",
32145
+ addonId: null,
32146
+ access: "create"
32147
+ },
32148
+ "navigation.playSound": {
32149
+ capName: "navigation",
32150
+ capScope: "device",
32151
+ addonId: null,
32152
+ access: "create"
32153
+ },
32154
+ "navigation.runAction": {
32155
+ capName: "navigation",
32156
+ capScope: "device",
32157
+ addonId: null,
32158
+ access: "create"
32159
+ },
32160
+ "navigation.setLightLevel": {
32161
+ capName: "navigation",
32162
+ capScope: "device",
32163
+ addonId: null,
32164
+ access: "create"
32165
+ },
32166
+ "navigation.setLightMode": {
32167
+ capName: "navigation",
32168
+ capScope: "device",
32169
+ addonId: null,
32170
+ access: "create"
32171
+ },
32172
+ "navigation.setLightOn": {
32173
+ capName: "navigation",
32174
+ capScope: "device",
32175
+ addonId: null,
32176
+ access: "create"
32177
+ },
32178
+ "navigation.stop": {
32179
+ capName: "navigation",
32180
+ capScope: "device",
32181
+ addonId: null,
32182
+ access: "create"
32183
+ },
31927
32184
  "networkAccess.getEndpoint": {
31928
32185
  capName: "network-access",
31929
32186
  capScope: "system",
@@ -36019,6 +36276,56 @@ Object.freeze({
36019
36276
  form: "single",
36020
36277
  optional: false
36021
36278
  }],
36279
+ "navigation.getFeatures": [{
36280
+ name: "deviceId",
36281
+ form: "single",
36282
+ optional: false
36283
+ }],
36284
+ "navigation.goToPoint": [{
36285
+ name: "deviceId",
36286
+ form: "single",
36287
+ optional: false
36288
+ }],
36289
+ "navigation.listActions": [{
36290
+ name: "deviceId",
36291
+ form: "single",
36292
+ optional: false
36293
+ }],
36294
+ "navigation.move": [{
36295
+ name: "deviceId",
36296
+ form: "single",
36297
+ optional: false
36298
+ }],
36299
+ "navigation.playSound": [{
36300
+ name: "deviceId",
36301
+ form: "single",
36302
+ optional: false
36303
+ }],
36304
+ "navigation.runAction": [{
36305
+ name: "deviceId",
36306
+ form: "single",
36307
+ optional: false
36308
+ }],
36309
+ "navigation.setLightLevel": [{
36310
+ name: "deviceId",
36311
+ form: "single",
36312
+ optional: false
36313
+ }],
36314
+ "navigation.setLightMode": [{
36315
+ name: "deviceId",
36316
+ form: "single",
36317
+ optional: false
36318
+ }],
36319
+ "navigation.setLightOn": [{
36320
+ name: "deviceId",
36321
+ form: "single",
36322
+ optional: false
36323
+ }],
36324
+ "navigation.stop": [{
36325
+ name: "deviceId",
36326
+ form: "single",
36327
+ optional: false
36328
+ }],
36022
36329
  "networkQuality.getDeviceStats": [{
36023
36330
  name: "deviceId",
36024
36331
  form: "single",
@@ -26883,6 +26883,203 @@ DeviceType.Camera, method(object({ deviceId: number() }), PtzAutotrackStatusSche
26883
26883
  deviceId: number(),
26884
26884
  status: PtzAutotrackStatusSchema
26885
26885
  });
26886
+ /**
26887
+ * `navigation` — a device-scoped capability that natively expresses the FULL
26888
+ * navigation / action surface of a robot that DRIVES ITSELF and carries an
26889
+ * on-board camera (the Dreame robot-vacuum camera is the first provider).
26890
+ *
26891
+ * Why a NEW cap rather than overloading `ptz`:
26892
+ * - `ptz` moves a *gimbal* on a fixed camera (pan/tilt/zoom of the lens). A
26893
+ * robot vacuum has no gimbal — the whole chassis drives, turns and spins.
26894
+ * The two are different physical models: PTZ is absolute-position + presets,
26895
+ * navigation is momentary drive nudges + discrete robot ACTIONS
26896
+ * (dock / spot-clean / follow-pet / go-to-point / …).
26897
+ * - This cap is the SOURCE OF TRUTH. Two consumers adapt from it rather than
26898
+ * the reverse:
26899
+ * 1. a native CamStack navigation panel (data-driven from `listActions`
26900
+ * / `getOptions`), and
26901
+ * 2. the PTZ surface — a thin adapter mimics `ptz` from `navigation` so a
26902
+ * robot camera shows up in the existing PTZ control path without every
26903
+ * PTZ provider learning about robots. The mapping lives in the adapter,
26904
+ * not here (see the addon design note):
26905
+ * ptz.continuousMove({pan,tilt}) → navigation.move({pan,tilt})
26906
+ * ptz.stop() → navigation.stop()
26907
+ * ptz.goHome() → navigation.runAction('goHome')
26908
+ * ptz.getPresets() → navigation.listActions() (id→preset)
26909
+ * ptz.goToPreset(id) → navigation.runAction(id)
26910
+ *
26911
+ * ## Continuous drive
26912
+ *
26913
+ * `move` is MOMENTARY. Fluid navigation comes from the UI (or the PTZ adapter)
26914
+ * sending `move({pan,tilt})` REPEATEDLY at ~1 Hz while a direction is held, and
26915
+ * one `stop()` on release — exactly like the robot app's remote-drive joystick.
26916
+ * The provider forwards EACH `move` to one drive write; it must NOT debounce or
26917
+ * coalesce them. The UI owns the cadence.
26918
+ *
26919
+ * ## The action dictionary
26920
+ *
26921
+ * The discrete controls (dock / locate / spot-clean / follow / flash / sounds)
26922
+ * are a DATA-DRIVEN dictionary the cap exposes via `listActions()`. Each entry
26923
+ * carries `{ id, kind, label, icon }` (plus `soundId` for sound entries) so the
26924
+ * native panel AND the PTZ mimic render buttons WITHOUT hardcoding a
26925
+ * vendor-specific list. `kind: 'action'` entries are triggered with
26926
+ * `runAction({ actionId })`; `kind: 'sound'` entries with `playSound({ soundId })`
26927
+ * (the entry carries the `soundId` to pass). The general primitives — `move`,
26928
+ * `stop`, `goToPoint` — stay as first-class methods, not dictionary entries.
26929
+ *
26930
+ * NOTE (provider wiring): the first provider (Dreame) drives this with the RAW
26931
+ * `callAction(siid,aiid,in)` / `setProperty({siid,piid,value})` MIoT primitives
26932
+ * that the currently-published `@apocaliss92/nodedreame` already exposes on
26933
+ * every device handle. A future nodedreame publish adds a typed
26934
+ * `DreameCameraController` (drive / playPetSound / spotClean / findPet / …); the
26935
+ * provider can then swap the raw calls for the typed methods with no change to
26936
+ * THIS contract.
26937
+ */
26938
+ /**
26939
+ * A momentary drive nudge. The robot MOVES (no gimbal) for as long as the caller
26940
+ * keeps sending nudges (~1 Hz); an explicit `stop` (or letting the nudges lapse)
26941
+ * halts it.
26942
+ *
26943
+ * - `pan` — turn: negative = left, positive = right, 0 = straight.
26944
+ * - `tilt` — throttle: positive = forward, negative = spin / turn-around.
26945
+ * - `speed` — optional intensity hint [0, 1]; the provider may scale the drive
26946
+ * vector by it (drivers without proportional drive ignore it).
26947
+ *
26948
+ * `pan` / `tilt` are normalized [-1, 1]. Both optional so a caller can nudge one
26949
+ * axis alone; an all-undefined nudge is a no-op.
26950
+ */
26951
+ var NavigationMoveCommandSchema = object({
26952
+ pan: number().min(-1).max(1).optional(),
26953
+ tilt: number().min(-1).max(1).optional(),
26954
+ speed: number().min(0).max(1).optional()
26955
+ });
26956
+ /**
26957
+ * The enumerated discrete actions a navigation-capable robot can perform via
26958
+ * `runAction`. This is the CLOSED vocabulary; a given device advertises the
26959
+ * subset it supports through `listActions`. Sounds are NOT here — they go through
26960
+ * `playSound` (see the `sound` dictionary entries).
26961
+ */
26962
+ var NavigationActionIdSchema = _enum([
26963
+ "goHome",
26964
+ "locate",
26965
+ "spotClean",
26966
+ "findPet",
26967
+ "personFollow",
26968
+ "stop",
26969
+ "startClean",
26970
+ "pauseClean",
26971
+ "dockWash",
26972
+ "autoEmpty",
26973
+ "flashOn",
26974
+ "flashOff"
26975
+ ]);
26976
+ /** Whether a dictionary entry is a `runAction` action or a `playSound` sound. */
26977
+ var NavigationEntryKindSchema = _enum(["action", "sound"]);
26978
+ /**
26979
+ * One entry in the navigation action dictionary — the DATA-DRIVEN unit both the
26980
+ * native panel and the PTZ mimic render as a button.
26981
+ *
26982
+ * - `id` — stable id. For `kind:'action'` it is a {@link NavigationActionId}
26983
+ * (pass to `runAction`); for `kind:'sound'` it is a namespaced id
26984
+ * (`sound:meow`) whose `soundId` is passed to `playSound`.
26985
+ * - `icon` — icon HINT (lucide-style name; the UI maps it to its own set).
26986
+ * - `label` — operator-facing English label.
26987
+ * - `soundId` — wire sound id, present only on `kind:'sound'` entries.
26988
+ * - `enabled` — per-device FEATURE FLAG. `listActions` reports it so the UI /
26989
+ * PTZ render ONLY enabled entries. Data-driven: the provider
26990
+ * flips it from config, never by editing code.
26991
+ */
26992
+ var NavigationActionEntrySchema = object({
26993
+ id: string(),
26994
+ kind: NavigationEntryKindSchema,
26995
+ label: string(),
26996
+ icon: string(),
26997
+ /** Present only on `kind:'sound'` entries — the id to pass to `playSound`. */
26998
+ soundId: number().int().optional(),
26999
+ /** Per-device feature flag — render this entry only when true. */
27000
+ enabled: boolean()
27001
+ });
27002
+ /** Coordinates for `goToPoint` — a point on the robot's live map. */
27003
+ var NavigationPointSchema = object({
27004
+ x: number(),
27005
+ y: number()
27006
+ });
27007
+ /**
27008
+ * Per-device FEATURE-FLAG report for the general (non-dictionary) primitives.
27009
+ * The cap reports which are enabled so the UI / PTZ render only the controls
27010
+ * that are turned on for THIS device. Data-driven: the provider derives these
27011
+ * from config + probe, never hardcoded in the UI. The per-DICTIONARY-entry flags
27012
+ * live on {@link NavigationActionEntrySchema.enabled}; these gate the primitives
27013
+ * that are not dictionary entries.
27014
+ *
27015
+ * - `move` / `stop` — the momentary drive joystick.
27016
+ * - `goToPoint` — send-to-map-coordinate. Ships OFF on Dreame until the
27017
+ * map-coordinate plumbing is wired.
27018
+ * - `runAction` — the discrete action buttons (dictionary `kind:'action'`).
27019
+ * - `playSound` — the sound buttons (dictionary `kind:'sound'`).
27020
+ * - `light` — the on/off fill-light toggle (works anytime).
27021
+ * - `lightMode` — the auto/manual selector + manual level slider (a
27022
+ * camera-service control; needs an active stream).
27023
+ */
27024
+ var NavigationFeaturesSchema = object({
27025
+ move: boolean(),
27026
+ stop: boolean(),
27027
+ goToPoint: boolean(),
27028
+ runAction: boolean(),
27029
+ playSound: boolean(),
27030
+ light: boolean(),
27031
+ lightMode: boolean()
27032
+ });
27033
+ /** Light mode: `auto` lets the camera choose brightness; `manual` uses `level`. */
27034
+ var NavigationLightModeSchema = _enum(["auto", "manual"]);
27035
+ /**
27036
+ * Live navigation state so the UI can reflect what the robot is doing:
27037
+ * - `mode` — coarse activity (idle / cleaning / following / …).
27038
+ * - `following` — person/pet follow is currently armed.
27039
+ * - `flash` — the on-camera fill light is on.
27040
+ * - `lightMode` — auto vs manual fill-light mode.
27041
+ * - `lightLevel` — manual fill-light level (40..100); meaningful when
27042
+ * `lightMode === 'manual'`.
27043
+ */
27044
+ var NavigationStatusSchema = object({
27045
+ mode: _enum([
27046
+ "idle",
27047
+ "cleaning",
27048
+ "spot",
27049
+ "following",
27050
+ "goto",
27051
+ "returning",
27052
+ "paused",
27053
+ "unknown"
27054
+ ]),
27055
+ following: boolean(),
27056
+ flash: boolean(),
27057
+ lightMode: NavigationLightModeSchema,
27058
+ lightLevel: number().min(40).max(100),
27059
+ /** Ms epoch when the slice was last updated. */
27060
+ lastChangedAt: number()
27061
+ });
27062
+ NavigationStatusSchema.extend({ lastFetchedAt: number() });
27063
+ DeviceType.Camera, method(NavigationMoveCommandSchema.extend({ deviceId: number() }), _void(), { kind: "mutation" }), method(object({ deviceId: number() }), _void(), { kind: "mutation" }), method(NavigationPointSchema.extend({ deviceId: number() }), _void(), { kind: "mutation" }), method(object({ deviceId: number() }), array(NavigationActionEntrySchema)), method(object({
27064
+ deviceId: number(),
27065
+ actionId: NavigationActionIdSchema
27066
+ }), _void(), { kind: "mutation" }), method(object({
27067
+ deviceId: number(),
27068
+ soundId: number().int()
27069
+ }), _void(), { kind: "mutation" }), method(object({
27070
+ deviceId: number(),
27071
+ on: boolean()
27072
+ }), _void(), { kind: "mutation" }), method(object({
27073
+ deviceId: number(),
27074
+ mode: NavigationLightModeSchema,
27075
+ level: number().min(40).max(100).optional()
27076
+ }), _void(), { kind: "mutation" }), method(object({
27077
+ deviceId: number(),
27078
+ level: number().min(40).max(100)
27079
+ }), _void(), { kind: "mutation" }), method(object({ deviceId: number() }), NavigationFeaturesSchema), object({
27080
+ deviceId: number(),
27081
+ status: NavigationStatusSchema
27082
+ });
26886
27083
  DeviceType.Camera, DeviceType.Sensor, DeviceType.Switch, method(object({ deviceId: number().int().nonnegative() }), object({ success: literal(true) }), {
26887
27084
  kind: "mutation",
26888
27085
  auth: "admin"
@@ -31947,6 +32144,66 @@ Object.freeze({
31947
32144
  addonId: null,
31948
32145
  access: "create"
31949
32146
  },
32147
+ "navigation.getFeatures": {
32148
+ capName: "navigation",
32149
+ capScope: "device",
32150
+ addonId: null,
32151
+ access: "view"
32152
+ },
32153
+ "navigation.goToPoint": {
32154
+ capName: "navigation",
32155
+ capScope: "device",
32156
+ addonId: null,
32157
+ access: "create"
32158
+ },
32159
+ "navigation.listActions": {
32160
+ capName: "navigation",
32161
+ capScope: "device",
32162
+ addonId: null,
32163
+ access: "view"
32164
+ },
32165
+ "navigation.move": {
32166
+ capName: "navigation",
32167
+ capScope: "device",
32168
+ addonId: null,
32169
+ access: "create"
32170
+ },
32171
+ "navigation.playSound": {
32172
+ capName: "navigation",
32173
+ capScope: "device",
32174
+ addonId: null,
32175
+ access: "create"
32176
+ },
32177
+ "navigation.runAction": {
32178
+ capName: "navigation",
32179
+ capScope: "device",
32180
+ addonId: null,
32181
+ access: "create"
32182
+ },
32183
+ "navigation.setLightLevel": {
32184
+ capName: "navigation",
32185
+ capScope: "device",
32186
+ addonId: null,
32187
+ access: "create"
32188
+ },
32189
+ "navigation.setLightMode": {
32190
+ capName: "navigation",
32191
+ capScope: "device",
32192
+ addonId: null,
32193
+ access: "create"
32194
+ },
32195
+ "navigation.setLightOn": {
32196
+ capName: "navigation",
32197
+ capScope: "device",
32198
+ addonId: null,
32199
+ access: "create"
32200
+ },
32201
+ "navigation.stop": {
32202
+ capName: "navigation",
32203
+ capScope: "device",
32204
+ addonId: null,
32205
+ access: "create"
32206
+ },
31950
32207
  "networkAccess.getEndpoint": {
31951
32208
  capName: "network-access",
31952
32209
  capScope: "system",
@@ -36042,6 +36299,56 @@ Object.freeze({
36042
36299
  form: "single",
36043
36300
  optional: false
36044
36301
  }],
36302
+ "navigation.getFeatures": [{
36303
+ name: "deviceId",
36304
+ form: "single",
36305
+ optional: false
36306
+ }],
36307
+ "navigation.goToPoint": [{
36308
+ name: "deviceId",
36309
+ form: "single",
36310
+ optional: false
36311
+ }],
36312
+ "navigation.listActions": [{
36313
+ name: "deviceId",
36314
+ form: "single",
36315
+ optional: false
36316
+ }],
36317
+ "navigation.move": [{
36318
+ name: "deviceId",
36319
+ form: "single",
36320
+ optional: false
36321
+ }],
36322
+ "navigation.playSound": [{
36323
+ name: "deviceId",
36324
+ form: "single",
36325
+ optional: false
36326
+ }],
36327
+ "navigation.runAction": [{
36328
+ name: "deviceId",
36329
+ form: "single",
36330
+ optional: false
36331
+ }],
36332
+ "navigation.setLightLevel": [{
36333
+ name: "deviceId",
36334
+ form: "single",
36335
+ optional: false
36336
+ }],
36337
+ "navigation.setLightMode": [{
36338
+ name: "deviceId",
36339
+ form: "single",
36340
+ optional: false
36341
+ }],
36342
+ "navigation.setLightOn": [{
36343
+ name: "deviceId",
36344
+ form: "single",
36345
+ optional: false
36346
+ }],
36347
+ "navigation.stop": [{
36348
+ name: "deviceId",
36349
+ form: "single",
36350
+ optional: false
36351
+ }],
36045
36352
  "networkQuality.getDeviceStats": [{
36046
36353
  name: "deviceId",
36047
36354
  form: "single",
package/dist/smb.addon.js CHANGED
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_shared = require("./shared-wJVLo41v.js");
5
+ const require_shared = require("./shared-DiZPvkCY.js");
6
6
  let node_crypto = require("node:crypto");
7
7
  let node_path = require("node:path");
8
8
  node_path = require_shared.__toESM(node_path);
@@ -1,4 +1,4 @@
1
- import { c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, s as storageProviderCapability } from "./shared-C1oHNHV8.mjs";
1
+ import { c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, s as storageProviderCapability } from "./shared-Dg4Fpj1Q.mjs";
2
2
  import { randomUUID } from "node:crypto";
3
3
  import * as path from "node:path";
4
4
  import * as fsp from "node:fs/promises";
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_shared = require("./shared-wJVLo41v.js");
5
+ const require_shared = require("./shared-DiZPvkCY.js");
6
6
  let node_stream = require("node:stream");
7
7
  let webdav = require("webdav");
8
8
  //#region src/providers/webdav/webdav-config-schema.ts
@@ -1,4 +1,4 @@
1
- import { a as safeJoinRemotePath, c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, r as getRequiredBasePath, s as storageProviderCapability, t as createSessionId } from "./shared-C1oHNHV8.mjs";
1
+ import { a as safeJoinRemotePath, c as BaseAddon, i as rearmIdleAbort, o as scheduleIdleAbort, r as getRequiredBasePath, s as storageProviderCapability, t as createSessionId } from "./shared-Dg4Fpj1Q.mjs";
2
2
  import { PassThrough } from "node:stream";
3
3
  import { AuthType, createClient } from "webdav";
4
4
  //#region src/providers/webdav/webdav-config-schema.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/addon-remote-storage",
3
- "version": "1.2.69",
3
+ "version": "1.2.70",
4
4
  "description": "Remote storage providers (SFTP, S3, WebDAV, SMB) — unifies remote backends behind the storage-provider cap",
5
5
  "keywords": [
6
6
  "camstack",