@farmslot/recipe-cli 0.3.0 → 0.4.1

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 (55) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +12 -12
  3. package/dist/harness/adapters.d.ts +2 -0
  4. package/dist/harness/adapters.d.ts.map +1 -1
  5. package/dist/harness/adapters.js +4 -0
  6. package/dist/harness/adapters.js.map +1 -1
  7. package/dist/harness/execution-provenance.d.ts +56 -0
  8. package/dist/harness/execution-provenance.d.ts.map +1 -0
  9. package/dist/harness/execution-provenance.js +308 -0
  10. package/dist/harness/execution-provenance.js.map +1 -0
  11. package/dist/harness/host.d.ts +8 -0
  12. package/dist/harness/host.d.ts.map +1 -1
  13. package/dist/harness/host.js +9 -2
  14. package/dist/harness/host.js.map +1 -1
  15. package/dist/harness/index.d.ts +12 -2
  16. package/dist/harness/index.d.ts.map +1 -1
  17. package/dist/harness/index.js +12 -2
  18. package/dist/harness/index.js.map +1 -1
  19. package/dist/harness/live-adapter-contract.d.ts +32 -0
  20. package/dist/harness/live-adapter-contract.d.ts.map +1 -0
  21. package/dist/harness/live-adapter-contract.js +425 -0
  22. package/dist/harness/live-adapter-contract.js.map +1 -0
  23. package/dist/harness/recording-target.d.ts +9 -0
  24. package/dist/harness/recording-target.d.ts.map +1 -0
  25. package/dist/harness/recording-target.js +39 -0
  26. package/dist/harness/recording-target.js.map +1 -0
  27. package/dist/harness/run-diagnostics.d.ts +139 -0
  28. package/dist/harness/run-diagnostics.d.ts.map +1 -0
  29. package/dist/harness/run-diagnostics.js +458 -0
  30. package/dist/harness/run-diagnostics.js.map +1 -0
  31. package/dist/harness/run-options.d.ts +4 -0
  32. package/dist/harness/run-options.d.ts.map +1 -0
  33. package/dist/harness/run-options.js +35 -0
  34. package/dist/harness/run-options.js.map +1 -0
  35. package/dist/harness/run-recording.d.ts +43 -0
  36. package/dist/harness/run-recording.d.ts.map +1 -0
  37. package/dist/harness/run-recording.js +517 -0
  38. package/dist/harness/run-recording.js.map +1 -0
  39. package/dist/harness/run-report.d.ts +19 -0
  40. package/dist/harness/run-report.d.ts.map +1 -0
  41. package/dist/harness/run-report.js +269 -0
  42. package/dist/harness/run-report.js.map +1 -0
  43. package/dist/harness/runtime-proof.d.ts +27 -0
  44. package/dist/harness/runtime-proof.d.ts.map +1 -0
  45. package/dist/harness/runtime-proof.js +144 -0
  46. package/dist/harness/runtime-proof.js.map +1 -0
  47. package/dist/harness/suggest.d.ts +3 -0
  48. package/dist/harness/suggest.d.ts.map +1 -0
  49. package/dist/harness/suggest.js +37 -0
  50. package/dist/harness/suggest.js.map +1 -0
  51. package/dist/harness/trust.d.ts +38 -0
  52. package/dist/harness/trust.d.ts.map +1 -0
  53. package/dist/harness/trust.js +89 -0
  54. package/dist/harness/trust.js.map +1 -0
  55. package/package.json +5 -3
