@switchbot/openapi-cli 3.2.1 → 3.3.0

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 +57419 -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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@switchbot/openapi-cli",
3
- "version": "3.2.1",
3
+ "version": "3.3.0",
4
4
  "description": "SwitchBot smart home CLI — control devices, run scenes, stream real-time events, and integrate AI agents via MCP. Full API v1.1 coverage.",
5
5
  "keywords": [
6
6
  "switchbot",
@@ -36,17 +36,21 @@
36
36
  "access": "public"
37
37
  },
38
38
  "scripts": {
39
- "build": "tsc && node scripts/copy-assets.mjs",
40
- "build:prod": "node scripts/bundle.mjs && node scripts/copy-assets.mjs",
41
- "clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
39
+ "typecheck": "tsc --noEmit",
40
+ "build": "node scripts/build.mjs",
42
41
  "dev": "tsx src/index.ts",
42
+ "hooks:install": "node scripts/install-git-hooks.mjs",
43
43
  "lint:md": "markdownlint \"**/*.md\"",
44
44
  "lint:md:changelog": "markdownlint CHANGELOG.md",
45
+ "prepare": "node scripts/install-git-hooks.mjs",
45
46
  "start": "node dist/index.js",
47
+ "smoke:pack-install": "node scripts/smoke-pack-install.mjs",
46
48
  "test": "vitest run",
47
49
  "test:watch": "vitest",
48
50
  "test:coverage": "vitest run --coverage",
49
- "prepublishOnly": "npm test && npm run clean && npm run build && node dist/index.js --version"
51
+ "verify:pre-commit": "npm run build && npm test -- tests/version.test.ts",
52
+ "verify:pre-push": "npm run build && npm test -- tests/version.test.ts && npm run smoke:pack-install",
53
+ "prepublishOnly": "npm test && npm run build && npm run smoke:pack-install"
50
54
  },
