@0xhayd3n/fling 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adb.d.ts +18 -0
- package/dist/adb.js +109 -0
- package/dist/adb.js.map +1 -0
- package/dist/apkFinder.d.ts +19 -0
- package/dist/apkFinder.js +113 -0
- package/dist/apkFinder.js.map +1 -0
- package/dist/apkResolver.d.ts +14 -0
- package/dist/apkResolver.js +55 -0
- package/dist/apkResolver.js.map +1 -0
- package/dist/config.d.ts +44 -0
- package/dist/config.js +113 -0
- package/dist/config.js.map +1 -0
- package/dist/devices.d.ts +24 -0
- package/dist/devices.js +143 -0
- package/dist/devices.js.map +1 -0
- package/dist/errors.d.ts +13 -0
- package/dist/errors.js +22 -0
- package/dist/errors.js.map +1 -0
- package/dist/featureFlags.d.ts +6 -0
- package/dist/featureFlags.js +11 -0
- package/dist/featureFlags.js.map +1 -0
- package/dist/gradle.d.ts +39 -0
- package/dist/gradle.js +129 -0
- package/dist/gradle.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +76 -0
- package/dist/index.js.map +1 -0
- package/dist/mdns.d.ts +19 -0
- package/dist/mdns.js +68 -0
- package/dist/mdns.js.map +1 -0
- package/dist/pairing.d.ts +52 -0
- package/dist/pairing.js +212 -0
- package/dist/pairing.js.map +1 -0
- package/dist/qrText.d.ts +5 -0
- package/dist/qrText.js +8 -0
- package/dist/qrText.js.map +1 -0
- package/dist/schemas.d.ts +31 -0
- package/dist/schemas.js +26 -0
- package/dist/schemas.js.map +1 -0
- package/dist/shellFraming.d.ts +28 -0
- package/dist/shellFraming.js +43 -0
- package/dist/shellFraming.js.map +1 -0
- package/dist/shellPool.d.ts +54 -0
- package/dist/shellPool.js +181 -0
- package/dist/shellPool.js.map +1 -0
- package/dist/toolResult.d.ts +10 -0
- package/dist/toolResult.js +11 -0
- package/dist/toolResult.js.map +1 -0
- package/dist/tools/build-app.d.ts +2 -0
- package/dist/tools/build-app.js +74 -0
- package/dist/tools/build-app.js.map +1 -0
- package/dist/tools/deploy-and-run.d.ts +2 -0
- package/dist/tools/deploy-and-run.js +195 -0
- package/dist/tools/deploy-and-run.js.map +1 -0
- package/dist/tools/device-state.d.ts +11 -0
- package/dist/tools/device-state.js +140 -0
- package/dist/tools/device-state.js.map +1 -0
- package/dist/tools/dismiss-dialog.d.ts +15 -0
- package/dist/tools/dismiss-dialog.js +89 -0
- package/dist/tools/dismiss-dialog.js.map +1 -0
- package/dist/tools/dump-ui.d.ts +4 -0
- package/dist/tools/dump-ui.js +93 -0
- package/dist/tools/dump-ui.js.map +1 -0
- package/dist/tools/find-on-screen.d.ts +27 -0
- package/dist/tools/find-on-screen.js +92 -0
- package/dist/tools/find-on-screen.js.map +1 -0
- package/dist/tools/install-app.d.ts +23 -0
- package/dist/tools/install-app.js +127 -0
- package/dist/tools/install-app.js.map +1 -0
- package/dist/tools/launch-and-wait.d.ts +27 -0
- package/dist/tools/launch-and-wait.js +103 -0
- package/dist/tools/launch-and-wait.js.map +1 -0
- package/dist/tools/launch-app.d.ts +20 -0
- package/dist/tools/launch-app.js +131 -0
- package/dist/tools/launch-app.js.map +1 -0
- package/dist/tools/launch-settings.d.ts +42 -0
- package/dist/tools/launch-settings.js +211 -0
- package/dist/tools/launch-settings.js.map +1 -0
- package/dist/tools/list-devices.d.ts +2 -0
- package/dist/tools/list-devices.js +35 -0
- package/dist/tools/list-devices.js.map +1 -0
- package/dist/tools/long-press-by-text.d.ts +3 -0
- package/dist/tools/long-press-by-text.js +99 -0
- package/dist/tools/long-press-by-text.js.map +1 -0
- package/dist/tools/open-setting.d.ts +55 -0
- package/dist/tools/open-setting.js +257 -0
- package/dist/tools/open-setting.js.map +1 -0
- package/dist/tools/read-logs.d.ts +2 -0
- package/dist/tools/read-logs.js +147 -0
- package/dist/tools/read-logs.js.map +1 -0
- package/dist/tools/screenshot-with-ui.d.ts +21 -0
- package/dist/tools/screenshot-with-ui.js +74 -0
- package/dist/tools/screenshot-with-ui.js.map +1 -0
- package/dist/tools/screenshot.d.ts +8 -0
- package/dist/tools/screenshot.js +97 -0
- package/dist/tools/screenshot.js.map +1 -0
- package/dist/tools/scroll-until-visible.d.ts +23 -0
- package/dist/tools/scroll-until-visible.js +138 -0
- package/dist/tools/scroll-until-visible.js.map +1 -0
- package/dist/tools/start-pair-qr.d.ts +11 -0
- package/dist/tools/start-pair-qr.js +62 -0
- package/dist/tools/start-pair-qr.js.map +1 -0
- package/dist/tools/stop-app.d.ts +2 -0
- package/dist/tools/stop-app.js +63 -0
- package/dist/tools/stop-app.js.map +1 -0
- package/dist/tools/tap-by-content-desc.d.ts +17 -0
- package/dist/tools/tap-by-content-desc.js +97 -0
- package/dist/tools/tap-by-content-desc.js.map +1 -0
- package/dist/tools/tap-by-resource-id.d.ts +17 -0
- package/dist/tools/tap-by-resource-id.js +89 -0
- package/dist/tools/tap-by-resource-id.js.map +1 -0
- package/dist/tools/tap-by-text.d.ts +40 -0
- package/dist/tools/tap-by-text.js +180 -0
- package/dist/tools/tap-by-text.js.map +1 -0
- package/dist/tools/tap-text-verified.d.ts +37 -0
- package/dist/tools/tap-text-verified.js +111 -0
- package/dist/tools/tap-text-verified.js.map +1 -0
- package/dist/tools/uninstall-app.d.ts +2 -0
- package/dist/tools/uninstall-app.js +96 -0
- package/dist/tools/uninstall-app.js.map +1 -0
- package/dist/tools/wait-for-pair.d.ts +29 -0
- package/dist/tools/wait-for-pair.js +132 -0
- package/dist/tools/wait-for-pair.js.map +1 -0
- package/dist/tools/wait-for.d.ts +26 -0
- package/dist/tools/wait-for.js +109 -0
- package/dist/tools/wait-for.js.map +1 -0
- package/dist/uiDump.d.ts +34 -0
- package/dist/uiDump.js +108 -0
- package/dist/uiDump.js.map +1 -0
- package/dist/uiSelector.d.ts +21 -0
- package/dist/uiSelector.js +62 -0
- package/dist/uiSelector.js.map +1 -0
- package/package.json +67 -0
package/dist/pairing.js
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { runAdb } from "./adb.js";
|
|
3
|
+
import { FlingError } from "./errors.js";
|
|
4
|
+
import { buildQrText } from "./qrText.js";
|
|
5
|
+
import { discoverPairingPort as realDiscoverPairing, discoverConnectByHost as realDiscoverConnect, } from "./mdns.js";
|
|
6
|
+
export { discoverConnectByHost } from "./mdns.js";
|
|
7
|
+
let runAdbImpl = (args) => runAdb(args);
|
|
8
|
+
export function __setRunAdbForTest(fn) {
|
|
9
|
+
runAdbImpl = fn ?? ((args) => runAdb(args));
|
|
10
|
+
}
|
|
11
|
+
let discoverImpl = {
|
|
12
|
+
discoverPairingPort: realDiscoverPairing,
|
|
13
|
+
discoverConnectByHost: realDiscoverConnect,
|
|
14
|
+
};
|
|
15
|
+
export function __setDiscoverForTest(d) {
|
|
16
|
+
discoverImpl = d ?? {
|
|
17
|
+
discoverPairingPort: realDiscoverPairing,
|
|
18
|
+
discoverConnectByHost: realDiscoverConnect,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
const DEFAULT_TIMEOUT_MS = 60_000;
|
|
22
|
+
function genServiceName() {
|
|
23
|
+
return `fling-debug-${randomBytes(2).toString("hex")}`;
|
|
24
|
+
}
|
|
25
|
+
function genPassword() {
|
|
26
|
+
return randomBytes(12).toString("base64").replace(/[=+/]/g, "");
|
|
27
|
+
}
|
|
28
|
+
function emit(cb, s) {
|
|
29
|
+
if (cb) {
|
|
30
|
+
try {
|
|
31
|
+
cb(s);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
// Listener errors must not break the state machine.
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
async function parseDevicesForSerial(serial) {
|
|
39
|
+
const { stdout } = await runAdbImpl(["devices", "-l"]);
|
|
40
|
+
const lines = stdout.split(/\r?\n/);
|
|
41
|
+
for (const line of lines) {
|
|
42
|
+
if (!line.includes(serial))
|
|
43
|
+
continue;
|
|
44
|
+
const parts = line.trim().split(/\s+/);
|
|
45
|
+
if (parts.length < 2)
|
|
46
|
+
continue;
|
|
47
|
+
if (parts[1] !== "device")
|
|
48
|
+
continue;
|
|
49
|
+
const modelMatch = parts.find((p) => p.startsWith("model:"));
|
|
50
|
+
return { serial: parts[0], model: modelMatch ? modelMatch.slice("model:".length) : "Unknown" };
|
|
51
|
+
}
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
async function waitForDeviceReady(serial, timeoutMs) {
|
|
55
|
+
const deadline = Date.now() + timeoutMs;
|
|
56
|
+
while (Date.now() < deadline) {
|
|
57
|
+
const d = await parseDevicesForSerial(serial);
|
|
58
|
+
if (d)
|
|
59
|
+
return d;
|
|
60
|
+
await new Promise((res) => setTimeout(res, 300));
|
|
61
|
+
}
|
|
62
|
+
throw new FlingError("ADB_CONNECT_FAILED", `Device ${serial} did not become ready within ${timeoutMs}ms.`);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Build an abort-aware race promise that rejects with "Cancelled." when the
|
|
66
|
+
* signal fires. Returns a no-op promise (never resolves/rejects) when no
|
|
67
|
+
* signal is provided, making Promise.race safe to call unconditionally.
|
|
68
|
+
*/
|
|
69
|
+
function abortPromise(signal) {
|
|
70
|
+
return new Promise((_, reject) => {
|
|
71
|
+
if (!signal)
|
|
72
|
+
return; // never resolves
|
|
73
|
+
if (signal.aborted) {
|
|
74
|
+
reject(new Error("Cancelled."));
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
signal.addEventListener("abort", () => reject(new Error("Cancelled.")), { once: true });
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
export function startPairQr(opts = {}) {
|
|
81
|
+
const serviceName = genServiceName();
|
|
82
|
+
const password = genPassword();
|
|
83
|
+
const qrText = buildQrText({ serviceName, password });
|
|
84
|
+
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
85
|
+
const done = (async () => {
|
|
86
|
+
if (opts.signal?.aborted) {
|
|
87
|
+
const s = { kind: "error", reason: "Cancelled before start." };
|
|
88
|
+
emit(opts.onStatus, s);
|
|
89
|
+
return s;
|
|
90
|
+
}
|
|
91
|
+
emit(opts.onStatus, { kind: "waiting" });
|
|
92
|
+
const abort = abortPromise(opts.signal);
|
|
93
|
+
let pairingHost;
|
|
94
|
+
let pairingPort;
|
|
95
|
+
try {
|
|
96
|
+
const r = await Promise.race([
|
|
97
|
+
discoverImpl.discoverPairingPort(serviceName, timeoutMs),
|
|
98
|
+
abort,
|
|
99
|
+
]);
|
|
100
|
+
pairingHost = r.host;
|
|
101
|
+
pairingPort = r.port;
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
const code = err.code;
|
|
105
|
+
if (opts.signal?.aborted) {
|
|
106
|
+
const s = { kind: "error", reason: "Cancelled." };
|
|
107
|
+
emit(opts.onStatus, s);
|
|
108
|
+
return s;
|
|
109
|
+
}
|
|
110
|
+
if (code === "PAIRING_TIMEOUT") {
|
|
111
|
+
const s = { kind: "timeout" };
|
|
112
|
+
emit(opts.onStatus, s);
|
|
113
|
+
return s;
|
|
114
|
+
}
|
|
115
|
+
const s = { kind: "error", reason: err.message };
|
|
116
|
+
emit(opts.onStatus, s);
|
|
117
|
+
return s;
|
|
118
|
+
}
|
|
119
|
+
emit(opts.onStatus, { kind: "pairing" });
|
|
120
|
+
try {
|
|
121
|
+
await runAdbImpl(["pair", `${pairingHost}:${pairingPort}`, password]);
|
|
122
|
+
}
|
|
123
|
+
catch (err) {
|
|
124
|
+
const e = err;
|
|
125
|
+
const s = {
|
|
126
|
+
kind: "error",
|
|
127
|
+
reason: (e.stderr && e.stderr.trim()) || e.message || "adb pair failed",
|
|
128
|
+
rawAdbError: e.stderr,
|
|
129
|
+
};
|
|
130
|
+
emit(opts.onStatus, s);
|
|
131
|
+
return s;
|
|
132
|
+
}
|
|
133
|
+
emit(opts.onStatus, { kind: "connecting" });
|
|
134
|
+
let connectInfo;
|
|
135
|
+
try {
|
|
136
|
+
// After pair, the phone advertises _adb-tls-connect on a fresh port.
|
|
137
|
+
// We don't know the device's serial yet (we get it from `adb devices`
|
|
138
|
+
// post-connect), so match by host — connect service is on the same
|
|
139
|
+
// host as pairing.
|
|
140
|
+
const r = await Promise.race([
|
|
141
|
+
discoverImpl.discoverConnectByHost(pairingHost, 10_000),
|
|
142
|
+
abort,
|
|
143
|
+
]);
|
|
144
|
+
connectInfo = r;
|
|
145
|
+
}
|
|
146
|
+
catch (err) {
|
|
147
|
+
const e = err;
|
|
148
|
+
const s = {
|
|
149
|
+
kind: "error",
|
|
150
|
+
reason: (e.message ?? "Couldn't find connect service after pairing"),
|
|
151
|
+
rawAdbError: e.stderr,
|
|
152
|
+
};
|
|
153
|
+
emit(opts.onStatus, s);
|
|
154
|
+
return s;
|
|
155
|
+
}
|
|
156
|
+
try {
|
|
157
|
+
await runAdbImpl(["connect", `${connectInfo.host}:${connectInfo.port}`]);
|
|
158
|
+
const dev = await waitForDeviceReady(`${connectInfo.host}:${connectInfo.port}`, 5_000);
|
|
159
|
+
const s = { kind: "success", serial: dev.serial, model: dev.model };
|
|
160
|
+
emit(opts.onStatus, s);
|
|
161
|
+
return s;
|
|
162
|
+
}
|
|
163
|
+
catch (err) {
|
|
164
|
+
const e = err;
|
|
165
|
+
const s = {
|
|
166
|
+
kind: "error",
|
|
167
|
+
reason: (e.stderr && e.stderr.trim()) || e.message || "adb connect failed",
|
|
168
|
+
rawAdbError: e.stderr,
|
|
169
|
+
};
|
|
170
|
+
emit(opts.onStatus, s);
|
|
171
|
+
return s;
|
|
172
|
+
}
|
|
173
|
+
})();
|
|
174
|
+
return { qrText, serviceName, done };
|
|
175
|
+
}
|
|
176
|
+
export async function pairWithCode(opts) {
|
|
177
|
+
const timeoutMs = opts.timeoutMs ?? 30_000;
|
|
178
|
+
emit(opts.onStatus, { kind: "pairing" });
|
|
179
|
+
try {
|
|
180
|
+
await runAdbImpl(["pair", `${opts.host}:${opts.port}`, opts.code]);
|
|
181
|
+
}
|
|
182
|
+
catch (err) {
|
|
183
|
+
const e = err;
|
|
184
|
+
const s = {
|
|
185
|
+
kind: "error",
|
|
186
|
+
reason: (e.stderr && e.stderr.trim()) || e.message || "adb pair failed",
|
|
187
|
+
rawAdbError: e.stderr,
|
|
188
|
+
};
|
|
189
|
+
emit(opts.onStatus, s);
|
|
190
|
+
return s;
|
|
191
|
+
}
|
|
192
|
+
emit(opts.onStatus, { kind: "connecting" });
|
|
193
|
+
try {
|
|
194
|
+
const r = await discoverImpl.discoverConnectByHost(opts.host, timeoutMs);
|
|
195
|
+
await runAdbImpl(["connect", `${r.host}:${r.port}`]);
|
|
196
|
+
const dev = await waitForDeviceReady(`${r.host}:${r.port}`, 5_000);
|
|
197
|
+
const s = { kind: "success", serial: dev.serial, model: dev.model };
|
|
198
|
+
emit(opts.onStatus, s);
|
|
199
|
+
return s;
|
|
200
|
+
}
|
|
201
|
+
catch (err) {
|
|
202
|
+
const e = err;
|
|
203
|
+
const s = {
|
|
204
|
+
kind: "error",
|
|
205
|
+
reason: (e.stderr && e.stderr.trim()) || e.message || "adb connect failed",
|
|
206
|
+
rawAdbError: e.stderr,
|
|
207
|
+
};
|
|
208
|
+
emit(opts.onStatus, s);
|
|
209
|
+
return s;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=pairing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pairing.js","sourceRoot":"","sources":["../src/pairing.ts"],"names":[],"mappings":"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"}
|
package/dist/qrText.d.ts
ADDED
package/dist/qrText.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export function buildQrText(opts) {
|
|
2
|
+
if (!opts.serviceName)
|
|
3
|
+
throw new Error("serviceName must be non-empty");
|
|
4
|
+
if (!opts.password)
|
|
5
|
+
throw new Error("password must be non-empty");
|
|
6
|
+
return `WIFI:T:ADB;S:${opts.serviceName};P:${opts.password};;`;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=qrText.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qrText.js","sourceRoot":"","sources":["../src/qrText.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,WAAW,CAAC,IAAwB;IAClD,IAAI,CAAC,IAAI,CAAC,WAAW;QAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACxE,IAAI,CAAC,IAAI,CAAC,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAClE,OAAO,gBAAgB,IAAI,CAAC,WAAW,MAAM,IAAI,CAAC,QAAQ,IAAI,CAAC;AACjE,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const deviceStateSchema: z.ZodEnum<["device", "unauthorized", "offline", "no permissions", "recovery", "sideload", "bootloader", "unknown"]>;
|
|
3
|
+
export declare const deviceShape: z.ZodObject<{
|
|
4
|
+
serial: z.ZodString;
|
|
5
|
+
state: z.ZodEnum<["device", "unauthorized", "offline", "no permissions", "recovery", "sideload", "bootloader", "unknown"]>;
|
|
6
|
+
product: z.ZodOptional<z.ZodString>;
|
|
7
|
+
model: z.ZodOptional<z.ZodString>;
|
|
8
|
+
device: z.ZodOptional<z.ZodString>;
|
|
9
|
+
transportId: z.ZodOptional<z.ZodString>;
|
|
10
|
+
usb: z.ZodOptional<z.ZodString>;
|
|
11
|
+
raw: z.ZodString;
|
|
12
|
+
}, "strip", z.ZodTypeAny, {
|
|
13
|
+
serial: string;
|
|
14
|
+
state: "unknown" | "device" | "unauthorized" | "offline" | "no permissions" | "recovery" | "sideload" | "bootloader";
|
|
15
|
+
raw: string;
|
|
16
|
+
device?: string | undefined;
|
|
17
|
+
product?: string | undefined;
|
|
18
|
+
model?: string | undefined;
|
|
19
|
+
usb?: string | undefined;
|
|
20
|
+
transportId?: string | undefined;
|
|
21
|
+
}, {
|
|
22
|
+
serial: string;
|
|
23
|
+
state: "unknown" | "device" | "unauthorized" | "offline" | "no permissions" | "recovery" | "sideload" | "bootloader";
|
|
24
|
+
raw: string;
|
|
25
|
+
device?: string | undefined;
|
|
26
|
+
product?: string | undefined;
|
|
27
|
+
model?: string | undefined;
|
|
28
|
+
usb?: string | undefined;
|
|
29
|
+
transportId?: string | undefined;
|
|
30
|
+
}>;
|
|
31
|
+
export declare const deviceIdInput: z.ZodOptional<z.ZodString>;
|
package/dist/schemas.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export const deviceStateSchema = z.enum([
|
|
3
|
+
"device",
|
|
4
|
+
"unauthorized",
|
|
5
|
+
"offline",
|
|
6
|
+
"no permissions",
|
|
7
|
+
"recovery",
|
|
8
|
+
"sideload",
|
|
9
|
+
"bootloader",
|
|
10
|
+
"unknown",
|
|
11
|
+
]);
|
|
12
|
+
export const deviceShape = z.object({
|
|
13
|
+
serial: z.string(),
|
|
14
|
+
state: deviceStateSchema,
|
|
15
|
+
product: z.string().optional(),
|
|
16
|
+
model: z.string().optional(),
|
|
17
|
+
device: z.string().optional(),
|
|
18
|
+
transportId: z.string().optional(),
|
|
19
|
+
usb: z.string().optional(),
|
|
20
|
+
raw: z.string(),
|
|
21
|
+
});
|
|
22
|
+
export const deviceIdInput = z
|
|
23
|
+
.string()
|
|
24
|
+
.optional()
|
|
25
|
+
.describe("Target device serial. Omit when exactly one device is connected; required when multiple are.");
|
|
26
|
+
//# sourceMappingURL=schemas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemas.js","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,IAAI,CAAC;IACtC,QAAQ;IACR,cAAc;IACd,SAAS;IACT,gBAAgB;IAChB,UAAU;IACV,UAAU;IACV,YAAY;IACZ,SAAS;CACV,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;IAClB,KAAK,EAAE,iBAAiB;IACxB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC1B,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;CAChB,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC;KAC3B,MAAM,EAAE;KACR,QAAQ,EAAE;KACV,QAAQ,CACP,8FAA8F,CAC/F,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-shell random token used to namespace sentinel lines. 8 hex chars =
|
|
3
|
+
* 2^32 possibilities — far below a credible accidental collision with
|
|
4
|
+
* legitimate command output.
|
|
5
|
+
*/
|
|
6
|
+
export declare function newToken(): string;
|
|
7
|
+
/**
|
|
8
|
+
* Append a printf sentinel to the user's command. The sentinel encodes the
|
|
9
|
+
* per-shell token and a per-call sequence number, plus the command's exit
|
|
10
|
+
* code via $?. Reader strips the marker line and exposes everything before
|
|
11
|
+
* it as stdout.
|
|
12
|
+
*
|
|
13
|
+
* Uses printf rather than echo for consistent newline handling across
|
|
14
|
+
* Android's toybox sh.
|
|
15
|
+
*/
|
|
16
|
+
export declare function buildFramedCommand(cmd: string, token: string, seq: number): string;
|
|
17
|
+
export interface FrameMatch {
|
|
18
|
+
matched: boolean;
|
|
19
|
+
exitCode?: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Pre-compile a per-shell matcher. The token is baked into a regex so we
|
|
23
|
+
* don't recompile per line. matchLine is invoked once per CR/LF-delimited
|
|
24
|
+
* stdout line.
|
|
25
|
+
*/
|
|
26
|
+
export declare function makeFrameMatcher(token: string): {
|
|
27
|
+
matchLine: (line: string, expectedSeq: number) => FrameMatch;
|
|
28
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
/**
|
|
3
|
+
* Per-shell random token used to namespace sentinel lines. 8 hex chars =
|
|
4
|
+
* 2^32 possibilities — far below a credible accidental collision with
|
|
5
|
+
* legitimate command output.
|
|
6
|
+
*/
|
|
7
|
+
export function newToken() {
|
|
8
|
+
return randomBytes(4).toString("hex");
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Append a printf sentinel to the user's command. The sentinel encodes the
|
|
12
|
+
* per-shell token and a per-call sequence number, plus the command's exit
|
|
13
|
+
* code via $?. Reader strips the marker line and exposes everything before
|
|
14
|
+
* it as stdout.
|
|
15
|
+
*
|
|
16
|
+
* Uses printf rather than echo for consistent newline handling across
|
|
17
|
+
* Android's toybox sh.
|
|
18
|
+
*/
|
|
19
|
+
export function buildFramedCommand(cmd, token, seq) {
|
|
20
|
+
return `${cmd} ; printf '\\n__FLING_RC_${token}_${seq}__%d\\n' $?`;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Pre-compile a per-shell matcher. The token is baked into a regex so we
|
|
24
|
+
* don't recompile per line. matchLine is invoked once per CR/LF-delimited
|
|
25
|
+
* stdout line.
|
|
26
|
+
*/
|
|
27
|
+
export function makeFrameMatcher(token) {
|
|
28
|
+
const re = new RegExp(`^__FLING_RC_${token}_(\\d+)__(\\d+)$`);
|
|
29
|
+
return {
|
|
30
|
+
matchLine(line, expectedSeq) {
|
|
31
|
+
const trimmed = line.replace(/\r$/, "");
|
|
32
|
+
const m = re.exec(trimmed);
|
|
33
|
+
if (!m)
|
|
34
|
+
return { matched: false };
|
|
35
|
+
const seq = Number(m[1]);
|
|
36
|
+
const exitCode = Number(m[2]);
|
|
37
|
+
if (seq !== expectedSeq)
|
|
38
|
+
return { matched: false };
|
|
39
|
+
return { matched: true, exitCode };
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=shellFraming.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shellFraming.js","sourceRoot":"","sources":["../src/shellFraming.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C;;;;GAIG;AACH,MAAM,UAAU,QAAQ;IACtB,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACxC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAChC,GAAW,EACX,KAAa,EACb,GAAW;IAEX,OAAO,GAAG,GAAG,4BAA4B,KAAK,IAAI,GAAG,aAAa,CAAC;AACrE,CAAC;AAOD;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAG5C,MAAM,EAAE,GAAG,IAAI,MAAM,CAAC,eAAe,KAAK,kBAAkB,CAAC,CAAC;IAC9D,OAAO;QACL,SAAS,CAAC,IAAY,EAAE,WAAmB;YACzC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YACxC,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC3B,IAAI,CAAC,CAAC;gBAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;YAClC,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACzB,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9B,IAAI,GAAG,KAAK,WAAW;gBAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;YACnD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;QACrC,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { type ChildProcess } from "node:child_process";
|
|
2
|
+
export interface AdbShellOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Injection seam for tests: a function returning a ChildProcess-shaped
|
|
5
|
+
* object. Defaults to node:child_process.spawn.
|
|
6
|
+
*/
|
|
7
|
+
spawnImpl?: (cmd: string, args: string[]) => ChildProcess;
|
|
8
|
+
}
|
|
9
|
+
export interface ExecOptions {
|
|
10
|
+
timeoutMs?: number;
|
|
11
|
+
}
|
|
12
|
+
export interface ExecResult {
|
|
13
|
+
stdout: string;
|
|
14
|
+
exitCode: number;
|
|
15
|
+
}
|
|
16
|
+
export declare class AdbShell {
|
|
17
|
+
readonly serial: string;
|
|
18
|
+
private child;
|
|
19
|
+
private readonly token;
|
|
20
|
+
private readonly matcher;
|
|
21
|
+
private seq;
|
|
22
|
+
private shutDown;
|
|
23
|
+
private readonly spawnImpl;
|
|
24
|
+
private buffer;
|
|
25
|
+
private queue;
|
|
26
|
+
private inFlight;
|
|
27
|
+
private inFlightTimer;
|
|
28
|
+
private readersAttached;
|
|
29
|
+
constructor(serial: string, options?: AdbShellOptions);
|
|
30
|
+
/** @internal — test seam. Real callers go through exec(). */
|
|
31
|
+
_ensureSpawned(): ChildProcess;
|
|
32
|
+
exec(cmd: string, opts?: ExecOptions): Promise<ExecResult>;
|
|
33
|
+
private _pump;
|
|
34
|
+
private _onTimeout;
|
|
35
|
+
private _recycle;
|
|
36
|
+
private _attachReadersOnce;
|
|
37
|
+
private _onExit;
|
|
38
|
+
/** @internal — test seam. */
|
|
39
|
+
_currentChildForTest(): ChildProcess | null;
|
|
40
|
+
private _onStdout;
|
|
41
|
+
shutdown(): void;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Lazily get-or-create the AdbShell for a device and exec a command on it.
|
|
45
|
+
* One persistent `adb -s <serial> shell` per device, shared across all
|
|
46
|
+
* tools that use this helper.
|
|
47
|
+
*/
|
|
48
|
+
export declare function shell(serial: string, cmd: string, opts?: ExecOptions): Promise<ExecResult>;
|
|
49
|
+
/** Kill all live shells and clear the pool. Wired to process exit/SIGINT. */
|
|
50
|
+
export declare function shutdownPool(): void;
|
|
51
|
+
/** @internal — test-only hook to clear pool state between tests. */
|
|
52
|
+
export declare function _resetPoolForTests(): void;
|
|
53
|
+
/** @internal — test-only hook to inspect the pool. */
|
|
54
|
+
export declare function _poolSizeForTests(): number;
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { spawn as nodeSpawn } from "node:child_process";
|
|
2
|
+
import { FlingError } from "./errors.js";
|
|
3
|
+
import { buildFramedCommand, makeFrameMatcher, newToken } from "./shellFraming.js";
|
|
4
|
+
const DEFAULT_TIMEOUT_MS = 15_000;
|
|
5
|
+
export class AdbShell {
|
|
6
|
+
serial;
|
|
7
|
+
child = null;
|
|
8
|
+
token = newToken();
|
|
9
|
+
matcher = makeFrameMatcher(this.token);
|
|
10
|
+
seq = 0;
|
|
11
|
+
shutDown = false;
|
|
12
|
+
spawnImpl;
|
|
13
|
+
buffer = "";
|
|
14
|
+
queue = [];
|
|
15
|
+
inFlight = null;
|
|
16
|
+
inFlightTimer = null;
|
|
17
|
+
readersAttached = false;
|
|
18
|
+
constructor(serial, options = {}) {
|
|
19
|
+
this.serial = serial;
|
|
20
|
+
this.spawnImpl = options.spawnImpl ?? nodeSpawn;
|
|
21
|
+
}
|
|
22
|
+
/** @internal — test seam. Real callers go through exec(). */
|
|
23
|
+
_ensureSpawned() {
|
|
24
|
+
if (this.child)
|
|
25
|
+
return this.child;
|
|
26
|
+
if (this.shutDown) {
|
|
27
|
+
throw new FlingError("ADB_SHELL_SHUT_DOWN", `Shell for ${this.serial} has been shut down.`);
|
|
28
|
+
}
|
|
29
|
+
this.child = this.spawnImpl("adb", ["-s", this.serial, "shell"]);
|
|
30
|
+
return this.child;
|
|
31
|
+
}
|
|
32
|
+
exec(cmd, opts = {}) {
|
|
33
|
+
if (this.shutDown) {
|
|
34
|
+
return Promise.reject(new FlingError("ADB_SHELL_SHUT_DOWN", `Shell for ${this.serial} has been shut down.`));
|
|
35
|
+
}
|
|
36
|
+
this.seq += 1;
|
|
37
|
+
const seq = this.seq;
|
|
38
|
+
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
39
|
+
return new Promise((resolve, reject) => {
|
|
40
|
+
this.queue.push({ cmd, seq, timeoutMs, resolve, reject });
|
|
41
|
+
this._pump();
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
_pump() {
|
|
45
|
+
if (this.inFlight)
|
|
46
|
+
return;
|
|
47
|
+
const next = this.queue.shift();
|
|
48
|
+
if (!next)
|
|
49
|
+
return;
|
|
50
|
+
const child = this._ensureSpawned();
|
|
51
|
+
this._attachReadersOnce(child);
|
|
52
|
+
this.inFlight = {
|
|
53
|
+
seq: next.seq,
|
|
54
|
+
resolve: next.resolve,
|
|
55
|
+
reject: next.reject,
|
|
56
|
+
stdoutLines: [],
|
|
57
|
+
};
|
|
58
|
+
this.inFlightTimer = setTimeout(() => this._onTimeout(), next.timeoutMs);
|
|
59
|
+
const framed = buildFramedCommand(next.cmd, this.token, next.seq);
|
|
60
|
+
child.stdin.write(framed + "\n");
|
|
61
|
+
}
|
|
62
|
+
_onTimeout() {
|
|
63
|
+
const failed = this.inFlight;
|
|
64
|
+
this.inFlight = null;
|
|
65
|
+
this.inFlightTimer = null;
|
|
66
|
+
if (failed) {
|
|
67
|
+
failed.reject(new FlingError("ADB_TIMEOUT", `adb shell command (seq ${failed.seq}) timed out on ${this.serial}.`));
|
|
68
|
+
}
|
|
69
|
+
this._recycle("ADB_SHELL_RECYCLED", `Shell for ${this.serial} was recycled after a command timeout.`);
|
|
70
|
+
}
|
|
71
|
+
_recycle(code, reason) {
|
|
72
|
+
for (const q of this.queue) {
|
|
73
|
+
q.reject(new FlingError(code, reason));
|
|
74
|
+
}
|
|
75
|
+
this.queue = [];
|
|
76
|
+
if (this.child && !this.child.killed) {
|
|
77
|
+
this.child.kill();
|
|
78
|
+
}
|
|
79
|
+
this.child = null;
|
|
80
|
+
this.readersAttached = false;
|
|
81
|
+
this.buffer = "";
|
|
82
|
+
}
|
|
83
|
+
_attachReadersOnce(child) {
|
|
84
|
+
if (this.readersAttached)
|
|
85
|
+
return;
|
|
86
|
+
this.readersAttached = true;
|
|
87
|
+
child.stdout.on("data", (chunk) => this._onStdout(chunk));
|
|
88
|
+
child.on("exit", (code, signal) => this._onExit(code, signal));
|
|
89
|
+
}
|
|
90
|
+
_onExit(code, signal) {
|
|
91
|
+
// If we already nulled the child (clean shutdown, recycle, timeout
|
|
92
|
+
// path), this is a no-op — those paths already rejected callers.
|
|
93
|
+
if (!this.child)
|
|
94
|
+
return;
|
|
95
|
+
const reason = `adb shell for ${this.serial} exited (code=${code} signal=${signal}).`;
|
|
96
|
+
const failed = this.inFlight;
|
|
97
|
+
this.inFlight = null;
|
|
98
|
+
if (this.inFlightTimer) {
|
|
99
|
+
clearTimeout(this.inFlightTimer);
|
|
100
|
+
this.inFlightTimer = null;
|
|
101
|
+
}
|
|
102
|
+
if (failed) {
|
|
103
|
+
failed.reject(new FlingError("ADB_SHELL_DIED", reason));
|
|
104
|
+
}
|
|
105
|
+
this._recycle("ADB_SHELL_DIED", reason);
|
|
106
|
+
}
|
|
107
|
+
/** @internal — test seam. */
|
|
108
|
+
_currentChildForTest() {
|
|
109
|
+
return this.child;
|
|
110
|
+
}
|
|
111
|
+
_onStdout(chunk) {
|
|
112
|
+
this.buffer += chunk.toString();
|
|
113
|
+
const lines = this.buffer.split(/\n/);
|
|
114
|
+
this.buffer = lines.pop() ?? "";
|
|
115
|
+
for (const line of lines) {
|
|
116
|
+
const call = this.inFlight;
|
|
117
|
+
if (!call)
|
|
118
|
+
continue;
|
|
119
|
+
const m = this.matcher.matchLine(line, call.seq);
|
|
120
|
+
if (m.matched) {
|
|
121
|
+
this.inFlight = null;
|
|
122
|
+
if (this.inFlightTimer) {
|
|
123
|
+
clearTimeout(this.inFlightTimer);
|
|
124
|
+
this.inFlightTimer = null;
|
|
125
|
+
}
|
|
126
|
+
// The framing's printf prepends a literal \n so the sentinel lines
|
|
127
|
+
// up at column 0 even if the user's command emitted no trailing
|
|
128
|
+
// newline. That separator surfaces as a trailing empty entry in
|
|
129
|
+
// stdoutLines — discard it so we don't tack a spurious blank line
|
|
130
|
+
// onto every command's stdout.
|
|
131
|
+
if (call.stdoutLines.length > 0 &&
|
|
132
|
+
call.stdoutLines[call.stdoutLines.length - 1] === "") {
|
|
133
|
+
call.stdoutLines.pop();
|
|
134
|
+
}
|
|
135
|
+
const stdout = call.stdoutLines.length === 0
|
|
136
|
+
? ""
|
|
137
|
+
: call.stdoutLines.join("\n") + "\n";
|
|
138
|
+
call.resolve({ stdout, exitCode: m.exitCode });
|
|
139
|
+
this._pump();
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
call.stdoutLines.push(line);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
shutdown() {
|
|
147
|
+
this.shutDown = true;
|
|
148
|
+
if (this.child && !this.child.killed) {
|
|
149
|
+
this.child.kill();
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
const pool = new Map();
|
|
154
|
+
/**
|
|
155
|
+
* Lazily get-or-create the AdbShell for a device and exec a command on it.
|
|
156
|
+
* One persistent `adb -s <serial> shell` per device, shared across all
|
|
157
|
+
* tools that use this helper.
|
|
158
|
+
*/
|
|
159
|
+
export function shell(serial, cmd, opts) {
|
|
160
|
+
let s = pool.get(serial);
|
|
161
|
+
if (!s) {
|
|
162
|
+
s = new AdbShell(serial);
|
|
163
|
+
pool.set(serial, s);
|
|
164
|
+
}
|
|
165
|
+
return s.exec(cmd, opts);
|
|
166
|
+
}
|
|
167
|
+
/** Kill all live shells and clear the pool. Wired to process exit/SIGINT. */
|
|
168
|
+
export function shutdownPool() {
|
|
169
|
+
for (const s of pool.values())
|
|
170
|
+
s.shutdown();
|
|
171
|
+
pool.clear();
|
|
172
|
+
}
|
|
173
|
+
/** @internal — test-only hook to clear pool state between tests. */
|
|
174
|
+
export function _resetPoolForTests() {
|
|
175
|
+
pool.clear();
|
|
176
|
+
}
|
|
177
|
+
/** @internal — test-only hook to inspect the pool. */
|
|
178
|
+
export function _poolSizeForTests() {
|
|
179
|
+
return pool.size;
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=shellPool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shellPool.js","sourceRoot":"","sources":["../src/shellPool.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface ToolErrorResult {
|
|
2
|
+
[key: string]: unknown;
|
|
3
|
+
isError: true;
|
|
4
|
+
content: Array<{
|
|
5
|
+
type: "text";
|
|
6
|
+
text: string;
|
|
7
|
+
}>;
|
|
8
|
+
}
|
|
9
|
+
export declare function toolError(message: string): ToolErrorResult;
|
|
10
|
+
export declare function toolErrorFrom(err: unknown): ToolErrorResult;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { describeError } from "./errors.js";
|
|
2
|
+
export function toolError(message) {
|
|
3
|
+
return {
|
|
4
|
+
isError: true,
|
|
5
|
+
content: [{ type: "text", text: message }],
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
export function toolErrorFrom(err) {
|
|
9
|
+
return toolError(describeError(err));
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=toolResult.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolResult.js","sourceRoot":"","sources":["../src/toolResult.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAQ5C,MAAM,UAAU,SAAS,CAAC,OAAe;IACvC,OAAO;QACL,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;KAC3C,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAY;IACxC,OAAO,SAAS,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC;AACvC,CAAC"}
|