humanish 0.102.0 → 0.103.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 (85) hide show
  1. package/README.md +2 -1
  2. package/dist/browser-control-client.d.ts +3 -1
  3. package/dist/browser-control-client.js +41 -5
  4. package/dist/browser-control-client.js.map +1 -1
  5. package/dist/browser-control-dispatcher.d.ts +6 -1
  6. package/dist/browser-control-dispatcher.js +38 -3
  7. package/dist/browser-control-dispatcher.js.map +1 -1
  8. package/dist/browser-control-protocol.d.ts +24 -0
  9. package/dist/browser-control-protocol.js +7 -4
  10. package/dist/browser-control-protocol.js.map +1 -1
  11. package/dist/browser-control-recording-transfer.d.ts +4 -0
  12. package/dist/browser-control-recording-transfer.js +42 -0
  13. package/dist/browser-control-recording-transfer.js.map +1 -0
  14. package/dist/browser-control-transport.d.ts +3 -0
  15. package/dist/browser-control-transport.js +23 -2
  16. package/dist/browser-control-transport.js.map +1 -1
  17. package/dist/cua-actor-lab.d.ts +5 -2
  18. package/dist/cua-actor-lab.js +9 -1
  19. package/dist/cua-actor-lab.js.map +1 -1
  20. package/dist/cua-desktop-lane.d.ts +1 -1
  21. package/dist/desktop-recorder.d.ts +39 -0
  22. package/dist/desktop-recorder.js +220 -0
  23. package/dist/desktop-recorder.js.map +1 -0
  24. package/dist/desktop-recording-artifact.d.ts +5 -0
  25. package/dist/desktop-recording-artifact.js +54 -0
  26. package/dist/desktop-recording-artifact.js.map +1 -0
  27. package/dist/desktop-recording-types.d.ts +24 -0
  28. package/dist/desktop-recording-types.js +14 -0
  29. package/dist/desktop-recording-types.js.map +1 -0
  30. package/dist/doctor-lab.js +1 -1
  31. package/dist/doctor-lab.js.map +1 -1
  32. package/dist/e2b-cua-desktop.js +31 -7
  33. package/dist/e2b-cua-desktop.js.map +1 -1
  34. package/dist/e2b-desktop-launch.d.ts +8 -0
  35. package/dist/e2b-desktop-launch.js.map +1 -1
  36. package/dist/e2b-desktop-recording.d.ts +16 -0
  37. package/dist/e2b-desktop-recording.js +162 -0
  38. package/dist/e2b-desktop-recording.js.map +1 -0
  39. package/dist/export-bundle.js +2 -0
  40. package/dist/export-bundle.js.map +1 -1
  41. package/dist/export.js +19 -3
  42. package/dist/export.js.map +1 -1
  43. package/dist/guest-bootstrap.d.ts +4 -2
  44. package/dist/guest-bootstrap.js +14 -8
  45. package/dist/guest-bootstrap.js.map +1 -1
  46. package/dist/guest-runtime-desktop.d.ts +3 -1
  47. package/dist/guest-runtime-desktop.js +44 -2
  48. package/dist/guest-runtime-desktop.js.map +1 -1
  49. package/dist/guest-runtime-main.js +3 -2
  50. package/dist/guest-runtime-main.js.map +1 -1
  51. package/dist/guest-runtime.d.ts +7 -2
  52. package/dist/guest-runtime.js +3 -2
  53. package/dist/guest-runtime.js.map +1 -1
  54. package/dist/lab-config.d.ts +4 -0
  55. package/dist/lab-config.js +11 -0
  56. package/dist/lab-config.js.map +1 -1
  57. package/dist/lab-summary.js +1 -1
  58. package/dist/lab-summary.js.map +1 -1
  59. package/dist/local-firecracker-desktop.d.ts +7 -1
  60. package/dist/local-firecracker-desktop.js +10 -2
  61. package/dist/local-firecracker-desktop.js.map +1 -1
  62. package/dist/local-firecracker-study.js +14 -2
  63. package/dist/local-firecracker-study.js.map +1 -1
  64. package/dist/local-runtime-release.js +8 -8
  65. package/dist/observer-app.html +9 -9
  66. package/dist/observer-serve.js +1 -1
  67. package/dist/observer-serve.js.map +1 -1
  68. package/dist/observer.d.ts +2 -2
  69. package/dist/observer.js +106 -27
  70. package/dist/observer.js.map +1 -1
  71. package/dist/run.d.ts +4 -2
  72. package/dist/run.js +49 -9
  73. package/dist/run.js.map +1 -1
  74. package/dist/selected-output-paths.d.ts +3 -0
  75. package/dist/selected-output-paths.js +29 -17
  76. package/dist/selected-output-paths.js.map +1 -1
  77. package/docs/architecture/desktop-recording.md +65 -0
  78. package/docs/architecture/participant-media.md +4 -4
  79. package/docs/contracts/run-bundle.md +27 -0
  80. package/docs/contracts/schemas.md +1 -1
  81. package/docs/goals/current.md +5 -5
  82. package/docs/ramp/README.md +5 -1
  83. package/docs/release/0.103.0-desktop-recording.md +29 -0
  84. package/package.json +1 -1
  85. package/skills/humanish/SKILL.md +6 -0
@@ -11,7 +11,7 @@ export interface ReadyCuaDesktop {
11
11
  };
12
12
  }
13
13
  /** Existing bundle fields. Provider-specific facts remain optional and must be measured. */
