Web and mobile runtimes
The web and mobile packages adapt the same Cheetah command model to two constrained hosts. A web runtime is a cooperative participant inside one ordinary page. A mobile runtime is a JavaScript layer embedded inside a native application and delegates transport, identity, HTTP, and actions through a host bridge.
Neither is a reduced-authority browser extension. A web page cannot acquire extension tab or window privileges, and the mobile bridge can execute only what its native host implements.
Web runtime: one cooperative document
createWebRuntime() connects code already running in a page and registers direct DOM handlers for that document.
import { createWebRuntime } from '@cheetah/web';
const runtime = await createWebRuntime({
serverUrl: 'wss://api.example.com/cheetah/ws',
authToken: await acquirePageCredential(),
localPolicySource,
modules: [siteSpecificHandlers],
clientMetadata: { role: 'customer-portal' },
});
console.log('Virtual context:', runtime.contextId);
await runtime.start();
The composition uses browser WebSocket and fetch facilities, preserves the logical client ID in local storage, creates a random numeric context ID unless one is supplied, and reports that context through WebStateReporter. Its clientType is web.
The context ID occupies the same target field used for an extension tab. A command with no target.tab_id may act on this page. A command naming this runtime's context may also act. A different target.tab_id fails with wrong_context before DOM work starts. This guard prevents one cooperating page runtime from silently accepting a command addressed to another.
Web configuration and actions
The web wrapper exposes transport security mode, result endpoint, logging, command and lease timeouts, telemetry and configuration providers, local policy, approval, optional payload decryption, state-reporter override, handler modules, and client metadata. It does not expose the browser extension's payload-reference resolver, parser, capture, tab, window, download, or worker facilities.
Its built-in handlers are click, type, scroll, get_text, wait_for_element, get_dom, get_page_info, get_element_info, query_selector_all, focus, blur, get_attribute, and wait_settled. They call this page's DOM directly instead of traversing a content-script bridge. Browser origin rules, the page's Content Security Policy, DOM lifecycle, and the runtime's JavaScript execution environment remain the effective platform limits.
wait_settled is intentionally modest: it polls until document.readyState is complete or its timeout expires. A true result is not proof of network idleness, framework hydration, finished background work, or application readiness. Use an application-specific handler or element condition when those are the real requirement.
The page must manage its own credential and call stop() during an orderly teardown when possible. Navigation destroys the JavaScript world; a later page construction is a fresh runtime instance even when local storage restores its logical client identity.
Mobile runtime: JavaScript-to-native composition
The mobile package is designed for a JavaScript engine hosted by a native application. Native code installs the global bridge, supplies asynchronous WebSocket and HTTP operations, persists the client ID, and executes named native handlers. The JavaScript entry point receives a JSON configuration rather than a normal object-valued factory call:
await createMobileRuntime(JSON.stringify({
serverUrl: 'wss://api.example.com/cheetah/ws',
authToken: nativeCredential,
clientType: 'android',
handlerTypes: ['scan_barcode', 'show_notification'],
}));
await startMobileRuntime();
The supported configuration is currently limited to server URL, transport security mode, credential, optional result endpoint, client type, logging, default command timeout, lease lifetime, and a list of native handler names. clientType defaults to android. Use the core or a deliberate mobile-package extension when a product needs policy, telemetry, payload, or module seams that this wrapper does not expose.
Creating a mobile runtime stops any previous runtime on a best-effort basis, rejects pending bridge calls, and replaces the exported runtime. Each runtime object still follows core's single-start-attempt rule. Register all handler names through configuration or through the exported pre-start registration function before starting it.
Native handler contract
For each registered name, BridgedCommandHandler sends a JSON object containing commandId, commandType, params, target, traceId, and optional tags to the native executeHandler bridge method. The native side returns JSON with:
{
"status": "success",
"payload": { "value": "observed result" }
}
or:
{
"status": "failure",
"error": { "code": "camera_unavailable", "message": "Camera is in use" }
}
Payloads must be a JSON object, explicit null, or absent. An array or primitive becomes invalid_result_payload. A rejected, timed-out, malformed, or unavailable bridge call becomes handler_bridge_error; asynchronous native bridge calls have a 30-second safety timeout.
Current bridged handler calls do not forward core's abort signal or lease-validity callback to native code. Core can suppress or fence a late terminal result, but the native operation itself must have a product-specific cancellation channel if interruption is required. Do not document or design native actions as fully cancellable until that channel is implemented and tested.
Choose by authority, not by naming
Use the web runtime when the participating page owns the DOM and can safely receive a page credential. Use the browser runtime when an installed extension must coordinate multiple tabs or use Chrome privileges. Use the mobile runtime when a native host deliberately exposes a bridge. If none of these compositions matches the platform, build on core so identity, transport, response delivery, policy, lifecycle, and handler authority remain explicit.