Skip to content

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.

Terminal window
pnpm add @coframe/editor-rest

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 open

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.

OptionTypeDescription
baseUrlstringEditor-web deployment URL.
tokenstringOptional bearer token sent with every request.
fetchtypeof fetchOptional custom fetch (testing / non-global environments).

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).

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.

Exercise the full headless lifecycle against a real Coframe Agent backend: