mirror of
https://github.com/morluto/rea.git
synced 2026-11-11 01:13:39 +00:00
* fix(desktop): keep added-record checks off ids, dates, and joined timestamps A position-named record's fields keep their paths, so an identifier, a stamped date, and text past the limit are not suggested checks. A whole-text check does not climb into an ancestor whose text joins a timestamp. * fix(desktop): bound home fetches and keep unsettled edits readable Split home-folder reads by the guest answer budget, keep a capacity error from the capture output, and drop the superseded task-argument refusal. Grade kept text per line, leave unretained dconf unread, and reserve by-position notes for XML children. Map a linked database's sidecars through the selected spelling and stop a detached capture only when its start identity still owns the pid. * fix(desktop): describe unretained dconf as unread The key comparison treats a missing copy as unknown. The comment still said that copy counted as an empty key list. * test(desktop): keep a capture capacity error through endedCapture An output past the guest answer ceiling stays the resource constraint, with its heap recovery and non-retryable status, instead of a generic capture-exit message. * fix(desktop): keep nested save times and formatting runs out of checks A field check drops save-time leaves before it joins the field, so a nested timestamp is not part of the suggested text. A text check beside a save time uses the paragraph when the diff names a formatting run. * test(desktop): read paragraph pointers from checks that have them * test(desktop): expect a large task to export intact The 96 KiB refusal is gone. A prompt past that size reaches the computer and comes back unchanged, instead of failing before export. * fix(desktop): keep real edits that save-side heuristics were dropping Repeated unnamed fields stay content checks. A formula that still has text is not renumbered with its ExprID. One gained style attribute is the edit; a repeated fill-in stays upkeep. Phone numbers and plain clock times stay text, and a decimal is the element's whole text. An older verifier matches on the task it states, not its evaluator source. * fix(desktop): cover repeated records and keep timestamps out of checks An added record whose words are already in the seed still gets the list's text when that text fits. Readiness is a start reason, so a final check names seed locks without matching the message. Field text split by a timestamp stays separate, and a timestamp line is not offered as a guard. * fix(desktop): compare a cell's joined decimal within tolerance The whole-element check keeps numeric tolerance, so 437.80 and a long float still match 437.8, including when a run splits the digits. A different number or other text does not. Both evaluators read an element's text for that comparison. * fix(desktop): keep selected logs and stop treating unknown walks as complete Match an app name as a whole token, treat an omitted unchecked_paths count as incomplete, seed Chromium user_prefs.json, and keep a caller-selected log even when that path is also a state directory. A log inside the app's own folder still marks that folder so settings beside it stay seeded, while a lock in the home does not. Sibling locks under a selected folder stay out unless that lock was the selected path. * fix(desktop): grade a number from a complete XML element only A tolerance check joins an element's text only in an XML file or an XML archive entry, and leaves that check undecided when the view is cut, so a dropped descendant cannot turn the kept runs into a passing number. A JSON object with the same shape stays the value itself. Equivalent decimals and a split run on a whole cell still match. * fix(desktop): accept an older grader only when its index helper agrees The witness still matches a bundle whose evaluator is this REA's, or the older index expression alone when no path segment is a leading-zero number. A truncated verifier, a changed grader, or that older helper beside a segment such as 01 no longer counts as the same task. * fix(desktop): keep a lone lock a document and drop one beside its file A selected name such as notes.lck stays a document, so launch and the draft still treat it as the caller's file. A lock beside a recorded sibling is left out of the seed unless that lock path itself was selected. * fix(desktop): require the added record and leave save times out of list checks A record a selector names is checked itself, so its words have to be in that record. When an unnamed record only repeats words the seed already has, a list that holds a save time is checked by the text around that time. A later save of the same records still passes, and a missing or rewritten record fails. * fix(desktop): judge the older index helper by pointer segments only A leading zero in a file name or a URL does not change how the older index helper reads a pointer. The witness still rejects that helper when a pointer segment is a number such as 01. * fix(desktop): keep a document whose name ends in .lock A lock beside a recorded file still stays out of the seed unless that lock was selected. A document such as Cargo.lock in the home is the user's file, so the seed keeps it. An application lock in the home, such as poedit.lock, stays out. * fix(desktop): do not suggest list text the seed already passes A repeated record is shown by text the seed does not hold. The seed's own text is not a check. A pointer inside a check value is not a pointer segment for the older index helper. * fix(desktop): do not let a left-out lock hide settings checks A sibling lock the seed omits is not the document the draft follows. Settings changes stay suggested. The unused sibling-lock name helper is removed. * fix(desktop): keep a linked settings file in the folder the link points at A selected ~/.config alias no longer moves MuseScore settings to that alias. The seed keeps settings/MuseScore or Documents, which is the path the export opens the note from. * fix(desktop): split home fetches by answer size and keep a size refusal A batch of tiny files stops before each path's envelope exceeds the host answer budget. A capture output past that ceiling stays a resource error instead of becoming a generic exit. * fix(desktop): seed a selected link under the path the app uses The selected spelling wins, so ~/.config/MuseScore is not rewritten to the folder it points at and the note stays the one launched document. A database wal and journal follow that database. A launch argument is respelled the same way. Teardown signals a detached PID only when its start identity still matches. * fix(desktop): keep a witness's actions and an incomplete checkpoint A failed witness save retries the action log it first recorded. A deletion left unconfirmed between the seed and the end is not reported as no change. Windows packs npm through a shell, which can start npm.cmd. * fix(desktop): read verifier pointers from the parsed checks A brace inside a check value is not an object boundary. A leading-zero pointer after that value still rejects the older index helper. * fix(desktop): leave out a sibling lock under a selected folder A file under a selected folder inherits selected_path. That does not make the lock beside its map a chosen document, so a settings change stays drafted. * fix(desktop): prefer the most specific home spelling and retarget launch files A selected parent directory no longer hides a settings folder walked through a link. A launch filename under that folder is replaced with the seeded file's absolute path. * fix(desktop): pack the build runtime through npm's JavaScript entry npm pack and npm ci no longer spawn npm.cmd through a shell, so a temporary directory whose path contains spaces stays one argument. * fix(desktop): spell launch settings and keep a database log exact A database log matches only that file, so a neighboring folder is not moved. A launch option and the working directory use the same home spelling as the seed. * fix(desktop): draft a lock the export selected exactly The draft uses the same selected paths as the export. A lock chosen by itself stays in the draft. A lock under a selected folder stays out. * fix(desktop): move a state database's logs with the database The write-ahead log and journal follow the spelling the database received, including a walked state link. A neighboring folder stays put. A separate --config argument uses that spelling too. * fix(desktop): keep a selected file ahead of a database-log guess A file selected as itself keeps that spelling even when its name ends in -journal. Relative launch arguments are resolved in the captured working directory before that directory moves. * fix(desktop): keep outside-home database logs and option values A selected database outside the home keeps its write-ahead log. Launch options are rewritten only when they name a captured file or settings path. * fix(desktop): follow a database mapping and own limitation text A selected database keeps its log when a parent folder moves or the file sits outside the home. Trash and seed-lock tests compare the owning notice with the paths, and launch options that are not captured paths stay as written. * fix(desktop): retarget a settings folder that holds captured files A nested profile directory is a captured path when a seeded file is inside it. An option value that only resolves under the home stays as written. * fix(desktop): keep a program word and a directory's neighbor The program after env stays the program even when a captured file sits in a folder of that name. A selected directory is not a database, so a neighboring file keeps the parent folder's spelling. * fix(desktop): record whether a selected path is a directory Capture stores the walked path's kind. A neighboring file of a selected directory keeps the parent folder's spelling even when that directory never changes and its children are not content roots. * fix(desktop): mark containing paths without a pairwise scan A recorded path marks its known ancestors as directories in one walk up the path, instead of comparing every recorded path with every other. * fix(desktop): keep a selected folder that is named like a database log A folder the caller selected stays a selected root when its name ends in -journal or -wal. A generated log beside a database file still does not. * fix(desktop): refuse a build command that exceeds the argument vector Splitting one argument still leaves the whole command under Linux's E2BIG limit. A request past that budget is refused before the process starts. * fix(desktop): remap a captured path in an env assignment The program word stays the program. A NAME=value assignment keeps its name and follows a captured path value when that path's spelling moves. * fix(desktop): keep oversized text out of draft guards A value or line longer than the draft's text bound is not copied into a guard, so one large frame cannot fill the task by itself. * fix(desktop): keep an empty env value empty An empty assignment is not a path. Resolving it named the working directory and rewrote the value when that directory's spelling moved. * fix(desktop): check build runtime export capability * fix(desktop): provide complete runtime repack command * fix(desktop): retain runtime probe failures * test(desktop): identify capture independently of schema preflight * fix(desktop): preserve document URLs and value formats * fix(desktop): bound added checks and omit noisy text guards * fix(desktop): preserve launch URLs and JSON draft values * fix(desktop): recognize captured file URL documents * fix(desktop): render captured file URLs for runtime home * fix(desktop): distinguish phone numbers from save metadata * fix(desktop): preserve launch URLs and user text * fix(desktop): preserve local file URL authority * fix(desktop): preserve local file URL authority * fix(desktop): render captured file URLs at launch * fix(desktop): classify numeric timestamps using field context * fix(desktop): classify numeric timestamps using field context * fix(desktop): retain context for generated draft values * fix(desktop): retain context for generated draft values * test(desktop): cover generated IDs in text guards * test(desktop): cover generated IDs in text guards * fix(desktop): isolate launcher URL encoding * fix(desktop): isolate launcher URL encoding * fix(desktop): isolate launcher URL encoding * fix(desktop): retain clean text in noisy record fields * style(desktop): format the noisy-record draft files with the pinned oxfmt Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(desktop): move launch execution to boundary suite * fix(desktop): redact build schema failure output * refactor(desktop): normalize schema failure once * fix(desktop): omit unsafe schema parser snippets * fix(desktop): preserve draft change and selected path evidence * test(desktop): group retained dconf note regressions * fix(desktop): respect archive entry format in draft checks * test(desktop): separate unowned-file draft note cases * fix(desktop): preserve explicitly selected journal documents * docs(desktop): clarify task checks before scratch export * fix(desktop): respell selected paths in file URLs * test(desktop): group captured document spelling cases * fix(desktop): bound draft preview serialization * fix(desktop): restore selected state aliases * fix(desktop): respect entry format in draft noise * test(desktop): match exported alias evidence at its JSON boundary * fix(desktop): retain app state logs in exported seeds * style: fix desktop launch test formatting * style: format native command path schema * fix(desktop): map selected external launch paths * style(desktop): format seed document regressions * test(desktop): group launch URL regressions * fix(desktop): omit redundant nested state aliases * fix(desktop): compare added free text as a whole * fix(desktop): check recompressed seeds as shipped * docs(desktop): clarify recovered seed format * test(desktop): group shipped gzip seed checks * fix(desktop): map captured launch paths once * refactor: remove unused whole-text guard state * refactor: stop passing unused text children * test: align free-text checks with whole-note policy * fix: validate recompressed desktop archive seeds * style(desktop): format archive seed regression * fix(desktop): redact runtime schema errors * fix(desktop): normalize captured file URLs * fix(desktop): report seeded files by capture path * fix(desktop): retain startup readiness failure stage * fix(desktop): retain JSON date checks * fix(desktop): preserve archive formatting checks * fix(desktop): preserve explicitly selected journal files * fix(desktop): report build command transport limits * docs(desktop): clarify unreadable dconf versions * style(desktop): format capture review fixes --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: morluto <76467478+morluto@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
369 lines
13 KiB
TypeScript
369 lines
13 KiB
TypeScript
import { createInterface } from "node:readline";
|
|
|
|
import { z } from "incur";
|
|
import type { Logger } from "pino";
|
|
|
|
import { captureDesktopApplication } from "../application/desktop/DesktopApplicationCapture.js";
|
|
import type { DesktopStateReaders } from "../application/desktop/DesktopApplicationState.js";
|
|
import { AnalysisError } from "../domain/analysisErrorBase.js";
|
|
import type { Evidence } from "../domain/evidence.js";
|
|
import { localPathStringSchema } from "../domain/localPath.js";
|
|
import { err, ok } from "../domain/result.js";
|
|
import { finishAnalysisCommand } from "./finishAnalysisCommand.js";
|
|
import { projectCliAnalysisResult } from "./projectCliAnalysisResult.js";
|
|
import { absoluteCallerPath } from "../filesystem/callerPath.js";
|
|
import { cliDecimalField } from "./options.js";
|
|
import { CLI_COMMANDS } from "../cliCommandNames.js";
|
|
import { logCliCommand } from "../cliLogging.js";
|
|
import {
|
|
DESKTOP_CAPTURE_DEFAULTS,
|
|
type DesktopCaptureProgress,
|
|
} from "../domain/desktop/desktopCapture.js";
|
|
import { SessionRequestQueue } from "../desktop/DesktopSessionRequests.js";
|
|
import { withCommandCancellation } from "./commandCancellation.js";
|
|
import type { CliInstance } from "./types.js";
|
|
|
|
const positive = (fallback: number) =>
|
|
cliDecimalField(z.int().positive().default(fallback));
|
|
|
|
/** Options of `capture-desktop-application`. */
|
|
const captureOptions = z.object({
|
|
desktopEntry: z
|
|
.string()
|
|
.min(1)
|
|
.optional()
|
|
.describe("Desktop entry id (org.xfce.mousepad) or absolute .desktop path"),
|
|
executable: z
|
|
.string()
|
|
.min(1)
|
|
.optional()
|
|
.describe(
|
|
"Executable path or program name on PATH, instead of a desktop entry",
|
|
),
|
|
// An empty argument reaches the application as is. Path options refuse
|
|
// one, because normalizing it would select the current directory.
|
|
argument: z
|
|
.array(z.string())
|
|
.optional()
|
|
.describe("Argument appended to the launch command (repeatable)"),
|
|
output: localPathStringSchema.describe(
|
|
"New or empty directory for capture.json and retained content",
|
|
),
|
|
statePath: z
|
|
.array(localPathStringSchema)
|
|
.optional()
|
|
.describe(
|
|
"File or directory whose starting content is retained in addition to the application's state directories; a file brings its SQLite write-ahead log and rollback journal (repeatable)",
|
|
),
|
|
exclude: z
|
|
.array(localPathStringSchema)
|
|
.optional()
|
|
.describe("Path left out of every checkpoint walk (repeatable)"),
|
|
maxDurationSeconds: positive(
|
|
DESKTOP_CAPTURE_DEFAULTS.maxDurationSeconds,
|
|
).describe("Stop the session after this many seconds"),
|
|
maxEntries: positive(DESKTOP_CAPTURE_DEFAULTS.maxEntries).describe(
|
|
"Maximum paths recorded per checkpoint walk",
|
|
),
|
|
maxFileBytes: positive(DESKTOP_CAPTURE_DEFAULTS.maxFileBytes).describe(
|
|
"Largest file whose content is retained",
|
|
),
|
|
maxContentBytes: positive(DESKTOP_CAPTURE_DEFAULTS.maxContentBytes).describe(
|
|
"Total retained content",
|
|
),
|
|
packageFile: localPathStringSchema
|
|
.optional()
|
|
.describe(
|
|
"The .deb file the application was installed from; its control fields, SHA-256 and size are recorded, never the file",
|
|
),
|
|
});
|
|
|
|
/** The checkpoints a bundle's seed and a task's end state are read at. */
|
|
const checkpointOptions = {
|
|
seedCheckpoint: z
|
|
.string()
|
|
.optional()
|
|
.describe(
|
|
"Checkpoint whose state seeds the bundle; the baseline by default",
|
|
),
|
|
endCheckpoint: z
|
|
.string()
|
|
.optional()
|
|
.describe(
|
|
"Checkpoint whose state a task must pass on; the capture's last by default",
|
|
),
|
|
};
|
|
|
|
/**
|
|
* Run a desktop operation with SQLite and dconf readers, finishing through
|
|
* the shared command owner so the result, cancellation and the SQLite
|
|
* service's cleanup are all kept. The readers load here, so registering the
|
|
* command catalog never loads them.
|
|
*/
|
|
const withStateReaders = async (
|
|
environment: NodeJS.ProcessEnv,
|
|
signal: AbortSignal,
|
|
operation: string,
|
|
run: (readers: DesktopStateReaders) => Promise<Evidence | AnalysisError>,
|
|
) => {
|
|
const [
|
|
{ createSqliteDatabaseService },
|
|
{ readSqliteStateView },
|
|
{ dumpDconfDatabase },
|
|
] = await Promise.all([
|
|
import("../composition/sqlite.js"),
|
|
import("../application/desktop/DesktopSqliteState.js"),
|
|
import("../desktop/DconfDatabaseReader.js"),
|
|
]);
|
|
const sqlite = createSqliteDatabaseService(environment);
|
|
return finishAnalysisCommand(
|
|
async () => {
|
|
const result = await run({
|
|
sqlite: (database, readSignal) =>
|
|
readSqliteStateView(sqlite, database, readSignal),
|
|
dconf: (database, readSignal) =>
|
|
dumpDconfDatabase(database, environment, readSignal),
|
|
});
|
|
return result instanceof AnalysisError ? err(result) : ok(result);
|
|
},
|
|
sqlite,
|
|
"rea-desktop",
|
|
operation,
|
|
signal,
|
|
).then(projectCliAnalysisResult);
|
|
};
|
|
|
|
/** Register the export of a capture folder as a computer app bundle. */
|
|
const registerDesktopExportCommand = (
|
|
cli: CliInstance,
|
|
logger: Logger,
|
|
environment: NodeJS.ProcessEnv,
|
|
): void => {
|
|
cli.command(CLI_COMMANDS.exportDesktopApplication, {
|
|
description:
|
|
"Export a desktop application capture folder as an agentenv computer app bundle: class, env.toml, skill and seed",
|
|
args: z.object({
|
|
capture: localPathStringSchema.describe(
|
|
"Folder written by capture-desktop-application",
|
|
),
|
|
directory: localPathStringSchema.describe(
|
|
"New or empty bundle directory",
|
|
),
|
|
}),
|
|
options: z.object({
|
|
name: z
|
|
.string()
|
|
.optional()
|
|
.describe(
|
|
"Environment name; defaults to one derived from the application",
|
|
),
|
|
task: z
|
|
.array(localPathStringSchema)
|
|
.optional()
|
|
.describe(
|
|
"Task file to validate against the capture and add with its verifier and eval; a capture yields one",
|
|
),
|
|
packageUrl: z
|
|
.string()
|
|
.optional()
|
|
.describe(
|
|
"http or https URL the computer downloads the captured --package-file from when the bundle is put, for an application installed from a .deb file",
|
|
),
|
|
extraPackage: z
|
|
.array(z.string())
|
|
.optional()
|
|
.describe(
|
|
"Ubuntu 24.04 archive package installed beside the application, such as a runtime piece its package does not install; repeat for more",
|
|
),
|
|
syntheticSeed: z
|
|
.boolean()
|
|
.default(false)
|
|
.describe(
|
|
"The seed was made for the task, as in a build computer, not taken from the user's own data; the README says so instead of keeping the bundle local",
|
|
),
|
|
...checkpointOptions,
|
|
}),
|
|
run: ({ args, options }) =>
|
|
withCommandCancellation((signal) =>
|
|
logCliCommand(
|
|
logger,
|
|
CLI_COMMANDS.exportDesktopApplication,
|
|
async () => {
|
|
const { exportDesktopApplication } =
|
|
await import("../application/desktop/DesktopApplicationExport.js");
|
|
return withStateReaders(
|
|
environment,
|
|
signal,
|
|
"export_desktop_application",
|
|
(readers) =>
|
|
exportDesktopApplication(
|
|
{
|
|
capture: absoluteCallerPath(args.capture),
|
|
directory: absoluteCallerPath(args.directory),
|
|
name: options.name,
|
|
tasks: (options.task ?? []).map((path) =>
|
|
absoluteCallerPath(path),
|
|
),
|
|
packageUrl: options.packageUrl,
|
|
extraPackages: options.extraPackage,
|
|
seedCheckpoint: options.seedCheckpoint,
|
|
endCheckpoint: options.endCheckpoint,
|
|
syntheticSeed: options.syntheticSeed,
|
|
},
|
|
readers,
|
|
signal,
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
});
|
|
};
|
|
|
|
/** Register the change summary an agent writes a task from. */
|
|
const registerDesktopTaskCommand = (
|
|
cli: CliInstance,
|
|
logger: Logger,
|
|
environment: NodeJS.ProcessEnv,
|
|
): void => {
|
|
cli.command(CLI_COMMANDS.describeDesktopApplicationTask, {
|
|
description:
|
|
"Describe how a desktop application capture's files changed from the seed checkpoint to the end, with suggested checks and a task draft to complete for export-desktop-application --task",
|
|
args: z.object({
|
|
capture: localPathStringSchema.describe(
|
|
"Folder written by capture-desktop-application",
|
|
),
|
|
}),
|
|
options: z.object(checkpointOptions),
|
|
run: ({ args, options }) =>
|
|
withCommandCancellation((signal) =>
|
|
logCliCommand(
|
|
logger,
|
|
CLI_COMMANDS.describeDesktopApplicationTask,
|
|
async () => {
|
|
const { draftDesktopApplicationTask } =
|
|
await import("../application/desktop/DesktopTaskDraft.js");
|
|
return withStateReaders(
|
|
environment,
|
|
signal,
|
|
"describe_desktop_application_task",
|
|
(readers) =>
|
|
draftDesktopApplicationTask(
|
|
absoluteCallerPath(args.capture),
|
|
readers,
|
|
signal,
|
|
{ seed: options.seedCheckpoint, end: options.endCheckpoint },
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
});
|
|
};
|
|
|
|
/** Register the state view over a capture folder. */
|
|
const registerDesktopStateCommand = (
|
|
cli: CliInstance,
|
|
logger: Logger,
|
|
environment: NodeJS.ProcessEnv,
|
|
): void => {
|
|
cli.command(CLI_COMMANDS.inspectDesktopApplicationState, {
|
|
description:
|
|
"Read a desktop application capture folder into the application's state: roles, typed JSON views of each version and kinds of change",
|
|
args: z.object({
|
|
capture: localPathStringSchema.describe(
|
|
"Folder written by capture-desktop-application",
|
|
),
|
|
}),
|
|
run: ({ args }) =>
|
|
withCommandCancellation((signal) =>
|
|
logCliCommand(
|
|
logger,
|
|
CLI_COMMANDS.inspectDesktopApplicationState,
|
|
async () => {
|
|
const { inspectDesktopApplicationState } =
|
|
await import("../application/desktop/DesktopApplicationState.js");
|
|
return withStateReaders(
|
|
environment,
|
|
signal,
|
|
"inspect_desktop_application_state",
|
|
(readers) =>
|
|
inspectDesktopApplicationState(
|
|
absoluteCallerPath(args.capture),
|
|
readers,
|
|
signal,
|
|
),
|
|
);
|
|
},
|
|
),
|
|
),
|
|
});
|
|
};
|
|
|
|
/** Register the interactive Linux desktop application capture. */
|
|
export const registerDesktopCaptureCommands = (
|
|
cli: CliInstance,
|
|
logger: Logger,
|
|
environment: NodeJS.ProcessEnv,
|
|
): void => {
|
|
registerDesktopStateCommand(cli, logger, environment);
|
|
registerDesktopExportCommand(cli, logger, environment);
|
|
registerDesktopTaskCommand(cli, logger, environment);
|
|
cli.command(CLI_COMMANDS.captureDesktopApplication, {
|
|
description:
|
|
"Launch a Linux desktop application, watch it while it is used and record its windows and state at checkpoints read from stdin",
|
|
options: captureOptions,
|
|
run: ({ options }) =>
|
|
withCommandCancellation((signal) =>
|
|
logCliCommand(
|
|
logger,
|
|
CLI_COMMANDS.captureDesktopApplication,
|
|
async () => {
|
|
const requests = new SessionRequestQueue(
|
|
createInterface({ input: process.stdin, terminal: false }),
|
|
);
|
|
try {
|
|
return await captureDesktopApplication(
|
|
{
|
|
desktopEntry: options.desktopEntry,
|
|
executable: options.executable,
|
|
arguments: options.argument ?? [],
|
|
output: options.output,
|
|
statePaths: options.statePath ?? [],
|
|
excludes: options.exclude ?? [],
|
|
maxDurationSeconds: options.maxDurationSeconds,
|
|
maxEntries: options.maxEntries,
|
|
maxFileBytes: options.maxFileBytes,
|
|
maxContentBytes: options.maxContentBytes,
|
|
packageFile:
|
|
options.packageFile === undefined
|
|
? undefined
|
|
: absoluteCallerPath(options.packageFile),
|
|
},
|
|
{
|
|
platform: process.platform,
|
|
environment,
|
|
callerDirectory: process.cwd(),
|
|
nextRequest: () => requests.next(),
|
|
report: async (message, event) => {
|
|
const progress: DesktopCaptureProgress = {
|
|
rea_progress: {
|
|
phase: "desktop_capture",
|
|
message,
|
|
...(event === undefined ? {} : { event }),
|
|
},
|
|
};
|
|
process.stderr.write(`${JSON.stringify(progress)}\n`);
|
|
},
|
|
},
|
|
signal,
|
|
);
|
|
} finally {
|
|
requests.close();
|
|
}
|
|
},
|
|
),
|
|
),
|
|
});
|
|
};
|