@beeos-ai/device-agent 0.9.3 → 0.9.5

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 (72) hide show
  1. package/dist/adapters/transport-bridge-ws.d.ts +12 -0
  2. package/dist/adapters/transport-bridge-ws.js +27 -3
  3. package/dist/adapters/transport-bridge-ws.js.map +1 -1
  4. package/dist/agent-runtime/core.d.ts +1 -1
  5. package/dist/agent-runtime/core.js +41 -0
  6. package/dist/agent-runtime/core.js.map +1 -1
  7. package/dist/app/session-manager.d.ts +14 -11
  8. package/dist/app/session-manager.js +8 -9
  9. package/dist/app/session-manager.js.map +1 -1
  10. package/dist/bootstrap.js +140 -11
  11. package/dist/bootstrap.js.map +1 -1
  12. package/dist/chat.js +11 -1
  13. package/dist/chat.js.map +1 -1
  14. package/dist/config/loader.js +3 -0
  15. package/dist/config/loader.js.map +1 -1
  16. package/dist/config/schema.d.ts +3 -0
  17. package/dist/config/schema.js +51 -15
  18. package/dist/config/schema.js.map +1 -1
  19. package/dist/fleet/adapters/process/node-process-manager.d.ts +115 -13
  20. package/dist/fleet/adapters/process/node-process-manager.js +412 -64
  21. package/dist/fleet/adapters/process/node-process-manager.js.map +1 -1
  22. package/dist/fleet/adapters/state/port-allocator.d.ts +12 -0
  23. package/dist/fleet/adapters/state/port-allocator.js +39 -5
  24. package/dist/fleet/adapters/state/port-allocator.js.map +1 -1
  25. package/dist/fleet/domain/events.d.ts +23 -1
  26. package/dist/fleet/domain/fsm.d.ts +13 -1
  27. package/dist/fleet/domain/fsm.js +70 -0
  28. package/dist/fleet/domain/fsm.js.map +1 -1
  29. package/dist/fleet/supervisor.js +30 -0
  30. package/dist/fleet/supervisor.js.map +1 -1
  31. package/dist/health/adb-track-devices.d.ts +103 -0
  32. package/dist/health/adb-track-devices.js +171 -0
  33. package/dist/health/adb-track-devices.js.map +1 -0
  34. package/dist/health/health-reporter.d.ts +67 -0
  35. package/dist/health/health-reporter.js +123 -0
  36. package/dist/health/health-reporter.js.map +1 -0
  37. package/dist/health/index.d.ts +6 -0
  38. package/dist/health/index.js +4 -0
  39. package/dist/health/index.js.map +1 -0
  40. package/dist/health/mcp-health-monitor.d.ts +190 -0
  41. package/dist/health/mcp-health-monitor.js +267 -0
  42. package/dist/health/mcp-health-monitor.js.map +1 -0
  43. package/dist/inbound/cli/main.js +8 -1
  44. package/dist/inbound/cli/main.js.map +1 -1
  45. package/dist/inbound/cli/run-command.js +11 -1
  46. package/dist/inbound/cli/run-command.js.map +1 -1
  47. package/dist/index.d.ts +1 -1
  48. package/dist/index.js.map +1 -1
  49. package/dist/mcp-client/action-mapping.d.ts +45 -0
  50. package/dist/mcp-client/action-mapping.js +224 -0
  51. package/dist/mcp-client/action-mapping.js.map +1 -0
  52. package/dist/mcp-client/autospawn.d.ts +15 -2
  53. package/dist/mcp-client/autospawn.js +82 -4
  54. package/dist/mcp-client/autospawn.js.map +1 -1
  55. package/dist/mcp-client/client.d.ts +134 -38
  56. package/dist/mcp-client/client.js +394 -87
  57. package/dist/mcp-client/client.js.map +1 -1
  58. package/dist/mcp-client/index.d.ts +5 -3
  59. package/dist/mcp-client/index.js +2 -1
  60. package/dist/mcp-client/index.js.map +1 -1
  61. package/dist/mcp-client/inproc.d.ts +2 -2
  62. package/dist/mcp-client/inproc.js.map +1 -1
  63. package/dist/mcp-client/runtime.d.ts +124 -21
  64. package/dist/mcp-client/runtime.js +18 -7
  65. package/dist/mcp-client/runtime.js.map +1 -1
  66. package/dist/model/adapters/autoglm.js +44 -45
  67. package/dist/model/adapters/autoglm.js.map +1 -1
  68. package/dist/plugins/acp/index.d.ts +35 -0
  69. package/dist/plugins/acp/index.js +121 -0
  70. package/dist/plugins/acp/index.js.map +1 -1
  71. package/dist/ports/transport.d.ts +11 -0
  72. package/package.json +3 -2
@@ -30,11 +30,13 @@
30
30
  */
