@beeos-ai/device-agent 0.4.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 (398) hide show
  1. package/.pi/extensions/android-tools.ts +139 -0
  2. package/.pi/skills/.gitkeep +0 -0
  3. package/.pi/skills/ground-mobile-fallback/SKILL.md +50 -0
  4. package/LICENSE +201 -0
  5. package/dist/action/handler.d.ts +9 -0
  6. package/dist/action/handler.js +124 -0
  7. package/dist/action/handler.js.map +1 -0
  8. package/dist/adapters/agent-gateway-client.d.ts +256 -0
  9. package/dist/adapters/agent-gateway-client.js +332 -0
  10. package/dist/adapters/agent-gateway-client.js.map +1 -0
  11. package/dist/adapters/agentcore-inner-loop.d.ts +29 -0
  12. package/dist/adapters/agentcore-inner-loop.js +72 -0
  13. package/dist/adapters/agentcore-inner-loop.js.map +1 -0
  14. package/dist/adapters/agentcore-pi.d.ts +215 -0
  15. package/dist/adapters/agentcore-pi.js +464 -0
  16. package/dist/adapters/agentcore-pi.js.map +1 -0
  17. package/dist/adapters/agentcore-runner.d.ts +70 -0
  18. package/dist/adapters/agentcore-runner.js +255 -0
  19. package/dist/adapters/agentcore-runner.js.map +1 -0
  20. package/dist/adapters/device-android-adb.d.ts +41 -0
  21. package/dist/adapters/device-android-adb.js +279 -0
  22. package/dist/adapters/device-android-adb.js.map +1 -0
  23. package/dist/adapters/device-desktop.d.ts +37 -0
  24. package/dist/adapters/device-desktop.js +101 -0
  25. package/dist/adapters/device-desktop.js.map +1 -0
  26. package/dist/adapters/identity-file.d.ts +30 -0
  27. package/dist/adapters/identity-file.js +50 -0
  28. package/dist/adapters/identity-file.js.map +1 -0
  29. package/dist/adapters/transport-bridge-ws.d.ts +39 -0
  30. package/dist/adapters/transport-bridge-ws.js +49 -0
  31. package/dist/adapters/transport-bridge-ws.js.map +1 -0
  32. package/dist/adapters/vlm-inner-loop.d.ts +88 -0
  33. package/dist/adapters/vlm-inner-loop.js +199 -0
  34. package/dist/adapters/vlm-inner-loop.js.map +1 -0
  35. package/dist/agent-runtime/adapters/base.d.ts +145 -0
  36. package/dist/agent-runtime/adapters/base.js +29 -0
  37. package/dist/agent-runtime/adapters/base.js.map +1 -0
  38. package/dist/agent-runtime/adapters/index.d.ts +17 -0
  39. package/dist/agent-runtime/adapters/index.js +17 -0
  40. package/dist/agent-runtime/adapters/index.js.map +1 -0
  41. package/dist/agent-runtime/adapters/mock.d.ts +44 -0
  42. package/dist/agent-runtime/adapters/mock.js +54 -0
  43. package/dist/agent-runtime/adapters/mock.js.map +1 -0
  44. package/dist/agent-runtime/adapters/openai.d.ts +63 -0
  45. package/dist/agent-runtime/adapters/openai.js +302 -0
  46. package/dist/agent-runtime/adapters/openai.js.map +1 -0
  47. package/dist/agent-runtime/adapters/registry.d.ts +49 -0
  48. package/dist/agent-runtime/adapters/registry.js +129 -0
  49. package/dist/agent-runtime/adapters/registry.js.map +1 -0
  50. package/dist/agent-runtime/adapters/ui-tars.d.ts +13 -0
  51. package/dist/agent-runtime/adapters/ui-tars.js +22 -0
  52. package/dist/agent-runtime/adapters/ui-tars.js.map +1 -0
  53. package/dist/agent-runtime/agent-runner.d.ts +149 -0
  54. package/dist/agent-runtime/agent-runner.js +356 -0
  55. package/dist/agent-runtime/agent-runner.js.map +1 -0
  56. package/dist/agent-runtime/core.d.ts +170 -0
  57. package/dist/agent-runtime/core.js +624 -0
  58. package/dist/agent-runtime/core.js.map +1 -0
  59. package/dist/agent-runtime/index.d.ts +16 -0
  60. package/dist/agent-runtime/index.js +17 -0
  61. package/dist/agent-runtime/index.js.map +1 -0
  62. package/dist/agent-runtime/plan-executor.d.ts +118 -0
  63. package/dist/agent-runtime/plan-executor.js +501 -0
  64. package/dist/agent-runtime/plan-executor.js.map +1 -0
  65. package/dist/agent-runtime/planner/base.d.ts +128 -0
  66. package/dist/agent-runtime/planner/base.js +157 -0
  67. package/dist/agent-runtime/planner/base.js.map +1 -0
  68. package/dist/agent-runtime/planner/llm-planner.d.ts +58 -0
  69. package/dist/agent-runtime/planner/llm-planner.js +112 -0
  70. package/dist/agent-runtime/planner/llm-planner.js.map +1 -0
  71. package/dist/agent-runtime/planner/noop-planner.d.ts +13 -0
  72. package/dist/agent-runtime/planner/noop-planner.js +30 -0
  73. package/dist/agent-runtime/planner/noop-planner.js.map +1 -0
  74. package/dist/agent-runtime/planner/prompts.d.ts +33 -0
  75. package/dist/agent-runtime/planner/prompts.js +165 -0
  76. package/dist/agent-runtime/planner/prompts.js.map +1 -0
  77. package/dist/agent-runtime/reflection.d.ts +81 -0
  78. package/dist/agent-runtime/reflection.js +189 -0
  79. package/dist/agent-runtime/reflection.js.map +1 -0
  80. package/dist/agent-runtime/reflectors/action-reflector.d.ts +97 -0
  81. package/dist/agent-runtime/reflectors/action-reflector.js +233 -0
  82. package/dist/agent-runtime/reflectors/action-reflector.js.map +1 -0
  83. package/dist/agent-runtime/reflectors/policy.d.ts +53 -0
  84. package/dist/agent-runtime/reflectors/policy.js +106 -0
  85. package/dist/agent-runtime/reflectors/policy.js.map +1 -0
  86. package/dist/agent-runtime/reflectors/trajectory-reflector.d.ts +94 -0
  87. package/dist/agent-runtime/reflectors/trajectory-reflector.js +223 -0
  88. package/dist/agent-runtime/reflectors/trajectory-reflector.js.map +1 -0
  89. package/dist/agent-runtime/skills/embedding.d.ts +53 -0
  90. package/dist/agent-runtime/skills/embedding.js +134 -0
  91. package/dist/agent-runtime/skills/embedding.js.map +1 -0
  92. package/dist/agent-runtime/skills/fs-store.d.ts +88 -0
  93. package/dist/agent-runtime/skills/fs-store.js +483 -0
  94. package/dist/agent-runtime/skills/fs-store.js.map +1 -0
  95. package/dist/agent-runtime/skills/index.d.ts +10 -0
  96. package/dist/agent-runtime/skills/index.js +10 -0
  97. package/dist/agent-runtime/skills/index.js.map +1 -0
  98. package/dist/agent-runtime/skills/matcher-evolver.d.ts +88 -0
  99. package/dist/agent-runtime/skills/matcher-evolver.js +110 -0
  100. package/dist/agent-runtime/skills/matcher-evolver.js.map +1 -0
  101. package/dist/agent-runtime/skills/memory-store.d.ts +23 -0
  102. package/dist/agent-runtime/skills/memory-store.js +94 -0
  103. package/dist/agent-runtime/skills/memory-store.js.map +1 -0
  104. package/dist/agent-runtime/skills/normalise.d.ts +40 -0
  105. package/dist/agent-runtime/skills/normalise.js +152 -0
  106. package/dist/agent-runtime/skills/normalise.js.map +1 -0
  107. package/dist/agent-runtime/skills/replay.d.ts +46 -0
  108. package/dist/agent-runtime/skills/replay.js +106 -0
  109. package/dist/agent-runtime/skills/replay.js.map +1 -0
  110. package/dist/agent-runtime/skills/sqlite-store.d.ts +60 -0
  111. package/dist/agent-runtime/skills/sqlite-store.js +234 -0
  112. package/dist/agent-runtime/skills/sqlite-store.js.map +1 -0
  113. package/dist/agent-runtime/skills/types.d.ts +99 -0
  114. package/dist/agent-runtime/skills/types.js +14 -0
  115. package/dist/agent-runtime/skills/types.js.map +1 -0
  116. package/dist/agent.d.ts +110 -0
  117. package/dist/agent.js +162 -0
  118. package/dist/agent.js.map +1 -0
  119. package/dist/api.d.ts +27 -0
  120. package/dist/api.js +48 -0
  121. package/dist/api.js.map +1 -0
  122. package/dist/app/agent-host.d.ts +59 -0
  123. package/dist/app/agent-host.js +263 -0
  124. package/dist/app/agent-host.js.map +1 -0
  125. package/dist/app/device-manager.d.ts +28 -0
  126. package/dist/app/device-manager.js +64 -0
  127. package/dist/app/device-manager.js.map +1 -0
  128. package/dist/app/message-store.d.ts +55 -0
  129. package/dist/app/message-store.js +99 -0
  130. package/dist/app/message-store.js.map +1 -0
  131. package/dist/app/session-manager.d.ts +132 -0
  132. package/dist/app/session-manager.js +350 -0
  133. package/dist/app/session-manager.js.map +1 -0
  134. package/dist/bootstrap.d.ts +94 -0
  135. package/dist/bootstrap.js +459 -0
  136. package/dist/bootstrap.js.map +1 -0
  137. package/dist/chat.d.ts +16 -0
  138. package/dist/chat.js +175 -0
  139. package/dist/chat.js.map +1 -0
  140. package/dist/config/loader.d.ts +77 -0
  141. package/dist/config/loader.js +292 -0
  142. package/dist/config/loader.js.map +1 -0
  143. package/dist/config/schema.d.ts +162 -0
  144. package/dist/config/schema.js +243 -0
  145. package/dist/config/schema.js.map +1 -0
  146. package/dist/core/actions.d.ts +60 -0
  147. package/dist/core/actions.js +120 -0
  148. package/dist/core/actions.js.map +1 -0
  149. package/dist/core/errors.d.ts +8 -0
  150. package/dist/core/errors.js +9 -0
  151. package/dist/core/errors.js.map +1 -0
  152. package/dist/core/screen.d.ts +7 -0
  153. package/dist/core/screen.js +8 -0
  154. package/dist/core/screen.js.map +1 -0
  155. package/dist/core/session.d.ts +42 -0
  156. package/dist/core/session.js +29 -0
  157. package/dist/core/session.js.map +1 -0
  158. package/dist/debug/dump-system-prompt.d.ts +1 -0
  159. package/dist/debug/dump-system-prompt.js +34 -0
  160. package/dist/debug/dump-system-prompt.js.map +1 -0
  161. package/dist/device/android.d.ts +25 -0
  162. package/dist/device/android.js +231 -0
  163. package/dist/device/android.js.map +1 -0
  164. package/dist/device/apps.d.ts +3 -0
  165. package/dist/device/apps.js +77 -0
  166. package/dist/device/apps.js.map +1 -0
  167. package/dist/device/base.d.ts +20 -0
  168. package/dist/device/base.js +2 -0
  169. package/dist/device/base.js.map +1 -0
  170. package/dist/device/ui-xml.d.ts +29 -0
  171. package/dist/device/ui-xml.js +194 -0
  172. package/dist/device/ui-xml.js.map +1 -0
  173. package/dist/fleet/adapters/process/node-process-manager.d.ts +157 -0
  174. package/dist/fleet/adapters/process/node-process-manager.js +664 -0
  175. package/dist/fleet/adapters/process/node-process-manager.js.map +1 -0
  176. package/dist/fleet/adapters/sources/local-adb.d.ts +105 -0
  177. package/dist/fleet/adapters/sources/local-adb.js +353 -0
  178. package/dist/fleet/adapters/sources/local-adb.js.map +1 -0
  179. package/dist/fleet/adapters/sources/remote-adb.d.ts +97 -0
  180. package/dist/fleet/adapters/sources/remote-adb.js +138 -0
  181. package/dist/fleet/adapters/sources/remote-adb.js.map +1 -0
  182. package/dist/fleet/adapters/state/beeos-cli-store.d.ts +72 -0
  183. package/dist/fleet/adapters/state/beeos-cli-store.js +250 -0
  184. package/dist/fleet/adapters/state/beeos-cli-store.js.map +1 -0
  185. package/dist/fleet/adapters/state/port-allocator.d.ts +43 -0
  186. package/dist/fleet/adapters/state/port-allocator.js +173 -0
  187. package/dist/fleet/adapters/state/port-allocator.js.map +1 -0
  188. package/dist/fleet/domain/device.d.ts +138 -0
  189. package/dist/fleet/domain/device.js +49 -0
  190. package/dist/fleet/domain/device.js.map +1 -0
  191. package/dist/fleet/domain/events.d.ts +102 -0
  192. package/dist/fleet/domain/events.js +15 -0
  193. package/dist/fleet/domain/events.js.map +1 -0
  194. package/dist/fleet/domain/fsm.d.ts +122 -0
  195. package/dist/fleet/domain/fsm.js +475 -0
  196. package/dist/fleet/domain/fsm.js.map +1 -0
  197. package/dist/fleet/http/status-client.d.ts +31 -0
  198. package/dist/fleet/http/status-client.js +115 -0
  199. package/dist/fleet/http/status-client.js.map +1 -0
  200. package/dist/fleet/http/status-server.d.ts +64 -0
  201. package/dist/fleet/http/status-server.js +200 -0
  202. package/dist/fleet/http/status-server.js.map +1 -0
  203. package/dist/fleet/index.d.ts +27 -0
  204. package/dist/fleet/index.js +17 -0
  205. package/dist/fleet/index.js.map +1 -0
  206. package/dist/fleet/installer/index.d.ts +12 -0
  207. package/dist/fleet/installer/index.js +13 -0
  208. package/dist/fleet/installer/index.js.map +1 -0
  209. package/dist/fleet/installer/launchd-mac.d.ts +73 -0
  210. package/dist/fleet/installer/launchd-mac.js +291 -0
  211. package/dist/fleet/installer/launchd-mac.js.map +1 -0
  212. package/dist/fleet/installer/service-spec.d.ts +70 -0
  213. package/dist/fleet/installer/service-spec.js +43 -0
  214. package/dist/fleet/installer/service-spec.js.map +1 -0
  215. package/dist/fleet/installer/spawn-env.d.ts +45 -0
  216. package/dist/fleet/installer/spawn-env.js +224 -0
  217. package/dist/fleet/installer/spawn-env.js.map +1 -0
  218. package/dist/fleet/ports/clock.d.ts +19 -0
  219. package/dist/fleet/ports/clock.js +26 -0
  220. package/dist/fleet/ports/clock.js.map +1 -0
  221. package/dist/fleet/ports/device-source.d.ts +28 -0
  222. package/dist/fleet/ports/device-source.js +18 -0
  223. package/dist/fleet/ports/device-source.js.map +1 -0
  224. package/dist/fleet/ports/process-manager.d.ts +110 -0
  225. package/dist/fleet/ports/process-manager.js +27 -0
  226. package/dist/fleet/ports/process-manager.js.map +1 -0
  227. package/dist/fleet/ports/state-registry.d.ts +49 -0
  228. package/dist/fleet/ports/state-registry.js +12 -0
  229. package/dist/fleet/ports/state-registry.js.map +1 -0
  230. package/dist/fleet/supervisor.d.ts +107 -0
  231. package/dist/fleet/supervisor.js +508 -0
  232. package/dist/fleet/supervisor.js.map +1 -0
  233. package/dist/grounding/grounder.d.ts +46 -0
  234. package/dist/grounding/grounder.js +82 -0
  235. package/dist/grounding/grounder.js.map +1 -0
  236. package/dist/inbound/acp/handlers/device.d.ts +43 -0
  237. package/dist/inbound/acp/handlers/device.js +153 -0
  238. package/dist/inbound/acp/handlers/device.js.map +1 -0
  239. package/dist/inbound/acp/handlers/initialize.d.ts +71 -0
  240. package/dist/inbound/acp/handlers/initialize.js +53 -0
  241. package/dist/inbound/acp/handlers/initialize.js.map +1 -0
  242. package/dist/inbound/acp/handlers/models.d.ts +16 -0
  243. package/dist/inbound/acp/handlers/models.js +23 -0
  244. package/dist/inbound/acp/handlers/models.js.map +1 -0
  245. package/dist/inbound/acp/handlers/session.d.ts +51 -0
  246. package/dist/inbound/acp/handlers/session.js +61 -0
  247. package/dist/inbound/acp/handlers/session.js.map +1 -0
  248. package/dist/inbound/acp/handlers/skills.d.ts +8 -0
  249. package/dist/inbound/acp/handlers/skills.js +9 -0
  250. package/dist/inbound/acp/handlers/skills.js.map +1 -0
  251. package/dist/inbound/acp/notifier.d.ts +35 -0
  252. package/dist/inbound/acp/notifier.js +45 -0
  253. package/dist/inbound/acp/notifier.js.map +1 -0
  254. package/dist/inbound/acp/router.d.ts +67 -0
  255. package/dist/inbound/acp/router.js +179 -0
  256. package/dist/inbound/acp/router.js.map +1 -0
  257. package/dist/inbound/cli/fleet-command.d.ts +34 -0
  258. package/dist/inbound/cli/fleet-command.js +792 -0
  259. package/dist/inbound/cli/fleet-command.js.map +1 -0
  260. package/dist/inbound/cli/main.d.ts +38 -0
  261. package/dist/inbound/cli/main.js +364 -0
  262. package/dist/inbound/cli/main.js.map +1 -0
  263. package/dist/inbound/cli/run-command.d.ts +101 -0
  264. package/dist/inbound/cli/run-command.js +405 -0
  265. package/dist/inbound/cli/run-command.js.map +1 -0
  266. package/dist/inbound/cli/skills-command.d.ts +39 -0
  267. package/dist/inbound/cli/skills-command.js +333 -0
  268. package/dist/inbound/cli/skills-command.js.map +1 -0
  269. package/dist/inbound/http/server.d.ts +7 -0
  270. package/dist/inbound/http/server.js +8 -0
  271. package/dist/inbound/http/server.js.map +1 -0
  272. package/dist/index.d.ts +66 -0
  273. package/dist/index.js +48 -0
  274. package/dist/index.js.map +1 -0
  275. package/dist/logger/index.d.ts +37 -0
  276. package/dist/logger/index.js +84 -0
  277. package/dist/logger/index.js.map +1 -0
  278. package/dist/mcp-client/autospawn.d.ts +67 -0
  279. package/dist/mcp-client/autospawn.js +173 -0
  280. package/dist/mcp-client/autospawn.js.map +1 -0
  281. package/dist/mcp-client/client.d.ts +78 -0
  282. package/dist/mcp-client/client.js +168 -0
  283. package/dist/mcp-client/client.js.map +1 -0
  284. package/dist/mcp-client/index.d.ts +7 -0
  285. package/dist/mcp-client/index.js +4 -0
  286. package/dist/mcp-client/index.js.map +1 -0
  287. package/dist/mcp-client/inproc.d.ts +47 -0
  288. package/dist/mcp-client/inproc.js +229 -0
  289. package/dist/mcp-client/inproc.js.map +1 -0
  290. package/dist/mcp-client/runtime.d.ts +34 -0
  291. package/dist/mcp-client/runtime.js +15 -0
  292. package/dist/mcp-client/runtime.js.map +1 -0
  293. package/dist/model/adapters/autoglm.d.ts +31 -0
  294. package/dist/model/adapters/autoglm.js +409 -0
  295. package/dist/model/adapters/autoglm.js.map +1 -0
  296. package/dist/model/adapters/base.d.ts +13 -0
  297. package/dist/model/adapters/base.js +27 -0
  298. package/dist/model/adapters/base.js.map +1 -0
  299. package/dist/model/adapters/guiowl.d.ts +1 -0
  300. package/dist/model/adapters/guiowl.js +253 -0
  301. package/dist/model/adapters/guiowl.js.map +1 -0
  302. package/dist/model/adapters/index.d.ts +6 -0
  303. package/dist/model/adapters/index.js +8 -0
  304. package/dist/model/adapters/index.js.map +1 -0
  305. package/dist/model/adapters/maiui.d.ts +1 -0
  306. package/dist/model/adapters/maiui.js +117 -0
  307. package/dist/model/adapters/maiui.js.map +1 -0
  308. package/dist/model/adapters/qwenvl.d.ts +1 -0
  309. package/dist/model/adapters/qwenvl.js +108 -0
  310. package/dist/model/adapters/qwenvl.js.map +1 -0
  311. package/dist/model/adapters/showui.d.ts +1 -0
  312. package/dist/model/adapters/showui.js +132 -0
  313. package/dist/model/adapters/showui.js.map +1 -0
  314. package/dist/model/adapters/tool-call.d.ts +6 -0
  315. package/dist/model/adapters/tool-call.js +102 -0
  316. package/dist/model/adapters/tool-call.js.map +1 -0
  317. package/dist/model/adapters/uitars.d.ts +1 -0
  318. package/dist/model/adapters/uitars.js +180 -0
  319. package/dist/model/adapters/uitars.js.map +1 -0
  320. package/dist/model/base.d.ts +32 -0
  321. package/dist/model/base.js +2 -0
  322. package/dist/model/base.js.map +1 -0
  323. package/dist/model/client.d.ts +26 -0
  324. package/dist/model/client.js +300 -0
  325. package/dist/model/client.js.map +1 -0
  326. package/dist/model/image/compress.d.ts +53 -0
  327. package/dist/model/image/compress.js +89 -0
  328. package/dist/model/image/compress.js.map +1 -0
  329. package/dist/model/image/transport.d.ts +134 -0
  330. package/dist/model/image/transport.js +154 -0
  331. package/dist/model/image/transport.js.map +1 -0
  332. package/dist/orchestrator-system-prompt.d.ts +6 -0
  333. package/dist/orchestrator-system-prompt.js +81 -0
  334. package/dist/orchestrator-system-prompt.js.map +1 -0
  335. package/dist/pi-context.d.ts +82 -0
  336. package/dist/pi-context.js +62 -0
  337. package/dist/pi-context.js.map +1 -0
  338. package/dist/pi-local-skills.d.ts +17 -0
  339. package/dist/pi-local-skills.js +24 -0
  340. package/dist/pi-local-skills.js.map +1 -0
  341. package/dist/plugins/acp/index.d.ts +46 -0
  342. package/dist/plugins/acp/index.js +111 -0
  343. package/dist/plugins/acp/index.js.map +1 -0
  344. package/dist/plugins/agent-sync/index.d.ts +40 -0
  345. package/dist/plugins/agent-sync/index.js +98 -0
  346. package/dist/plugins/agent-sync/index.js.map +1 -0
  347. package/dist/plugins/http-debug/index.d.ts +30 -0
  348. package/dist/plugins/http-debug/index.js +64 -0
  349. package/dist/plugins/http-debug/index.js.map +1 -0
  350. package/dist/plugins/http-debug/server.d.ts +92 -0
  351. package/dist/plugins/http-debug/server.js +464 -0
  352. package/dist/plugins/http-debug/server.js.map +1 -0
  353. package/dist/ports/agent-core.d.ts +158 -0
  354. package/dist/ports/agent-core.js +2 -0
  355. package/dist/ports/agent-core.js.map +1 -0
  356. package/dist/ports/agent-host.d.ts +125 -0
  357. package/dist/ports/agent-host.js +23 -0
  358. package/dist/ports/agent-host.js.map +1 -0
  359. package/dist/ports/device.d.ts +53 -0
  360. package/dist/ports/device.js +13 -0
  361. package/dist/ports/device.js.map +1 -0
  362. package/dist/ports/identity.d.ts +22 -0
  363. package/dist/ports/identity.js +9 -0
  364. package/dist/ports/identity.js.map +1 -0
  365. package/dist/ports/plugin.d.ts +62 -0
  366. package/dist/ports/plugin.js +35 -0
  367. package/dist/ports/plugin.js.map +1 -0
  368. package/dist/ports/transport.d.ts +32 -0
  369. package/dist/ports/transport.js +12 -0
  370. package/dist/ports/transport.js.map +1 -0
  371. package/dist/ports/vlm.d.ts +59 -0
  372. package/dist/ports/vlm.js +14 -0
  373. package/dist/ports/vlm.js.map +1 -0
  374. package/dist/test-lan-autoglm.d.ts +7 -0
  375. package/dist/test-lan-autoglm.js +46 -0
  376. package/dist/test-lan-autoglm.js.map +1 -0
  377. package/dist/test-mem-breakdown.d.ts +1 -0
  378. package/dist/test-mem-breakdown.js +103 -0
  379. package/dist/test-mem-breakdown.js.map +1 -0
  380. package/dist/test-mem.d.ts +1 -0
  381. package/dist/test-mem.js +60 -0
  382. package/dist/test-mem.js.map +1 -0
  383. package/dist/test-mobile-use.d.ts +1 -0
  384. package/dist/test-mobile-use.js +18 -0
  385. package/dist/test-mobile-use.js.map +1 -0
  386. package/dist/test-screenshot-loop.d.ts +1 -0
  387. package/dist/test-screenshot-loop.js +43 -0
  388. package/dist/test-screenshot-loop.js.map +1 -0
  389. package/dist/test-screenshot.d.ts +1 -0
  390. package/dist/test-screenshot.js +10 -0
  391. package/dist/test-screenshot.js.map +1 -0
  392. package/dist/test-ui-xml-dump.d.ts +15 -0
  393. package/dist/test-ui-xml-dump.js +49 -0
  394. package/dist/test-ui-xml-dump.js.map +1 -0
  395. package/dist/types.d.ts +69 -0
  396. package/dist/types.js +23 -0
  397. package/dist/types.js.map +1 -0
  398. package/package.json +94 -0
