Skip to content

SPEC.md — @robota-sdk/agent-web

Scope

Browser React component library for monitoring and optionally controlling a running agent-cli session over WebSocket. Provides a connection hook (useWsSession), a conversation view component (ConversationView), and a self-contained monitor widget (SessionMonitor) that applications can embed without importing from any other @robota-sdk/* package.

This package sits in the Product shells layer. It is a pure browser UI library — it does not own session lifecycle, conversation history, or agent runtime state.

Distinction from apps/agent-web: packages/agent-web-ui is a published npm package that exports reusable browser React components. apps/agent-webis a Next.js host application that consumespackages/agent-web-ui and deploys the actual web UI. They share a name prefix but are different layers: this package is a library; the app is a deployment.

Boundaries

  • Does NOT own WebSocket protocol framing — that is @robota-sdk/agent-transport/ws (TServerMessage, TClientMessage).
  • Does NOT own InteractiveSession or any SDK/session/runtime contracts — those live in agent-framework, agent-session, agent-executor.
  • Does NOT own agent-core types directly — message types pass through agent-transport/ws.
  • Does NOT own the CLI sidecar server — that is agent-cli (startWebSidecarServer).
  • OWNS: browser WebSocket client lifecycle (IWsSessionClient, reconnect logic).
  • OWNS: React state reconstruction from TServerMessage events (useWsSession).
  • OWNS: React components SessionMonitor and ConversationView.
  • OWNS: TConnectionStatus type (disconnected | connecting | connected | error).

Architecture Overview

agent-web (browser)
  └── useWsSession(url)
        └── createWsSessionClient  ← reconnects on disconnect (max 10 attempts, 2s delay)
              │  onMessage (TServerMessage)
              └── agent-transport/ws  ← TServerMessage / TClientMessage types only

On connect the client sends { type: "get-messages" } to request full history replay from the CLI sidecar. Subsequent TServerMessage events update React state in useWsSession.

SessionMonitor is a self-contained React component that renders connection status, the conversation view, and a prompt input. It calls useWsSession internally and requires only a url prop pointing at the CLI sidecar's WebSocket endpoint.

ConversationView is a pure rendering component that accepts IConversationMessage[], IActiveTool[], streamingText, and isThinking props from the caller.

Type Ownership

TypeLocationPurpose
TConnectionStatussrc/client/ws-session-client.tsWebSocket lifecycle state: disconnected / connecting / connected / error
IWsSessionClientsrc/client/ws-session-client.tsHandle returned by createWsSessionClient (connect/disconnect/send/status)
IConversationMessagesrc/hooks/useWsSession.tsReconstructed conversation message with id, role, content, and optional streaming flag
IActiveToolsrc/hooks/useWsSession.tsActive tool call state: id, name, status (running/done/error), input, result
IWsSessionStatesrc/hooks/useWsSession.tsFull React hook state: status, messages, activeTools, streamingText, isThinking, send

Public API Surface

ExportKindDescription
SessionMonitorcomponentSelf-contained monitor widget; accepts url prop for the CLI sidecar WebSocket
ConversationViewcomponentPure conversation renderer; accepts messages, activeTools, streamingText, isThinking
useWsSessionhookReact hook managing WebSocket connection and reconstructing session state
IConversationMessagetypeReconstructed message shape for display
IActiveTooltypeActive tool call display state
IWsSessionStatetypeFull hook return type
TConnectionStatustypeWebSocket lifecycle status enum

Extension Points

  • Consumers may use useWsSession directly for custom UI layouts instead of SessionMonitor.
  • ConversationView accepts all display props explicitly; consumers can wrap it inside any layout.
  • The send function returned by useWsSession accepts TClientMessage values to submit prompts back to the CLI session (Phase 2 feature).

Error Taxonomy

SourceBehavior
WebSocket bind failStatus transitions to error; reconnect attempted up to 10 times
Invalid JSONSilently ignored (non-string data is filtered before parse)
Server-closedStatus transitions to disconnected; automatic reconnect unless disconnect() was called

Test Strategy

  • No test files exist currently. Recommended:
    • Unit tests for createWsSessionClient reconnect logic with a mock WebSocket.
    • Unit tests for useWsSession message reconstruction logic (mocking createWsSessionClient).
    • Render tests for ConversationView with representative message arrays.

Class Contract Registry

Functions / Hooks

ExportDefined InNotes
createWsSessionClientsrc/client/ws-session-client.tsFactory; not re-exported from package root
useWsSessionsrc/hooks/useWsSession.tsRe-exported from package root

Components

ComponentDefined InNotes
SessionMonitorsrc/components/SessionMonitor.tsx'use client' directive; Tailwind CSS
ConversationViewsrc/components/ConversationView.tsxPure renderer; Tailwind CSS

Cross-Package Port Consumers

Port (Owner)Usage
TServerMessage (agent-transport/ws)Parsed from WebSocket onmessage events
TClientMessage (agent-transport/ws)Sent to sidecar via ws.send(JSON.stringify(msg))

Released under the MIT License.