@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,224 @@
1
+ /**
2
+ * Fleet OS-service spawn-env derivation.
3
+ *
4
+ * Goal: make `device-agent fleet enable` produce a launchd plist whose
5
+ * `EnvironmentVariables` block has EVERYTHING the supervisor needs to
6
+ * spawn its mcp + daemon (+ optional scrcpy) children, without the user
7
+ * having to hand-edit the plist.
8
+ *
9
+ * Concretely, when we install the fleet plist we capture three pieces
10
+ * of state from the operator's current login shell:
11
+ *
12
+ * 1. **PATH** — the launchd `EnvironmentVariables` we inherit on a
13
+ * fresh boot is minimal (`/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin`),
14
+ * so spawned children can't resolve `adb`, `node`, our managed
15
+ * `~/.beeos/bin/*` shims, or anything from the user's profile.
16
+ * We snapshot `process.env.PATH` at install time so the supervisor
17
+ * and ITS children see the same PATH the operator did when they
18
+ * ran `device-agent fleet enable`.
19
+ *
20
+ * 2. **Binary overrides** — `NodeProcessManager` defaults to bare
21
+ * names (`device-agent`, `device-mcp-server`, `scrcpy-bridge`)
22
+ * and relies on PATH. To make the chain robust against PATH
23
+ * drift we also seed `BEEOS_DEVICE_AGENT_BIN`,
24
+ * `BEEOS_DEVICE_MCP_BIN`, and `BEEOS_SCRCPY_BRIDGE_BIN` with
25
+ * absolute paths discovered now. Sibling-of-cliEntry is the
26
+ * cheapest discovery (covers `~/.beeos/bin/` from
27
+ * `install-local.sh` and `node_modules/.bin/` from npm
28
+ * installs); `~/.beeos/bin/` and `which` are progressive
29
+ * fallbacks.
30
+ *
31
+ * 3. **Platform URLs** — `AGENT_GATEWAY_URL` (and `BRIDGE_URL` when
32
+ * present) are read from `~/.beeos/config.toml` so the daemons
33
+ * the fleet spawns talk to the same backend the rest of BeeOS
34
+ * CLI does. The operator can still override either one
35
+ * explicitly via `--agent-gateway-url` on `fleet enable` or by
36
+ * editing the plist after install.
37
+ *
38
+ * This module is intentionally pure: every external resource is
39
+ * abstracted behind an injected hook (`fileExists`, `which`,
40
+ * `readConfig`) so unit tests can drive every branch deterministically.
41
+ */
42
+ import { execFile } from "node:child_process";
43
+ import * as fs from "node:fs/promises";
44
+ import * as os from "node:os";
45
+ import * as path from "node:path";
46
+ import { promisify } from "node:util";
47
+ const execFileP = promisify(execFile);
48
+ /**
49
+ * The list of binaries the supervisor needs to spawn (mcp / daemon /
50
+ * scrcpy). Each entry maps to the env var the
51
+ * `NodeProcessManager` reads when an explicit override is required.
52
+ */
53
+ const SUPERVISED_BINARIES = [
54
+ { envVar: "BEEOS_DEVICE_AGENT_BIN", bin: "device-agent", required: true },
55
+ { envVar: "BEEOS_DEVICE_MCP_BIN", bin: "device-mcp-server", required: true },
56
+ { envVar: "BEEOS_SCRCPY_BRIDGE_BIN", bin: "scrcpy-bridge", required: false },
57
+ ];
58
+ /**
59
+ * Derive the env vars that should be threaded into the launchd
60
+ * `EnvironmentVariables` block for the fleet plist.
61
+ *
62
+ * Returns ONLY the keys that have a value — `installFleetLaunchd` will
63
+ * merge them with `BEEOS_HOME` (always) and `PATH` (defaulted to the
64
+ * minimal mac PATH if neither operator nor this function provides one).
65
+ */
66
+ export async function deriveFleetSpawnEnv(opts) {
67
+ const env = {};
68
+ const warnings = [];
69
+ const fe = opts.fileExists ?? defaultFileExists;
70
+ const wh = opts.whichBin ?? defaultWhich;
71
+ const rc = opts.readConfigToml ?? defaultReadConfigToml;
72
+ const currentEnv = opts.currentEnv ?? process.env;
73
+ // 1. Snapshot the current shell's PATH so launchd-spawned children
74
+ // resolve `adb`, `node`, `~/.beeos/bin/*` etc. the same way the
75
+ // user's interactive shell does.
76
+ if (currentEnv.PATH && currentEnv.PATH.length > 0) {
77
+ env.PATH = currentEnv.PATH;
78
+ }
79
+ // 2. Resolve absolute paths for the supervised binaries.
80
+ const beeosHome = resolveBeeosHome(opts.beeosHome, currentEnv);
81
+ const cliDir = path.dirname(opts.cliEntry);
82
+ const managedDir = path.join(beeosHome, "bin");
83
+ for (const target of SUPERVISED_BINARIES) {
84
+ const found = await resolveBinary({
85
+ name: target.bin,
86
+ cliEntry: opts.cliEntry,
87
+ cliDir,
88
+ managedDir,
89
+ fileExists: fe,
90
+ whichBin: wh,
91
+ });
92
+ if (found) {
93
+ env[target.envVar] = found;
94
+ }
95
+ else if (target.required) {
96
+ warnings.push(`could not locate ${target.bin} (looked next to ${opts.cliEntry}, in ${managedDir}, and on PATH); ` +
97
+ `set ${target.envVar} explicitly or symlink ${target.bin} into ${managedDir} before the fleet spawns it.`);
98
+ }
99
+ }
100
+ // 3. Pull AGENT_GATEWAY_URL / BRIDGE_URL from ~/.beeos/config.toml
101
+ // so the fleet uses the same backend as the rest of `beeos *`.
102
+ const cfg = await rc(path.join(beeosHome, "config.toml"));
103
+ if (cfg?.agentGatewayUrl)
104
+ env.AGENT_GATEWAY_URL = cfg.agentGatewayUrl;
105
+ if (cfg?.bridgeUrl)
106
+ env.BRIDGE_URL = cfg.bridgeUrl;
107
+ // 4. Operator-supplied overrides win over everything we discovered.
108
+ // `undefined` values are treated as "unset"; empty strings are
109
+ // honoured (operator may want to clear a default).
110
+ if (opts.overrides) {
111
+ for (const [k, v] of Object.entries(opts.overrides)) {
112
+ if (v !== undefined)
113
+ env[k] = v;
114
+ }
115
+ }
116
+ return { env, warnings };
117
+ }
118
+ async function resolveBinary(args) {
119
+ const exeSuffix = process.platform === "win32" ? ".exe" : "";
120
+ const filename = `${args.name}${exeSuffix}`;
121
+ // 1. Sibling of cliEntry (covers `~/.beeos/bin/` from install-local.sh
122
+ // and `node_modules/.bin/` from npm consumers).
123
+ // Also short-circuit when the requested binary IS cliEntry itself
124
+ // (i.e. `device-agent`).
125
+ const baseCli = path.basename(args.cliEntry);
126
+ if (baseCli === args.name || baseCli === filename) {
127
+ if (await args.fileExists(args.cliEntry))
128
+ return args.cliEntry;
129
+ }
130
+ const siblingPlain = path.join(args.cliDir, args.name);
131
+ if (await args.fileExists(siblingPlain))
132
+ return siblingPlain;
133
+ if (filename !== args.name) {
134
+ const siblingExe = path.join(args.cliDir, filename);
135
+ if (await args.fileExists(siblingExe))
136
+ return siblingExe;
137
+ }
138
+ // 2. ~/.beeos/bin/<name> (cargo-dist + install-local.sh canonical install location).
139
+ const managed = path.join(args.managedDir, filename);
140
+ if (await args.fileExists(managed))
141
+ return managed;
142
+ // 3. PATH lookup (last resort — the launchd PATH may differ from
143
+ // the install-time PATH, so we still keep BEEOS_*_BIN as the
144
+ // canonical hint).
145
+ return args.whichBin(args.name);
146
+ }
147
+ async function defaultFileExists(p) {
148
+ try {
149
+ await fs.access(p);
150
+ return true;
151
+ }
152
+ catch {
153
+ return false;
154
+ }
155
+ }
156
+ async function defaultWhich(name) {
157
+ const cmd = process.platform === "win32" ? "where" : "which";
158
+ try {
159
+ const { stdout } = await execFileP(cmd, [name]);
160
+ const first = stdout.split(/\r?\n/).find((l) => l.trim().length > 0);
161
+ return first ? first.trim() : null;
162
+ }
163
+ catch {
164
+ return null;
165
+ }
166
+ }
167
+ /**
168
+ * Minimal `~/.beeos/config.toml` reader — only extracts the two keys
169
+ * we care about (`platform.agent_gateway_url`, `platform.bridge_url`).
170
+ *
171
+ * Keeping this inline avoids pulling `smol-toml` (or any other parser)
172
+ * into the device-agent runtime — `config.toml` is shaped exactly as
173
+ * the BeeOS CLI writes it: a single `[platform]` section with bare
174
+ * `key = "value"` lines. Comments and arrays are not supported here
175
+ * because they are not part of the file we own.
176
+ */
177
+ export async function defaultReadConfigToml(cfgPath) {
178
+ let text;
179
+ try {
180
+ text = await fs.readFile(cfgPath, "utf8");
181
+ }
182
+ catch {
183
+ return null;
184
+ }
185
+ return parseConfigToml(text);
186
+ }
187
+ /**
188
+ * Pure parser exported for unit tests — operates on the file body text.
189
+ */
190
+ export function parseConfigToml(text) {
191
+ const out = {};
192
+ let inPlatform = false;
193
+ for (const rawLine of text.split(/\r?\n/)) {
194
+ const line = rawLine.trim();
195
+ if (line.length === 0 || line.startsWith("#"))
196
+ continue;
197
+ const sect = line.match(/^\[([^\]]+)\]/);
198
+ if (sect) {
199
+ inPlatform = sect[1] === "platform";
200
+ continue;
201
+ }
202
+ if (!inPlatform)
203
+ continue;
204
+ const kv = line.match(/^([A-Za-z_][\w]*)\s*=\s*"([^"]*)"/);
205
+ if (!kv)
206
+ continue;
207
+ const key = kv[1];
208
+ const value = kv[2];
209
+ if (key === "agent_gateway_url")
210
+ out.agentGatewayUrl = value;
211
+ else if (key === "bridge_url")
212
+ out.bridgeUrl = value;
213
+ }
214
+ return out;
215
+ }
216
+ function resolveBeeosHome(override, env) {
217
+ if (override && override.length > 0)
218
+ return override;
219
+ const fromEnv = env.BEEOS_HOME;
220
+ if (fromEnv && fromEnv.length > 0)
221
+ return fromEnv;
222
+ return path.join(os.homedir(), ".beeos");
223
+ }
224
+ //# sourceMappingURL=spawn-env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawn-env.js","sourceRoot":"","sources":["../../../src/fleet/installer/spawn-env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,SAAS,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAsBtC;;;;GAIG;AACH,MAAM,mBAAmB,GAA8D;IACrF,EAAE,MAAM,EAAE,wBAAwB,EAAE,GAAG,EAAE,cAAc,EAAE,QAAQ,EAAE,IAAI,EAAE;IACzE,EAAE,MAAM,EAAE,sBAAsB,EAAE,GAAG,EAAE,mBAAmB,EAAE,QAAQ,EAAE,IAAI,EAAE;IAC5E,EAAE,MAAM,EAAE,yBAAyB,EAAE,GAAG,EAAE,eAAe,EAAE,QAAQ,EAAE,KAAK,EAAE;CAC7E,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,IAA2B;IAE3B,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,MAAM,EAAE,GAAG,IAAI,CAAC,UAAU,IAAI,iBAAiB,CAAC;IAChD,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,IAAI,YAAY,CAAC;IACzC,MAAM,EAAE,GAAG,IAAI,CAAC,cAAc,IAAI,qBAAqB,CAAC;IACxD,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,OAAO,CAAC,GAAG,CAAC;IAElD,mEAAmE;IACnE,gEAAgE;IAChE,iCAAiC;IACjC,IAAI,UAAU,CAAC,IAAI,IAAI,UAAU,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClD,GAAG,CAAC,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC;IAC7B,CAAC;IAED,yDAAyD;IACzD,MAAM,SAAS,GAAG,gBAAgB,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAC/D,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC3C,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAE/C,KAAK,MAAM,MAAM,IAAI,mBAAmB,EAAE,CAAC;QACzC,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC;YAChC,IAAI,EAAE,MAAM,CAAC,GAAG;YAChB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,MAAM;YACN,UAAU;YACV,UAAU,EAAE,EAAE;YACd,QAAQ,EAAE,EAAE;SACb,CAAC,CAAC;QACH,IAAI,KAAK,EAAE,CAAC;YACV,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC;QAC7B,CAAC;aAAM,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YAC3B,QAAQ,CAAC,IAAI,CACX,oBAAoB,MAAM,CAAC,GAAG,oBAAoB,IAAI,CAAC,QAAQ,QAAQ,UAAU,kBAAkB;gBACjG,OAAO,MAAM,CAAC,MAAM,0BAA0B,MAAM,CAAC,GAAG,SAAS,UAAU,8BAA8B,CAC5G,CAAC;QACJ,CAAC;IACH,CAAC;IAED,mEAAmE;IACnE,+DAA+D;IAC/D,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC;IAC1D,IAAI,GAAG,EAAE,eAAe;QAAE,GAAG,CAAC,iBAAiB,GAAG,GAAG,CAAC,eAAe,CAAC;IACtE,IAAI,GAAG,EAAE,SAAS;QAAE,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC,SAAS,CAAC;IAEnD,oEAAoE;IACpE,+DAA+D;IAC/D,mDAAmD;IACnD,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YACpD,IAAI,CAAC,KAAK,SAAS;gBAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IAED,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC;AAC3B,CAAC;AAED,KAAK,UAAU,aAAa,CAAC,IAO5B;IACC,MAAM,SAAS,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7D,MAAM,QAAQ,GAAG,GAAG,IAAI,CAAC,IAAI,GAAG,SAAS,EAAE,CAAC;IAE5C,uEAAuE;IACvE,gDAAgD;IAChD,kEAAkE;IAClE,yBAAyB;IACzB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC7C,IAAI,OAAO,KAAK,IAAI,CAAC,IAAI,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;QAClD,IAAI,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC;YAAE,OAAO,IAAI,CAAC,QAAQ,CAAC;IACjE,CAAC;IACD,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IACvD,IAAI,MAAM,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC;QAAE,OAAO,YAAY,CAAC;IAC7D,IAAI,QAAQ,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;QAC3B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACpD,IAAI,MAAM,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;YAAE,OAAO,UAAU,CAAC;IAC3D,CAAC;IAED,qFAAqF;IACrF,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IACrD,IAAI,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,OAAO,CAAC;IAEnD,iEAAiE;IACjE,6DAA6D;IAC7D,mBAAmB;IACnB,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAClC,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAC,CAAS;IACxC,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,IAAY;IACtC,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;IAC7D,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;QAChD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACrE,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,OAAe;IAEf,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,MAAM,GAAG,GAAe,EAAE,CAAC;IAC3B,IAAI,UAAU,GAAG,KAAK,CAAC;IACvB,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QACxD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;QACzC,IAAI,IAAI,EAAE,CAAC;YACT,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,KAAK,UAAU,CAAC;YACpC,SAAS;QACX,CAAC;QACD,IAAI,CAAC,UAAU;YAAE,SAAS;QAC1B,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC;QAC3D,IAAI,CAAC,EAAE;YAAE,SAAS;QAClB,MAAM,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;QAClB,MAAM,KAAK,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,GAAG,KAAK,mBAAmB;YAAE,GAAG,CAAC,eAAe,GAAG,KAAK,CAAC;aACxD,IAAI,GAAG,KAAK,YAAY;YAAE,GAAG,CAAC,SAAS,GAAG,KAAK,CAAC;IACvD,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,gBAAgB,CACvB,QAA4B,EAC5B,GAAsB;IAEtB,IAAI,QAAQ,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,QAAQ,CAAC;IACrD,MAAM,OAAO,GAAG,GAAG,CAAC,UAAU,CAAC;IAC/B,IAAI,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,OAAO,CAAC;IAClD,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC;AAC3C,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Port — clock & timer abstraction.
3
+ *
4
+ * Centralising `Date.now()` and `setTimeout` behind this port lets unit tests
5
+ * for the supervisor advance time deterministically (`FakeClock`). Pure FSM
6
+ * tests don't need this — they pass `now` directly into `step()`.
7
+ */
8
+ export type CancelFn = () => void;
9
+ export interface IClock {
10
+ /** Monotonic-ish wall clock millis. */
11
+ now(): number;
12
+ /** Schedule `cb` to run after `ms`. Returns a cancel handle. */
13
+ schedule(ms: number, cb: () => void): CancelFn;
14
+ }
15
+ /** Default `IClock` backed by Node.js `Date.now()` + `setTimeout`. */
16
+ export declare class SystemClock implements IClock {
17
+ now(): number;
18
+ schedule(ms: number, cb: () => void): CancelFn;
19
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Port — clock & timer abstraction.
3
+ *
4
+ * Centralising `Date.now()` and `setTimeout` behind this port lets unit tests
5
+ * for the supervisor advance time deterministically (`FakeClock`). Pure FSM
6
+ * tests don't need this — they pass `now` directly into `step()`.
7
+ */
8
+ /** Default `IClock` backed by Node.js `Date.now()` + `setTimeout`. */
9
+ export class SystemClock {
10
+ now() {
11
+ return Date.now();
12
+ }
13
+ schedule(ms, cb) {
14
+ const handle = setTimeout(cb, ms);
15
+ if (typeof handle === "object" && handle && "unref" in handle) {
16
+ try {
17
+ handle.unref();
18
+ }
19
+ catch {
20
+ /* node 20+ always supports unref */
21
+ }
22
+ }
23
+ return () => clearTimeout(handle);
24
+ }
25
+ }
26
+ //# sourceMappingURL=clock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clock.js","sourceRoot":"","sources":["../../../src/fleet/ports/clock.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAYH,sEAAsE;AACtE,MAAM,OAAO,WAAW;IACtB,GAAG;QACD,OAAO,IAAI,CAAC,GAAG,EAAE,CAAC;IACpB,CAAC;IACD,QAAQ,CAAC,EAAU,EAAE,EAAc;QACjC,MAAM,MAAM,GAAG,UAAU,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QAClC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,IAAI,OAAO,IAAI,MAAM,EAAE,CAAC;YAC9D,IAAI,CAAC;gBACF,MAAgC,CAAC,KAAK,EAAE,CAAC;YAC5C,CAAC;YAAC,MAAM,CAAC;gBACP,oCAAoC;YACtC,CAAC;QACH,CAAC;QACD,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC;CACF"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Port — device source.
3
+ *
4
+ * A `DeviceSource` is an event stream surfacing ADB-style device events.
5
+ * Implementations:
6
+ * - `LocalAdbSource` (M2) — `adb track-devices` long-running subprocess.
7
+ * - `RemoteAdbSource` (M6) — static `host:port` list (e.g. ReDroid containers).
8
+ *
9
+ * Sources MUST emit:
10
+ * 1. An `adb_online` event for every serial currently attached at start
11
+ * (initial sync), and
12
+ * 2. Subsequent online / offline / unauthorized transitions in real time.
13
+ *
14
+ * Sources MUST NOT spawn anything or touch the FSM directly. They are pure
15
+ * observation channels — the supervisor wires the events into FSM updates.
16
+ */
17
+ import type { AdbEvent } from "../domain/events.js";
18
+ export type AdbEventListener = (event: AdbEvent) => void;
19
+ export interface IDeviceSource {
20
+ /** Begin emitting events. Must be idempotent. */
21
+ start(): Promise<void>;
22
+ /** Stop the underlying watcher and release resources. */
23
+ stop(): Promise<void>;
24
+ /** Subscribe; returns an unsubscribe function. */
25
+ on(listener: AdbEventListener): () => void;
26
+ /** Snapshot of currently-online serials (for `/fleet/devices` queries). */
27
+ snapshot(): readonly string[];
28
+ }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Port — device source.
3
+ *
4
+ * A `DeviceSource` is an event stream surfacing ADB-style device events.
5
+ * Implementations:
6
+ * - `LocalAdbSource` (M2) — `adb track-devices` long-running subprocess.
7
+ * - `RemoteAdbSource` (M6) — static `host:port` list (e.g. ReDroid containers).
8
+ *
9
+ * Sources MUST emit:
10
+ * 1. An `adb_online` event for every serial currently attached at start
11
+ * (initial sync), and
12
+ * 2. Subsequent online / offline / unauthorized transitions in real time.
13
+ *
14
+ * Sources MUST NOT spawn anything or touch the FSM directly. They are pure
15
+ * observation channels — the supervisor wires the events into FSM updates.
16
+ */
17
+ export {};
18
+ //# sourceMappingURL=device-source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device-source.js","sourceRoot":"","sources":["../../../src/fleet/ports/device-source.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG"}
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Port — process manager.
3
+ *
4
+ * Owns the spawn/kill lifecycle of the per-device child processes:
5
+ * - `device-mcp-server --backend android --adb-serial <serial> --port <p>`
6
+ * - `device-agent` (no subcommand → daemon) `--adb <serial> --key <keyFile>`
7
+ * - `scrcpy-bridge` (optional sibling for WebRTC video; supervised when
8
+ * `video_mode === "scrcpy"`)
9
+ *
10
+ * The implementation lives in `fleet/adapters/process/`. The port is
11
+ * deliberately narrow so a fake can drive the FSM end-to-end in tests.
12
+ *
13
+ * Health & crash semantics:
14
+ * - The implementation must emit `mcp_started` / `daemon_started` /
15
+ * `scrcpy_started` once the child has cleared a basic readiness check
16
+ * (TCP probe on `mcpUrl` / daemon HTTP `/healthz` / N-second startup
17
+ * liveness for scrcpy-bridge which has no /healthz).
18
+ * - `*_exited` events MUST set `expected = true` if and only if the
19
+ * supervisor previously asked for a kill (so the FSM doesn't penalise
20
+ * `restartCount`).
21
+ * - `spawnScrcpy` is best-effort: when the binary cannot be found the
22
+ * adapter logs and emits a `scrcpy_exited` with `reason` set, but never
23
+ * blocks the rest of the device's spawn pipeline (video gracefully
24
+ * degrades; mcp + daemon still come up).
25
+ */
26
+ import type { ProcessEvent } from "../domain/events.js";
27
+ export type ProcessEventListener = (event: ProcessEvent) => void;
28
+ export interface SpawnOptions {
29
+ serial: string;
30
+ /** Allocated port for the mcp-server. */
31
+ mcpPort: number;
32
+ /** Path to the Ed25519 identity key file (daemon only). */
33
+ keyFile: string;
34
+ /** Agent Gateway URL (daemon only). Defaults via env. */
35
+ agentGatewayUrl?: string;
36
+ /** Daemon-side HTTP debug port (sticky from devices.json). */
37
+ daemonHttpPort?: number;
38
+ /** Optional binding name (for log decoration). */
39
+ name?: string;
40
+ /** Platform instance id (used for `--vlm-config-file` resolution and scrcpy-bridge `DEVICE_ID`). */
41
+ instanceId?: string;
42
+ /**
43
+ * Per-device `device-mcp-server --backend <name>` selection. When
44
+ * unset, `NodeProcessManager` falls back to its constructor-time
45
+ * default (`opts.mcpBackend` / `BEEOS_MCP_BACKEND` / `android`).
46
+ *
47
+ * In production this is read from `devices.json#backend` by the
48
+ * supervisor (`spawnOptionsFor`), which maps the canonical short
49
+ * name (`adb` / `macos` / `linux` / `windows` / `desktop` /
50
+ * `mock-desktop`) directly into `--backend`.
51
+ */
52
+ backend?: string;
53
+ }
54
+ /**
55
+ * Options for spawning `scrcpy-bridge`. Mirrors the env contract documented
56
+ * in `web/packages/core/src/runtime/scrcpy-bridge.ts` `buildEnv`. We
57
+ * intentionally re-declare the shape here instead of importing from
58
+ * `@beeos/core` so the device-agent package stays free of CLI deps.
59
+ */
60
+ export interface SpawnScrcpyOptions {
61
+ serial: string;
62
+ /** Platform instance id used to compute scrcpy-bridge `DEVICE_ID` (`device-<instanceId>`). */
63
+ instanceId: string;
64
+ agentGatewayUrl: string;
65
+ /** Path to Ed25519 private key (raw base64 or `.key.json`). */
66
+ bridgePrivateKeyFile: string;
67
+ /** Path to Ed25519 public key (may equal private when using `.key.json`). */
68
+ bridgePublicKeyFile: string;
69
+ /** Optional video/ICE/TURN tuning. */
70
+ videoBitrateKbps?: number;
71
+ maxFps?: number;
72
+ iceUrls?: string[];
73
+ turnUrls?: string[];
74
+ turnUsername?: string;
75
+ turnCredential?: string;
76
+ /** Extra `KEY=VAL` pairs merged into the spawned process env. */
77
+ extraEnv?: Record<string, string>;
78
+ }
79
+ export type ManagedProcess = "mcp" | "daemon" | "scrcpy";
80
+ export interface IProcessManager {
81
+ start(): Promise<void>;
82
+ stop(): Promise<void>;
83
+ /** Spawn the device-mcp-server child for a given serial. */
84
+ spawnMcp(opts: SpawnOptions): Promise<void>;
85
+ /** Spawn the device-agent daemon child for a given serial. */
86
+ spawnDaemon(opts: SpawnOptions): Promise<void>;
87
+ /**
88
+ * Spawn the optional scrcpy-bridge sibling for a given serial. Best-effort:
89
+ * a missing binary yields a `scrcpy_exited` with `reason` rather than a
90
+ * thrown error.
91
+ */
92
+ spawnScrcpy(opts: SpawnScrcpyOptions): Promise<void>;
93
+ /** Stop the mcp child (SIGTERM, then SIGKILL after grace). */
94
+ killMcp(serial: string, opts?: {
95
+ expected?: boolean;
96
+ }): Promise<void>;
97
+ /** Stop the daemon child. */
98
+ killDaemon(serial: string, opts?: {
99
+ expected?: boolean;
100
+ }): Promise<void>;
101
+ /** Stop the scrcpy-bridge child (idempotent — no-op if not running). */
102
+ killScrcpy(serial: string, opts?: {
103
+ expected?: boolean;
104
+ }): Promise<void>;
105
+ /** Whether the requested child is currently alive (best-effort, observation only). */
106
+ isAlive(serial: string, which: ManagedProcess): boolean;
107
+ /** Best-effort PID introspection. */
108
+ pid(serial: string, which: ManagedProcess): number | null;
109
+ on(listener: ProcessEventListener): () => void;
110
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Port — process manager.
3
+ *
4
+ * Owns the spawn/kill lifecycle of the per-device child processes:
5
+ * - `device-mcp-server --backend android --adb-serial <serial> --port <p>`
6
+ * - `device-agent` (no subcommand → daemon) `--adb <serial> --key <keyFile>`
7
+ * - `scrcpy-bridge` (optional sibling for WebRTC video; supervised when
8
+ * `video_mode === "scrcpy"`)
9
+ *
10
+ * The implementation lives in `fleet/adapters/process/`. The port is
11
+ * deliberately narrow so a fake can drive the FSM end-to-end in tests.
12
+ *
13
+ * Health & crash semantics:
14
+ * - The implementation must emit `mcp_started` / `daemon_started` /
15
+ * `scrcpy_started` once the child has cleared a basic readiness check
16
+ * (TCP probe on `mcpUrl` / daemon HTTP `/healthz` / N-second startup
17
+ * liveness for scrcpy-bridge which has no /healthz).
18
+ * - `*_exited` events MUST set `expected = true` if and only if the
19
+ * supervisor previously asked for a kill (so the FSM doesn't penalise
20
+ * `restartCount`).
21
+ * - `spawnScrcpy` is best-effort: when the binary cannot be found the
22
+ * adapter logs and emits a `scrcpy_exited` with `reason` set, but never
23
+ * blocks the rest of the device's spawn pipeline (video gracefully
24
+ * degrades; mcp + daemon still come up).
25
+ */
26
+ export {};
27
+ //# sourceMappingURL=process-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-manager.js","sourceRoot":"","sources":["../../../src/fleet/ports/process-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Port — binding state registry.
3
+ *
4
+ * Adapter contract for reading per-device bindings from `~/.beeos/devices.json`
5
+ * (the file owned by `web/packages/cli` `attach` / `detach`). Fleet treats
6
+ * the file as read-only; the CLI is the writer. The store also exposes a
7
+ * watcher so fleet can react when a user runs `beeos device attach` mid-flight.
8
+ *
9
+ * Implementation: `fleet/adapters/state/beeos-cli-store.ts`.
10
+ */
11
+ import type { DeviceBinding } from "../domain/device.js";
12
+ import type { BindingEvent } from "../domain/events.js";
13
+ export type BindingEventListener = (event: BindingEvent) => void;
14
+ export interface IStateRegistry {
15
+ /** Begin watching the underlying file (idempotent). */
16
+ start(): Promise<void>;
17
+ /** Stop watching and release resources. */
18
+ stop(): Promise<void>;
19
+ /** Force-reload the file and emit diff events. */
20
+ reload(): Promise<void>;
21
+ /** Snapshot of all bindings currently visible. */
22
+ list(): readonly DeviceBinding[];
23
+ /** Lookup by ADB serial. */
24
+ get(serial: string): DeviceBinding | null;
25
+ on(listener: BindingEventListener): () => void;
26
+ }
27
+ /**
28
+ * Port — port allocator (sticky).
29
+ *
30
+ * Allocates one mcp-server port per serial. Allocations are persisted to
31
+ * `~/.beeos/fleet.json` so the same serial always lands on the same port
32
+ * across restarts (URLs in user UI stay stable). On collision with another
33
+ * already-running process, the allocator probes the next free port within a
34
+ * configurable range.
35
+ *
36
+ * Implementation: `fleet/adapters/state/port-allocator.ts`.
37
+ */
38
+ export interface IPortAllocator {
39
+ /** Lazy-initialise: load persisted file if any. */
40
+ start(): Promise<void>;
41
+ /** Persist + close the underlying file. */
42
+ stop(): Promise<void>;
43
+ /** Get the (existing or freshly-allocated) port for a serial. */
44
+ acquire(serial: string): Promise<number>;
45
+ /** Free the slot — does not delete the persisted entry (kept sticky). */
46
+ release(serial: string): Promise<void>;
47
+ /** Read-only snapshot for `/fleet/devices`. */
48
+ snapshot(): ReadonlyMap<string, number>;
49
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Port — binding state registry.
3
+ *
4
+ * Adapter contract for reading per-device bindings from `~/.beeos/devices.json`
5
+ * (the file owned by `web/packages/cli` `attach` / `detach`). Fleet treats
6
+ * the file as read-only; the CLI is the writer. The store also exposes a
7
+ * watcher so fleet can react when a user runs `beeos device attach` mid-flight.
8
+ *
9
+ * Implementation: `fleet/adapters/state/beeos-cli-store.ts`.
10
+ */
11
+ export {};
12
+ //# sourceMappingURL=state-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-registry.js","sourceRoot":"","sources":["../../../src/fleet/ports/state-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Fleet supervisor — orchestrator that translates the pure FSM (`domain/fsm.ts`)
3
+ * effects into real side effects against the adapter ports.
4
+ *
5
+ * Responsibilities:
6
+ *
7
+ * 1. Wire `IDeviceSource` (ADB events), `IStateRegistry` (devices.json),
8
+ * `IProcessManager` (mcp + daemon spawn/kill) and `IClock` (timers).
9
+ * 2. Maintain one `DeviceRecord` per serial discovered from EITHER source
10
+ * (a device with a binding but no ADB → `adb_offline`; a device with
11
+ * ADB but no binding → `awaiting_bind`).
12
+ * 3. For every event, call `step()` to compute `(record', effects)` and
13
+ * enact each effect (spawn / kill / timer / port allocation / log).
14
+ * 4. Track `mcpAlive` / `daemonAlive` outside the FSM and call
15
+ * `markHealthy()` when both are observed in `spawning`.
16
+ * 5. Expose a read-only `snapshot()` for the HTTP `/fleet/devices` endpoint
17
+ * in M4.
18
+ *
19
+ * Concurrency model: single async serializer. All inbound events queue through
20
+ * `dispatch()` which pulls one at a time. This guarantees a coherent view of
21
+ * the FSM during multi-effect transitions and removes any need for locks.
22
+ */
23
+ import type { DeviceSnapshot } from "./domain/device.js";
24
+ import type { IClock } from "./ports/clock.js";
25
+ import type { IDeviceSource } from "./ports/device-source.js";
26
+ import type { IProcessManager } from "./ports/process-manager.js";
27
+ import type { IPortAllocator, IStateRegistry } from "./ports/state-registry.js";
28
+ export interface SupervisorLogger {
29
+ debug(msg: string, data?: Record<string, unknown>): void;
30
+ info(msg: string, data?: Record<string, unknown>): void;
31
+ warn(msg: string, data?: Record<string, unknown>): void;
32
+ error(msg: string, data?: Record<string, unknown>): void;
33
+ }
34
+ export interface FleetSupervisorOptions {
35
+ source: IDeviceSource;
36
+ registry: IStateRegistry;
37
+ allocator: IPortAllocator;
38
+ processManager: IProcessManager;
39
+ clock?: IClock;
40
+ /** HEALTHY → DEGRADED window (default 5 s). */
41
+ graceMs?: number;
42
+ /** DEGRADED → GONE window (default 5 min). */
43
+ keepMs?: number;
44
+ logger?: SupervisorLogger;
45
+ /** Daemon-side metadata pulled from `devices.json` (overrides). */
46
+ defaultAgentGatewayUrl?: string;
47
+ }
48
+ export declare class FleetSupervisor {
49
+ private readonly source;
50
+ private readonly registry;
51
+ private readonly allocator;
52
+ private readonly processManager;
53
+ private readonly clock;
54
+ private readonly graceMs;
55
+ private readonly keepMs;
56
+ private readonly logger;
57
+ private readonly defaultAgentGatewayUrl?;
58
+ private readonly slots;
59
+ private readonly queue;
60
+ private dispatching;
61
+ private started;
62
+ private unsubAdb;
63
+ private unsubBinding;
64
+ private unsubProcess;
65
+ constructor(opts: FleetSupervisorOptions);
66
+ start(): Promise<void>;
67
+ stop(): Promise<void>;
68
+ /** Read-only snapshot for `/fleet/devices`. */
69
+ snapshot(): DeviceSnapshot[];
70
+ /**
71
+ * Force the registry to re-read `devices.json` (e.g. after `beeos device
72
+ * attach` finished). Returns once the diff has been queued; the per-slot
73
+ * effects fire asynchronously.
74
+ */
75
+ reload(): Promise<void>;
76
+ /**
77
+ * User-initiated full restart of one device's mcp + daemon pair.
78
+ *
79
+ * Flow: kill both children → reset slot to `adb_offline` (cancels timers,
80
+ * releases port, clears restartCount) → if ADB is currently online and
81
+ * the device is still bound, synthesise an `adb_online` event so the FSM
82
+ * walks the normal spawn path. The result mirrors what would happen if
83
+ * the user yanked the cable and plugged it back in immediately, except
84
+ * that grace/keep windows are skipped.
85
+ *
86
+ * Returns `false` if `serial` is unknown, `true` otherwise.
87
+ */
88
+ restartDevice(serial: string): Promise<boolean>;
89
+ private enqueue;
90
+ private drain;
91
+ private dispatch;
92
+ private bindingFor;
93
+ private ensureSlot;
94
+ private applyEffect;
95
+ private spawnOptionsFor;
96
+ /**
97
+ * Build `SpawnScrcpyOptions` for a slot, returning `null` when scrcpy is
98
+ * not requested (`videoMode !== "scrcpy"`) or the binding lacks the
99
+ * mandatory fields (`instanceId` / `keyFile` / Agent Gateway URL).
100
+ *
101
+ * We deliberately pass `bridgePrivateKeyFile === bridgePublicKeyFile`
102
+ * (both pointing at the same `.key.json` file written by `beeos device
103
+ * attach`). The Rust side accepts that layout (see scrcpy-bridge's
104
+ * `bootstrap/mod.rs`).
105
+ */
106
+ private scrcpySpawnOptionsFor;
107
+ }