@beeos-ai/device-agent 0.9.3 → 0.9.7

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 (102) 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 +65 -21
  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 +10 -3
  44. package/dist/inbound/cli/main.js.map +1 -1
  45. package/dist/inbound/cli/run-command.js +24 -2
  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/messaging/token-provider.d.ts +15 -14
  67. package/dist/messaging/token-provider.js +16 -16
  68. package/dist/messaging/token-provider.js.map +1 -1
  69. package/dist/model/adapters/autoglm.js +44 -45
  70. package/dist/model/adapters/autoglm.js.map +1 -1
  71. package/dist/model/adapters/guiowl.js +3 -2
  72. package/dist/model/adapters/guiowl.js.map +1 -1
  73. package/dist/model/adapters/maiui.js +80 -53
  74. package/dist/model/adapters/maiui.js.map +1 -1
  75. package/dist/model/adapters/qwenvl.js +147 -51
  76. package/dist/model/adapters/qwenvl.js.map +1 -1
  77. package/dist/model/adapters/tool-call.js +13 -3
  78. package/dist/model/adapters/tool-call.js.map +1 -1
  79. package/dist/model/adapters/uitars.js +80 -84
  80. package/dist/model/adapters/uitars.js.map +1 -1
  81. package/dist/plugins/acp/index.d.ts +35 -0
  82. package/dist/plugins/acp/index.js +121 -0
  83. package/dist/plugins/acp/index.js.map +1 -1
  84. package/dist/plugins/message-bus/busy-reply.d.ts +5 -5
  85. package/dist/plugins/message-bus/busy-reply.js +30 -9
  86. package/dist/plugins/message-bus/busy-reply.js.map +1 -1
  87. package/dist/plugins/message-bus/cancel.d.ts +5 -11
  88. package/dist/plugins/message-bus/cancel.js +8 -14
  89. package/dist/plugins/message-bus/cancel.js.map +1 -1
  90. package/dist/plugins/message-bus/inbound.d.ts +18 -25
  91. package/dist/plugins/message-bus/inbound.js +23 -55
  92. package/dist/plugins/message-bus/inbound.js.map +1 -1
  93. package/dist/plugins/message-bus/index.d.ts +25 -44
  94. package/dist/plugins/message-bus/index.js +70 -111
  95. package/dist/plugins/message-bus/index.js.map +1 -1
  96. package/dist/plugins/message-bus/ms-channel-notifier.d.ts +24 -37
  97. package/dist/plugins/message-bus/ms-channel-notifier.js +39 -59
  98. package/dist/plugins/message-bus/ms-channel-notifier.js.map +1 -1
  99. package/dist/ports/transport.d.ts +11 -0
  100. package/dist/resources/parsers.js +17 -0
  101. package/dist/resources/parsers.js.map +1 -1
  102. package/package.json +4 -3
@@ -1,66 +1,122 @@
1
1
  /**
2
- * McpClient — typed HTTP wrapper around `device-mcp-server`.
2
+ * McpClient — typed wrapper around the official `@modelcontextprotocol/sdk`
3
+ * Client connected over Streamable HTTP to the sibling
4
+ * `device-mcp-server` (or any other MCP server speaking the same tools).
3
5
  *
4
- * The device-agent never talks to ADB / desktop sandboxes directly any more —
5
- * everything goes through this client to the sibling MCP HTTP server. The
6
- * client is intentionally thin: zero LLM / agent semantics, no caching, no
7
- * retry on tool errors (only on connection-level failures during health
8
- * probing).
6
+ * 0.4.0 reshape:
7
+ * - The bespoke `/healthz` / `/mcp/tools/list` / `/mcp/tools/call` /
8
+ * `/act` REST surface is gone — everything goes through the SDK
9
+ * `Client.callTool` and the `initialize` handshake handled by
10
+ * `Client.connect(transport)`.
11
+ * - `device-mcp-server` is now a singleton multi-device process; this
12
+ * client owns a `defaultDevice` (Ed25519-derived ADB serial / "desktop")
13
+ * and injects it as the `device` argument on every `callTool` so the
14
+ * server's `BackendRegistry.resolve(...)` always lands on the right
15
+ * backend.
16
+ * - `act(action)` is implemented locally by translating the Action into
17
+ * the matching tool call via `mapActionToTool` and synthesising the
18
+ * legacy `ActResponse` envelope on top of the SDK `CallToolResult`.
9
19
  *
10
20
  * Defaults:
11
- * - baseUrl: http://127.0.0.1:7900 (override via `MCP_URL` env)
21
+ * - baseUrl: http://127.0.0.1:7900 (override via `MCP_URL` env)
12
22
  * - timeout: 30s per request
13
23
  *
14
- * Surface mirrors the Python reference's `MCPClient` plus a couple of
15
- * device-agent–specific conveniences (`act`, `screenshot`, `uiDump`,
16
- * `health`, `waitUntilReady`).
24
+ * Threading: `Client.connect` is invoked lazily on first call. Concurrent
25
+ * callers share a single in-flight connect promise so the handshake only
26
+ * runs once. After connect, the client is stateless from the caller's
27
+ * point of view — every `callTool` is an independent JSON-RPC request.
17
28
  */