31
31
  import { BridgeWsTransport } from "../../adapters/transport-bridge-ws.js";
32
32
  import { deriveFixedSessionId } from "../../app/fixed-session-id.js";
33
+ import { AdbTrackDevices, HealthReporter, MCPHealthMonitor, } from "../../health/index.js";
33
34
  import { AcpDeviceHandlers } from "../../inbound/acp/handlers/device.js";
34
35
  import { AcpSessionHandlers } from "../../inbound/acp/handlers/session.js";
35
36
  import { AcpSkillsHandlers } from "../../inbound/acp/handlers/skills.js";
36
37
  import { AcpRouter, bindRouterToTransport } from "../../inbound/acp/router.js";
37
38
  import { TransportSessionNotifier } from "../../inbound/acp/notifier.js";
39
+ import { resolveDefaultMcpUrl } from "../../mcp-client/index.js";
38
40
  export class AcpPlugin {
39
41
  opts;
40
42
  name = "acp";
@@ -42,6 +44,10 @@ export class AcpPlugin {
42
44
  transport = null;
43
45
  boundSid = null;
44
46
  unbind = null;
47
+ healthMonitor = null;
48
+ healthReporter = null;
49
+ adbTracker = null;
50
+ adbTrackerOnChange = null;
45
51
  constructor(opts) {
46
52
  this.opts = opts;
47
53
  }
@@ -87,11 +93,86 @@ export class AcpPlugin {
87
93
  });
88
94
  this.transport = transport;
89
95
  this.unbind = bindRouterToTransport(router, transport);
96
+ // Health-reporting plumbing — only activates when an HTTP McpClient
97
+ // is wired in by bootstrap. The pair publishes `device/health`
98
+ // notifications over the same transport (so they ride the same
99
+ // auth + reconnect machinery as session/update). The reporter
100
+ // listens for `transport.connected` and re-emits last-known state
101
+ // on every reconnect — without that, a state change that happens
102
+ // while the WS is down is silently dropped (see notifier.ts).
103
+ if (this.opts.mcpClient) {
104
+ const endpoint = new URL(this.opts.mcpEndpoint ?? resolveDefaultMcpUrl());
105
+ // Normalise bare-origin URLs to /mcp so the active probe hits the
106
+ // streamable HTTP endpoint, not a 404 root.
107
+ if (endpoint.pathname === "" || endpoint.pathname === "/") {
108
+ endpoint.pathname = "/mcp";
109
+ }
110
+ this.healthMonitor = new MCPHealthMonitor({
111
+ mcpEndpoint: endpoint,
112
+ mcpClient: this.opts.mcpClient,
113
+ });
114
+ this.healthReporter = new HealthReporter({
115
+ monitor: this.healthMonitor,
116
+ transport,
117
+ logger: log,
118
+ });
119
+ // Push source — when an ADB serial is configured (Android self-
120
+ // hosted path), wire `adb track-devices` events directly into the
121
+ // monitor via mark{Healthy,Unhealthy}. This bypasses the 60s
122
+ // active probe + 5s flap window so USB unplug propagates to the
123
+ // cluster in ~2-3s. Desktop / agentbay paths leave adbSerial
124
+ // empty and fall back to the passive callResult path.
125
+ if (this.opts.adbSerial) {
126
+ this.adbTracker = new AdbTrackDevices({
127
+ targetSerial: this.opts.adbSerial,
128
+ logger: log,
129
+ });
130
+ this.adbTrackerOnChange = (state) => {
131
+ if (!this.healthMonitor)
132
+ return;
133
+ if (state.ok)
134
+ this.healthMonitor.markHealthy();
135
+ else
136
+ this.healthMonitor.markUnhealthy(state.reason);
137
+ };
138
+ this.adbTracker.on("change", this.adbTrackerOnChange);
139
+ }
140
+ }
90
141
  }
91
142
  async start() {
92
143
  if (!this.transport)
93
144
  return;
94
145
  await this.transport.connect();
146
+ // Order: arm the active probe BEFORE priming so the periodic timer
147
+ // is already running by the time the first state lands. Prime is
148
+ // awaited so the very first `change` event is the ground-truth
149
+ // snapshot, not a guess — the bridge is connected at this point so
150
+ // the prime emission gets delivered immediately.
151
+ if (this.healthMonitor) {
152
+ this.healthMonitor.start();
153
+ // Settle window: give the transport's `connected` event a tick
154
+ // to propagate so flushOnReconnect doesn't fire before
155
+ // `last` is non-null. 1s is generous; the actual prime probe
156
+ // returns in <2s under normal conditions.
157
+ await new Promise((resolve) => setTimeout(resolve, 1_000));
158
+ await this.healthMonitor.primeInitialState().catch((err) => {
159
+ if (this.ctx) {
160
+ this.ctx.log.warn({ err: err instanceof Error ? err.message : String(err) }, "acp: health monitor primeInitialState failed (will retry on next probe)");
161
+ }
162
+ });
163
+ }
164
+ // Start the ADB push source AFTER monitor.primeInitialState — so the
165
+ // initial healthy/unhealthy snapshot lands first, and the
166
+ // first track-devices event (typically `adb_online` for the bound
167
+ // serial) becomes a markHealthy() that's correctly deduped by
168
+ // transition.equalState rather than an extra emission.
169
+ if (this.adbTracker) {
170
+ await this.adbTracker.start().catch((err) => {
171
+ if (this.ctx) {
172
+ this.ctx.log.warn({ err: err instanceof Error ? err.message : String(err) }, "acp: adb-track-devices failed to start (will retry internally)");
173
+ }
174
+ });
175
+ }
95
176
  }
