@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.
- package/dist/adapters/transport-bridge-ws.d.ts +12 -0
- package/dist/adapters/transport-bridge-ws.js +27 -3
- package/dist/adapters/transport-bridge-ws.js.map +1 -1
- package/dist/agent-runtime/core.d.ts +1 -1
- package/dist/agent-runtime/core.js +41 -0
- package/dist/agent-runtime/core.js.map +1 -1
- package/dist/app/session-manager.d.ts +14 -11
- package/dist/app/session-manager.js +8 -9
- package/dist/app/session-manager.js.map +1 -1
- package/dist/bootstrap.js +140 -11
- package/dist/bootstrap.js.map +1 -1
- package/dist/chat.js +11 -1
- package/dist/chat.js.map +1 -1
- package/dist/config/loader.js +3 -0
- package/dist/config/loader.js.map +1 -1
- package/dist/config/schema.d.ts +3 -0
- package/dist/config/schema.js +65 -21
- package/dist/config/schema.js.map +1 -1
- package/dist/fleet/adapters/process/node-process-manager.d.ts +115 -13
- package/dist/fleet/adapters/process/node-process-manager.js +412 -64
- package/dist/fleet/adapters/process/node-process-manager.js.map +1 -1
- package/dist/fleet/adapters/state/port-allocator.d.ts +12 -0
- package/dist/fleet/adapters/state/port-allocator.js +39 -5
- package/dist/fleet/adapters/state/port-allocator.js.map +1 -1
- package/dist/fleet/domain/events.d.ts +23 -1
- package/dist/fleet/domain/fsm.d.ts +13 -1
- package/dist/fleet/domain/fsm.js +70 -0
- package/dist/fleet/domain/fsm.js.map +1 -1
- package/dist/fleet/supervisor.js +30 -0
- package/dist/fleet/supervisor.js.map +1 -1
- package/dist/health/adb-track-devices.d.ts +103 -0
- package/dist/health/adb-track-devices.js +171 -0
- package/dist/health/adb-track-devices.js.map +1 -0
- package/dist/health/health-reporter.d.ts +67 -0
- package/dist/health/health-reporter.js +123 -0
- package/dist/health/health-reporter.js.map +1 -0
- package/dist/health/index.d.ts +6 -0
- package/dist/health/index.js +4 -0
- package/dist/health/index.js.map +1 -0
- package/dist/health/mcp-health-monitor.d.ts +190 -0
- package/dist/health/mcp-health-monitor.js +267 -0
- package/dist/health/mcp-health-monitor.js.map +1 -0
- package/dist/inbound/cli/main.js +10 -3
- package/dist/inbound/cli/main.js.map +1 -1
- package/dist/inbound/cli/run-command.js +24 -2
- package/dist/inbound/cli/run-command.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp-client/action-mapping.d.ts +45 -0
- package/dist/mcp-client/action-mapping.js +224 -0
- package/dist/mcp-client/action-mapping.js.map +1 -0
- package/dist/mcp-client/autospawn.d.ts +15 -2
- package/dist/mcp-client/autospawn.js +82 -4
- package/dist/mcp-client/autospawn.js.map +1 -1
- package/dist/mcp-client/client.d.ts +134 -38
- package/dist/mcp-client/client.js +394 -87
- package/dist/mcp-client/client.js.map +1 -1
- package/dist/mcp-client/index.d.ts +5 -3
- package/dist/mcp-client/index.js +2 -1
- package/dist/mcp-client/index.js.map +1 -1
- package/dist/mcp-client/inproc.d.ts +2 -2
- package/dist/mcp-client/inproc.js.map +1 -1
- package/dist/mcp-client/runtime.d.ts +124 -21
- package/dist/mcp-client/runtime.js +18 -7
- package/dist/mcp-client/runtime.js.map +1 -1
- package/dist/messaging/token-provider.d.ts +15 -14
- package/dist/messaging/token-provider.js +16 -16
- package/dist/messaging/token-provider.js.map +1 -1
- package/dist/model/adapters/autoglm.js +44 -45
- package/dist/model/adapters/autoglm.js.map +1 -1
- package/dist/model/adapters/guiowl.js +3 -2
- package/dist/model/adapters/guiowl.js.map +1 -1
- package/dist/model/adapters/maiui.js +80 -53
- package/dist/model/adapters/maiui.js.map +1 -1
- package/dist/model/adapters/qwenvl.js +147 -51
- package/dist/model/adapters/qwenvl.js.map +1 -1
- package/dist/model/adapters/tool-call.js +13 -3
- package/dist/model/adapters/tool-call.js.map +1 -1
- package/dist/model/adapters/uitars.js +80 -84
- package/dist/model/adapters/uitars.js.map +1 -1
- package/dist/plugins/acp/index.d.ts +35 -0
- package/dist/plugins/acp/index.js +121 -0
- package/dist/plugins/acp/index.js.map +1 -1
- package/dist/plugins/message-bus/busy-reply.d.ts +5 -5
- package/dist/plugins/message-bus/busy-reply.js +30 -9
- package/dist/plugins/message-bus/busy-reply.js.map +1 -1
- package/dist/plugins/message-bus/cancel.d.ts +5 -11
- package/dist/plugins/message-bus/cancel.js +8 -14
- package/dist/plugins/message-bus/cancel.js.map +1 -1
- package/dist/plugins/message-bus/inbound.d.ts +18 -25
- package/dist/plugins/message-bus/inbound.js +23 -55
- package/dist/plugins/message-bus/inbound.js.map +1 -1
- package/dist/plugins/message-bus/index.d.ts +25 -44
- package/dist/plugins/message-bus/index.js +70 -111
- package/dist/plugins/message-bus/index.js.map +1 -1
- package/dist/plugins/message-bus/ms-channel-notifier.d.ts +24 -37
- package/dist/plugins/message-bus/ms-channel-notifier.js +39 -59
- package/dist/plugins/message-bus/ms-channel-notifier.js.map +1 -1
- package/dist/ports/transport.d.ts +11 -0
- package/dist/resources/parsers.js +17 -0
- package/dist/resources/parsers.js.map +1 -1
- package/package.json +4 -3
package/dist/index.d.ts
CHANGED
|
@@ -44,7 +44,7 @@ export type { AgentHost, AgentEvent, SubmittedTask } from "./ports/agent-host.js
|
|
|
44
44
|
export type { AgentPlugin, PluginContext } from "./ports/plugin.js";
|
|
45
45
|
export { DeviceError, VlmError, AcpError } from "./core/errors.js";
|
|
46
46
|
export { McpClient, resolveDefaultMcpUrl } from "./mcp-client/index.js";
|
|
47
|
-
export type { McpClientOptions,
|
|
47
|
+
export type { ActResponse, CallToolOutput, McpClientOptions, } from "./mcp-client/index.js";
|
|
48
48
|
export { AgentLoop, AgentRunner, HierarchicalReflector, LLMPlanner, NoOpPlanner, PlanExecutor, actionsEqual, availableAdapters, clearAdapters, makePrediction, MockAdapter, OpenAIAdapter, parsedToAction, registerAdapter as registerModelAdapter, resolveAdapter as resolveModelAdapter, resolveAdapterSync as resolveModelAdapterSync, UITarsAdapter, } from "./agent-runtime/index.js";
|
|
49
49
|
export type { AdapterDescriptor as ModelAdapterDescriptor, AgentErrorCode, AgentErrorEvent, AgentLoopTerminator, AgentRunHooks as AgentLoopRunHooks, AgentRunOptions as AgentLoopRunOptions, AgentRunResult as AgentLoopRunResult, AgentRunnerOptions, AgentRunnerResult, AgentStepEvent, AgentToolEvent, IModelAdapter, IPlanner, LLMPlannerOptions, MockAdapterOptions, ModelUsage, OpenAIAdapterOptions, Plan, PlanContext, PlanExecutorOptions, PlanExecutorResult, PlanStep, PredictHooks, PredictOptions, Prediction, StepHistory, } from "./agent-runtime/index.js";
|
|
50
50
|
export { StickyPortAllocator, defaultFleetStatePath, } from "./fleet/adapters/state/port-allocator.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAG3D,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAIhD,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAG5G,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAEtE,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAGvD,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEtD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAEhE,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAM3E,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEnE,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAG3D,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAIhD,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAG5G,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AAEtE,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAGvD,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEtD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAEhE,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAM3E,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEnE,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAOxE,OAAO,EACL,SAAS,EACT,WAAW,EACX,qBAAqB,EACrB,UAAU,EACV,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,WAAW,EACX,aAAa,EACb,cAAc,EACd,eAAe,IAAI,oBAAoB,EACvC,cAAc,IAAI,mBAAmB,EACrC,kBAAkB,IAAI,uBAAuB,EAC7C,aAAa,GACd,MAAM,0BAA0B,CAAC;AA8BlC,8EAA8E;AAE9E,OAAO,EACL,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,0CAA0C,CAAC;AAGlD,OAAO,EACL,aAAa,EACb,kBAAkB,GACnB,MAAM,2CAA2C,CAAC;AAGnD,OAAO,EACL,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,qBAAqB,EACrB,cAAc,GACf,MAAM,uCAAuC,CAAC;AAM/C,OAAO,EACL,eAAe,EACf,eAAe,GAChB,MAAM,wCAAwC,CAAC;AAOhD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kDAAkD,CAAC;AAStF,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAGxD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAE7D,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAIpF,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* action-mapping — translate a unified `Action` (`type+target+payload`) into
|
|
3
|
+
* the matching MCP tool name + arguments.
|
|
4
|
+
*
|
|
5
|
+
* Moved from `device-mcp-server/src/server/action-mapping.ts` in 0.4.0 — the
|
|
6
|
+
* server now speaks plain MCP `tools/call` and never sees the high-level
|
|
7
|
+
* `Action` shape, so the mapping is a pure client concern. `device-agent`
|
|
8
|
+
* is the sole consumer.
|
|
9
|
+
*
|
|
10
|
+
* Mirrors the Python reference's `_action_to_call` table.
|
|
11
|
+
*/
|
|
12
|
+
import { type Action, type ActionType, type BackendFamily } from "@beeos-ai/device-common";
|
|
13
|
+
export interface ToolCall {
|
|
14
|
+
toolName: string;
|
|
15
|
+
args: Record<string, unknown>;
|
|
16
|
+
}
|
|
17
|
+
export interface UnsupportedActionResult {
|
|
18
|
+
/** Terminal verbs (`done`, `fail`, `wait`, `call_for_user`) — caller short-circuits. */
|
|
19
|
+
terminal: true;
|
|
20
|
+
type: ActionType;
|
|
21
|
+
}
|
|
22
|
+
export type ActionMappingResult = ToolCall | UnsupportedActionResult;
|
|
23
|
+
/**
|
|
24
|
+
* Translate a unified `Action` into the matching MCP `tools/call` payload.
|
|
25
|
+
*
|
|
26
|
+
* The optional `family` parameter resolves the wire-name fork between
|
|
27
|
+
* mobile and desktop backends:
|
|
28
|
+
*
|
|
29
|
+
* - mobile (`android` / `ios`) backends advertise `tap` / `double_tap`
|
|
30
|
+
* in `MOBILE_TOOLS` but DO NOT carry `click` / `double_click`. The
|
|
31
|
+
* high-level Action vocabulary uses the desktop name `click` as the
|
|
32
|
+
* canonical "press at point" verb (matches OpenAI computer-use), so
|
|
33
|
+
* on mobile we transparently rewrite `click` → `tap` and
|
|
34
|
+
* `double_click` → `double_tap` here. Without this rewrite the
|
|
35
|
+
* server's `BackendRegistry` rejects every tap with
|
|
36
|
+
* `unsupported tool` on Android.
|
|
37
|
+
* - desktop backends keep both names — `click` stays `click`, etc.
|
|
38
|
+
* - mouse-only verbs (`right_click`, `move`) raise
|
|
39
|
+
* `DeviceError(invalid_args)` on mobile so the agent loop sees a
|
|
40
|
+
* clean actionable error instead of a server-side "unsupported tool".
|
|
41
|
+
*
|
|
42
|
+
* `family === undefined` keeps the legacy 1:1 mapping (no rewrite,
|
|
43
|
+
* no early reject) so old call sites and tests don't break.
|
|
44
|
+
*/
|
|
45
|
+
export declare function mapActionToTool(action: Action, family?: BackendFamily): ActionMappingResult;
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* action-mapping — translate a unified `Action` (`type+target+payload`) into
|
|
3
|
+
* the matching MCP tool name + arguments.
|
|
4
|
+
*
|
|
5
|
+
* Moved from `device-mcp-server/src/server/action-mapping.ts` in 0.4.0 — the
|
|
6
|
+
* server now speaks plain MCP `tools/call` and never sees the high-level
|
|
7
|
+
* `Action` shape, so the mapping is a pure client concern. `device-agent`
|
|
8
|
+
* is the sole consumer.
|
|
9
|
+
*
|
|
10
|
+
* Mirrors the Python reference's `_action_to_call` table.
|
|
11
|
+
*/
|
|
12
|
+
import { DeviceError, TERMINAL_ACTIONS, } from "@beeos-ai/device-common";
|
|
13
|
+
/**
|
|
14
|
+
* Translate a unified `Action` into the matching MCP `tools/call` payload.
|
|
15
|
+
*
|
|
16
|
+
* The optional `family` parameter resolves the wire-name fork between
|
|
17
|
+
* mobile and desktop backends:
|
|
18
|
+
*
|
|
19
|
+
* - mobile (`android` / `ios`) backends advertise `tap` / `double_tap`
|
|
20
|
+
* in `MOBILE_TOOLS` but DO NOT carry `click` / `double_click`. The
|
|
21
|
+
* high-level Action vocabulary uses the desktop name `click` as the
|
|
22
|
+
* canonical "press at point" verb (matches OpenAI computer-use), so
|
|
23
|
+
* on mobile we transparently rewrite `click` → `tap` and
|
|
24
|
+
* `double_click` → `double_tap` here. Without this rewrite the
|
|
25
|
+
* server's `BackendRegistry` rejects every tap with
|
|
26
|
+
* `unsupported tool` on Android.
|
|
27
|
+
* - desktop backends keep both names — `click` stays `click`, etc.
|
|
28
|
+
* - mouse-only verbs (`right_click`, `move`) raise
|
|
29
|
+
* `DeviceError(invalid_args)` on mobile so the agent loop sees a
|
|
30
|
+
* clean actionable error instead of a server-side "unsupported tool".
|
|
31
|
+
*
|
|
32
|
+
* `family === undefined` keeps the legacy 1:1 mapping (no rewrite,
|
|
33
|
+
* no early reject) so old call sites and tests don't break.
|
|
34
|
+
*/
|
|
35
|
+
export function mapActionToTool(action, family) {
|
|
36
|
+
if (TERMINAL_ACTIONS.has(action.type) || action.type === "wait") {
|
|
37
|
+
return { terminal: true, type: action.type };
|
|
38
|
+
}
|
|
39
|
+
const target = action.target;
|
|
40
|
+
const payload = action.payload ?? {};
|
|
41
|
+
const isMobile = family === "mobile";
|
|
42
|
+
switch (action.type) {
|
|
43
|
+
case "click":
|
|
44
|
+
case "tap":
|
|
45
|
+
case "double_click":
|
|
46
|
+
case "right_click":
|
|
47
|
+
case "long_press":
|
|
48
|
+
case "move": {
|
|
49
|
+
if (isMobile && (action.type === "right_click" || action.type === "move")) {
|
|
50
|
+
throw new DeviceError(`action '${action.type}' is not supported on mobile backends`, { subtype: "unsupported", retriable: false });
|
|
51
|
+
}
|
|
52
|
+
const xy = pointFromTarget(target);
|
|
53
|
+
const toolName = isMobile && action.type === "click"
|
|
54
|
+
? "tap"
|
|
55
|
+
: isMobile && action.type === "double_click"
|
|
56
|
+
? "double_tap"
|
|
57
|
+
: action.type === "move"
|
|
58
|
+
? "move"
|
|
59
|
+
: action.type;
|
|
60
|
+
return {
|
|
61
|
+
toolName,
|
|
62
|
+
args: {
|
|
63
|
+
...xy,
|
|
64
|
+
...(action.type === "click" && payload.button ? { button: payload.button } : {}),
|
|
65
|
+
...(action.type === "click" && payload.clicks ? { clicks: payload.clicks } : {}),
|
|
66
|
+
...(action.type === "long_press" && payload.durationMs
|
|
67
|
+
? { durationMs: payload.durationMs }
|
|
68
|
+
: {}),
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
case "drag":
|
|
73
|
+
case "swipe": {
|
|
74
|
+
const seg = segmentFromTarget(target);
|
|
75
|
+
return {
|
|
76
|
+
toolName: action.type,
|
|
77
|
+
args: {
|
|
78
|
+
...seg,
|
|
79
|
+
...(payload.durationMs ? { durationMs: payload.durationMs } : {}),
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
case "scroll": {
|
|
84
|
+
const xy = target ? pointFromTarget(target) : { x: 0, y: 0 };
|
|
85
|
+
return {
|
|
86
|
+
toolName: "scroll",
|
|
87
|
+
args: {
|
|
88
|
+
...xy,
|
|
89
|
+
direction: payload.direction ?? "down",
|
|
90
|
+
...(payload.amount ? { amount: payload.amount } : {}),
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
case "type":
|
|
95
|
+
return {
|
|
96
|
+
toolName: "type",
|
|
97
|
+
args: {
|
|
98
|
+
text: typeof payload.text === "string" ? payload.text : "",
|
|
99
|
+
// r3 mobile-mcp parity: forward `submit` so the backend can
|
|
100
|
+
// press Enter at the end of the typed string ("type and submit
|
|
101
|
+
// search" pattern). Only forwarded when explicitly true so the
|
|
102
|
+
// server-side default (no submit) is preserved.
|
|
103
|
+
...(payload.submit === true ? { submit: true } : {}),
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
case "key":
|
|
107
|
+
return {
|
|
108
|
+
toolName: "key",
|
|
109
|
+
args: { key: payload.key ?? payload.keycode ?? "" },
|
|
110
|
+
};
|
|
111
|
+
case "hotkey": {
|
|
112
|
+
const keys = Array.isArray(payload.keys) ? payload.keys : [];
|
|
113
|
+
if (keys.length === 0) {
|
|
114
|
+
// Server-side zod schema requires `min(1)`. Fail fast at the
|
|
115
|
+
// mapping boundary with an actionable subtype so the agent
|
|
116
|
+
// loop's reflector / feedback path categorises this as
|
|
117
|
+
// "the planner emitted bad args" rather than a transport error.
|
|
118
|
+
throw new DeviceError("hotkey requires a non-empty `keys` array", { subtype: "invalid_args", retriable: false });
|
|
119
|
+
}
|
|
120
|
+
return { toolName: "hotkey", args: { keys } };
|
|
121
|
+
}
|
|
122
|
+
case "back":
|
|
123
|
+
return { toolName: "back", args: {} };
|
|
124
|
+
case "home":
|
|
125
|
+
return { toolName: "home", args: {} };
|
|
126
|
+
case "navigate": {
|
|
127
|
+
// r3 mobile-mcp parity: server now exposes `navigate(direction)`
|
|
128
|
+
// with `back | forward | up`. Pre-r3 device-agent always called
|
|
129
|
+
// the `back` tool regardless of `payload.direction`, dropping
|
|
130
|
+
// `forward` / `up` semantics. Keep `back` as the default so old
|
|
131
|
+
// call sites (no direction in payload) continue to work.
|
|
132
|
+
const raw = payload.direction;
|
|
133
|
+
const direction = raw === "back" || raw === "forward" || raw === "up" ? raw : "back";
|
|
134
|
+
return { toolName: "navigate", args: { direction } };
|
|
135
|
+
}
|
|
136
|
+
case "launch_app": {
|
|
137
|
+
const fromTarget = target && (target.kind === "text" || target.kind === "selector")
|
|
138
|
+
? target.value
|
|
139
|
+
: undefined;
|
|
140
|
+
const pkg = fromTarget ??
|
|
141
|
+
payload.pkg ??
|
|
142
|
+
payload.appName ??
|
|
143
|
+
payload.packageOrName ??
|
|
144
|
+
payload.package ??
|
|
145
|
+
"";
|
|
146
|
+
return {
|
|
147
|
+
toolName: "launch_app",
|
|
148
|
+
args: {
|
|
149
|
+
pkg,
|
|
150
|
+
...(payload.activity ? { activity: payload.activity } : {}),
|
|
151
|
+
// r3 parity: BCP-47 locale (`en-US`, `zh-CN`, …). Forwarded
|
|
152
|
+
// when the planner injects a locale — the server validates
|
|
153
|
+
// the character class and rejects shell-injection attempts.
|
|
154
|
+
...(typeof payload.locale === "string" ? { locale: payload.locale } : {}),
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
case "screenshot":
|
|
159
|
+
return {
|
|
160
|
+
toolName: "screenshot",
|
|
161
|
+
args: {
|
|
162
|
+
// r3 parity: optional sizing / quality / format / displayId
|
|
163
|
+
// forwarded straight through. Server enforces zod bounds —
|
|
164
|
+
// we don't second-guess them here.
|
|
165
|
+
...(typeof payload.displayId === "number" ? { displayId: payload.displayId } : {}),
|
|
166
|
+
...(typeof payload.maxEdge === "number" ? { maxEdge: payload.maxEdge } : {}),
|
|
167
|
+
...(typeof payload.quality === "number" ? { quality: payload.quality } : {}),
|
|
168
|
+
...(payload.format === "png" || payload.format === "jpeg"
|
|
169
|
+
? { format: payload.format }
|
|
170
|
+
: {}),
|
|
171
|
+
},
|
|
172
|
+
};
|
|
173
|
+
case "ui_dump":
|
|
174
|
+
return {
|
|
175
|
+
toolName: "ui_dump",
|
|
176
|
+
args: {
|
|
177
|
+
...(payload.query ? { query: payload.query } : {}),
|
|
178
|
+
...(payload.format ? { format: payload.format } : {}),
|
|
179
|
+
},
|
|
180
|
+
};
|
|
181
|
+
case "execute_command":
|
|
182
|
+
case "run_code":
|
|
183
|
+
return {
|
|
184
|
+
toolName: "execute_command",
|
|
185
|
+
args: {
|
|
186
|
+
body: payload.body ?? payload.command ?? "",
|
|
187
|
+
...(payload.timeoutS ? { timeoutS: payload.timeoutS } : {}),
|
|
188
|
+
...(payload.cwd ? { cwd: payload.cwd } : {}),
|
|
189
|
+
},
|
|
190
|
+
};
|
|
191
|
+
case "file_read": {
|
|
192
|
+
const path = payload.path ??
|
|
193
|
+
(target && (target.kind === "text" || target.kind === "selector")
|
|
194
|
+
? target.value
|
|
195
|
+
: "");
|
|
196
|
+
return { toolName: "file_read", args: { path } };
|
|
197
|
+
}
|
|
198
|
+
case "file_write": {
|
|
199
|
+
const path = payload.path ??
|
|
200
|
+
(target && (target.kind === "text" || target.kind === "selector")
|
|
201
|
+
? target.value
|
|
202
|
+
: "");
|
|
203
|
+
return {
|
|
204
|
+
toolName: "file_write",
|
|
205
|
+
args: { path, contentB64: payload.contentB64 ?? "" },
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
default:
|
|
209
|
+
throw new Error(`unsupported action type: ${String(action.type)}`);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
function pointFromTarget(target) {
|
|
213
|
+
if (target && target.kind === "point") {
|
|
214
|
+
return { x: target.x, y: target.y };
|
|
215
|
+
}
|
|
216
|
+
throw new TypeError("action.target must be {kind:'point', x, y} for this action type");
|
|
217
|
+
}
|
|
218
|
+
function segmentFromTarget(target) {
|
|
219
|
+
if (target && target.kind === "box") {
|
|
220
|
+
return { x1: target.x1, y1: target.y1, x2: target.x2, y2: target.y2 };
|
|
221
|
+
}
|
|
222
|
+
throw new TypeError("action.target must be {kind:'box', x1, y1, x2, y2} for this action type");
|
|
223
|
+
}
|
|
224
|
+
//# sourceMappingURL=action-mapping.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action-mapping.js","sourceRoot":"","sources":["../../src/mcp-client/action-mapping.ts"],"names":[],"mappings":"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"}
|
|
@@ -32,8 +32,6 @@ import type { Logger } from "../logger/index.js";
|
|
|
32
32
|
export interface AutospawnOptions {
|
|
33
33
|
/** Backend family to forward to the MCP server's `--backend` flag. */
|
|
34
34
|
backend: "android" | "desktop" | "ios" | "windows" | "macos";
|
|
35
|
-
/** ADB serial — forwarded only for the `android` backend. */
|
|
36
|
-
adbSerial?: string;
|
|
37
35
|
/** Bind host for the spawned server (default `127.0.0.1`). */
|
|
38
36
|
host?: string;
|
|
39
37
|
/**
|
|
@@ -50,6 +48,21 @@ export interface AutospawnOptions {
|
|
|
50
48
|
logger?: Logger;
|
|
51
49
|
/** Time we wait for SIGTERM before escalating to SIGKILL. */
|
|
52
50
|
gracePeriodMs?: number;
|
|
51
|
+
/**
|
|
52
|
+
* Maximum time to wait for the spawned server's `/healthz` endpoint
|
|
53
|
+
* to respond 200 OK (or for the child process to crash) before
|
|
54
|
+
* `autospawnMcpServer` rejects. Defaults to 5_000ms — long enough
|
|
55
|
+
* for a Node ESM cold start, short enough that a misconfigured
|
|
56
|
+
* binary fails fast instead of stalling boot for 15s on
|
|
57
|
+
* `waitUntilReady`. Set to `0` to skip the probe entirely (legacy
|
|
58
|
+
* behaviour).
|
|
59
|
+
*/
|
|
60
|
+
healthTimeoutMs?: number;
|
|
61
|
+
/**
|
|
62
|
+
* Test seam: override the HTTP probe function. Production callers
|
|
63
|
+
* should never pass this — the default uses the global `fetch`.
|
|
64
|
+
*/
|
|
65
|
+
healthProbe?: (url: string) => Promise<boolean>;
|
|
53
66
|
}
|
|
54
67
|
export interface AutospawnHandle {
|
|
55
68
|
/** `http://host:port` — pass to `McpClient` as its `baseUrl`. */
|
|
@@ -86,9 +86,10 @@ export async function autospawnMcpServer(opts) {
|
|
|
86
86
|
"--host", host,
|
|
87
87
|
"--port", String(port),
|
|
88
88
|
];
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
89
|
+
// 0.4.0: device-mcp-server is now a singleton multi-device process.
|
|
90
|
+
// The `--adb-serial` per-device pin flag is gone — callers identify the
|
|
91
|
+
// target device on each tool call via the `device` argument, which the
|
|
92
|
+
// McpClient injects automatically from its `defaultDevice` option.
|
|
92
93
|
if (opts.extraArgs?.length)
|
|
93
94
|
args.push(...opts.extraArgs);
|
|
94
95
|
const log = opts.logger;
|
|
@@ -103,7 +104,6 @@ export async function autospawnMcpServer(opts) {
|
|
|
103
104
|
DEVICEAGENT_BACKEND: opts.backend,
|
|
104
105
|
MCP_HOST: host,
|
|
105
106
|
MCP_PORT: String(port),
|
|
106
|
-
...(opts.adbSerial ? { ANDROID_SERIAL: opts.adbSerial } : {}),
|
|
107
107
|
},
|
|
108
108
|
});
|
|
109
109
|
pipeLines(child.stdout, (line) => log?.info({ src: "mcp.stdout" }, line));
|
|
@@ -112,6 +112,59 @@ export async function autospawnMcpServer(opts) {
|
|
|
112
112
|
child.once("exit", (code, signal) => resolve({ code, signal }));
|
|
113
113
|
});
|
|
114
114
|
exited.then((r) => log?.warn({ ...r }, "mcp: autospawned child exited")).catch(() => undefined);
|
|
115
|
+
// Active health-check: poll `GET /mcp` until the server starts answering
|
|
116
|
+
// (any HTTP response — including the standard 405 Method Not Allowed
|
|
117
|
+
// that the stateless Streamable HTTP transport returns for GET — proves
|
|
118
|
+
// the listener is up and dependencies have resolved) OR the child dies
|
|
119
|
+
// OR `healthTimeoutMs` elapses.
|
|
120
|
+
//
|
|
121
|
+
// `/healthz` was removed from `device-mcp-server` in 0.4.0 (the only
|
|
122
|
+
// route is `POST /mcp`), so we deliberately probe `GET /mcp` instead
|
|
123
|
+
// and treat 4xx/5xx as "alive" — we just need a TCP-listening server
|
|
124
|
+
// to prove the spawn succeeded. The full MCP `initialize` handshake
|
|
125
|
+
// still runs downstream in `McpClient.waitUntilReady`.
|
|
126
|
+
const healthTimeoutMs = opts.healthTimeoutMs === undefined ? 5_000 : opts.healthTimeoutMs;
|
|
127
|
+
if (healthTimeoutMs > 0) {
|
|
128
|
+
const probe = opts.healthProbe ?? defaultHealthProbe;
|
|
129
|
+
const healthUrl = `http://${host}:${port}/mcp`;
|
|
130
|
+
const deadline = Date.now() + healthTimeoutMs;
|
|
131
|
+
let ok = false;
|
|
132
|
+
let earlyExit;
|
|
133
|
+
while (Date.now() < deadline) {
|
|
134
|
+
if (child.exitCode !== null || child.signalCode !== null) {
|
|
135
|
+
earlyExit = {
|
|
136
|
+
code: child.exitCode,
|
|
137
|
+
signal: child.signalCode,
|
|
138
|
+
};
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
try {
|
|
142
|
+
if (await probe(healthUrl)) {
|
|
143
|
+
ok = true;
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
/* keep polling */
|
|
149
|
+
}
|
|
150
|
+
await sleep(150);
|
|
151
|
+
}
|
|
152
|
+
if (!ok) {
|
|
153
|
+
try {
|
|
154
|
+
child.kill("SIGKILL");
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
/* already gone */
|
|
158
|
+
}
|
|
159
|
+
if (earlyExit) {
|
|
160
|
+
log?.error({ ...earlyExit, healthUrl }, "mcp: autospawned child exited before becoming healthy");
|
|
161
|
+
throw new Error(`autospawned device-mcp-server exited (code=${earlyExit.code}, signal=${earlyExit.signal}) before becoming healthy`);
|
|
162
|
+
}
|
|
163
|
+
log?.error({ healthUrl, healthTimeoutMs }, "mcp: autospawned child did not become healthy in time");
|
|
164
|
+
throw new Error(`autospawned device-mcp-server at ${healthUrl} did not become healthy within ${healthTimeoutMs}ms`);
|
|
165
|
+
}
|
|
166
|
+
log?.info({ healthUrl }, "mcp: autospawn health probe OK");
|
|
167
|
+
}
|
|
115
168
|
const grace = opts.gracePeriodMs ?? 3_000;
|
|
116
169
|
let stopped = false;
|
|
117
170
|
const stop = async () => {
|
|
@@ -147,6 +200,31 @@ export async function autospawnMcpServer(opts) {
|
|
|
147
200
|
stop,
|
|
148
201
|
};
|
|
149
202
|
}
|
|
203
|
+
/** Sleep helper for the health-check polling loop. */
|
|
204
|
+
function sleep(ms) {
|
|
205
|
+
return new Promise((res) => setTimeout(res, ms));
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Default health probe — Node 18+ global `fetch`. ANY HTTP status (incl.
|
|
209
|
+
* the 405 the SDK transport returns for GET /mcp) counts as "alive": the
|
|
210
|
+
* listener is up, dependencies resolved, the dispatcher can answer.
|
|
211
|
+
* Connection errors / timeouts return `false` so the caller polls again.
|
|
212
|
+
*/
|
|
213
|
+
async function defaultHealthProbe(url) {
|
|
214
|
+
const ctrl = new AbortController();
|
|
215
|
+
const t = setTimeout(() => ctrl.abort(), 1_500);
|
|
216
|
+
try {
|
|
217
|
+
const r = await fetch(url, { method: "GET", signal: ctrl.signal });
|
|
218
|
+
// Anything that came back through the HTTP stack is good enough.
|
|
219
|
+
return r.status >= 100 && r.status < 600;
|
|
220
|
+
}
|
|
221
|
+
catch {
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
finally {
|
|
225
|
+
clearTimeout(t);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
150
228
|
/** Pipe a readable stream of bytes into a per-line callback. */
|
|
151
229
|
function pipeLines(stream, emit) {
|
|
152
230
|
if (!stream)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"autospawn.js","sourceRoot":"","sources":["../../src/mcp-client/autospawn.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAAE,KAAK,EAAqB,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"autospawn.js","sourceRoot":"","sources":["../../src/mcp-client/autospawn.ts"],"names":[],"mappings":"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"}
|