18
- import { type Action, type ActResponse, type DeviceInfo, type ExecuteCommandResult, type HealthResponse, type ScreenshotResult, type ToolListResponse, type UiDumpResult } from "@beeos-ai/device-common";
19
- import type { ExecuteCommandOptions, IMcpRuntime, UiDumpOptions } from "./runtime.js";
29
+ import { EventEmitter } from "node:events";
30
+ import type { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
31
+ import { type Action, type AppInfo, type BackendFamily, type CrashSummary, type DeviceInfo, type ExecuteCommandResult, type Orientation, type SaveScreenshotResult, type ScreenRecordHandle, type ScreenRecordResult, type ScreenshotResult, type UiDumpResult } from "@beeos-ai/device-common";
32
+ import type { ActResponse, CallToolOutput, ExecuteCommandOptions, IMcpRuntime, ListAppsOptions, ScreenshotToFileOptions, StartScreenRecordOptions, SwipeDirectionOptions, UiDumpOptions } from "./runtime.js";
20
33
  export interface McpClientOptions {
21
- /** HTTP base URL of the sibling device-mcp-server. Falls back to MCP_URL env / 127.0.0.1:7900. */
34
+ /**
35
+ * HTTP base URL of the sibling device-mcp-server. Either the bare host
36
+ * (e.g. `http://127.0.0.1:7900`, in which case we append `/mcp`) or the
37
+ * full MCP endpoint (`http://127.0.0.1:7900/mcp`). Falls back to MCP_URL
38
+ * env / 127.0.0.1:7900.
39
+ */
22
40
  baseUrl?: string;
23
41
  /** Per-request timeout in ms. Defaults to 30s. */
24
42
  timeoutMs?: number;
43
+ /**
44
+ * Default device id passed as `device: "..."` on every tool call. Lets
45
+ * the singleton multi-device server route to the right backend without
46
+ * the caller having to thread it through every method. Empty / undefined
47
+ * = no implicit device (server falls back to its single-device default
48
+ * or to the `use_device` sticky session, neither of which apply over
49
+ * stateless HTTP — so production should always set this).
50
+ */
51
+ defaultDevice?: string;
25
52
  /** Optional Bearer / shared-secret auth token forwarded as `Authorization: Bearer ...`. */
26
53
  authToken?: string;
27
- /** Optional fetch override (used by tests). */
28
- fetchImpl?: typeof fetch;
29
- }
30
- export interface CallToolResult<T = unknown> {
31
- ok: boolean;
32
- raw: T;
33
- durationMs: number;
54
+ /**
55
+ * Backend family of the resolved `defaultDevice`. Used by the
56
+ * action-mapping layer to fork desktop-only verbs (`click` /
57
+ * `double_click`) onto their mobile equivalents (`tap` / `double_tap`)
58
+ * before they hit the wire. `undefined` keeps the legacy 1:1 mapping
59
+ * (no rewrite) so old call sites and tests don't break.
60
+ */
61
+ backendFamily?: BackendFamily;
62
+ /**
63
+ * Test seam: inject a pre-built MCP `Transport` (e.g. one half of an
64
+ * `InMemoryTransport.createLinkedPair()`) instead of opening a real
65
+ * HTTP connection. When set, `baseUrl` / `authToken` are ignored.
66
+ * Production callers should never pass this.
67
+ */
68
+ transport?: Transport;
34
69
  }
35
70
  /**
36
71
  * Resolve the default MCP base URL (env-aware).
37
72
  */
38
73
  export declare function resolveDefaultMcpUrl(): string;
39
- export declare class McpClient implements IMcpRuntime {
40
- private readonly baseUrl;
74
+ /** Read the version string the McpClient advertises via MCP `initialize`. */
75
+ export declare function getClientVersion(): string;
76
+ /**
77
+ * Payload emitted on every `callTool` outcome (including failures from
78
+ * `invoke`'s try/catch). Subscribed by the device-agent's MCP health
79
+ * monitor so it can derive the device's connectivity state without
80
+ * each call site re-implementing the classification:
81
+ *
82
+ * ok=true → MCP + device reachable
83
+ * ok=false, subtype="adb_unauthorized" → device present, ADB not authorised
84
+ * ok=false, subtype="mcp_unreachable" → MCP HTTP transport down
85
+ * ok=false, subtype=other / undefined → device-level failure (treat as disconnected)
86
+ */
87
+ export interface McpCallResult {
88
+ ok: boolean;
89
+ subtype?: string;
90
+ }
91
+ export declare class McpClient extends EventEmitter implements IMcpRuntime {
92
+ private readonly endpoint;
41
93
  private readonly timeoutMs;
94
+ private readonly defaultDevice?;
42
95
  private readonly authToken?;
43
- private readonly fetchImpl;
96
+ private readonly backendFamily?;
97
+ private readonly client;
98
+ private readonly injectedTransport?;
99
+ private connectPromise?;
44
100
  constructor(opts?: McpClientOptions);
45
- /** Backend health probe. Throws `McpUnreachableError` on connection failure. */
46
- health(): Promise<HealthResponse>;
47
101
  /**
48
- * Wait until the MCP server's `/healthz` returns `ok=true`. Used by
49
- * bootstrap to gate startup on the sibling process.
102
+ * Wait until the MCP server's `initialize` handshake succeeds. Used by
103
+ * bootstrap to gate startup on the sibling process. Replaces the
104
+ * pre-0.4 `health()` + `/healthz` probe.
50
105
  *
51
106
  * Strategy: linear retry with `attemptDelayMs` between probes; gives up
52
- * after `attempts` tries. Default: 10 × 500ms = ~5s.
107
+ * after `attempts` tries. Default: 30 × 500ms = ~15s — large enough to
108
+ * cover the cold-start window of an autospawned `device-mcp-server`
109
+ * binary (especially under `tsx`/Node ESM resolve on the first run)
110
+ * without blocking too long when the server is genuinely unreachable.
53
111
  */
54
112
  waitUntilReady(opts?: {
55
113
  attempts?: number;
56
114
  attemptDelayMs?: number;
57
- }): Promise<HealthResponse>;
58
- /** List all registered MCP tool descriptors. */
59
- listTools(): Promise<ToolListResponse>;
60
- /** Invoke a single MCP tool by name. */
61
- callTool<T = unknown>(name: string, args?: Record<string, unknown>): Promise<CallToolResult<T>>;
62
- /** Submit a unified Action — server maps to the right tool internally. */
63
- act(action: Action): Promise<ActResponse>;
115
+ }): Promise<{
116
+ ok: true;
117
+ }>;
118
+ /** Generic MCP tool dispatch — used for tools without a typed convenience method. */
119
+ callTool<T = unknown>(name: string, args?: Record<string, unknown>): Promise<CallToolOutput<T>>;
64
120
  /** Convenience: take a screenshot via `tool: screenshot`. */
65
121
  screenshot(): Promise<ScreenshotResult>;
66
122
  /**
@@ -76,9 +132,49 @@ export declare class McpClient implements IMcpRuntime {
76
132
  executeCommand(body: string, opts?: ExecuteCommandOptions): Promise<ExecuteCommandResult>;
77
133
  /**
78
134
  * Convenience: push `bytes` to an absolute device-local `path` via
79
- * the MCP `file_write` tool. Used by the Resource Resolution Layer
80
- * to land downloaded URL payloads on-device before the VLM sees them.
135
+ * the MCP `file_write` tool.
81
136
  */
82
137
  fileWrite(path: string, bytes: Buffer): Promise<void>;
83
- private request;
138
+ screenshotToFile(path: string, opts?: ScreenshotToFileOptions): Promise<SaveScreenshotResult>;
139
+ startScreenRecord(opts?: StartScreenRecordOptions): Promise<ScreenRecordHandle>;
140
+ stopScreenRecord(id: string, path?: string): Promise<ScreenRecordResult>;
141
+ swipeDirection(direction: "up" | "down" | "left" | "right", opts?: SwipeDirectionOptions): Promise<void>;
142
+ pressButton(button: string): Promise<void>;
143
+ terminateApp(pkg: string): Promise<void>;
144
+ openUrl(url: string): Promise<void>;
145
+ listApps(opts?: ListAppsOptions): Promise<AppInfo[]>;
146
+ listCrashes(): Promise<CrashSummary[]>;
147
+ getCrash(id: string): Promise<string>;
148
+ uninstallApp(pkg: string): Promise<void>;
149
+ setOrientation(orientation: Orientation): Promise<void>;
150
+ getOrientation(): Promise<Orientation>;
151
+ /**
152
+ * MCP `tools/list` — best-effort wrapper for compatibility probes
153
+ * (bootstrap warns when an old server is missing r3 tools). The
154
+ * underlying SDK call uses `client.listTools()` and fails gracefully
155
+ * on transport errors so the caller can decide to log-and-continue.
156
+ */
157
+ listTools(): Promise<{
158
+ name: string;
159
+ }[]>;
160
+ /**
161
+ * Read the server-advertised version (from MCP `initialize` response).
162
+ * `undefined` when not yet connected. The SDK `getServerVersion()`
163
+ * returns the full `Implementation { name, version }` shape; we only
164
+ * need the version string.
165
+ */
166
+ getServerVersion(): string | undefined;
167
+ /**
168
+ * Submit a unified `Action`. Implemented locally as
169
+ * `mapActionToTool(action)` → `callTool(...)`. Terminal verbs short-circuit
170
+ * with a synthetic `{ ok: true, terminal: true }` envelope so the
171
+ * AgentLoop / ACP handlers can keep treating `act()` as the single dispatch
172
+ * point.
173
+ */
174
+ act(action: Action): Promise<ActResponse>;
175
+ private ensureConnected;
176
+ private openTransport;
177
+ private buildHttpTransport;
178
+ private invoke;
179
+ private withDefaultDevice;
84
180
  }