51
55
  "dependencies": {
52
56
  "@modelcontextprotocol/sdk": "^1.29.0",
@@ -1,31 +0,0 @@
1
- import { type AxiosInstance } from 'axios';
2
- import { CircuitBreaker, CircuitOpenError } from '../utils/retry.js';
3
- /** Thrown by the request interceptor when --dry-run intercepts a mutating call. */
4
- export declare class DryRunSignal extends Error {
5
- readonly method: string;
6
- readonly url: string;
7
- constructor(method: string, url: string);
8
- }
9
- /**
10
- * Module-level circuit breaker for the SwitchBot API. Shared across all
11
- * client instances in the process. Opens after 5 consecutive 5xx / network
12
- * errors; resets to half-open after 60 s.
13
- * Exported for health-check inspection.
14
- */
15
- export declare const apiCircuitBreaker: CircuitBreaker;
16
- export { CircuitOpenError };
17
- export declare function createClient(): AxiosInstance;
18
- export interface ApiErrorMeta {
19
- retryable?: boolean;
20
- hint?: string;
21
- retryAfterMs?: number;
22
- transient?: boolean;
23
- }
24
- export declare class ApiError extends Error {
25
- readonly code: number;
26
- readonly retryable: boolean;
27
- readonly hint?: string;
28
- readonly retryAfterMs?: number;
29
- readonly transient: boolean;
30
- constructor(message: string, code: number, meta?: ApiErrorMeta);
31
- }
@@ -1,236 +0,0 @@
1
- import axios from 'axios';
2
- import chalk from 'chalk';
3
- import { buildAuthHeaders } from '../auth.js';
4
- import { loadConfig } from '../config.js';
5
- import { isVerbose, isDryRun, getTimeout, getRetryOn429, getRetryOn5xx, getBackoffStrategy, isQuotaDisabled, } from '../utils/flags.js';
6
- import { nextRetryDelayMs, sleep, CircuitBreaker, CircuitOpenError } from '../utils/retry.js';
7
- import { recordRequest, checkDailyCap } from '../utils/quota.js';
8
- import { readProfileMeta } from '../config.js';
9
- import { getActiveProfile } from '../lib/request-context.js';
10
- import { redactHeaders, warnOnceIfUnsafe } from '../utils/redact.js';
11
- class DailyCapExceededError extends Error {
12
- cap;
13
- total;
14
- profile;
15
- constructor(cap, total, profile) {
16
- super(`Local daily cap reached: ${total}/${cap} SwitchBot API calls used today${profile ? ` for profile "${profile}"` : ''}. ` +
17
- `Raise with: switchbot ${profile ? `--profile ${profile} ` : ''}config set-token --daily-cap <N>`);
18
- this.cap = cap;
19
- this.total = total;
20
- this.profile = profile;
21
- this.name = 'DailyCapExceededError';
22
- }
23
- }
24
- const API_ERROR_MESSAGES = {
25
- 151: 'Device type does not support this command',
26
- 152: 'Device ID does not exist',
27
- 160: 'This device does not support this command',
28
- 161: 'Device offline (check Wi-Fi / Bluetooth connection)',
29
- 171: 'Hub device offline (BLE devices require a Hub to communicate)',
30
- 190: 'Device internal error — often an invalid deviceId, unsupported parameter, or device busy',
31
- };
32
- /** Thrown by the request interceptor when --dry-run intercepts a mutating call. */
33
- export class DryRunSignal extends Error {
34
- method;
35
- url;
36
- constructor(method, url) {
37
- super('dry-run');
38
- this.method = method;
39
- this.url = url;
40
- this.name = 'DryRunSignal';
41
- }
42
- }
43
- /**
44
- * Module-level circuit breaker for the SwitchBot API. Shared across all
45
- * client instances in the process. Opens after 5 consecutive 5xx / network
46
- * errors; resets to half-open after 60 s.
47
- * Exported for health-check inspection.
48
- */
49
- export const apiCircuitBreaker = new CircuitBreaker('switchbot-api', {
50
- failureThreshold: 5,
51
- resetTimeoutMs: 60_000,
52
- });
53
- export { CircuitOpenError };
54
- export function createClient() {
55
- const { token, secret } = loadConfig();
56
- const verbose = isVerbose();
57
- const dryRun = isDryRun();
58
- const maxRetries = getRetryOn429();
59
- const max5xxRetries = getRetryOn5xx();
60
- const backoff = getBackoffStrategy();
61
- const quotaEnabled = !isQuotaDisabled();
62
- const profile = getActiveProfile();
63
- const profileMeta = readProfileMeta(profile);
64
- const dailyCap = profileMeta?.limits?.dailyCap;
65
- const client = axios.create({
66
- baseURL: 'https://api.switch-bot.com',
67
- timeout: getTimeout(),
68
- });
69
- // Inject auth headers; optionally log the request; short-circuit on --dry-run.
70
- client.interceptors.request.use((config) => {
71
- // Circuit breaker check — fail fast when the API is consistently down.
72
- apiCircuitBreaker.checkAndAllow();
73
- // Pre-flight cap check: refuse the call before it touches the network.
74
- if (dailyCap) {
75
- const check = checkDailyCap(dailyCap);
76
- if (check.over) {
77
- throw new DailyCapExceededError(dailyCap, check.total, profile);
78
- }
79
- }
80
- const authHeaders = buildAuthHeaders(token, secret);
81
- Object.assign(config.headers, authHeaders);
82
- const method = (config.method ?? 'get').toUpperCase();
83
- const url = `${config.baseURL ?? ''}${config.url ?? ''}`;
84
- if (verbose) {
85
- warnOnceIfUnsafe();
86
- process.stderr.write(chalk.grey(`[verbose] ${method} ${url}\n`));
87
- const { safe, redactedCount } = redactHeaders(config.headers);
88
- process.stderr.write(chalk.grey(`[verbose] headers: ${JSON.stringify(safe)}\n`));
89
- if (redactedCount > 0) {
90
- process.stderr.write(chalk.grey(`[verbose] 🔒 ${redactedCount} sensitive header(s) redacted.\n`));
91
- }
92
- if (config.data !== undefined) {
93
- process.stderr.write(chalk.grey(`[verbose] body: ${JSON.stringify(config.data)}\n`));
94
- }
95
- }
96
- if (dryRun && method !== 'GET') {
97
- process.stderr.write(chalk.yellow(`[dry-run] Would ${method} ${url}\n`));
98
- if (config.data !== undefined) {
99
- process.stderr.write(chalk.yellow(`[dry-run] body: ${JSON.stringify(config.data)}\n`));
100
- }
101
- throw new DryRunSignal(method, url);
102
- }
103
- // P8: record the quota attempt BEFORE the request is dispatched so
104
- // failures (timeouts / DNS errors / 5xx / aborted) also count. Only
105
- // pre-flight refusals (daily-cap, --dry-run) above skip recording
106
- // since they never touch the network. Retries re-enter this
107
- // interceptor and record again, which matches the SwitchBot API
108
- // billing model (every dispatched HTTP request consumes quota).
109
- if (quotaEnabled) {
110
- recordRequest(method, url);
111
- }
112
- return config;
113
- });
114
- // Handle API-level errors (HTTP 200 but statusCode !== 100)
115
- client.interceptors.response.use((response) => {
116
- if (verbose) {
117
- process.stderr.write(chalk.grey(`[verbose] ${response.status} ${response.statusText}\n`));
118
- }
119
- const data = response.data;
120
- if (data.statusCode !== undefined && data.statusCode !== 100) {
121
- const msg = API_ERROR_MESSAGES[data.statusCode] ??
122
- data.message ??
123
- `API error code: ${data.statusCode}`;
124
- throw new ApiError(msg, data.statusCode);
125
- }
126
- // Successful HTTP response — record for circuit breaker.
127
- apiCircuitBreaker.recordSuccess();
128
- return response;
129
- }, (error) => {
130
- if (error instanceof DryRunSignal)
131
- throw error;
132
- if (axios.isAxiosError(error)) {
133
- const config = error.config;
134
- const method = (config?.method ?? 'get').toUpperCase();
135
- const isIdempotentRead = method === 'GET';
136
- if (error.code === 'ECONNABORTED' || error.code === 'ETIMEDOUT') {
137
- // Retry idempotent GETs on timeout up to `max5xxRetries` times.
138
- if (isIdempotentRead && config && max5xxRetries > 0) {
139
- const attempt = config.__retryCount ?? 0;
140
- if (attempt < max5xxRetries) {
141
- config.__retryCount = attempt + 1;
142
- const delay = nextRetryDelayMs(attempt, backoff, undefined);
143
- if (verbose) {
144
- process.stderr.write(chalk.grey(`[verbose] timeout — retry ${attempt + 1}/${max5xxRetries} in ${delay}ms\n`));
145
- }
146
- return sleep(delay).then(() => client.request(config));
147
- }
148
- }
149
- // Network-level failure — record for circuit breaker.
150
- apiCircuitBreaker.recordFailure();
151
- throw new ApiError(`Request timed out after ${getTimeout()}ms (override with --timeout <ms>)`, 0, { transient: true, retryable: isIdempotentRead });
152
- }
153
- const status = error.response?.status;
154
- // 429 → transparent retry with Retry-After / exponential backoff.
155
- // Skipped when: no config (shouldn't happen for real axios errors),
156
- // retries disabled, or we've already used our budget.
157
- if (status === 429 && config && maxRetries > 0) {
158
- const attempt = config.__retryCount ?? 0;
159
- if (attempt < maxRetries) {
160
- config.__retryCount = attempt + 1;
161
- const delay = nextRetryDelayMs(attempt, backoff, error.response?.headers?.['retry-after']);
162
- if (verbose) {
163
- process.stderr.write(chalk.grey(`[verbose] 429 received — retry ${attempt + 1}/${maxRetries} in ${delay}ms\n`));
164
- }
165
- return sleep(delay).then(() => client.request(config));
166
- }
167
- }
168
- // 502/503/504 on idempotent GETs → transparent retry. Mutating calls
169
- // never auto-retry; use --idempotency-key for safe POST retries.
170
- if (isIdempotentRead &&
171
- status !== undefined &&
172
- (status === 502 || status === 503 || status === 504) &&
173
- config &&
174
- max5xxRetries > 0) {
175
- const attempt = config.__retryCount ?? 0;
176
- if (attempt < max5xxRetries) {
177
- config.__retryCount = attempt + 1;
178
- const delay = nextRetryDelayMs(attempt, backoff, error.response?.headers?.['retry-after']);
179
- if (verbose) {
180
- process.stderr.write(chalk.grey(`[verbose] ${status} received — retry ${attempt + 1}/${max5xxRetries} in ${delay}ms\n`));
181
- }
182
- return sleep(delay).then(() => client.request(config));
183
- }
184
- }
185
- // Record 5xx and network errors for circuit breaker. 4xx errors are
186
- // expected business responses — don't count toward circuit threshold.
187
- if (status === undefined || status >= 500) {
188
- apiCircuitBreaker.recordFailure();
189
- }
190
- // P8: quota already recorded in the request interceptor before
191
- // dispatch — no extra bookkeeping needed here on the error path.
192
- // Timeouts, DNS failures, 5xx, and exhausted retries all counted
193
- // when the attempt was first made.
194
- if (status === 401) {
195
- throw new ApiError('Authentication failed: invalid token or daily 10,000-request quota exceeded', 401, {
196
- transient: false,
197
- retryable: false,
198
- hint: 'Run `switchbot config set-token <token> <secret>` to re-enter credentials, or `switchbot quota status` to check today\'s local count.'
199
- });
200
- }
201
- if (status === 429) {
202
- const retryAfter = error.response?.headers?.['retry-after'];
203
- const retryAfterMs = nextRetryDelayMs(maxRetries - 1, backoff, retryAfter);
204
- throw new ApiError('Request rate too high: daily 10,000-request quota exceeded (retries exhausted)', 429, {
205
- retryable: true,
206
- transient: true,
207
- retryAfterMs,
208
- hint: 'Use `switchbot quota status` to see today\'s usage; raise `--retry-on-429 <n>` for more retries.'
209
- });
210
- }
211
- throw new ApiError(`HTTP ${status ?? '?'}: ${error.message}`, status ?? 0, {
212
- retryable: status !== undefined && status >= 500,
213
- transient: status !== undefined && (status >= 500 || status === 0) // 5xx, 0 = connection error
214
- });
215
- }
216
- throw error;
217
- });
218
- return client;
219
- }
220
- export class ApiError extends Error {
221
- code;
222
- retryable;
223
- hint;
224
- retryAfterMs;
225
- transient;
226
- constructor(message, code, meta = {}) {
227
- super(message);
228
- this.code = code;
229
- this.name = 'ApiError';
230
- this.retryable = meta.retryable ?? false;
231
- this.hint = meta.hint;
232
- this.retryAfterMs = meta.retryAfterMs;
233
- this.transient = meta.transient ?? false;
234
- }
235
- }
236
- //# sourceMappingURL=client.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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"}
package/dist/auth.d.ts DELETED
@@ -1 +0,0 @@
1
- export declare function buildAuthHeaders(token: string, secret: string): Record<string, string>;
package/dist/auth.js DELETED
@@ -1,21 +0,0 @@
1
- import crypto from 'node:crypto';
2
- import { v4 as uuidv4 } from 'uuid';
3
- export function buildAuthHeaders(token, secret) {
4
- const t = String(Date.now()); // 13-digit millisecond timestamp
5
- const nonce = uuidv4(); // unique per request
6
- const data = token + t + nonce;
7
- const sign = crypto
8
- .createHmac('sha256', secret)
9
- .update(data)
10
- .digest('base64')
11
- .toUpperCase(); // API requires uppercase
12
- return {
13
- Authorization: token,
14
- t,
15
- sign,
16
- nonce,
17
- src: 'OpenClaw',
18
- 'Content-Type': 'application/json',
19
- };
20
- }
21
- //# sourceMappingURL=auth.js.map
package/dist/auth.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,MAAM,CAAC;AAEpC,MAAM,UAAU,gBAAgB,CAAC,KAAa,EAAE,MAAc;IAC5D,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAE,iCAAiC;IAChE,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,CAAQ,qBAAqB;IACpD,MAAM,IAAI,GAAG,KAAK,GAAG,CAAC,GAAG,KAAK,CAAC;IAC/B,MAAM,IAAI,GAAG,MAAM;SAChB,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC;SAC5B,MAAM,CAAC,IAAI,CAAC;SACZ,MAAM,CAAC,QAAQ,CAAC;SAChB,WAAW,EAAE,CAAC,CAAc,yBAAyB;IAExD,OAAO;QACL,aAAa,EAAE,KAAK;QACpB,CAAC;QACD,IAAI;QACJ,KAAK;QACL,GAAG,EAAE,UAAU;QACf,cAAc,EAAE,kBAAkB;KACnC,CAAC;AACJ,CAAC"}
@@ -1,10 +0,0 @@
1
- import { Command } from 'commander';
2
- /**
3
- * Schema version of the agent-bootstrap payload. Must stay in lockstep
4
- * with the catalog schema — bootstrap consumers (AI agents) reason about
5
- * catalog-derived fields (safetyTier, destructive flag), so a drift
6
- * between the two would silently break their assumptions. `doctor`
7
- * fails the `catalog-schema` check when these differ.
8
- */
9
- export declare const AGENT_BOOTSTRAP_SCHEMA_VERSION = "1.0";
10
- export declare function registerAgentBootstrapCommand(program: Command): void;
@@ -1,200 +0,0 @@
1
- import { printJson, exitWithError } from '../utils/output.js';
2
- import { loadCache } from '../devices/cache.js';
3
- import { getEffectiveCatalog, deriveSafetyTier, CATALOG_SCHEMA_VERSION, } from '../devices/catalog.js';
4
- import { readProfileMeta } from '../config.js';
5
- import { todayUsage, DAILY_QUOTA } from '../utils/quota.js';
6
- import { ALL_STRATEGIES } from '../utils/name-resolver.js';
7
- import { IDENTITY } from './identity.js';
8
- import { resolvePolicyPath, loadPolicyFile, PolicyFileNotFoundError, PolicyYamlParseError, } from '../policy/load.js';
9
- import { validateLoadedPolicy } from '../policy/validate.js';
10
- import { selectCredentialStore } from '../credentials/keychain.js';
11
- import { VERSION as pkgVersion } from '../version.js';
12
- /**
13
- * Schema version of the agent-bootstrap payload. Must stay in lockstep
14
- * with the catalog schema — bootstrap consumers (AI agents) reason about
15
- * catalog-derived fields (safetyTier, destructive flag), so a drift
16
- * between the two would silently break their assumptions. `doctor`
17
- * fails the `catalog-schema` check when these differ.
18
- */
19
- export const AGENT_BOOTSTRAP_SCHEMA_VERSION = CATALOG_SCHEMA_VERSION;
20
- const SAFETY_TIERS = {
21
- read: 'No state mutation; safe to call freely.',
22
- action: 'Mutates device/cloud state but reversible (turnOn, setColor).',
23
- destructive: 'Hard to reverse / physical-world side effects (unlock). Requires confirmation.',
24
- };
25
- const QUICK_REFERENCE = {
26
- discovery: ['devices list', 'devices describe <id>', 'devices status <id>'],
27
- action: ['devices command <id> <cmd>', 'devices command --name <q> <cmd>', 'scenes execute <id>'],
28
- safety: ['--dry-run', '--idempotency-key <k>', '--audit-log', '--no-quota'],
29
- observability: ['doctor --json', 'quota status', 'cache status', 'events mqtt-tail'],
30
- history: ['history range <id> --since 7d', 'history stats <id>'],
31
- meta: ['devices meta set <id> --alias <name>', 'devices meta list', 'devices meta get <id>'],
32
- policy: ['policy validate', 'policy new', 'policy migrate'],
33
- auth: ['auth keychain describe', 'auth keychain migrate', 'auth keychain get'],
34
- };
35
- function readPolicyStatus() {
36
- // Lightweight read — used by the bootstrap payload so agents know whether
37
- // a policy file exists and is healthy without shelling out to
38
- // `switchbot policy validate`. Parallel to `checkPolicy` in doctor but
39
- // returns a more compact shape (no first-error drill-down; agents who
40
- // want that run the dedicated command).
41
- const policyPath = resolvePolicyPath();
42
- try {
43
- const loaded = loadPolicyFile(policyPath);
44
- const result = validateLoadedPolicy(loaded);
45
- return {
46
- present: true,
47
- valid: result.valid,
48
- path: policyPath,
49
- schemaVersion: result.schemaVersion,
50
- errorCount: result.valid ? 0 : result.errors.length,
51
- };
52
- }
53
- catch (err) {
54
- if (err instanceof PolicyFileNotFoundError) {
55
- return { present: false, valid: null, path: policyPath };
56
- }
57
- if (err instanceof PolicyYamlParseError) {
58
- return { present: true, valid: false, path: policyPath, errorCount: 1 };
59
- }
60
- return { present: false, valid: null, path: policyPath };
61
- }
62
- }
63
- async function readCredentialsBackend() {
64
- try {
65
- const store = await selectCredentialStore();
66
- const desc = store.describe();
67
- return { name: store.name, label: desc.backend, writable: desc.writable };
68
- }
69
- catch {
70
- return { name: 'file', label: 'File (~/.switchbot/config.json)', writable: true };
71
- }
72
- }
73
- export function registerAgentBootstrapCommand(program) {
74
- program
75
- .command('agent-bootstrap')
76
- .description('Print a compact, aggregate JSON snapshot for agent onboarding — combines identity, cached devices, catalog summary, quota usage, and profile in a single call. Offline-safe; does not hit the API.')
77
- .option('--compact', 'Emit an even smaller payload by dropping catalog descriptions and non-essential fields (target: <20 KB).')
78
- .option('--sections <csv>', 'Comma-separated top-level sections to include (e.g. identity,devices,catalog). Omit for all sections.')
79
- .addHelpText('after', `
80
- Output is always JSON (this command ignores --format). It is a one-shot
81
- orientation document for an agent/LLM to understand what's available without
82
- spending quota. It reads from local cache (devices + quota + profile) and the
83
- bundled catalog — no network calls.
84
-
85
- For fresher device state, have the agent follow up with:
86
- $ switchbot devices list --json # refreshes cache
87
- $ switchbot devices status <id> --json
88
-
89
- Examples:
90
- $ switchbot agent-bootstrap --compact | wc -c # fit in agent context window
91
- $ switchbot agent-bootstrap | jq '.devices | length'
92
- $ switchbot agent-bootstrap --compact | jq '.quickReference'
93
- `)
94
- .action(async (opts) => {
95
- const compact = Boolean(opts.compact);
96
- const cache = loadCache();
97
- const catalog = getEffectiveCatalog();
98
- const usage = todayUsage();
99
- const meta = readProfileMeta(undefined);
100
- const credentialsBackend = await readCredentialsBackend();
101
- const cachedDevices = cache
102
- ? Object.entries(cache.devices).map(([id, d]) => ({
103
- deviceId: id,
104
- type: d.type,
105
- name: d.name,
106
- category: d.category,
107
- roomName: d.roomName ?? null,
108
- }))
109
- : [];
110
- const usedTypes = new Set(cachedDevices.map((d) => d.type.toLowerCase()));
111
- const relevantCatalog = cachedDevices.length > 0
112
- ? catalog.filter((e) => usedTypes.has(e.type.toLowerCase()) ||
113
- (e.aliases ?? []).some((a) => usedTypes.has(a.toLowerCase())))
114
- : catalog;
115
- const catalogTypes = relevantCatalog.map((e) => {
116
- if (compact) {
117
- return {
118
- type: e.type,
119
- category: e.category,
120
- role: e.role ?? null,
121
- readOnly: e.readOnly ?? false,
122
- commands: e.commands.map((c) => c.command),
123
- statusFields: e.statusFields ?? [],
124
- };
125
- }
126
- return {
127
- type: e.type,
128
- category: e.category,
129
- role: e.role ?? null,
130
- readOnly: e.readOnly ?? false,
131
- commands: e.commands.map((c) => {
132
- const tier = deriveSafetyTier(c, e);
133
- return {
134
- command: c.command,
135
- parameter: c.parameter,
136
- safetyTier: tier,
137
- idempotent: Boolean(c.idempotent),
138
- };
139
- }),
140
- statusFields: e.statusFields ?? [],
141
- };
142
- });
143
- const payload = {
144
- schemaVersion: AGENT_BOOTSTRAP_SCHEMA_VERSION,
145
- generatedAt: new Date().toISOString(),
146
- cliVersion: pkgVersion,
147
- identity: IDENTITY,
148
- quickReference: QUICK_REFERENCE,
149
- safetyTiers: SAFETY_TIERS,
150
- nameStrategies: [...ALL_STRATEGIES],
151
- profile: meta
152
- ? {
153
- label: meta.label ?? null,
154
- description: meta.description ?? null,
155
- dailyCap: meta.limits?.dailyCap ?? null,
156
- defaultFlags: meta.defaults?.flags ?? null,
157
- }
158
- : null,
159
- quota: {
160
- date: usage.date,
161
- total: usage.total,
162
- remaining: usage.remaining,
163
- dailyLimit: DAILY_QUOTA,
164
- },
165
- policyStatus: readPolicyStatus(),
166
- credentialsBackend,
167
- devices: cachedDevices,
168
- catalog: {
169
- scope: cachedDevices.length > 0 ? 'used' : 'all',
170
- types: catalogTypes,
171
- },
172
- // hints: empty array means no hints to report; always emitted, never null.
173
- // An empty array signals "nothing to act on" — agents should not treat
174
- // it as a disabled or missing field.
175
- hints: cachedDevices.length === 0
176
- ? ['Run `switchbot devices list` once to populate the device cache for richer bootstrap output.']
177
- : [],
178
- };
179
- const VALID_SECTIONS = new Set([
180
- 'schemaVersion', 'generatedAt', 'cliVersion', 'identity', 'quickReference',
181
- 'safetyTiers', 'nameStrategies', 'profile', 'quota', 'policyStatus',
182
- 'credentialsBackend', 'devices', 'catalog', 'hints',
183
- ]);
184
- let finalPayload = payload;
185
- if (opts.sections) {
186
- const requested = opts.sections.split(',').map((s) => s.trim()).filter(Boolean);
187
- const unknown = requested.filter((s) => !VALID_SECTIONS.has(s));
188
- if (unknown.length > 0) {
189
- exitWithError({
190
- code: 2,
191
- kind: 'usage',
192
- message: `Unknown section(s): ${unknown.join(', ')}. Valid sections: ${[...VALID_SECTIONS].join(', ')}.`,
193
- });
194
- }
195
- finalPayload = Object.fromEntries(Object.entries(finalPayload).filter(([k]) => requested.includes(k)));
196
- }
197
- printJson(finalPayload);
198
- });
199
- }
200
- //# sourceMappingURL=agent-bootstrap.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"agent-bootstrap.js","sourceRoot":"","sources":["../../src/commands/agent-bootstrap.ts"],"names":[],"mappings":"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"}
@@ -1,18 +0,0 @@
1
- /**
2
- * `switchbot auth` command group (v2.9 preview, part of Phase 3A).
3
- *
4
- * Surfaces the credential store abstraction added in F1/F2 so users
5
- * can introspect, write to, delete from, and migrate into the OS
6
- * keychain without editing `~/.switchbot/config.json` by hand.
7
- *
8
- * All subcommands honour the active `--profile <name>` flag so a user
9
- * who runs multiple accounts keeps the keychain entries cleanly
10
- * partitioned.
11
- *
12
- * No credential material is ever printed in plain text. `get` emits
13
- * a masked summary only; `set` reads via a TTY prompt (echo-off) or a
14
- * file passed via `--stdin-file <path>`. `migrate` never touches the
15
- * keychain unless the backend reports `writable: true`.
16
- */
17
- import { Command } from 'commander';
18
- export declare function registerAuthCommand(program: Command): void;