Delegate edits (REST)
Use @coframe/editor-rest when you want to hand an edit off to Coframe Agent
and get the result back — no persistent connection, no UI. Start a session
with an instruction, then either poll for completion or stream events as the
agent works. It’s a zero-dependency TypeScript client that runs in Node 18+,
Cloudflare Workers, and browsers. Not using TypeScript? The underlying wire
contract is documented in the Session API.
Installation
Section titled “Installation”pnpm add @coframe/editor-restQuick start
Section titled “Quick start”The recommended flow is start → wait → use the result:
import { EditorRestClient } from "@coframe/editor-rest";
const client = new EditorRestClient({ baseUrl: "https://editor.example.com", token: "your-api-token",});
// 1. Start a session with an initial instruction.const session = await client.startSession({ messages: [ { role: "user", parts: [{ type: "text", text: "Make the hero headline more compelling" }], }, ], targetUrl: "https://example.com",});
// 2. Wait for the agent to finish.const status = await client.waitForCompletion( session.sessionId, session.requestId,);
// 3. Share or open the result.console.log(status.status); // "completed"console.log(session.shareUrl); // a link your users can openStream events as they happen
Section titled “Stream events as they happen”If you’d rather render progress live, iterate streamRequestEvents instead of
waiting. Each frame is a { type, data } pair:
const session = await client.startSession({ messages: [ { role: "user", parts: [{ type: "text", text: "Add a pricing section" }], }, ], targetUrl: "https://example.com",});
for await (const event of client.streamRequestEvents( session.sessionId, session.requestId,)) { console.log(event.type, event.data);}Pass an AbortSignal as the third argument to cancel the stream early.
API reference
Section titled “API reference”new EditorRestClient(options)
Section titled “new EditorRestClient(options)”| Option | Type | Description |
|---|---|---|
baseUrl | string | Editor-web deployment URL. |
token | string | Optional bearer token sent with every request. |
fetch | typeof fetch | Optional custom fetch (testing / non-global environments). |
startSession(input)
Section titled “startSession(input)”Mints a session and starts the first turn. Returns:
interface StartSessionResult { sessionId: string; requestId: string; runId: string; shareUrl: string; // human-openable link to the session statusUrl: string; // GET endpoint for polling status streamUrl: string; // SSE endpoint for live events}input accepts messages (required), plus optional targetUrl,
targetPageUrls, metadata, idempotencyKey, userId, source
(caller attribution: "web" | "api" | "slack" | "cli", default "api"), and
callback ({ url, secret?, events? } — a webhook that receives run
lifecycle events so you don’t have to poll or stream; see the
Session API for the
delivery format and signature verification).
getRequestStatus(sessionId, requestId)
Section titled “getRequestStatus(sessionId, requestId)”Polls a single request. Returns { requestId, runId, status, sessionId },
where status is "pending" | "running" | "completed".
streamRequestEvents(sessionId, requestId, signal?)
Section titled “streamRequestEvents(sessionId, requestId, signal?)”Returns an AsyncGenerator<StreamEvent> that yields { type, data } frames
over SSE until the stream closes. The parser reassembles messages that span
multiple network chunks, so you always receive whole events.
waitForCompletion(sessionId, requestId, options?)
Section titled “waitForCompletion(sessionId, requestId, options?)”Convenience wrapper that polls until the request reaches completed and
returns the final RequestStatus. Options: pollIntervalMs, timeoutMs,
and signal.
Live demo
Section titled “Live demo”Exercise the full headless lifecycle against a real Coframe Agent backend: