@switchbot/openapi-cli 3.2.1 → 3.2.2

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 (332) hide show
  1. package/README.md +3 -1
  2. package/dist/index.js +57349 -170
  3. package/package.json +9 -5
  4. package/dist/api/client.d.ts +0 -31
  5. package/dist/api/client.js +0 -236
  6. package/dist/api/client.js.map +0 -1
  7. package/dist/auth.d.ts +0 -1
  8. package/dist/auth.js +0 -21
  9. package/dist/auth.js.map +0 -1
  10. package/dist/commands/agent-bootstrap.d.ts +0 -10
  11. package/dist/commands/agent-bootstrap.js +0 -200
  12. package/dist/commands/agent-bootstrap.js.map +0 -1
  13. package/dist/commands/auth.d.ts +0 -18
  14. package/dist/commands/auth.js +0 -355
  15. package/dist/commands/auth.js.map +0 -1
  16. package/dist/commands/batch.d.ts +0 -2
  17. package/dist/commands/batch.js +0 -414
  18. package/dist/commands/batch.js.map +0 -1
  19. package/dist/commands/cache.d.ts +0 -2
  20. package/dist/commands/cache.js +0 -127
  21. package/dist/commands/cache.js.map +0 -1
  22. package/dist/commands/capabilities.d.ts +0 -31
  23. package/dist/commands/capabilities.js +0 -383
  24. package/dist/commands/capabilities.js.map +0 -1
  25. package/dist/commands/catalog.d.ts +0 -2
  26. package/dist/commands/catalog.js +0 -360
  27. package/dist/commands/catalog.js.map +0 -1
  28. package/dist/commands/completion.d.ts +0 -2
  29. package/dist/commands/completion.js +0 -386
  30. package/dist/commands/completion.js.map +0 -1
  31. package/dist/commands/config.d.ts +0 -21
  32. package/dist/commands/config.js +0 -377
  33. package/dist/commands/config.js.map +0 -1
  34. package/dist/commands/daemon.d.ts +0 -2
  35. package/dist/commands/daemon.js +0 -411
  36. package/dist/commands/daemon.js.map +0 -1
  37. package/dist/commands/device-meta.d.ts +0 -2
  38. package/dist/commands/device-meta.js +0 -160
  39. package/dist/commands/device-meta.js.map +0 -1
  40. package/dist/commands/devices.d.ts +0 -2
  41. package/dist/commands/devices.js +0 -949
  42. package/dist/commands/devices.js.map +0 -1
  43. package/dist/commands/doctor.d.ts +0 -3
  44. package/dist/commands/doctor.js +0 -1016
  45. package/dist/commands/doctor.js.map +0 -1
  46. package/dist/commands/events.d.ts +0 -31
  47. package/dist/commands/events.js +0 -564
  48. package/dist/commands/events.js.map +0 -1
  49. package/dist/commands/expand.d.ts +0 -2
  50. package/dist/commands/expand.js +0 -131
  51. package/dist/commands/expand.js.map +0 -1
  52. package/dist/commands/explain.d.ts +0 -2
  53. package/dist/commands/explain.js +0 -140
  54. package/dist/commands/explain.js.map +0 -1
  55. package/dist/commands/health.d.ts +0 -8
  56. package/dist/commands/health.js +0 -114
  57. package/dist/commands/health.js.map +0 -1
  58. package/dist/commands/history.d.ts +0 -2
  59. package/dist/commands/history.js +0 -321
  60. package/dist/commands/history.js.map +0 -1
  61. package/dist/commands/identity.d.ts +0 -45
  62. package/dist/commands/identity.js +0 -60
  63. package/dist/commands/identity.js.map +0 -1
  64. package/dist/commands/install.d.ts +0 -20
  65. package/dist/commands/install.js +0 -247
  66. package/dist/commands/install.js.map +0 -1
  67. package/dist/commands/mcp.d.ts +0 -14
  68. package/dist/commands/mcp.js +0 -2018
  69. package/dist/commands/mcp.js.map +0 -1
  70. package/dist/commands/plan.d.ts +0 -51
  71. package/dist/commands/plan.js +0 -654
  72. package/dist/commands/plan.js.map +0 -1
  73. package/dist/commands/policy.d.ts +0 -24
  74. package/dist/commands/policy.js +0 -587
  75. package/dist/commands/policy.js.map +0 -1
  76. package/dist/commands/quota.d.ts +0 -2
  77. package/dist/commands/quota.js +0 -79
  78. package/dist/commands/quota.js.map +0 -1
  79. package/dist/commands/rules.d.ts +0 -2
  80. package/dist/commands/rules.js +0 -876
  81. package/dist/commands/rules.js.map +0 -1
  82. package/dist/commands/scenes.d.ts +0 -2
  83. package/dist/commands/scenes.js +0 -265
  84. package/dist/commands/scenes.js.map +0 -1
  85. package/dist/commands/schema.d.ts +0 -2
  86. package/dist/commands/schema.js +0 -185
  87. package/dist/commands/schema.js.map +0 -1
  88. package/dist/commands/status-sync.d.ts +0 -2
  89. package/dist/commands/status-sync.js +0 -132
  90. package/dist/commands/status-sync.js.map +0 -1
  91. package/dist/commands/uninstall.d.ts +0 -20
  92. package/dist/commands/uninstall.js +0 -238
  93. package/dist/commands/uninstall.js.map +0 -1
  94. package/dist/commands/upgrade-check.d.ts +0 -2
  95. package/dist/commands/upgrade-check.js +0 -107
  96. package/dist/commands/upgrade-check.js.map +0 -1
  97. package/dist/commands/watch.d.ts +0 -2
  98. package/dist/commands/watch.js +0 -195
  99. package/dist/commands/watch.js.map +0 -1
  100. package/dist/commands/webhook.d.ts +0 -2
  101. package/dist/commands/webhook.js +0 -183
  102. package/dist/commands/webhook.js.map +0 -1
  103. package/dist/config.d.ts +0 -57
  104. package/dist/config.js +0 -259
  105. package/dist/config.js.map +0 -1
  106. package/dist/credentials/backends/file.d.ts +0 -18
  107. package/dist/credentials/backends/file.js +0 -102
  108. package/dist/credentials/backends/file.js.map +0 -1
  109. package/dist/credentials/backends/linux.d.ts +0 -16
  110. package/dist/credentials/backends/linux.js +0 -130
  111. package/dist/credentials/backends/linux.js.map +0 -1
  112. package/dist/credentials/backends/macos.d.ts +0 -18
  113. package/dist/credentials/backends/macos.js +0 -130
  114. package/dist/credentials/backends/macos.js.map +0 -1
  115. package/dist/credentials/backends/windows.d.ts +0 -23
  116. package/dist/credentials/backends/windows.js +0 -216
  117. package/dist/credentials/backends/windows.js.map +0 -1
  118. package/dist/credentials/keychain.d.ts +0 -83
  119. package/dist/credentials/keychain.js +0 -89
  120. package/dist/credentials/keychain.js.map +0 -1
  121. package/dist/credentials/prime.d.ts +0 -32
  122. package/dist/credentials/prime.js +0 -53
  123. package/dist/credentials/prime.js.map +0 -1
  124. package/dist/devices/cache.d.ts +0 -79
  125. package/dist/devices/cache.js +0 -294
  126. package/dist/devices/cache.js.map +0 -1
  127. package/dist/devices/catalog.d.ts +0 -138
  128. package/dist/devices/catalog.js +0 -768
  129. package/dist/devices/catalog.js.map +0 -1
  130. package/dist/devices/device-meta.d.ts +0 -15
  131. package/dist/devices/device-meta.js +0 -57
  132. package/dist/devices/device-meta.js.map +0 -1
  133. package/dist/devices/history-agg.d.ts +0 -37
  134. package/dist/devices/history-agg.js +0 -139
  135. package/dist/devices/history-agg.js.map +0 -1
  136. package/dist/devices/history-query.d.ts +0 -45
  137. package/dist/devices/history-query.js +0 -182
  138. package/dist/devices/history-query.js.map +0 -1
  139. package/dist/devices/param-validator.d.ts +0 -40
  140. package/dist/devices/param-validator.js +0 -434
  141. package/dist/devices/param-validator.js.map +0 -1
  142. package/dist/devices/resources.d.ts +0 -74
  143. package/dist/devices/resources.js +0 -271
  144. package/dist/devices/resources.js.map +0 -1
  145. package/dist/index.d.ts +0 -1
  146. package/dist/index.js.map +0 -1
  147. package/dist/install/default-steps.d.ts +0 -66
  148. package/dist/install/default-steps.js +0 -258
  149. package/dist/install/default-steps.js.map +0 -1
  150. package/dist/install/preflight.d.ts +0 -60
  151. package/dist/install/preflight.js +0 -213
  152. package/dist/install/preflight.js.map +0 -1
  153. package/dist/install/steps.d.ts +0 -61
  154. package/dist/install/steps.js +0 -68
  155. package/dist/install/steps.js.map +0 -1
  156. package/dist/lib/command-keywords.d.ts +0 -5
  157. package/dist/lib/command-keywords.js +0 -18
  158. package/dist/lib/command-keywords.js.map +0 -1
  159. package/dist/lib/daemon-state.d.ts +0 -24
  160. package/dist/lib/daemon-state.js +0 -47
  161. package/dist/lib/daemon-state.js.map +0 -1
  162. package/dist/lib/destructive-mode.d.ts +0 -2
  163. package/dist/lib/destructive-mode.js +0 -13
  164. package/dist/lib/destructive-mode.js.map +0 -1
  165. package/dist/lib/devices.d.ts +0 -151
  166. package/dist/lib/devices.js +0 -383
  167. package/dist/lib/devices.js.map +0 -1
  168. package/dist/lib/idempotency.d.ts +0 -46
  169. package/dist/lib/idempotency.js +0 -107
  170. package/dist/lib/idempotency.js.map +0 -1
  171. package/dist/lib/plan-store.d.ts +0 -19
  172. package/dist/lib/plan-store.js +0 -69
  173. package/dist/lib/plan-store.js.map +0 -1
  174. package/dist/lib/request-context.d.ts +0 -7
  175. package/dist/lib/request-context.js +0 -13
  176. package/dist/lib/request-context.js.map +0 -1
  177. package/dist/lib/scenes.d.ts +0 -7
  178. package/dist/lib/scenes.js +0 -11
  179. package/dist/lib/scenes.js.map +0 -1
  180. package/dist/logger.d.ts +0 -4
  181. package/dist/logger.js +0 -17
  182. package/dist/logger.js.map +0 -1
  183. package/dist/mcp/device-history.d.ts +0 -36
  184. package/dist/mcp/device-history.js +0 -146
  185. package/dist/mcp/device-history.js.map +0 -1
  186. package/dist/mcp/events-subscription.d.ts +0 -45
  187. package/dist/mcp/events-subscription.js +0 -214
  188. package/dist/mcp/events-subscription.js.map +0 -1
  189. package/dist/mqtt/client.d.ts +0 -25
  190. package/dist/mqtt/client.js +0 -181
  191. package/dist/mqtt/client.js.map +0 -1
  192. package/dist/mqtt/credential.d.ts +0 -16
  193. package/dist/mqtt/credential.js +0 -31
  194. package/dist/mqtt/credential.js.map +0 -1
  195. package/dist/policy/add-rule.d.ts +0 -21
  196. package/dist/policy/add-rule.js +0 -125
  197. package/dist/policy/add-rule.js.map +0 -1
  198. package/dist/policy/diff.d.ts +0 -21
  199. package/dist/policy/diff.js +0 -92
  200. package/dist/policy/diff.js.map +0 -1
  201. package/dist/policy/format.d.ts +0 -6
  202. package/dist/policy/format.js +0 -58
  203. package/dist/policy/format.js.map +0 -1
  204. package/dist/policy/load.d.ts +0 -32
  205. package/dist/policy/load.js +0 -62
  206. package/dist/policy/load.js.map +0 -1
  207. package/dist/policy/migrate.d.ts +0 -21
  208. package/dist/policy/migrate.js +0 -68
  209. package/dist/policy/migrate.js.map +0 -1
  210. package/dist/policy/schema.d.ts +0 -5
  211. package/dist/policy/schema.js +0 -19
  212. package/dist/policy/schema.js.map +0 -1
  213. package/dist/policy/validate.d.ts +0 -19
  214. package/dist/policy/validate.js +0 -263
  215. package/dist/policy/validate.js.map +0 -1
  216. package/dist/rules/action.d.ts +0 -65
  217. package/dist/rules/action.js +0 -217
  218. package/dist/rules/action.js.map +0 -1
  219. package/dist/rules/audit-query.d.ts +0 -51
  220. package/dist/rules/audit-query.js +0 -90
  221. package/dist/rules/audit-query.js.map +0 -1
  222. package/dist/rules/conflict-analyzer.d.ts +0 -57
  223. package/dist/rules/conflict-analyzer.js +0 -215
  224. package/dist/rules/conflict-analyzer.js.map +0 -1
  225. package/dist/rules/cron-scheduler.d.ts +0 -62
  226. package/dist/rules/cron-scheduler.js +0 -187
  227. package/dist/rules/cron-scheduler.js.map +0 -1
  228. package/dist/rules/destructive.d.ts +0 -20
  229. package/dist/rules/destructive.js +0 -53
  230. package/dist/rules/destructive.js.map +0 -1
  231. package/dist/rules/engine.d.ts +0 -193
  232. package/dist/rules/engine.js +0 -758
  233. package/dist/rules/engine.js.map +0 -1
  234. package/dist/rules/matcher.d.ts +0 -56
  235. package/dist/rules/matcher.js +0 -231
  236. package/dist/rules/matcher.js.map +0 -1
  237. package/dist/rules/pid-file.d.ts +0 -43
  238. package/dist/rules/pid-file.js +0 -96
  239. package/dist/rules/pid-file.js.map +0 -1
  240. package/dist/rules/quiet-hours.d.ts +0 -26
  241. package/dist/rules/quiet-hours.js +0 -46
  242. package/dist/rules/quiet-hours.js.map +0 -1
  243. package/dist/rules/suggest.d.ts +0 -20
  244. package/dist/rules/suggest.js +0 -96
  245. package/dist/rules/suggest.js.map +0 -1
  246. package/dist/rules/throttle.d.ts +0 -61
  247. package/dist/rules/throttle.js +0 -117
  248. package/dist/rules/throttle.js.map +0 -1
  249. package/dist/rules/types.d.ts +0 -117
  250. package/dist/rules/types.js +0 -35
  251. package/dist/rules/types.js.map +0 -1
  252. package/dist/rules/webhook-listener.d.ts +0 -63
  253. package/dist/rules/webhook-listener.js +0 -224
  254. package/dist/rules/webhook-listener.js.map +0 -1
  255. package/dist/rules/webhook-token.d.ts +0 -50
  256. package/dist/rules/webhook-token.js +0 -91
  257. package/dist/rules/webhook-token.js.map +0 -1
  258. package/dist/schema/field-aliases.d.ts +0 -34
  259. package/dist/schema/field-aliases.js +0 -132
  260. package/dist/schema/field-aliases.js.map +0 -1
  261. package/dist/sinks/dispatcher.d.ts +0 -7
  262. package/dist/sinks/dispatcher.js +0 -13
  263. package/dist/sinks/dispatcher.js.map +0 -1
  264. package/dist/sinks/file.d.ts +0 -6
  265. package/dist/sinks/file.js +0 -20
  266. package/dist/sinks/file.js.map +0 -1
  267. package/dist/sinks/format.d.ts +0 -20
  268. package/dist/sinks/format.js +0 -57
  269. package/dist/sinks/format.js.map +0 -1
  270. package/dist/sinks/homeassistant.d.ts +0 -18
  271. package/dist/sinks/homeassistant.js +0 -45
  272. package/dist/sinks/homeassistant.js.map +0 -1
  273. package/dist/sinks/openclaw.d.ts +0 -13
  274. package/dist/sinks/openclaw.js +0 -34
  275. package/dist/sinks/openclaw.js.map +0 -1
  276. package/dist/sinks/stdout.d.ts +0 -4
  277. package/dist/sinks/stdout.js +0 -6
  278. package/dist/sinks/stdout.js.map +0 -1
  279. package/dist/sinks/telegram.d.ts +0 -11
  280. package/dist/sinks/telegram.js +0 -29
  281. package/dist/sinks/telegram.js.map +0 -1
  282. package/dist/sinks/types.d.ts +0 -13
  283. package/dist/sinks/types.js +0 -2
  284. package/dist/sinks/types.js.map +0 -1
  285. package/dist/sinks/webhook.d.ts +0 -6
  286. package/dist/sinks/webhook.js +0 -23
  287. package/dist/sinks/webhook.js.map +0 -1
  288. package/dist/status-sync/manager.d.ts +0 -48
  289. package/dist/status-sync/manager.js +0 -269
  290. package/dist/status-sync/manager.js.map +0 -1
  291. package/dist/utils/arg-parsers.d.ts +0 -16
  292. package/dist/utils/arg-parsers.js +0 -67
  293. package/dist/utils/arg-parsers.js.map +0 -1
  294. package/dist/utils/audit.d.ts +0 -69
  295. package/dist/utils/audit.js +0 -122
  296. package/dist/utils/audit.js.map +0 -1
  297. package/dist/utils/filter.d.ts +0 -81
  298. package/dist/utils/filter.js +0 -190
  299. package/dist/utils/filter.js.map +0 -1
  300. package/dist/utils/flags.d.ts +0 -72
  301. package/dist/utils/flags.js +0 -187
  302. package/dist/utils/flags.js.map +0 -1
  303. package/dist/utils/format.d.ts +0 -9
  304. package/dist/utils/format.js +0 -118
  305. package/dist/utils/format.js.map +0 -1
  306. package/dist/utils/health.d.ts +0 -48
  307. package/dist/utils/health.js +0 -102
  308. package/dist/utils/health.js.map +0 -1
  309. package/dist/utils/help-json.d.ts +0 -39
  310. package/dist/utils/help-json.js +0 -55
  311. package/dist/utils/help-json.js.map +0 -1
  312. package/dist/utils/name-resolver.d.ts +0 -26
  313. package/dist/utils/name-resolver.js +0 -138
  314. package/dist/utils/name-resolver.js.map +0 -1
  315. package/dist/utils/output.d.ts +0 -73
  316. package/dist/utils/output.js +0 -405
  317. package/dist/utils/output.js.map +0 -1
  318. package/dist/utils/quota.d.ts +0 -61
  319. package/dist/utils/quota.js +0 -228
  320. package/dist/utils/quota.js.map +0 -1
  321. package/dist/utils/redact.d.ts +0 -23
  322. package/dist/utils/redact.js +0 -69
  323. package/dist/utils/redact.js.map +0 -1
  324. package/dist/utils/retry.d.ts +0 -72
  325. package/dist/utils/retry.js +0 -141
  326. package/dist/utils/retry.js.map +0 -1
  327. package/dist/utils/string.d.ts +0 -2
  328. package/dist/utils/string.js +0 -23
  329. package/dist/utils/string.js.map +0 -1
  330. package/dist/version.d.ts +0 -2
  331. package/dist/version.js +0 -5
  332. package/dist/version.js.map +0 -1
