deepadb 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (247) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +631 -0
  3. package/build/bridge/adb-bridge.d.ts +65 -0
  4. package/build/bridge/adb-bridge.d.ts.map +1 -0
  5. package/build/bridge/adb-bridge.js +164 -0
  6. package/build/bridge/adb-bridge.js.map +1 -0
  7. package/build/bridge/device-manager.d.ts +41 -0
  8. package/build/bridge/device-manager.d.ts.map +1 -0
  9. package/build/bridge/device-manager.js +109 -0
  10. package/build/bridge/device-manager.js.map +1 -0
  11. package/build/bridge/local-bridge.d.ts +92 -0
  12. package/build/bridge/local-bridge.d.ts.map +1 -0
  13. package/build/bridge/local-bridge.js +345 -0
  14. package/build/bridge/local-bridge.js.map +1 -0
  15. package/build/config/config.d.ts +39 -0
  16. package/build/config/config.d.ts.map +1 -0
  17. package/build/config/config.js +84 -0
  18. package/build/config/config.js.map +1 -0
  19. package/build/graphql-api.d.ts +36 -0
  20. package/build/graphql-api.d.ts.map +1 -0
  21. package/build/graphql-api.js +296 -0
  22. package/build/graphql-api.js.map +1 -0
  23. package/build/http-transport.d.ts +26 -0
  24. package/build/http-transport.d.ts.map +1 -0
  25. package/build/http-transport.js +105 -0
  26. package/build/http-transport.js.map +1 -0
  27. package/build/index.d.ts +14 -0
  28. package/build/index.d.ts.map +1 -0
  29. package/build/index.js +66 -0
  30. package/build/index.js.map +1 -0
  31. package/build/middleware/chipset.d.ts +29 -0
  32. package/build/middleware/chipset.d.ts.map +1 -0
  33. package/build/middleware/chipset.js +123 -0
  34. package/build/middleware/chipset.js.map +1 -0
  35. package/build/middleware/cleanup.d.ts +24 -0
  36. package/build/middleware/cleanup.d.ts.map +1 -0
  37. package/build/middleware/cleanup.js +53 -0
  38. package/build/middleware/cleanup.js.map +1 -0
  39. package/build/middleware/fetch-utils.d.ts +19 -0
  40. package/build/middleware/fetch-utils.d.ts.map +1 -0
  41. package/build/middleware/fetch-utils.js +64 -0
  42. package/build/middleware/fetch-utils.js.map +1 -0
  43. package/build/middleware/logger.d.ts +17 -0
  44. package/build/middleware/logger.d.ts.map +1 -0
  45. package/build/middleware/logger.js +38 -0
  46. package/build/middleware/logger.js.map +1 -0
  47. package/build/middleware/output-processor.d.ts +57 -0
  48. package/build/middleware/output-processor.d.ts.map +1 -0
  49. package/build/middleware/output-processor.js +162 -0
  50. package/build/middleware/output-processor.js.map +1 -0
  51. package/build/middleware/sanitize.d.ts +30 -0
  52. package/build/middleware/sanitize.d.ts.map +1 -0
  53. package/build/middleware/sanitize.js +46 -0
  54. package/build/middleware/sanitize.js.map +1 -0
  55. package/build/middleware/security.d.ts +52 -0
  56. package/build/middleware/security.d.ts.map +1 -0
  57. package/build/middleware/security.js +123 -0
  58. package/build/middleware/security.js.map +1 -0
  59. package/build/middleware/ui-dump.d.ts +23 -0
  60. package/build/middleware/ui-dump.d.ts.map +1 -0
  61. package/build/middleware/ui-dump.js +59 -0
  62. package/build/middleware/ui-dump.js.map +1 -0
  63. package/build/server.d.ts +18 -0
  64. package/build/server.d.ts.map +1 -0
  65. package/build/server.js +133 -0
  66. package/build/server.js.map +1 -0
  67. package/build/tool-context.d.ts +22 -0
  68. package/build/tool-context.d.ts.map +1 -0
  69. package/build/tool-context.js +9 -0
  70. package/build/tool-context.js.map +1 -0
  71. package/build/tools/accessibility.d.ts +10 -0
  72. package/build/tools/accessibility.d.ts.map +1 -0
  73. package/build/tools/accessibility.js +259 -0
  74. package/build/tools/accessibility.js.map +1 -0
  75. package/build/tools/at-commands.d.ts +20 -0
  76. package/build/tools/at-commands.d.ts.map +1 -0
  77. package/build/tools/at-commands.js +378 -0
  78. package/build/tools/at-commands.js.map +1 -0
  79. package/build/tools/baseband.d.ts +15 -0
  80. package/build/tools/baseband.d.ts.map +1 -0
  81. package/build/tools/baseband.js +323 -0
  82. package/build/tools/baseband.js.map +1 -0
  83. package/build/tools/build.d.ts +6 -0
  84. package/build/tools/build.d.ts.map +1 -0
  85. package/build/tools/build.js +80 -0
  86. package/build/tools/build.js.map +1 -0
  87. package/build/tools/ci.d.ts +9 -0
  88. package/build/tools/ci.d.ts.map +1 -0
  89. package/build/tools/ci.js +163 -0
  90. package/build/tools/ci.js.map +1 -0
  91. package/build/tools/control.d.ts +10 -0
  92. package/build/tools/control.d.ts.map +1 -0
  93. package/build/tools/control.js +197 -0
  94. package/build/tools/control.js.map +1 -0
  95. package/build/tools/device-farm.d.ts +10 -0
  96. package/build/tools/device-farm.d.ts.map +1 -0
  97. package/build/tools/device-farm.js +140 -0
  98. package/build/tools/device-farm.js.map +1 -0
  99. package/build/tools/device-profiles.d.ts +16 -0
  100. package/build/tools/device-profiles.d.ts.map +1 -0
  101. package/build/tools/device-profiles.js +272 -0
  102. package/build/tools/device-profiles.js.map +1 -0
  103. package/build/tools/device.d.ts +6 -0
  104. package/build/tools/device.d.ts.map +1 -0
  105. package/build/tools/device.js +72 -0
  106. package/build/tools/device.js.map +1 -0
  107. package/build/tools/diagnostics.d.ts +7 -0
  108. package/build/tools/diagnostics.d.ts.map +1 -0
  109. package/build/tools/diagnostics.js +153 -0
  110. package/build/tools/diagnostics.js.map +1 -0
  111. package/build/tools/emulator.d.ts +9 -0
  112. package/build/tools/emulator.d.ts.map +1 -0
  113. package/build/tools/emulator.js +223 -0
  114. package/build/tools/emulator.js.map +1 -0
  115. package/build/tools/files.d.ts +6 -0
  116. package/build/tools/files.d.ts.map +1 -0
  117. package/build/tools/files.js +78 -0
  118. package/build/tools/files.js.map +1 -0
  119. package/build/tools/firmware-analysis.d.ts +24 -0
  120. package/build/tools/firmware-analysis.d.ts.map +1 -0
  121. package/build/tools/firmware-analysis.js +623 -0
  122. package/build/tools/firmware-analysis.js.map +1 -0
  123. package/build/tools/forwarding.d.ts +7 -0
  124. package/build/tools/forwarding.d.ts.map +1 -0
  125. package/build/tools/forwarding.js +64 -0
  126. package/build/tools/forwarding.js.map +1 -0
  127. package/build/tools/health.d.ts +7 -0
  128. package/build/tools/health.d.ts.map +1 -0
  129. package/build/tools/health.js +112 -0
  130. package/build/tools/health.js.map +1 -0
  131. package/build/tools/logcat-watch.d.ts +11 -0
  132. package/build/tools/logcat-watch.d.ts.map +1 -0
  133. package/build/tools/logcat-watch.js +209 -0
  134. package/build/tools/logcat-watch.js.map +1 -0
  135. package/build/tools/logs.d.ts +6 -0
  136. package/build/tools/logs.d.ts.map +1 -0
  137. package/build/tools/logs.js +83 -0
  138. package/build/tools/logs.js.map +1 -0
  139. package/build/tools/mirroring.d.ts +14 -0
  140. package/build/tools/mirroring.d.ts.map +1 -0
  141. package/build/tools/mirroring.js +243 -0
  142. package/build/tools/mirroring.js.map +1 -0
  143. package/build/tools/multi-device.d.ts +9 -0
  144. package/build/tools/multi-device.d.ts.map +1 -0
  145. package/build/tools/multi-device.js +138 -0
  146. package/build/tools/multi-device.js.map +1 -0
  147. package/build/tools/network-capture.d.ts +10 -0
  148. package/build/tools/network-capture.d.ts.map +1 -0
  149. package/build/tools/network-capture.js +143 -0
  150. package/build/tools/network-capture.js.map +1 -0
  151. package/build/tools/network-discovery.d.ts +21 -0
  152. package/build/tools/network-discovery.d.ts.map +1 -0
  153. package/build/tools/network-discovery.js +284 -0
  154. package/build/tools/network-discovery.js.map +1 -0
  155. package/build/tools/ota-monitor.d.ts +16 -0
  156. package/build/tools/ota-monitor.d.ts.map +1 -0
  157. package/build/tools/ota-monitor.js +211 -0
  158. package/build/tools/ota-monitor.js.map +1 -0
  159. package/build/tools/packages.d.ts +6 -0
  160. package/build/tools/packages.d.ts.map +1 -0
  161. package/build/tools/packages.js +237 -0
  162. package/build/tools/packages.js.map +1 -0
  163. package/build/tools/plugins.d.ts +22 -0
  164. package/build/tools/plugins.d.ts.map +1 -0
  165. package/build/tools/plugins.js +118 -0
  166. package/build/tools/plugins.js.map +1 -0
  167. package/build/tools/prompts.d.ts +9 -0
  168. package/build/tools/prompts.d.ts.map +1 -0
  169. package/build/tools/prompts.js +94 -0
  170. package/build/tools/prompts.js.map +1 -0
  171. package/build/tools/qemu.d.ts +18 -0
  172. package/build/tools/qemu.d.ts.map +1 -0
  173. package/build/tools/qemu.js +791 -0
  174. package/build/tools/qemu.js.map +1 -0
  175. package/build/tools/registry.d.ts +13 -0
  176. package/build/tools/registry.d.ts.map +1 -0
  177. package/build/tools/registry.js +221 -0
  178. package/build/tools/registry.js.map +1 -0
  179. package/build/tools/regression.d.ts +10 -0
  180. package/build/tools/regression.d.ts.map +1 -0
  181. package/build/tools/regression.js +215 -0
  182. package/build/tools/regression.js.map +1 -0
  183. package/build/tools/resources.d.ts +10 -0
  184. package/build/tools/resources.d.ts.map +1 -0
  185. package/build/tools/resources.js +77 -0
  186. package/build/tools/resources.js.map +1 -0
  187. package/build/tools/ril-intercept.d.ts +24 -0
  188. package/build/tools/ril-intercept.d.ts.map +1 -0
  189. package/build/tools/ril-intercept.js +273 -0
  190. package/build/tools/ril-intercept.js.map +1 -0
  191. package/build/tools/screen-record.d.ts +9 -0
  192. package/build/tools/screen-record.d.ts.map +1 -0
  193. package/build/tools/screen-record.js +95 -0
  194. package/build/tools/screen-record.js.map +1 -0
  195. package/build/tools/screenshot-diff.d.ts +13 -0
  196. package/build/tools/screenshot-diff.d.ts.map +1 -0
  197. package/build/tools/screenshot-diff.js +370 -0
  198. package/build/tools/screenshot-diff.js.map +1 -0
  199. package/build/tools/selinux-audit.d.ts +17 -0
  200. package/build/tools/selinux-audit.d.ts.map +1 -0
  201. package/build/tools/selinux-audit.js +301 -0
  202. package/build/tools/selinux-audit.js.map +1 -0
  203. package/build/tools/shell.d.ts +6 -0
  204. package/build/tools/shell.d.ts.map +1 -0
  205. package/build/tools/shell.js +63 -0
  206. package/build/tools/shell.js.map +1 -0
  207. package/build/tools/snapshot.d.ts +9 -0
  208. package/build/tools/snapshot.d.ts.map +1 -0
  209. package/build/tools/snapshot.js +192 -0
  210. package/build/tools/snapshot.js.map +1 -0
  211. package/build/tools/split-apk.d.ts +13 -0
  212. package/build/tools/split-apk.d.ts.map +1 -0
  213. package/build/tools/split-apk.js +229 -0
  214. package/build/tools/split-apk.js.map +1 -0
  215. package/build/tools/test-gen.d.ts +14 -0
  216. package/build/tools/test-gen.d.ts.map +1 -0
  217. package/build/tools/test-gen.js +252 -0
  218. package/build/tools/test-gen.js.map +1 -0
  219. package/build/tools/testing.d.ts +9 -0
  220. package/build/tools/testing.d.ts.map +1 -0
  221. package/build/tools/testing.js +144 -0
  222. package/build/tools/testing.js.map +1 -0
  223. package/build/tools/thermal-power.d.ts +19 -0
  224. package/build/tools/thermal-power.d.ts.map +1 -0
  225. package/build/tools/thermal-power.js +330 -0
  226. package/build/tools/thermal-power.js.map +1 -0
  227. package/build/tools/ui.d.ts +6 -0
  228. package/build/tools/ui.d.ts.map +1 -0
  229. package/build/tools/ui.js +266 -0
  230. package/build/tools/ui.js.map +1 -0
  231. package/build/tools/wireless.d.ts +7 -0
  232. package/build/tools/wireless.d.ts.map +1 -0
  233. package/build/tools/wireless.js +78 -0
  234. package/build/tools/wireless.js.map +1 -0
  235. package/build/tools/workflow-market.d.ts +17 -0
  236. package/build/tools/workflow-market.d.ts.map +1 -0
  237. package/build/tools/workflow-market.js +237 -0
  238. package/build/tools/workflow-market.js.map +1 -0
  239. package/build/tools/workflow.d.ts +32 -0
  240. package/build/tools/workflow.d.ts.map +1 -0
  241. package/build/tools/workflow.js +374 -0
  242. package/build/tools/workflow.js.map +1 -0
  243. package/build/ws-transport.d.ts +30 -0
  244. package/build/ws-transport.d.ts.map +1 -0
  245. package/build/ws-transport.js +133 -0
  246. package/build/ws-transport.js.map +1 -0
  247. package/package.json +37 -0
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Device Mirroring Tools — Live screen mirroring via scrcpy.
3
+ *
4
+ * Provides start/stop control over scrcpy mirroring sessions.
5
+ * Scrcpy must be installed separately and available on PATH.
6
+ * Supports headless (no-display) mode for recording-only workflows,
7
+ * windowed mode for visual feedback, and configurable bitrate/resolution.
8
+ *
9
+ * Multi-device: sessions are tracked per device serial, allowing
10
+ * simultaneous mirroring of multiple connected devices.
11
+ */
12
+ import { ToolContext } from "../tool-context.js";
13
+ export declare function registerMirroringTools(ctx: ToolContext): void;
14
+ //# sourceMappingURL=mirroring.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mirroring.d.ts","sourceRoot":"","sources":["../../src/tools/mirroring.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAgEjD,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAmM7D"}
@@ -0,0 +1,243 @@
1
+ /**
2
+ * Device Mirroring Tools — Live screen mirroring via scrcpy.
3
+ *
4
+ * Provides start/stop control over scrcpy mirroring sessions.
5
+ * Scrcpy must be installed separately and available on PATH.
6
+ * Supports headless (no-display) mode for recording-only workflows,
7
+ * windowed mode for visual feedback, and configurable bitrate/resolution.
8
+ *
9
+ * Multi-device: sessions are tracked per device serial, allowing
10
+ * simultaneous mirroring of multiple connected devices.
11
+ */
12
+ import { z } from "zod";
13
+ import { spawn, execFile } from "child_process";
14
+ import { platform } from "os";
15
+ import { existsSync } from "fs";
16
+ import { OutputProcessor } from "../middleware/output-processor.js";
17
+ import { registerCleanup } from "../middleware/cleanup.js";
18
+ /** Active mirror sessions by device serial. */
19
+ const sessions = new Map();
20
+ /** Locate scrcpy binary. */
21
+ function findScrcpy() {
22
+ const isWindows = platform() === "win32";
23
+ const binary = isWindows ? "scrcpy.exe" : "scrcpy";
24
+ // Check common install locations
25
+ const candidates = [];
26
+ if (isWindows) {
27
+ const localAppData = process.env.LOCALAPPDATA ?? "";
28
+ if (localAppData) {
29
+ candidates.push(`${localAppData}\\scrcpy\\${binary}`);
30
+ }
31
+ candidates.push(`C:\\scrcpy\\${binary}`);
32
+ const programFiles = process.env.ProgramFiles ?? "C:\\Program Files";
33
+ candidates.push(`${programFiles}\\scrcpy\\${binary}`);
34
+ }
35
+ else {
36
+ candidates.push("/usr/local/bin/scrcpy");
37
+ candidates.push("/usr/bin/scrcpy");
38
+ }
39
+ for (const path of candidates) {
40
+ if (existsSync(path))
41
+ return path;
42
+ }
43
+ // Fall back to PATH
44
+ return binary;
45
+ }
46
+ function checkScrcpyVersion(scrcpyPath) {
47
+ return new Promise((resolve) => {
48
+ execFile(scrcpyPath, ["--version"], { timeout: 5000, windowsHide: true }, (error, stdout) => {
49
+ if (error) {
50
+ resolve(null);
51
+ return;
52
+ }
53
+ resolve(stdout?.toString().trim() ?? null);
54
+ });
55
+ });
56
+ }
57
+ // Register cleanup via shared registry
58
+ function ensureCleanupRegistered() {
59
+ registerCleanup("mirroring", () => {
60
+ for (const [, session] of sessions) {
61
+ try {
62
+ session.process.kill();
63
+ }
64
+ catch { /* ignore */ }
65
+ }
66
+ sessions.clear();
67
+ });
68
+ }
69
+ export function registerMirroringTools(ctx) {
70
+ ensureCleanupRegistered();
71
+ ctx.server.tool("adb_mirror_start", "Start live screen mirroring for a device using scrcpy. Requires scrcpy installed and on PATH. Supports windowed (visual) and headless (no display) modes. One session per device.", {
72
+ device: z.string().optional().describe("Device serial"),
73
+ headless: z.boolean().optional().default(false).describe("No-display mode — useful with recording. Omits the scrcpy window."),
74
+ maxFps: z.number().min(1).max(120).optional().default(30).describe("Maximum frame rate (1-120, default 30)"),
75
+ bitrate: z.string().optional().default("4M").describe("Video bitrate (e.g., '4M', '8M', '2M')"),
76
+ maxSize: z.number().min(0).max(4096).optional().default(0).describe("Max dimension in pixels (0 = no limit, max 4096)"),
77
+ record: z.string().optional().describe("Record to a local file path (e.g., 'mirror.mp4')"),
78
+ stayAwake: z.boolean().optional().default(true).describe("Keep device awake while mirroring"),
79
+ turnScreenOff: z.boolean().optional().default(false).describe("Turn device screen off during mirroring (saves battery)"),
80
+ }, async ({ device, headless, maxFps, bitrate, maxSize, record, stayAwake, turnScreenOff }) => {
81
+ try {
82
+ const resolved = await ctx.deviceManager.resolveDevice(device);
83
+ const serial = resolved.serial;
84
+ if (sessions.has(serial)) {
85
+ return {
86
+ content: [{ type: "text", text: `Mirror session already active for ${serial}. Stop it first with adb_mirror_stop.` }],
87
+ isError: true,
88
+ };
89
+ }
90
+ const scrcpyPath = findScrcpy();
91
+ if (!scrcpyPath) {
92
+ return {
93
+ content: [{ type: "text", text: "scrcpy not found. Install from: https://github.com/Genymobile/scrcpy\nOn Windows: scoop install scrcpy, or download the release ZIP.\nOn Linux: apt install scrcpy or snap install scrcpy." }],
94
+ isError: true,
95
+ };
96
+ }
97
+ // Verify scrcpy works
98
+ const version = await checkScrcpyVersion(scrcpyPath);
99
+ if (!version) {
100
+ return {
101
+ content: [{ type: "text", text: `scrcpy found at ${scrcpyPath} but failed to run. Check installation.` }],
102
+ isError: true,
103
+ };
104
+ }
105
+ // Build scrcpy args
106
+ const args = ["-s", serial];
107
+ if (headless)
108
+ args.push("--no-display");
109
+ if (maxFps > 0)
110
+ args.push("--max-fps", String(maxFps));
111
+ if (bitrate)
112
+ args.push("--video-bit-rate", bitrate);
113
+ if (maxSize > 0)
114
+ args.push("--max-size", String(maxSize));
115
+ if (record)
116
+ args.push("--record", record);
117
+ if (stayAwake)
118
+ args.push("--stay-awake");
119
+ if (turnScreenOff)
120
+ args.push("--turn-screen-off");
121
+ const proc = spawn(scrcpyPath, args, {
122
+ windowsHide: false, // scrcpy needs a window unless headless
123
+ stdio: ["ignore", "pipe", "pipe"],
124
+ detached: false,
125
+ });
126
+ const session = {
127
+ process: proc,
128
+ device: serial,
129
+ startedAt: Date.now(),
130
+ options: { headless, maxFps, bitrate, maxSize },
131
+ };
132
+ let stderrOutput = "";
133
+ proc.stderr?.on("data", (chunk) => {
134
+ stderrOutput += chunk.toString();
135
+ });
136
+ proc.on("error", (err) => {
137
+ ctx.logger.error(`[mirror:${serial}] Spawn error: ${err.message}`);
138
+ sessions.delete(serial);
139
+ });
140
+ proc.on("exit", (code) => {
141
+ ctx.logger.info(`[mirror:${serial}] scrcpy exited (code: ${code})`);
142
+ sessions.delete(serial);
143
+ });
144
+ // Brief wait to check for immediate failure
145
+ await new Promise((r) => setTimeout(r, 2000));
146
+ if (proc.exitCode !== null) {
147
+ const errorMsg = stderrOutput.trim().split("\n").slice(0, 5).join("\n");
148
+ // Don't add to sessions if already exited
149
+ return {
150
+ content: [{ type: "text", text: `scrcpy failed to start for ${serial}.${errorMsg ? "\n" + errorMsg : ""}` }],
151
+ isError: true,
152
+ };
153
+ }
154
+ sessions.set(serial, session);
155
+ const modeDesc = headless ? "headless (no display)" : "windowed";
156
+ const recordDesc = record ? `\nRecording to: ${record}` : "";
157
+ return {
158
+ content: [{
159
+ type: "text",
160
+ text: `Mirror started: ${serial} (${modeDesc})\nscrcpy ${version}\nFPS: ${maxFps}, Bitrate: ${bitrate}${maxSize > 0 ? `, Max size: ${maxSize}px` : ""}${recordDesc}\nUse adb_mirror_stop to end the session.`,
161
+ }],
162
+ };
163
+ }
164
+ catch (error) {
165
+ return { content: [{ type: "text", text: OutputProcessor.formatError(error) }], isError: true };
166
+ }
167
+ });
168
+ ctx.server.tool("adb_mirror_stop", "Stop an active scrcpy mirroring session for a device.", {
169
+ device: z.string().optional().describe("Device serial (stops that device's session). Omit to stop all."),
170
+ }, async ({ device }) => {
171
+ try {
172
+ if (!device) {
173
+ // Stop all
174
+ const count = sessions.size;
175
+ if (count === 0) {
176
+ return { content: [{ type: "text", text: "No active mirror sessions." }] };
177
+ }
178
+ for (const [serial, session] of sessions) {
179
+ try {
180
+ session.process.kill();
181
+ }
182
+ catch { /* ignore */ }
183
+ ctx.logger.info(`[mirror:${serial}] Stopped.`);
184
+ }
185
+ sessions.clear();
186
+ return { content: [{ type: "text", text: `Stopped ${count} mirror session(s).` }] };
187
+ }
188
+ const resolved = await ctx.deviceManager.resolveDevice(device);
189
+ const serial = resolved.serial;
190
+ const session = sessions.get(serial);
191
+ if (!session) {
192
+ return { content: [{ type: "text", text: `No active mirror session for ${serial}.` }], isError: true };
193
+ }
194
+ const elapsed = ((Date.now() - session.startedAt) / 1000).toFixed(1);
195
+ try {
196
+ session.process.kill();
197
+ }
198
+ catch { /* ignore */ }
199
+ sessions.delete(serial);
200
+ return { content: [{ type: "text", text: `Mirror stopped: ${serial} (ran for ${elapsed}s).` }] };
201
+ }
202
+ catch (error) {
203
+ return { content: [{ type: "text", text: OutputProcessor.formatError(error) }], isError: true };
204
+ }
205
+ });
206
+ ctx.server.tool("adb_mirror_status", "Check scrcpy availability and list active mirroring sessions.", {}, async () => {
207
+ try {
208
+ const scrcpyPath = findScrcpy();
209
+ const sections = [];
210
+ if (!scrcpyPath) {
211
+ sections.push("scrcpy: NOT FOUND");
212
+ sections.push("Install from: https://github.com/Genymobile/scrcpy");
213
+ }
214
+ else {
215
+ const version = await checkScrcpyVersion(scrcpyPath);
216
+ if (version) {
217
+ sections.push(`scrcpy: ${version}`);
218
+ sections.push(`Path: ${scrcpyPath}`);
219
+ }
220
+ else {
221
+ sections.push(`scrcpy: found at ${scrcpyPath} but failed to execute`);
222
+ }
223
+ }
224
+ sections.push("");
225
+ if (sessions.size === 0) {
226
+ sections.push("Active sessions: none");
227
+ }
228
+ else {
229
+ sections.push(`Active sessions: ${sessions.size}`);
230
+ for (const [serial, session] of sessions) {
231
+ const elapsed = ((Date.now() - session.startedAt) / 1000).toFixed(0);
232
+ const mode = session.options.headless ? "headless" : "windowed";
233
+ sections.push(` ${serial}: ${mode}, ${session.options.maxFps}fps, ${session.options.bitrate}, running ${elapsed}s`);
234
+ }
235
+ }
236
+ return { content: [{ type: "text", text: sections.join("\n") }] };
237
+ }
238
+ catch (error) {
239
+ return { content: [{ type: "text", text: OutputProcessor.formatError(error) }], isError: true };
240
+ }
241
+ });
242
+ }
243
+ //# sourceMappingURL=mirroring.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mirroring.js","sourceRoot":"","sources":["../../src/tools/mirroring.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Multi-Device Orchestration Tools — Run commands across multiple devices simultaneously.
3
+ *
4
+ * Useful for comparative testing across different Android versions and device models,
5
+ * fleet management, or parallel deployment.
6
+ */
7
+ import { ToolContext } from "../tool-context.js";
8
+ export declare function registerMultiDeviceTools(ctx: ToolContext): void;
9
+ //# sourceMappingURL=multi-device.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multi-device.d.ts","sourceRoot":"","sources":["../../src/tools/multi-device.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGjD,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAqK/D"}
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Multi-Device Orchestration Tools — Run commands across multiple devices simultaneously.
3
+ *
4
+ * Useful for comparative testing across different Android versions and device models,
5
+ * fleet management, or parallel deployment.
6
+ */
7
+ import { z } from "zod";
8
+ import { OutputProcessor } from "../middleware/output-processor.js";
9
+ export function registerMultiDeviceTools(ctx) {
10
+ ctx.server.tool("adb_multi_shell", "Execute a shell command on multiple (or all) connected devices in parallel. Returns results grouped by device.", {
11
+ command: z.string().describe("Shell command to execute on each device"),
12
+ devices: z.array(z.string()).optional().describe("Device serials to target (omit for all online devices)"),
13
+ timeout: z.number().min(1000).max(600000).optional().describe("Timeout per device in milliseconds (1s-10min)"),
14
+ }, async ({ command, devices, timeout }) => {
15
+ try {
16
+ // Security check — same as adb_shell
17
+ const blocked = ctx.security.checkCommand(command);
18
+ if (blocked) {
19
+ return { content: [{ type: "text", text: blocked }], isError: true };
20
+ }
21
+ const allDevices = await ctx.deviceManager.listDevices();
22
+ const online = allDevices.filter((d) => d.state === "device");
23
+ const targets = devices
24
+ ? online.filter((d) => devices.includes(d.serial))
25
+ : online;
26
+ if (targets.length === 0) {
27
+ return { content: [{ type: "text", text: "No matching online devices found." }], isError: true };
28
+ }
29
+ const results = await Promise.allSettled(targets.map(async (d) => {
30
+ const result = await ctx.bridge.shell(command, {
31
+ device: d.serial, timeout, ignoreExitCode: true,
32
+ });
33
+ return { serial: d.serial, model: d.model, result };
34
+ }));
35
+ const output = results.map((r, i) => {
36
+ const device = targets[i];
37
+ const label = device.model ? `${device.serial} (${device.model})` : device.serial;
38
+ if (r.status === "fulfilled") {
39
+ const out = r.value.result.stdout.trim() || "(no output)";
40
+ return `=== ${label} ===\n${out}`;
41
+ }
42
+ const reason = r.reason;
43
+ return `=== ${label} ===\nError: ${reason instanceof Error ? reason.message : reason}`;
44
+ }).join("\n\n");
45
+ return { content: [{ type: "text", text: `Ran on ${targets.length} device(s):\n\n${OutputProcessor.process(output)}` }] };
46
+ }
47
+ catch (error) {
48
+ return { content: [{ type: "text", text: OutputProcessor.formatError(error) }], isError: true };
49
+ }
50
+ });
51
+ ctx.server.tool("adb_multi_install", "Install an APK on multiple (or all) connected devices in parallel.", {
52
+ apkPath: z.string().describe("Local filesystem path to the APK file"),
53
+ devices: z.array(z.string()).optional().describe("Device serials (omit for all online devices)"),
54
+ replace: z.boolean().optional().default(true).describe("Replace existing app (-r)"),
55
+ }, async ({ apkPath, devices, replace }) => {
56
+ try {
57
+ const allDevices = await ctx.deviceManager.listDevices();
58
+ const online = allDevices.filter((d) => d.state === "device");
59
+ const targets = devices
60
+ ? online.filter((d) => devices.includes(d.serial))
61
+ : online;
62
+ if (targets.length === 0) {
63
+ return { content: [{ type: "text", text: "No matching online devices found." }], isError: true };
64
+ }
65
+ const args = ["install"];
66
+ if (replace)
67
+ args.push("-r");
68
+ args.push(apkPath);
69
+ const results = await Promise.allSettled(targets.map(async (d) => {
70
+ const result = await ctx.bridge.exec(args, { device: d.serial, timeout: 120000 });
71
+ return { serial: d.serial, model: d.model, stdout: result.stdout.trim() };
72
+ }));
73
+ const output = results.map((r, i) => {
74
+ const device = targets[i];
75
+ const label = device.model ? `${device.serial} (${device.model})` : device.serial;
76
+ if (r.status === "fulfilled") {
77
+ return `${label}: ${r.value.stdout || "Success"}`;
78
+ }
79
+ const reason = r.reason;
80
+ return `${label}: FAILED — ${reason instanceof Error ? reason.message : reason}`;
81
+ }).join("\n");
82
+ return { content: [{ type: "text", text: `Install results (${targets.length} devices):\n\n${output}` }] };
83
+ }
84
+ catch (error) {
85
+ return { content: [{ type: "text", text: OutputProcessor.formatError(error) }], isError: true };
86
+ }
87
+ });
88
+ ctx.server.tool("adb_multi_compare", "Run a command on all devices and compare outputs side by side. Highlights differences across devices.", {
89
+ command: z.string().describe("Shell command to compare across devices"),
90
+ devices: z.array(z.string()).optional().describe("Device serials (omit for all online devices)"),
91
+ }, async ({ command, devices }) => {
92
+ try {
93
+ // Security check — same as adb_shell and adb_multi_shell
94
+ const blocked = ctx.security.checkCommand(command);
95
+ if (blocked) {
96
+ return { content: [{ type: "text", text: blocked }], isError: true };
97
+ }
98
+ const allDevices = await ctx.deviceManager.listDevices();
99
+ const online = allDevices.filter((d) => d.state === "device");
100
+ const targets = devices
101
+ ? online.filter((d) => devices.includes(d.serial))
102
+ : online;
103
+ if (targets.length < 2) {
104
+ return { content: [{ type: "text", text: "Need at least 2 online devices to compare." }], isError: true };
105
+ }
106
+ const results = await Promise.allSettled(targets.map(async (d) => {
107
+ const result = await ctx.bridge.shell(command, {
108
+ device: d.serial, ignoreExitCode: true,
109
+ });
110
+ return { serial: d.serial, model: d.model, output: result.stdout.trim() };
111
+ }));
112
+ const succeeded = results
113
+ .filter((r) => r.status === "fulfilled")
114
+ .map((r) => r.value);
115
+ if (succeeded.length < 2) {
116
+ return { content: [{ type: "text", text: "Fewer than 2 devices returned results." }], isError: true };
117
+ }
118
+ // Check if all outputs are identical
119
+ const allSame = succeeded.every((r) => r.output === succeeded[0].output);
120
+ let output;
121
+ if (allSame) {
122
+ output = `All ${succeeded.length} devices returned identical output:\n\n${succeeded[0].output}`;
123
+ }
124
+ else {
125
+ output = `DIFFERENCES DETECTED across ${succeeded.length} devices:\n\n`;
126
+ output += succeeded.map((r) => {
127
+ const label = r.model ? `${r.serial} (${r.model})` : r.serial;
128
+ return `=== ${label} ===\n${r.output || "(empty)"}`;
129
+ }).join("\n\n");
130
+ }
131
+ return { content: [{ type: "text", text: OutputProcessor.process(output) }] };
132
+ }
133
+ catch (error) {
134
+ return { content: [{ type: "text", text: OutputProcessor.formatError(error) }], isError: true };
135
+ }
136
+ });
137
+ }
138
+ //# sourceMappingURL=multi-device.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multi-device.js","sourceRoot":"","sources":["../../src/tools/multi-device.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Network Capture Tools — On-device packet capture via tcpdump.
3
+ *
4
+ * Captures network traffic for analysis. Requires tcpdump on device
5
+ * (available on rooted devices or via manual installation).
6
+ * Pulls pcap files locally for Wireshark analysis.
7
+ */
8
+ import { ToolContext } from "../tool-context.js";
9
+ export declare function registerNetworkCaptureTools(ctx: ToolContext): void;
10
+ //# sourceMappingURL=network-capture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network-capture.d.ts","sourceRoot":"","sources":["../../src/tools/network-capture.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAOjD,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAiKlE"}
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Network Capture Tools — On-device packet capture via tcpdump.
3
+ *
4
+ * Captures network traffic for analysis. Requires tcpdump on device
5
+ * (available on rooted devices or via manual installation).
6
+ * Pulls pcap files locally for Wireshark analysis.
7
+ */
8
+ import { z } from "zod";
9
+ import { join } from "path";
10
+ import { OutputProcessor } from "../middleware/output-processor.js";
11
+ import { validateShellArg, shellEscape } from "../middleware/sanitize.js";
12
+ /** Track active captures. Key = device serial. */
13
+ const activeCaptures = new Map();
14
+ export function registerNetworkCaptureTools(ctx) {
15
+ ctx.server.tool("adb_tcpdump_start", "Start a packet capture on the device using tcpdump. Requires root or tcpdump binary on device. Capture runs in background.", {
16
+ interface: z.string().optional().default("any").describe("Network interface to capture (default: 'any')"),
17
+ filter: z.string().optional().describe("tcpdump filter expression (e.g., 'port 443', 'host 10.0.0.1')"),
18
+ maxPackets: z.number().min(1).max(1000000).optional().describe("Stop after N packets (1-1000000, omit for continuous until stop)"),
19
+ device: z.string().optional().describe("Device serial"),
20
+ }, async ({ interface: iface, filter, maxPackets, device }) => {
21
+ try {
22
+ const resolved = await ctx.deviceManager.resolveDevice(device);
23
+ const serial = resolved.serial;
24
+ if (activeCaptures.has(serial)) {
25
+ return { content: [{ type: "text", text: `Capture already running on ${serial}. Stop it first with adb_tcpdump_stop.` }], isError: true };
26
+ }
27
+ // Check if tcpdump is available
28
+ const which = await ctx.bridge.shell("which tcpdump || echo NOT_FOUND", {
29
+ device: serial, ignoreExitCode: true,
30
+ });
31
+ if (which.stdout.includes("NOT_FOUND")) {
32
+ return { content: [{ type: "text", text: "tcpdump not found on device. Requires root or manual installation of tcpdump binary." }], isError: true };
33
+ }
34
+ const filename = `capture_${Date.now()}.pcap`;
35
+ const remotePath = `/sdcard/${filename}`;
36
+ // Validate parameters that get interpolated into the shell command
37
+ const ifaceErr = validateShellArg(iface, "interface");
38
+ if (ifaceErr)
39
+ return { content: [{ type: "text", text: ifaceErr }], isError: true };
40
+ if (filter) {
41
+ const filterErr = validateShellArg(filter, "filter");
42
+ if (filterErr)
43
+ return { content: [{ type: "text", text: filterErr }], isError: true };
44
+ }
45
+ let cmd = `nohup tcpdump -i ${iface} -w '${shellEscape(remotePath)}'`;
46
+ if (maxPackets)
47
+ cmd += ` -c ${maxPackets}`;
48
+ if (filter)
49
+ cmd += ` ${filter}`;
50
+ cmd += " > /dev/null 2>&1 &";
51
+ await ctx.bridge.shell(cmd, { device: serial, ignoreExitCode: true });
52
+ activeCaptures.set(serial, { remotePath, startedAt: Date.now() });
53
+ return {
54
+ content: [{
55
+ type: "text",
56
+ text: `Packet capture started on ${serial}\nInterface: ${iface}\nDevice path: ${remotePath}${filter ? "\nFilter: " + filter : ""}${maxPackets ? "\nMax packets: " + maxPackets : ""}\nUse adb_tcpdump_stop to finish and pull the pcap file.`,
57
+ }],
58
+ };
59
+ }
60
+ catch (error) {
61
+ return { content: [{ type: "text", text: OutputProcessor.formatError(error) }], isError: true };
62
+ }
63
+ });
64
+ ctx.server.tool("adb_tcpdump_stop", "Stop an active packet capture and pull the pcap file locally for analysis.", {
65
+ device: z.string().optional().describe("Device serial"),
66
+ }, async ({ device }) => {
67
+ let resolvedSerial;
68
+ try {
69
+ const resolved = await ctx.deviceManager.resolveDevice(device);
70
+ resolvedSerial = resolved.serial;
71
+ const serial = resolved.serial;
72
+ const capture = activeCaptures.get(serial);
73
+ if (!capture) {
74
+ return { content: [{ type: "text", text: `No active capture on ${serial}.` }], isError: true };
75
+ }
76
+ // Kill the tcpdump process writing to our specific file.
77
+ // Uses pgrep (by binary name) + /proc/cmdline grep to avoid the pkill -f
78
+ // self-match bug: on-device, pkill -f runs through su -c whose cmdline
79
+ // contains the pattern, causing pkill to kill itself instead of tcpdump.
80
+ const captureFilename = capture.remotePath.split("/").pop() ?? "";
81
+ await ctx.bridge.shell(`pgrep tcpdump | while read p; do grep -q '${captureFilename}' /proc/$p/cmdline 2>/dev/null && kill $p; done 2>/dev/null; true`, { device: serial, ignoreExitCode: true });
82
+ await new Promise((r) => setTimeout(r, 1000));
83
+ // Pull pcap file
84
+ const localFilename = capture.remotePath.split("/").pop() ?? "capture.pcap";
85
+ const localPath = join(ctx.config.tempDir, localFilename);
86
+ await ctx.bridge.exec(["pull", capture.remotePath, localPath], { device: serial, timeout: 60000 });
87
+ // Get file size
88
+ const sizeResult = await ctx.bridge.shell(`stat -c %s '${shellEscape(capture.remotePath)}'`, {
89
+ device: serial, ignoreExitCode: true,
90
+ });
91
+ const sizeBytes = parseInt(sizeResult.stdout.trim(), 10) || 0;
92
+ // Clean up device file
93
+ await ctx.bridge.shell(`rm '${shellEscape(capture.remotePath)}'`, { device: serial, ignoreExitCode: true });
94
+ const elapsed = ((Date.now() - capture.startedAt) / 1000).toFixed(1);
95
+ activeCaptures.delete(serial);
96
+ return {
97
+ content: [{
98
+ type: "text",
99
+ text: `Capture saved: ${localPath}\nDuration: ${elapsed}s\nSize: ${(sizeBytes / 1024).toFixed(1)} KB\nOpen in Wireshark for analysis.`,
100
+ }],
101
+ };
102
+ }
103
+ catch (error) {
104
+ if (resolvedSerial) {
105
+ activeCaptures.delete(resolvedSerial);
106
+ }
107
+ return { content: [{ type: "text", text: OutputProcessor.formatError(error) }], isError: true };
108
+ }
109
+ });
110
+ ctx.server.tool("adb_network_connections", "Show active network connections on the device (TCP/UDP). Similar to netstat — shows established connections, listening ports, and connection states.", {
111
+ protocol: z.enum(["tcp", "udp", "all"]).optional().default("all").describe("Filter by protocol"),
112
+ device: z.string().optional().describe("Device serial"),
113
+ }, async ({ protocol, device }) => {
114
+ try {
115
+ const resolved = await ctx.deviceManager.resolveDevice(device);
116
+ const serial = resolved.serial;
117
+ const commands = [];
118
+ if (protocol === "tcp" || protocol === "all")
119
+ commands.push("cat /proc/net/tcp /proc/net/tcp6 2>/dev/null");
120
+ if (protocol === "udp" || protocol === "all")
121
+ commands.push("cat /proc/net/udp /proc/net/udp6 2>/dev/null");
122
+ // Also try ss or netstat if available
123
+ const ssResult = await ctx.bridge.shell("ss -tuln 2>/dev/null || netstat -tuln 2>/dev/null || echo FALLBACK", {
124
+ device: serial, ignoreExitCode: true,
125
+ });
126
+ if (!ssResult.stdout.includes("FALLBACK")) {
127
+ return { content: [{ type: "text", text: OutputProcessor.process(ssResult.stdout) }] };
128
+ }
129
+ // Fallback: parse /proc/net
130
+ const results = await Promise.allSettled(commands.map((cmd) => ctx.bridge.shell(cmd, { device: serial, ignoreExitCode: true })));
131
+ const output = results
132
+ .filter((r) => r.status === "fulfilled")
133
+ .map((r) => r.value.stdout.trim())
134
+ .filter((s) => s.length > 0)
135
+ .join("\n\n");
136
+ return { content: [{ type: "text", text: OutputProcessor.process(output || "No connection data available.") }] };
137
+ }
138
+ catch (error) {
139
+ return { content: [{ type: "text", text: OutputProcessor.formatError(error) }], isError: true };
140
+ }
141
+ });
142
+ }
143
+ //# sourceMappingURL=network-capture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network-capture.js","sourceRoot":"","sources":["../../src/tools/network-capture.ts"],"names":[],"mappings":"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"}