@@ -0,0 +1,35 @@
1
+ import { adapterPortFlags, harnessAdapter } from './adapters.js';
2
+ import { optionString } from './parse-args.js';
3
+ import { explicitRecipeTrustOptions } from './trust.js';
4
+ export function recipeRunOptionsFromCli(adapter, options) {
5
+ const recordVideo = options.recordVideo;
6
+ const hud = optionString(options, 'hud');
7
+ const trust = explicitRecipeTrustOptions({
8
+ sourceTrust: optionString(options, 'sourceTrust'),
9
+ sourceKind: optionString(options, 'sourceKind'),
10
+ sourceName: optionString(options, 'sourceName'),
11
+ sourceDigest: optionString(options, 'sourceDigest'),
12
+ approvalDigest: optionString(options, 'approvePlan'),
13
+ });
14
+ const platform = harnessAdapter(adapter).run?.platformOptions?.(options);
15
+ return {
16
+ cdpPort: optionString(options, 'cdpPort'),
17
+ watcherPort: watcherPortOption(options),
18
+ slot: optionString(options, 'slot'),
19
+ validationRuntimeDir: optionString(options, 'validationRuntimeDir'),
20
+ recordVideo: recordVideo === 'full-run' ? 'full-run' : false,
21
+ autoHud: hud === 'show' ? true : hud === 'hide' ? false : undefined,
22
+ ...(platform ? { platform } : {}),
23
+ ...trust,
24
+ };
25
+ }
26
+ // --watcher-port, else the first port option a registered adapter adds.
27
+ function watcherPortOption(options) {
28
+ for (const flag of ['watcherPort', ...adapterPortFlags()]) {
29
+ const port = optionString(options, flag);
30
+ if (port !== undefined)
31
+ return port;
32
+ }
33
+ return undefined;
34
+ }
35
+ //# sourceMappingURL=run-options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-options.js","sourceRoot":"","sources":["../../src/harness/run-options.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EAAmB,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,0BAA0B,EAAE,MAAM,YAAY,CAAC;AAExD,MAAM,UAAU,uBAAuB,CAAC,OAAe,EAAE,OAAmB;IAC1E,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;IACxC,MAAM,GAAG,GAAG,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACzC,MAAM,KAAK,GAAG,0BAA0B,CAAC;QACvC,WAAW,EAAE,YAAY,CAAC,OAAO,EAAE,aAAa,CAAC;QACjD,UAAU,EAAE,YAAY,CAAC,OAAO,EAAE,YAAY,CAAC;QAC/C,UAAU,EAAE,YAAY,CAAC,OAAO,EAAE,YAAY,CAAC;QAC/C,YAAY,EAAE,YAAY,CAAC,OAAO,EAAE,cAAc,CAAC;QACnD,cAAc,EAAE,YAAY,CAAC,OAAO,EAAE,aAAa,CAAC;KACrD,CAAC,CAAC;IACH,MAAM,QAAQ,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,eAAe,EAAE,CAAC,OAAO,CAAC,CAAC;IACzE,OAAO;QACL,OAAO,EAAE,YAAY,CAAC,OAAO,EAAE,SAAS,CAAC;QACzC,WAAW,EAAE,iBAAiB,CAAC,OAAO,CAAC;QACvC,IAAI,EAAE,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC;QACnC,oBAAoB,EAAE,YAAY,CAAC,OAAO,EAAE,sBAAsB,CAAC;QACnE,WAAW,EAAE,WAAW,KAAK,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK;QAC5D,OAAO,EAAE,GAAG,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;QACnE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjC,GAAG,KAAK;KACT,CAAC;AACJ,CAAC;AAED,wEAAwE;AACxE,SAAS,iBAAiB,CAAC,OAAmB;IAC5C,KAAK,MAAM,IAAI,IAAI,CAAC,aAAa,EAAE,GAAG,gBAAgB,EAAE,CAAC,EAAE,CAAC;QAC1D,MAAM,IAAI,GAAG,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACzC,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC;IACtC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -0,0 +1,43 @@
1
+ import { type ChildProcessWithoutNullStreams } from 'node:child_process';
2
+ import { readCaptureHelperTiming, type RecipeRunResult } from '@farmslot/recipe-runner';
3
+ export interface RecipeRecordingOptions {
4
+ record?: boolean;
5
+ cdpPort?: string;
6
+ }
7
+ export interface ActiveRecipeRecording {
8
+ child: ChildProcessWithoutNullStreams;
9
+ outputPath: string;
10
+ stagingDir: string;
11
+ stagedPath: string;
12
+ relativePath: string;
13
+ pid: number;
14
+ stdout: string;
15
+ stderr: string;
16
+ exited: boolean;
17
+ exitCode: number | null;
18
+ frameReady: boolean;
19
+ finalized: boolean;
20
+ startedAtUnixMs: number;
21
+ stoppedAtUnixMs?: number;
22
+ nativeTiming: boolean;
23
+ completedRecordingId?: string;
24
+ completedVideo?: boolean;
25
+ nativeTimingEvidence?: Awaited<ReturnType<typeof readCaptureHelperTiming>>;
26
+ error?: Error;
27
+ activePidEnv: string;
28
+ previousActiveRecordingPid: string | undefined;
29
+ stderrBuffer: string;
30
+ pendingSnapshots: Map<string, PendingRecordingSnapshot>;
31
+ }
32
+ interface PendingRecordingSnapshot {
33
+ outputPath: string;
34
+ timer: NodeJS.Timeout;
35
+ resolve: (event: Record<string, unknown>) => void;
36
+ reject: (error: Error) => void;
37
+ }
38
+ export declare function startRecipeRecording(adapter: string, projectRoot: string, artifactsDir: string, options: RecipeRecordingOptions): Promise<ActiveRecipeRecording | undefined>;
39
+ /** Ask the recording of `pid` for an in-session snapshot; undefined when none runs. */
40
+ export declare function captureActiveRecipeRecordingSnapshot(pid: number, outputPath: string, timeoutMs?: number): Promise<Record<string, unknown> | undefined>;
41
+ export declare function stopRecipeRecording(recording: ActiveRecipeRecording | undefined, result?: RecipeRunResult): Promise<void>;
42
+ export {};
43
+ //# sourceMappingURL=run-recording.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-recording.d.ts","sourceRoot":"","sources":["../../src/harness/run-recording.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,8BAA8B,EAAoB,MAAM,oBAAoB,CAAC;AAI3F,OAAO,EAEL,uBAAuB,EACvB,KAAK,eAAe,EAErB,MAAM,yBAAyB,CAAC;AAUjC,MAAM,WAAW,sBAAsB;IACrC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,8BAA8B,CAAC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,OAAO,CAAC;IACtB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,oBAAoB,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,uBAAuB,CAAC,CAAC,CAAC;IAC3E,KAAK,CAAC,EAAE,KAAK,CAAC;IAEd,YAAY,EAAE,MAAM,CAAC;IACrB,0BAA0B,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/C,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,GAAG,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAAC;CACzD;AAED,UAAU,wBAAwB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC;IACtB,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAClD,MAAM,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAChC;AAID,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,qBAAqB,GAAG,SAAS,CAAC,CA8G5C;AAED,uFAAuF;AACvF,wBAAsB,oCAAoC,CACxD,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,EAClB,SAAS,SAAS,GACjB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,CAsB9C;AAED,wBAAsB,mBAAmB,CACvC,SAAS,EAAE,qBAAqB,GAAG,SAAS,EAC5C,MAAM,CAAC,EAAE,eAAe,GACvB,OAAO,CAAC,IAAI,CAAC,CAqBf"}
@@ -0,0 +1,517 @@
1
+ // The harness-owned framed recorder: capture-helper records the browser a
2
+ // platform names (`recording.framed`) for the whole run, actions take in-session
3
+ // snapshots while it runs, and the video is published into the run's artifacts.
4
+ import { spawn, spawnSync } from 'node:child_process';
5
+ import fs from 'node:fs';
6
+ import path from 'node:path';
7
+ import { optionalVideoTiming, readCaptureHelperTiming, writeRecordingTimeline, } from '@farmslot/recipe-runner';
8
+ import { harnessAdapter } from './adapters.js';
9
+ import { harnessHost } from './host.js';
10
+ import { captureHelperPath, captureHelperSupportsCapability, captureHelperSupportsRecordSessionSnapshots, } from './recording-target.js';
11
+ const activeRecordingsByPid = new Map();
12
+ export async function startRecipeRecording(adapter, projectRoot, artifactsDir, options) {
13
+ if (!options.record)
14
+ return undefined;
15
+ if (process.platform !== 'darwin') {
16
+ console.error('WARN: --record-video uses capture-helper and is currently supported only on macOS; continuing without video.');
17
+ return undefined;
18
+ }
19
+ const framed = harnessAdapter(adapter).recording?.framed;
20
+ if (!framed)
21
+ return undefined;
22
+ const cdpPort = options.cdpPort ?? process.env.CDP_PORT ?? process.env.RECIPE_CDP_PORT;
23
+ if (!captureHelperSupportsRecordSessionSnapshots(projectRoot)) {
24
+ console.error(`WARN: framed ${adapter} recording requires capture-helper capability record_session_snapshot; falling back to harness --record-video.`);
25
+ return undefined;
26
+ }
27
+ const pid = framed.browserPid(projectRoot, artifactsDir, cdpPort);
28
+ if (!pid) {
29
+ console.error(`WARN: framed ${adapter} recording could not resolve browser PID from CDP port ${cdpPort ?? '<unset>'}; falling back to harness --record-video.`);
30
+ return undefined;
31
+ }
32
+ const recordArgs = ['record', '--framed', '--pid', String(pid)];
33
+ const relativePath = 'videos/full-run.mp4';
34
+ const outputPath = path.join(artifactsDir, relativePath);
35
+ const { stagingDir, stagedPath } = preparePrivateRecordingDestination(artifactsDir, outputPath);
36
+ let child;
37
+ const startedAtUnixMs = Date.now();
38
+ try {
39
+ child = spawn(captureHelperPath(), [...recordArgs, '--output', stagedPath], {
40
+ cwd: projectRoot,
41
+ env: process.env,
42
+ stdio: ['pipe', 'pipe', 'pipe'],
43
+ });
44
+ }
45
+ catch (error) {
46
+ cleanupRecordingStaging(stagingDir);
47
+ throw error;
48
+ }
49
+ const recording = {
50
+ child,
51
+ startedAtUnixMs,
52
+ nativeTiming: captureHelperSupportsCapability(projectRoot, 'record_session_timing_v1'),
53
+ outputPath,
54
+ stagingDir,
55
+ stagedPath,
56
+ relativePath,
57
+ pid,
58
+ stdout: '',
59
+ stderr: '',
60
+ exited: false,
61
+ exitCode: null,
62
+ frameReady: false,
63
+ finalized: false,
64
+ activePidEnv: framed.activePidEnv,
65
+ previousActiveRecordingPid: process.env[framed.activePidEnv],
66
+ stderrBuffer: '',
67
+ pendingSnapshots: new Map(),
68
+ };
69
+ child.stdout.on('data', (chunk) => {
70
+ recording.stdout += String(chunk);
71
+ });
72
+ child.stderr.on('data', (chunk) => {
73
+ recording.stderr += String(chunk);
74
+ handleRecordingStderr(recording, String(chunk));
75
+ });
76
+ child.on('error', (error) => {
77
+ recording.error = error;
78
+ recording.stderr += error.message;
79
+ recording.exited = true;
80
+ });
81
+ child.on('close', (exitCode) => {
82
+ recording.stoppedAtUnixMs = Date.now();
83
+ recording.exited = true;
84
+ recording.exitCode = exitCode;
85
+ activeRecordingsByPid.delete(recording.pid);
86
+ restoreActiveRecordingEnvironment(recording);
87
+ rejectPendingSnapshots(recording, new Error(`capture-helper recording exited before snapshot completed (code=${exitCode ?? 'unknown'})`));
88
+ });
89
+ await waitForRecordingReady(recording, 15_000);
90
+ if (recording.exited) {
91
+ cleanupRecordingStaging(recording.stagingDir);
92
+ throw new Error(`capture-helper exited before recording its first frame (code=${recording.exitCode ?? 'unknown'}): ${recording.stderr || recording.stdout}`);
93
+ }
94
+ if (!recording.frameReady) {
95
+ try {
96
+ await stopRecordingProcess(recording);
97
+ }
98
+ finally {
99
+ cleanupRecordingStaging(recording.stagingDir);
100
+ }
101
+ throw new Error(`capture-helper did not record a frame within 15000ms: ${recording.stderr || recording.stdout || 'no recorder output'}`);
102
+ }
103
+ activeRecordingsByPid.set(pid, recording);
104
+ process.env[framed.activePidEnv] = String(pid);
105
+ console.error(`INFO: recording recipe video with capture-helper pid=${pid} output=${outputPath}`);
106
+ return recording;
107
+ }
108
+ /** Ask the recording of `pid` for an in-session snapshot; undefined when none runs. */
109
+ export async function captureActiveRecipeRecordingSnapshot(pid, outputPath, timeoutMs = 30_000) {
110
+ const recording = activeRecordingsByPid.get(pid);
111
+ if (!recording || recording.exited)
112
+ return undefined;
113
+ fs.mkdirSync(path.dirname(outputPath), { recursive: true });
114
+ fs.rmSync(outputPath, { force: true });
115
+ return new Promise((resolve, reject) => {
116
+ const timer = setTimeout(() => {
117
+ recording.pendingSnapshots.delete(outputPath);
118
+ reject(new Error(`capture-helper record session snapshot timed out after ${timeoutMs}ms: ${outputPath}`));
119
+ }, timeoutMs);
120
+ recording.pendingSnapshots.set(outputPath, { outputPath, timer, resolve, reject });
121
+ recording.child.stdin.write(`snapshot ${outputPath}\n`, (error) => {
122
+ if (!error)
123
+ return;
124
+ clearTimeout(timer);
125
+ recording.pendingSnapshots.delete(outputPath);
126
+ reject(error);
127
+ });
128
+ });
129
+ }
130
+ export async function stopRecipeRecording(recording, result) {
131
+ if (!recording || recording.finalized)
132
+ return;
133
+ recording.finalized = true;
134
+ try {
135
+ await stopRecordingProcess(recording);
136
+ const validation = await validateRecordingArtifact(recording);
137
+ if (validation.ok === false) {
138
+ throw new Error(`capture-helper recording did not produce a usable video artifact: ${validation.reason}`);
139
+ }
140
+ publishRecordingArtifact(recording);
141
+ if (result)
142
+ await addRecordingArtifactToManifest(result, recording);
143
+ }
144
+ catch (error) {
145
+ if (result)
146
+ removeRecordingArtifactFromManifest(result, recording.relativePath);
147
+ throw error;
148
+ }
149
+ finally {
150
+ activeRecordingsByPid.delete(recording.pid);
151
+ restoreActiveRecordingEnvironment(recording);
152
+ cleanupRecordingStaging(recording.stagingDir);
153
+ }
154
+ }
155
+ async function stopRecordingProcess(recording) {
156
+ if (!recording.exited && !recording.child.stdin.destroyed) {
157
+ recording.child.stdin.end('stop\n');
158
+ await waitForRecordingExit(recording, 15_000);
159
+ }
160
+ if (!recording.exited) {
161
+ recording.child.kill('SIGINT');
162
+ await waitForRecordingExit(recording, 5_000);
163
+ }
164
+ if (!recording.exited) {
165
+ recording.child.kill('SIGTERM');
166
+ await waitForRecordingExit(recording, 3_000);
167
+ }
168
+ if (!recording.exited) {
169
+ recording.child.kill('SIGKILL');
170
+ await waitForRecordingExit(recording, 2_000);
171
+ }
172
+ if (!recording.exited) {
173
+ throw new Error(`capture-helper recording process did not exit: pid=${recording.child.pid ?? 'unknown'}`);
174
+ }
175
+ }
176
+ async function waitForRecordingExit(recording, timeoutMs) {
177
+ if (recording.exited)
178
+ return;
179
+ await new Promise((resolve) => {
180
+ const finish = () => {
181
+ clearTimeout(timer);
182
+ recording.child.removeListener('close', finish);
183
+ resolve();
184
+ };
185
+ const timer = setTimeout(finish, timeoutMs);
186
+ recording.child.once('close', finish);
187
+ if (recording.exited)
188
+ finish();
189
+ });
190
+ }
191
+ async function waitForRecordingReady(recording, timeoutMs) {
192
+ const deadline = Date.now() + timeoutMs;
193
+ while (!recording.frameReady && !recording.exited && Date.now() < deadline) {
194
+ await sleep(50);
195
+ }
196
+ }
197
+ function handleRecordingStderr(recording, chunk) {
198
+ recording.stderrBuffer += chunk;
199
+ let newlineIndex = recording.stderrBuffer.indexOf('\n');
200
+ while (newlineIndex !== -1) {
201
+ const line = recording.stderrBuffer.slice(0, newlineIndex).trim();
202
+ recording.stderrBuffer = recording.stderrBuffer.slice(newlineIndex + 1);
203
+ if (line)
204
+ handleRecordingEventLine(recording, line);
205
+ newlineIndex = recording.stderrBuffer.indexOf('\n');
206
+ }
207
+ }
208
+ function handleRecordingEventLine(recording, line) {
209
+ let event;
210
+ try {
211
+ const parsed = JSON.parse(line);
212
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))
213
+ return;
214
+ event = parsed;
215
+ }
216
+ catch {
217
+ // capture-helper may emit human-readable stderr lines; only JSON event
218
+ // records are relevant for in-session screenshot correlation.
219
+ return;
220
+ }
221
+ if (event.type === 'info' &&
222
+ typeof event.msg === 'string' &&
223
+ /^record frames=[1-9]\d*$/.test(event.msg)) {
224
+ recording.frameReady = true;
225
+ }
226
+ if (event.type === 'record_complete' && event.output === recording.stagedPath) {
227
+ recording.completedVideo = typeof event.frames === 'number' && event.frames > 0;
228
+ if (typeof event.recording_id === 'string')
229
+ recording.completedRecordingId = event.recording_id;
230
+ }
231
+ const output = typeof event.output === 'string' ? event.output : undefined;
232
+ if (!output)
233
+ return;
234
+ const pending = recording.pendingSnapshots.get(output);
235
+ if (!pending)
236
+ return;
237
+ if (event.type === 'snapshot') {
238
+ clearTimeout(pending.timer);
239
+ recording.pendingSnapshots.delete(output);
240
+ pending.resolve(event);
241
+ return;
242
+ }
243
+ if (event.type === 'error') {
244
+ clearTimeout(pending.timer);
245
+ recording.pendingSnapshots.delete(output);
246
+ pending.reject(new Error(String(event.message ?? `capture-helper snapshot failed: ${output}`)));
247
+ }
248
+ }
249
+ function rejectPendingSnapshots(recording, error) {
250
+ for (const pending of recording.pendingSnapshots.values()) {
251
+ clearTimeout(pending.timer);
252
+ pending.reject(error);
253
+ }
254
+ recording.pendingSnapshots.clear();
255
+ }
256
+ async function validateRecordingArtifact(recording) {
257
+ if (!fs.existsSync(recording.stagedPath)) {
258
+ return { ok: false, reason: `missing output ${recording.stagedPath}` };
259
+ }
260
+ const stagedStat = fs.lstatSync(recording.stagedPath);
261
+ if (stagedStat.isSymbolicLink() || !stagedStat.isFile()) {
262
+ return { ok: false, reason: `unsafe non-regular output ${recording.stagedPath}` };
263
+ }
264
+ const size = stagedStat.size;
265
+ if (size === 0) {
266
+ return { ok: false, reason: `empty output ${recording.stagedPath}` };
267
+ }
268
+ const recorderOutput = `${recording.stdout}\n${recording.stderr}`;
269
+ if (recording.nativeTiming) {
270
+ if (!recording.completedVideo)
271
+ return { ok: false, reason: 'Missing finalized video completion' };
272
+ recording.nativeTimingEvidence = await readNativeRecordingTiming(recording);
273
+ return { ok: true };
274
+ }
275
+ if (!recorderOutput.includes('record_complete')) {
276
+ return {
277
+ ok: false,
278
+ reason: `capture-helper did not report record_complete for ${recording.stagedPath}: ${recorderOutput.trim() || 'no recorder output'}`,
279
+ };
280
+ }
281
+ const ffprobe = spawnSync('ffprobe', [
282
+ '-hide_banner',
283
+ '-v',
284
+ 'error',
285
+ '-show_entries',
286
+ 'format=duration',
287
+ '-of',
288
+ 'default=noprint_wrappers=1:nokey=1',
289
+ recording.stagedPath,
290
+ ], { encoding: 'utf8' });
291
+ if (ffprobe.error && ffprobe.error.code === 'ENOENT') {
292
+ return { ok: true };
293
+ }
294
+ if (ffprobe.error) {
295
+ return {
296
+ ok: false,
297
+ reason: `ffprobe failed for ${recording.stagedPath}: ${ffprobe.error.message}`,
298
+ };
299
+ }
300
+ if (ffprobe.status !== 0) {
301
+ return {
302
+ ok: false,
303
+ reason: `invalid MP4 ${recording.stagedPath}: ${ffprobe.stderr.trim() || ffprobe.stdout.trim() || `ffprobe exited ${ffprobe.status}`}`,
304
+ };
305
+ }
306
+ const durationSeconds = Number(ffprobe.stdout.trim());
307
+ if (!Number.isFinite(durationSeconds) || durationSeconds <= 0) {
308
+ return { ok: false, reason: `MP4 has no positive duration: ${recording.stagedPath}` };
309
+ }
310
+ return { ok: true };
311
+ }
312
+ async function readNativeRecordingTiming(recording) {
313
+ try {
314
+ if (!recording.completedRecordingId)
315
+ throw new Error('Missing native recording completion identity');
316
+ const sidecar = recording.stagedPath + '.timing.json';
317
+ const entry = fs.lstatSync(sidecar);
318
+ if (!entry.isFile() || entry.isSymbolicLink())
319
+ throw new Error('Native timing must be a regular file');
320
+ const native = JSON.parse(fs.readFileSync(sidecar, 'utf8'));
321
+ if (native.recording_id !== recording.completedRecordingId)
322
+ throw new Error('Native recording identity mismatch');
323
+ return await readCaptureHelperTiming(recording.stagedPath);
324
+ }
325
+ catch (error) {
326
+ // Timing is optional; retain finalized video without unverifiable markers.
327
+ return { timingUnavailableReason: error instanceof Error ? error.message : String(error) };
328
+ }
329
+ }
330
+ function preparePrivateRecordingDestination(artifactsDir, outputPath) {
331
+ const outputDir = path.dirname(outputPath);
332
+ ensureRecordingDirectory(path.resolve(artifactsDir), outputDir);
333
+ refuseRecordingDestinationSymlink(outputPath);
334
+ const stagingDir = fs.mkdtempSync(path.join(outputDir, `.${harnessHost().name}-recording-`));
335
+ fs.chmodSync(stagingDir, 0o700);
336
+ return {
337
+ stagingDir,
338
+ stagedPath: path.join(stagingDir, 'full-run.mp4'),
339
+ };
340
+ }
341
+ function ensureRecordingDirectory(artifactsRoot, outputDir) {
342
+ fs.mkdirSync(artifactsRoot, { recursive: true });
343
+ requireRecordingDirectory(artifactsRoot);
344
+ const relative = path.relative(artifactsRoot, outputDir);
345
+ let current = artifactsRoot;
346
+ for (const segment of relative.split(path.sep).filter(Boolean)) {
347
+ current = path.join(current, segment);
348
+ try {
349
+ fs.mkdirSync(current);
350
+ }
351
+ catch (error) {
352
+ if (error.code !== 'EEXIST')
353
+ throw error;
354
+ }
355
+ requireRecordingDirectory(current);
356
+ }
357
+ }
358
+ function requireRecordingDirectory(directory) {
359
+ const entry = fs.lstatSync(directory);
360
+ if (entry.isDirectory() && !entry.isSymbolicLink())
361
+ return;
362
+ throw new Error(`Refusing unsafe recording artifact directory: ${directory}\n` +
363
+ `Next: replace ${JSON.stringify(directory)} with a regular directory and retry the recipe.`);
364
+ }
365
+ function publishRecordingArtifact(recording) {
366
+ publishPrivateRecordingFile(recording.stagedPath, recording.outputPath);
367
+ if (recording.nativeTimingEvidence?.timing) {
368
+ try {
369
+ publishPrivateRecordingFile(recording.stagedPath + '.timing.json', recording.outputPath + '.timing.json');
370
+ }
371
+ catch (error) {
372
+ // A sidecar publication failure must not remove the finalized footage.
373
+ recording.nativeTimingEvidence = {
374
+ timingUnavailableReason: error instanceof Error ? error.message : String(error),
375
+ };
376
+ }
377
+ }
378
+ }
379
+ function publishPrivateRecordingFile(sourcePath, outputPath) {
380
+ const noFollow = fs.constants.O_NOFOLLOW ?? 0;
381
+ let descriptor;
382
+ try {
383
+ descriptor = fs.openSync(sourcePath, fs.constants.O_RDONLY | noFollow);
384
+ const stagedStat = fs.fstatSync(descriptor);
385
+ if (!stagedStat.isFile()) {
386
+ throw unsafeRecordingArtifactError(sourcePath);
387
+ }
388
+ fs.fchmodSync(descriptor, 0o600);
389
+ }
390
+ catch (error) {
391
+ if (error instanceof Error && error.message.includes('Next:'))
392
+ throw error;
393
+ throw unsafeRecordingArtifactError(sourcePath, error instanceof Error ? error.message : String(error));
394
+ }
395
+ finally {
396
+ if (descriptor !== undefined)
397
+ fs.closeSync(descriptor);
398
+ }
399
+ refuseRecordingDestinationSymlink(outputPath);
400
+ fs.renameSync(sourcePath, outputPath);
401
+ }
402
+ function refuseRecordingDestinationSymlink(outputPath) {
403
+ try {
404
+ const destination = fs.lstatSync(outputPath);
405
+ if (destination.isSymbolicLink()) {
406
+ throw new Error(`Refusing recording artifact destination symlink: ${outputPath}\n` +
407
+ `Next: rm -- ${JSON.stringify(outputPath)} and retry the recipe.`);
408
+ }
409
+ if (!destination.isFile()) {
410
+ throw new Error(`Refusing non-file recording artifact destination: ${outputPath}\n` +
411
+ `Next: remove ${JSON.stringify(outputPath)} and retry the recipe.`);
412
+ }
413
+ }
414
+ catch (error) {
415
+ if (error.code === 'ENOENT')
416
+ return;
417
+ throw error;
418
+ }
419
+ }
420
+ function unsafeRecordingArtifactError(stagedPath, detail) {
421
+ return new Error(`Capture-helper recording output is not a safe regular file: ${stagedPath}${detail ? ` (${detail})` : ''}.\n` +
422
+ 'Next: capture-helper doctor --json');
423
+ }
424
+ function cleanupRecordingStaging(stagingDir) {
425
+ try {
426
+ fs.rmSync(stagingDir, { recursive: true, force: true });
427
+ }
428
+ catch (error) {
429
+ console.error(`WARN: could not remove capture-helper staging directory ${stagingDir}: ${error instanceof Error ? error.message : String(error)}`);
430
+ }
431
+ }
432
+ function restoreActiveRecordingEnvironment(recording) {
433
+ if (process.env[recording.activePidEnv] !== String(recording.pid))
434
+ return;
435
+ if (recording.previousActiveRecordingPid === undefined) {
436
+ delete process.env[recording.activePidEnv];
437
+ return;
438
+ }
439
+ process.env[recording.activePidEnv] = recording.previousActiveRecordingPid;
440
+ }
441
+ async function addRecordingArtifactToManifest(result, recording) {
442
+ const manifestPath = result.artifactManifestPath;
443
+ if (!manifestPath || !fs.existsSync(manifestPath)) {
444
+ console.error(`WARN: cannot add video artifact to missing artifact manifest: ${manifestPath ?? '<unset>'}`);
445
+ return;
446
+ }
447
+ const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
448
+ if (!Array.isArray(manifest.artifacts))
449
+ manifest.artifacts = [];
450
+ manifest.artifacts = manifest.artifacts.filter((artifact) => artifact.path !== recording.relativePath);
451
+ const timing = recording.nativeTiming
452
+ ? (recording.nativeTimingEvidence ?? {
453
+ timingUnavailableReason: 'Native recording timing unavailable',
454
+ })
455
+ : await optionalVideoTiming(recording.outputPath, {
456
+ startedAtUnixMs: recording.startedAtUnixMs,
457
+ stoppedAtUnixMs: recording.stoppedAtUnixMs ?? Date.now(),
458
+ });
459
+ if (recording.nativeTimingEvidence?.timing)
460
+ manifest.artifacts.push({
461
+ path: recording.relativePath + '.timing.json',
462
+ type: 'json',
463
+ category: 'system',
464
+ label: 'Native recording and screenshot timing',
465
+ });
466
+ let timelinePath;
467
+ let timelineUnavailableReason = timing.timingUnavailableReason;
468
+ if (timing.timing) {
469
+ try {
470
+ const raw = JSON.parse(fs.readFileSync(result.tracePath, 'utf8'));
471
+ const trace = Array.isArray(raw) ? raw : raw.entries;
472
+ timelinePath = await writeRecordingTimeline(path.dirname(manifestPath), recording.relativePath, timing.timing, trace);
473
+ manifest.artifacts.push({
474
+ path: timelinePath,
475
+ type: 'json',
476
+ label: 'Recording frames and action markers',
477
+ category: 'system',
478
+ });
479
+ }
480
+ catch (error) {
481
+ // Keep valid footage when optional trace alignment cannot be established.
482
+ timelineUnavailableReason = error instanceof Error ? error.message : String(error);
483
+ }
484
+ }
485
+ manifest.artifacts.push({
486
+ path: recording.relativePath,
487
+ type: 'video',
488
+ label: 'Full recipe replay video',
489
+ category: 'evidence',
490
+ mimeType: 'video/mp4',
491
+ record: 'full_run',
492
+ ...(timelinePath ? { timelinePath } : { timelineUnavailableReason }),
493
+ metadata: {
494
+ provider: 'capture-helper',
495
+ mode: 'full_run',
496
+ pid: recording.pid,
497
+ },
498
+ });
499
+ fs.writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
500
+ }
501
+ function removeRecordingArtifactFromManifest(result, relativePath) {
502
+ const manifestPath = result.artifactManifestPath;
503
+ if (!manifestPath || !fs.existsSync(manifestPath))
504
+ return;
505
+ const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
506
+ if (!Array.isArray(manifest.artifacts))
507
+ return;
508
+ const nextArtifacts = manifest.artifacts.filter((artifact) => artifact.path !== relativePath);
509
+ if (nextArtifacts.length === manifest.artifacts.length)
510
+ return;
511
+ manifest.artifacts = nextArtifacts;
512
+ fs.writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
513
+ }
514
+ function sleep(ms) {
515
+ return new Promise((resolve) => setTimeout(resolve, ms));
516
+ }
517
+ //# sourceMappingURL=run-recording.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run-recording.js","sourceRoot":"","sources":["../../src/harness/run-recording.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,iFAAiF;AACjF,gFAAgF;AAChF,OAAO,EAAuC,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC3F,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EACL,mBAAmB,EACnB,uBAAuB,EAEvB,sBAAsB,GACvB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EACL,iBAAiB,EACjB,+BAA+B,EAC/B,2CAA2C,GAC5C,MAAM,uBAAuB,CAAC;AAyC/B,MAAM,qBAAqB,GAAG,IAAI,GAAG,EAAiC,CAAC;AAEvE,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,OAAe,EACf,WAAmB,EACnB,YAAoB,EACpB,OAA+B;IAE/B,IAAI,CAAC,OAAO,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IACtC,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAClC,OAAO,CAAC,KAAK,CACX,8GAA8G,CAC/G,CAAC;QACF,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,MAAM,MAAM,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,MAAM,CAAC;IACzD,IAAI,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IAE9B,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;IACvF,IAAI,CAAC,2CAA2C,CAAC,WAAW,CAAC,EAAE,CAAC;QAC9D,OAAO,CAAC,KAAK,CACX,gBAAgB,OAAO,gHAAgH,CACxI,CAAC;QACF,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,WAAW,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC;IAClE,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,CAAC,KAAK,CACX,gBAAgB,OAAO,0DAA0D,OAAO,IAAI,SAAS,2CAA2C,CACjJ,CAAC;QACF,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,UAAU,GAAG,CAAC,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IAEhE,MAAM,YAAY,GAAG,qBAAqB,CAAC;IAC3C,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;IACzD,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,kCAAkC,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;IAChG,IAAI,KAAqC,CAAC;IAC1C,MAAM,eAAe,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACnC,IAAI,CAAC;QACH,KAAK,GAAG,KAAK,CAAC,iBAAiB,EAAE,EAAE,CAAC,GAAG,UAAU,EAAE,UAAU,EAAE,UAAU,CAAC,EAAE;YAC1E,GAAG,EAAE,WAAW;YAChB,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,uBAAuB,CAAC,UAAU,CAAC,CAAC;QACpC,MAAM,KAAK,CAAC;IACd,CAAC;IACD,MAAM,SAAS,GAA0B;QACvC,KAAK;QACL,eAAe;QACf,YAAY,EAAE,+BAA+B,CAAC,WAAW,EAAE,0BAA0B,CAAC;QACtF,UAAU;QACV,UAAU;QACV,UAAU;QACV,YAAY;QACZ,GAAG;QACH,MAAM,EAAE,EAAE;QACV,MAAM,EAAE,EAAE;QACV,MAAM,EAAE,KAAK;QACb,QAAQ,EAAE,IAAI;QACd,UAAU,EAAE,KAAK;QACjB,SAAS,EAAE,KAAK;QAChB,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,0BAA0B,EAAE,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC;QAC5D,YAAY,EAAE,EAAE;QAChB,gBAAgB,EAAE,IAAI,GAAG,EAAE;KAC5B,CAAC;IACF,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;QAChC,SAAS,CAAC,MAAM,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IACH,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;QAChC,SAAS,CAAC,MAAM,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;QAClC,qBAAqB,CAAC,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;QAC1B,SAAS,CAAC,KAAK,GAAG,KAAK,CAAC;QACxB,SAAS,CAAC,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC;QAClC,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC;IAC1B,CAAC,CAAC,CAAC;IACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,EAAE;QAC7B,SAAS,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvC,SAAS,CAAC,MAAM,GAAG,IAAI,CAAC;QACxB,SAAS,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAC9B,qBAAqB,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAC5C,iCAAiC,CAAC,SAAS,CAAC,CAAC;QAC7C,sBAAsB,CACpB,SAAS,EACT,IAAI,KAAK,CACP,mEAAmE,QAAQ,IAAI,SAAS,GAAG,CAC5F,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,qBAAqB,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAC/C,IAAI,SAAS,CAAC,MAAM,EAAE,CAAC;QACrB,uBAAuB,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAC9C,MAAM,IAAI,KAAK,CACb,gEAAgE,SAAS,CAAC,QAAQ,IAAI,SAAS,MAAM,SAAS,CAAC,MAAM,IAAI,SAAS,CAAC,MAAM,EAAE,CAC5I,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,CAAC;QAC1B,IAAI,CAAC;YACH,MAAM,oBAAoB,CAAC,SAAS,CAAC,CAAC;QACxC,CAAC;gBAAS,CAAC;YACT,uBAAuB,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAChD,CAAC;QACD,MAAM,IAAI,KAAK,CACb,yDAAyD,SAAS,CAAC,MAAM,IAAI,SAAS,CAAC,MAAM,IAAI,oBAAoB,EAAE,CACxH,CAAC;IACJ,CAAC;IACD,qBAAqB,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAC1C,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IAC/C,OAAO,CAAC,KAAK,CAAC,wDAAwD,GAAG,WAAW,UAAU,EAAE,CAAC,CAAC;IAClG,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,uFAAuF;AACvF,MAAM,CAAC,KAAK,UAAU,oCAAoC,CACxD,GAAW,EACX,UAAkB,EAClB,SAAS,GAAG,MAAM;IAElB,MAAM,SAAS,GAAG,qBAAqB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACjD,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,MAAM;QAAE,OAAO,SAAS,CAAC;IACrD,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5D,EAAE,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACvC,OAAO,IAAI,OAAO,CAA0B,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC9D,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,SAAS,CAAC,gBAAgB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YAC9C,MAAM,CACJ,IAAI,KAAK,CACP,0DAA0D,SAAS,OAAO,UAAU,EAAE,CACvF,CACF,CAAC;QACJ,CAAC,EAAE,SAAS,CAAC,CAAC;QACd,SAAS,CAAC,gBAAgB,CAAC,GAAG,CAAC,UAAU,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACnF,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,YAAY,UAAU,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE;YAChE,IAAI,CAAC,KAAK;gBAAE,OAAO;YACnB,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,SAAS,CAAC,gBAAgB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YAC9C,MAAM,CAAC,KAAK,CAAC,CAAC;QAChB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,SAA4C,EAC5C,MAAwB;IAExB,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,SAAS;QAAE,OAAO;IAC9C,SAAS,CAAC,SAAS,GAAG,IAAI,CAAC;IAC3B,IAAI,CAAC;QACH,MAAM,oBAAoB,CAAC,SAAS,CAAC,CAAC;QACtC,MAAM,UAAU,GAAG,MAAM,yBAAyB,CAAC,SAAS,CAAC,CAAC;QAC9D,IAAI,UAAU,CAAC,EAAE,KAAK,KAAK,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CACb,qEAAqE,UAAU,CAAC,MAAM,EAAE,CACzF,CAAC;QACJ,CAAC;QACD,wBAAwB,CAAC,SAAS,CAAC,CAAC;QACpC,IAAI,MAAM;YAAE,MAAM,8BAA8B,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACtE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,MAAM;YAAE,mCAAmC,CAAC,MAAM,EAAE,SAAS,CAAC,YAAY,CAAC,CAAC;QAChF,MAAM,KAAK,CAAC;IACd,CAAC;YAAS,CAAC;QACT,qBAAqB,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAC5C,iCAAiC,CAAC,SAAS,CAAC,CAAC;QAC7C,uBAAuB,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IAChD,CAAC;AACH,CAAC;AAED,KAAK,UAAU,oBAAoB,CAAC,SAAgC;IAClE,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;QAC1D,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACpC,MAAM,oBAAoB,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAChD,CAAC;IACD,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;QACtB,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC/B,MAAM,oBAAoB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAC/C,CAAC;IACD,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;QACtB,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAChC,MAAM,oBAAoB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAC/C,CAAC;IACD,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;QACtB,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAChC,MAAM,oBAAoB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAC/C,CAAC;IACD,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CACb,sDAAsD,SAAS,CAAC,KAAK,CAAC,GAAG,IAAI,SAAS,EAAE,CACzF,CAAC;IACJ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,oBAAoB,CACjC,SAAgC,EAChC,SAAiB;IAEjB,IAAI,SAAS,CAAC,MAAM;QAAE,OAAO;IAC7B,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QAClC,MAAM,MAAM,GAAG,GAAG,EAAE;YAClB,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,SAAS,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAChD,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC;QACF,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAC5C,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACtC,IAAI,SAAS,CAAC,MAAM;YAAE,MAAM,EAAE,CAAC;IACjC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,qBAAqB,CAClC,SAAgC,EAChC,SAAiB;IAEjB,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;IACxC,OAAO,CAAC,SAAS,CAAC,UAAU,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;QAC3E,MAAM,KAAK,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,SAAS,qBAAqB,CAAC,SAAgC,EAAE,KAAa;IAC5E,SAAS,CAAC,YAAY,IAAI,KAAK,CAAC;IAChC,IAAI,YAAY,GAAG,SAAS,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,OAAO,YAAY,KAAK,CAAC,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,SAAS,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC,IAAI,EAAE,CAAC;QAClE,SAAS,CAAC,YAAY,GAAG,SAAS,CAAC,YAAY,CAAC,KAAK,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC;QACxE,IAAI,IAAI;YAAE,wBAAwB,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QACpD,YAAY,GAAG,SAAS,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,CAAC;AACH,CAAC;AAED,SAAS,wBAAwB,CAAC,SAAgC,EAAE,IAAY;IAC9E,IAAI,KAA8B,CAAC;IACnC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,OAAO;QAC3E,KAAK,GAAG,MAAiC,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,uEAAuE;QACvE,8DAA8D;QAC9D,OAAO;IACT,CAAC;IACD,IACE,KAAK,CAAC,IAAI,KAAK,MAAM;QACrB,OAAO,KAAK,CAAC,GAAG,KAAK,QAAQ;QAC7B,0BAA0B,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAC1C,CAAC;QACD,SAAS,CAAC,UAAU,GAAG,IAAI,CAAC;IAC9B,CAAC;IACD,IAAI,KAAK,CAAC,IAAI,KAAK,iBAAiB,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,UAAU,EAAE,CAAC;QAC9E,SAAS,CAAC,cAAc,GAAG,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;QAChF,IAAI,OAAO,KAAK,CAAC,YAAY,KAAK,QAAQ;YAAE,SAAS,CAAC,oBAAoB,GAAG,KAAK,CAAC,YAAY,CAAC;IAClG,CAAC;IACD,MAAM,MAAM,GAAG,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3E,IAAI,CAAC,MAAM;QAAE,OAAO;IACpB,MAAM,OAAO,GAAG,SAAS,CAAC,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACvD,IAAI,CAAC,OAAO;QAAE,OAAO;IACrB,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QAC9B,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC5B,SAAS,CAAC,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC1C,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACvB,OAAO;IACT,CAAC;IACD,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC3B,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC5B,SAAS,CAAC,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC1C,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,IAAI,mCAAmC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;IAClG,CAAC;AACH,CAAC;AAED,SAAS,sBAAsB,CAAC,SAAgC,EAAE,KAAY;IAC5E,KAAK,MAAM,OAAO,IAAI,SAAS,CAAC,gBAAgB,CAAC,MAAM,EAAE,EAAE,CAAC;QAC1D,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC5B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACxB,CAAC;IACD,SAAS,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC;AACrC,CAAC;AAED,KAAK,UAAU,yBAAyB,CACtC,SAAgC;IAEhC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,CAAC;QACzC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,kBAAkB,SAAS,CAAC,UAAU,EAAE,EAAE,CAAC;IACzE,CAAC;IACD,MAAM,UAAU,GAAG,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IACtD,IAAI,UAAU,CAAC,cAAc,EAAE,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC;QACxD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,6BAA6B,SAAS,CAAC,UAAU,EAAE,EAAE,CAAC;IACpF,CAAC;IACD,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC;IAC7B,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;QACf,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,SAAS,CAAC,UAAU,EAAE,EAAE,CAAC;IACvE,CAAC;IACD,MAAM,cAAc,GAAG,GAAG,SAAS,CAAC,MAAM,KAAK,SAAS,CAAC,MAAM,EAAE,CAAC;IAClE,IAAI,SAAS,CAAC,YAAY,EAAE,CAAC;QAC3B,IAAI,CAAC,SAAS,CAAC,cAAc;YAC3B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,oCAAoC,EAAE,CAAC;QACrE,SAAS,CAAC,oBAAoB,GAAG,MAAM,yBAAyB,CAAC,SAAS,CAAC,CAAC;QAC5E,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACtB,CAAC;IACD,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC;QAChD,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,qDAAqD,SAAS,CAAC,UAAU,KAAK,cAAc,CAAC,IAAI,EAAE,IAAI,oBAAoB,EAAE;SACtI,CAAC;IACJ,CAAC;IAED,MAAM,OAAO,GAAG,SAAS,CACvB,SAAS,EACT;QACE,cAAc;QACd,IAAI;QACJ,OAAO;QACP,eAAe;QACf,iBAAiB;QACjB,KAAK;QACL,oCAAoC;QACpC,SAAS,CAAC,UAAU;KACrB,EACD,EAAE,QAAQ,EAAE,MAAM,EAAE,CACrB,CAAC;IACF,IAAI,OAAO,CAAC,KAAK,IAAK,OAAO,CAAC,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAChF,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACtB,CAAC;IACD,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,sBAAsB,SAAS,CAAC,UAAU,KAAK,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE;SAC/E,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,eAAe,SAAS,CAAC,UAAU,KAAK,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,kBAAkB,OAAO,CAAC,MAAM,EAAE,EAAE;SACvI,CAAC;IACJ,CAAC;IACD,MAAM,eAAe,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IACtD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,eAAe,IAAI,CAAC,EAAE,CAAC;QAC9D,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,iCAAiC,SAAS,CAAC,UAAU,EAAE,EAAE,CAAC;IACxF,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;AACtB,CAAC;AAED,KAAK,UAAU,yBAAyB,CACtC,SAAgC;IAEhC,IAAI,CAAC;QACH,IAAI,CAAC,SAAS,CAAC,oBAAoB;YACjC,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;QAClE,MAAM,OAAO,GAAG,SAAS,CAAC,UAAU,GAAG,cAAc,CAAC;QACtD,MAAM,KAAK,GAAG,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACpC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,cAAc,EAAE;YAC3C,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAC1D,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;QAC5D,IAAI,MAAM,CAAC,YAAY,KAAK,SAAS,CAAC,oBAAoB;YACxD,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QACxD,OAAO,MAAM,uBAAuB,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IAC7D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,2EAA2E;QAC3E,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;AAED,SAAS,kCAAkC,CACzC,YAAoB,EACpB,UAAkB;IAKlB,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3C,wBAAwB,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,SAAS,CAAC,CAAC;IAChE,iCAAiC,CAAC,UAAU,CAAC,CAAC;IAC9C,MAAM,UAAU,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,WAAW,EAAE,CAAC,IAAI,aAAa,CAAC,CAAC,CAAC;IAC7F,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IAChC,OAAO;QACL,UAAU;QACV,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC;KAClD,CAAC;AACJ,CAAC;AAED,SAAS,wBAAwB,CAAC,aAAqB,EAAE,SAAiB;IACxE,EAAE,CAAC,SAAS,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACjD,yBAAyB,CAAC,aAAa,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;IACzD,IAAI,OAAO,GAAG,aAAa,CAAC;IAC5B,KAAK,MAAM,OAAO,IAAI,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QAC/D,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACtC,IAAI,CAAC;YACH,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ;gBAAE,MAAM,KAAK,CAAC;QACtE,CAAC;QACD,yBAAyB,CAAC,OAAO,CAAC,CAAC;IACrC,CAAC;AACH,CAAC;AAED,SAAS,yBAAyB,CAAC,SAAiB;IAClD,MAAM,KAAK,GAAG,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IACtC,IAAI,KAAK,CAAC,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE;QAAE,OAAO;IAC3D,MAAM,IAAI,KAAK,CACb,iDAAiD,SAAS,IAAI;QAC5D,iBAAiB,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,iDAAiD,CAC9F,CAAC;AACJ,CAAC;AAED,SAAS,wBAAwB,CAAC,SAAgC;IAChE,2BAA2B,CAAC,SAAS,CAAC,UAAU,EAAE,SAAS,CAAC,UAAU,CAAC,CAAC;IACxE,IAAI,SAAS,CAAC,oBAAoB,EAAE,MAAM,EAAE,CAAC;QAC3C,IAAI,CAAC;YACH,2BAA2B,CACzB,SAAS,CAAC,UAAU,GAAG,cAAc,EACrC,SAAS,CAAC,UAAU,GAAG,cAAc,CACtC,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,uEAAuE;YACvE,SAAS,CAAC,oBAAoB,GAAG;gBAC/B,uBAAuB,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;aAChF,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,2BAA2B,CAAC,UAAkB,EAAE,UAAkB;IACzE,MAAM,QAAQ,GAAG,EAAE,CAAC,SAAS,CAAC,UAAU,IAAI,CAAC,CAAC;IAC9C,IAAI,UAA8B,CAAC;IACnC,IAAI,CAAC;QACH,UAAU,GAAG,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,GAAG,QAAQ,CAAC,CAAC;QACvE,MAAM,UAAU,GAAG,EAAE,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAC5C,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC;YACzB,MAAM,4BAA4B,CAAC,UAAU,CAAC,CAAC;QACjD,CAAC;QACD,EAAE,CAAC,UAAU,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IACnC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC;YAAE,MAAM,KAAK,CAAC;QAC3E,MAAM,4BAA4B,CAChC,UAAU,EACV,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CACvD,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,IAAI,UAAU,KAAK,SAAS;YAAE,EAAE,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IACzD,CAAC;IACD,iCAAiC,CAAC,UAAU,CAAC,CAAC;IAC9C,EAAE,CAAC,UAAU,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;AACxC,CAAC;AAED,SAAS,iCAAiC,CAAC,UAAkB;IAC3D,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,EAAE,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QAC7C,IAAI,WAAW,CAAC,cAAc,EAAE,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CACb,oDAAoD,UAAU,IAAI;gBAChE,eAAe,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,wBAAwB,CACpE,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CACb,qDAAqD,UAAU,IAAI;gBACjE,gBAAgB,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,wBAAwB,CACrE,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO;QAC/D,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,4BAA4B,CAAC,UAAkB,EAAE,MAAe;IACvE,OAAO,IAAI,KAAK,CACd,+DAA+D,UAAU,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK;QAC3G,oCAAoC,CACvC,CAAC;AACJ,CAAC;AAED,SAAS,uBAAuB,CAAC,UAAkB;IACjD,IAAI,CAAC;QACH,EAAE,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CACX,2DAA2D,UAAU,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CACnI,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,iCAAiC,CAAC,SAAgC;IACzE,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,YAAY,CAAC,KAAK,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC;QAAE,OAAO;IAC1E,IAAI,SAAS,CAAC,0BAA0B,KAAK,SAAS,EAAE,CAAC;QACvD,OAAO,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QAC3C,OAAO;IACT,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,YAAY,CAAC,GAAG,SAAS,CAAC,0BAA0B,CAAC;AAC7E,CAAC;AAED,KAAK,UAAU,8BAA8B,CAC3C,MAAuB,EACvB,SAAgC;IAEhC,MAAM,YAAY,GAAG,MAAM,CAAC,oBAAoB,CAAC;IACjD,IAAI,CAAC,YAAY,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAClD,OAAO,CAAC,KAAK,CACX,iEAAiE,YAAY,IAAI,SAAS,EAAE,CAC7F,CAAC;QACF,OAAO;IACT,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAEhE,CAAC;IACF,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;QAAE,QAAQ,CAAC,SAAS,GAAG,EAAE,CAAC;IAChE,QAAQ,CAAC,SAAS,GAAG,QAAQ,CAAC,SAAS,CAAC,MAAM,CAC5C,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,KAAK,SAAS,CAAC,YAAY,CACvD,CAAC;IACF,MAAM,MAAM,GAAG,SAAS,CAAC,YAAY;QACnC,CAAC,CAAC,CAAC,SAAS,CAAC,oBAAoB,IAAI;YACjC,uBAAuB,EAAE,qCAAqC;SAC/D,CAAC;QACJ,CAAC,CAAC,MAAM,mBAAmB,CAAC,SAAS,CAAC,UAAU,EAAE;YAC9C,eAAe,EAAE,SAAS,CAAC,eAAe;YAC1C,eAAe,EAAE,SAAS,CAAC,eAAe,IAAI,IAAI,CAAC,GAAG,EAAE;SACzD,CAAC,CAAC;IACP,IAAI,SAAS,CAAC,oBAAoB,EAAE,MAAM;QACxC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC;YACtB,IAAI,EAAE,SAAS,CAAC,YAAY,GAAG,cAAc;YAC7C,IAAI,EAAE,MAAM;YACZ,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,wCAAwC;SAChD,CAAC,CAAC;IACL,IAAI,YAAgC,CAAC;IACrC,IAAI,yBAAyB,GAAG,MAAM,CAAC,uBAAuB,CAAC;IAC/D,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAClB,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;YAClE,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC;YACrD,YAAY,GAAG,MAAM,sBAAsB,CACzC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,EAC1B,SAAS,CAAC,YAAY,EACtB,MAAM,CAAC,MAAM,EACb,KAAK,CACN,CAAC;YACF,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC;gBACtB,IAAI,EAAE,YAAY;gBAClB,IAAI,EAAE,MAAM;gBACZ,KAAK,EAAE,qCAAqC;gBAC5C,QAAQ,EAAE,QAAQ;aACnB,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,0EAA0E;YAC1E,yBAAyB,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACrF,CAAC;IACH,CAAC;IACD,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC;QACtB,IAAI,EAAE,SAAS,CAAC,YAAY;QAC5B,IAAI,EAAE,OAAO;QACb,KAAK,EAAE,0BAA0B;QACjC,QAAQ,EAAE,UAAU;QACpB,QAAQ,EAAE,WAAW;QACrB,MAAM,EAAE,UAAU;QAClB,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,yBAAyB,EAAE,CAAC;QACpE,QAAQ,EAAE;YACR,QAAQ,EAAE,gBAAgB;YAC1B,IAAI,EAAE,UAAU;YAChB,GAAG,EAAE,SAAS,CAAC,GAAG;SACnB;KACF,CAAC,CAAC;IACH,EAAE,CAAC,aAAa,CAAC,YAAY,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AAC3E,CAAC;AAED,SAAS,mCAAmC,CAAC,MAAuB,EAAE,YAAoB;IACxF,MAAM,YAAY,GAAG,MAAM,CAAC,oBAAoB,CAAC;IACjD,IAAI,CAAC,YAAY,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC;QAAE,OAAO;IAC1D,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAEhE,CAAC;IACF,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;QAAE,OAAO;IAC/C,MAAM,aAAa,GAAG,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC;IAC9F,IAAI,aAAa,CAAC,MAAM,KAAK,QAAQ,CAAC,SAAS,CAAC,MAAM;QAAE,OAAO;IAC/D,QAAQ,CAAC,SAAS,GAAG,aAAa,CAAC;IACnC,EAAE,CAAC,aAAa,CAAC,YAAY,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AAC3E,CAAC;AAED,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { AdapterBrowser } from '@farmslot/adapter-sdk';
2
+ export interface RunReport {
3
+ path: string;
4
+ preview: string[];
5
+ }
6
+ export declare function writeRunReport(result: {
7
+ summaryPath: string;
8
+ tracePath: string;
9
+ artifactManifestPath: string;
10
+ }): RunReport;
11
+ export declare function indexProductProvenanceArtifact(artifactManifestPath: string, target: string, adapter: string, browser?: AdapterBrowser | null): void;
12
+ export declare function recipeCdpPorts(request: {
13
+ env?: Record<string, string | undefined>;
14
+ params?: Record<string, unknown>;
15
+ recipeDocument?: unknown;
16
+ recipePath?: string;
17
+ }): string[];
18
+ export declare function executedBrowser(adapter: string, target: string, artifactManifestPath: string, ports: string[]): AdapterBrowser | null;
19
+ //# sourceMappingURL=run-report.d.ts.map