@@ -0,0 +1,792 @@
1
+ /**
2
+ * inbound/cli/fleet-command — `device-agent fleet …` subcommand family.
3
+ *
4
+ * The fleet supervisor process is a single long-running daemon that:
5
+ *
6
+ * - Listens to ADB events (`adb track-devices`)
7
+ * - Watches `~/.beeos/devices.json` for binding changes
8
+ * - For every BOUND device, spawns and supervises:
9
+ * device-mcp-server (local AI tooling)
10
+ * device-agent (BeeOS cloud control daemon, Ed25519 → Agent Gateway)
11
+ * - Exposes a tiny HTTP status server on `127.0.0.1:7950` for the
12
+ * other CLI subcommands (`status`, `devices`, `restart`, `reload`).
13
+ *
14
+ * The CLI splits into two halves:
15
+ *
16
+ * server side: `start [--no-daemon]` → builds the `FleetSupervisor` and
17
+ * serves `/fleet/*` over HTTP.
18
+ * client side: `status | devices | restart | reload` → opens an HTTP
19
+ * connection to the running fleet on `:7950`.
20
+ *
21
+ * All client-side commands fail fast with an actionable hint when the
22
+ * fleet isn't running. There is intentionally NO auto-spawn: the user is
23
+ * expected to start the fleet via `fleet start` (foreground) or `fleet
24
+ * enable` (launchd / systemd, M5 in a follow-up plan).
25
+ */
26
+ import * as os from "node:os";
27
+ import * as path from "node:path";
28
+ import * as fs from "node:fs/promises";
29
+ import { BeeosCliStore, defaultDevicesPath, } from "../../fleet/adapters/state/beeos-cli-store.js";
30
+ import { StickyPortAllocator, defaultFleetStatePath } from "../../fleet/adapters/state/port-allocator.js";
31
+ import { LocalAdbSource } from "../../fleet/adapters/sources/local-adb.js";
32
+ import { NodeProcessManager } from "../../fleet/adapters/process/node-process-manager.js";
33
+ import { SystemClock } from "../../fleet/ports/clock.js";
34
+ import { FleetSupervisor } from "../../fleet/supervisor.js";
35
+ import { StatusServer } from "../../fleet/http/status-server.js";
36
+ import { FleetStatusClient, FleetClientError } from "../../fleet/http/status-client.js";
37
+ import { buildFleetServiceSpec, deriveFleetSpawnEnv, FLEET_LABEL, fleetPlistPath, installFleetLaunchd, migrateFromAttach, uninstallFleetLaunchd, } from "../../fleet/installer/index.js";
38
+ import { getLogger } from "../../logger/index.js";
39
+ export async function fleetCommand(argv, io = {}) {
40
+ const stdout = io.stdout ?? process.stdout;
41
+ const stderr = io.stderr ?? process.stderr;
42
+ const sub = argv[0];
43
+ if (!sub || sub === "-h" || sub === "--help" || sub === "help") {
44
+ printUsage(stdout);
45
+ return sub ? 0 : 2;
46
+ }
47
+ switch (sub) {
48
+ case "start":
49
+ return startCommand(argv.slice(1), { stdout, stderr });
50
+ case "status":
51
+ return statusCommand({ stdout, stderr });
52
+ case "devices":
53
+ return devicesCommand(argv.slice(1), { stdout, stderr });
54
+ case "restart":
55
+ return restartCommand(argv.slice(1), { stdout, stderr });
56
+ case "reload":
57
+ return reloadCommand({ stdout, stderr });
58
+ case "stop":
59
+ return stopCommand({ stdout, stderr });
60
+ case "enable":
61
+ return enableCommand(argv.slice(1), { stdout, stderr });
62
+ case "disable":
63
+ return disableCommand({ stdout, stderr });
64
+ case "migrate-from-attach":
65
+ return migrateCommand({ stdout, stderr });
66
+ case "logs":
67
+ return logsCommand(argv.slice(1), { stdout, stderr });
68
+ default:
69
+ stderr.write(`device-agent fleet: unknown subcommand '${sub}'\n`);
70
+ printUsage(stderr);
71
+ return 2;
72
+ }
73
+ }
74
+ function parseStartArgs(argv) {
75
+ const out = {};
76
+ for (let i = 0; i < argv.length; i++) {
77
+ const a = argv[i];
78
+ const next = () => {
79
+ const v = argv[++i];
80
+ if (v === undefined)
81
+ throw new Error(`Missing value for ${a}`);
82
+ return v;
83
+ };
84
+ switch (a) {
85
+ case "-h":
86
+ case "--help":
87
+ out.help = true;
88
+ break;
89
+ case "--no-daemon":
90
+ out.noDaemon = true;
91
+ break;
92
+ case "--agent-gateway-url":
93
+ out.agentGatewayUrl = next();
94
+ break;
95
+ case "--grace-ms":
96
+ out.graceMs = Number(next());
97
+ break;
98
+ case "--keep-ms":
99
+ out.keepMs = Number(next());
100
+ break;
101
+ case "--port":
102
+ out.port = Number(next());
103
+ break;
104
+ default:
105
+ if (a.startsWith("--")) {
106
+ throw new Error(`device-agent fleet start: unknown flag ${a}`);
107
+ }
108
+ }
109
+ }
110
+ return out;
111
+ }
112
+ async function startCommand(argv, io) {
113
+ let flags;
114
+ try {
115
+ flags = parseStartArgs(argv);
116
+ }
117
+ catch (e) {
118
+ io.stderr.write(`${e.message}\n`);
119
+ return 2;
120
+ }
121
+ if (flags.help) {
122
+ io.stdout.write(`device-agent fleet start — run the supervisor in the foreground
123
+
124
+ Usage:
125
+ device-agent fleet start [options]
126
+
127
+ Options:
128
+ --no-daemon (reserved) skip OS service detach (current default)
129
+ --agent-gateway-url URL Default Agent Gateway URL injected into spawned daemons
130
+ --grace-ms <n> HEALTHY → DEGRADED window in ms (default 5000, env FLEET_ADB_GRACE_MS)
131
+ --keep-ms <n> DEGRADED → GONE window in ms (default 300000, env FLEET_DAEMON_KEEP_MS)
132
+ --port <n> Status HTTP port on loopback (default 7950, env FLEET_STATUS_PORT)
133
+ -h, --help Show this help
134
+ `);
135
+ return 0;
136
+ }
137
+ const log = getLogger().child({ component: "fleet" });
138
+ const supervisorLogger = {
139
+ debug: (msg, data) => log.debug({ ...data }, msg),
140
+ info: (msg, data) => log.info({ ...data }, msg),
141
+ warn: (msg, data) => log.warn({ ...data }, msg),
142
+ error: (msg, data) => log.error({ ...data }, msg),
143
+ };
144
+ const registry = new BeeosCliStore({ filePath: defaultDevicesPath() });
145
+ const allocator = new StickyPortAllocator({ filePath: defaultFleetStatePath() });
146
+ // NOTE: every adapter inside `fleet/` defines its OWN logger shape
147
+ // — `(msg: string, data?: Record<string, unknown>)`. Pino's runtime
148
+ // calling convention is the OPPOSITE: `(obj, msg)`. Passing the
149
+ // raw pino logger therefore swallows every structured field
150
+ // (observed in M11 dogfooding: `child error` arrived without
151
+ // `serial` / `error`). The wrapper above (`supervisorLogger`)
152
+ // bridges the two conventions, so every adapter must use it
153
+ // — not the bare `log`.
154
+ const source = new LocalAdbSource({ logger: supervisorLogger });
155
+ const processManager = new NodeProcessManager({ logger: supervisorLogger });
156
+ const clock = new SystemClock();
157
+ const supervisor = new FleetSupervisor({
158
+ source,
159
+ registry,
160
+ allocator,
161
+ processManager,
162
+ clock,
163
+ graceMs: flags.graceMs,
164
+ keepMs: flags.keepMs,
165
+ logger: supervisorLogger,
166
+ defaultAgentGatewayUrl: flags.agentGatewayUrl ?? process.env.AGENT_GATEWAY_URL ?? undefined,
167
+ });
168
+ let stopping = false;
169
+ const shutdown = async (signal) => {
170
+ if (stopping)
171
+ return 0;
172
+ stopping = true;
173
+ log.info({ signal }, "fleet shutdown initiated");
174
+ try {
175
+ await status.stop();
176
+ await supervisor.stop();
177
+ log.info("fleet shutdown complete");
178
+ return 0;
179
+ }
180
+ catch (e) {
181
+ log.error({ err: String(e) }, "fleet shutdown failed");
182
+ return 1;
183
+ }
184
+ };
185
+ const status = new StatusServer({
186
+ supervisor,
187
+ port: flags.port ?? Number(process.env.FLEET_STATUS_PORT ?? 7950),
188
+ logger: supervisorLogger,
189
+ onShutdown: () => {
190
+ // POST /fleet/shutdown — defer to the same path as SIGTERM so we
191
+ // exit with the same lifecycle order regardless of whether the
192
+ // signal came from launchd, the user, or the CLI's `fleet stop`.
193
+ void shutdown("HTTP /fleet/shutdown").then((c) => process.exit(c));
194
+ },
195
+ });
196
+ process.once("SIGINT", () => {
197
+ void shutdown("SIGINT").then((c) => process.exit(c));
198
+ });
199
+ process.once("SIGTERM", () => {
200
+ void shutdown("SIGTERM").then((c) => process.exit(c));
201
+ });
202
+ try {
203
+ await supervisor.start();
204
+ await status.start();
205
+ log.info({
206
+ host: status.address.host,
207
+ port: status.address.port,
208
+ beeosHome: defaultDevicesPath(),
209
+ host_os: os.platform(),
210
+ }, "fleet supervisor running");
211
+ }
212
+ catch (e) {
213
+ log.error({ err: String(e) }, "fleet supervisor failed to start");
214
+ await status.stop().catch(() => { });
215
+ await supervisor.stop().catch(() => { });
216
+ return 1;
217
+ }
218
+ await new Promise((resolve) => {
219
+ process.once("beforeExit", () => resolve());
220
+ });
221
+ return 0;
222
+ }
223
+ // ── client-side commands ────────────────────────────────────────────────────
224
+ async function statusCommand(io) {
225
+ const client = new FleetStatusClient();
226
+ const alive = await client.healthz();
227
+ if (!alive) {
228
+ io.stdout.write("fleet: NOT RUNNING\n");
229
+ io.stdout.write("hint: start it with `device-agent fleet start`\n");
230
+ return 1;
231
+ }
232
+ try {
233
+ const devices = await client.listDevices();
234
+ io.stdout.write(`fleet: RUNNING (${devices.length} device${devices.length === 1 ? "" : "s"})\n`);
235
+ return 0;
236
+ }
237
+ catch (e) {
238
+ if (e instanceof FleetClientError) {
239
+ io.stderr.write(`${e.message}\n`);
240
+ return 1;
241
+ }
242
+ throw e;
243
+ }
244
+ }
245
+ function parseDevicesArgs(argv) {
246
+ const out = {};
247
+ for (const a of argv) {
248
+ if (a === "--json")
249
+ out.json = true;
250
+ else if (a === "-h" || a === "--help")
251
+ out.help = true;
252
+ else if (a.startsWith("--"))
253
+ throw new Error(`fleet devices: unknown flag ${a}`);
254
+ }
255
+ return out;
256
+ }
257
+ async function devicesCommand(argv, io) {
258
+ let flags;
259
+ try {
260
+ flags = parseDevicesArgs(argv);
261
+ }
262
+ catch (e) {
263
+ io.stderr.write(`${e.message}\n`);
264
+ return 2;
265
+ }
266
+ if (flags.help) {
267
+ io.stdout.write(`device-agent fleet devices — list managed devices
268
+
269
+ Usage:
270
+ device-agent fleet devices [--json]
271
+ `);
272
+ return 0;
273
+ }
274
+ const client = new FleetStatusClient();
275
+ let devices;
276
+ try {
277
+ devices = await client.listDevices();
278
+ }
279
+ catch (e) {
280
+ if (e instanceof FleetClientError) {
281
+ io.stderr.write(`${e.message}\n`);
282
+ return 1;
283
+ }
284
+ throw e;
285
+ }
286
+ if (flags.json) {
287
+ io.stdout.write(`${JSON.stringify(devices, null, 2)}\n`);
288
+ return 0;
289
+ }
290
+ if (devices.length === 0) {
291
+ io.stdout.write("(no devices discovered)\n");
292
+ return 0;
293
+ }
294
+ const rows = [
295
+ ["SERIAL", "NAME", "STATE", "INSTANCE", "MCP", "DAEMON", "SCRCPY", "AGE"],
296
+ ];
297
+ for (const d of devices) {
298
+ rows.push([
299
+ d.serial,
300
+ d.name,
301
+ d.state.toUpperCase(),
302
+ d.instanceId ?? "—",
303
+ d.mcpUrl
304
+ ? `${d.mcpUrl}${d.mcpPid ? ` pid:${d.mcpPid}` : ""}`
305
+ : "—",
306
+ d.daemonPid ? `pid:${d.daemonPid}` : "—",
307
+ formatScrcpy(d.scrcpy),
308
+ formatAge(d.sinceMs),
309
+ ]);
310
+ }
311
+ io.stdout.write(formatTable(rows));
312
+ return 0;
313
+ }
314
+ async function restartCommand(argv, io) {
315
+ const target = argv[0];
316
+ if (!target || target === "-h" || target === "--help") {
317
+ io.stdout.write(`device-agent fleet restart — restart a device's mcp + daemon pair
318
+
319
+ Usage:
320
+ device-agent fleet restart <serial-or-name>
321
+ `);
322
+ return target ? 0 : 2;
323
+ }
324
+ const client = new FleetStatusClient();
325
+ // Resolve name → serial first if needed.
326
+ let serial = target;
327
+ try {
328
+ const devices = await client.listDevices();
329
+ const match = devices.find((d) => d.serial === target || d.name === target);
330
+ if (!match) {
331
+ io.stderr.write(`fleet: no device matches '${target}'.\n`);
332
+ io.stderr.write("hint: run `device-agent fleet devices` to see available serials.\n");
333
+ return 1;
334
+ }
335
+ serial = match.serial;
336
+ }
337
+ catch (e) {
338
+ if (e instanceof FleetClientError) {
339
+ io.stderr.write(`${e.message}\n`);
340
+ return 1;
341
+ }
342
+ throw e;
343
+ }
344
+ try {
345
+ const ok = await client.restartDevice(serial);
346
+ if (!ok) {
347
+ io.stderr.write(`fleet: serial '${serial}' is unknown to the supervisor.\n`);
348
+ return 1;
349
+ }
350
+ io.stdout.write(`fleet: restart accepted for ${serial}\n`);
351
+ return 0;
352
+ }
353
+ catch (e) {
354
+ if (e instanceof FleetClientError) {
355
+ io.stderr.write(`${e.message}\n`);
356
+ return 1;
357
+ }
358
+ throw e;
359
+ }
360
+ }
361
+ async function reloadCommand(io) {
362
+ const client = new FleetStatusClient();
363
+ try {
364
+ await client.reload();
365
+ io.stdout.write("fleet: reload accepted\n");
366
+ return 0;
367
+ }
368
+ catch (e) {
369
+ if (e instanceof FleetClientError) {
370
+ io.stderr.write(`${e.message}\n`);
371
+ return 1;
372
+ }
373
+ throw e;
374
+ }
375
+ }
376
+ function parseEnableArgs(argv) {
377
+ const out = {};
378
+ for (let i = 0; i < argv.length; i++) {
379
+ const a = argv[i];
380
+ const next = () => {
381
+ const v = argv[++i];
382
+ if (v === undefined)
383
+ throw new Error(`Missing value for ${a}`);
384
+ return v;
385
+ };
386
+ switch (a) {
387
+ case "-h":
388
+ case "--help":
389
+ out.help = true;
390
+ break;
391
+ case "--cli-entry":
392
+ out.cliEntry = next();
393
+ break;
394
+ case "--agent-gateway-url":
395
+ out.agentGatewayUrl = next();
396
+ break;
397
+ case "--grace-ms":
398
+ out.graceMs = Number(next());
399
+ break;
400
+ case "--keep-ms":
401
+ out.keepMs = Number(next());
402
+ break;
403
+ case "--port":
404
+ out.port = Number(next());
405
+ break;
406
+ default:
407
+ if (a.startsWith("--")) {
408
+ throw new Error(`device-agent fleet enable: unknown flag ${a}`);
409
+ }
410
+ }
411
+ }
412
+ return out;
413
+ }
414
+ async function enableCommand(argv, io) {
415
+ let flags;
416
+ try {
417
+ flags = parseEnableArgs(argv);
418
+ }
419
+ catch (e) {
420
+ io.stderr.write(`${e.message}\n`);
421
+ return 2;
422
+ }
423
+ if (flags.help) {
424
+ io.stdout.write(`device-agent fleet enable — register the fleet supervisor as an OS service
425
+
426
+ Usage:
427
+ device-agent fleet enable [options]
428
+
429
+ Options:
430
+ --cli-entry PATH Absolute path to the device-agent CLI entry. Defaults
431
+ to the entry that's running this command.
432
+ --agent-gateway-url URL Agent Gateway URL injected into spawned daemons.
433
+ Defaults to the AGENT_GATEWAY_URL env var.
434
+ --grace-ms <n> HEALTHY → DEGRADED window (env FLEET_ADB_GRACE_MS).
435
+ --keep-ms <n> DEGRADED → GONE window (env FLEET_DAEMON_KEEP_MS).
436
+ --port <n> Override status server port (env FLEET_STATUS_PORT).
437
+
438
+ Currently macOS-only. Linux (systemd --user) and Windows (Task Scheduler)
439
+ support is tracked separately.
440
+ `);
441
+ return 0;
442
+ }
443
+ if (process.platform !== "darwin") {
444
+ io.stderr.write(`device-agent fleet enable: not yet supported on ${process.platform}.\n` +
445
+ "Run `device-agent fleet start` manually instead.\n");
446
+ return 2;
447
+ }
448
+ const cliEntry = flags.cliEntry ?? resolveCliEntryGuess();
449
+ if (!cliEntry) {
450
+ io.stderr.write("fleet enable: could not detect device-agent CLI entry path. " +
451
+ "Re-run with `--cli-entry /absolute/path/to/cli.js`.\n");
452
+ return 2;
453
+ }
454
+ if (!path.isAbsolute(cliEntry)) {
455
+ io.stderr.write(`fleet enable: --cli-entry must be absolute: ${cliEntry}\n`);
456
+ return 2;
457
+ }
458
+ if (!(await fileExists(cliEntry))) {
459
+ io.stderr.write(`fleet enable: --cli-entry not found: ${cliEntry}\n`);
460
+ return 2;
461
+ }
462
+ // Build the operator-level overrides (CLI flags + explicit env). The
463
+ // derivation step seeds defaults (PATH, BEEOS_DEVICE_*_BIN,
464
+ // AGENT_GATEWAY_URL/BRIDGE_URL from ~/.beeos/config.toml) which the
465
+ // overrides win over.
466
+ const overrides = {};
467
+ const explicitAgw = flags.agentGatewayUrl ?? process.env.AGENT_GATEWAY_URL;
468
+ if (explicitAgw)
469
+ overrides.AGENT_GATEWAY_URL = explicitAgw;
470
+ if (flags.graceMs !== undefined && Number.isFinite(flags.graceMs)) {
471
+ overrides.FLEET_ADB_GRACE_MS = String(flags.graceMs);
472
+ }
473
+ if (flags.keepMs !== undefined && Number.isFinite(flags.keepMs)) {
474
+ overrides.FLEET_DAEMON_KEEP_MS = String(flags.keepMs);
475
+ }
476
+ if (flags.port !== undefined && Number.isFinite(flags.port)) {
477
+ overrides.FLEET_STATUS_PORT = String(flags.port);
478
+ }
479
+ const { env, warnings: envWarnings } = await deriveFleetSpawnEnv({
480
+ cliEntry,
481
+ overrides,
482
+ });
483
+ const spec = buildFleetServiceSpec({ cliEntry, env });
484
+ let result;
485
+ try {
486
+ result = await installFleetLaunchd(spec);
487
+ }
488
+ catch (e) {
489
+ io.stderr.write(`fleet enable: install failed: ${e.message}\n`);
490
+ return 1;
491
+ }
492
+ io.stdout.write(`fleet enabled (label=${spec.label})\n`);
493
+ io.stdout.write(` plist: ${result.plistPath}\n`);
494
+ io.stdout.write(` log: ${spec.logFile}\n`);
495
+ io.stdout.write(` bootstrap: ${result.bootstrapped ? "ok" : "skipped (see warnings)"}\n`);
496
+ // Visibility into discovered binaries / config so operators can spot
497
+ // a misconfigured AGENT_GATEWAY_URL or missing scrcpy-bridge BEFORE
498
+ // children start crashing. Logged in dependency order so a missing
499
+ // PATH (rare) shows up first.
500
+ if (env.PATH)
501
+ io.stdout.write(` PATH: captured\n`);
502
+ if (env.AGENT_GATEWAY_URL) {
503
+ io.stdout.write(` agent-gateway-url: ${env.AGENT_GATEWAY_URL}\n`);
504
+ }
505
+ else {
506
+ io.stdout.write(` agent-gateway-url: <unset> (set --agent-gateway-url or platform.agent_gateway_url in ~/.beeos/config.toml)\n`);
507
+ }
508
+ if (env.BEEOS_DEVICE_AGENT_BIN) {
509
+ io.stdout.write(` device-agent: ${env.BEEOS_DEVICE_AGENT_BIN}\n`);
510
+ }
511
+ if (env.BEEOS_DEVICE_MCP_BIN) {
512
+ io.stdout.write(` device-mcp: ${env.BEEOS_DEVICE_MCP_BIN}\n`);
513
+ }
514
+ if (env.BEEOS_SCRCPY_BRIDGE_BIN) {
515
+ io.stdout.write(` scrcpy-bridge: ${env.BEEOS_SCRCPY_BRIDGE_BIN}\n`);
516
+ }
517
+ for (const w of envWarnings) {
518
+ io.stdout.write(` warning: ${w}\n`);
519
+ }
520
+ for (const w of result.warnings) {
521
+ io.stdout.write(` warning: ${w}\n`);
522
+ }
523
+ io.stdout.write("Verify: launchctl print gui/$(id -u)/" + spec.label + " # or `device-agent fleet status`\n");
524
+ return 0;
525
+ }
526
+ async function disableCommand(io) {
527
+ if (process.platform !== "darwin") {
528
+ io.stderr.write(`device-agent fleet disable: not yet supported on ${process.platform}.\n`);
529
+ return 2;
530
+ }
531
+ let result;
532
+ try {
533
+ result = await uninstallFleetLaunchd(FLEET_LABEL);
534
+ }
535
+ catch (e) {
536
+ io.stderr.write(`fleet disable failed: ${e.message}\n`);
537
+ return 1;
538
+ }
539
+ if (!result.removed) {
540
+ io.stdout.write(`fleet: nothing installed (${result.plistPath} not found)\n`);
541
+ }
542
+ else {
543
+ io.stdout.write(`fleet disabled — removed ${result.plistPath}\n`);
544
+ }
545
+ for (const w of result.warnings) {
546
+ io.stdout.write(` warning: ${w}\n`);
547
+ }
548
+ return 0;
549
+ }
550
+ async function migrateCommand(io) {
551
+ if (process.platform !== "darwin") {
552
+ io.stderr.write(`device-agent fleet migrate-from-attach: not yet supported on ${process.platform}.\n`);
553
+ return 2;
554
+ }
555
+ let result;
556
+ try {
557
+ result = await migrateFromAttach();
558
+ }
559
+ catch (e) {
560
+ io.stderr.write(`fleet migrate failed: ${e.message}\n`);
561
+ return 1;
562
+ }
563
+ const a = result.removedDeviceAgents.length;
564
+ const b = result.removedScrcpyBridges.length;
565
+ if (a === 0 && b === 0) {
566
+ io.stdout.write("fleet: no legacy per-device launchd entries found\n");
567
+ }
568
+ else {
569
+ io.stdout.write(`Removed ${a} device-agent + ${b} scrcpy-bridge launchd entries; fleet now exclusive\n`);
570
+ for (const label of result.removedDeviceAgents) {
571
+ io.stdout.write(` - ${label}\n`);
572
+ }
573
+ for (const label of result.removedScrcpyBridges) {
574
+ io.stdout.write(` - ${label}\n`);
575
+ }
576
+ }
577
+ for (const w of result.warnings) {
578
+ io.stdout.write(` warning: ${w}\n`);
579
+ }
580
+ return 0;
581
+ }
582
+ async function stopCommand(io) {
583
+ // Prefer the in-band shutdown route — it lets a fleet started in the
584
+ // foreground (e.g. via `goreman` or `pnpm dev`) exit cleanly without
585
+ // launchctl. Fall back to launchctl stop only when the HTTP route is
586
+ // unreachable AND we're on macOS.
587
+ const client = new FleetStatusClient();
588
+ if (await client.healthz()) {
589
+ try {
590
+ const accepted = await client.shutdown();
591
+ if (accepted) {
592
+ io.stdout.write("fleet: shutdown requested via HTTP\n");
593
+ return 0;
594
+ }
595
+ io.stdout.write("fleet: HTTP shutdown not supported by this supervisor build; falling back to launchctl\n");
596
+ }
597
+ catch (e) {
598
+ if (!(e instanceof FleetClientError))
599
+ throw e;
600
+ io.stderr.write(`fleet: HTTP shutdown failed: ${e.message}\n`);
601
+ }
602
+ }
603
+ if (process.platform !== "darwin") {
604
+ io.stderr.write("fleet stop: HTTP unreachable and launchctl fallback only available on macOS.\n");
605
+ return 1;
606
+ }
607
+ try {
608
+ const { execFile } = await import("node:child_process");
609
+ const { promisify } = await import("node:util");
610
+ const execFileP = promisify(execFile);
611
+ await execFileP("launchctl", ["stop", FLEET_LABEL]);
612
+ io.stdout.write("fleet: launchctl stop issued\n");
613
+ return 0;
614
+ }
615
+ catch (e) {
616
+ io.stderr.write(`fleet stop: launchctl fallback failed: ${e.message}\n`);
617
+ return 1;
618
+ }
619
+ }
620
+ function parseLogsArgs(argv) {
621
+ const out = {};
622
+ for (const a of argv) {
623
+ if (a === "-f" || a === "--follow")
624
+ out.follow = true;
625
+ else if (a === "-h" || a === "--help")
626
+ out.help = true;
627
+ else if (a.startsWith("--"))
628
+ throw new Error(`fleet logs: unknown flag ${a}`);
629
+ else if (!out.serial)
630
+ out.serial = a;
631
+ }
632
+ return out;
633
+ }
634
+ async function logsCommand(argv, io) {
635
+ let flags;
636
+ try {
637
+ flags = parseLogsArgs(argv);
638
+ }
639
+ catch (e) {
640
+ io.stderr.write(`${e.message}\n`);
641
+ return 2;
642
+ }
643
+ if (flags.help) {
644
+ io.stdout.write(`device-agent fleet logs — tail the fleet supervisor log
645
+
646
+ Usage:
647
+ device-agent fleet logs [-f] [serial]
648
+
649
+ Options:
650
+ -f, --follow Follow new lines (like \`tail -f\`)
651
+ serial Filter to lines containing this serial (substring match)
652
+ `);
653
+ return 0;
654
+ }
655
+ const logFile = path.join(beeosHome(), "logs", "device-fleet.log");
656
+ if (!(await fileExists(logFile))) {
657
+ io.stderr.write(`fleet logs: ${logFile} does not exist yet — has the fleet been started?\n` +
658
+ " hint: `device-agent fleet enable` (launchd) or `device-agent fleet start` (foreground)\n");
659
+ return 1;
660
+ }
661
+ const grep = flags.serial;
662
+ // Use `tail` for follow + grep — far simpler than reimplementing
663
+ // streaming + filter in Node and matches what an operator would type
664
+ // by hand. This is intentionally a thin convenience wrapper.
665
+ const { spawn } = await import("node:child_process");
666
+ const tailArgs = flags.follow ? ["-n", "200", "-f", logFile] : ["-n", "1000", logFile];
667
+ const tail = spawn("tail", tailArgs, { stdio: ["ignore", "pipe", "inherit"] });
668
+ return await new Promise((resolve) => {
669
+ if (!tail.stdout) {
670
+ io.stderr.write("fleet logs: failed to capture tail stdout\n");
671
+ resolve(1);
672
+ return;
673
+ }
674
+ let buf = "";
675
+ tail.stdout.setEncoding("utf8");
676
+ tail.stdout.on("data", (chunk) => {
677
+ buf += chunk;
678
+ const lines = buf.split("\n");
679
+ buf = lines.pop() ?? "";
680
+ for (const line of lines) {
681
+ if (grep && !line.includes(grep))
682
+ continue;
683
+ io.stdout.write(`${line}\n`);
684
+ }
685
+ });
686
+ tail.on("close", (code) => {
687
+ if (buf) {
688
+ if (!grep || buf.includes(grep))
689
+ io.stdout.write(buf);
690
+ }
691
+ resolve(code ?? 0);
692
+ });
693
+ tail.on("error", (err) => {
694
+ io.stderr.write(`fleet logs: tail spawn failed: ${err.message}\n`);
695
+ resolve(1);
696
+ });
697
+ // Forward Ctrl-C cleanly when running in --follow.
698
+ process.once("SIGINT", () => {
699
+ tail.kill("SIGINT");
700
+ });
701
+ });
702
+ }
703
+ // ── helpers ─────────────────────────────────────────────────────────────────
704
+ /**
705
+ * Best-effort detection of the device-agent CLI entry — what the current
706
+ * process is running. Used as the default `--cli-entry` for `fleet
707
+ * enable` so users don't have to type a path. Returns null when running
708
+ * via REPL / unit test where the entry isn't a stable file.
709
+ */
710
+ function resolveCliEntryGuess() {
711
+ // Node populates argv[1] with the script path when launched via
712
+ // `node /path/to/script.js …`. Anything else (e.g. REPL, --eval) is
713
+ // not a reliable path we can hand to launchd.
714
+ const script = process.argv[1];
715
+ if (!script || !path.isAbsolute(script))
716
+ return null;
717
+ return script;
718
+ }
719
+ /** Resolve the BeeOS home dir (override-aware). */
720
+ function beeosHome() {
721
+ const override = process.env.BEEOS_HOME;
722
+ if (override && override.length > 0)
723
+ return override;
724
+ return path.join(os.homedir(), ".beeos");
725
+ }
726
+ async function fileExists(p) {
727
+ try {
728
+ await fs.stat(p);
729
+ return true;
730
+ }
731
+ catch {
732
+ return false;
733
+ }
734
+ }
735
+ // Avoid unused-warning for fleetPlistPath (will be used by tests/docs).
736
+ void fleetPlistPath;
737
+ function printUsage(out) {
738
+ out.write(`device-agent fleet — multi-device supervisor
739
+
740
+ Usage:
741
+ device-agent fleet start [options] Run the supervisor (foreground)
742
+ device-agent fleet enable [--cli-entry PATH] Register OS service (macOS launchd)
743
+ device-agent fleet disable Stop + unregister OS service
744
+ device-agent fleet migrate-from-attach Remove legacy per-device launchd entries
745
+ device-agent fleet stop Graceful shutdown of running supervisor
746
+ device-agent fleet logs [-f] [serial] Tail fleet log (filtered by serial)
747
+ device-agent fleet status Print supervisor liveness
748
+ device-agent fleet devices [--json] List managed devices
749
+ device-agent fleet restart <serial-or-name> Restart one device's mcp + daemon
750
+ device-agent fleet reload Re-read ~/.beeos/devices.json
751
+
752
+ Environment:
753
+ FLEET_STATUS_PORT HTTP status server port (default 7950)
754
+ FLEET_ADB_GRACE_MS HEALTHY → DEGRADED window (default 5000)
755
+ FLEET_DAEMON_KEEP_MS DEGRADED → GONE window (default 300000)
756
+ AGENT_GATEWAY_URL Default Agent Gateway URL for spawned daemons
757
+ BEEOS_HOME Override ~/.beeos location
758
+ `);
759
+ }
760
+ function formatTable(rows) {
761
+ if (rows.length === 0)
762
+ return "";
763
+ const widths = rows[0].map((_, i) => Math.max(...rows.map((r) => (r[i] ?? "").length)));
764
+ const lines = [];
765
+ for (const r of rows) {
766
+ lines.push(r
767
+ .map((cell, i) => (cell ?? "").padEnd(widths[i]))
768
+ .join(" ")
769
+ .trimEnd());
770
+ }
771
+ return `${lines.join("\n")}\n`;
772
+ }
773
+ function formatScrcpy(status) {
774
+ if (!status.enabled)
775
+ return "—";
776
+ if (status.running)
777
+ return status.pid ? `pid:${status.pid}` : "running";
778
+ return status.lastError ? `err:${status.lastError}` : "off";
779
+ }
780
+ function formatAge(ms) {
781
+ if (ms < 1_000)
782
+ return `${ms}ms`;
783
+ const s = Math.floor(ms / 1_000);
784
+ if (s < 60)
785
+ return `${s}s`;
786
+ const m = Math.floor(s / 60);
787
+ if (m < 60)
788
+ return `${m}m${s % 60}s`;
789
+ const h = Math.floor(m / 60);
790
+ return `${h}h${m % 60}m`;
791
+ }
792
+ //# sourceMappingURL=fleet-command.js.map