96
177
  /**
97
178
  * Visible for tests — exposes the sid this plugin binds to so test
@@ -100,6 +181,46 @@ export class AcpPlugin {
100
181
  */
101
182
  static deriveFixedSessionId = deriveFixedSessionId;
102
183
  async stop() {
184
+ // Tear down health plumbing first so its on-transport "connected"
185
+ // / on-monitor "change" handlers don't fire during the rest of
186
+ // teardown. Order: tracker → reporter → monitor (push source first
187
+ // so it can't push into a half-disposed monitor).
188
+ if (this.adbTracker) {
189
+ if (this.adbTrackerOnChange) {
190
+ try {
191
+ this.adbTracker.off("change", this.adbTrackerOnChange);
192
+ }
193
+ catch {
194
+ /* ignore */
195
+ }
196
+ this.adbTrackerOnChange = null;
197
+ }
198
+ try {
199
+ await this.adbTracker.dispose();
200
+ }
201
+ catch {
202
+ /* ignore */
203
+ }
204
+ this.adbTracker = null;
205
+ }
206
+ if (this.healthReporter) {
207
+ try {
208
+ this.healthReporter.dispose();
209
+ }
210
+ catch {
211
+ /* ignore */
212
+ }
213
+ this.healthReporter = null;
214
+ }
215
+ if (this.healthMonitor) {
216
+ try {
217
+ this.healthMonitor.dispose();
218
+ }
219
+ catch {
220
+ /* ignore */
221
+ }
222
+ this.healthMonitor = null;
223
+ }
103
224
  if (this.boundSid && this.ctx) {
104
225
  try {
105
226
  this.ctx.sessionManager.unbindNotifier(this.boundSid);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/plugins/acp/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/plugins/acp/index.ts"],"names":[],"mappings":"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"}
@@ -29,4 +29,15 @@ export interface IBridgeTransport {
29
29
  on(event: "disconnected", handler: (reason: string) => void): void;
30
30
  on(event: "message", handler: (data: string) => void | Promise<void>): void;
31
31
  on(event: "error", handler: (err: Error) => void): void;
32
+ /**
33
+ * Detach a handler previously attached via `on`. Used by long-lived
34
+ * subscribers (e.g. HealthReporter) to clean up on shutdown so the
35
+ * underlying EventEmitter doesn't grow unboundedly across hot reloads
36
+ * or test harnesses. The handler reference must match the one passed
37
+ * to `on`; identity-based removal mirrors `EventEmitter.off`.
38
+ */
39
+ off(event: "connected", handler: () => void): void;
40
+ off(event: "disconnected", handler: (reason: string) => void): void;
41
+ off(event: "message", handler: (data: string) => void | Promise<void>): void;
42
+ off(event: "error", handler: (err: Error) => void): void;
32
43
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@beeos-ai/device-agent",
3
- "version": "0.9.3",
3
+ "version": "0.9.5",
4
4
  "description": "BeeOS device-agent — Android/desktop AI control agent (TypeScript) speaking ACP over Bridge WebSocket. Connects to a sibling device-mcp-server process for device control.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -57,6 +57,7 @@
57
57
  "@fastify/cors": "^11.2.0",
58
58
  "@fastify/multipart": "^10.0.0",
59
59
  "@mariozechner/pi-coding-agent": "0.70.2",
60
+ "@modelcontextprotocol/sdk": "^1.29.0",
60
61
  "dotenv": "^16.5.0",
61
62
  "fastify": "^5.8.5",
62
63
  "openai": "^4.98.0",
@@ -72,7 +73,7 @@
72
73
  "tsx": "^4.19.0",
73
74
  "typescript": "^5.8.0",
74
75
  "vitest": "^4.1.5",
75
- "@beeos-ai/device-mcp-server": "0.3.0"
76
+ "@beeos-ai/device-mcp-server": "0.4.2"
76
77
  },
77
78
  "scripts": {
78
79
  "build": "tsc -p tsconfig.json && chmod +x dist/inbound/cli/main.js",