14
- export type DesktopLaneEvidence = Pick<LaneRunOutcome, 'sandboxId' | 'desktopDurationMs' | 'desktopResources' | 'killed' | 'streamUrlPresent' | 'subjectCommit' | 'desktopBrowser' | 'desktopGeometry' | 'stateStepRecords' | 'phaseRecords' | 'failureCode' | 'commsArtifactPath'>;
14
+ export type DesktopLaneEvidence = Pick<LaneRunOutcome, 'sandboxId' | 'desktopDurationMs' | 'desktopResources' | 'killed' | 'streamUrlPresent' | 'subjectCommit' | 'desktopBrowser' | 'desktopGeometry' | 'stateStepRecords' | 'phaseRecords' | 'failureCode' | 'commsArtifactPath' | 'recording'>;
15
15
  /** One lane owns its desktop through preparation failure and final evidence collection.
16
16
  * Call methods sequentially: prepare, openSession, then finalize in a finally block.
17
17
  * finalize must be idempotent, record unavailable evidence/cleanup as warnings, and not throw.
@@ -0,0 +1,39 @@
1
+ import { type DesktopRecordingMetadata } from "./desktop-recording-types.js";
2
+ export type DesktopRecordingAudioSource = "microphone-input" | "speaker-output";
3
+ export interface DesktopRecorderCommandOptions {
4
+ display: string;
5
+ width: number;
6
+ height: number;
7
+ outputPath: string;
8
+ frameRate?: number;
9
+ audioSources?: readonly DesktopRecordingAudioSource[];
10
+ }
11
+ export interface DesktopRecorderResult {
12
+ metadata: DesktopRecordingMetadata;
13
+ outputPath: string;
14
+ }
15
+ export interface DesktopRecorderHandle {
16
+ readonly env: Readonly<Record<string, string>>;
17
+ readonly outputPath: string;
18
+ finish(): Promise<DesktopRecorderResult>;
19
+ }
20
+ /** One fixed, ordinary FFmpeg recipe. Adapters own process transport and the output path. */
21
+ export declare function buildDesktopRecorderCommand(options: DesktopRecorderCommandOptions, startedAtMs: number): {
22
+ binary: "/usr/bin/ffmpeg";
23
+ args: string[];
24
+ };
25
+ export declare function buildDesktopRecorderPulseSetupCommands(): Array<{
26
+ binary: "/usr/bin/pactl";
27
+ args: string[];
28
+ }>;
29
+ export declare function buildDesktopRecorderProbeCommand(outputPath: string): {
30
+ binary: "/usr/bin/ffprobe";
31
+ args: string[];
32
+ };
33
+ export declare function parseDesktopRecorderDuration(output: string): number;
34
+ /** Guest-local lifecycle. Recorder faults are reported only when evidence is finalized. */
35
+ export declare function startDesktopRecorder(options: DesktopRecorderCommandOptions & {
36
+ env: Readonly<Record<string, string>>;
37
+ signal: AbortSignal;
38
+ pulseReady?: boolean;
39
+ }): Promise<DesktopRecorderHandle>;
@@ -0,0 +1,220 @@
1
+ import { spawn } from "node:child_process";
2
+ import { stat } from "node:fs/promises";
3
+ import { isAbsolute, normalize } from "node:path";
4
+ import { setTimeout as delay } from "node:timers/promises";
5
+ import { DESKTOP_RECORDING_MAX_BYTES } from "./desktop-recording-types.js";
6
+ const PULSE_DEVICE = Object.freeze({
7
+ "microphone-input": "humanish_mic.monitor",
8
+ "speaker-output": "humanish_speaker.monitor"
9
+ });
10
+ const COMBINED_PULSE_DEVICE = "humanish_recording.monitor";
11
+ const RECORDING_FILE_LIMIT_BYTES = DESKTOP_RECORDING_MAX_BYTES - 1024 * 1024;
12
+ function validInteger(value, maximum) {
13
+ return Number.isInteger(value) && value > 0 && value <= maximum;
14
+ }
15
+ function validate(options) {
16
+ if (!/^:[0-9]{1,5}$/.test(options.display)
17
+ || !validInteger(options.width, 4096) || !validInteger(options.height, 4096)
18
+ || !validInteger(options.frameRate ?? 15, 60)
19
+ || !isAbsolute(options.outputPath) || normalize(options.outputPath) !== options.outputPath
20
+ || !/^\/[A-Za-z0-9._/-]+$/.test(options.outputPath))
21
+ throw new Error("Invalid desktop recording configuration.");
22
+ const sources = options.audioSources ?? [];
23
+ if (sources.length > 2 || new Set(sources).size !== sources.length
24
+ || sources.some(source => !Object.hasOwn(PULSE_DEVICE, source)))
25
+ throw new Error("Invalid desktop recording audio sources.");
26
+ return sources;
27
+ }
28
+ /** One fixed, ordinary FFmpeg recipe. Adapters own process transport and the output path. */
29
+ export function buildDesktopRecorderCommand(options, startedAtMs) {
30
+ const sources = validate(options);
31
+ if (!Number.isSafeInteger(startedAtMs) || startedAtMs < 1)
32
+ throw new Error("Invalid desktop recording start time.");
33
+ // Both live inputs use wall-clock timestamps; one output origin preserves their offset.
34
+ // Bound raw video buffering separately from the much smaller audio packets.
35
+ const args = ["-nostdin", "-v", "error", "-y", "-copyts", "-thread_queue_size", "32", "-probesize", "32", "-analyzeduration", "0",
36
+ "-f", "x11grab", "-framerate", String(options.frameRate ?? 15),
37
+ "-video_size", `${options.width}x${options.height}`, "-i", options.display];
38
+ const devices = sources.length === 2 ? [COMBINED_PULSE_DEVICE] : sources.map(source => PULSE_DEVICE[source]);
39
+ for (const device of devices)
40
+ args.push("-thread_queue_size", "512", "-probesize", "32", "-analyzeduration", "0", "-fflags", "nobuffer", "-f", "pulse", "-sample_rate", "48000", "-channels", "2", "-i", device);
41
+ if (devices.length === 1)
42
+ args.push("-map", "0:v", "-map", "1:a");
43
+ else
44
+ args.push("-map", "0:v");
45
+ args.push("-vf", "pad=ceil(iw/2)*2:ceil(ih/2)*2", "-c:v", "libx264", "-preset", "ultrafast", "-crf", "28", "-pix_fmt", "yuv420p");
46
+ if (sources.length > 0)
47
+ args.push("-c:a", "aac");
48
+ args.push("-fs", String(RECORDING_FILE_LIMIT_BYTES), "-movflags", "+faststart", "-output_ts_offset", String(-startedAtMs / 1000), options.outputPath);
49
+ return { binary: "/usr/bin/ffmpeg", args };
50
+ }
51
+ export function buildDesktopRecorderPulseSetupCommands() {
52
+ return [
53
+ ["load-module", "module-null-sink", "sink_name=humanish_recording", "sink_properties=device.description=HumanishRecordingMix"],
54
+ ["set-sink-volume", "humanish_recording", "0.5"],
55
+ ["load-module", "module-loopback", "source=humanish_mic.monitor", "sink=humanish_recording", "latency_msec=20"],
56
+ ["load-module", "module-loopback", "source=humanish_speaker.monitor", "sink=humanish_recording", "latency_msec=20"]
57
+ ].map(args => ({ binary: "/usr/bin/pactl", args }));
58
+ }
59
+ export function buildDesktopRecorderProbeCommand(outputPath) {
60
+ validate({ display: ":0", width: 1, height: 1, outputPath });
61
+ return { binary: "/usr/bin/ffprobe", args: ["-v", "error", "-show_entries", "format=duration", "-of", "default=noprint_wrappers=1:nokey=1", outputPath] };
62
+ }
63
+ export function parseDesktopRecorderDuration(output) {
64
+ if (!/^[0-9]+(?:\.[0-9]+)?\s*$/.test(output))
65
+ throw new Error("Desktop recording duration was invalid.");
66
+ const durationMs = Math.round(Number(output.trim()) * 1000);
67
+ if (!Number.isSafeInteger(durationMs) || durationMs < 1)
68
+ throw new Error("Desktop recording duration was invalid.");
69
+ return durationMs;
70
+ }
71
+ function waitForClose(child) {
72
+ return new Promise((resolve, reject) => {
73
+ child.once("error", reject);
74
+ child.once("close", (code, signal) => resolve({ code, signal }));
75
+ });
76
+ }
77
+ async function run(binary, args, env, signal) {
78
+ signal.throwIfAborted();
79
+ const child = spawn(binary, args, { env, stdio: "ignore" });
80
+ const abort = () => { if (child.exitCode === null && child.signalCode === null)
81
+ child.kill("SIGKILL"); };
82
+ signal.addEventListener("abort", abort, { once: true });
83
+ try {
84
+ const result = await waitForClose(child);
85
+ if (result.code !== 0)
86
+ throw new Error("Desktop recording audio setup failed.");
87
+ }
88
+ finally {
89
+ signal.removeEventListener("abort", abort);
90
+ }
91
+ }
92
+ async function startPulse(env, signal) {
93
+ const pulse = spawn("/usr/bin/pulseaudio", ["--daemonize=no", "--exit-idle-time=-1", "--disallow-exit", "--log-target=stderr"], { env, stdio: "ignore" });
94
+ const closed = waitForClose(pulse);
95
+ void closed.catch(() => { });
96
+ try {
97
+ let ready = false;
98
+ for (let attempt = 0; attempt < 100; attempt++) {
99
+ try {
100
+ await run("/usr/bin/pactl", ["info"], env, signal);
101
+ ready = true;
102
+ break;
103
+ }
104
+ catch {
105
+ await delay(50, undefined, { signal });
106
+ }
107
+ }
108
+ if (!ready)
109
+ throw new Error("Desktop recording audio setup failed.");
110
+ await run("/usr/bin/pactl", ["load-module", "module-null-sink", "sink_name=humanish_mic", "sink_properties=device.description=HumanishSyntheticMicrophone"], env, signal);
111
+ await run("/usr/bin/pactl", ["load-module", "module-remap-source", "master=humanish_mic.monitor", "source_name=humanish_input", "source_properties=device.description=HumanishSyntheticMicrophone"], env, signal);
112
+ await run("/usr/bin/pactl", ["load-module", "module-null-sink", "sink_name=humanish_speaker", "sink_properties=device.description=HumanishSyntheticSpeaker"], env, signal);
113
+ await run("/usr/bin/pactl", ["set-default-source", "humanish_input"], env, signal);
114
+ await run("/usr/bin/pactl", ["set-default-sink", "humanish_speaker"], env, signal);
115
+ return { child: pulse, closed };
116
+ }
117
+ catch (error) {
118
+ await stopPulse({ child: pulse, closed });
119
+ throw error;
120
+ }
121
+ }
122
+ async function stopPulse(pulse) {
123
+ if (!pulse)
124
+ return;
125
+ if (pulse.child.exitCode === null && pulse.child.signalCode === null)
126
+ pulse.child.kill("SIGTERM");
127
+ let settled = false;
128
+ await Promise.race([pulse.closed.catch(() => { }).finally(() => { settled = true; }), delay(1500)]);
129
+ if (!settled && pulse.child.exitCode === null && pulse.child.signalCode === null)
130
+ pulse.child.kill("SIGKILL");
131
+ await Promise.race([pulse.closed.catch(() => { }), delay(500)]);
132
+ }
133
+ async function probeDuration(outputPath, env) {
134
+ const command = buildDesktopRecorderProbeCommand(outputPath);
135
+ const child = spawn(command.binary, command.args, { env, stdio: ["ignore", "pipe", "ignore"] });
136
+ let output = "";
137
+ child.stdout.on("data", (chunk) => { if (output.length < 256)
138
+ output += chunk.toString("utf8").slice(0, 256 - output.length); });
139
+ let timer;
140
+ const result = await Promise.race([waitForClose(child), new Promise((_resolve, reject) => {
141
+ timer = setTimeout(() => {
142
+ if (child.exitCode === null && child.signalCode === null)
143
+ child.kill("SIGKILL");
144
+ reject(new Error("Desktop recording probe timed out."));
145
+ }, 3000);
146
+ })]).finally(() => clearTimeout(timer));
147
+ if (result.code !== 0)
148
+ throw new Error("Desktop recording probe failed.");
149
+ return parseDesktopRecorderDuration(output);
150
+ }
151
+ /** Guest-local lifecycle. Recorder faults are reported only when evidence is finalized. */
152
+ export async function startDesktopRecorder(options) {
153
+ const sources = validate(options);
154
+ const outputPath = options.outputPath;
155
+ const pulseServer = `unix:${options.env.XDG_RUNTIME_DIR ?? "/run/humanish/xdg"}/pulse/native`;
156
+ const env = sources.length === 0 ? options.env : { ...options.env, PULSE_SERVER: pulseServer, PULSE_SOURCE: "humanish_input", PULSE_SINK: "humanish_speaker" };
157
+ const ownedPulse = sources.length > 0 && options.pulseReady !== true ? await startPulse(env, options.signal) : undefined;
158
+ if (sources.length === 2) {
159
+ try {
160
+ for (const setup of buildDesktopRecorderPulseSetupCommands())
161
+ await run(setup.binary, setup.args, env, options.signal);
162
+ }
163
+ catch (error) {
164
+ await stopPulse(ownedPulse);
165
+ throw error;
166
+ }
167
+ }
168
+ const startedAtMs = Date.now();
169
+ const command = buildDesktopRecorderCommand(options, startedAtMs);
170
+ const child = spawn(command.binary, command.args, { env, stdio: "ignore" });
171
+ const closed = waitForClose(child);
172
+ void closed.catch(() => { });
173
+ let finishing;
174
+ let abort;
175
+ const finish = () => finishing ??= (async () => {
176
+ let forced = false, requestedStop = false;
177
+ try {
178
+ if (child.exitCode === null && child.signalCode === null) {
179
+ requestedStop = child.kill("SIGINT");
180
+ }
181
+ let timer, settled = false;
182
+ await Promise.race([closed.catch(() => undefined).finally(() => { settled = true; }), new Promise(resolve => { timer = setTimeout(resolve, 3000); })])
183
+ .finally(() => clearTimeout(timer));
184
+ if (!settled && child.exitCode === null && child.signalCode === null) {
185
+ forced = true;
186
+ child.kill("SIGKILL");
187
+ }
188
+ if (!settled)
189
+ await Promise.race([closed.catch(() => undefined), delay(500)]);
190
+ const file = await stat(outputPath);
191
+ if (!file.isFile() || file.size < 1 || file.size > DESKTOP_RECORDING_MAX_BYTES)
192
+ throw new Error("Desktop recorder produced invalid output.");
193
+ const durationMs = await probeDuration(outputPath, env);
194
+ return { outputPath, metadata: { mimeType: "video/mp4", startedAt: new Date(startedAtMs).toISOString(),
195
+ durationMs, bytes: file.size, audioSources: [...sources], complete: requestedStop && !forced && file.size < RECORDING_FILE_LIMIT_BYTES } };
196
+ }
197
+ catch {
198
+ throw new Error("Desktop recording failed.");
199
+ }
200
+ finally {
201
+ if (abort)
202
+ options.signal.removeEventListener("abort", abort);
203
+ await stopPulse(ownedPulse);
204
+ }
205
+ })();
206
+ try {
207
+ await Promise.race([closed.then(() => { throw new Error("Desktop recorder exited during startup."); }), delay(150, undefined, { signal: options.signal })]);
208
+ }
209
+ catch {
210
+ if (child.exitCode === null && child.signalCode === null)
211
+ child.kill("SIGKILL");
212
+ await Promise.race([closed.catch(() => { }), delay(500)]);
213
+ await stopPulse(ownedPulse);
214
+ throw new Error("Desktop recording failed.");
215
+ }
216
+ abort = () => { void finish().catch(() => { }); };
217
+ options.signal.addEventListener("abort", abort, { once: true });
218
+ return { env, outputPath, finish };
219
+ }
220
+ //# sourceMappingURL=desktop-recorder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"desktop-recorder.js","sourceRoot":"","sources":["../src/desktop-recorder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { Writable } from "node:stream";
2
+ import { type DesktopRecordingMetadata, type RunDesktopRecording } from "./desktop-recording-types.js";
3
+ import { type PreparedOutputDirectory } from "./selected-output-paths.js";
4
+ /** Both providers stream into the same bounded artifact writer before desktop teardown. */
5
+ export declare function collectDesktopRecording(root: PreparedOutputDirectory, laneId: string, receive: (destination: Writable) => Promise<DesktopRecordingMetadata>): Promise<RunDesktopRecording>;
@@ -0,0 +1,54 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { open, rename, unlink } from "node:fs/promises";
3
+ import { Writable } from "node:stream";
4
+ import { finished } from "node:stream/promises";
5
+ import { desktopRecordingMetadataSchema, DESKTOP_RECORDING_MAX_BYTES } from "./desktop-recording-types.js";
6
+ import { assertSafeOutputPathSegment, prepareContainedOutputFile } from "./selected-output-paths.js";
7
+ /** Both providers stream into the same bounded artifact writer before desktop teardown. */
8
+ export async function collectDesktopRecording(root, laneId, receive) {
9
+ assertSafeOutputPathSegment(laneId, "Recording lane");
10
+ const path = `recordings/${laneId}/desktop.mp4`;
11
+ const target = await prepareContainedOutputFile(root, path);
12
+ const temporary = await prepareContainedOutputFile(root, `recordings/${laneId}/.recording-${randomUUID()}.mp4`);
13
+ const handle = await open(temporary, "wx", 0o600);
14
+ let bytes = 0;
15
+ const destination = new Writable({
16
+ write(chunk, _encoding, callback) {
17
+ if (bytes + chunk.length > DESKTOP_RECORDING_MAX_BYTES) {
18
+ callback(new Error("Recording exceeds the size limit."));
19
+ return;
20
+ }
21
+ // FileHandle.write can write fewer bytes than requested.
22
+ void (async () => {
23
+ let offset = 0;
24
+ while (offset < chunk.length) {
25
+ const result = await handle.write(chunk, offset, chunk.length - offset);
26
+ if (!result.bytesWritten)
27
+ throw new Error("Recording write made no progress.");
28
+ offset += result.bytesWritten;
29
+ }
30
+ bytes += chunk.length;
31
+ })().then(() => callback(), callback);
32
+ }
33
+ });
34
+ const completed = finished(destination);
35
+ void completed.catch(() => { });
36
+ try {
37
+ const metadata = desktopRecordingMetadataSchema.parse(await receive(destination));
38
+ await completed;
39
+ if (bytes !== metadata.bytes)
40
+ throw new Error("Recording transfer size does not match its metadata.");
41
+ await handle.close();
42
+ if (await prepareContainedOutputFile(root, path) !== target)
43
+ throw new Error("Recording output changed.");
44
+ await rename(temporary, target);
45
+ return { schema: "humanish.desktop-recording.v1", path, ...metadata };
46
+ }
47
+ finally {
48
+ destination.destroy();
49
+ await completed.catch(() => { });
50
+ await handle.close().catch(() => { });
51
+ await unlink(temporary).catch(() => { });
52
+ }
53
+ }
54
+ //# sourceMappingURL=desktop-recording-artifact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"desktop-recording-artifact.js","sourceRoot":"","sources":["../src/desktop-recording-artifact.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import { z } from "zod";
2
+ /** Leaves room for Chromium on the local guest's shared 512 MiB state disk. */
3
+ export declare const DESKTOP_RECORDING_MAX_BYTES: number;
4
+ export declare const desktopRecordingMetadataSchema: z.ZodObject<{
5
+ mimeType: z.ZodLiteral<"video/mp4">;
6
+ startedAt: z.ZodISODateTime;
7
+ durationMs: z.ZodNumber;
8
+ bytes: z.ZodNumber;
9
+ audioSources: z.ZodArray<z.ZodEnum<{
10
+ "microphone-input": "microphone-input";
11
+ "speaker-output": "speaker-output";
12
+ }>>;
13
+ complete: z.ZodBoolean;
14
+ }, z.core.$strict>;
15
+ export type DesktopRecordingMetadata = z.infer<typeof desktopRecordingMetadataSchema>;
16
+ /** Capture points describe recorded signals, not delivery to another caller. */
17
+ export interface RunDesktopRecording extends DesktopRecordingMetadata {
18
+ schema: "humanish.desktop-recording.v1";
19
+ path: string;
20
+ }
21
+ export declare const desktopRecordingConfigSchema: z.ZodObject<{
22
+ audio: z.ZodBoolean;
23
+ }, z.core.$strict>;
24
+ export type DesktopRecordingConfig = z.infer<typeof desktopRecordingConfigSchema>;
@@ -0,0 +1,14 @@
1
+ import { z } from "zod";
2
+ /** Leaves room for Chromium on the local guest's shared 512 MiB state disk. */
3
+ export const DESKTOP_RECORDING_MAX_BYTES = 128 * 1024 * 1024;
4
+ export const desktopRecordingMetadataSchema = z.strictObject({
5
+ mimeType: z.literal("video/mp4"),
6
+ startedAt: z.iso.datetime(),
7
+ durationMs: z.number().finite().positive(),
8
+ bytes: z.number().int().positive().max(DESKTOP_RECORDING_MAX_BYTES),
9
+ audioSources: z.array(z.enum(["microphone-input", "speaker-output"])).max(2)
10
+ .refine(values => new Set(values).size === values.length),
11
+ complete: z.boolean()
12
+ });
13
+ export const desktopRecordingConfigSchema = z.strictObject({ audio: z.boolean() });
14
+ //# sourceMappingURL=desktop-recording-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"desktop-recording-types.js","sourceRoot":"","sources":["../src/desktop-recording-types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,+EAA+E;AAC/E,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,CAAC;AAE7D,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC,YAAY,CAAC;IAC3D,QAAQ,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC;IAChC,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE;IAC3B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC1C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,2BAA2B,CAAC;IACnE,YAAY,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,kBAAkB,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;SACzE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,MAAM,CAAC;IAC3D,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE;CACtB,CAAC,CAAC;AAUH,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC"}
@@ -32,7 +32,7 @@ export async function labSetupChecks(args) {
32
32
  const checkAccount = () => accountReadiness ??= (args.codexAnalysisReadiness ?? (async (env) => (await import("./restricted-codex-analysis.js")).checkRestrictedCodexAnalysisReadiness({ timeoutMs: 5000 }, { env })))(args.env)
33
33
  .catch(() => ({ ready: false, errorCode: "codex_unavailable" }));
34
34
  if (local) {
35
- const runtime = await (args.localRuntimeReadiness ?? (() => localRuntimeStatus({ env: args.env, media: config.execution?.desktop?.media !== undefined })))();
35
+ const runtime = await (args.localRuntimeReadiness ?? (() => localRuntimeStatus({ env: args.env, media: config.execution?.desktop?.media !== undefined || config.execution?.desktop?.recording !== undefined })))();
36
36
  checks.push({ name: "local browser runtime", ok: runtime.ok, message: runtime.message });
37
37
  }
38
38
  if (config.comms?.email?.kind === "real") {
@@ -1 +1 @@
1
- {"version":3,"file":"doctor-lab.js","sourceRoot":"","sources":["../src/doctor-lab.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"doctor-lab.js","sourceRoot":"","sources":["../src/doctor-lab.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAA2B,MAAM,oBAAoB,CAAC;AAKjF,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AACzE,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAIxD,yFAAyF;AACzF,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAAC,IAGhD;IACC,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,KAAK,EAAE,GAAsB,EAAE,EAAE,CAC3E,CAAC,MAAM,MAAM,CAAC,gCAAgC,CAAC,CAAC,CAAC,qCAAqC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;SAC/H,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,mBAAmB,EAAE,CAAC,CAAC,CAAC;IACnE,OAAO,EAAE,IAAI,EAAE,kCAAkC,EAAE,EAAE,EAAE,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,CAAC,KAAK;YAC9F,CAAC,CAAC,0MAA0M;YAC5M,CAAC,CAAC,iDAAiD,SAAS,CAAC,SAAS,yGAAyG,EAAE,CAAC;AACtL,CAAC;AAED,sGAAsG;AACtG,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,IAMpC;IACC,MAAM,EAAE,kBAAkB,EAAE,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAC;IACzD,MAAM,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;IAC/E,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;IAC9D,IAAI,CAAC,QAAQ,CAAC,EAAE;QAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;IAC7H,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACnE,MAAM,MAAM,GAAG,gBAAgB,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,KAAK,IAAI,CAAC;IAClE,MAAM,MAAM,GAAY,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,IAAI;YACpD,OAAO,EAAE,GAAG,MAAM,CAAC,EAAE,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,IAAI,WAAW,MAAM,OAAO,MAAM,MAAM,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC3I,IAAI,MAAM;QAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC;IACxD,MAAM,WAAW,GAAG,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzD,IAAI,WAAW;QAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;IACnI,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,kBAAkB,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;IACtF,MAAM,KAAK,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACxC,IAAI,gBAAmF,CAAC;IACxF,MAAM,YAAY,GAAG,GAAG,EAAE,CAAC,gBAAgB,KAAK,CAAC,IAAI,CAAC,sBAAsB,IAAI,CAAC,KAAK,EAAE,GAAsB,EAAE,EAAE,CAChH,CAAC,MAAM,MAAM,CAAC,gCAAgC,CAAC,CAAC,CAAC,qCAAqC,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;SAC/H,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,mBAAmB,EAAE,CAAC,CAAC,CAAC;IACnE,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,qBAAqB,IAAI,CAAC,GAAG,EAAE,CAAC,kBAAkB,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,SAAS,EAAE,OAAO,EAAE,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,SAAS,EAAE,OAAO,EAAE,SAAS,KAAK,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnN,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,uBAAuB,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAC3F,CAAC;IACD,IAAI,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,KAAK,MAAM,EAAE,CAAC;QACzC,MAAM,IAAI,GAAG,MAAM,oBAAoB,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QACjF,IAAI,IAAI;YAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,uBAAuB,EAAE,EAAE,EAAE,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,KAAK,IAAI;gBAC7G,CAAC,CAAC,mFAAmF;gBACrF,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;oBACxB,CAAC,CAAC,WAAW,IAAI,wHAAwH;oBACzI,CAAC,CAAC,yKAAyK,EAAE,CAAC,CAAC;IACnL,CAAC;IACD,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,aAAa,CAAE,CAAC;QACvD,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,+BAA+B,EAAE,EAAE,EAAE,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,OAAO,EACpF,mKAAmK,EAAE,CAAC,CAAC;IAC3K,CAAC;SAAM,IAAI,OAAO,KAAK,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,KAAK,aAAa,EAAE,CAAC;QACzE,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,UAAU,IAAI,OAAO,CAAC;QACvD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC;QAC7D,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,CAAC,IAAI,CAAC,MAAM,0BAA0B,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC;QAC5F,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,kCAAkC,EAAE,EAAE,EAAE,KAAK,EAAE,UAAU,KAAK,eAAe,EAAE,OAAO,EACxG,KAAK,EAAE,UAAU,KAAK,eAAe,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,mHAAmH;oBACvK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,UAAU,KAAK,iBAAiB,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,qCAAqC,WAAW,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,oBAAoB,+CAA+C;wBAC5P,CAAC,CAAC,GAAG,MAAM,qHAAqH,EAAE,CAAC,CAAC;QAC5I,CAAC;IACH,CAAC;IACD,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC;QAC3B,MAAM,EAAE,qBAAqB,EAAE,GAAG,MAAM,MAAM,CAAC,6BAA6B,CAAC,CAAC;QAC9E,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,qBAAqB,EAAE,EAAE,OAAO,EAClF,wKAAwK,EAAE,CAAC,CAAC;IAChL,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC;QAC5C,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,eAAe,IAAI,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,OAAO,EACvG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC,CAAC,2EAA2E,EAAE,CAAC,CAAC;IAClK,CAAC;IACD,MAAM,QAAQ,GAAG,uBAAuB,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC3E,IAAI,QAAQ,EAAE,QAAQ,KAAK,OAAO,EAAE,CAAC;QACnC,MAAM,SAAS,GAAG,MAAM,YAAY,EAAE,CAAC;QACvC,MAAM,QAAQ,GAAG,SAAS,CAAC,SAAS,KAAK,4BAA4B;YACnE,CAAC,CAAC,2HAA2H;YAC7H,CAAC,CAAC,SAAS,CAAC,SAAS,KAAK,YAAY;gBACtC,CAAC,CAAC,+GAA+G;gBACjH,CAAC,CAAC,+DAA+D,CAAC;QACpE,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,EAAE,EAAE,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,CAAC,KAAK;gBACpF,CAAC,CAAC,6PAA6P;gBAC/P,CAAC,CAAC,0CAA0C,SAAS,CAAC,SAAS,IAAI,mBAAmB,MAAM,QAAQ,iEAAiE,EAAE,CAAC,CAAC;IAC7K,CAAC;SAAM,IAAI,QAAQ,EAAE,CAAC;QACpB,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC;gBAC3F,CAAC,CAAC,sHAAsH,QAAQ,CAAC,UAAU,+IAA+I;gBAC1R,CAAC,CAAC,wLAAwL,EAAE,CAAC,CAAC;IAClM,CAAC;IACD,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,KAAK,OAAO;YAClF,CAAC,CAAC,oOAAoO;YACtO,CAAC,CAAC,wJAAwJ,EAAE,CAAC,CAAC;IAChK,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AACnC,CAAC;AAED,uGAAuG;AACvG,MAAM,UAAU,kBAAkB,CAChC,MAAiB,EACjB,OAAmB,EACnB,MAAe,EACf,UAAqC;IAErC,IAAI,MAAM,IAAI,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IACxF,0EAA0E;IAC1E,MAAM,OAAO,GAAG,CAAC,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,KAAK,KAAK,IAAI,OAAO,KAAK,UAAU,IAAI,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC;WACzH,OAAO,KAAK,UAAU,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC;IAClE,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5C,IAAI,OAAO,KAAK,UAAU;QAAE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC;SACnG,IAAI,CAAC,OAAO,KAAK,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,KAAK,aAAa,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC;QAAE,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAC1I,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;AAC3B,CAAC;AAED,SAAS,mBAAmB,CAAC,MAAiB,EAAE,OAAmB;IACjE,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,WAAW;QAAE,OAAO,+GAA+G,CAAC;IAClK,IAAI,OAAO,KAAK,MAAM;QAAE,OAAO,kIAAkI,CAAC;IAClK,IAAI,OAAO,KAAK,WAAW;QAAE,OAAO,oGAAoG,CAAC;IACzI,IAAI,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,KAAK,qBAAqB;QAAE,OAAO,iIAAiI,CAAC;IACnO,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -5,9 +5,11 @@ import { buildOriginMap } from "./comms-inbox.js";
5
5
  import { deployReceivingInbox } from "./comms-receiving-inbox.js";
6
6
  import { DEFAULT_SANDBOX_CATCH_PORT, collectCommsThread, deployCommsCatch, refreshInboxSurface, writeInboxSurface } from "./comms-sandbox-catch.js";
7
7
  import { inboxRecipientFor, laneHasInboxRecipient } from "./cua-desktop-lane.js";
8
+ import { collectDesktopRecording } from "./desktop-recording-artifact.js";
8
9
  import { BROWSER_SETTLE_MS, CUA_ACTOR_LAB_PROVIDER_METADATA, DEFAULT_MOBILE_USER_AGENT, INBOX_SURFACE_CADENCE_MS, applyMobileEmulation, captureDesktopBrowserGeometry, declaredScreenForRender, defaultSubjectPhaseSink, inspectDesktopScreenGeometry, makeChromeBrowserStateObserver, openDesktopBrowserTarget, openDesktopTerminal, prepareDesktopMedia, provisionCloneSubject, provisionDesktopCli, provisionLocalTreeSubject, startDesktopStream } from "./e2b-cua-provisioning.js";
9
10
  import { createE2BDesktopExecutor } from "./e2b-desktop-executor.js";
10
11
  import { e2bDesktopTemplate, startE2BDesktopMedia } from "./e2b-desktop-media.js";
12
+ import { startE2BDesktopRecording } from "./e2b-desktop-recording.js";
11
13
  import { loadE2BDesktopModule } from "./e2b-desktop-launch.js";
12
14
  import { observeDesktopResources } from "./e2b-desktop-resources.js";
13
15
  import { allocateE2BDesktopSession } from "./e2b-desktop-session.js";
@@ -117,6 +119,8 @@ export function createE2BCuaDesktopLane(spec, deps, warnings) {
117
119
  let allocation;
118
120
  let desktop;
119
121
  let speech;
122
+ let recording;
123
+ let recordingEvidence;
120
124
  const mediaStop = new AbortController();
121
125
  let preparationStarted = false;
122
126
  let prepared = false;
@@ -329,15 +333,26 @@ export function createE2BCuaDesktopLane(spec, deps, warnings) {
329
333
  ...(deps.hooks.detachedTimers ?? {})
330
334
  });
331
335
  }
336
+ const requestedFidelity = config.execution?.desktop?.fidelity;
337
+ const requestedMedia = config.execution?.desktop?.media;
338
+ if (!desktopCliRoute && requestedMedia?.microphone?.source === "speech") {
339
+ speech = await startE2BDesktopMedia({ desktop, media: requestedMedia, signal: mediaStop.signal,
340
+ onTerminal: () => mediaStop.abort(), requestTimeoutMs: deps.requestTimeoutMs });
341
+ }
342
+ const requestedRecording = config.execution?.desktop?.recording;
343
+ if (requestedRecording) {
344
+ try {
345
+ recording = await startE2BDesktopRecording({ desktop, width: spec.resolution[0], height: spec.resolution[1],
346
+ audio: requestedRecording.audio, ...(speech === undefined ? {} : { pulseEnv: speech.env }),
347
+ requestTimeoutMs: deps.requestTimeoutMs });
348
+ }
349
+ catch (error) {
350
+ warnings.push(`Desktop recording startup failed; the study continues without video: ${redactText(deps.scrubKnownValues(toErrorMessage(error)))}`);
351
+ }
352
+ }
332
353
  if (!desktopCliRoute) {
333
- const requestedFidelity = config.execution?.desktop?.fidelity;
334
354
  // A declared camera (#509) is in place before the browser starts: the feed is generated or
335
355
  // uploaded first, and a feed that cannot be produced fails the lane closed here.
336
- const requestedMedia = config.execution?.desktop?.media;
337
- if (requestedMedia?.microphone?.source === "speech") {
338
- speech = await startE2BDesktopMedia({ desktop, media: requestedMedia, signal: mediaStop.signal,
339
- onTerminal: () => mediaStop.abort(), requestTimeoutMs: deps.requestTimeoutMs });
340
- }
341
356
  const mediaEvidence = requestedMedia === undefined
342
357
  ? undefined
343
358
  : await prepareDesktopMedia(desktop, requestedMedia, config.policies?.mediaPermission ?? "prompt", deps.labCwd, deps.requestTimeoutMs);
@@ -349,7 +364,7 @@ export function createE2BCuaDesktopLane(spec, deps, warnings) {
349
364
  ]
350
365
  : []),
351
366
  ...(mediaEvidence?.flags ?? [])
352
- ], speech?.env);
367
+ ], speech?.env ?? recording?.env);
353
368
  desktopBrowser = mediaEvidence === undefined
