@tapflowio/ios-agent 0.17.0 → 0.19.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.
@@ -1,100 +1,144 @@
1
1
  import { spawn } from 'child_process';
2
2
  import { join } from 'path';
3
3
  import { createLogger } from '@tapflowio/agent-core';
4
+ import { killWithSigkillFallback } from './childProcessKill.js';
4
5
  const logger = createLogger('ios-agent:touch-helper');
5
6
  const BINARY = join(import.meta.dirname, '..', 'bin', 'touch-helper');
7
+ // At most this many spawns in any window of this length. A rolling window rather than a count
8
+ // of consecutive failures: the helper's start-up is expensive (a subprocess, two dlopens, a
9
+ // device lookup), so "it failed quickly" cannot be told apart from "it failed slowly" without
10
+ // guessing how long start-up takes — and a helper that reliably dies just after that guess would
11
+ // reset a consecutive counter forever and churn processes for the life of the agent. A window
12
+ // bounds it whatever the lifetime, and it self-clears, so a session that briefly could not start
13
+ // a helper is not stuck without input until the device is rebooted.
14
+ const RESPAWN_LIMIT = 3;
15
+ const RESPAWN_WINDOW_MS = 30_000;
16
+ // The helper announces itself on stderr once it holds its HID client and is about to start
17
+ // reading stdin (`touch-helper.swift:281`). Measured against a real simulator: 186–247ms after
18
+ // spawn (n=5), and a gesture written before it lands *nothing* — the frames are buffered by the
19
+ // pipe and then drained in one go, which collapses a swipe into microseconds and iOS reads it as
20
+ // no gesture at all. So "the pipe is open" is not the same as "the device will act on this", and
21
+ // reporting the first as success is the same lie as #482 in a narrower window.
22
+ const READY_MARKER = 'touch-helper ready';
23
+ // A helper that wedges *before* announcing would otherwise never be replaced: it is running, so
24
+ // nothing asks for a new one, and it is not ready, so every input is refused — honestly, but
25
+ // forever. The announcement comes after a device lookup through CoreSimulator, which is where a
26
+ // wedge would sit. Measured start-up is 186–247ms, so this is roughly twenty times the worst case
27
+ // observed rather than a tight bound.
28
+ const READY_DEADLINE_MS = 5_000;
6
29
  export class TouchHelper {
7
30
  udid;
8
31
  proc = null;
32
+ // The process that received the current gesture's opening frame. Mid-gesture frames are only
33
+ // meaningful to that one, so they are checked against it rather than against liveness alone.
34
+ gestureProc = null;
9
35
  lastX = 0;
10
36
  lastY = 0;
37
+ stopped = false;
38
+ ready = false;
39
+ readyTimer = null;
40
+ spawns = [];
11
41
  constructor(udid) {
12
42
  this.udid = udid;
13
43
  }
14
44
  start() {
15
- const bin = BINARY;
16
- this.proc = spawn(bin, [this.udid], { stdio: ['pipe', 'ignore', 'pipe'] });
17
- this.proc.stderr?.on('data', (d) => {
18
- const msg = d.toString().trim();
19
- // print all lines, even debug: lines, until we're confident it's working
20
- logger.error(msg);
21
- });
22
- this.proc.on('exit', (code) => {
23
- logger.error(`exited with code ${code ?? 'null'}`);
24
- });
25
- this.proc.on('error', (e) => {
26
- logger.error(`spawn error: ${e.message}`);
27
- });
45
+ this.stopped = false;
46
+ this.spawnHelper();
28
47
  }
29
48
  stop() {
30
- this.proc?.kill();
49
+ this.stopped = true;
50
+ this.clearReadyDeadline();
51
+ killWithSigkillFallback(this.proc);
31
52
  this.proc = null;
53
+ this.gestureProc = null;
54
+ }
55
+ // Whether an input written right now actually reaches the device. Two conditions, and they are
56
+ // deliberately not the same question as `isRunning()`: a helper that is still starting up is
57
+ // very much alive and must not be replaced, but a frame written to it is dropped on the floor.
58
+ isReady() {
59
+ return this.isRunning() && this.ready;
60
+ }
61
+ // Whether the helper process exists with an open pipe — the question a *replacement* decision
62
+ // asks. `this.proc` only ever holds a process that execed (`spawnHelper` is the gate), so from
63
+ // here on stdin closing is what death looks like.
64
+ isRunning() {
65
+ return this.proc?.stdin?.writable === true;
66
+ }
67
+ /**
68
+ * Why a write would be refused right now, for the ack to report.
69
+ *
70
+ * `starting` is the state that had no name: measured 186–247ms after spawn, the pipe is open and
71
+ * frames written to it land nowhere, and a caller that retries a moment later succeeds. Answering
72
+ * "no channel" for it — which is what a bare boolean forced — told the caller to reconnect when it
73
+ * should simply have waited.
74
+ *
75
+ * Safe to read at the ack site rather than inside the write: writes here are synchronous, so
76
+ * nothing can have changed between the two.
77
+ */
78
+ inputState() {
79
+ if (this.isReady())
80
+ return 'ready';
81
+ return this.isRunning() ? 'starting' : 'unavailable';
82
+ }
83
+ /**
84
+ * Whether a gesture is currently owned by the live process — i.e. whether a continuation frame
85
+ * could land at all.
86
+ *
87
+ * Separate from `inputState()` because the two answer questions decided at different times.
88
+ * Readiness is about now; ownership was decided when the opening frame was written. A gesture whose
89
+ * open was refused (during the start-up window, say) leaves nothing owned, and no amount of waiting
90
+ * makes its terminal frame deliverable — the caller has to open a new gesture. Reading readiness
91
+ * alone at the ack site turned that into "the message is malformed, never retry".
92
+ */
93
+ ownsGesture() {
94
+ return this.proc !== null && this.proc === this.gestureProc;
32
95
  }
33
96
  touchStart(x, y) {
34
97
  this.lastX = x;
35
98
  this.lastY = y;
36
- this.write(1, x, y);
99
+ return this.openGesture(this.coordFrame(1, x, y));
37
100
  }
38
101
  touchMove(x, y) {
39
102
  this.lastX = x;
40
103
  this.lastY = y;
41
- this.write(2, x, y);
104
+ return this.continueGesture(this.coordFrame(2, x, y));
42
105
  }
43
106
  touchEnd() {
44
- this.write(3, this.lastX, this.lastY);
107
+ return this.continueGesture(this.coordFrame(3, this.lastX, this.lastY));
45
108
  }
46
109
  pressButton(usagePage, usage) {
47
- if (!this.proc?.stdin?.writable)
48
- return;
49
- const buf = Buffer.allocUnsafe(9);
50
- buf.writeUInt8(4, 0);
51
- buf.writeUInt32BE(usagePage, 1);
52
- buf.writeUInt32BE(usage, 5);
53
- this.proc.stdin.write(buf);
110
+ return this.sendSelfContained(this.buttonFrame(4, usagePage, usage));
54
111
  }
55
112
  // Real-time button hold: down + up sent as separate frames so the hold lasts as long as
56
113
  // the user holds the button in the dashboard (e.g. Action button long-press). type 4 above
57
114
  // remains the fixed short-press path.
58
- writeButtonOp(type, usagePage, usage) {
59
- if (!this.proc?.stdin?.writable)
60
- return;
61
- const buf = Buffer.allocUnsafe(9);
62
- buf.writeUInt8(type, 0);
63
- buf.writeUInt32BE(usagePage, 1);
64
- buf.writeUInt32BE(usage, 5);
65
- this.proc.stdin.write(buf);
66
- }
67
115
  pressButtonDown(usagePage, usage) {
68
- this.writeButtonOp(10, usagePage, usage);
116
+ return this.sendSelfContained(this.buttonFrame(10, usagePage, usage));
69
117
  }
118
+ // Self-contained despite being the tail of a pair: the helper keeps no record of which
119
+ // buttons are down (`touch-helper.swift` sends one op per frame), so a fresh process serves
120
+ // this exactly as the old one would have. Refusing it would be worse — a `down` that reached
121
+ // a live helper could then never be released.
70
122
  pressButtonUp(usagePage, usage) {
71
- this.writeButtonOp(11, usagePage, usage);
123
+ return this.sendSelfContained(this.buttonFrame(11, usagePage, usage));
72
124
  }
73
125
  // Legacy path for home (code=0) and lock (code=1) buttons
74
126
  pressLegacyButton(code) {
75
- if (!this.proc?.stdin?.writable)
76
- return;
77
- const buf = Buffer.allocUnsafe(9);
78
- buf.writeUInt8(5, 0);
79
- buf.writeUInt32BE(code, 1);
80
- buf.writeUInt32BE(0, 5);
81
- this.proc.stdin.write(buf);
127
+ return this.sendSelfContained(this.buttonFrame(5, code, 0));
82
128
  }
83
129
  pinchStart(x1, y1, x2, y2) {
84
- this.writeTwoFinger(6, x1, y1, x2, y2);
130
+ return this.openGesture(this.twoFingerFrame(6, x1, y1, x2, y2));
85
131
  }
86
132
  pinchMove(x1, y1, x2, y2) {
87
- this.writeTwoFinger(7, x1, y1, x2, y2);
133
+ return this.continueGesture(this.twoFingerFrame(7, x1, y1, x2, y2));
88
134
  }
89
135
  pinchEnd() {
90
- this.writeTwoFinger(8, 0, 0, 0, 0);
136
+ return this.continueGesture(this.twoFingerFrame(8, 0, 0, 0, 0));
91
137
  }
92
138
  // HID keyboard — type 9 frame: [9][modifiers][pad x3][usage:u32BE]
93
139
  // modifiers: USB HID modifier bitmap (0x01=LeftCtrl, 0x02=LeftShift, 0x04=LeftAlt, 0x08=LeftMeta, …)
94
140
  // usage: keyboard usage code from HID Keyboard/Keypad page (0x07)
95
141
  sendKey(usage, modifiers = 0) {
96
- if (!this.proc?.stdin?.writable)
97
- return;
98
142
  const buf = Buffer.allocUnsafe(9);
99
143
  buf.writeUInt8(9, 0);
100
144
  buf.writeUInt8(modifiers, 1);
@@ -102,27 +146,161 @@ export class TouchHelper {
102
146
  buf.writeUInt8(0, 3);
103
147
  buf.writeUInt8(0, 4);
104
148
  buf.writeUInt32BE(usage, 5);
105
- this.proc.stdin.write(buf);
149
+ return this.sendSelfContained(buf);
106
150
  }
107
- writeTwoFinger(type, x1, y1, x2, y2) {
108
- if (!this.proc?.stdin?.writable)
109
- return;
151
+ coordFrame(type, x, y) {
152
+ const buf = Buffer.allocUnsafe(9);
153
+ buf.writeUInt8(type, 0);
154
+ buf.writeFloatBE(x, 1);
155
+ buf.writeFloatBE(y, 5);
156
+ return buf;
157
+ }
158
+ buttonFrame(type, a, b) {
159
+ const buf = Buffer.allocUnsafe(9);
160
+ buf.writeUInt8(type, 0);
161
+ buf.writeUInt32BE(a, 1);
162
+ buf.writeUInt32BE(b, 5);
163
+ return buf;
164
+ }
165
+ twoFingerFrame(type, x1, y1, x2, y2) {
110
166
  const buf = Buffer.allocUnsafe(17);
111
167
  buf.writeUInt8(type, 0);
112
168
  buf.writeFloatBE(x1, 1);
113
169
  buf.writeFloatBE(y1, 5);
114
170
  buf.writeFloatBE(x2, 9);
115
171
  buf.writeFloatBE(y2, 13);
116
- this.proc.stdin.write(buf);
172
+ return buf;
173
+ }
174
+ // Frames that carry their whole payload: a dead helper is replaced before the frame goes out,
175
+ // so input recovers rather than staying dead for the rest of the session (#482).
176
+ sendSelfContained(buf) {
177
+ // `isRunning`, not `isReady`: replacing a helper that is merely still starting up would spawn
178
+ // a second one, burn the window budget, and make the wait longer rather than shorter.
179
+ if (!this.isRunning())
180
+ this.respawn();
181
+ return this.send(buf);
182
+ }
183
+ // A gesture's opening frame. Self-contained, and it records which process is serving the
184
+ // gesture so the frames that follow can be held to it.
185
+ openGesture(buf) {
186
+ const sent = this.sendSelfContained(buf);
187
+ // Only a *delivered* open owns the gesture. Recording unconditionally looks equivalent and is
188
+ // not: during the start-up window the open is refused while `this.proc` is a healthy process
189
+ // that becomes ready ~200ms later, so identity would then pass and the rest of the gesture
190
+ // would reach a process that never received the down — a release at (0,0) reported as
191
+ // delivered, which is the exact defect this guard exists to prevent.
192
+ this.gestureProc = sent ? this.proc : null;
193
+ return sent;
194
+ }
195
+ // Everything after the opening frame. These are meaningless to any other process: types 3 and
196
+ // 8 inject coordinate latches the helper accumulated (`lastX/lastY`, `pinchLast*`) — a pinch
197
+ // end's own coordinates are all zero for exactly that reason — and a type 2 or 7 move with no
198
+ // preceding down is not the gesture the tester made.
199
+ //
200
+ // Checking liveness is not enough. Replacement is eager, so by the time a terminal frame
201
+ // arrives after a mid-gesture death there is usually a healthy process to write to, and a
202
+ // fresh one has those latches at zero: the tap would be released at (0,0) and reported as
203
+ // delivered. Identity is what the guard has to be about.
204
+ continueGesture(buf) {
205
+ if (this.proc === null || this.proc !== this.gestureProc)
206
+ return false;
207
+ return this.send(buf);
117
208
  }
118
- write(type, x, y) {
119
- if (!this.proc?.stdin?.writable)
209
+ send(buf) {
210
+ if (!this.isReady())
211
+ return false;
212
+ // A `false` from write() is backpressure: node buffers the frame and flushes it when the
213
+ // pipe drains, so it does not mean the input was dropped.
214
+ this.proc?.stdin?.write(buf);
215
+ return true;
216
+ }
217
+ armReadyDeadline(proc) {
218
+ this.clearReadyDeadline();
219
+ const timer = setTimeout(() => {
220
+ if (this.proc !== proc || this.ready)
221
+ return;
222
+ logger.error(`no readiness announcement within ${READY_DEADLINE_MS}ms — replacing the helper`);
223
+ killWithSigkillFallback(proc);
224
+ // Through the same path as a real death, so the replacement is subject to the same window.
225
+ this.handleDeath(proc);
226
+ }, READY_DEADLINE_MS);
227
+ timer.unref?.();
228
+ this.readyTimer = timer;
229
+ }
230
+ clearReadyDeadline() {
231
+ if (this.readyTimer) {
232
+ clearTimeout(this.readyTimer);
233
+ this.readyTimer = null;
234
+ }
235
+ }
236
+ respawn() {
237
+ if (this.stopped)
120
238
  return;
121
- const buf = Buffer.allocUnsafe(9);
122
- buf.writeUInt8(type, 0);
123
- buf.writeFloatBE(x, 1);
124
- buf.writeFloatBE(y, 5);
125
- this.proc.stdin.write(buf);
239
+ const now = Date.now();
240
+ this.spawns = this.spawns.filter((t) => now - t < RESPAWN_WINDOW_MS);
241
+ if (this.spawns.length >= RESPAWN_LIMIT)
242
+ return;
243
+ this.spawnHelper();
244
+ }
245
+ spawnHelper() {
246
+ const proc = spawn(BINARY, [this.udid], { stdio: ['pipe', 'ignore', 'pipe'] });
247
+ this.spawns.push(Date.now());
248
+ this.ready = false;
249
+ // The one place that decides whether a spawn counts as a helper, and it has to decide
250
+ // synchronously: the frame that triggered this spawn is written immediately after.
251
+ //
252
+ // A pid is the only signal available that early. When the exec fails — binary missing, no
253
+ // execute bit, wrong architecture (#464) — libuv still hands back an open stdin pipe and
254
+ // reports the failure on a LATER tick. Measured against a real spawn of a nonexistent path,
255
+ // `stdin.writable` is `true` on a process that does not exist, and `stdin.write()` returning
256
+ // `false` is indistinguishable from ordinary backpressure on a healthy helper. A pid is
257
+ // assigned only once the exec succeeded.
258
+ if (proc.pid === undefined) {
259
+ proc.on('error', (e) => logger.error(`spawn error: ${e.message}`));
260
+ this.proc = null;
261
+ return;
262
+ }
263
+ this.proc = proc;
264
+ this.armReadyDeadline(proc);
265
+ // Cap what is retained: the marker is short, and a helper that never announces itself can
266
+ // still emit warnings indefinitely.
267
+ let tail = '';
268
+ proc.stderr?.on('data', (d) => {
269
+ const msg = d.toString();
270
+ // Guarded on identity so a superseded process's late announcement cannot mark a newer one
271
+ // ready.
272
+ if (!this.ready && this.proc === proc) {
273
+ const seen = tail + msg;
274
+ if (seen.includes(READY_MARKER)) {
275
+ this.ready = true;
276
+ tail = '';
277
+ this.clearReadyDeadline();
278
+ // Retain only enough to rejoin a marker split across two chunks.
279
+ }
280
+ else
281
+ tail = seen.slice(-READY_MARKER.length);
282
+ }
283
+ // print all lines, even debug: lines, until we're confident it's working
284
+ logger.error(msg.trim());
285
+ });
286
+ proc.on('exit', (code) => {
287
+ logger.error(`exited with code ${code ?? 'null'}`);
288
+ this.handleDeath(proc);
289
+ });
290
+ proc.on('error', (e) => {
291
+ logger.error(`spawn error: ${e.message}`);
292
+ this.handleDeath(proc);
293
+ });
294
+ }
295
+ // Replace the helper as soon as it dies rather than on the next input. Waiting would make
296
+ // the first tap after a death pay the whole start-up cost (xcode-select, two dlopens, a
297
+ // device lookup), and that tap is the one the tester is watching.
298
+ handleDeath(proc) {
299
+ if (this.proc !== proc)
300
+ return; // superseded by a newer spawn, or stop() already cleared it
301
+ this.clearReadyDeadline();
302
+ this.proc = null;
303
+ this.respawn();
126
304
  }
127
305
  }
128
306
  //# sourceMappingURL=TouchHelper.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TouchHelper.js","sourceRoot":"","sources":["../src/TouchHelper.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TouchHelper.js","sourceRoot":"","sources":["../src/TouchHelper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ChildProcess } from 'child_process';
2
+ export declare function killWithSigkillFallback(proc: ChildProcess | null, timeoutMs?: number): void;
3
+ //# sourceMappingURL=childProcessKill.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"childProcessKill.d.ts","sourceRoot":"","sources":["../src/childProcessKill.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAMjD,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,EAAE,SAAS,SAAO,GAAG,IAAI,CAWzF"}
@@ -0,0 +1,19 @@
1
+ // SIGKILL fallback if SIGTERM did not take — shared by TouchHelper and KeyboardHelperDaemon,
2
+ // which spawn non-detached helper processes (plain kill(), not a process group).
3
+ // ScreenCaptureStreamer / XCUITreeReader use their own variant (different timeout, and
4
+ // XCUITreeReader kills a process group) and are intentionally not folded into this helper.
5
+ export function killWithSigkillFallback(proc, timeoutMs = 1000) {
6
+ if (!proc)
7
+ return;
8
+ // kill() returns false when the signal can't be delivered (e.g. already exited) — don't
9
+ // arm the fallback in that case, or it fires later against a possibly-reused pid: 'exit'
10
+ // already happened, so a once('exit', ...) attached now would never see it and clear it.
11
+ if (!proc.kill('SIGTERM'))
12
+ return;
13
+ const killTimer = setTimeout(() => proc.kill('SIGKILL'), timeoutMs);
14
+ killTimer.unref?.();
15
+ const clear = () => clearTimeout(killTimer);
16
+ proc.once('exit', clear);
17
+ proc.once('error', clear);
18
+ }
19
+ //# sourceMappingURL=childProcessKill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"childProcessKill.js","sourceRoot":"","sources":["../src/childProcessKill.ts"],"names":[],"mappings":"AAEA,6FAA6F;AAC7F,iFAAiF;AACjF,uFAAuF;AACvF,2FAA2F;AAC3F,MAAM,UAAU,uBAAuB,CAAC,IAAyB,EAAE,SAAS,GAAG,IAAI;IACjF,IAAI,CAAC,IAAI;QAAE,OAAM;IACjB,wFAAwF;IACxF,yFAAyF;IACzF,yFAAyF;IACzF,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC;QAAE,OAAM;IACjC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC,CAAA;IACnE,SAAS,CAAC,KAAK,EAAE,EAAE,CAAA;IACnB,MAAM,KAAK,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,CAAA;IAC3C,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;IACxB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;AAC3B,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tapflowio/ios-agent",
3
- "version": "0.17.0",
3
+ "version": "0.19.0",
4
4
  "description": "iOS simulator agent for tapflow — xcrun simctl control and screen streaming",
5
5
  "keywords": [
6
6
  "tapflow",
@@ -46,27 +46,29 @@
46
46
  "LICENSE"
47
47
  ],
48
48
  "engines": {
49
- "node": ">=20.12.0"
49
+ "node": ">=22.0.0"
50
50
  },
51
51
  "publishConfig": {
52
52
  "access": "public"
53
53
  },
54
54
  "dependencies": {
55
- "ws": "^8.21.1",
56
- "@tapflowio/agent-core": "0.17.0",
57
- "@tapflowio/audiotap-helper": "0.2.7"
55
+ "ws": "^8.21.3",
56
+ "@tapflowio/audiotap-helper": "0.3.0",
57
+ "@tapflowio/protocol": "0.19.0",
58
+ "@tapflowio/agent-core": "0.19.0"
58
59
  },
59
60
  "devDependencies": {
60
- "@types/node": "^20.19.43",
61
+ "@types/node": "^22.20.1",
61
62
  "@types/ws": "^8.0.0",
62
63
  "typescript": "^5.0.0",
63
64
  "vitest": "^4.1.10",
64
- "@tapflowio/relay": "0.17.0"
65
+ "@tapflowio/relay": "0.19.0",
66
+ "@tapflowio/test-utils": "0.0.0"
65
67
  },
66
68
  "scripts": {
67
69
  "postinstall": "node -e \"if (process.platform === 'darwin') { require('fs').readdirSync('bin').forEach(f => require('fs').chmodSync('bin/' + f, 0o755)) }\"",
68
70
  "build": "tsc -b",
69
- "typecheck": "tsc -b",
71
+ "typecheck": "tsc -b && tsc -p src/__tests__/tsconfig.json",
70
72
  "test": "vitest run",
71
73
  "lint": "eslint src"
72
74
  }