@tapflowio/ios-agent 0.30.0 → 0.31.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/bin/guest-helper +0 -0
- package/bin/screencapture-helper +0 -0
- package/dist/DeviceChromeLoader.d.ts +28 -1
- package/dist/DeviceChromeLoader.d.ts.map +1 -1
- package/dist/DeviceChromeLoader.js +118 -37
- package/dist/DeviceChromeLoader.js.map +1 -1
- package/dist/FoldableInput.d.ts +58 -0
- package/dist/FoldableInput.d.ts.map +1 -0
- package/dist/FoldableInput.js +166 -0
- package/dist/FoldableInput.js.map +1 -0
- package/dist/GuestHelper.d.ts +109 -0
- package/dist/GuestHelper.d.ts.map +1 -0
- package/dist/GuestHelper.js +437 -0
- package/dist/GuestHelper.js.map +1 -0
- package/dist/IOSAgent.d.ts +119 -2
- package/dist/IOSAgent.d.ts.map +1 -1
- package/dist/IOSAgent.js +586 -24
- package/dist/IOSAgent.js.map +1 -1
- package/dist/InputChannel.d.ts +38 -0
- package/dist/InputChannel.d.ts.map +1 -0
- package/dist/InputChannel.js +7 -0
- package/dist/InputChannel.js.map +1 -0
- package/dist/PanelState.d.ts +72 -0
- package/dist/PanelState.d.ts.map +1 -0
- package/dist/PanelState.js +192 -0
- package/dist/PanelState.js.map +1 -0
- package/dist/PhysicalOrientation.d.ts +58 -0
- package/dist/PhysicalOrientation.d.ts.map +1 -0
- package/dist/PhysicalOrientation.js +155 -0
- package/dist/PhysicalOrientation.js.map +1 -0
- package/dist/ScreenCaptureStreamer.d.ts +12 -1
- package/dist/ScreenCaptureStreamer.d.ts.map +1 -1
- package/dist/ScreenCaptureStreamer.js +28 -3
- package/dist/ScreenCaptureStreamer.js.map +1 -1
- package/dist/SimctlWrapper.d.ts +18 -1
- package/dist/SimctlWrapper.d.ts.map +1 -1
- package/dist/SimctlWrapper.js +43 -1
- package/dist/SimctlWrapper.js.map +1 -1
- package/dist/TouchHelper.d.ts +3 -2
- package/dist/TouchHelper.d.ts.map +1 -1
- package/dist/TouchHelper.js +4 -6
- package/dist/TouchHelper.js.map +1 -1
- package/dist/TypePanels.d.ts +33 -0
- package/dist/TypePanels.d.ts.map +1 -0
- package/dist/TypePanels.js +68 -0
- package/dist/TypePanels.js.map +1 -0
- package/dist/panels.d.ts +52 -0
- package/dist/panels.d.ts.map +1 -0
- package/dist/panels.js +68 -0
- package/dist/panels.js.map +1 -0
- package/package.json +6 -5
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
import { execFile, spawn } from 'child_process';
|
|
2
|
+
import { existsSync } from 'fs';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { promisify } from 'util';
|
|
5
|
+
import { createLogger } from '@tapflowio/agent-core';
|
|
6
|
+
const logger = createLogger('ios-agent:guest-helper');
|
|
7
|
+
const execFileAsync = promisify(execFile);
|
|
8
|
+
// `bin/guest-helper` runs INSIDE the simulator (an iphonesimulator executable), so it is started through
|
|
9
|
+
// `simctl spawn`, never directly. See `src/guest-helper.m` for its protocol and why it exists.
|
|
10
|
+
export const GUEST_HELPER_BINARY = join(import.meta.dirname, '..', 'bin', 'guest-helper');
|
|
11
|
+
// The same rolling window as TouchHelper, for the same reason it gives.
|
|
12
|
+
const RESPAWN_LIMIT = 3;
|
|
13
|
+
const RESPAWN_WINDOW_MS = 30_000;
|
|
14
|
+
// `ready` comes after `simctl spawn` has started the guest process, the helper has registered its
|
|
15
|
+
// services, and a 300 ms settle (a tap within 50 ms of registering is dropped, measured on Xcode 27.1).
|
|
16
|
+
// The spawn alone measured ~0.6–0.9 s. **The bound is for a wedge, not a slow Mac**: on an 8 GB Mac mini
|
|
17
|
+
// swapping 1.8 GB with a Duo up, the agent's own loop stalled 3.2 s, and an 8 s bound replaced three
|
|
18
|
+
// healthy-but-slow helpers in a row.
|
|
19
|
+
const READY_DEADLINE_MS = 15_000;
|
|
20
|
+
// A command the helper answers with `done`: the fold sweep plays inside the helper (0.8 s), a key is held
|
|
21
|
+
// for its own duration. Past this margin on top of that, the helper is treated as wedged and replaced —
|
|
22
|
+
// generous for the reason READY_DEADLINE_MS gives: a 5 s margin replaced a helper mid-stall.
|
|
23
|
+
const COMMAND_MARGIN_MS = 10_000;
|
|
24
|
+
// A fold's margin, longer: the sweep can sit blocked while the device changes panel. Measured on that Mac
|
|
25
|
+
// mini with a session streaming: a sweep went unanswered past 10.8 s although its panel lit at 10.6 s, so
|
|
26
|
+
// the helper was replaced just after it had folded the device — and the next press, landing while the new
|
|
27
|
+
// helper started, was refused. A late answer to a fold is harmless; it is what was asked for.
|
|
28
|
+
const HINGE_MARGIN_MS = 30_000;
|
|
29
|
+
const STOP_SIGKILL_AFTER_MS = 1_000;
|
|
30
|
+
export const defaultGuestHelperNative = {
|
|
31
|
+
spawn(udid, args) {
|
|
32
|
+
// Detached so a terminal's Ctrl-C, which signals the whole process group, cannot take `simctl spawn`
|
|
33
|
+
// down before the agent's own cleanup runs — the guest would then be orphaned with nobody left to
|
|
34
|
+
// know its pid.
|
|
35
|
+
return spawn('xcrun', ['simctl', 'spawn', udid, GUEST_HELPER_BINARY, ...args], {
|
|
36
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
37
|
+
detached: true,
|
|
38
|
+
});
|
|
39
|
+
},
|
|
40
|
+
async findOrphans(udid) {
|
|
41
|
+
// **Found by search, not by memory.** An agent killed with -9 restarts knowing no pids, and a
|
|
42
|
+
// `simctl spawn` that died alone leaves the guest running (measured) — a respawn would then register
|
|
43
|
+
// a second set of services on the same displays. The udid in argv is what makes the match ours.
|
|
44
|
+
const marker = `--udid ${udid}`;
|
|
45
|
+
let out;
|
|
46
|
+
try {
|
|
47
|
+
out = (await execFileAsync('/usr/bin/pgrep', ['-f', `guest-helper ${marker}`], { timeout: 5_000 })).stdout;
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return []; // pgrep exits 1 when nothing matches
|
|
51
|
+
}
|
|
52
|
+
const pids = [];
|
|
53
|
+
for (const pid of out.split('\n').map(Number).filter((n) => Number.isInteger(n) && n > 0 && n !== process.pid)) {
|
|
54
|
+
try {
|
|
55
|
+
const cmd = (await execFileAsync('/bin/ps', ['-o', 'command=', '-p', String(pid)], { timeout: 5_000 })).stdout;
|
|
56
|
+
if (cmd.includes(GUEST_HELPER_BINARY) && cmd.includes(marker))
|
|
57
|
+
pids.push(pid);
|
|
58
|
+
}
|
|
59
|
+
catch { /* gone between the two calls */ }
|
|
60
|
+
}
|
|
61
|
+
return pids;
|
|
62
|
+
},
|
|
63
|
+
killPid(pid, signal) {
|
|
64
|
+
try {
|
|
65
|
+
process.kill(pid, signal);
|
|
66
|
+
}
|
|
67
|
+
catch { /* already gone, or not ours */ }
|
|
68
|
+
},
|
|
69
|
+
async unavailableReason() {
|
|
70
|
+
if (!existsSync(GUEST_HELPER_BINARY))
|
|
71
|
+
return `${GUEST_HELPER_BINARY} is missing — reinstall @tapflowio/ios-agent`;
|
|
72
|
+
try {
|
|
73
|
+
await execFileAsync('xcrun', ['--find', 'devicectl'], { timeout: 10_000 });
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return 'devicectl was not found — install Xcode and select it with xcode-select';
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* The host side of `guest-helper`: one per multi-panel device, resident for the device's life.
|
|
83
|
+
*
|
|
84
|
+
* Its lifecycle follows TouchHelper's rules — readiness gates writes, a gesture belongs to the process
|
|
85
|
+
* that took its opening frame, deaths are replaced eagerly within a rolling budget — with three
|
|
86
|
+
* differences the guest process forces:
|
|
87
|
+
* - the process the agent spawns is `simctl spawn`, not the helper; the helper's own pid arrives on
|
|
88
|
+
* stdout and is killed separately, because the two do not die together;
|
|
89
|
+
* - earlier helpers for the same device are found with `pgrep` and killed before every spawn;
|
|
90
|
+
* - `fatal` is final: it means the runtime refused the private API, and spawning again would only
|
|
91
|
+
* hear the same answer.
|
|
92
|
+
*
|
|
93
|
+
* **Running out of the respawn budget is not final**, which is TouchHelper's rule too ("it self-clears,
|
|
94
|
+
* so a session that briefly could not start a helper is not left without input until the device is
|
|
95
|
+
* rebooted"). A first version made it final, and a Mac short of memory turned one slow minute into a
|
|
96
|
+
* device with no input for the rest of its boot. The helper waits for the window to clear and launches
|
|
97
|
+
* again, answering `starting` meanwhile.
|
|
98
|
+
*/
|
|
99
|
+
export class GuestHelper {
|
|
100
|
+
udid;
|
|
101
|
+
touchscreens;
|
|
102
|
+
native;
|
|
103
|
+
options;
|
|
104
|
+
proc = null;
|
|
105
|
+
guestPid = null;
|
|
106
|
+
gestureProc = null;
|
|
107
|
+
ready = false;
|
|
108
|
+
stopped = false;
|
|
109
|
+
unavailable = null;
|
|
110
|
+
fatalReason = null;
|
|
111
|
+
spawns = [];
|
|
112
|
+
pending = [];
|
|
113
|
+
readyTimer = null;
|
|
114
|
+
readyWaiters = [];
|
|
115
|
+
generation = 0;
|
|
116
|
+
// Set while waiting out the respawn window after the budget ran out; cleared by the launch it schedules.
|
|
117
|
+
cooldown = null;
|
|
118
|
+
// The reason the helper last went out of service, until a ready says it is back.
|
|
119
|
+
outage = null;
|
|
120
|
+
// Between `start()` (or a respawn) and the spawn: sweeping orphans and reading the panels. Input sent
|
|
121
|
+
// then is told to wait, not that the channel is gone.
|
|
122
|
+
launching = false;
|
|
123
|
+
/**
|
|
124
|
+
* `touchscreens` is asked on every launch, not once: display UUIDs change on every boot, and a respawn
|
|
125
|
+
* after the device rebooted under the agent must register the new ones.
|
|
126
|
+
*/
|
|
127
|
+
constructor(udid, touchscreens, native = defaultGuestHelperNative, options = {}) {
|
|
128
|
+
this.udid = udid;
|
|
129
|
+
this.touchscreens = touchscreens;
|
|
130
|
+
this.native = native;
|
|
131
|
+
this.options = options;
|
|
132
|
+
}
|
|
133
|
+
async start() {
|
|
134
|
+
this.stopped = false;
|
|
135
|
+
await this.launch();
|
|
136
|
+
}
|
|
137
|
+
stop() {
|
|
138
|
+
this.stopped = true;
|
|
139
|
+
this.launching = false;
|
|
140
|
+
if (this.cooldown) {
|
|
141
|
+
clearTimeout(this.cooldown);
|
|
142
|
+
this.cooldown = null;
|
|
143
|
+
}
|
|
144
|
+
this.generation++;
|
|
145
|
+
this.clearReadyDeadline();
|
|
146
|
+
this.failPending();
|
|
147
|
+
const proc = this.proc;
|
|
148
|
+
const guestPid = this.guestPid;
|
|
149
|
+
this.proc = null;
|
|
150
|
+
this.guestPid = null;
|
|
151
|
+
this.gestureProc = null;
|
|
152
|
+
this.ready = false;
|
|
153
|
+
this.settleReadyWaiters(false);
|
|
154
|
+
// EOF is the first line of defence (the helper exits on it, measured); the signals cover a helper
|
|
155
|
+
// that is wedged and a `simctl spawn` that outlives its child.
|
|
156
|
+
proc?.stdin?.end();
|
|
157
|
+
if (proc)
|
|
158
|
+
this.signalProcess(proc, 'SIGTERM');
|
|
159
|
+
if (guestPid)
|
|
160
|
+
this.native.killPid(guestPid, 'SIGTERM');
|
|
161
|
+
const timer = setTimeout(() => {
|
|
162
|
+
if (proc)
|
|
163
|
+
this.signalProcess(proc, 'SIGKILL');
|
|
164
|
+
if (guestPid)
|
|
165
|
+
this.native.killPid(guestPid, 'SIGKILL');
|
|
166
|
+
}, STOP_SIGKILL_AFTER_MS);
|
|
167
|
+
timer.unref?.();
|
|
168
|
+
}
|
|
169
|
+
inputState() {
|
|
170
|
+
if (this.proc && this.ready)
|
|
171
|
+
return 'ready';
|
|
172
|
+
if ((this.proc || this.launching || this.cooldown) && !this.unavailable)
|
|
173
|
+
return 'starting';
|
|
174
|
+
return 'unavailable';
|
|
175
|
+
}
|
|
176
|
+
/** Resolves true once the helper is ready, false if it becomes unavailable or is stopped first. */
|
|
177
|
+
whenReady() {
|
|
178
|
+
if (this.inputState() === 'ready')
|
|
179
|
+
return Promise.resolve(true);
|
|
180
|
+
if (this.unavailable || this.stopped)
|
|
181
|
+
return Promise.resolve(false);
|
|
182
|
+
return new Promise((resolve) => this.readyWaiters.push(resolve));
|
|
183
|
+
}
|
|
184
|
+
/** Why the helper cannot serve — for good, or for now — or null. */
|
|
185
|
+
unavailableReason() {
|
|
186
|
+
return this.unavailable ?? this.outage;
|
|
187
|
+
}
|
|
188
|
+
ownsGesture() {
|
|
189
|
+
return this.proc !== null && this.proc === this.gestureProc;
|
|
190
|
+
}
|
|
191
|
+
/** One finger on the panel whose display UUID is `screen`. Acked on the write, like Indigo: the helper
|
|
192
|
+
* answers a touch only when it fails, and a drag is too many lines a second to wait on. */
|
|
193
|
+
touch(screen, phase, x, y, edge) {
|
|
194
|
+
return this.gestureFrame(phase, `touch ${screen} ${phase} ${x} ${y} ${edge ? 1 : 0}`);
|
|
195
|
+
}
|
|
196
|
+
pinch(screen, phase, x1, y1, x2, y2) {
|
|
197
|
+
return this.gestureFrame(phase, `pinch ${screen} ${phase} ${x1} ${y1} ${x2} ${y2}`);
|
|
198
|
+
}
|
|
199
|
+
hinge(fromDeg, toDeg, durationMs) {
|
|
200
|
+
return this.command(`hinge ${fromDeg} ${toDeg} ${durationMs}`, durationMs, HINGE_MARGIN_MS);
|
|
201
|
+
}
|
|
202
|
+
orient(value) {
|
|
203
|
+
return this.command(`orient ${value}`, 0);
|
|
204
|
+
}
|
|
205
|
+
key(usagePage, usage, holdMs, modifiers = []) {
|
|
206
|
+
const mods = modifiers.map(([p, u]) => ` ${p} ${u}`).join('');
|
|
207
|
+
return this.command(`key ${usagePage} ${usage} ${holdMs}${mods}`, holdMs);
|
|
208
|
+
}
|
|
209
|
+
/** Half of a held press — a long-press lasts as long as the tester holds it, like TouchHelper's
|
|
210
|
+
* `pressButtonDown`/`Up`. */
|
|
211
|
+
keyDown(usagePage, usage) {
|
|
212
|
+
return this.command(`keydown ${usagePage} ${usage}`, 0);
|
|
213
|
+
}
|
|
214
|
+
keyUp(usagePage, usage) {
|
|
215
|
+
return this.command(`keyup ${usagePage} ${usage}`, 0);
|
|
216
|
+
}
|
|
217
|
+
gestureFrame(phase, line) {
|
|
218
|
+
if (phase === 'd') {
|
|
219
|
+
const sent = this.write(line);
|
|
220
|
+
// Only a delivered down owns the gesture — TouchHelper's `openGesture` explains why recording it
|
|
221
|
+
// unconditionally lets a fresh process receive an up for a touch it never saw.
|
|
222
|
+
this.gestureProc = sent ? this.proc : null;
|
|
223
|
+
return sent;
|
|
224
|
+
}
|
|
225
|
+
if (!this.ownsGesture())
|
|
226
|
+
return false;
|
|
227
|
+
return this.write(line);
|
|
228
|
+
}
|
|
229
|
+
command(line, playMs, marginMs = COMMAND_MARGIN_MS) {
|
|
230
|
+
const proc = this.proc;
|
|
231
|
+
if (!proc || !this.write(line))
|
|
232
|
+
return Promise.resolve(false);
|
|
233
|
+
return new Promise((resolve) => {
|
|
234
|
+
const timer = setTimeout(() => {
|
|
235
|
+
const at = this.pending.findIndex((p) => p.timer === timer);
|
|
236
|
+
if (at !== -1)
|
|
237
|
+
this.pending.splice(at, 1);
|
|
238
|
+
resolve(false);
|
|
239
|
+
if (this.proc !== proc)
|
|
240
|
+
return;
|
|
241
|
+
logger.error(`no answer to "${line}" within ${playMs + marginMs}ms — replacing the helper`);
|
|
242
|
+
// The guest would still act on a queued command after we gave up on it, so it goes, not only
|
|
243
|
+
// the simctl process that carries its pipe.
|
|
244
|
+
if (this.guestPid)
|
|
245
|
+
this.native.killPid(this.guestPid, 'SIGKILL');
|
|
246
|
+
this.signalProcess(proc, 'SIGKILL');
|
|
247
|
+
}, playMs + marginMs);
|
|
248
|
+
timer.unref?.();
|
|
249
|
+
this.pending.push({ resolve, timer });
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
write(line) {
|
|
253
|
+
if (this.inputState() !== 'ready')
|
|
254
|
+
return false;
|
|
255
|
+
this.proc?.stdin?.write(`${line}\n`);
|
|
256
|
+
return true;
|
|
257
|
+
}
|
|
258
|
+
async launch() {
|
|
259
|
+
const generation = ++this.generation;
|
|
260
|
+
this.launching = true;
|
|
261
|
+
let screens;
|
|
262
|
+
try {
|
|
263
|
+
for (const pid of await this.native.findOrphans(this.udid)) {
|
|
264
|
+
logger.warn(`killing a leftover guest-helper (pid ${pid}) for ${this.udid}`);
|
|
265
|
+
this.native.killPid(pid, 'SIGKILL');
|
|
266
|
+
}
|
|
267
|
+
screens = await this.touchscreens();
|
|
268
|
+
}
|
|
269
|
+
catch (e) {
|
|
270
|
+
if (generation === this.generation)
|
|
271
|
+
this.launching = false;
|
|
272
|
+
if (!this.stopped && generation === this.generation) {
|
|
273
|
+
// Not final: `simctl io enumerate` can fail while a busy Mac is still bringing the device up.
|
|
274
|
+
this.spawns.push(Date.now());
|
|
275
|
+
this.retryLater(`could not read the device's panels: ${e instanceof Error ? e.message : String(e)}`);
|
|
276
|
+
}
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
if (generation !== this.generation)
|
|
280
|
+
return;
|
|
281
|
+
this.launching = false;
|
|
282
|
+
if (this.stopped)
|
|
283
|
+
return;
|
|
284
|
+
this.spawns.push(Date.now());
|
|
285
|
+
this.ready = false;
|
|
286
|
+
this.guestPid = null;
|
|
287
|
+
const proc = this.native.spawn(this.udid, [
|
|
288
|
+
'--udid', this.udid, ...screens.flatMap((uuid) => ['--touchscreen', uuid]),
|
|
289
|
+
]);
|
|
290
|
+
// A pid is the only synchronous sign the exec happened — TouchHelper's `spawnHelper` has the measurement.
|
|
291
|
+
if (proc.pid === undefined) {
|
|
292
|
+
proc.on('error', (e) => logger.error(`spawn error: ${e.message}`));
|
|
293
|
+
this.proc = null;
|
|
294
|
+
this.becomeUnavailable('could not start guest-helper through simctl spawn');
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
this.proc = proc;
|
|
298
|
+
this.armReadyDeadline(proc);
|
|
299
|
+
let partial = '';
|
|
300
|
+
proc.stdout?.on('data', (d) => {
|
|
301
|
+
const lines = (partial + d.toString()).split('\n');
|
|
302
|
+
partial = lines.pop() ?? '';
|
|
303
|
+
for (const line of lines)
|
|
304
|
+
this.onLine(proc, line.trim());
|
|
305
|
+
});
|
|
306
|
+
proc.stderr?.on('data', (d) => logger.error(d.toString().trim()));
|
|
307
|
+
proc.on('exit', (code) => {
|
|
308
|
+
logger.warn(`guest-helper for ${this.udid} exited with code ${code ?? 'null'}`);
|
|
309
|
+
this.handleDeath(proc);
|
|
310
|
+
});
|
|
311
|
+
proc.on('error', (e) => {
|
|
312
|
+
logger.error(`spawn error: ${e.message}`);
|
|
313
|
+
this.handleDeath(proc);
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
onLine(proc, line) {
|
|
317
|
+
if (this.proc !== proc || !line)
|
|
318
|
+
return;
|
|
319
|
+
const [word, ...rest] = line.split(' ');
|
|
320
|
+
if (word === 'pid') {
|
|
321
|
+
const pid = Number(rest[0]);
|
|
322
|
+
if (Number.isInteger(pid) && pid > 0)
|
|
323
|
+
this.guestPid = pid;
|
|
324
|
+
}
|
|
325
|
+
else if (word === 'ready') {
|
|
326
|
+
this.ready = true;
|
|
327
|
+
this.clearReadyDeadline();
|
|
328
|
+
this.settleReadyWaiters(true);
|
|
329
|
+
if (this.outage) {
|
|
330
|
+
logger.info(`guest-helper back in service for ${this.udid}`);
|
|
331
|
+
this.outage = null;
|
|
332
|
+
this.options.onAvailable?.();
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
else if (word === 'done') {
|
|
336
|
+
this.pending.shift()?.resolve(rest[0] === '0');
|
|
337
|
+
}
|
|
338
|
+
else if (word === 'err') {
|
|
339
|
+
// A touch frame the guest refused. Touches are acked on the write, so this only gets logged.
|
|
340
|
+
logger.warn(`guest-helper refused: ${rest.slice(1).join(' ')} (status ${rest[0]})`);
|
|
341
|
+
}
|
|
342
|
+
else if (word === 'fatal') {
|
|
343
|
+
this.fatalReason = rest.join(' ') || 'guest-helper could not start';
|
|
344
|
+
this.becomeUnavailable(this.fatalReason);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
handleDeath(proc) {
|
|
348
|
+
if (this.proc !== proc)
|
|
349
|
+
return;
|
|
350
|
+
this.clearReadyDeadline();
|
|
351
|
+
this.failPending();
|
|
352
|
+
this.proc = null;
|
|
353
|
+
this.guestPid = null;
|
|
354
|
+
this.ready = false;
|
|
355
|
+
if (this.stopped || this.fatalReason)
|
|
356
|
+
return;
|
|
357
|
+
const now = Date.now();
|
|
358
|
+
this.spawns = this.spawns.filter((t) => now - t < RESPAWN_WINDOW_MS);
|
|
359
|
+
if (this.spawns.length >= RESPAWN_LIMIT) {
|
|
360
|
+
this.retryLater(`guest-helper died ${RESPAWN_LIMIT} times in ${RESPAWN_WINDOW_MS / 1000}s`);
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
void this.launch();
|
|
364
|
+
}
|
|
365
|
+
/** Out of service until the respawn window has room again, then launch. */
|
|
366
|
+
retryLater(reason) {
|
|
367
|
+
if (this.cooldown || this.stopped)
|
|
368
|
+
return;
|
|
369
|
+
const now = Date.now();
|
|
370
|
+
this.spawns = this.spawns.filter((t) => now - t < RESPAWN_WINDOW_MS);
|
|
371
|
+
const wait = this.spawns.length >= RESPAWN_LIMIT ? RESPAWN_WINDOW_MS - (now - this.spawns[0]) + 50 : 0;
|
|
372
|
+
logger.warn(`guest-helper out of service for ${this.udid}: ${reason} — trying again in ${Math.round(wait / 1000)}s`);
|
|
373
|
+
this.noteOutage(reason);
|
|
374
|
+
const timer = setTimeout(() => {
|
|
375
|
+
if (this.cooldown !== timer)
|
|
376
|
+
return;
|
|
377
|
+
this.cooldown = null;
|
|
378
|
+
if (!this.stopped)
|
|
379
|
+
void this.launch();
|
|
380
|
+
}, wait);
|
|
381
|
+
timer.unref?.();
|
|
382
|
+
this.cooldown = timer;
|
|
383
|
+
}
|
|
384
|
+
noteOutage(reason) {
|
|
385
|
+
if (this.outage)
|
|
386
|
+
return;
|
|
387
|
+
this.outage = reason;
|
|
388
|
+
this.options.onUnavailable?.(reason);
|
|
389
|
+
}
|
|
390
|
+
/** For good: the runtime refused the helper, or it could not be exec'd at all. */
|
|
391
|
+
becomeUnavailable(reason) {
|
|
392
|
+
if (this.unavailable)
|
|
393
|
+
return;
|
|
394
|
+
this.unavailable = reason;
|
|
395
|
+
this.ready = false;
|
|
396
|
+
this.settleReadyWaiters(false);
|
|
397
|
+
logger.error(`guest-helper unavailable for ${this.udid}: ${reason}`);
|
|
398
|
+
this.outage = null;
|
|
399
|
+
this.noteOutage(reason);
|
|
400
|
+
}
|
|
401
|
+
armReadyDeadline(proc) {
|
|
402
|
+
this.clearReadyDeadline();
|
|
403
|
+
const timer = setTimeout(() => {
|
|
404
|
+
if (this.proc !== proc || this.ready)
|
|
405
|
+
return;
|
|
406
|
+
logger.error(`no ready from guest-helper within ${READY_DEADLINE_MS}ms — replacing it`);
|
|
407
|
+
if (this.guestPid)
|
|
408
|
+
this.native.killPid(this.guestPid, 'SIGKILL');
|
|
409
|
+
this.signalProcess(proc, 'SIGKILL');
|
|
410
|
+
}, READY_DEADLINE_MS);
|
|
411
|
+
timer.unref?.();
|
|
412
|
+
this.readyTimer = timer;
|
|
413
|
+
}
|
|
414
|
+
clearReadyDeadline() {
|
|
415
|
+
if (this.readyTimer) {
|
|
416
|
+
clearTimeout(this.readyTimer);
|
|
417
|
+
this.readyTimer = null;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
failPending() {
|
|
421
|
+
for (const p of this.pending.splice(0)) {
|
|
422
|
+
clearTimeout(p.timer);
|
|
423
|
+
p.resolve(false);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
settleReadyWaiters(ok) {
|
|
427
|
+
for (const resolve of this.readyWaiters.splice(0))
|
|
428
|
+
resolve(ok);
|
|
429
|
+
}
|
|
430
|
+
/** `simctl spawn` was started detached, so it leads its own process group. */
|
|
431
|
+
signalProcess(proc, signal) {
|
|
432
|
+
if (proc.pid)
|
|
433
|
+
this.native.killPid(-proc.pid, signal);
|
|
434
|
+
proc.kill(signal);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
//# sourceMappingURL=GuestHelper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GuestHelper.js","sourceRoot":"","sources":["../src/GuestHelper.ts"],"names":[],"mappings":"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"}
|
package/dist/IOSAgent.d.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import type { Device, DeviceAgent, NetworkControlCapability, NetworkStatePayload, UIElement } from '@tapflowio/agent-core';
|
|
1
|
+
import type { Device, DeviceAgent, DevicePosture, NetworkControlCapability, NetworkStatePayload, PosturableAgent, UIElement } from '@tapflowio/agent-core';
|
|
2
2
|
import type { LaunchOptions } from '@tapflowio/protocol';
|
|
3
3
|
export declare const IOS_BUTTON_ALIASES: Record<string, string>;
|
|
4
4
|
import { type SleepBlocker } from '@tapflowio/agent-core/utils';
|
|
5
5
|
import { SimctlWrapper } from './SimctlWrapper.js';
|
|
6
6
|
import { SimulatorNetwork } from './SimulatorNetwork.js';
|
|
7
7
|
import { LeanStore } from './LeanStore.js';
|
|
8
|
+
import { type GuestHelperNative } from './GuestHelper.js';
|
|
9
|
+
import { PanelState } from './PanelState.js';
|
|
10
|
+
import { PhysicalOrientation } from './PhysicalOrientation.js';
|
|
8
11
|
import { DeviceChromeLoader } from './DeviceChromeLoader.js';
|
|
9
12
|
/** Lean mode needs an iOS runtime of 18.5 or later, where launchd honours the host-side overrides
|
|
10
13
|
* across reboots. tvOS, watchOS and visionOS devices come through the same list and are left alone. */
|
|
@@ -32,8 +35,25 @@ export interface IOSAgentOptions {
|
|
|
32
35
|
/** Device frame loading. Under vitest the default points at directories that do not exist, so a suite never
|
|
33
36
|
* reads the developer's Xcode chrome or spends seconds rendering it. */
|
|
34
37
|
chromeLoader?: DeviceChromeLoader;
|
|
38
|
+
/** Which panel a multi-panel device shows (devicectl). Injectable so a suite never runs devicectl. */
|
|
39
|
+
panelState?: PanelState;
|
|
40
|
+
/** Which way a multi-panel device is held (devicectl). Injectable for the same reason. */
|
|
41
|
+
physicalOrientation?: PhysicalOrientation;
|
|
42
|
+
/** How a multi-panel device's in-simulator helper is spawned and found. Injectable for the same reason. */
|
|
43
|
+
guestHelperNative?: GuestHelperNative;
|
|
44
|
+
/** How long a fold may take to light its panel before it counts as failed. Injectable so a suite does not
|
|
45
|
+
* wait the real 10 s on the path where it never does. */
|
|
46
|
+
foldSettleMs?: number;
|
|
47
|
+
/** How often a multi-panel device's lit panel is read while a session is on it, to follow a fold made
|
|
48
|
+
* outside tapflow (DeviceHub). Injectable for the same reason. */
|
|
49
|
+
panelPollMs?: number;
|
|
50
|
+
/** The same, once nothing has moved for `panelQuietMs`. Injectable for the same reason. */
|
|
51
|
+
panelIdlePollMs?: number;
|
|
52
|
+
panelQuietMs?: number;
|
|
53
|
+
/** How long a boot waits for a multi-panel device's helper to be ready. Injectable for the same reason. */
|
|
54
|
+
helperBootReadyMs?: number;
|
|
35
55
|
}
|
|
36
|
-
export declare class IOSAgent implements DeviceAgent, NetworkControlCapability {
|
|
56
|
+
export declare class IOSAgent implements DeviceAgent, NetworkControlCapability, PosturableAgent {
|
|
37
57
|
private readonly simctl;
|
|
38
58
|
private readonly network;
|
|
39
59
|
private readonly fps;
|
|
@@ -97,6 +117,24 @@ export declare class IOSAgent implements DeviceAgent, NetworkControlCapability {
|
|
|
97
117
|
*/
|
|
98
118
|
private readonly ownedDevices;
|
|
99
119
|
private lastBundleIds;
|
|
120
|
+
private multiPanelDevices;
|
|
121
|
+
private deviceTypeIds;
|
|
122
|
+
private readonly guests;
|
|
123
|
+
private readonly guestScreens;
|
|
124
|
+
private readonly panelState;
|
|
125
|
+
private readonly physical;
|
|
126
|
+
private readonly typePanels;
|
|
127
|
+
private readonly guestHelperNative;
|
|
128
|
+
private readonly foldSettleMs;
|
|
129
|
+
private readonly panelPollMs;
|
|
130
|
+
private readonly panelIdlePollMs;
|
|
131
|
+
private readonly panelQuietMs;
|
|
132
|
+
private readonly helperBootReadyMs;
|
|
133
|
+
private readonly panelPolls;
|
|
134
|
+
private readonly panelActivity;
|
|
135
|
+
private readonly panelRechecks;
|
|
136
|
+
private readonly posturing;
|
|
137
|
+
private readonly reportedPosture;
|
|
100
138
|
private readonly uiTreeReader;
|
|
101
139
|
private readonly sleepBlocker;
|
|
102
140
|
/** What the next "relay disconnected" line reports: when the relay last pinged, and the socket's last error. */
|
|
@@ -202,6 +240,85 @@ export declare class IOSAgent implements DeviceAgent, NetworkControlCapability {
|
|
|
202
240
|
*/
|
|
203
241
|
private clearPasteboardQueued;
|
|
204
242
|
private ensureTouchHelper;
|
|
243
|
+
/**
|
|
244
|
+
* **The one place a device's input path is chosen** (see `InputChannel`). A device with more than one
|
|
245
|
+
* integrated panel gets `FoldableInput` over its in-simulator helper; every other device gets the Indigo
|
|
246
|
+
* `TouchHelper` it always had. A multi-panel device is never given a `TouchHelper`: its writes would
|
|
247
|
+
* answer success and land on a dark panel or nowhere.
|
|
248
|
+
*/
|
|
249
|
+
private createInputChannel;
|
|
250
|
+
private ensureGuest;
|
|
251
|
+
/** The lit panel of a multi-panel device, from the last devicectl reading and this boot's panels. */
|
|
252
|
+
private litPanel;
|
|
253
|
+
/**
|
|
254
|
+
* How far the viewer turns a multi-panel device (`ChromeData.streamRotation`): the way it is held, plus the
|
|
255
|
+
* lit panel's own native turn — the Duo's unfolded panel is drawn turned 270, so a device held upright
|
|
256
|
+
* shows it turned 90 (measured: portrait → rot90 … landscapeLeft → rot0). Undefined for a single-panel
|
|
257
|
+
* device, and until both the orientation and the lit panel have been read.
|
|
258
|
+
*/
|
|
259
|
+
private chromeRotation;
|
|
260
|
+
/** The cached frame with this send's turn and scale — never written into the loader's shared object. */
|
|
261
|
+
private forViewer;
|
|
262
|
+
/** The lit panel's frame for `DeviceChromeLoader`, or undefined for a single-panel device or an unknown panel. */
|
|
263
|
+
private chromePanel;
|
|
264
|
+
/** Point every stream of this device at its lit panel, and give its viewers that panel's frame. */
|
|
265
|
+
private applyLitPanel;
|
|
266
|
+
/**
|
|
267
|
+
* Load the lit panel's frame and send it as `session:chrome` to every session on this device whose frame
|
|
268
|
+
* it is not already. `session:chrome` is re-sendable by contract (protocol `InputPosture`), and the relay
|
|
269
|
+
* caches the last one for a re-joining viewer.
|
|
270
|
+
*/
|
|
271
|
+
private resendChrome;
|
|
272
|
+
/** The display UUID of the panel a multi-panel device is showing, or null if not known yet. */
|
|
273
|
+
private litScreen;
|
|
274
|
+
/**
|
|
275
|
+
* Follow a fold made outside tapflow (DeviceHub's picker) while a session is on the device: read the lit
|
|
276
|
+
* panel, re-point the capture and the frame, and report the posture if it moved. Skipped while tapflow's own
|
|
277
|
+
* fold is in flight, which reports for itself.
|
|
278
|
+
*/
|
|
279
|
+
private startPanelPoll;
|
|
280
|
+
private schedulePanelPoll;
|
|
281
|
+
/** The device's panel or orientation is moving, or about to: the poll goes back to its fast rate now, not
|
|
282
|
+
* after the slow wait already scheduled. */
|
|
283
|
+
private panelMoved;
|
|
284
|
+
private followPanel;
|
|
285
|
+
/** The device's teardown: shut down, erased, or the agent leaving. Not a relay reconnect — see `guests`. */
|
|
286
|
+
private stopGuest;
|
|
287
|
+
listPostures(deviceId: string): Promise<DevicePosture[]>;
|
|
288
|
+
getPosture(deviceId: string): Promise<DevicePosture | null>;
|
|
289
|
+
setPosture(deviceId: string, postureId: string): Promise<void>;
|
|
290
|
+
/**
|
|
291
|
+
* Turn a multi-panel device the way it is held, through the helper (Purple and `devicectl orientation set`
|
|
292
|
+
* do nothing on the Duo — measured). From the orientation read back now, never one remembered: a quarter
|
|
293
|
+
* turn `direction`, or an older viewer's `target` — where either landscape meets landscape, so asking for
|
|
294
|
+
* it never flips one into the other, and portrait means upright. Then waits for devicectl to say so, which
|
|
295
|
+
* is what the re-sent chrome reports; a turn that does not land is logged and the chrome says where the
|
|
296
|
+
* device really is.
|
|
297
|
+
*/
|
|
298
|
+
private turnHeld;
|
|
299
|
+
/**
|
|
300
|
+
* Where a single-panel device is held: read (devicectl on Xcode 27, the guest helper before — see
|
|
301
|
+
* `defaultPhysicalOrientationNative`), else the last known — the last reading, or what tapflow last set on a
|
|
302
|
+
* host where neither source answers. Read every time, never marked unreadable: one failure right after a
|
|
303
|
+
* boot would otherwise have left the device on memory for the life of the agent (review finding).
|
|
304
|
+
*/
|
|
305
|
+
private heldSingle;
|
|
306
|
+
/** Turn a device nobody can say the orientation of upright, so there is one to turn from. */
|
|
307
|
+
private standUp;
|
|
308
|
+
/**
|
|
309
|
+
* Turn a single-panel device, through Purple: a quarter turn `direction` from where it is held, or an older
|
|
310
|
+
* viewer's `target`. **That viewer draws landscape as 270**, so `landscape` means exactly `landscapeLeft` —
|
|
311
|
+
* the other landscape would show it upside down — and is met only there; `portrait` means upright. A device
|
|
312
|
+
* whose orientation cannot be read or remembered (an agent restarted under it) is stood up first.
|
|
313
|
+
*/
|
|
314
|
+
private turnSingle;
|
|
315
|
+
/** Re-send the frame each session on this device already has, with the turn it is held at now. */
|
|
316
|
+
private resendTurn;
|
|
317
|
+
/** `closed` while the cover is lit, `open` while the unfolded panel is. */
|
|
318
|
+
private postureOf;
|
|
319
|
+
/** Tell the viewer which postures exist and which one the device is in — read from the device, so a fold
|
|
320
|
+
* made outside tapflow shows too. Sent at boot, after a change (failed or not), and on the helper dying. */
|
|
321
|
+
private sendPostures;
|
|
205
322
|
private readonly clipboardQueue;
|
|
206
323
|
private readonly parkedSentinels;
|
|
207
324
|
private markSentinel;
|
package/dist/IOSAgent.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IOSAgent.d.ts","sourceRoot":"","sources":["../src/IOSAgent.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAA4C,MAAM,EAAE,WAAW,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"IOSAgent.d.ts","sourceRoot":"","sources":["../src/IOSAgent.ts"],"names":[],"mappings":"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"}
|