@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,173 @@
1
+ /**
2
+ * Adapter — sticky port allocator backed by `~/.beeos/fleet.json`.
3
+ *
4
+ * Sticky semantics: once a serial is mapped to a port, that mapping is kept
5
+ * indefinitely so users can bookmark / paste the URL. The allocator only
6
+ * forgets a mapping if the persisted port collides with another listener at
7
+ * acquire time — then we probe the next free port within the configured
8
+ * range.
9
+ *
10
+ * Range: configurable, defaults to `[7900, 7999]` (matches the historical
11
+ * device-mcp-server default of 7900). 100 slots × per-laptop scale is plenty
12
+ * even for power users running 30 devices.
13
+ */
14
+ import * as fs from "node:fs";
15
+ import * as net from "node:net";
16
+ import * as os from "node:os";
17
+ import * as path from "node:path";
18
+ const DEFAULT_BASE = 7900;
19
+ const DEFAULT_RANGE = 100;
20
+ const FALLBACK_PORT = 7900;
21
+ export class StickyPortAllocator {
22
+ filePath;
23
+ basePort;
24
+ rangeSize;
25
+ probe;
26
+ map = new Map();
27
+ writeQueue = Promise.resolve();
28
+ started = false;
29
+ constructor(opts = {}) {
30
+ this.filePath = opts.filePath ?? defaultFleetStatePath();
31
+ this.basePort = opts.basePort ?? DEFAULT_BASE;
32
+ this.rangeSize = opts.rangeSize ?? DEFAULT_RANGE;
33
+ this.probe = opts.probe ?? defaultProbe;
34
+ }
35
+ async start() {
36
+ if (this.started)
37
+ return;
38
+ this.started = true;
39
+ await this.load();
40
+ }
41
+ async stop() {
42
+ this.started = false;
43
+ await this.writeQueue;
44
+ }
45
+ async acquire(serial) {
46
+ if (!this.started)
47
+ await this.start();
48
+ const sticky = this.map.get(serial);
49
+ const hint = sticky ?? this.hintFor(serial);
50
+ const port = await this.findAvailable(serial, hint);
51
+ if (this.map.get(serial) !== port) {
52
+ this.map.set(serial, port);
53
+ this.flush();
54
+ }
55
+ return port;
56
+ }
57
+ async release(serial) {
58
+ // Sticky — we keep the mapping. This is a no-op by design but exposed
59
+ // for symmetry. Tests may call `forget` (below) for full reset.
60
+ void serial;
61
+ return;
62
+ }
63
+ /** Test/maintenance helper: drop the persisted mapping for a serial. */
64
+ forget(serial) {
65
+ if (this.map.delete(serial))
66
+ this.flush();
67
+ }
68
+ snapshot() {
69
+ return new Map(this.map);
70
+ }
71
+ // ── Internals ────────────────────────────────────────────────────────────
72
+ hintFor(serial) {
73
+ // Stable hash → base + (h % range). Avoids "everyone gets 7900" stampede.
74
+ let h = 2166136261; // FNV-1a
75
+ for (let i = 0; i < serial.length; i++) {
76
+ h ^= serial.charCodeAt(i);
77
+ h = Math.imul(h, 16777619);
78
+ }
79
+ return this.basePort + (Math.abs(h) % this.rangeSize);
80
+ }
81
+ async findAvailable(serial, hint) {
82
+ // Probe `hint` first (so sticky mappings re-acquire the same port), then
83
+ // walk the rest of the range. We don't take ports outside the configured
84
+ // range — easier to firewall.
85
+ const candidates = [];
86
+ if (hint >= this.basePort && hint < this.basePort + this.rangeSize) {
87
+ candidates.push(hint);
88
+ }
89
+ for (let i = 0; i < this.rangeSize; i++) {
90
+ const p = this.basePort + i;
91
+ if (!candidates.includes(p))
92
+ candidates.push(p);
93
+ }
94
+ // Skip ports already assigned to OTHER serials (in-memory). The current
95
+ // serial's own existing mapping is allowed (sticky re-acquire).
96
+ const occupiedByOthers = new Set();
97
+ for (const [s, p] of this.map) {
98
+ if (s !== serial)
99
+ occupiedByOthers.add(p);
100
+ }
101
+ for (const port of candidates) {
102
+ if (occupiedByOthers.has(port))
103
+ continue;
104
+ const free = await this.probe(port);
105
+ if (free)
106
+ return port;
107
+ }
108
+ return FALLBACK_PORT;
109
+ }
110
+ async load() {
111
+ let raw;
112
+ try {
113
+ raw = await fs.promises.readFile(this.filePath, "utf8");
114
+ }
115
+ catch {
116
+ return;
117
+ }
118
+ try {
119
+ const parsed = JSON.parse(raw);
120
+ if (!parsed || parsed.v !== 1 || !parsed.ports)
121
+ return;
122
+ for (const [serial, port] of Object.entries(parsed.ports)) {
123
+ if (typeof port === "number" && port >= 1024 && port < 65536) {
124
+ this.map.set(serial, port);
125
+ }
126
+ }
127
+ }
128
+ catch {
129
+ /* corrupt — start clean */
130
+ }
131
+ }
132
+ flush() {
133
+ const snap = {
134
+ v: 1,
135
+ ports: Object.fromEntries(this.map.entries()),
136
+ };
137
+ const dir = path.dirname(this.filePath);
138
+ const data = JSON.stringify(snap, null, 2);
139
+ this.writeQueue = this.writeQueue.then(async () => {
140
+ try {
141
+ await fs.promises.mkdir(dir, { recursive: true });
142
+ await fs.promises.writeFile(this.filePath, data, "utf8");
143
+ }
144
+ catch {
145
+ /* best-effort */
146
+ }
147
+ });
148
+ }
149
+ }
150
+ // ── Pure helpers (exported for tests) ────────────────────────────────────────
151
+ export function defaultFleetStatePath() {
152
+ const override = process.env.BEEOS_HOME;
153
+ const base = override && override.length > 0
154
+ ? override
155
+ : path.join(os.homedir(), ".beeos");
156
+ return path.join(base, "fleet.json");
157
+ }
158
+ async function defaultProbe(port) {
159
+ return await new Promise((resolve) => {
160
+ const srv = net.createServer();
161
+ srv.once("error", () => resolve(false));
162
+ srv.once("listening", () => {
163
+ srv.close(() => resolve(true));
164
+ });
165
+ try {
166
+ srv.listen(port, "127.0.0.1");
167
+ }
168
+ catch {
169
+ resolve(false);
170
+ }
171
+ });
172
+ }
173
+ //# sourceMappingURL=port-allocator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"port-allocator.js","sourceRoot":"","sources":["../../../../src/fleet/adapters/state/port-allocator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Fleet domain — `Device` entity and lifecycle state.
3
+ *
4
+ * A `Device` represents one ADB-connected target (real phone, ReDroid container,
5
+ * remote `host:port`) under fleet supervision. Each device transitions through
6
+ * the FSM defined in `./fsm.ts` driven by ADB / process / config / timer events.
7
+ *
8
+ * The FSM has 9 named states; see the lifecycle diagram in
9
+ * `agents/device-agent/CHANGELOG.md` (or the v4 plan) for the full picture.
10
+ *
11
+ * Layered decay (HEALTHY → GRACE → DEGRADED → GONE):
12
+ * - GRACE keeps mcp + daemon alive for a short window so USB jitter is
13
+ * transparent to the user.
14
+ * - DEGRADED tears down mcp (which is tightly coupled to ADB pipes) but
15
+ * retains the daemon so the BeeOS session and Centrifugo subscription
16
+ * survive transient outages.
17
+ * - GONE is reached only after a long absence; the daemon is finally killed
18
+ * and the user-side session is paused.
19
+ *
20
+ * Tunables (`grace_ms`, `keep_ms`) come from env vars or per-device entries in
21
+ * `~/.beeos/devices.json`; see {@link DeviceBinding}.
22
+ */
23
+ /** All FSM states a device can occupy. */
24
+ export type FleetState = "adb_offline" | "adb_unauthorized" | "awaiting_bind" | "spawning" | "healthy" | "grace" | "degraded" | "gone" | "crashed";
25
+ /**
26
+ * Whether a state owns child processes (mcp/daemon) at all. Useful for the
27
+ * supervisor to decide whether `kill_*` effects are no-ops.
28
+ */
29
+ export declare function stateExpectsMcp(s: FleetState): boolean;
30
+ export declare function stateExpectsDaemon(s: FleetState): boolean;
31
+ /**
32
+ * Per-device binding loaded from `~/.beeos/devices.json` (the file owned by
33
+ * `web/packages/cli` `attach` / `detach`). Fleet treats the file as read-only;
34
+ * `beeos device attach` is the writer. `instance_id === null` means the user
35
+ * started attach but didn't complete the platform bind step — fleet must NOT
36
+ * spawn anything for those entries (treat as `awaiting_bind`).
37
+ */
38
+ /**
39
+ * Canonical backend names used by `device-mcp-server` (and forwarded as
40
+ * `--backend <name>` by the fleet's process manager). Pre-self-hosted
41
+ * `devices.json` files don't carry this field; the supervisor treats
42
+ * `undefined` as `adb` for back-compat with v0.1 ADB-only attaches.
43
+ *
44
+ * Aliases (`android`/`mac`/`win`/`desktop-{linux,windows,macos}`) are
45
+ * accepted on read and normalized to the canonical short name in
46
+ * `toBinding`. See plan §3.4.
47
+ */
48
+ export type FleetBackend = "adb" | "macos" | "linux" | "windows" | "desktop" | "mock-desktop";
49
+ export interface DeviceBinding {
50
+ serial: string;
51
+ name: string;
52
+ instanceId: string | null;
53
+ keyFile: string;
54
+ /** Persisted http_port from `web/packages/cli`. Fleet honours it for the daemon's HTTP debug port (sticky). */
55
+ httpPort?: number;
56
+ /**
57
+ * Video backend selection inherited from `devices.json#video_mode`. Drives
58
+ * whether the supervisor co-spawns `scrcpy-bridge` alongside mcp + daemon.
59
+ *
60
+ * - `"scrcpy"` — Android/ADB device (default for ADB serials)
61
+ * - `"vnc"` — desktop/macOS/Linux device with a VNC server (vnc-bridge
62
+ * is OS-service-managed, not fleet-managed)
63
+ * - `"none"` — explicit opt-out (e.g. CI)
64
+ * - `undefined` — fleet treats as "no scrcpy" to stay backwards
65
+ * compatible with older devices.json entries
66
+ */
67
+ videoMode?: "scrcpy" | "vnc" | "none";
68
+ /**
69
+ * `device-mcp-server --backend <name>` selection. Drives which capability
70
+ * set the spawned MCP server exposes. `undefined` is interpreted as `adb`
71
+ * by the fleet for back-compat (the v0.1 attach flow only ever bound ADB
72
+ * devices). See {@link FleetBackend}.
73
+ */
74
+ backend?: FleetBackend;
75
+ /** Optional per-device override of `FLEET_ADB_GRACE_MS` (HEALTHY → DEGRADED). */
76
+ graceMs?: number;
77
+ /** Optional per-device override of `FLEET_DAEMON_KEEP_MS` (DEGRADED → GONE). */
78
+ keepMs?: number;
79
+ }
80
+ /**
81
+ * In-memory FSM record for a single device. The supervisor mutates this via
82
+ * the pure `step()` function in `./fsm.ts`. PIDs and timer handles live
83
+ * outside the FSM (the supervisor manages them) so the FSM stays pure /
84
+ * snapshottable.
85
+ */
86
+ export interface DeviceRecord {
87
+ serial: string;
88
+ name: string;
89
+ state: FleetState;
90
+ binding: DeviceBinding | null;
91
+ /** Monotonic ms timestamp when `state` was last entered. */
92
+ enteredAt: number;
93
+ /** Increments on each unexpected child-process exit while ADB was online. */
94
+ restartCount: number;
95
+ /** Allocated mcp-server port (sticky across restarts). `0` means unallocated. */
96
+ mcpPort: number;
97
+ }
98
+ /** Convenient initial value for a freshly-discovered ADB device. */
99
+ export declare function newDeviceRecord(args: {
100
+ serial: string;
101
+ name?: string;
102
+ binding?: DeviceBinding | null;
103
+ state?: FleetState;
104
+ now: number;
105
+ }): DeviceRecord;
106
+ /** Liveness summary for the optional scrcpy-bridge sibling. */
107
+ export interface ScrcpyStatus {
108
+ /**
109
+ * Whether the device's binding requested scrcpy at all (i.e. `videoMode
110
+ * === "scrcpy"`). When `false`, all other fields are meaningless and the
111
+ * supervisor does not co-spawn scrcpy-bridge.
112
+ */
113
+ enabled: boolean;
114
+ /** True iff the supervisor currently observes the scrcpy-bridge child as alive. */
115
+ running: boolean;
116
+ pid: number | null;
117
+ /** Last error/reason recorded for scrcpy-bridge (binary missing, startup_failed, …). */
118
+ lastError: string | null;
119
+ }
120
+ /** A snapshot exported through the HTTP `/fleet/devices` endpoint. */
121
+ export interface DeviceSnapshot {
122
+ serial: string;
123
+ name: string;
124
+ instanceId: string | null;
125
+ state: FleetState;
126
+ mcpUrl: string | null;
127
+ mcpPid: number | null;
128
+ daemonPid: number | null;
129
+ /**
130
+ * scrcpy-bridge sibling status. Always present (even when scrcpy is
131
+ * disabled for the device) so that consumers can render a stable shape.
132
+ */
133
+ scrcpy: ScrcpyStatus;
134
+ enteredAt: number;
135
+ /** ms since the FSM entered the current state, computed at read time. */
136
+ sinceMs: number;
137
+ restartCount: number;
138
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Fleet domain — `Device` entity and lifecycle state.
3
+ *
4
+ * A `Device` represents one ADB-connected target (real phone, ReDroid container,
5
+ * remote `host:port`) under fleet supervision. Each device transitions through
6
+ * the FSM defined in `./fsm.ts` driven by ADB / process / config / timer events.
7
+ *
8
+ * The FSM has 9 named states; see the lifecycle diagram in
9
+ * `agents/device-agent/CHANGELOG.md` (or the v4 plan) for the full picture.
10
+ *
11
+ * Layered decay (HEALTHY → GRACE → DEGRADED → GONE):
12
+ * - GRACE keeps mcp + daemon alive for a short window so USB jitter is
13
+ * transparent to the user.
14
+ * - DEGRADED tears down mcp (which is tightly coupled to ADB pipes) but
15
+ * retains the daemon so the BeeOS session and Centrifugo subscription
16
+ * survive transient outages.
17
+ * - GONE is reached only after a long absence; the daemon is finally killed
18
+ * and the user-side session is paused.
19
+ *
20
+ * Tunables (`grace_ms`, `keep_ms`) come from env vars or per-device entries in
21
+ * `~/.beeos/devices.json`; see {@link DeviceBinding}.
22
+ */
23
+ /**
24
+ * Whether a state owns child processes (mcp/daemon) at all. Useful for the
25
+ * supervisor to decide whether `kill_*` effects are no-ops.
26
+ */
27
+ export function stateExpectsMcp(s) {
28
+ return s === "healthy" || s === "grace" || s === "spawning" || s === "crashed";
29
+ }
30
+ export function stateExpectsDaemon(s) {
31
+ return (s === "healthy" ||
32
+ s === "grace" ||
33
+ s === "degraded" ||
34
+ s === "spawning" ||
35
+ s === "crashed");
36
+ }
37
+ /** Convenient initial value for a freshly-discovered ADB device. */
38
+ export function newDeviceRecord(args) {
39
+ return {
40
+ serial: args.serial,
41
+ name: args.name ?? args.binding?.name ?? args.serial,
42
+ state: args.state ?? "adb_offline",
43
+ binding: args.binding ?? null,
44
+ enteredAt: args.now,
45
+ restartCount: 0,
46
+ mcpPort: 0,
47
+ };
48
+ }
49
+ //# sourceMappingURL=device.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device.js","sourceRoot":"","sources":["../../../src/fleet/domain/device.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAcH;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,CAAa;IAC3C,OAAO,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,OAAO,IAAI,CAAC,KAAK,UAAU,IAAI,CAAC,KAAK,SAAS,CAAC;AACjF,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,CAAa;IAC9C,OAAO,CACL,CAAC,KAAK,SAAS;QACf,CAAC,KAAK,OAAO;QACb,CAAC,KAAK,UAAU;QAChB,CAAC,KAAK,UAAU;QAChB,CAAC,KAAK,SAAS,CAChB,CAAC;AACJ,CAAC;AA8ED,oEAAoE;AACpE,MAAM,UAAU,eAAe,CAAC,IAM/B;IACC,OAAO;QACL,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO,EAAE,IAAI,IAAI,IAAI,CAAC,MAAM;QACpD,KAAK,EAAE,IAAI,CAAC,KAAK,IAAI,aAAa;QAClC,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,IAAI;QAC7B,SAAS,EAAE,IAAI,CAAC,GAAG;QACnB,YAAY,EAAE,CAAC;QACf,OAAO,EAAE,CAAC;KACX,CAAC;AACJ,CAAC"}
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Fleet domain — event types fed into the FSM (`./fsm.ts`).
3
+ *
4
+ * Events are produced by adapters:
5
+ * - `LocalAdbSource` / `RemoteAdbSource` → `AdbEvent` (online / offline / unauthorized)
6
+ * - `BeeosCliStore` watcher → `BindingEvent`
7
+ * - `ProcessManager` → `ProcessEvent` (spawn ack, exit, health)
8
+ * - In-process timers → `TimerEvent` (grace expiry, keep expiry, restart backoff)
9
+ *
10
+ * The FSM is purely a `(state, event) => { next, effects }` reducer; effects
11
+ * are descriptions (e.g. `{ kind: "spawn_mcp", serial }`) that the supervisor
12
+ * translates into real `child_process.spawn` calls and timer handles.
13
+ */
14
+ export interface AdbOnlineEvent {
15
+ kind: "adb_online";
16
+ serial: string;
17
+ }
18
+ export interface AdbOfflineEvent {
19
+ kind: "adb_offline";
20
+ serial: string;
21
+ }
22
+ export interface AdbUnauthorizedEvent {
23
+ kind: "adb_unauthorized";
24
+ serial: string;
25
+ }
26
+ export type AdbEvent = AdbOnlineEvent | AdbOfflineEvent | AdbUnauthorizedEvent;
27
+ export interface BindingAddedEvent {
28
+ kind: "binding_added";
29
+ serial: string;
30
+ }
31
+ export interface BindingChangedEvent {
32
+ kind: "binding_changed";
33
+ serial: string;
34
+ }
35
+ export interface BindingRemovedEvent {
36
+ kind: "binding_removed";
37
+ serial: string;
38
+ }
39
+ export type BindingEvent = BindingAddedEvent | BindingChangedEvent | BindingRemovedEvent;
40
+ export interface McpStartedEvent {
41
+ kind: "mcp_started";
42
+ serial: string;
43
+ pid: number;
44
+ port: number;
45
+ }
46
+ export interface McpExitedEvent {
47
+ kind: "mcp_exited";
48
+ serial: string;
49
+ /** Process exit code (null when killed by signal). */
50
+ code: number | null;
51
+ /** UNIX signal name when killed by signal (`SIGTERM`, `SIGKILL`, …). */
52
+ signal: NodeJS.Signals | null;
53
+ /** True if fleet asked for the kill (so the FSM should not penalise restartCount). */
54
+ expected: boolean;
55
+ }
56
+ export interface DaemonStartedEvent {
57
+ kind: "daemon_started";
58
+ serial: string;
59
+ pid: number;
60
+ }
61
+ export interface DaemonExitedEvent {
62
+ kind: "daemon_exited";
63
+ serial: string;
64
+ code: number | null;
65
+ signal: NodeJS.Signals | null;
66
+ expected: boolean;
67
+ }
68
+ /**
69
+ * `scrcpy-bridge` is an OPTIONAL sibling we co-supervise alongside
70
+ * mcp + daemon when `video_mode === "scrcpy"`. The pure FSM ignores
71
+ * these events (scrcpy lifecycle does not gate `healthy`); the
72
+ * supervisor uses them solely for the `/fleet/devices` snapshot.
73
+ */
74
+ export interface ScrcpyStartedEvent {
75
+ kind: "scrcpy_started";
76
+ serial: string;
77
+ pid: number;
78
+ }
79
+ export interface ScrcpyExitedEvent {
80
+ kind: "scrcpy_exited";
81
+ serial: string;
82
+ code: number | null;
83
+ signal: NodeJS.Signals | null;
84
+ expected: boolean;
85
+ /** Optional human-readable reason (binary missing, spawn failure, …). */
86
+ reason?: string;
87
+ }
88
+ export type ProcessEvent = McpStartedEvent | McpExitedEvent | DaemonStartedEvent | DaemonExitedEvent | ScrcpyStartedEvent | ScrcpyExitedEvent;
89
+ export interface GraceExpiredEvent {
90
+ kind: "grace_expired";
91
+ serial: string;
92
+ }
93
+ export interface KeepExpiredEvent {
94
+ kind: "keep_expired";
95
+ serial: string;
96
+ }
97
+ export interface BackoffElapsedEvent {
98
+ kind: "backoff_elapsed";
99
+ serial: string;
100
+ }
101
+ export type TimerEvent = GraceExpiredEvent | KeepExpiredEvent | BackoffElapsedEvent;
102
+ export type FleetEvent = AdbEvent | BindingEvent | ProcessEvent | TimerEvent;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Fleet domain — event types fed into the FSM (`./fsm.ts`).
3
+ *
4
+ * Events are produced by adapters:
5
+ * - `LocalAdbSource` / `RemoteAdbSource` → `AdbEvent` (online / offline / unauthorized)
6
+ * - `BeeosCliStore` watcher → `BindingEvent`
7
+ * - `ProcessManager` → `ProcessEvent` (spawn ack, exit, health)
8
+ * - In-process timers → `TimerEvent` (grace expiry, keep expiry, restart backoff)
9
+ *
10
+ * The FSM is purely a `(state, event) => { next, effects }` reducer; effects
11
+ * are descriptions (e.g. `{ kind: "spawn_mcp", serial }`) that the supervisor
12
+ * translates into real `child_process.spawn` calls and timer handles.
13
+ */
14
+ export {};
15
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../../src/fleet/domain/events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG"}
@@ -0,0 +1,122 @@
1
+ /**
2
+ * Fleet domain — pure FSM reducer.
3
+ *
4
+ * Single entry point: `step(record, event, ctx) => { record', effects }`.
5
+ *
6
+ * Effects are *intent descriptors* the supervisor (`fleet/supervisor.ts`)
7
+ * translates into actual side effects (process spawn, timer, log line). This
8
+ * keeps the FSM trivially testable — the M1 unit suite covers the entire
9
+ * lifecycle without any IO.
10
+ *
11
+ * Lifecycle (see also v4 plan):
12
+ * adb_offline ─► (adb_online + bound) ─► spawning ─► healthy
13
+ * (adb_online + unbound) ─► awaiting_bind
14
+ * (adb_online + unauthorized) ─► adb_unauthorized
15
+ * healthy ─► (adb_offline) ─► grace
16
+ * grace ─► (adb_online same serial) ─► healthy (USB jitter, transparent)
17
+ * (grace_expired) ─► degraded (kill mcp only, daemon survives)
18
+ * degraded ─► (adb_online same serial) ─► spawning (respawn mcp, daemon self-heals)
19
+ * (keep_expired) ─► gone (kill daemon, session paused)
20
+ * gone ─► (adb_online) ─► spawning
21
+ * healthy ─► (mcp_exited unexpected) ─► spawning (mcp_only_restart)
22
+ * (daemon_exited unexpected) ─► spawning (daemon_only_restart)
23
+ * (both crashed back-to-back) ─► crashed → spawning
24
+ *
25
+ * The reducer never reads outside its inputs (`record`, `event`, `ctx`) — pure.
26
+ */
27
+ import type { DeviceRecord } from "./device.js";
28
+ import type { FleetEvent } from "./events.js";
29
+ export interface SpawnMcpEffect {
30
+ kind: "spawn_mcp";
31
+ serial: string;
32
+ }
33
+ export interface KillMcpEffect {
34
+ kind: "kill_mcp";
35
+ serial: string;
36
+ /** When true, supervisor records the kill as fleet-initiated → expected exit. */
37
+ expected: true;
38
+ }
39
+ export interface SpawnDaemonEffect {
40
+ kind: "spawn_daemon";
41
+ serial: string;
42
+ }
43
+ export interface KillDaemonEffect {
44
+ kind: "kill_daemon";
45
+ serial: string;
46
+ expected: true;
47
+ }
48
+ export interface StartGraceTimerEffect {
49
+ kind: "start_grace_timer";
50
+ serial: string;
51
+ }
52
+ export interface CancelGraceTimerEffect {
53
+ kind: "cancel_grace_timer";
54
+ serial: string;
55
+ }
56
+ export interface StartKeepTimerEffect {
57
+ kind: "start_keep_timer";
58
+ serial: string;
59
+ }
60
+ export interface CancelKeepTimerEffect {
61
+ kind: "cancel_keep_timer";
62
+ serial: string;
63
+ }
64
+ export interface StartBackoffTimerEffect {
65
+ kind: "start_backoff_timer";
66
+ serial: string;
67
+ /** How many failed restarts have already happened. */
68
+ attempt: number;
69
+ }
70
+ export interface CancelBackoffTimerEffect {
71
+ kind: "cancel_backoff_timer";
72
+ serial: string;
73
+ }
74
+ export interface AllocatePortEffect {
75
+ kind: "allocate_port";
76
+ serial: string;
77
+ }
78
+ export interface ReleasePortEffect {
79
+ kind: "release_port";
80
+ serial: string;
81
+ }
82
+ export interface LogEffect {
83
+ kind: "log";
84
+ level: "debug" | "info" | "warn" | "error";
85
+ serial: string;
86
+ msg: string;
87
+ data?: Record<string, unknown>;
88
+ }
89
+ export type FleetEffect = SpawnMcpEffect | KillMcpEffect | SpawnDaemonEffect | KillDaemonEffect | StartGraceTimerEffect | CancelGraceTimerEffect | StartKeepTimerEffect | CancelKeepTimerEffect | StartBackoffTimerEffect | CancelBackoffTimerEffect | AllocatePortEffect | ReleasePortEffect | LogEffect;
90
+ export interface StepContext {
91
+ /** Monotonic ms (used to set `enteredAt` on transitions). */
92
+ now: number;
93
+ }
94
+ export interface StepResult {
95
+ record: DeviceRecord;
96
+ effects: FleetEffect[];
97
+ }
98
+ /**
99
+ * Pure FSM reducer.
100
+ *
101
+ * Apply `event` to `record` and return the next `record` plus the effects the
102
+ * supervisor must enact. Events that the current state does not care about
103
+ * are no-ops (empty effects, identical record).
104
+ *
105
+ * Important: the supervisor MUST update `record.binding` before calling
106
+ * `step()` for binding events, because some transitions consult
107
+ * `record.binding.instanceId` to decide between `spawning` and
108
+ * `awaiting_bind`.
109
+ */
110
+ export declare function step(record: DeviceRecord, event: FleetEvent, ctx: StepContext): StepResult;
111
+ /**
112
+ * Internal helper for the supervisor: when both children have been observed
113
+ * alive (mcp_started + daemon_started), the supervisor calls this to flip the
114
+ * record from `spawning` → `healthy`. Centralised here so the transition
115
+ * lives next to the rest of the state machine.
116
+ */
117
+ export declare function markHealthy(record: DeviceRecord, ctx: StepContext): StepResult;
118
+ /**
119
+ * Backoff schedule used by the supervisor when arming the
120
+ * `start_backoff_timer` effect. Exponential with cap.
121
+ */
122
+ export declare function backoffMs(attempt: number): number;