@@ -1,79 +0,0 @@
1
- export interface CachedDevice {
2
- type: string;
3
- name: string;
4
- category: 'physical' | 'ir';
5
- hubDeviceId?: string;
6
- enableCloudService?: boolean;
7
- roomID?: string;
8
- roomName?: string | null;
9
- familyName?: string;
10
- controlType?: string;
11
- }
12
- export interface DeviceCache {
13
- lastUpdated: string;
14
- devices: Record<string, CachedDevice>;
15
- }
16
- export interface DeviceListBodyShape {
17
- deviceList: Array<{
18
- deviceId: string;
19
- deviceName: string;
20
- deviceType?: string;
21
- hubDeviceId?: string;
22
- enableCloudService?: boolean;
23
- roomID?: string;
24
- roomName?: string | null;
25
- familyName?: string;
26
- controlType?: string;
27
- }>;
28
- infraredRemoteList: Array<{
29
- deviceId: string;
30
- deviceName: string;
31
- remoteType: string;
32
- hubDeviceId?: string;
33
- controlType?: string;
34
- }>;
35
- }
36
- /** Force the next loadCache() call to re-read from disk. Used in tests. */
37
- export declare function resetListCache(): void;
38
- /** Force the next loadStatusCache() call to re-read from disk. Used in tests. */
39
- export declare function resetStatusCache(): void;
40
- export declare function loadCache(): DeviceCache | null;
41
- export declare function getCachedDevice(deviceId: string): CachedDevice | null;
42
- /** Build a deviceId -> type map from the metadata cache. */
43
- export declare function getCachedTypeMap(deviceIds?: Iterable<string>): Map<string, string>;
44
- export declare function updateCacheFromDeviceList(body: DeviceListBodyShape): void;
45
- export declare function clearCache(): void;
46
- /** Age of the on-disk list cache in ms, or null if there is no cache. */
47
- export declare function listCacheAgeMs(now?: number): number | null;
48
- /** True when the on-disk list cache is present and younger than `ttlMs`. */
49
- export declare function isListCacheFresh(ttlMs: number, now?: number): boolean;
50
- export interface CachedStatus {
51
- fetchedAt: string;
52
- body: Record<string, unknown>;
53
- }
54
- export interface StatusCache {
55
- entries: Record<string, CachedStatus>;
56
- }
57
- export declare function loadStatusCache(): StatusCache;
58
- /** Read a status entry; returns null when missing or older than `ttlMs`. */
59
- export declare function getCachedStatus(deviceId: string, ttlMs: number, now?: number): Record<string, unknown> | null;
60
- export declare function setCachedStatus(deviceId: string, body: Record<string, unknown>, now?: Date, ttlMsForGc?: number): void;
61
- export declare function clearStatusCache(): void;
62
- /** Summary for `switchbot cache show`. */
63
- export interface CacheSummary {
64
- list: {
65
- path: string;
66
- exists: boolean;
67
- lastUpdated?: string;
68
- ageMs?: number;
69
- deviceCount?: number;
70
- };
71
- status: {
72
- path: string;
73
- exists: boolean;
74
- entryCount: number;
75
- oldestFetchedAt?: string;
76
- newestFetchedAt?: string;
77
- };
78
- }
79
- export declare function describeCache(now?: number): CacheSummary;
@@ -1,294 +0,0 @@
1
- import fs from 'node:fs';
2
- import path from 'node:path';
3
- import os from 'node:os';
4
- import { createHash } from 'node:crypto';
5
- import { getConfigPath } from '../utils/flags.js';
6
- import { getActiveProfile } from '../lib/request-context.js';
7
- /**
8
- * Returns the directory where cache files should be stored.
9
- *
10
- * - If a profile is active, scopes into a per-profile sub-directory so that
11
- * rotating credentials or switching profiles never serves stale inventory
12
- * from a prior session (Bug #37).
13
- * - If no profile is active (unnamed / default), returns `baseDir` unchanged
14
- * so the existing legacy path (~/.switchbot/devices.json) is preserved.
15
- *
16
- * Only called when `getConfigPath()` returns undefined — the --config-path
17
- * override takes full precedence and bypasses this helper entirely.
18
- */
19
- function scopedCacheDir(baseDir) {
20
- const profile = getActiveProfile();
21
- if (profile === undefined)
22
- return baseDir;
23
- const hash = createHash('sha256').update(profile).digest('hex').slice(0, 8);
24
- const dir = path.join(baseDir, 'cache', hash);
25
- if (!fs.existsSync(dir))
26
- fs.mkdirSync(dir, { recursive: true });
27
- return dir;
28
- }
29
- /** GC cutoff for status entries: evict anything older than this. */
30
- const DEFAULT_STATUS_GC_TTL_MS = 24 * 60 * 60 * 1000; // 24 h
31
- function cacheFilePath() {
32
- const override = getConfigPath();
33
- const dir = override
34
- ? path.dirname(path.resolve(override))
35
- : scopedCacheDir(path.join(os.homedir(), '.switchbot'));
36
- return path.join(dir, 'devices.json');
37
- }
38
- // In-memory hot-cache keyed by active profile (or '__default__' for no profile).
39
- // Using Maps instead of module-level singletons ensures that mcp serve, which
40
- // rotates profiles per request via withRequestContext, never leaks inventory
41
- // across profiles within the same process (Bug #37).
42
- const _listCacheByProfile = new Map();
43
- const _statusCacheByProfile = new Map();
44
- function cacheKey() {
45
- return getActiveProfile() ?? '__default__';
46
- }
47
- /** Force the next loadCache() call to re-read from disk. Used in tests. */
48
- export function resetListCache() {
49
- _listCacheByProfile.clear();
50
- }
51
- /** Force the next loadStatusCache() call to re-read from disk. Used in tests. */
52
- export function resetStatusCache() {
53
- _statusCacheByProfile.clear();
54
- }
55
- export function loadCache() {
56
- const key = cacheKey();
57
- if (_listCacheByProfile.has(key))
58
- return _listCacheByProfile.get(key);
59
- const file = cacheFilePath();
60
- if (!fs.existsSync(file)) {
61
- _listCacheByProfile.set(key, null);
62
- return null;
63
- }
64
- try {
65
- const raw = fs.readFileSync(file, 'utf-8');
66
- const cache = JSON.parse(raw);
67
- if (!cache || typeof cache.devices !== 'object' || cache.devices === null) {
68
- _listCacheByProfile.set(key, null);
69
- return null;
70
- }
71
- _listCacheByProfile.set(key, cache);
72
- return cache;
73
- }
74
- catch {
75
- _listCacheByProfile.set(key, null);
76
- return null;
77
- }
78
- }
79
- export function getCachedDevice(deviceId) {
80
- const cache = loadCache();
81
- if (!cache)
82
- return null;
83
- return cache.devices[deviceId] ?? null;
84
- }
85
- /** Build a deviceId -> type map from the metadata cache. */
86
- export function getCachedTypeMap(deviceIds) {
87
- const cache = loadCache();
88
- const out = new Map();
89
- if (!cache)
90
- return out;
91
- if (deviceIds) {
92
- for (const id of deviceIds) {
93
- const entry = cache.devices[id];
94
- if (entry?.type)
95
- out.set(id, entry.type);
96
- }
97
- return out;
98
- }
99
- for (const [deviceId, entry] of Object.entries(cache.devices)) {
100
- if (entry.type)
101
- out.set(deviceId, entry.type);
102
- }
103
- return out;
104
- }
105
- export function updateCacheFromDeviceList(body) {
106
- const devices = {};
107
- for (const d of body.deviceList) {
108
- if (!d.deviceId || !d.deviceType)
109
- continue;
110
- devices[d.deviceId] = {
111
- type: d.deviceType,
112
- name: d.deviceName,
113
- category: 'physical',
114
- hubDeviceId: d.hubDeviceId,
115
- enableCloudService: d.enableCloudService,
116
- roomID: d.roomID,
117
- roomName: d.roomName,
118
- familyName: d.familyName,
119
- controlType: d.controlType,
120
- };
121
- }
122
- for (const d of body.infraredRemoteList) {
123
- if (!d.deviceId)
124
- continue;
125
- devices[d.deviceId] = {
126
- type: d.remoteType,
127
- name: d.deviceName,
128
- category: 'ir',
129
- hubDeviceId: d.hubDeviceId,
130
- controlType: d.controlType,
131
- };
132
- }
133
- const cache = {
134
- lastUpdated: new Date().toISOString(),
135
- devices,
136
- };
137
- try {
138
- const file = cacheFilePath();
139
- const dir = path.dirname(file);
140
- if (!fs.existsSync(dir))
141
- fs.mkdirSync(dir, { recursive: true });
142
- fs.writeFileSync(file, JSON.stringify(cache, null, 2), { mode: 0o600 });
143
- _listCacheByProfile.set(cacheKey(), cache);
144
- }
145
- catch {
146
- // Cache write failures must not break the command that triggered them.
147
- }
148
- }
149
- export function clearCache() {
150
- const file = cacheFilePath();
151
- if (fs.existsSync(file))
152
- fs.unlinkSync(file);
153
- _listCacheByProfile.set(cacheKey(), null);
154
- }
155
- // ---- Device list freshness -------------------------------------------------
156
- /** Age of the on-disk list cache in ms, or null if there is no cache. */
157
- export function listCacheAgeMs(now = Date.now()) {
158
- const cache = loadCache();
159
- if (!cache)
160
- return null;
161
- const ts = Date.parse(cache.lastUpdated);
162
- if (!Number.isFinite(ts))
163
- return null;
164
- return Math.max(0, now - ts);
165
- }
166
- /** True when the on-disk list cache is present and younger than `ttlMs`. */
167
- export function isListCacheFresh(ttlMs, now = Date.now()) {
168
- if (!ttlMs || ttlMs <= 0)
169
- return false;
170
- const age = listCacheAgeMs(now);
171
- return age !== null && age < ttlMs;
172
- }
173
- function statusCacheFilePath() {
174
- const override = getConfigPath();
175
- const dir = override
176
- ? path.dirname(path.resolve(override))
177
- : scopedCacheDir(path.join(os.homedir(), '.switchbot'));
178
- return path.join(dir, 'status.json');
179
- }
180
- export function loadStatusCache() {
181
- const key = cacheKey();
182
- if (_statusCacheByProfile.has(key))
183
- return _statusCacheByProfile.get(key);
184
- const file = statusCacheFilePath();
185
- if (!fs.existsSync(file)) {
186
- const empty = { entries: {} };
187
- _statusCacheByProfile.set(key, empty);
188
- return empty;
189
- }
190
- try {
191
- const raw = fs.readFileSync(file, 'utf-8');
192
- const parsed = JSON.parse(raw);
193
- if (!parsed || typeof parsed.entries !== 'object' || parsed.entries === null) {
194
- const empty = { entries: {} };
195
- _statusCacheByProfile.set(key, empty);
196
- return empty;
197
- }
198
- _statusCacheByProfile.set(key, parsed);
199
- return parsed;
200
- }
201
- catch {
202
- const empty = { entries: {} };
203
- _statusCacheByProfile.set(key, empty);
204
- return empty;
205
- }
206
- }
207
- function saveStatusCache(cache) {
208
- _statusCacheByProfile.set(cacheKey(), cache);
209
- try {
210
- const file = statusCacheFilePath();
211
- const dir = path.dirname(file);
212
- if (!fs.existsSync(dir))
213
- fs.mkdirSync(dir, { recursive: true });
214
- fs.writeFileSync(file, JSON.stringify(cache, null, 2), { mode: 0o600 });
215
- }
216
- catch {
217
- /* best-effort */
218
- }
219
- }
220
- /** Read a status entry; returns null when missing or older than `ttlMs`. */
221
- export function getCachedStatus(deviceId, ttlMs, now = Date.now()) {
222
- if (!ttlMs || ttlMs <= 0)
223
- return null;
224
- const cache = loadStatusCache();
225
- const entry = cache.entries[deviceId];
226
- if (!entry)
227
- return null;
228
- const ts = Date.parse(entry.fetchedAt);
229
- if (!Number.isFinite(ts))
230
- return null;
231
- if (now - ts >= ttlMs)
232
- return null;
233
- return entry.body;
234
- }
235
- /** Evict status entries older than max(ttlMs × 10, 24 h) to bound file growth. */
236
- function evictExpiredStatusEntries(cache, ttlMs, now = Date.now()) {
237
- const cutoff = now - Math.max(ttlMs * 10, 24 * 60 * 60 * 1000);
238
- for (const id of Object.keys(cache.entries)) {
239
- const entry = cache.entries[id];
240
- const ts = Date.parse(entry.fetchedAt);
241
- if (!Number.isFinite(ts) || ts < cutoff)
242
- delete cache.entries[id];
243
- }
244
- }
245
- export function setCachedStatus(deviceId, body, now = new Date(), ttlMsForGc = DEFAULT_STATUS_GC_TTL_MS) {
246
- const cache = loadStatusCache();
247
- cache.entries[deviceId] = {
248
- fetchedAt: now.toISOString(),
249
- body,
250
- };
251
- evictExpiredStatusEntries(cache, ttlMsForGc, now.getTime());
252
- saveStatusCache(cache);
253
- }
254
- export function clearStatusCache() {
255
- const file = statusCacheFilePath();
256
- if (fs.existsSync(file))
257
- fs.unlinkSync(file);
258
- _statusCacheByProfile.set(cacheKey(), { entries: {} });
259
- }
260
- export function describeCache(now = Date.now()) {
261
- const listFile = cacheFilePath();
262
- const listCache = loadCache();
263
- const listExists = fs.existsSync(listFile);
264
- const list = {
265
- path: listFile,
266
- exists: listExists,
267
- };
268
- if (listCache) {
269
- list.lastUpdated = listCache.lastUpdated;
270
- const ts = Date.parse(listCache.lastUpdated);
271
- if (Number.isFinite(ts))
272
- list.ageMs = Math.max(0, now - ts);
273
- list.deviceCount = Object.keys(listCache.devices).length;
274
- }
275
- const statusFile = statusCacheFilePath();
276
- const statusExists = fs.existsSync(statusFile);
277
- const statusCache = loadStatusCache();
278
- const entries = Object.values(statusCache.entries);
279
- const status = {
280
- path: statusFile,
281
- exists: statusExists,
282
- entryCount: entries.length,
283
- };
284
- if (entries.length > 0) {
285
- const sorted = entries
286
- .map((e) => e.fetchedAt)
287
- .filter((s) => typeof s === 'string')
288
- .sort();
289
- status.oldestFetchedAt = sorted[0];
290
- status.newestFetchedAt = sorted[sorted.length - 1];
291
- }
292
- return { list, status };
293
- }
294
- //# sourceMappingURL=cache.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/devices/cache.ts"],"names":[],"mappings":"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"}
@@ -1,138 +0,0 @@
1
- /**
2
- * Static catalog of SwitchBot device types, control commands and status fields.
3
- * Sourced from https://github.com/OpenWonderLabs/SwitchBotAPI — keep in sync
4
- * when the upstream API adds new device types.
5
- *
6
- * Field conventions:
7
- * - CommandSpec.idempotent: repeat-safe — calling it N times ends in the
8
- * same state as calling it once (turnOn, setBrightness 50). Agents can
9
- * retry these freely. Counter-examples: toggle, press, volumeAdd.
10
- * - CommandSpec.safetyTier: explicit action safety classification. See
11
- * SafetyTier for the 5-tier enum. Built-in entries set this on the
12
- * destructive tier; other tiers are derived (see deriveSafetyTier).
13
- * - DeviceCatalogEntry.role: functional grouping for filter/search
14
- * ("all lighting", "all security"). Does not affect API behavior.
15
- * - DeviceCatalogEntry.readOnly: the device has no control commands; it
16
- * can only be queried via 'devices status'.
17
- */
18
- /**
19
- * Catalog shape version. Bump when any of the exported interfaces
20
- * (CommandSpec / DeviceCatalogEntry / SafetyTier) gain/lose/rename a
21
- * load-bearing field. The agent-bootstrap payload's schemaVersion must
22
- * stay pinned to this value; `doctor` fails the `catalog-schema` check
23
- * when they drift.
24
- */
25
- export declare const CATALOG_SCHEMA_VERSION = "1.0";
26
- /**
27
- * Safety classification for catalog commands.
28
- *
29
- * - 'read' —— Read-only query (status fetch). Reserved for v2.8+
30
- * `statusQueries` expansion; no command uses it today.
31
- * - 'mutation' —— Causes a state change but is reversible/idempotent
32
- * (turnOn/Off, setBrightness, setPosition).
33
- * - 'ir-fire-forget' —— IR command (no reply/ack) or customize IR button.
34
- * Fire-and-forget; reversibility depends on device.
35
- * - 'destructive' —— Hard or unsafe to reverse; physical-world side effects
36
- * (unlock, garage open, deleteKey). Needs confirmation.
37
- * - 'maintenance' —— Factory reset / firmware update / deep calibrate.
38
- * Reserved; the SwitchBot API exposes no such endpoint
39
- * today, so no command uses it.
40
- */
41
- export type SafetyTier = 'read' | 'mutation' | 'ir-fire-forget' | 'destructive' | 'maintenance';
42
- export interface CommandSpec {
43
- command: string;
44
- parameter: string;
45
- description: string;
46
- commandType?: 'command' | 'customize';
47
- idempotent?: boolean;
48
- /**
49
- * Explicit safety tier. When omitted, deriveSafetyTier() infers:
50
- * commandType: 'customize' or entry.category === 'ir' → 'ir-fire-forget'
51
- * otherwise → 'mutation'
52
- */
53
- safetyTier?: SafetyTier;
54
- /** One sentence explaining *why* this command needs caution — used in guard errors. */
55
- safetyReason?: string;
56
- exampleParams?: string[];
57
- }
58
- /** Coarse functional role — helpful for cross-type selection in agents. */
59
- export type DeviceRole = 'lighting' | 'climate' | 'security' | 'media' | 'sensor' | 'cleaning' | 'curtain' | 'fan' | 'power' | 'hub' | 'other';
60
- export interface DeviceCatalogEntry {
61
- type: string;
62
- category: 'physical' | 'ir';
63
- description?: string;
64
- aliases?: string[];
65
- commands: CommandSpec[];
66
- statusFields?: string[];
67
- /**
68
- * P11: strongly-typed read-only queries powering the 'read' safety tier.
69
- * When omitted, deriveStatusQueries() produces equivalent entries from
70
- * `statusFields`. Use this to override descriptions or attach examples.
71
- */
72
- statusQueries?: ReadOnlyQuerySpec[];
73
- role?: DeviceRole;
74
- readOnly?: boolean;
75
- }
76
- /**
77
- * P11: a single read-only query against a device. `endpoint: 'status'` is
78
- * the normal /devices/{id}/status call; 'keys' reads lock keypad entries;
79
- * 'webhook' reads the server-side webhook event subscription. All three
80
- * are safe to call at any time — they never mutate state.
81
- */
82
- export interface ReadOnlyQuerySpec {
83
- field: string;
84
- description: string;
85
- endpoint: 'status' | 'keys' | 'webhook';
86
- safetyTier: 'read';
87
- example?: unknown;
88
- }
89
- /**
90
- * P11: derive the read-only query list for an entry. If the entry has
91
- * explicit `statusQueries`, return them as-is; otherwise synthesize one
92
- * ReadOnlyQuerySpec per `statusFields` entry, all keyed to the `status`
93
- * endpoint. IR-category entries have no status channel so return [].
94
- */
95
- export declare function deriveStatusQueries(entry: DeviceCatalogEntry): ReadOnlyQuerySpec[];
96
- export declare const DEVICE_CATALOG: DeviceCatalogEntry[];
97
- /** Find a catalog entry by exact name, alias, or case-insensitive substring. */
98
- export declare function findCatalogEntry(query: string): DeviceCatalogEntry | DeviceCatalogEntry[] | null;
99
- /**
100
- * Derive the safety tier for a catalog command, honouring an explicit
101
- * `safetyTier` when present and falling back to heuristic inference.
102
- *
103
- * The inference order is:
104
- * 1. Explicit `spec.safetyTier`.
105
- * 2. IR context (customize command OR entry.category === 'ir')
106
- * → `'ir-fire-forget'`.
107
- * 3. Default → `'mutation'`.
108
- */
109
- export declare function deriveSafetyTier(spec: CommandSpec, entry?: Pick<DeviceCatalogEntry, 'category'>): SafetyTier;
110
- /** Read the safety reason for a command. */
111
- export declare function getCommandSafetyReason(spec: CommandSpec): string | null;
112
- /**
113
- * Pick up to 3 non-destructive, idempotent commands an agent can safely invoke
114
- * to explore or exercise a device. Used by `devices describe --json` to hint
115
- * at concrete next steps.
116
- */
117
- export declare function suggestedActions(entry: DeviceCatalogEntry): Array<{
118
- command: string;
119
- parameter?: string;
120
- description: string;
121
- }>;
122
- export interface CatalogOverlayEntry extends Partial<DeviceCatalogEntry> {
123
- type: string;
124
- remove?: boolean;
125
- }
126
- export interface OverlayLoadResult {
127
- path: string;
128
- exists: boolean;
129
- entries: CatalogOverlayEntry[];
130
- error?: string;
131
- }
132
- export declare function getCatalogOverlayPath(): string;
133
- /** Read the overlay file. Never throws — returns `error` on bad files. */
134
- export declare function loadCatalogOverlay(): OverlayLoadResult;
135
- /** Clear the overlay cache (test helper; also useful for `catalog refresh`). */
136
- export declare function resetCatalogOverlayCache(): void;
137
- /** Merge built-in catalog with the on-disk overlay. */
138
- export declare function getEffectiveCatalog(): DeviceCatalogEntry[];