354
369
  ? browserLaunch.evidence
355
370
  : { requested: config.execution?.desktop?.browser ?? "default", ...(browserLaunch.evidence ?? {}), media: mediaEvidence };
@@ -611,6 +626,14 @@ export function createE2BCuaDesktopLane(spec, deps, warnings) {
611
626
  warnings.push(`Desktop final evidence collection failed: ${redactText(deps.scrubKnownValues(toErrorMessage(error)))}`);
612
627
  }
613
628
  finally {
629
+ if (recording) {
630
+ try {
631
+ recordingEvidence = await collectDesktopRecording(deps.artifactRoot, spec.laneId, destination => recording.finish(destination));
632
+ }
633
+ catch (error) {
634
+ warnings.push(`Desktop recording collection failed: ${redactText(deps.scrubKnownValues(toErrorMessage(error)))}`);
635
+ }
636
+ }
614
637
  mediaStop.abort();
615
638
  await speech?.close().catch(() => { warnings.push("Speech worker cleanup was interrupted; desktop teardown will reclaim it."); });
616
639
  // Each route's own keep flag gates its own lane only: a clone.keep can never leak into
@@ -672,6 +695,7 @@ export function createE2BCuaDesktopLane(spec, deps, warnings) {
672
695
  streamUrlPresent: streamUrl !== undefined,
673
696
  ...(subjectCommit === undefined ? {} : { subjectCommit }),
674
697
  ...(desktopBrowser === undefined ? {} : { desktopBrowser }),
698
+ ...(recordingEvidence === undefined ? {} : { recording: recordingEvidence }),
675
699
  desktopGeometry,
676
700
  stateStepRecords,
677
701
  phaseRecords,