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.
- package/README.md +2 -1
- package/dist/browser-control-client.d.ts +3 -1
- package/dist/browser-control-client.js +41 -5
- package/dist/browser-control-client.js.map +1 -1
- package/dist/browser-control-dispatcher.d.ts +6 -1
- package/dist/browser-control-dispatcher.js +38 -3
- package/dist/browser-control-dispatcher.js.map +1 -1
- package/dist/browser-control-protocol.d.ts +24 -0
- package/dist/browser-control-protocol.js +7 -4
- package/dist/browser-control-protocol.js.map +1 -1
- package/dist/browser-control-recording-transfer.d.ts +4 -0
- package/dist/browser-control-recording-transfer.js +42 -0
- package/dist/browser-control-recording-transfer.js.map +1 -0
- package/dist/browser-control-transport.d.ts +3 -0
- package/dist/browser-control-transport.js +23 -2
- package/dist/browser-control-transport.js.map +1 -1
- package/dist/cua-actor-lab.d.ts +5 -2
- package/dist/cua-actor-lab.js +9 -1
- package/dist/cua-actor-lab.js.map +1 -1
- package/dist/cua-desktop-lane.d.ts +1 -1
- package/dist/desktop-recorder.d.ts +39 -0
- package/dist/desktop-recorder.js +220 -0
- package/dist/desktop-recorder.js.map +1 -0
- package/dist/desktop-recording-artifact.d.ts +5 -0
- package/dist/desktop-recording-artifact.js +54 -0
- package/dist/desktop-recording-artifact.js.map +1 -0
- package/dist/desktop-recording-types.d.ts +24 -0
- package/dist/desktop-recording-types.js +14 -0
- package/dist/desktop-recording-types.js.map +1 -0
- package/dist/doctor-lab.js +1 -1
- package/dist/doctor-lab.js.map +1 -1
- package/dist/e2b-cua-desktop.js +31 -7
- package/dist/e2b-cua-desktop.js.map +1 -1
- package/dist/e2b-desktop-launch.d.ts +8 -0
- package/dist/e2b-desktop-launch.js.map +1 -1
- package/dist/e2b-desktop-recording.d.ts +16 -0
- package/dist/e2b-desktop-recording.js +162 -0
- package/dist/e2b-desktop-recording.js.map +1 -0
- package/dist/export-bundle.js +2 -0
- package/dist/export-bundle.js.map +1 -1
- package/dist/export.js +19 -3
- package/dist/export.js.map +1 -1
- package/dist/guest-bootstrap.d.ts +4 -2
- package/dist/guest-bootstrap.js +14 -8
- package/dist/guest-bootstrap.js.map +1 -1
- package/dist/guest-runtime-desktop.d.ts +3 -1
- package/dist/guest-runtime-desktop.js +44 -2
- package/dist/guest-runtime-desktop.js.map +1 -1
- package/dist/guest-runtime-main.js +3 -2
- package/dist/guest-runtime-main.js.map +1 -1
- package/dist/guest-runtime.d.ts +7 -2
- package/dist/guest-runtime.js +3 -2
- package/dist/guest-runtime.js.map +1 -1
- package/dist/lab-config.d.ts +4 -0
- package/dist/lab-config.js +11 -0
- package/dist/lab-config.js.map +1 -1
- package/dist/lab-summary.js +1 -1
- package/dist/lab-summary.js.map +1 -1
- package/dist/local-firecracker-desktop.d.ts +7 -1
- package/dist/local-firecracker-desktop.js +10 -2
- package/dist/local-firecracker-desktop.js.map +1 -1
- package/dist/local-firecracker-study.js +14 -2
- package/dist/local-firecracker-study.js.map +1 -1
- package/dist/local-runtime-release.js +8 -8
- package/dist/observer-app.html +9 -9
- package/dist/observer-serve.js +1 -1
- package/dist/observer-serve.js.map +1 -1
- package/dist/observer.d.ts +2 -2
- package/dist/observer.js +106 -27
- package/dist/observer.js.map +1 -1
- package/dist/run.d.ts +4 -2
- package/dist/run.js +49 -9
- package/dist/run.js.map +1 -1
- package/dist/selected-output-paths.d.ts +3 -0
- package/dist/selected-output-paths.js +29 -17
- package/dist/selected-output-paths.js.map +1 -1
- package/docs/architecture/desktop-recording.md +65 -0
- package/docs/architecture/participant-media.md +4 -4
- package/docs/contracts/run-bundle.md +27 -0
- package/docs/contracts/schemas.md +1 -1
- package/docs/goals/current.md +5 -5
- package/docs/ramp/README.md +5 -1
- package/docs/release/0.103.0-desktop-recording.md +29 -0
- package/package.json +1 -1
- 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":"AAAA,OAAO,EAAE,KAAK,EAAqB,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EAAE,UAAU,IAAI,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,2BAA2B,EAAiC,MAAM,8BAA8B,CAAC;AAI1G,MAAM,YAAY,GAA0D,MAAM,CAAC,MAAM,CAAC;IACxF,kBAAkB,EAAE,sBAAsB;IAC1C,gBAAgB,EAAE,0BAA0B;CAC7C,CAAC,CAAC;AACH,MAAM,qBAAqB,GAAG,4BAA4B,CAAC;AAC3D,MAAM,0BAA0B,GAAG,2BAA2B,GAAG,IAAI,GAAG,IAAI,CAAC;AAsB7E,SAAS,YAAY,CAAC,KAAa,EAAE,OAAe;IAClD,OAAO,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,IAAI,OAAO,CAAC;AAClE,CAAC;AAED,SAAS,QAAQ,CAAC,OAAsC;IACtD,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC;WACrC,CAAC,YAAY,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC;WACzE,CAAC,YAAY,CAAC,OAAO,CAAC,SAAS,IAAI,EAAE,EAAE,EAAE,CAAC;WAC1C,CAAC,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,SAAS,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,OAAO,CAAC,UAAU;WACvF,CAAC,sBAAsB,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IACnH,MAAM,OAAO,GAAG,OAAO,CAAC,YAAY,IAAI,EAAE,CAAC;IAC3C,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC,MAAM;WAC7D,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC/H,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,6FAA6F;AAC7F,MAAM,UAAU,2BAA2B,CAAC,OAAsC,EAAE,WAAmB;IACrG,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAClC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,WAAW,CAAC,IAAI,WAAW,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IACpH,wFAAwF;IACxF,4EAA4E;IAC5E,MAAM,IAAI,GAAG,CAAC,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,oBAAoB,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,kBAAkB,EAAE,GAAG;QAC/H,IAAI,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,CAAC,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC;QAC9D,aAAa,EAAE,GAAG,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9E,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC;IAC7G,KAAK,MAAM,MAAM,IAAI,OAAO;QAAE,IAAI,CAAC,IAAI,CAAC,oBAAoB,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,kBAAkB,EAAE,GAAG,EAC9G,SAAS,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IACjG,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;;QAC7D,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC9B,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,+BAA+B,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC;IAClI,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACjD,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,0BAA0B,CAAC,EAAE,WAAW,EAAE,YAAY,EAC5E,mBAAmB,EAAE,MAAM,CAAC,CAAC,WAAW,GAAG,IAAI,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IACxE,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,sCAAsC;IACpD,OAAO;QACL,CAAC,aAAa,EAAE,kBAAkB,EAAE,8BAA8B,EAAE,yDAAyD,CAAC;QAC9H,CAAC,iBAAiB,EAAE,oBAAoB,EAAE,KAAK,CAAC;QAChD,CAAC,aAAa,EAAE,iBAAiB,EAAE,6BAA6B,EAAE,yBAAyB,EAAE,iBAAiB,CAAC;QAC/G,CAAC,aAAa,EAAE,iBAAiB,EAAE,iCAAiC,EAAE,yBAAyB,EAAE,iBAAiB,CAAC;KACpH,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,gBAAyB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,gCAAgC,CAAC,UAAkB;IACjE,QAAQ,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC;IAC7D,OAAO,EAAE,MAAM,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,KAAK,EAAE,oCAAoC,EAAE,UAAU,CAAC,EAAE,CAAC;AAC5J,CAAC;AAED,MAAM,UAAU,4BAA4B,CAAC,MAAc;IACzD,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IACzG,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;IAC5D,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,IAAI,UAAU,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IACpH,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,SAAS,YAAY,CAAC,KAAmB;IACvC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC5B,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,GAAG,CAAC,MAAc,EAAE,IAAc,EAAE,GAAqC,EAAE,MAAmB;IAC3G,MAAM,CAAC,cAAc,EAAE,CAAC;IACxB,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC5D,MAAM,KAAK,GAAG,GAAS,EAAE,GAAG,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,IAAI,KAAK,CAAC,UAAU,KAAK,IAAI;QAAE,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/G,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IACxD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,KAAK,CAAC,CAAC;QACzC,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAClF,CAAC;YAAS,CAAC;QAAC,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAAC,CAAC;AAC3D,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,GAAqC,EAAE,MAAmB;IAClF,MAAM,KAAK,GAAG,KAAK,CAAC,qBAAqB,EAAE,CAAC,gBAAgB,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,qBAAqB,CAAC,EAC5H,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC5B,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACnC,KAAK,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAC5B,IAAI,CAAC;QACH,IAAI,KAAK,GAAG,KAAK,CAAC;QAClB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC;YAC/C,IAAI,CAAC;gBAAC,MAAM,GAAG,CAAC,gBAAgB,EAAE,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;gBAAC,KAAK,GAAG,IAAI,CAAC;gBAAC,MAAM;YAAC,CAAC;YAChF,MAAM,CAAC;gBAAC,MAAM,KAAK,CAAC,EAAE,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;YAAC,CAAC;QACnD,CAAC;QACD,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QACrE,MAAM,GAAG,CAAC,gBAAgB,EAAE,CAAC,aAAa,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,gEAAgE,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;QAC1K,MAAM,GAAG,CAAC,gBAAgB,EAAE,CAAC,aAAa,EAAE,qBAAqB,EAAE,6BAA6B,EAAE,4BAA4B,EAAE,kEAAkE,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;QAClN,MAAM,GAAG,CAAC,gBAAgB,EAAE,CAAC,aAAa,EAAE,kBAAkB,EAAE,4BAA4B,EAAE,6DAA6D,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;QAC3K,MAAM,GAAG,CAAC,gBAAgB,EAAE,CAAC,oBAAoB,EAAE,gBAAgB,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;QACnF,MAAM,GAAG,CAAC,gBAAgB,EAAE,CAAC,kBAAkB,EAAE,kBAAkB,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;QACnF,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAClC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,SAAS,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QAC1C,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,KAAoE;IAC3F,IAAI,CAAC,KAAK;QAAE,OAAO;IACnB,IAAI,KAAK,CAAC,KAAK,CAAC,QAAQ,KAAK,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,UAAU,KAAK,IAAI;QAAE,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAClG,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACnG,IAAI,CAAC,OAAO,IAAI,KAAK,CAAC,KAAK,CAAC,QAAQ,KAAK,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,UAAU,KAAK,IAAI;QAAE,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC9G,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AACjE,CAAC;AAED,KAAK,UAAU,aAAa,CAAC,UAAkB,EAAE,GAAqC;IACpF,MAAM,OAAO,GAAG,gCAAgC,CAAC,UAAU,CAAC,CAAC;IAC7D,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;IAChG,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,CAAC,MAAO,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,GAAG,IAAI,MAAM,CAAC,MAAM,GAAG,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1I,IAAI,KAAiC,CAAC;IACtC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,IAAI,OAAO,CAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE;YAAG,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;gBACzH,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,IAAI,KAAK,CAAC,UAAU,KAAK,IAAI;oBAAE,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBAChF,MAAM,CAAC,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC,CAAC;YAC1D,CAAC,EAAE,IAAI,CAAC,CAAC;QAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;IAClD,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;IAC1E,OAAO,4BAA4B,CAAC,MAAM,CAAC,CAAC;AAC9C,CAAC;AAED,2FAA2F;AAC3F,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,OAI1C;IACC,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAClC,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IACtC,MAAM,WAAW,GAAG,QAAQ,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,mBAAmB,eAAe,CAAC;IAC9F,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,gBAAgB,EAAE,UAAU,EAAE,kBAAkB,EAAE,CAAC;IAC/J,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,CAAC,UAAU,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACzH,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,IAAI,CAAC;YAAC,KAAK,MAAM,KAAK,IAAI,sCAAsC,EAAE;gBAAE,MAAM,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAAC,CAAC;QAC/H,OAAO,KAAK,EAAE,CAAC;YAAC,MAAM,SAAS,CAAC,UAAU,CAAC,CAAC;YAAC,MAAM,KAAK,CAAC;QAAC,CAAC;IAC7D,CAAC;IACD,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC/B,MAAM,OAAO,GAAG,2BAA2B,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IAClE,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC5E,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACnC,KAAK,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IAC5B,IAAI,SAAqD,CAAC;IAC1D,IAAI,KAA+B,CAAC;IACpC,MAAM,MAAM,GAAG,GAAmC,EAAE,CAAC,SAAS,KAAK,CAAC,KAAK,IAAI,EAAE;QAC7E,IAAI,MAAM,GAAG,KAAK,EAAE,aAAa,GAAG,KAAK,CAAC;QAC1C,IAAI,CAAC;YACH,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,IAAI,KAAK,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;gBAAC,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAAC,CAAC;YACnG,IAAI,KAAiC,EAAE,OAAO,GAAG,KAAK,CAAC;YACvD,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,OAAO,CAAO,OAAO,CAAC,EAAE,GAAG,KAAK,GAAG,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;iBACzJ,OAAO,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;YACtC,IAAI,CAAC,OAAO,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,IAAI,KAAK,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;gBAAC,MAAM,GAAG,IAAI,CAAC;gBAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAAC,CAAC;YAC/G,IAAI,CAAC,OAAO;gBAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YAC9E,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,CAAC;YACpC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,IAAI,CAAC,IAAI,GAAG,2BAA2B;gBAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;YAC7I,MAAM,UAAU,GAAG,MAAM,aAAa,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;YACxD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,IAAI,IAAI,CAAC,WAAW,CAAC,CAAC,WAAW,EAAE;oBACpG,UAAU,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,EAAE,YAAY,EAAE,CAAC,GAAG,OAAO,CAAC,EAAE,QAAQ,EAAE,aAAa,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,IAAI,GAAG,0BAA0B,EAAE,EAAE,CAAC;QAC/I,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAC/C,CAAC;gBAAS,CAAC;YACT,IAAI,KAAK;gBAAE,OAAO,CAAC,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YAC9D,MAAM,SAAS,CAAC,UAAU,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC,CAAC,EAAE,CAAC;IACL,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;IAC9J,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,IAAI,KAAK,CAAC,UAAU,KAAK,IAAI;YAAE,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAChF,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACzD,MAAM,SAAS,CAAC,UAAU,CAAC,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IAC/C,CAAC;IACD,KAAK,GAAG,GAAS,EAAE,GAAG,KAAK,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvD,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAChE,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;AACrC,CAAC"}
|
|
@@ -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"}
|
package/dist/doctor-lab.js
CHANGED
|
@@ -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") {
|
package/dist/doctor-lab.js.map
CHANGED
|
@@ -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":"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"}
|
package/dist/e2b-cua-desktop.js
CHANGED
|
@@ -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,
|