@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.
- package/.pi/extensions/android-tools.ts +139 -0
- package/.pi/skills/.gitkeep +0 -0
- package/.pi/skills/ground-mobile-fallback/SKILL.md +50 -0
- package/LICENSE +201 -0
- package/dist/action/handler.d.ts +9 -0
- package/dist/action/handler.js +124 -0
- package/dist/action/handler.js.map +1 -0
- package/dist/adapters/agent-gateway-client.d.ts +256 -0
- package/dist/adapters/agent-gateway-client.js +332 -0
- package/dist/adapters/agent-gateway-client.js.map +1 -0
- package/dist/adapters/agentcore-inner-loop.d.ts +29 -0
- package/dist/adapters/agentcore-inner-loop.js +72 -0
- package/dist/adapters/agentcore-inner-loop.js.map +1 -0
- package/dist/adapters/agentcore-pi.d.ts +215 -0
- package/dist/adapters/agentcore-pi.js +464 -0
- package/dist/adapters/agentcore-pi.js.map +1 -0
- package/dist/adapters/agentcore-runner.d.ts +70 -0
- package/dist/adapters/agentcore-runner.js +255 -0
- package/dist/adapters/agentcore-runner.js.map +1 -0
- package/dist/adapters/device-android-adb.d.ts +41 -0
- package/dist/adapters/device-android-adb.js +279 -0
- package/dist/adapters/device-android-adb.js.map +1 -0
- package/dist/adapters/device-desktop.d.ts +37 -0
- package/dist/adapters/device-desktop.js +101 -0
- package/dist/adapters/device-desktop.js.map +1 -0
- package/dist/adapters/identity-file.d.ts +30 -0
- package/dist/adapters/identity-file.js +50 -0
- package/dist/adapters/identity-file.js.map +1 -0
- package/dist/adapters/transport-bridge-ws.d.ts +39 -0
- package/dist/adapters/transport-bridge-ws.js +49 -0
- package/dist/adapters/transport-bridge-ws.js.map +1 -0
- package/dist/adapters/vlm-inner-loop.d.ts +88 -0
- package/dist/adapters/vlm-inner-loop.js +199 -0
- package/dist/adapters/vlm-inner-loop.js.map +1 -0
- package/dist/agent-runtime/adapters/base.d.ts +145 -0
- package/dist/agent-runtime/adapters/base.js +29 -0
- package/dist/agent-runtime/adapters/base.js.map +1 -0
- package/dist/agent-runtime/adapters/index.d.ts +17 -0
- package/dist/agent-runtime/adapters/index.js +17 -0
- package/dist/agent-runtime/adapters/index.js.map +1 -0
- package/dist/agent-runtime/adapters/mock.d.ts +44 -0
- package/dist/agent-runtime/adapters/mock.js +54 -0
- package/dist/agent-runtime/adapters/mock.js.map +1 -0
- package/dist/agent-runtime/adapters/openai.d.ts +63 -0
- package/dist/agent-runtime/adapters/openai.js +302 -0
- package/dist/agent-runtime/adapters/openai.js.map +1 -0
- package/dist/agent-runtime/adapters/registry.d.ts +49 -0
- package/dist/agent-runtime/adapters/registry.js +129 -0
- package/dist/agent-runtime/adapters/registry.js.map +1 -0
- package/dist/agent-runtime/adapters/ui-tars.d.ts +13 -0
- package/dist/agent-runtime/adapters/ui-tars.js +22 -0
- package/dist/agent-runtime/adapters/ui-tars.js.map +1 -0
- package/dist/agent-runtime/agent-runner.d.ts +149 -0
- package/dist/agent-runtime/agent-runner.js +356 -0
- package/dist/agent-runtime/agent-runner.js.map +1 -0
- package/dist/agent-runtime/core.d.ts +170 -0
- package/dist/agent-runtime/core.js +624 -0
- package/dist/agent-runtime/core.js.map +1 -0
- package/dist/agent-runtime/index.d.ts +16 -0
- package/dist/agent-runtime/index.js +17 -0
- package/dist/agent-runtime/index.js.map +1 -0
- package/dist/agent-runtime/plan-executor.d.ts +118 -0
- package/dist/agent-runtime/plan-executor.js +501 -0
- package/dist/agent-runtime/plan-executor.js.map +1 -0
- package/dist/agent-runtime/planner/base.d.ts +128 -0
- package/dist/agent-runtime/planner/base.js +157 -0
- package/dist/agent-runtime/planner/base.js.map +1 -0
- package/dist/agent-runtime/planner/llm-planner.d.ts +58 -0
- package/dist/agent-runtime/planner/llm-planner.js +112 -0
- package/dist/agent-runtime/planner/llm-planner.js.map +1 -0
- package/dist/agent-runtime/planner/noop-planner.d.ts +13 -0
- package/dist/agent-runtime/planner/noop-planner.js +30 -0
- package/dist/agent-runtime/planner/noop-planner.js.map +1 -0
- package/dist/agent-runtime/planner/prompts.d.ts +33 -0
- package/dist/agent-runtime/planner/prompts.js +165 -0
- package/dist/agent-runtime/planner/prompts.js.map +1 -0
- package/dist/agent-runtime/reflection.d.ts +81 -0
- package/dist/agent-runtime/reflection.js +189 -0
- package/dist/agent-runtime/reflection.js.map +1 -0
- package/dist/agent-runtime/reflectors/action-reflector.d.ts +97 -0
- package/dist/agent-runtime/reflectors/action-reflector.js +233 -0
- package/dist/agent-runtime/reflectors/action-reflector.js.map +1 -0
- package/dist/agent-runtime/reflectors/policy.d.ts +53 -0
- package/dist/agent-runtime/reflectors/policy.js +106 -0
- package/dist/agent-runtime/reflectors/policy.js.map +1 -0
- package/dist/agent-runtime/reflectors/trajectory-reflector.d.ts +94 -0
- package/dist/agent-runtime/reflectors/trajectory-reflector.js +223 -0
- package/dist/agent-runtime/reflectors/trajectory-reflector.js.map +1 -0
- package/dist/agent-runtime/skills/embedding.d.ts +53 -0
- package/dist/agent-runtime/skills/embedding.js +134 -0
- package/dist/agent-runtime/skills/embedding.js.map +1 -0
- package/dist/agent-runtime/skills/fs-store.d.ts +88 -0
- package/dist/agent-runtime/skills/fs-store.js +483 -0
- package/dist/agent-runtime/skills/fs-store.js.map +1 -0
- package/dist/agent-runtime/skills/index.d.ts +10 -0
- package/dist/agent-runtime/skills/index.js +10 -0
- package/dist/agent-runtime/skills/index.js.map +1 -0
- package/dist/agent-runtime/skills/matcher-evolver.d.ts +88 -0
- package/dist/agent-runtime/skills/matcher-evolver.js +110 -0
- package/dist/agent-runtime/skills/matcher-evolver.js.map +1 -0
- package/dist/agent-runtime/skills/memory-store.d.ts +23 -0
- package/dist/agent-runtime/skills/memory-store.js +94 -0
- package/dist/agent-runtime/skills/memory-store.js.map +1 -0
- package/dist/agent-runtime/skills/normalise.d.ts +40 -0
- package/dist/agent-runtime/skills/normalise.js +152 -0
- package/dist/agent-runtime/skills/normalise.js.map +1 -0
- package/dist/agent-runtime/skills/replay.d.ts +46 -0
- package/dist/agent-runtime/skills/replay.js +106 -0
- package/dist/agent-runtime/skills/replay.js.map +1 -0
- package/dist/agent-runtime/skills/sqlite-store.d.ts +60 -0
- package/dist/agent-runtime/skills/sqlite-store.js +234 -0
- package/dist/agent-runtime/skills/sqlite-store.js.map +1 -0
- package/dist/agent-runtime/skills/types.d.ts +99 -0
- package/dist/agent-runtime/skills/types.js +14 -0
- package/dist/agent-runtime/skills/types.js.map +1 -0
- package/dist/agent.d.ts +110 -0
- package/dist/agent.js +162 -0
- package/dist/agent.js.map +1 -0
- package/dist/api.d.ts +27 -0
- package/dist/api.js +48 -0
- package/dist/api.js.map +1 -0
- package/dist/app/agent-host.d.ts +59 -0
- package/dist/app/agent-host.js +263 -0
- package/dist/app/agent-host.js.map +1 -0
- package/dist/app/device-manager.d.ts +28 -0
- package/dist/app/device-manager.js +64 -0
- package/dist/app/device-manager.js.map +1 -0
- package/dist/app/message-store.d.ts +55 -0
- package/dist/app/message-store.js +99 -0
- package/dist/app/message-store.js.map +1 -0
- package/dist/app/session-manager.d.ts +132 -0
- package/dist/app/session-manager.js +350 -0
- package/dist/app/session-manager.js.map +1 -0
- package/dist/bootstrap.d.ts +94 -0
- package/dist/bootstrap.js +459 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/chat.d.ts +16 -0
- package/dist/chat.js +175 -0
- package/dist/chat.js.map +1 -0
- package/dist/config/loader.d.ts +77 -0
- package/dist/config/loader.js +292 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/schema.d.ts +162 -0
- package/dist/config/schema.js +243 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/core/actions.d.ts +60 -0
- package/dist/core/actions.js +120 -0
- package/dist/core/actions.js.map +1 -0
- package/dist/core/errors.d.ts +8 -0
- package/dist/core/errors.js +9 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/screen.d.ts +7 -0
- package/dist/core/screen.js +8 -0
- package/dist/core/screen.js.map +1 -0
- package/dist/core/session.d.ts +42 -0
- package/dist/core/session.js +29 -0
- package/dist/core/session.js.map +1 -0
- package/dist/debug/dump-system-prompt.d.ts +1 -0
- package/dist/debug/dump-system-prompt.js +34 -0
- package/dist/debug/dump-system-prompt.js.map +1 -0
- package/dist/device/android.d.ts +25 -0
- package/dist/device/android.js +231 -0
- package/dist/device/android.js.map +1 -0
- package/dist/device/apps.d.ts +3 -0
- package/dist/device/apps.js +77 -0
- package/dist/device/apps.js.map +1 -0
- package/dist/device/base.d.ts +20 -0
- package/dist/device/base.js +2 -0
- package/dist/device/base.js.map +1 -0
- package/dist/device/ui-xml.d.ts +29 -0
- package/dist/device/ui-xml.js +194 -0
- package/dist/device/ui-xml.js.map +1 -0
- package/dist/fleet/adapters/process/node-process-manager.d.ts +157 -0
- package/dist/fleet/adapters/process/node-process-manager.js +664 -0
- package/dist/fleet/adapters/process/node-process-manager.js.map +1 -0
- package/dist/fleet/adapters/sources/local-adb.d.ts +105 -0
- package/dist/fleet/adapters/sources/local-adb.js +353 -0
- package/dist/fleet/adapters/sources/local-adb.js.map +1 -0
- package/dist/fleet/adapters/sources/remote-adb.d.ts +97 -0
- package/dist/fleet/adapters/sources/remote-adb.js +138 -0
- package/dist/fleet/adapters/sources/remote-adb.js.map +1 -0
- package/dist/fleet/adapters/state/beeos-cli-store.d.ts +72 -0
- package/dist/fleet/adapters/state/beeos-cli-store.js +250 -0
- package/dist/fleet/adapters/state/beeos-cli-store.js.map +1 -0
- package/dist/fleet/adapters/state/port-allocator.d.ts +43 -0
- package/dist/fleet/adapters/state/port-allocator.js +173 -0
- package/dist/fleet/adapters/state/port-allocator.js.map +1 -0
- package/dist/fleet/domain/device.d.ts +138 -0
- package/dist/fleet/domain/device.js +49 -0
- package/dist/fleet/domain/device.js.map +1 -0
- package/dist/fleet/domain/events.d.ts +102 -0
- package/dist/fleet/domain/events.js +15 -0
- package/dist/fleet/domain/events.js.map +1 -0
- package/dist/fleet/domain/fsm.d.ts +122 -0
- package/dist/fleet/domain/fsm.js +475 -0
- package/dist/fleet/domain/fsm.js.map +1 -0
- package/dist/fleet/http/status-client.d.ts +31 -0
- package/dist/fleet/http/status-client.js +115 -0
- package/dist/fleet/http/status-client.js.map +1 -0
- package/dist/fleet/http/status-server.d.ts +64 -0
- package/dist/fleet/http/status-server.js +200 -0
- package/dist/fleet/http/status-server.js.map +1 -0
- package/dist/fleet/index.d.ts +27 -0
- package/dist/fleet/index.js +17 -0
- package/dist/fleet/index.js.map +1 -0
- package/dist/fleet/installer/index.d.ts +12 -0
- package/dist/fleet/installer/index.js +13 -0
- package/dist/fleet/installer/index.js.map +1 -0
- package/dist/fleet/installer/launchd-mac.d.ts +73 -0
- package/dist/fleet/installer/launchd-mac.js +291 -0
- package/dist/fleet/installer/launchd-mac.js.map +1 -0
- package/dist/fleet/installer/service-spec.d.ts +70 -0
- package/dist/fleet/installer/service-spec.js +43 -0
- package/dist/fleet/installer/service-spec.js.map +1 -0
- package/dist/fleet/installer/spawn-env.d.ts +45 -0
- package/dist/fleet/installer/spawn-env.js +224 -0
- package/dist/fleet/installer/spawn-env.js.map +1 -0
- package/dist/fleet/ports/clock.d.ts +19 -0
- package/dist/fleet/ports/clock.js +26 -0
- package/dist/fleet/ports/clock.js.map +1 -0
- package/dist/fleet/ports/device-source.d.ts +28 -0
- package/dist/fleet/ports/device-source.js +18 -0
- package/dist/fleet/ports/device-source.js.map +1 -0
- package/dist/fleet/ports/process-manager.d.ts +110 -0
- package/dist/fleet/ports/process-manager.js +27 -0
- package/dist/fleet/ports/process-manager.js.map +1 -0
- package/dist/fleet/ports/state-registry.d.ts +49 -0
- package/dist/fleet/ports/state-registry.js +12 -0
- package/dist/fleet/ports/state-registry.js.map +1 -0
- package/dist/fleet/supervisor.d.ts +107 -0
- package/dist/fleet/supervisor.js +508 -0
- package/dist/fleet/supervisor.js.map +1 -0
- package/dist/grounding/grounder.d.ts +46 -0
- package/dist/grounding/grounder.js +82 -0
- package/dist/grounding/grounder.js.map +1 -0
- package/dist/inbound/acp/handlers/device.d.ts +43 -0
- package/dist/inbound/acp/handlers/device.js +153 -0
- package/dist/inbound/acp/handlers/device.js.map +1 -0
- package/dist/inbound/acp/handlers/initialize.d.ts +71 -0
- package/dist/inbound/acp/handlers/initialize.js +53 -0
- package/dist/inbound/acp/handlers/initialize.js.map +1 -0
- package/dist/inbound/acp/handlers/models.d.ts +16 -0
- package/dist/inbound/acp/handlers/models.js +23 -0
- package/dist/inbound/acp/handlers/models.js.map +1 -0
- package/dist/inbound/acp/handlers/session.d.ts +51 -0
- package/dist/inbound/acp/handlers/session.js +61 -0
- package/dist/inbound/acp/handlers/session.js.map +1 -0
- package/dist/inbound/acp/handlers/skills.d.ts +8 -0
- package/dist/inbound/acp/handlers/skills.js +9 -0
- package/dist/inbound/acp/handlers/skills.js.map +1 -0
- package/dist/inbound/acp/notifier.d.ts +35 -0
- package/dist/inbound/acp/notifier.js +45 -0
- package/dist/inbound/acp/notifier.js.map +1 -0
- package/dist/inbound/acp/router.d.ts +67 -0
- package/dist/inbound/acp/router.js +179 -0
- package/dist/inbound/acp/router.js.map +1 -0
- package/dist/inbound/cli/fleet-command.d.ts +34 -0
- package/dist/inbound/cli/fleet-command.js +792 -0
- package/dist/inbound/cli/fleet-command.js.map +1 -0
- package/dist/inbound/cli/main.d.ts +38 -0
- package/dist/inbound/cli/main.js +364 -0
- package/dist/inbound/cli/main.js.map +1 -0
- package/dist/inbound/cli/run-command.d.ts +101 -0
- package/dist/inbound/cli/run-command.js +405 -0
- package/dist/inbound/cli/run-command.js.map +1 -0
- package/dist/inbound/cli/skills-command.d.ts +39 -0
- package/dist/inbound/cli/skills-command.js +333 -0
- package/dist/inbound/cli/skills-command.js.map +1 -0
- package/dist/inbound/http/server.d.ts +7 -0
- package/dist/inbound/http/server.js +8 -0
- package/dist/inbound/http/server.js.map +1 -0
- package/dist/index.d.ts +66 -0
- package/dist/index.js +48 -0
- package/dist/index.js.map +1 -0
- package/dist/logger/index.d.ts +37 -0
- package/dist/logger/index.js +84 -0
- package/dist/logger/index.js.map +1 -0
- package/dist/mcp-client/autospawn.d.ts +67 -0
- package/dist/mcp-client/autospawn.js +173 -0
- package/dist/mcp-client/autospawn.js.map +1 -0
- package/dist/mcp-client/client.d.ts +78 -0
- package/dist/mcp-client/client.js +168 -0
- package/dist/mcp-client/client.js.map +1 -0
- package/dist/mcp-client/index.d.ts +7 -0
- package/dist/mcp-client/index.js +4 -0
- package/dist/mcp-client/index.js.map +1 -0
- package/dist/mcp-client/inproc.d.ts +47 -0
- package/dist/mcp-client/inproc.js +229 -0
- package/dist/mcp-client/inproc.js.map +1 -0
- package/dist/mcp-client/runtime.d.ts +34 -0
- package/dist/mcp-client/runtime.js +15 -0
- package/dist/mcp-client/runtime.js.map +1 -0
- package/dist/model/adapters/autoglm.d.ts +31 -0
- package/dist/model/adapters/autoglm.js +409 -0
- package/dist/model/adapters/autoglm.js.map +1 -0
- package/dist/model/adapters/base.d.ts +13 -0
- package/dist/model/adapters/base.js +27 -0
- package/dist/model/adapters/base.js.map +1 -0
- package/dist/model/adapters/guiowl.d.ts +1 -0
- package/dist/model/adapters/guiowl.js +253 -0
- package/dist/model/adapters/guiowl.js.map +1 -0
- package/dist/model/adapters/index.d.ts +6 -0
- package/dist/model/adapters/index.js +8 -0
- package/dist/model/adapters/index.js.map +1 -0
- package/dist/model/adapters/maiui.d.ts +1 -0
- package/dist/model/adapters/maiui.js +117 -0
- package/dist/model/adapters/maiui.js.map +1 -0
- package/dist/model/adapters/qwenvl.d.ts +1 -0
- package/dist/model/adapters/qwenvl.js +108 -0
- package/dist/model/adapters/qwenvl.js.map +1 -0
- package/dist/model/adapters/showui.d.ts +1 -0
- package/dist/model/adapters/showui.js +132 -0
- package/dist/model/adapters/showui.js.map +1 -0
- package/dist/model/adapters/tool-call.d.ts +6 -0
- package/dist/model/adapters/tool-call.js +102 -0
- package/dist/model/adapters/tool-call.js.map +1 -0
- package/dist/model/adapters/uitars.d.ts +1 -0
- package/dist/model/adapters/uitars.js +180 -0
- package/dist/model/adapters/uitars.js.map +1 -0
- package/dist/model/base.d.ts +32 -0
- package/dist/model/base.js +2 -0
- package/dist/model/base.js.map +1 -0
- package/dist/model/client.d.ts +26 -0
- package/dist/model/client.js +300 -0
- package/dist/model/client.js.map +1 -0
- package/dist/model/image/compress.d.ts +53 -0
- package/dist/model/image/compress.js +89 -0
- package/dist/model/image/compress.js.map +1 -0
- package/dist/model/image/transport.d.ts +134 -0
- package/dist/model/image/transport.js +154 -0
- package/dist/model/image/transport.js.map +1 -0
- package/dist/orchestrator-system-prompt.d.ts +6 -0
- package/dist/orchestrator-system-prompt.js +81 -0
- package/dist/orchestrator-system-prompt.js.map +1 -0
- package/dist/pi-context.d.ts +82 -0
- package/dist/pi-context.js +62 -0
- package/dist/pi-context.js.map +1 -0
- package/dist/pi-local-skills.d.ts +17 -0
- package/dist/pi-local-skills.js +24 -0
- package/dist/pi-local-skills.js.map +1 -0
- package/dist/plugins/acp/index.d.ts +46 -0
- package/dist/plugins/acp/index.js +111 -0
- package/dist/plugins/acp/index.js.map +1 -0
- package/dist/plugins/agent-sync/index.d.ts +40 -0
- package/dist/plugins/agent-sync/index.js +98 -0
- package/dist/plugins/agent-sync/index.js.map +1 -0
- package/dist/plugins/http-debug/index.d.ts +30 -0
- package/dist/plugins/http-debug/index.js +64 -0
- package/dist/plugins/http-debug/index.js.map +1 -0
- package/dist/plugins/http-debug/server.d.ts +92 -0
- package/dist/plugins/http-debug/server.js +464 -0
- package/dist/plugins/http-debug/server.js.map +1 -0
- package/dist/ports/agent-core.d.ts +158 -0
- package/dist/ports/agent-core.js +2 -0
- package/dist/ports/agent-core.js.map +1 -0
- package/dist/ports/agent-host.d.ts +125 -0
- package/dist/ports/agent-host.js +23 -0
- package/dist/ports/agent-host.js.map +1 -0
- package/dist/ports/device.d.ts +53 -0
- package/dist/ports/device.js +13 -0
- package/dist/ports/device.js.map +1 -0
- package/dist/ports/identity.d.ts +22 -0
- package/dist/ports/identity.js +9 -0
- package/dist/ports/identity.js.map +1 -0
- package/dist/ports/plugin.d.ts +62 -0
- package/dist/ports/plugin.js +35 -0
- package/dist/ports/plugin.js.map +1 -0
- package/dist/ports/transport.d.ts +32 -0
- package/dist/ports/transport.js +12 -0
- package/dist/ports/transport.js.map +1 -0
- package/dist/ports/vlm.d.ts +59 -0
- package/dist/ports/vlm.js +14 -0
- package/dist/ports/vlm.js.map +1 -0
- package/dist/test-lan-autoglm.d.ts +7 -0
- package/dist/test-lan-autoglm.js +46 -0
- package/dist/test-lan-autoglm.js.map +1 -0
- package/dist/test-mem-breakdown.d.ts +1 -0
- package/dist/test-mem-breakdown.js +103 -0
- package/dist/test-mem-breakdown.js.map +1 -0
- package/dist/test-mem.d.ts +1 -0
- package/dist/test-mem.js +60 -0
- package/dist/test-mem.js.map +1 -0
- package/dist/test-mobile-use.d.ts +1 -0
- package/dist/test-mobile-use.js +18 -0
- package/dist/test-mobile-use.js.map +1 -0
- package/dist/test-screenshot-loop.d.ts +1 -0
- package/dist/test-screenshot-loop.js +43 -0
- package/dist/test-screenshot-loop.js.map +1 -0
- package/dist/test-screenshot.d.ts +1 -0
- package/dist/test-screenshot.js +10 -0
- package/dist/test-screenshot.js.map +1 -0
- package/dist/test-ui-xml-dump.d.ts +15 -0
- package/dist/test-ui-xml-dump.js +49 -0
- package/dist/test-ui-xml-dump.js.map +1 -0
- package/dist/types.d.ts +69 -0
- package/dist/types.js +23 -0
- package/dist/types.js.map +1 -0
- 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
|
+
}
|