6.5 KiB
Phase 5 Browser SDK and Reference Console
Public package surface
Phase 5 freezes the first browser SDK as package version 0.1.0.
| Import | Purpose |
|---|---|
@paperclipai/paperclip-runner |
Protocol, reducer, and existing package contracts |
@paperclipai/paperclip-runner/browser |
Framework-free HTTP/SSE client, protocol types, transcript projection |
@paperclipai/paperclip-runner/react |
Hook, reference console, and reusable React components |
@paperclipai/paperclip-runner/styles.css |
Scoped light-theme token and component styles |
React and React DOM are peer dependencies. The extracted surface adds no
runtime dependency. It is client-only: it uses window, sessionStorage,
Fetch, and EventSource, so applications must mount it in the browser rather
than render it on the server.
Framework-free client
import { createRunnerClient } from "@paperclipai/paperclip-runner/browser";
const client = createRunnerClient({ baseUrl: "/api/phase4b" });
const manifests = await client.fetchManifests();
RunnerClient exposes manifest listing; session create/read/close; event
history and SSE streaming; turn start, steering, and interrupt; typed request
resolution; goal operations; and reconnect. RunnerClientError preserves the
HTTP status, stable error code, and redacted server message.
The protocol server remains authoritative. The browser client never creates a second event model, invents capabilities, changes run/session/provider identities, or removes duplicate events before the shared reducer sees them.
React hook
import { useRunnerConsole } from "@paperclipai/paperclip-runner/react";
function Console() {
const runner = useRunnerConsole({ baseUrl: "/api/phase4b" });
return <p>{runner.connection}: {runner.replayParity ? "match" : "waiting"}</p>;
}
useRunnerConsole returns manifests and selection, canonical server state,
the exact event list, reducer snapshot, transcript projection, connection and
retry state, composer state, steering acknowledgements, a single polite
announcement channel, errors, busy state, lineage selection, replay controls,
and verbs for every supported mutation. Durable history is re-read before a
reconnected stream opens. Replay uses the same reducer as live state.
Components
The ./react export includes:
- primitives:
Button,Badge,Card,Textarea,Tabs,Menu,Dialog,Tooltip, andBanner; - protocol views:
Conversation,Message,ReasoningItem,ToolItem,RequestCard,SessionTimeline,Inspector,ReplayControls, andConnectionBanner; - composition:
Composer,RunnerConsoleApp, anduseRunnerConsole.
Components take reducer/protocol shapes. Every component owns a stable
data-slot and pcr- class. Terminal, file, tool, plan, request, failure,
lineage, goal, connection, and replay states come only from canonical events
or public session state.
Five extension points
These are the complete extension surface for 0.1.0:
Conversation,Message,ReasoningItem, andToolItemacceptrenderItemBody(item)for markdown, highlighting, or another item body.RequestCardacceptsrenderRequestDetail(request)for its detail region.ComposeracceptsleadingActionsandtrailingActions.- Consumers may override
--pcr-*properties under.pcr-root. createRunnerClientanduseRunnerConsoleacceptbaseUrl,fetchImpl, andeventSourceFactorytransport injection.
There is no headless distribution, component registry, render-prop shell, dark theme, toast layer, or virtualized transcript in this version.
Transport and credential boundary
const runner = useRunnerConsole({
baseUrl: "/runner",
fetchImpl: (input, init) => fetch(input, {
...init,
headers: { ...Object.fromEntries(new Headers(init?.headers)), "x-app-session": appSession },
}),
eventSourceFactory: (url) => new EventSource(url),
});
Transport injection is for browser-to-protocol-server authentication, proxies, and test doubles. Provider credentials stay on that server. Do not place a provider bearer token in component props, manifest text, events, diagnostics, browser storage, or an EventSource query string. The package demo fixes and validates its workspace server-side and redacts provider paths and credentials.
Tokens and contrast
styles.css declares a light-only color-scheme and all visual values under
.pcr-root. The shipped foreground/surface pairs are:
| Foreground | Surface | Contrast |
|---|---|---|
--pcr-foreground |
--pcr-background |
16.4:1 |
--pcr-card-foreground |
--pcr-card |
17.6:1 |
--pcr-primary-foreground |
--pcr-primary |
15.6:1 |
--pcr-muted-foreground |
--pcr-muted |
5.0:1 |
--pcr-success |
--pcr-success-surface |
6.5:1 |
--pcr-warning |
--pcr-warning-surface |
5.4:1 |
--pcr-danger |
--pcr-danger-surface |
6.2:1 |
--pcr-accent |
--pcr-accent-surface |
5.5:1 |
When a consumer overrides either side of a pair, that consumer owns a new
contrast check. Keep normal text at 4.5:1 or better. Motion respects
prefers-reduced-motion. All mobile controls use the --pcr-touch-target
minimum.
Minimum supported widths are 320px for Conversation, Composer, and
Inspector, and 280px for RequestCard. RunnerConsoleApp renders one
responsive tree: three panes above 900px and one selected pane below it.
Keyboard and accessibility contract
- The transcript is a labelled
role="log"; consumers render the hook'sannouncementonce in anaria-live="polite"region. - Composer Enter sends or steers; Shift+Enter adds a line. Stop remains a separate button.
- Tabs use arrow-key roving focus plus Home/End.
- Menu supports Enter/Space/ArrowDown, arrows, Home/End, and Escape with focus restoration.
- The native dialog traps focus, closes on Escape, and restores its trigger.
- Reasoning and tool disclosures use native summary keyboard behavior.
- Replay Left/Right steps; Space toggles play from the scrubber.
- Status is always named in text, not communicated by color alone.
- Informational banners do not steal focus. A blocking reconnect failure may.
Reference applications
examples/reference-console/ composes RunnerConsoleApp only from public
exports. examples/mini-consumer/ imports only the three public SDK subpaths
and visibly exercises every extension point. Both run against the package fake
driver or the real Codex driver through the same server-only adapter.
See the hand-run tutorial and the implementation decision record.