# How the CDP Evaluation Module in ego-lite Executes Raw CDP Commands and JavaScript

> Discover how ego-lite's CDP evaluation module executes raw CDP commands and JavaScript using cdp() and js() helpers. Learn about its runtime state and session manager for efficient message transport and parsing.

- Repository: [CitroLabs/ego-lite](https://github.com/citrolabs/ego-lite)
- Tags: internals
- Published: 2026-08-28

---

**The CDP evaluation module in ego-lite exposes two main helpers—`cdp()` for raw Chrome DevTools Protocol commands and `js()` for in-page JavaScript execution—both backed by a singleton runtime state and session manager that handle CDP message transport and response parsing.**

The ego-lite browser-automation framework provides AI agents with low-level browser control through its dedicated evaluation layer. Located in [`package/ego-browser/src/cdp-eval.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/cdp-eval.ts), this module bridges high-level agent scripts with the Chrome DevTools Protocol (CDP), enabling both protocol-level commands and arbitrary JavaScript execution without requiring manual imports or complex setup.

## Core Helper Functions

The module exports two primary functions that are automatically injected into every agent script's scope.

### `cdp(command, params?)` — Raw CDP Command Execution

The `cdp` helper sends arbitrary CDP commands to the underlying browser instance. It accepts a command name string and an optional parameters object, then forwards these to the runtime's CDP transport layer.

```javascript
// Enable network tracking
await cdp('Network.enable');

// Navigate to a URL
await cdp('Page.navigate', { url: 'https://example.com' });

// Capture a screenshot
await cdp('Page.captureScreenshot', { format: 'png' });

```

Under the hood, `cdp` calls `ego.sendCDPMessage`, defined in [`package/ego-browser/src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/browser-runtime.ts). This method marshals the request into JSON, transmits it over the CDP socket, awaits the response, and returns the parsed result. Protocol-level errors are converted to `CdpError` exceptions.

### `js(expr)` — JavaScript Expression Evaluation

The `js` helper evaluates JavaScript expressions within the current page's execution context. It wraps the supplied expression in an **Immediately-Invoked Function Expression (IIFE)** to ensure proper return value handling, then invokes `Runtime.evaluate` via the internal `cdp` helper.

```javascript
// Get the page title
const title = await js('document.title');

// Count DOM elements
const count = await js('document.querySelectorAll("a").length');

// Execute complex page-side logic
const data = await js(`
  (function() {
    const rows = document.querySelectorAll('table tr');
    return Array.from(rows).map(r => r.textContent);
  })()
`);

```

The helper passes these flags to `Runtime.evaluate`:
- `awaitPromise: true` — Waits for Promise resolution
- `returnByValue: true` — Returns serializable values directly

Execution errors surface as `JsEvaluationError` instances with original stack traces preserved.

## Runtime Architecture

Both helpers depend on a coordinated infrastructure spanning three core files:

| Component | File Path | Responsibility |
|-----------|-----------|----------------|
| **State Management** | [`package/ego-browser/src/state.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/state.ts) | Maintains singleton runtime state including the active CDP session and pending request map |
| **Session Manager** | [`package/ego-browser/src/browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/browser-runtime.ts) | Handles connection lifecycle, message routing, and `ensureSession()` re-attachment logic |
| **Helper Injection** | [`package/ego-browser/src/helpers.ts`](https://github.com/citrolabs/ego-lite/blob/main/package/ego-browser/src/helpers.ts) | Registers `cdp` and `js` in `helperContext()` for automatic script scope availability |

### Execution Flow

When either helper is invoked, the following sequence occurs:

1. **Session validation** — `ensureSession()` verifies or re-establishes a live CDP session
2. **Message dispatch** — `ego.sendCDPMessage` transmits the JSON-RPC formatted command
3. **Response processing** — The runtime parses the CDP response, resolves the Promise with the result value, or propagates errors

This design eliminates the need for agents to manage connection state manually.

## Practical Code Examples

### Enable Console Logging and Capture Events

```javascript
// Enable Console domain via raw CDP
await cdp('Console.enable');

// Set up event listener for console messages
await cdp('Runtime.enable');
const logs = [];
const { sessionId } = await cdp('Target.attachToTarget', {
  targetId: (await cdp('Target.getTargets')).targetInfos[0].targetId,
  flatten: true
});

```

### Extract Structured Page Data

```javascript
// Combine navigation and JavaScript evaluation
await cdp('Page.navigate', { url: 'https://news.ycombinator.com' });
await cdp('Page.loadEventFired'); // Wait for load

// Extract story titles and URLs
const stories = await js(`
  Array.from(document.querySelectorAll('.storylink')).map(a => ({
    title: a.textContent,
    url: a.href
  }))
`);
console.log(`Found ${stories.length} stories`);

```

### Error Handling Pattern

```javascript
try {
  // This will fail if the selector doesn't exist
  const result = await js('document.querySelector("#nonexistent").textContent');
} catch (err) {
  if (err.name === 'JsEvaluationError') {
    console.error('Page evaluation failed:', err.message);
    // err contains the original JavaScript exception details
  }
}

```

## Type Safety and Documentation

The `cdp` and `js` helpers are fully implemented in TypeScript with JSDoc annotations. This enables ego-lite's `help()` introspection feature, allowing agents to query function signatures and usage examples at runtime. The type definitions ensure IDE autocomplete and compile-time validation for common CDP commands.

## Summary

- The **CDP evaluation module** ([`cdp-eval.ts`](https://github.com/citrolabs/ego-lite/blob/main/cdp-eval.ts)) provides `cdp()` for raw protocol commands and `js()` for in-page JavaScript execution
- Both helpers rely on **singleton runtime state** ([`state.ts`](https://github.com/citrolabs/ego-lite/blob/main/state.ts)) and **session management** ([`browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/browser-runtime.ts)) for connection handling
- **Automatic scope injection** via `helperContext()` eliminates import boilerplate in agent scripts
- **Full TypeScript coverage** with JSDoc enables runtime `help()` introspection
- **Structured error types** (`CdpError`, `JsEvaluationError`) distinguish protocol failures from JavaScript exceptions

## Frequently Asked Questions

### How does the `js()` helper handle async JavaScript?

The `js()` helper automatically sets `awaitPromise: true` when calling `Runtime.evaluate`, so any Promise returned by the evaluated expression is awaited before the result is passed back. This allows agents to write `await js('fetch("/api").then(r => r.json())')` and receive the resolved JSON directly.

### What happens if the CDP session disconnects during execution?

The `ensureSession()` call in [`browser-runtime.ts`](https://github.com/citrolabs/ego-lite/blob/main/browser-runtime.ts) automatically re-attaches to the browser target if the previous session expired or was terminated. Agents typically don't need to handle reconnection logic manually, though long-running scripts may observe brief delays during session recovery.

### Can I use `cdp()` to access experimental or domain-specific CDP features?

Yes. The `cdp()` helper accepts any valid CDP command string, including experimental domains and browser-specific extensions. The module performs no command validation—it forwards the command directly to the browser and returns whatever response the protocol provides, enabling access to new CDP features without framework updates.

### Where are the tests for CDP evaluation functionality?

Unit tests reside in `package/ego-browser/src/cdp-eval.test.mjs`, covering command forwarding, JavaScript evaluation, Promise handling, and error propagation scenarios.