@farmslot/recipe-runner 0.23.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 (212) hide show
  1. package/CHANGELOG.md +255 -0
  2. package/LICENSE +21 -0
  3. package/README.md +274 -0
  4. package/bin/farmslot-visual-review.mjs +152 -0
  5. package/dist/adapters/app-lifecycle.d.ts +41 -0
  6. package/dist/adapters/app-lifecycle.d.ts.map +1 -0
  7. package/dist/adapters/app-lifecycle.js +224 -0
  8. package/dist/adapters/app-lifecycle.js.map +1 -0
  9. package/dist/adapters/core.d.ts +5 -0
  10. package/dist/adapters/core.d.ts.map +1 -0
  11. package/dist/adapters/core.js +433 -0
  12. package/dist/adapters/core.js.map +1 -0
  13. package/dist/adapters/gesture.d.ts +12 -0
  14. package/dist/adapters/gesture.d.ts.map +1 -0
  15. package/dist/adapters/gesture.js +76 -0
  16. package/dist/adapters/gesture.js.map +1 -0
  17. package/dist/adapters/ui.d.ts +33 -0
  18. package/dist/adapters/ui.d.ts.map +1 -0
  19. package/dist/adapters/ui.js +130 -0
  20. package/dist/adapters/ui.js.map +1 -0
  21. package/dist/cli/error-output.d.ts +6 -0
  22. package/dist/cli/error-output.d.ts.map +1 -0
  23. package/dist/cli/error-output.js +19 -0
  24. package/dist/cli/error-output.js.map +1 -0
  25. package/dist/cli/index.d.ts +12 -0
  26. package/dist/cli/index.d.ts.map +1 -0
  27. package/dist/cli/index.js +29 -0
  28. package/dist/cli/index.js.map +1 -0
  29. package/dist/cli/run-command.d.ts +8 -0
  30. package/dist/cli/run-command.d.ts.map +1 -0
  31. package/dist/cli/run-command.js +253 -0
  32. package/dist/cli/run-command.js.map +1 -0
  33. package/dist/cli/support.d.ts +31 -0
  34. package/dist/cli/support.d.ts.map +1 -0
  35. package/dist/cli/support.js +297 -0
  36. package/dist/cli/support.js.map +1 -0
  37. package/dist/cli/validate-command.d.ts +4 -0
  38. package/dist/cli/validate-command.d.ts.map +1 -0
  39. package/dist/cli/validate-command.js +52 -0
  40. package/dist/cli/validate-command.js.map +1 -0
  41. package/dist/core/compose.d.ts +23 -0
  42. package/dist/core/compose.d.ts.map +1 -0
  43. package/dist/core/compose.js +104 -0
  44. package/dist/core/compose.js.map +1 -0
  45. package/dist/core/execution.d.ts +44 -0
  46. package/dist/core/execution.d.ts.map +1 -0
  47. package/dist/core/execution.js +304 -0
  48. package/dist/core/execution.js.map +1 -0
  49. package/dist/core/failure.d.ts +23 -0
  50. package/dist/core/failure.d.ts.map +1 -0
  51. package/dist/core/failure.js +43 -0
  52. package/dist/core/failure.js.map +1 -0
  53. package/dist/core/graph.d.ts +12 -0
  54. package/dist/core/graph.d.ts.map +1 -0
  55. package/dist/core/graph.js +65 -0
  56. package/dist/core/graph.js.map +1 -0
  57. package/dist/core/hud.d.ts +11 -0
  58. package/dist/core/hud.d.ts.map +1 -0
  59. package/dist/core/hud.js +120 -0
  60. package/dist/core/hud.js.map +1 -0
  61. package/dist/core/invocation.d.ts +13 -0
  62. package/dist/core/invocation.d.ts.map +1 -0
  63. package/dist/core/invocation.js +68 -0
  64. package/dist/core/invocation.js.map +1 -0
  65. package/dist/core/json.d.ts +9 -0
  66. package/dist/core/json.d.ts.map +1 -0
  67. package/dist/core/json.js +74 -0
  68. package/dist/core/json.js.map +1 -0
  69. package/dist/core/library-manifest.d.ts +53 -0
  70. package/dist/core/library-manifest.d.ts.map +1 -0
  71. package/dist/core/library-manifest.js +263 -0
  72. package/dist/core/library-manifest.js.map +1 -0
  73. package/dist/core/library.d.ts +80 -0
  74. package/dist/core/library.d.ts.map +1 -0
  75. package/dist/core/library.js +321 -0
  76. package/dist/core/library.js.map +1 -0
  77. package/dist/core/parameters.d.ts +5 -0
  78. package/dist/core/parameters.d.ts.map +1 -0
  79. package/dist/core/parameters.js +57 -0
  80. package/dist/core/parameters.js.map +1 -0
  81. package/dist/core/passive-observations.d.ts +25 -0
  82. package/dist/core/passive-observations.d.ts.map +1 -0
  83. package/dist/core/passive-observations.js +62 -0
  84. package/dist/core/passive-observations.js.map +1 -0
  85. package/dist/core/path.d.ts +7 -0
  86. package/dist/core/path.d.ts.map +1 -0
  87. package/dist/core/path.js +147 -0
  88. package/dist/core/path.js.map +1 -0
  89. package/dist/core/recording-cleanup.d.ts +10 -0
  90. package/dist/core/recording-cleanup.d.ts.map +1 -0
  91. package/dist/core/recording-cleanup.js +32 -0
  92. package/dist/core/recording-cleanup.js.map +1 -0
  93. package/dist/core/resolution-error.d.ts +7 -0
  94. package/dist/core/resolution-error.d.ts.map +1 -0
  95. package/dist/core/resolution-error.js +9 -0
  96. package/dist/core/resolution-error.js.map +1 -0
  97. package/dist/core/runner.d.ts +4 -0
  98. package/dist/core/runner.d.ts.map +1 -0
  99. package/dist/core/runner.js +738 -0
  100. package/dist/core/runner.js.map +1 -0
  101. package/dist/core/scroll-to.d.ts +111 -0
  102. package/dist/core/scroll-to.d.ts.map +1 -0
  103. package/dist/core/scroll-to.js +353 -0
  104. package/dist/core/scroll-to.js.map +1 -0
  105. package/dist/core/suite.d.ts +25 -0
  106. package/dist/core/suite.d.ts.map +1 -0
  107. package/dist/core/suite.js +76 -0
  108. package/dist/core/suite.js.map +1 -0
  109. package/dist/core/trace.d.ts +5 -0
  110. package/dist/core/trace.d.ts.map +1 -0
  111. package/dist/core/trace.js +25 -0
  112. package/dist/core/trace.js.map +1 -0
  113. package/dist/core/trust-error.d.ts +9 -0
  114. package/dist/core/trust-error.d.ts.map +1 -0
  115. package/dist/core/trust-error.js +18 -0
  116. package/dist/core/trust-error.js.map +1 -0
  117. package/dist/core/trust-input.d.ts +20 -0
  118. package/dist/core/trust-input.d.ts.map +1 -0
  119. package/dist/core/trust-input.js +68 -0
  120. package/dist/core/trust-input.js.map +1 -0
  121. package/dist/core/trust.d.ts +28 -0
  122. package/dist/core/trust.d.ts.map +1 -0
  123. package/dist/core/trust.js +284 -0
  124. package/dist/core/trust.js.map +1 -0
  125. package/dist/core/types.d.ts +319 -0
  126. package/dist/core/types.d.ts.map +1 -0
  127. package/dist/core/types.js +2 -0
  128. package/dist/core/types.js.map +1 -0
  129. package/dist/core/validation.d.ts +4 -0
  130. package/dist/core/validation.d.ts.map +1 -0
  131. package/dist/core/validation.js +18 -0
  132. package/dist/core/validation.js.map +1 -0
  133. package/dist/index.d.ts +32 -0
  134. package/dist/index.d.ts.map +1 -0
  135. package/dist/index.js +25 -0
  136. package/dist/index.js.map +1 -0
  137. package/dist/node/writers.d.ts +27 -0
  138. package/dist/node/writers.d.ts.map +1 -0
  139. package/dist/node/writers.js +99 -0
  140. package/dist/node/writers.js.map +1 -0
  141. package/dist/recording/android-mirror.d.ts +10 -0
  142. package/dist/recording/android-mirror.d.ts.map +1 -0
  143. package/dist/recording/android-mirror.js +180 -0
  144. package/dist/recording/android-mirror.js.map +1 -0
  145. package/dist/recording/capture-helper-timing.d.ts +4 -0
  146. package/dist/recording/capture-helper-timing.d.ts.map +1 -0
  147. package/dist/recording/capture-helper-timing.js +47 -0
  148. package/dist/recording/capture-helper-timing.js.map +1 -0
  149. package/dist/recording/capture-helper.d.ts +10 -0
  150. package/dist/recording/capture-helper.d.ts.map +1 -0
  151. package/dist/recording/capture-helper.js +335 -0
  152. package/dist/recording/capture-helper.js.map +1 -0
  153. package/dist/recording/cdp-video-recorder.d.ts +9 -0
  154. package/dist/recording/cdp-video-recorder.d.ts.map +1 -0
  155. package/dist/recording/cdp-video-recorder.js +319 -0
  156. package/dist/recording/cdp-video-recorder.js.map +1 -0
  157. package/dist/recording/frame-sampler.d.ts +19 -0
  158. package/dist/recording/frame-sampler.d.ts.map +1 -0
  159. package/dist/recording/frame-sampler.js +29 -0
  160. package/dist/recording/frame-sampler.js.map +1 -0
  161. package/dist/recording/timeline.d.ts +15 -0
  162. package/dist/recording/timeline.d.ts.map +1 -0
  163. package/dist/recording/timeline.js +88 -0
  164. package/dist/recording/timeline.js.map +1 -0
  165. package/dist/runtime/browser-extension.d.ts +17 -0
  166. package/dist/runtime/browser-extension.d.ts.map +1 -0
  167. package/dist/runtime/browser-extension.js +42 -0
  168. package/dist/runtime/browser-extension.js.map +1 -0
  169. package/dist/runtime/cdp.d.ts +138 -0
  170. package/dist/runtime/cdp.d.ts.map +1 -0
  171. package/dist/runtime/cdp.js +1429 -0
  172. package/dist/runtime/cdp.js.map +1 -0
  173. package/dist/runtime/decision-types.d.ts +23 -0
  174. package/dist/runtime/decision-types.d.ts.map +1 -0
  175. package/dist/runtime/decision-types.js +2 -0
  176. package/dist/runtime/decision-types.js.map +1 -0
  177. package/dist/runtime/deps-readiness.d.ts +21 -0
  178. package/dist/runtime/deps-readiness.d.ts.map +1 -0
  179. package/dist/runtime/deps-readiness.js +141 -0
  180. package/dist/runtime/deps-readiness.js.map +1 -0
  181. package/dist/runtime/log-analysis.d.ts +48 -0
  182. package/dist/runtime/log-analysis.d.ts.map +1 -0
  183. package/dist/runtime/log-analysis.js +128 -0
  184. package/dist/runtime/log-analysis.js.map +1 -0
  185. package/dist/runtime/metro-probe.d.ts +5 -0
  186. package/dist/runtime/metro-probe.d.ts.map +1 -0
  187. package/dist/runtime/metro-probe.js +24 -0
  188. package/dist/runtime/metro-probe.js.map +1 -0
  189. package/dist/runtime/operation.d.ts +32 -0
  190. package/dist/runtime/operation.d.ts.map +1 -0
  191. package/dist/runtime/operation.js +184 -0
  192. package/dist/runtime/operation.js.map +1 -0
  193. package/dist/runtime/orchestrate-up.d.ts +22 -0
  194. package/dist/runtime/orchestrate-up.d.ts.map +1 -0
  195. package/dist/runtime/orchestrate-up.js +35 -0
  196. package/dist/runtime/orchestrate-up.js.map +1 -0
  197. package/dist/runtime/react-native-bridge.d.ts +17 -0
  198. package/dist/runtime/react-native-bridge.d.ts.map +1 -0
  199. package/dist/runtime/react-native-bridge.js +57 -0
  200. package/dist/runtime/react-native-bridge.js.map +1 -0
  201. package/dist/version.d.ts +2 -0
  202. package/dist/version.d.ts.map +1 -0
  203. package/dist/version.js +8 -0
  204. package/dist/version.js.map +1 -0
  205. package/package.json +163 -0
  206. package/test/fixtures/scroll-to-visible/README.md +39 -0
  207. package/visual-review/feedback-draft.mjs +82 -0
  208. package/visual-review/index.d.mts +41 -0
  209. package/visual-review/index.mjs +4 -0
  210. package/visual-review/recipe-board.mjs +142 -0
  211. package/visual-review/review-board.mjs +981 -0
  212. package/visual-review/server.mjs +69 -0
@@ -0,0 +1,180 @@
1
+ import { execFile, spawn } from 'node:child_process';
2
+ import { randomUUID } from 'node:crypto';
3
+ import { setTimeout as delay } from 'node:timers/promises';
4
+ import { promisify } from 'node:util';
5
+ import { captureHelperPath } from '@farmslot/protocol/node/capture-helper-path';
6
+ import { createCaptureHelperVideoRecorder } from './capture-helper.js';
7
+ const exec = promisify(execFile);
8
+ /** The caller must hold the device lease. This recorder owns only its scrcpy
9
+ * process and exact window; it never installs, unlocks, or controls the device. */
10
+ export function createAndroidMirrorVideoRecorder(options) {
11
+ const helperPath = options.captureHelperPath ?? captureHelperPath();
12
+ const scrcpy = options.scrcpyPath ?? 'scrcpy';
13
+ const primary = createCaptureHelperVideoRecorder({ captureHelperPath: helperPath });
14
+ let selected;
15
+ let fallbackReason;
16
+ async function doctor() {
17
+ selected = undefined;
18
+ const native = await primary.doctor();
19
+ if (native.ok) {
20
+ try {
21
+ await exec(scrcpy, ['--version'], { timeout: 5000 });
22
+ selected = 'primary';
23
+ return {
24
+ ok: true,
25
+ code: 'ok',
26
+ message: 'Capture-helper and Android mirror are available; target readiness is checked at recording start.',
27
+ };
28
+ }
29
+ catch (error) {
30
+ fallbackReason = `Android mirror unavailable: ${error instanceof Error ? error.message : String(error)}`;
31
+ }
32
+ }
33
+ else
34
+ fallbackReason = native.message;
35
+ const result = (await options.fallback.doctor?.()) ?? {
36
+ ok: true,
37
+ code: 'ok',
38
+ message: 'Fallback provider selected.',
39
+ };
40
+ if (result.ok)
41
+ selected = 'fallback';
42
+ return {
43
+ ...result,
44
+ message: `${result.message} Primary recording path unavailable: ${fallbackReason}`,
45
+ };
46
+ }
47
+ return {
48
+ name: 'android-recording',
49
+ platform: 'android',
50
+ doctor,
51
+ async start(request) {
52
+ if (request.target.kind !== 'android-device' || request.target.serial !== options.serial)
53
+ throw new Error('Android recording target does not match the selected device.');
54
+ if (!selected) {
55
+ const result = await doctor();
56
+ if (!result.ok)
57
+ throw new Error(result.message);
58
+ }
59
+ if (selected === 'fallback') {
60
+ const active = await options.fallback.start(request);
61
+ return {
62
+ ...active,
63
+ async stop() {
64
+ const result = await active.stop();
65
+ return { ...result, recorder: { ...result.recorder, fallbackReason } };
66
+ },
67
+ };
68
+ }
69
+ const title = `Recipe recording ${randomUUID()}`;
70
+ const child = spawn(scrcpy, ['--serial', options.serial, '--no-control', '--no-audio', '--window-title', title], { stdio: ['ignore', 'ignore', 'pipe'] });
71
+ let stderr = '';
72
+ let error;
73
+ let closing = false;
74
+ let mirrorFailure;
75
+ child.stderr.setEncoding('utf8');
76
+ child.stderr.on('data', (chunk) => {
77
+ stderr = (stderr + chunk).slice(-4000);
78
+ });
79
+ child.on('error', (failure) => {
80
+ error = failure;
81
+ if (!closing)
82
+ mirrorFailure = failure;
83
+ });
84
+ const exited = new Promise((resolve) => {
85
+ child.once('exit', (code, signal) => {
86
+ if (!closing)
87
+ mirrorFailure = new Error(`Owned Android mirror exited during recording (${signal ?? code}): ${stderr}`);
88
+ resolve();
89
+ });
90
+ child.once('error', () => {
91
+ if (child.pid === undefined)
92
+ resolve();
93
+ });
94
+ });
95
+ const waitForExit = (ms) => new Promise((resolve) => {
96
+ const timer = setTimeout(() => resolve(false), ms);
97
+ void exited.then(() => {
98
+ clearTimeout(timer);
99
+ resolve(true);
100
+ });
101
+ });
102
+ const cleanup = async () => {
103
+ closing = true;
104
+ if (child.pid !== undefined && child.exitCode === null && child.signalCode === null) {
105
+ child.kill('SIGTERM');
106
+ if (!(await waitForExit(5000))) {
107
+ child.kill('SIGKILL');
108
+ if (!(await waitForExit(5000)))
109
+ throw new Error('Owned Android mirror did not exit after forced cleanup.');
110
+ }
111
+ }
112
+ };
113
+ try {
114
+ let windowId;
115
+ const deadline = Date.now() + 15_000;
116
+ while (Date.now() < deadline) {
117
+ if (error)
118
+ throw error;
119
+ if (child.exitCode !== null || child.signalCode !== null)
120
+ throw new Error(`Android mirror exited: ${stderr}`);
121
+ const list = await exec(helperPath, ['list', '--json'], {
122
+ timeout: 5000,
123
+ maxBuffer: 4 * 1024 * 1024,
124
+ });
125
+ const windows = JSON.parse(list.stdout).windows;
126
+ const owned = windows.find((window) => window.pid === child.pid && window.title === title);
127
+ if (owned) {
128
+ windowId = owned.id;
129
+ break;
130
+ }
131
+ await delay(100);
132
+ }
133
+ if (windowId === undefined)
134
+ throw new Error('The owned Android mirror did not expose a capture window.');
135
+ const active = await primary.start({
136
+ ...request,
137
+ target: { kind: 'window-id', windowId: String(windowId) },
138
+ });
139
+ return {
140
+ ...(active.snapshot
141
+ ? {
142
+ async snapshot(outputPath) {
143
+ if (mirrorFailure)
144
+ throw mirrorFailure;
145
+ const result = await active.snapshot(outputPath);
146
+ if (mirrorFailure)
147
+ throw mirrorFailure;
148
+ return result;
149
+ },
150
+ }
151
+ : {}),
152
+ async stop() {
153
+ try {
154
+ const result = await active.stop();
155
+ if (mirrorFailure)
156
+ throw mirrorFailure;
157
+ return {
158
+ ...result,
159
+ recorder: {
160
+ ...result.recorder,
161
+ platform: 'android',
162
+ target: { selector: 'adb-serial', value: options.serial },
163
+ mirrorWindowId: String(windowId),
164
+ },
165
+ };
166
+ }
167
+ finally {
168
+ await cleanup();
169
+ }
170
+ },
171
+ };
172
+ }
173
+ catch (failure) {
174
+ await cleanup();
175
+ throw failure;
176
+ }
177
+ },
178
+ };
179
+ }
180
+ //# sourceMappingURL=android-mirror.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"android-mirror.js","sourceRoot":"","sources":["../../src/recording/android-mirror.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { VideoRecordingResult } from '../core/types.js';
2
+ /** Consume capture facts from the finalized native recording, not a launch-time estimate. */
3
+ export declare function readCaptureHelperTiming(outputPath: string): Promise<Pick<VideoRecordingResult, 'timing' | 'timingUnavailableReason'>>;
4
+ //# sourceMappingURL=capture-helper-timing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture-helper-timing.d.ts","sourceRoot":"","sources":["../../src/recording/capture-helper-timing.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAE7D,6FAA6F;AAC7F,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,oBAAoB,EAAE,QAAQ,GAAG,yBAAyB,CAAC,CAAC,CAyC3E"}
@@ -0,0 +1,47 @@
1
+ import { readFile, realpath } from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { validateRecipeRecordingTimelineDocument, } from '@farmslot/protocol';
4
+ import { digestFileWithinRoot } from '../core/path.js';
5
+ /** Consume capture facts from the finalized native recording, not a launch-time estimate. */
6
+ export async function readCaptureHelperTiming(outputPath) {
7
+ try {
8
+ const root = await realpath(path.dirname(outputPath));
9
+ const name = path.basename(outputPath);
10
+ const sidecar = await realpath(`${outputPath}.timing.json`);
11
+ if (path.dirname(sidecar) !== root)
12
+ throw new Error('Capture timing sidecar escapes the recording directory.');
13
+ const data = JSON.parse(await readFile(sidecar, 'utf8'));
14
+ if (data.version !== 1 ||
15
+ typeof data.recording_id !== 'string' ||
16
+ !data.recording_id ||
17
+ data.video_file !== name)
18
+ throw new Error('Capture timing identity does not match the recording.');
19
+ const digest = await digestFileWithinRoot(root, name);
20
+ if (data.video_digest !== digest)
21
+ throw new Error('Capture timing digest does not match finalized video bytes.');
22
+ const timing = {
23
+ framesMs: data.frames_ms,
24
+ durationMs: data.duration_ms,
25
+ clock: {
26
+ source: data.clock?.source,
27
+ earliestZeroUnixMs: data.clock?.earliest_zero_unix_ms,
28
+ latestZeroUnixMs: data.clock?.latest_zero_unix_ms,
29
+ },
30
+ };
31
+ const validation = validateRecipeRecordingTimelineDocument({
32
+ ...timing,
33
+ version: 1,
34
+ videoPath: name,
35
+ videoDigest: digest,
36
+ traceDigest: `sha256:${'0'.repeat(64)}`,
37
+ markers: [],
38
+ });
39
+ if (validation.status !== 'valid')
40
+ throw new Error('Capture timing contains invalid frame or clock data.');
41
+ return { timing };
42
+ }
43
+ catch (error) {
44
+ return { timingUnavailableReason: error instanceof Error ? error.message : String(error) };
45
+ }
46
+ }
47
+ //# sourceMappingURL=capture-helper-timing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture-helper-timing.js","sourceRoot":"","sources":["../../src/recording/capture-helper-timing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAEL,uCAAuC,GACxC,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAGvD,6FAA6F;AAC7F,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,UAAkB;IAElB,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;QACtD,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QACvC,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,GAAG,UAAU,cAAc,CAAC,CAAC;QAC5D,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,IAAI;YAChC,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;QAC7E,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;QACzD,IACE,IAAI,CAAC,OAAO,KAAK,CAAC;YAClB,OAAO,IAAI,CAAC,YAAY,KAAK,QAAQ;YACrC,CAAC,IAAI,CAAC,YAAY;YAClB,IAAI,CAAC,UAAU,KAAK,IAAI;YAExB,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;QAC3E,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACtD,IAAI,IAAI,CAAC,YAAY,KAAK,MAAM;YAC9B,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;QACjF,MAAM,MAAM,GAAsB;YAChC,QAAQ,EAAE,IAAI,CAAC,SAAS;YACxB,UAAU,EAAE,IAAI,CAAC,WAAW;YAC5B,KAAK,EAAE;gBACL,MAAM,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM;gBAC1B,kBAAkB,EAAE,IAAI,CAAC,KAAK,EAAE,qBAAqB;gBACrD,gBAAgB,EAAE,IAAI,CAAC,KAAK,EAAE,mBAAmB;aAClD;SACF,CAAC;QACF,MAAM,UAAU,GAAG,uCAAuC,CAAC;YACzD,GAAG,MAAM;YACT,OAAO,EAAE,CAAC;YACV,SAAS,EAAE,IAAI;YACf,WAAW,EAAE,MAAM;YACnB,WAAW,EAAE,UAAU,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE;YACvC,OAAO,EAAE,EAAE;SACZ,CAAC,CAAC;QACH,IAAI,UAAU,CAAC,MAAM,KAAK,OAAO;YAC/B,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;QAC1E,OAAO,EAAE,MAAM,EAAE,CAAC;IACpB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,EAAE,uBAAuB,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;IAC7F,CAAC;AACH,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { RecipeArtifactRecorderTarget } from '@farmslot/protocol';
2
+ import type { RecordingTarget, VideoRecorder } from '../core/types.js';
3
+ export interface CaptureHelperVideoRecorderOptions {
4
+ captureHelperPath?: string;
5
+ stopTimeoutMs?: number;
6
+ }
7
+ export declare function createCaptureHelperVideoRecorder(options?: CaptureHelperVideoRecorderOptions): VideoRecorder;
8
+ export declare function manifestTarget(target: RecordingTarget): RecipeArtifactRecorderTarget;
9
+ export declare function errorMessage(error: unknown): string;
10
+ //# sourceMappingURL=capture-helper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture-helper.d.ts","sourceRoot":"","sources":["../../src/recording/capture-helper.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,oBAAoB,CAAC;AAGvE,OAAO,KAAK,EAEV,eAAe,EACf,aAAa,EAGd,MAAM,kBAAkB,CAAC;AAK1B,MAAM,WAAW,iCAAiC;IAChD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAWD,wBAAgB,gCAAgC,CAC9C,OAAO,GAAE,iCAAsC,GAC9C,aAAa,CAEf;AAgWD,wBAAgB,cAAc,CAAC,MAAM,EAAE,eAAe,GAAG,4BAA4B,CAUpF;AAMD,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEnD"}
@@ -0,0 +1,335 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { stat } from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ import { captureHelperPath } from '@farmslot/protocol/node/capture-helper-path';
5
+ import { readCaptureHelperTiming } from './capture-helper-timing.js';
6
+ import { optionalVideoTiming } from './timeline.js';
7
+ const DEFAULT_STOP_TIMEOUT_MS = 10_000;
8
+ export function createCaptureHelperVideoRecorder(options = {}) {
9
+ return new CaptureHelperVideoRecorder(options);
10
+ }
11
+ class CaptureHelperVideoRecorder {
12
+ #captureHelperPath;
13
+ #stopTimeoutMs;
14
+ #version;
15
+ constructor(options) {
16
+ this.name = 'capture-helper';
17
+ this.platform = 'macos';
18
+ this.#captureHelperPath = options.captureHelperPath ?? captureHelperPath();
19
+ this.#stopTimeoutMs = options.stopTimeoutMs ?? DEFAULT_STOP_TIMEOUT_MS;
20
+ }
21
+ get version() {
22
+ return this.#version;
23
+ }
24
+ async doctor() {
25
+ if (process.platform !== 'darwin') {
26
+ return {
27
+ ok: false,
28
+ code: 'unsupported_platform',
29
+ message: 'capture-helper recording is macOS-only.',
30
+ suggestedFix: 'Run on macOS or omit --record-video.',
31
+ };
32
+ }
33
+ let result;
34
+ try {
35
+ result = await runCommand(this.#captureHelperPath, ['doctor', '--json'], {
36
+ timeoutMs: 10_000,
37
+ });
38
+ }
39
+ catch (error) {
40
+ // Do NOT claim "not installed" — this only means spawn/exec failed (PATH, sandbox,
41
+ // permissions, wrong CAPTURE_HELPER_PATH). Operators often have capture-helper on
42
+ // PATH in interactive shells while the recipe child process does not.
43
+ return {
44
+ ok: false,
45
+ code: 'capture_helper_exec_failed',
46
+ message: `capture-helper doctor could not be executed (spawn/exec failed; not proof it is uninstalled): ${errorMessage(error)}`,
47
+ suggestedFix: 'Run `command -v capture-helper && capture-helper doctor --json` in this same environment. Ensure PATH includes the binary (e.g. ~/.npm-global/bin), or set CAPTURE_HELPER_PATH to the real binary. Unset a stale CAPTURE_HELPER_PATH if checksum_mismatch is reported.',
48
+ };
49
+ }
50
+ if (result.exitCode !== 0) {
51
+ return {
52
+ ok: false,
53
+ code: 'capture_helper_doctor_failed',
54
+ message: result.stderr.trim() || result.stdout.trim() || 'capture-helper doctor failed.',
55
+ suggestedFix: 'Run `capture-helper doctor --open-permissions` on the node host.',
56
+ };
57
+ }
58
+ const parsed = parseDoctor(result.stdout);
59
+ this.#version = parsed.build?.version;
60
+ if (parsed.ok === false) {
61
+ const failed = (parsed.checks ?? []).filter((check) => check.required && !check.ok);
62
+ return {
63
+ ok: false,
64
+ code: failed[0]?.code ?? 'capture_helper_doctor_failed',
65
+ message: failed
66
+ .map((check) => check.message ?? check.code)
67
+ .filter(Boolean)
68
+ .join('; ') || 'capture-helper doctor reported required failures.',
69
+ suggestedFix: 'Run `capture-helper doctor --open-permissions` on the node host.',
70
+ };
71
+ }
72
+ return {
73
+ ok: true,
74
+ code: 'ok',
75
+ message: `capture-helper${this.#version ? ` ${this.#version}` : ''} is ready.`,
76
+ };
77
+ }
78
+ async start(request) {
79
+ const versionResult = await runCommand(this.#captureHelperPath, ['version', '--json'], {
80
+ timeoutMs: 10_000,
81
+ });
82
+ if (versionResult.exitCode !== 0)
83
+ throw new Error('Capture-helper version probe failed.');
84
+ const version = JSON.parse(versionResult.stdout);
85
+ const nativeTiming = Array.isArray(version.capabilities) &&
86
+ version.capabilities.includes('record_session_timing_v1');
87
+ const sessionSnapshots = Array.isArray(version.capabilities) &&
88
+ version.capabilities.includes('record_session_snapshot');
89
+ const args = ['record', ...targetArgs(request.target), '--output', request.outputPath];
90
+ if (sessionSnapshots)
91
+ args.push('--framed');
92
+ if (request.maxFps != null)
93
+ args.push('--max-fps', String(request.maxFps));
94
+ if (request.maxSize != null)
95
+ args.push('--max-size', String(request.maxSize));
96
+ const startedAtUnixMs = Date.now();
97
+ const child = spawn(this.#captureHelperPath, args, { stdio: ['pipe', 'pipe', 'pipe'] });
98
+ const stderr = [];
99
+ let ready = false;
100
+ let eventBuffer = '';
101
+ const snapshots = new Map();
102
+ const usedSnapshotPaths = new Set();
103
+ let recordingId;
104
+ child.stderr.setEncoding('utf-8');
105
+ child.stderr.on('data', (chunk) => {
106
+ stderr.push(chunk);
107
+ eventBuffer += chunk;
108
+ const lines = eventBuffer.split('\n');
109
+ eventBuffer = lines.pop() ?? '';
110
+ for (const line of lines) {
111
+ if (!line.trim())
112
+ continue;
113
+ let event;
114
+ try {
115
+ event = JSON.parse(line);
116
+ }
117
+ catch {
118
+ continue; /* legacy helper diagnostics may be plain text */
119
+ }
120
+ if (event.type === 'record_ready' &&
121
+ typeof event.recording_id === 'string' &&
122
+ event.recording_id) {
123
+ recordingId = event.recording_id;
124
+ ready = true;
125
+ }
126
+ const snapshot = typeof event.output === 'string' ? snapshots.get(event.output) : undefined;
127
+ if (snapshot && ['snapshot', 'error'].includes(event.type)) {
128
+ clearTimeout(snapshot.timer);
129
+ snapshots.delete(event.output);
130
+ if (event.type === 'snapshot' &&
131
+ nativeTiming &&
132
+ (event.recording_id !== recordingId ||
133
+ typeof event.media_time_ms !== 'number' ||
134
+ !Number.isFinite(event.media_time_ms) ||
135
+ event.media_time_ms < 0 ||
136
+ typeof event.source_time_ms !== 'number' ||
137
+ !Number.isFinite(event.source_time_ms) ||
138
+ typeof event.writer_accepted !== 'boolean' ||
139
+ (event.writer_accepted &&
140
+ (!Number.isInteger(event.writer_frame_index) || event.writer_frame_index < 0))))
141
+ snapshot.reject(new Error('Recording snapshot omitted valid timing or recording identity.'));
142
+ else if (event.type === 'snapshot')
143
+ snapshot.resolve(nativeTiming
144
+ ? event
145
+ : {
146
+ ...event,
147
+ timingUnavailableReason: 'Recorder does not advertise snapshot timing.',
148
+ });
149
+ else
150
+ snapshot.reject(new Error(event.message ?? 'Recording snapshot failed.'));
151
+ }
152
+ }
153
+ });
154
+ child.stdout.resume();
155
+ const exit = new Promise((resolve) => {
156
+ child.once('exit', (code, signal) => {
157
+ for (const snapshot of snapshots.values()) {
158
+ clearTimeout(snapshot.timer);
159
+ snapshot.reject(new Error('Recorder exited before the snapshot completed.'));
160
+ }
161
+ snapshots.clear();
162
+ resolve({ code, signal });
163
+ });
164
+ });
165
+ await new Promise((resolve, reject) => {
166
+ const timeout = setTimeout(resolve, 250);
167
+ child.once('error', (error) => {
168
+ clearTimeout(timeout);
169
+ reject(error);
170
+ });
171
+ child.once('exit', (code, signal) => {
172
+ clearTimeout(timeout);
173
+ reject(new Error(`capture-helper record exited early (${formatExit(code, signal)}): ${stderr.join('').trim()}`));
174
+ });
175
+ });
176
+ if (nativeTiming) {
177
+ const deadline = Date.now() + 15_000;
178
+ while (!ready &&
179
+ child.exitCode === null &&
180
+ child.signalCode === null &&
181
+ Date.now() < deadline)
182
+ await new Promise((resolve) => setTimeout(resolve, 20));
183
+ if (!ready) {
184
+ if (child.exitCode === null && child.signalCode === null)
185
+ child.kill('SIGINT');
186
+ await waitForExit(exit, {
187
+ timeoutMs: this.#stopTimeoutMs,
188
+ onTimeout: () => child.kill('SIGKILL'),
189
+ message: 'Capture-helper did not stop after readiness failure.',
190
+ });
191
+ throw new Error(`Capture-helper did not provide a recorded first frame: ${stderr.join('').trim()}`);
192
+ }
193
+ }
194
+ const getVersion = () => this.version;
195
+ const stopTimeoutMs = this.#stopTimeoutMs;
196
+ return {
197
+ ...(sessionSnapshots
198
+ ? {
199
+ snapshot(outputPath) {
200
+ if (/[\r\n]/.test(outputPath))
201
+ return Promise.reject(new Error('Snapshot path cannot contain a newline.'));
202
+ if (child.exitCode !== null || child.signalCode !== null)
203
+ return Promise.reject(new Error('Recording is no longer active.'));
204
+ if (usedSnapshotPaths.has(outputPath))
205
+ return Promise.reject(new Error('This snapshot path was already used in this recording.'));
206
+ usedSnapshotPaths.add(outputPath);
207
+ return new Promise((resolve, reject) => {
208
+ const timer = setTimeout(() => {
209
+ snapshots.delete(outputPath);
210
+ reject(new Error('Recording snapshot timed out.'));
211
+ }, 15_000);
212
+ snapshots.set(outputPath, { resolve, reject, timer });
213
+ child.stdin.write(`snapshot ${outputPath}\n`, (error) => {
214
+ if (!error)
215
+ return;
216
+ clearTimeout(timer);
217
+ snapshots.delete(outputPath);
218
+ reject(error);
219
+ });
220
+ });
221
+ },
222
+ }
223
+ : {}),
224
+ async stop() {
225
+ if (child.exitCode == null && child.signalCode == null)
226
+ child.kill('SIGINT');
227
+ const result = await waitForExit(exit, {
228
+ timeoutMs: stopTimeoutMs,
229
+ onTimeout: () => child.kill('SIGKILL'),
230
+ message: `capture-helper record did not stop within ${stopTimeoutMs}ms after SIGINT.`,
231
+ });
232
+ const expectedInterrupt = result.signal === 'SIGINT';
233
+ const stoppedAtUnixMs = Date.now();
234
+ if (result.code !== 0 && !expectedInterrupt) {
235
+ throw new Error(`capture-helper record failed (${formatExit(result.code, result.signal)}): ${stderr.join('').trim()}`);
236
+ }
237
+ const stats = await stat(request.outputPath);
238
+ if (stats.size <= 0)
239
+ throw new Error(`Recording output is empty: ${request.outputPath}`);
240
+ return {
241
+ ...(nativeTiming
242
+ ? { timingEvidencePath: `${path.basename(request.outputPath)}.timing.json` }
243
+ : {}),
244
+ ...(nativeTiming
245
+ ? await readCaptureHelperTiming(request.outputPath)
246
+ : await optionalVideoTiming(request.outputPath, { startedAtUnixMs, stoppedAtUnixMs })),
247
+ recorder: {
248
+ name: 'capture-helper',
249
+ ...(getVersion() ? { version: getVersion() } : {}),
250
+ platform: 'macos',
251
+ target: manifestTarget(request.target),
252
+ },
253
+ };
254
+ },
255
+ };
256
+ }
257
+ }
258
+ function runCommand(command, args, options) {
259
+ return new Promise((resolve, reject) => {
260
+ const child = spawn(command, args, { stdio: ['ignore', 'pipe', 'pipe'] });
261
+ let stdout = '';
262
+ let stderr = '';
263
+ const timer = setTimeout(() => {
264
+ child.kill('SIGTERM');
265
+ reject(new Error(`${command} ${args.join(' ')} timed out after ${options.timeoutMs}ms`));
266
+ }, options.timeoutMs);
267
+ child.stdout.setEncoding('utf-8');
268
+ child.stderr.setEncoding('utf-8');
269
+ child.stdout.on('data', (chunk) => (stdout += chunk));
270
+ child.stderr.on('data', (chunk) => (stderr += chunk));
271
+ child.once('error', (error) => {
272
+ clearTimeout(timer);
273
+ reject(error);
274
+ });
275
+ child.once('exit', (exitCode) => {
276
+ clearTimeout(timer);
277
+ resolve({ stdout, stderr, exitCode });
278
+ });
279
+ });
280
+ }
281
+ function parseDoctor(stdout) {
282
+ try {
283
+ return JSON.parse(stdout);
284
+ }
285
+ catch (error) {
286
+ throw new Error(`capture-helper doctor returned invalid JSON: ${errorMessage(error)}`);
287
+ }
288
+ }
289
+ function waitForExit(exit, options) {
290
+ return new Promise((resolve, reject) => {
291
+ const timer = setTimeout(() => {
292
+ options.onTimeout();
293
+ reject(new Error(options.message));
294
+ }, options.timeoutMs);
295
+ exit.then((result) => {
296
+ clearTimeout(timer);
297
+ resolve(result);
298
+ }, (error) => {
299
+ clearTimeout(timer);
300
+ reject(error);
301
+ });
302
+ });
303
+ }
304
+ function targetArgs(target) {
305
+ if (target.kind === 'android-device')
306
+ throw new Error('A physical Android recording requires the owned mirror recorder.');
307
+ if (target.kind === 'pid')
308
+ return ['--pid', String(target.pid)];
309
+ if (target.kind === 'window-id')
310
+ return ['--window-id', target.windowId];
311
+ if (target.kind === 'simulator') {
312
+ throw new Error('capture-helper does not support simulator targets; use the simctl recorder.');
313
+ }
314
+ return ['--app-name', target.appName, '--window-name', target.windowName];
315
+ }
316
+ export function manifestTarget(target) {
317
+ if (target.kind === 'android-device')
318
+ return { selector: 'adb-serial', value: target.serial };
319
+ if (target.kind === 'pid')
320
+ return { selector: 'pid', value: String(target.pid) };
321
+ if (target.kind === 'app-window') {
322
+ return { selector: 'app-window', value: `${target.appName}:${target.windowName}` };
323
+ }
324
+ if (target.kind === 'simulator') {
325
+ return { selector: 'simulator', value: target.device };
326
+ }
327
+ return { selector: 'window-id', value: target.windowId };
328
+ }
329
+ function formatExit(code, signal) {
330
+ return signal ? `signal ${signal}` : `exit ${code ?? 'unknown'}`;
331
+ }
332
+ export function errorMessage(error) {
333
+ return error instanceof Error ? error.message : String(error);
334
+ }
335
+ //# sourceMappingURL=capture-helper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture-helper.js","sourceRoot":"","sources":["../../src/recording/capture-helper.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { VideoRecorder } from '../core/types.js';
2
+ export interface CdpVideoRecorderOptions {
3
+ cdpPort: number;
4
+ cdpHost?: string;
5
+ urlIncludes?: string;
6
+ ffmpegPath?: string;
7
+ }
8
+ export declare function createCdpVideoRecorder(options: CdpVideoRecorderOptions): VideoRecorder;
9
+ //# sourceMappingURL=cdp-video-recorder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cdp-video-recorder.d.ts","sourceRoot":"","sources":["../../src/recording/cdp-video-recorder.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAEV,aAAa,EAGd,MAAM,kBAAkB,CAAC;AAO1B,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,uBAAuB,GAAG,aAAa,CAEtF"}