How Ego‑Lite Handles File Uploads and Downloads: CDP‑Based Implementation Explained

Ego‑Lite implements file uploads and downloads through Playwright‑style helpers in the ego-browser package, using the Chrome DevTools Protocol (CDP) directly via the src/driver/files.ts and src/driver/downloads.ts modules.

The citrolabs/ego-lite library provides lightweight browser automation with a focus on CDP‑native operations. File handling follows the Playwright API surface while operating at the protocol level, eliminating heavy dependency chains. This article examines the complete upload and download workflow as implemented in the source code.

File Upload Architecture

The setInputFiles Helper

The primary entry point for uploads is page.setInputFiles(), exported from src/helpers.ts and implemented in src/driver/files.ts. This method populates a file input element with one or more files without simulated user interaction.

// Re-export from helpers.ts (lines 99-100)
export const setInputFiles = driverFiles.setInputFiles;

CDP Implementation Details

The setInputFiles(selector, path) implementation in src/driver/files.ts performs three coordinated steps:

  1. Path normalization – Converts the path argument to an array of absolute file paths
  2. Element resolution – Uses withHandle() to obtain the DOM element's objectId and current CDP session ID
  3. Protocol invocation – Calls DOM.setFileInputFiles with the file list and element reference
// Upload multiple files to a file input element
await page.setInputFiles('#file-input', [
  '/absolute/path/to/file1.txt',
  '/absolute/path/to/file2.jpg',
]);

The operation returns Promise<void> — no value is returned because the upload modifies page state as a side effect. The CDP command DOM.setFileInputFiles is a Chromium‑native operation that directly populates the input's files property.

File Download Handling

Event‑Based Download Capture

Downloads are captured through page.waitForEvent('download'), which delegates to src/driver/downloads.ts. The implementation currently supports only the "download" event; other event names throw descriptive errors.

Download Workflow Stages

The downloads.ts driver implements a multi‑stage download pipeline:

Stage 1: Environment Preparation

  • Creates a unique temporary directory under os.tmpdir() with naming pattern: {pid}-{timestamp}-{randomSuffix}
  • Invokes ensureSession() to guarantee an active CDP session
  • Configures download behavior via setDownloadBehavior() using Browser.setDownloadBehavior (preferred) or Page.setDownloadBehavior (fallback)

Stage 2: Event Listening

Two CDP events are monitored simultaneously:

  • Page.downloadWillBegin – Captures the download guid and suggestedFilename
  • Page.downloadProgress – Filters by guid, watching for "completed" or "canceled" state

Stage 3: Completion Handling

Upon successful completion, a facade object provides four methods:

Method Return Type Description
suggestedFilename() string Filename proposed by the browser
url() string Source URL of the download
path() Promise<string> Absolute path in temporary directory
saveAs(targetPath) Promise<void> Copies file to permanent location

If the download is canceled, the operation throws an error including the filename.

Timeout Configuration

Both event listeners respect the timeout option, defaulting to state.defaultTimeout when unspecified.

// Wait for download with custom timeout
const download = await page.waitForEvent('download', { timeout: 30_000 });
console.log('Downloading:', download.suggestedFilename());

// Move to permanent storage
await download.saveAs('/my/downloads/' + download.suggestedFilename());

Key Source Files and Responsibilities

Understanding the module structure clarifies where specific behaviors originate:

  • src/driver/files.ts – Core upload implementation using DOM.setFileInputFiles
  • src/driver/downloads.ts – Complete download lifecycle: temp directory management, behavior configuration, event listening, and facade object creation
  • src/helpers.ts – Public API surface re-exporting driver functions as page.* methods
  • src/cdp-eval.ts – Low‑level cdp() wrapper used by both drivers for protocol commands
  • src/browser-runtime.ts – Provides ensureSession() and waitForBrowserEvent() infrastructure essential for download operations

Summary

  • File uploads in Ego‑Lite use CDP's DOM.setFileInputFiles via src/driver/files.ts, accepting absolute paths and operating directly on element objectIds
  • File downloads require configuring browser download behavior, creating temporary directories, and listening for Page.downloadWillBegin and Page.downloadProgress events
  • The facade pattern for downloads provides Playwright‑compatible methods (suggestedFilename(), saveAs(), etc.) while managing temporary file cleanup implicitly
  • All operations are promise‑based with configurable timeouts consistent with Ego‑Lite's global timeout state
  • The CDP abstraction layer in cdp-eval.ts and session management in browser-runtime.ts enable these features without external browser control dependencies

Frequently Asked Questions

How does Ego‑Lite handle multiple file uploads?

The setInputFiles method normalizes any path argument to an array, then passes the complete list to CDP's DOM.setFileInputFiles command. The browser's native file input mechanism accepts multiple paths simultaneously, populating the input's files FileList in order.

Where are downloaded files stored before saveAs() is called?

Downloads are written to a uniquely‑named temporary directory created under the OS temp folder (os.tmpdir()). The directory name incorporates process PID, timestamp, and random suffix to prevent collisions. The path() method on the download object resolves to this temporary location.

What happens if a download is canceled or fails?

The Page.downloadProgress event watcher detects state: "canceled" and throws an error containing the filename. Successful completion requires state: "completed"; no partial file handling is implemented—canceled downloads remain in the temporary directory until system cleanup.

Can I use waitForEvent for events other than "download"?

Currently no. The src/driver/downloads.ts implementation explicitly validates the event name and throws 'Unsupported event: ${event}' for any value other than "download". This matches Ego‑Lite's scoped feature set focused on file operations rather than general event coverage.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →