@switchbot/openapi-cli 3.2.0 → 3.2.1

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 (331) hide show
  1. package/dist/api/client.d.ts +31 -0
  2. package/dist/api/client.js +236 -0
  3. package/dist/api/client.js.map +1 -0
  4. package/dist/auth.d.ts +1 -0
  5. package/dist/auth.js +21 -0
  6. package/dist/auth.js.map +1 -0
  7. package/dist/commands/agent-bootstrap.d.ts +10 -0
  8. package/dist/commands/agent-bootstrap.js +200 -0
  9. package/dist/commands/agent-bootstrap.js.map +1 -0
  10. package/dist/commands/auth.d.ts +18 -0
  11. package/dist/commands/auth.js +355 -0
  12. package/dist/commands/auth.js.map +1 -0
  13. package/dist/commands/batch.d.ts +2 -0
  14. package/dist/commands/batch.js +414 -0
  15. package/dist/commands/batch.js.map +1 -0
  16. package/dist/commands/cache.d.ts +2 -0
  17. package/dist/commands/cache.js +127 -0
  18. package/dist/commands/cache.js.map +1 -0
  19. package/dist/commands/capabilities.d.ts +31 -0
  20. package/dist/commands/capabilities.js +383 -0
  21. package/dist/commands/capabilities.js.map +1 -0
  22. package/dist/commands/catalog.d.ts +2 -0
  23. package/dist/commands/catalog.js +360 -0
  24. package/dist/commands/catalog.js.map +1 -0
  25. package/dist/commands/completion.d.ts +2 -0
  26. package/dist/commands/completion.js +386 -0
  27. package/dist/commands/completion.js.map +1 -0
  28. package/dist/commands/config.d.ts +21 -0
  29. package/dist/commands/config.js +377 -0
  30. package/dist/commands/config.js.map +1 -0
  31. package/dist/commands/daemon.d.ts +2 -0
  32. package/dist/commands/daemon.js +411 -0
  33. package/dist/commands/daemon.js.map +1 -0
  34. package/dist/commands/device-meta.d.ts +2 -0
  35. package/dist/commands/device-meta.js +160 -0
  36. package/dist/commands/device-meta.js.map +1 -0
  37. package/dist/commands/devices.d.ts +2 -0
  38. package/dist/commands/devices.js +949 -0
  39. package/dist/commands/devices.js.map +1 -0
  40. package/dist/commands/doctor.d.ts +3 -0
  41. package/dist/commands/doctor.js +1016 -0
  42. package/dist/commands/doctor.js.map +1 -0
  43. package/dist/commands/events.d.ts +31 -0
  44. package/dist/commands/events.js +564 -0
  45. package/dist/commands/events.js.map +1 -0
  46. package/dist/commands/expand.d.ts +2 -0
  47. package/dist/commands/expand.js +131 -0
  48. package/dist/commands/expand.js.map +1 -0
  49. package/dist/commands/explain.d.ts +2 -0
  50. package/dist/commands/explain.js +140 -0
  51. package/dist/commands/explain.js.map +1 -0
  52. package/dist/commands/health.d.ts +8 -0
  53. package/dist/commands/health.js +114 -0
  54. package/dist/commands/health.js.map +1 -0
  55. package/dist/commands/history.d.ts +2 -0
  56. package/dist/commands/history.js +321 -0
  57. package/dist/commands/history.js.map +1 -0
  58. package/dist/commands/identity.d.ts +45 -0
  59. package/dist/commands/identity.js +60 -0
  60. package/dist/commands/identity.js.map +1 -0
  61. package/dist/commands/install.d.ts +20 -0
  62. package/dist/commands/install.js +247 -0
  63. package/dist/commands/install.js.map +1 -0
  64. package/dist/commands/mcp.d.ts +14 -0
  65. package/dist/commands/mcp.js +2018 -0
  66. package/dist/commands/mcp.js.map +1 -0
  67. package/dist/commands/plan.d.ts +51 -0
  68. package/dist/commands/plan.js +654 -0
  69. package/dist/commands/plan.js.map +1 -0
  70. package/dist/commands/policy.d.ts +24 -0
  71. package/dist/commands/policy.js +587 -0
  72. package/dist/commands/policy.js.map +1 -0
  73. package/dist/commands/quota.d.ts +2 -0
  74. package/dist/commands/quota.js +79 -0
  75. package/dist/commands/quota.js.map +1 -0
  76. package/dist/commands/rules.d.ts +2 -0
  77. package/dist/commands/rules.js +876 -0
  78. package/dist/commands/rules.js.map +1 -0
  79. package/dist/commands/scenes.d.ts +2 -0
  80. package/dist/commands/scenes.js +265 -0
  81. package/dist/commands/scenes.js.map +1 -0
  82. package/dist/commands/schema.d.ts +2 -0
  83. package/dist/commands/schema.js +185 -0
  84. package/dist/commands/schema.js.map +1 -0
  85. package/dist/commands/status-sync.d.ts +2 -0
  86. package/dist/commands/status-sync.js +132 -0
  87. package/dist/commands/status-sync.js.map +1 -0
  88. package/dist/commands/uninstall.d.ts +20 -0
  89. package/dist/commands/uninstall.js +238 -0
  90. package/dist/commands/uninstall.js.map +1 -0
  91. package/dist/commands/upgrade-check.d.ts +2 -0
  92. package/dist/commands/upgrade-check.js +107 -0
  93. package/dist/commands/upgrade-check.js.map +1 -0
  94. package/dist/commands/watch.d.ts +2 -0
  95. package/dist/commands/watch.js +195 -0
  96. package/dist/commands/watch.js.map +1 -0
  97. package/dist/commands/webhook.d.ts +2 -0
  98. package/dist/commands/webhook.js +183 -0
  99. package/dist/commands/webhook.js.map +1 -0
  100. package/dist/config.d.ts +57 -0
  101. package/dist/config.js +259 -0
  102. package/dist/config.js.map +1 -0
  103. package/dist/credentials/backends/file.d.ts +18 -0
  104. package/dist/credentials/backends/file.js +102 -0
  105. package/dist/credentials/backends/file.js.map +1 -0
  106. package/dist/credentials/backends/linux.d.ts +16 -0
  107. package/dist/credentials/backends/linux.js +130 -0
  108. package/dist/credentials/backends/linux.js.map +1 -0
  109. package/dist/credentials/backends/macos.d.ts +18 -0
  110. package/dist/credentials/backends/macos.js +130 -0
  111. package/dist/credentials/backends/macos.js.map +1 -0
  112. package/dist/credentials/backends/windows.d.ts +23 -0
  113. package/dist/credentials/backends/windows.js +216 -0
  114. package/dist/credentials/backends/windows.js.map +1 -0
  115. package/dist/credentials/keychain.d.ts +83 -0
  116. package/dist/credentials/keychain.js +89 -0
  117. package/dist/credentials/keychain.js.map +1 -0
  118. package/dist/credentials/prime.d.ts +32 -0
  119. package/dist/credentials/prime.js +53 -0
  120. package/dist/credentials/prime.js.map +1 -0
  121. package/dist/devices/cache.d.ts +79 -0
  122. package/dist/devices/cache.js +294 -0
  123. package/dist/devices/cache.js.map +1 -0
  124. package/dist/devices/catalog.d.ts +138 -0
  125. package/dist/devices/catalog.js +768 -0
  126. package/dist/devices/catalog.js.map +1 -0
  127. package/dist/devices/device-meta.d.ts +15 -0
  128. package/dist/devices/device-meta.js +57 -0
  129. package/dist/devices/device-meta.js.map +1 -0
  130. package/dist/devices/history-agg.d.ts +37 -0
  131. package/dist/devices/history-agg.js +139 -0
  132. package/dist/devices/history-agg.js.map +1 -0
  133. package/dist/devices/history-query.d.ts +45 -0
  134. package/dist/devices/history-query.js +182 -0
  135. package/dist/devices/history-query.js.map +1 -0
  136. package/dist/devices/param-validator.d.ts +40 -0
  137. package/dist/devices/param-validator.js +434 -0
  138. package/dist/devices/param-validator.js.map +1 -0
  139. package/dist/devices/resources.d.ts +74 -0
  140. package/dist/devices/resources.js +271 -0
  141. package/dist/devices/resources.js.map +1 -0
  142. package/dist/index.d.ts +1 -0
  143. package/dist/index.js +170 -56946
  144. package/dist/index.js.map +1 -0
  145. package/dist/install/default-steps.d.ts +66 -0
  146. package/dist/install/default-steps.js +258 -0
  147. package/dist/install/default-steps.js.map +1 -0
  148. package/dist/install/preflight.d.ts +60 -0
  149. package/dist/install/preflight.js +213 -0
  150. package/dist/install/preflight.js.map +1 -0
  151. package/dist/install/steps.d.ts +61 -0
  152. package/dist/install/steps.js +68 -0
  153. package/dist/install/steps.js.map +1 -0
  154. package/dist/lib/command-keywords.d.ts +5 -0
  155. package/dist/lib/command-keywords.js +18 -0
  156. package/dist/lib/command-keywords.js.map +1 -0
  157. package/dist/lib/daemon-state.d.ts +24 -0
  158. package/dist/lib/daemon-state.js +47 -0
  159. package/dist/lib/daemon-state.js.map +1 -0
  160. package/dist/lib/destructive-mode.d.ts +2 -0
  161. package/dist/lib/destructive-mode.js +13 -0
  162. package/dist/lib/destructive-mode.js.map +1 -0
  163. package/dist/lib/devices.d.ts +151 -0
  164. package/dist/lib/devices.js +383 -0
  165. package/dist/lib/devices.js.map +1 -0
  166. package/dist/lib/idempotency.d.ts +46 -0
  167. package/dist/lib/idempotency.js +107 -0
  168. package/dist/lib/idempotency.js.map +1 -0
  169. package/dist/lib/plan-store.d.ts +19 -0
  170. package/dist/lib/plan-store.js +69 -0
  171. package/dist/lib/plan-store.js.map +1 -0
  172. package/dist/lib/request-context.d.ts +7 -0
  173. package/dist/lib/request-context.js +13 -0
  174. package/dist/lib/request-context.js.map +1 -0
  175. package/dist/lib/scenes.d.ts +7 -0
  176. package/dist/lib/scenes.js +11 -0
  177. package/dist/lib/scenes.js.map +1 -0
  178. package/dist/logger.d.ts +4 -0
  179. package/dist/logger.js +17 -0
  180. package/dist/logger.js.map +1 -0
  181. package/dist/mcp/device-history.d.ts +36 -0
  182. package/dist/mcp/device-history.js +146 -0
  183. package/dist/mcp/device-history.js.map +1 -0
  184. package/dist/mcp/events-subscription.d.ts +45 -0
  185. package/dist/mcp/events-subscription.js +214 -0
  186. package/dist/mcp/events-subscription.js.map +1 -0
  187. package/dist/mqtt/client.d.ts +25 -0
  188. package/dist/mqtt/client.js +181 -0
  189. package/dist/mqtt/client.js.map +1 -0
  190. package/dist/mqtt/credential.d.ts +16 -0
  191. package/dist/mqtt/credential.js +31 -0
  192. package/dist/mqtt/credential.js.map +1 -0
  193. package/dist/policy/add-rule.d.ts +21 -0
  194. package/dist/policy/add-rule.js +125 -0
  195. package/dist/policy/add-rule.js.map +1 -0
  196. package/dist/policy/diff.d.ts +21 -0
  197. package/dist/policy/diff.js +92 -0
  198. package/dist/policy/diff.js.map +1 -0
  199. package/dist/policy/format.d.ts +6 -0
  200. package/dist/policy/format.js +58 -0
  201. package/dist/policy/format.js.map +1 -0
  202. package/dist/policy/load.d.ts +32 -0
  203. package/dist/policy/load.js +62 -0
  204. package/dist/policy/load.js.map +1 -0
  205. package/dist/policy/migrate.d.ts +21 -0
  206. package/dist/policy/migrate.js +68 -0
  207. package/dist/policy/migrate.js.map +1 -0
  208. package/dist/policy/schema.d.ts +5 -0
  209. package/dist/policy/schema.js +19 -0
  210. package/dist/policy/schema.js.map +1 -0
  211. package/dist/policy/validate.d.ts +19 -0
  212. package/dist/policy/validate.js +263 -0
  213. package/dist/policy/validate.js.map +1 -0
  214. package/dist/rules/action.d.ts +65 -0
  215. package/dist/rules/action.js +217 -0
  216. package/dist/rules/action.js.map +1 -0
  217. package/dist/rules/audit-query.d.ts +51 -0
  218. package/dist/rules/audit-query.js +90 -0
  219. package/dist/rules/audit-query.js.map +1 -0
  220. package/dist/rules/conflict-analyzer.d.ts +57 -0
  221. package/dist/rules/conflict-analyzer.js +215 -0
  222. package/dist/rules/conflict-analyzer.js.map +1 -0
  223. package/dist/rules/cron-scheduler.d.ts +62 -0
  224. package/dist/rules/cron-scheduler.js +187 -0
  225. package/dist/rules/cron-scheduler.js.map +1 -0
  226. package/dist/rules/destructive.d.ts +20 -0
  227. package/dist/rules/destructive.js +53 -0
  228. package/dist/rules/destructive.js.map +1 -0
  229. package/dist/rules/engine.d.ts +193 -0
  230. package/dist/rules/engine.js +758 -0
  231. package/dist/rules/engine.js.map +1 -0
  232. package/dist/rules/matcher.d.ts +56 -0
  233. package/dist/rules/matcher.js +231 -0
  234. package/dist/rules/matcher.js.map +1 -0
  235. package/dist/rules/pid-file.d.ts +43 -0
  236. package/dist/rules/pid-file.js +96 -0
  237. package/dist/rules/pid-file.js.map +1 -0
  238. package/dist/rules/quiet-hours.d.ts +26 -0
  239. package/dist/rules/quiet-hours.js +46 -0
  240. package/dist/rules/quiet-hours.js.map +1 -0
  241. package/dist/rules/suggest.d.ts +20 -0
  242. package/dist/rules/suggest.js +96 -0
  243. package/dist/rules/suggest.js.map +1 -0
  244. package/dist/rules/throttle.d.ts +61 -0
  245. package/dist/rules/throttle.js +117 -0
  246. package/dist/rules/throttle.js.map +1 -0
  247. package/dist/rules/types.d.ts +117 -0
  248. package/dist/rules/types.js +35 -0
  249. package/dist/rules/types.js.map +1 -0
  250. package/dist/rules/webhook-listener.d.ts +63 -0
  251. package/dist/rules/webhook-listener.js +224 -0
  252. package/dist/rules/webhook-listener.js.map +1 -0
  253. package/dist/rules/webhook-token.d.ts +50 -0
  254. package/dist/rules/webhook-token.js +91 -0
  255. package/dist/rules/webhook-token.js.map +1 -0
  256. package/dist/schema/field-aliases.d.ts +34 -0
  257. package/dist/schema/field-aliases.js +132 -0
  258. package/dist/schema/field-aliases.js.map +1 -0
  259. package/dist/sinks/dispatcher.d.ts +7 -0
  260. package/dist/sinks/dispatcher.js +13 -0
  261. package/dist/sinks/dispatcher.js.map +1 -0
  262. package/dist/sinks/file.d.ts +6 -0
  263. package/dist/sinks/file.js +20 -0
  264. package/dist/sinks/file.js.map +1 -0
  265. package/dist/sinks/format.d.ts +20 -0
  266. package/dist/sinks/format.js +57 -0
  267. package/dist/sinks/format.js.map +1 -0
  268. package/dist/sinks/homeassistant.d.ts +18 -0
  269. package/dist/sinks/homeassistant.js +45 -0
  270. package/dist/sinks/homeassistant.js.map +1 -0
  271. package/dist/sinks/openclaw.d.ts +13 -0
  272. package/dist/sinks/openclaw.js +34 -0
  273. package/dist/sinks/openclaw.js.map +1 -0
  274. package/dist/sinks/stdout.d.ts +4 -0
  275. package/dist/sinks/stdout.js +6 -0
  276. package/dist/sinks/stdout.js.map +1 -0
  277. package/dist/sinks/telegram.d.ts +11 -0
  278. package/dist/sinks/telegram.js +29 -0
  279. package/dist/sinks/telegram.js.map +1 -0
  280. package/dist/sinks/types.d.ts +13 -0
  281. package/dist/sinks/types.js +2 -0
  282. package/dist/sinks/types.js.map +1 -0
  283. package/dist/sinks/webhook.d.ts +6 -0
  284. package/dist/sinks/webhook.js +23 -0
  285. package/dist/sinks/webhook.js.map +1 -0
  286. package/dist/status-sync/manager.d.ts +48 -0
  287. package/dist/status-sync/manager.js +269 -0
  288. package/dist/status-sync/manager.js.map +1 -0
  289. package/dist/utils/arg-parsers.d.ts +16 -0
  290. package/dist/utils/arg-parsers.js +67 -0
  291. package/dist/utils/arg-parsers.js.map +1 -0
  292. package/dist/utils/audit.d.ts +69 -0
  293. package/dist/utils/audit.js +122 -0
  294. package/dist/utils/audit.js.map +1 -0
  295. package/dist/utils/filter.d.ts +81 -0
  296. package/dist/utils/filter.js +190 -0
  297. package/dist/utils/filter.js.map +1 -0
  298. package/dist/utils/flags.d.ts +72 -0
  299. package/dist/utils/flags.js +187 -0
  300. package/dist/utils/flags.js.map +1 -0
  301. package/dist/utils/format.d.ts +9 -0
  302. package/dist/utils/format.js +118 -0
  303. package/dist/utils/format.js.map +1 -0
  304. package/dist/utils/health.d.ts +48 -0
  305. package/dist/utils/health.js +102 -0
  306. package/dist/utils/health.js.map +1 -0
  307. package/dist/utils/help-json.d.ts +39 -0
  308. package/dist/utils/help-json.js +55 -0
  309. package/dist/utils/help-json.js.map +1 -0
  310. package/dist/utils/name-resolver.d.ts +26 -0
  311. package/dist/utils/name-resolver.js +138 -0
  312. package/dist/utils/name-resolver.js.map +1 -0
  313. package/dist/utils/output.d.ts +73 -0
  314. package/dist/utils/output.js +405 -0
  315. package/dist/utils/output.js.map +1 -0
  316. package/dist/utils/quota.d.ts +61 -0
  317. package/dist/utils/quota.js +228 -0
  318. package/dist/utils/quota.js.map +1 -0
  319. package/dist/utils/redact.d.ts +23 -0
  320. package/dist/utils/redact.js +69 -0
  321. package/dist/utils/redact.js.map +1 -0
  322. package/dist/utils/retry.d.ts +72 -0
  323. package/dist/utils/retry.js +141 -0
  324. package/dist/utils/retry.js.map +1 -0
  325. package/dist/utils/string.d.ts +2 -0
  326. package/dist/utils/string.js +23 -0
  327. package/dist/utils/string.js.map +1 -0
  328. package/dist/version.d.ts +2 -0
  329. package/dist/version.js +5 -0
  330. package/dist/version.js.map +1 -0
  331. package/package.json +2 -2
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Install-orchestrator step runner (Phase 3A · F5).
3
+ *
4
+ * Each step has a deterministic `execute` and a matching `undo`. The
5
+ * runner executes steps in order; on any failure it walks the
6
+ * already-completed steps in reverse and invokes their `undo`. If an
7
+ * `undo` itself fails, the error is captured and surfaced — the
8
+ * runner does NOT abort the rollback. The caller gets a full report
9
+ * and can decide how to surface partial cleanup failures.
10
+ *
11
+ * The module is intentionally agnostic of what steps do; consumers
12
+ * (future `openclaw plugins install`) plug in concrete steps like
13
+ * "npm i -g the CLI" or "write the credential to the keychain".
14
+ */
15
+ export interface InstallStep<Ctx = unknown> {
16
+ name: string;
17
+ description?: string;
18
+ execute: (ctx: Ctx) => Promise<void> | void;
19
+ undo: (ctx: Ctx) => Promise<void> | void;
20
+ }
21
+ export type StepOutcome = {
22
+ step: string;
23
+ status: 'succeeded';
24
+ } | {
25
+ step: string;
26
+ status: 'failed';
27
+ error: string;
28
+ } | {
29
+ step: string;
30
+ status: 'rolled-back';
31
+ } | {
32
+ step: string;
33
+ status: 'rollback-failed';
34
+ error: string;
35
+ } | {
36
+ step: string;
37
+ status: 'skipped';
38
+ };
39
+ export interface InstallReport {
40
+ ok: boolean;
41
+ /** Outcome entries in execution order (execution first, then rollback). */
42
+ outcomes: StepOutcome[];
43
+ /** Name of the step that caused the rollback, if any. */
44
+ failedAt?: string;
45
+ }
46
+ export interface RunInstallOptions<Ctx> {
47
+ /** Context object passed to every step. Defaults to `{}`. */
48
+ context?: Ctx;
49
+ /**
50
+ * When set, the runner stops immediately after executing this step
51
+ * (even on success). Useful for tests that want to exercise partial
52
+ * state without needing every step to succeed.
53
+ */
54
+ stopAfter?: string;
55
+ }
56
+ /**
57
+ * Run the given steps in order. On the first failure, the runner
58
+ * walks already-executed steps in reverse and invokes each step's
59
+ * undo. Returns a report describing every step's fate.
60
+ */
61
+ export declare function runInstall<Ctx = Record<string, unknown>>(steps: InstallStep<Ctx>[], options?: RunInstallOptions<Ctx>): Promise<InstallReport>;
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Install-orchestrator step runner (Phase 3A · F5).
3
+ *
4
+ * Each step has a deterministic `execute` and a matching `undo`. The
5
+ * runner executes steps in order; on any failure it walks the
6
+ * already-completed steps in reverse and invokes their `undo`. If an
7
+ * `undo` itself fails, the error is captured and surfaced — the
8
+ * runner does NOT abort the rollback. The caller gets a full report
9
+ * and can decide how to surface partial cleanup failures.
10
+ *
11
+ * The module is intentionally agnostic of what steps do; consumers
12
+ * (future `openclaw plugins install`) plug in concrete steps like
13
+ * "npm i -g the CLI" or "write the credential to the keychain".
14
+ */
15
+ /**
16
+ * Run the given steps in order. On the first failure, the runner
17
+ * walks already-executed steps in reverse and invokes each step's
18
+ * undo. Returns a report describing every step's fate.
19
+ */
20
+ export async function runInstall(steps, options = {}) {
21
+ const ctx = (options.context ?? {});
22
+ const outcomes = [];
23
+ const executed = [];
24
+ let failedAt;
25
+ for (const step of steps) {
26
+ try {
27
+ await step.execute(ctx);
28
+ outcomes.push({ step: step.name, status: 'succeeded' });
29
+ executed.push(step);
30
+ }
31
+ catch (err) {
32
+ outcomes.push({
33
+ step: step.name,
34
+ status: 'failed',
35
+ error: err instanceof Error ? err.message : String(err),
36
+ });
37
+ failedAt = step.name;
38
+ break;
39
+ }
40
+ if (options.stopAfter === step.name)
41
+ break;
42
+ }
43
+ if (failedAt !== undefined) {
44
+ // Roll back completed steps in reverse. Undo failures are captured
45
+ // but do not abort further rollback attempts — the goal is to
46
+ // leave as little residue as possible.
47
+ for (let i = executed.length - 1; i >= 0; i--) {
48
+ const step = executed[i];
49
+ try {
50
+ await step.undo(ctx);
51
+ outcomes.push({ step: step.name, status: 'rolled-back' });
52
+ }
53
+ catch (err) {
54
+ outcomes.push({
55
+ step: step.name,
56
+ status: 'rollback-failed',
57
+ error: err instanceof Error ? err.message : String(err),
58
+ });
59
+ }
60
+ }
61
+ }
62
+ return {
63
+ ok: failedAt === undefined,
64
+ outcomes,
65
+ ...(failedAt !== undefined ? { failedAt } : {}),
66
+ };
67
+ }
68
+ //# sourceMappingURL=steps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"steps.js","sourceRoot":"","sources":["../../src/install/steps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAmCH;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,KAAyB,EACzB,UAAkC,EAAE;IAEpC,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,OAAO,IAAK,EAAU,CAAQ,CAAC;IACpD,MAAM,QAAQ,GAAkB,EAAE,CAAC;IACnC,MAAM,QAAQ,GAAuB,EAAE,CAAC;IAExC,IAAI,QAA4B,CAAC;IAEjC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC;YACxD,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,QAAQ,CAAC,IAAI,CAAC;gBACZ,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,MAAM,EAAE,QAAQ;gBAChB,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;aACxD,CAAC,CAAC;YACH,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC;YACrB,MAAM;QACR,CAAC;QACD,IAAI,OAAO,CAAC,SAAS,KAAK,IAAI,CAAC,IAAI;YAAE,MAAM;IAC7C,CAAC;IAED,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,mEAAmE;QACnE,8DAA8D;QAC9D,uCAAuC;QACvC,KAAK,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC9C,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;YACzB,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACrB,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC,CAAC;YAC5D,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,QAAQ,CAAC,IAAI,CAAC;oBACZ,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,MAAM,EAAE,iBAAiB;oBACzB,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;iBACxD,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO;QACL,EAAE,EAAE,QAAQ,KAAK,SAAS;QAC1B,QAAQ;QACR,GAAG,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAChD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare const COMMAND_KEYWORDS: Array<{
2
+ pattern: RegExp;
3
+ command: string;
4
+ }>;
5
+ export declare function inferCommandFromIntent(intent: string): string | undefined;
@@ -0,0 +1,18 @@
1
+ export const COMMAND_KEYWORDS = [
2
+ { pattern: /\boff\b|\bturn.?off\b|\bstop\b/i, command: 'turnOff' },
3
+ { pattern: /\bon\b|\bturn.?on\b|\bstart\b/i, command: 'turnOn' },
4
+ { pattern: /\bpress\b|\bclick\b|\btap\b/i, command: 'press' },
5
+ { pattern: /\block\b/i, command: 'lock' },
6
+ { pattern: /\bunlock\b/i, command: 'unlock' },
7
+ { pattern: /\bopen\b|\braise\b|\bup\b/i, command: 'open' },
8
+ { pattern: /\bclose\b|\blower\b|\bdown\b/i, command: 'close' },
9
+ { pattern: /\bpause\b/i, command: 'pause' },
10
+ ];
11
+ export function inferCommandFromIntent(intent) {
12
+ for (const k of COMMAND_KEYWORDS) {
13
+ if (k.pattern.test(intent))
14
+ return k.command;
15
+ }
16
+ return undefined;
17
+ }
18
+ //# sourceMappingURL=command-keywords.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-keywords.js","sourceRoot":"","sources":["../../src/lib/command-keywords.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,gBAAgB,GAAgD;IAC3E,EAAE,OAAO,EAAE,iCAAiC,EAAE,OAAO,EAAE,SAAS,EAAE;IAClE,EAAE,OAAO,EAAE,gCAAgC,EAAE,OAAO,EAAE,QAAQ,EAAE;IAChE,EAAE,OAAO,EAAE,8BAA8B,EAAE,OAAO,EAAE,OAAO,EAAE;IAC7D,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE;IACzC,EAAE,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,QAAQ,EAAE;IAC7C,EAAE,OAAO,EAAE,4BAA4B,EAAE,OAAO,EAAE,MAAM,EAAE;IAC1D,EAAE,OAAO,EAAE,+BAA+B,EAAE,OAAO,EAAE,OAAO,EAAE;IAC9D,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE;CAC5C,CAAC;AAEF,MAAM,UAAU,sBAAsB,CAAC,MAAc;IACnD,KAAK,MAAM,CAAC,IAAI,gBAAgB,EAAE,CAAC;QACjC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;YAAE,OAAO,CAAC,CAAC,OAAO,CAAC;IAC/C,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,24 @@
1
+ export declare const DAEMON_PID_FILE: string;
2
+ export declare const DAEMON_LOG_FILE: string;
3
+ export declare const DAEMON_STATE_FILE: string;
4
+ export declare const HEALTHZ_PID_FILE: string;
5
+ export interface DaemonState {
6
+ status: 'starting' | 'running' | 'stopped' | 'failed';
7
+ pid: number | null;
8
+ startedAt?: string;
9
+ stoppedAt?: string;
10
+ failedAt?: string;
11
+ failureReason?: string;
12
+ logFile: string;
13
+ pidFile: string;
14
+ stateFile: string;
15
+ healthzPid?: number | null;
16
+ healthzPort?: number | null;
17
+ healthzPidFile?: string;
18
+ lastReloadAt?: string;
19
+ lastReloadStatus?: 'ok' | 'failed';
20
+ lastReloadMessage?: string;
21
+ }
22
+ export declare function writeDaemonState(state: DaemonState): void;
23
+ export declare function readDaemonState(): DaemonState | null;
24
+ export declare function removeDaemonState(): void;
@@ -0,0 +1,47 @@
1
+ import fs from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ function getStateDir() {
5
+ return path.join(os.homedir(), '.switchbot');
6
+ }
7
+ function getDaemonPidFile() {
8
+ return path.join(getStateDir(), 'daemon.pid');
9
+ }
10
+ function getDaemonLogFile() {
11
+ return path.join(getStateDir(), 'daemon.log');
12
+ }
13
+ function getDaemonStateFile() {
14
+ return path.join(getStateDir(), 'daemon.state.json');
15
+ }
16
+ function getHealthzPidFile() {
17
+ return path.join(getStateDir(), 'healthz.pid');
18
+ }
19
+ export const DAEMON_PID_FILE = getDaemonPidFile();
20
+ export const DAEMON_LOG_FILE = getDaemonLogFile();
21
+ export const DAEMON_STATE_FILE = getDaemonStateFile();
22
+ export const HEALTHZ_PID_FILE = getHealthzPidFile();
23
+ function ensureStateDir() {
24
+ fs.mkdirSync(getStateDir(), { recursive: true, mode: 0o700 });
25
+ }
26
+ export function writeDaemonState(state) {
27
+ ensureStateDir();
28
+ fs.writeFileSync(getDaemonStateFile(), JSON.stringify(state, null, 2), { mode: 0o600 });
29
+ }
30
+ export function readDaemonState() {
31
+ try {
32
+ const raw = fs.readFileSync(getDaemonStateFile(), 'utf-8');
33
+ return JSON.parse(raw);
34
+ }
35
+ catch {
36
+ return null;
37
+ }
38
+ }
39
+ export function removeDaemonState() {
40
+ try {
41
+ fs.unlinkSync(getDaemonStateFile());
42
+ }
43
+ catch {
44
+ // best effort
45
+ }
46
+ }
47
+ //# sourceMappingURL=daemon-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon-state.js","sourceRoot":"","sources":["../../src/lib/daemon-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,SAAS,WAAW;IAClB,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,YAAY,CAAC,CAAC;AAC/C,CAAC;AAED,SAAS,gBAAgB;IACvB,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,YAAY,CAAC,CAAC;AAChD,CAAC;AAED,SAAS,gBAAgB;IACvB,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,YAAY,CAAC,CAAC;AAChD,CAAC;AAED,SAAS,kBAAkB;IACzB,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,mBAAmB,CAAC,CAAC;AACvD,CAAC;AAED,SAAS,iBAAiB;IACxB,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,aAAa,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,gBAAgB,EAAE,CAAC;AAClD,MAAM,CAAC,MAAM,eAAe,GAAG,gBAAgB,EAAE,CAAC;AAClD,MAAM,CAAC,MAAM,iBAAiB,GAAG,kBAAkB,EAAE,CAAC;AACtD,MAAM,CAAC,MAAM,gBAAgB,GAAG,iBAAiB,EAAE,CAAC;AAoBpD,SAAS,cAAc;IACrB,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAkB;IACjD,cAAc,EAAE,CAAC;IACjB,EAAE,CAAC,aAAa,CAAC,kBAAkB,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAC1F,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,kBAAkB,EAAE,EAAE,OAAO,CAAC,CAAC;QAC3D,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAgB,CAAC;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,IAAI,CAAC;QACH,EAAE,CAAC,UAAU,CAAC,kBAAkB,EAAE,CAAC,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,cAAc;IAChB,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function allowsDirectDestructiveExecution(profile?: string | undefined): boolean;
2
+ export declare function destructiveExecutionHint(): string;
@@ -0,0 +1,13 @@
1
+ import { getActiveProfile } from './request-context.js';
2
+ const DIRECT_DESTRUCTIVE_PROFILES = new Set(['dev', 'development']);
3
+ export function allowsDirectDestructiveExecution(profile = getActiveProfile()) {
4
+ if (process.env.SWITCHBOT_ALLOW_DIRECT_DESTRUCTIVE === '1')
5
+ return true;
6
+ if (!profile)
7
+ return false;
8
+ return DIRECT_DESTRUCTIVE_PROFILES.has(profile.toLowerCase());
9
+ }
10
+ export function destructiveExecutionHint() {
11
+ return "Use 'switchbot plan save <file>' -> 'switchbot plan review <planId>' -> 'switchbot plan approve <planId>' -> 'switchbot plan execute <planId>' instead.";
12
+ }
13
+ //# sourceMappingURL=destructive-mode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"destructive-mode.js","sourceRoot":"","sources":["../../src/lib/destructive-mode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,MAAM,2BAA2B,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC;AAEpE,MAAM,UAAU,gCAAgC,CAAC,OAAO,GAAG,gBAAgB,EAAE;IAC3E,IAAI,OAAO,CAAC,GAAG,CAAC,kCAAkC,KAAK,GAAG;QAAE,OAAO,IAAI,CAAC;IACxE,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAC3B,OAAO,2BAA2B,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,wBAAwB;IACtC,OAAO,yJAAyJ,CAAC;AACnK,CAAC"}
@@ -0,0 +1,151 @@
1
+ import type { AxiosInstance } from 'axios';
2
+ import { suggestedActions, type DeviceCatalogEntry, type CommandSpec } from '../devices/catalog.js';
3
+ export interface Device {
4
+ deviceId: string;
5
+ deviceName: string;
6
+ deviceType?: string;
7
+ enableCloudService: boolean;
8
+ hubDeviceId: string;
9
+ roomID?: string;
10
+ roomName?: string | null;
11
+ familyName?: string;
12
+ controlType?: string;
13
+ }
14
+ export interface InfraredDevice {
15
+ deviceId: string;
16
+ deviceName: string;
17
+ remoteType: string;
18
+ hubDeviceId: string;
19
+ controlType?: string;
20
+ }
21
+ export interface DeviceListBody {
22
+ deviceList: Device[];
23
+ infraredRemoteList: InfraredDevice[];
24
+ }
25
+ export interface DescribeCapabilities {
26
+ role: string | null;
27
+ readOnly: boolean;
28
+ commands: CommandSpec[];
29
+ statusFields: string[];
30
+ liveStatus?: Record<string, unknown>;
31
+ }
32
+ export interface DescribeResult {
33
+ device: Device | InfraredDevice;
34
+ isPhysical: boolean;
35
+ typeName: string;
36
+ controlType: string | null;
37
+ catalog: DeviceCatalogEntry | null;
38
+ capabilities: DescribeCapabilities | {
39
+ liveStatus: Record<string, unknown>;
40
+ } | null;
41
+ source: 'catalog' | 'live' | 'catalog+live' | 'none';
42
+ suggestedActions: ReturnType<typeof suggestedActions>;
43
+ /** For IR remotes: the family/room inherited from their bound Hub. Undefined for physical devices. */
44
+ inheritedLocation?: {
45
+ family?: string;
46
+ room?: string;
47
+ roomID?: string;
48
+ };
49
+ }
50
+ export declare class DeviceNotFoundError extends Error {
51
+ readonly deviceId: string;
52
+ constructor(deviceId: string);
53
+ }
54
+ export declare class CommandValidationError extends Error {
55
+ readonly kind: 'read-only-device' | 'unknown-command' | 'unexpected-parameter' | 'missing-parameter';
56
+ readonly hint?: string | undefined;
57
+ constructor(message: string, kind: 'read-only-device' | 'unknown-command' | 'unexpected-parameter' | 'missing-parameter', hint?: string | undefined);
58
+ }
59
+ /** Fetch the full device + IR remote inventory and refresh the local cache. */
60
+ export declare function fetchDeviceList(client?: AxiosInstance): Promise<DeviceListBody>;
61
+ /** Fetch live status for a single physical device. IR remotes have no status channel. */
62
+ export declare function fetchDeviceStatus(deviceId: string, client?: AxiosInstance): Promise<Record<string, unknown>>;
63
+ /**
64
+ * Execute a command on a device. `parameter` is the fully-parsed value already
65
+ * (JSON-object when applicable), not a raw CLI string — callers should parse
66
+ * upstream if needed.
67
+ */
68
+ export declare function executeCommand(deviceId: string, cmd: string, parameter: unknown, commandType: 'command' | 'customize', client?: AxiosInstance, options?: {
69
+ idempotencyKey?: string;
70
+ planId?: string;
71
+ }): Promise<unknown>;
72
+ /**
73
+ * Validate a command against the locally-cached device → catalog mapping.
74
+ * Returns `{ ok: true }` when validation passes or is skipped (unknown device,
75
+ * custom IR button, etc.). On a case-only mismatch the canonical command name
76
+ * is returned via `normalized` along with a `caseNormalizedFrom` field so the
77
+ * caller can emit a warning and continue with the canonical name.
78
+ * Returns `{ ok: false, error }` only when the caller should refuse the call.
79
+ */
80
+ export declare function validateCommand(deviceId: string, cmd: string, parameter: string | undefined, commandType: string): {
81
+ ok: true;
82
+ normalized?: string;
83
+ caseNormalizedFrom?: string;
84
+ } | {
85
+ ok: false;
86
+ error: CommandValidationError;
87
+ };
88
+ /**
89
+ * Inspect catalog annotations to decide whether a command is destructive,
90
+ * i.e. has hard-to-reverse real-world effects and should require an explicit
91
+ * confirmation from an agent / operator before execution. Customize commands
92
+ * are considered non-destructive here — they're user-defined IR buttons
93
+ * whose behavior the catalog can't know about.
94
+ */
95
+ export declare function isDestructiveCommand(deviceType: string | undefined, cmd: string, commandType: string): boolean;
96
+ /** Return the safetyReason for a command, or null if not destructive / not found. */
97
+ export declare function getDestructiveReason(deviceType: string | undefined, cmd: string, commandType: string): string | null;
98
+ /**
99
+ * Describe a device by id: metadata + catalog entry (if known) +
100
+ * optional live status. Throws `DeviceNotFoundError` when the id is unknown.
101
+ */
102
+ export declare function describeDevice(deviceId: string, options?: {
103
+ live?: boolean;
104
+ }, client?: AxiosInstance): Promise<DescribeResult>;
105
+ /** Build a map from hubDeviceId → room/family/roomID for IR-remote inheritance. */
106
+ export declare function buildHubLocationMap(deviceList: Device[]): Map<string, {
107
+ family?: string;
108
+ room?: string;
109
+ roomID?: string;
110
+ }>;
111
+ /**
112
+ * Search the local catalog by type name / alias. Returns up to `limit`
113
+ * entries whose type or alias contains the query (case-insensitive).
114
+ * Intended for MCP's `search_catalog` tool — not for dispatching commands.
115
+ */
116
+ export declare function searchCatalog(query: string, limit?: number): DeviceCatalogEntry[];
117
+ /** Shape expected by the MCP describe_device outputSchema. */
118
+ export interface McpDescribeShape {
119
+ device: {
120
+ deviceId: string;
121
+ deviceName: string;
122
+ deviceType?: string;
123
+ enableCloudService?: boolean;
124
+ hubDeviceId?: string;
125
+ roomID?: string;
126
+ roomName?: string | null;
127
+ familyName?: string;
128
+ controlType?: string;
129
+ remoteType?: string;
130
+ };
131
+ isPhysical: boolean;
132
+ typeName: string;
133
+ controlType: string | null;
134
+ source: 'catalog' | 'live' | 'catalog+live' | 'none';
135
+ capabilities: unknown;
136
+ suggestedActions: Array<{
137
+ command: string;
138
+ parameter?: string;
139
+ description: string;
140
+ }>;
141
+ inheritedLocation?: {
142
+ family?: string;
143
+ room?: string;
144
+ };
145
+ }
146
+ /** Convert a DescribeResult to the shape validated by the MCP outputSchema. */
147
+ export declare function toMcpDescribeShape(r: DescribeResult): McpDescribeShape;
148
+ /** Shapes the device list body for the MCP list_devices outputSchema. */
149
+ export declare function toMcpDeviceListShape(d: Device): Record<string, unknown>;
150
+ /** Shapes an infrared remote for the MCP list_devices outputSchema. */
151
+ export declare function toMcpIrDeviceShape(d: InfraredDevice): Record<string, unknown>;