Skip to main content
The Palyra Web Console is a React-based Single Page Application (SPA) that serves as the primary operator interface for the palyrad daemon. It utilizes a centralized API client for communication and a unified state management hook to coordinate domain-specific logic, authentication, and real-time data streaming.

Console API Client (ConsoleApiClient)

The ConsoleApiClient is the core transport layer for the web console. It abstracts the underlying fetch calls, handles session lifecycle, enforces CSRF protection, and manages NDJSON (Newline Delimited JSON) streaming for long-running operations like chat runs.

Implementation Details

NDJSON Streaming

For chat interactions, the client implements runChatStream, which processes a stream of ChatStreamLine objects. This allows the UI to render incremental updates (e.g., partial LLM tokens or tool execution status) as they arrive from the orchestrator apps/web/src/consoleApi.ts#47-192.

API Interaction Flow

The following diagram illustrates how the ConsoleApiClient coordinates a mutating request with CSRF enforcement. Diagram: Mutating Request Lifecycle Sources: apps/web/src/consoleApi.test.ts#44-106, apps/web/src/console/useConsoleAppState.tsx#166-168.

State Management and useConsoleAppState

The useConsoleAppState hook serves as the “brain” of the console, orchestrating multiple sub-domains and managing the global application lifecycle (booting, auth, and routing).

Boot Sequence

When the application starts, it undergoes a multi-stage bootstrap process:
  1. Check Handoff: It looks for a desktop_handoff_token in the URL query parameters apps/web/src/console/useConsoleAppState.tsx#134-144.
  2. Session Recovery: If on localhost, it attempts to recover an existing session or consume the handoff token apps/web/src/console/useConsoleAppState.tsx#126-132.
  3. Retry Loop: If the daemon is still starting up, it retries the session fetch with exponential backoff (up to 5 attempts) apps/web/src/console/useConsoleAppState.tsx#89-108.
  4. Auth Fallback: If no session is found after retries, it transitions from booting to the ConsoleAuthScreen apps/web/src/App.tsx#16-30.

Domain Hooks

The state is partitioned into domain-specific hooks that manage their own loading states and data fetching:

Auto-Refresh Logic

The console implements a TTL-based auto-refresh strategy to keep the UI current without overloading the daemon. Each section has a defined AUTO_REFRESH_SECTION_TTL_MS apps/web/src/console/useConsoleAppState.tsx#43-55.
SectionTTL (ms)Purpose
overview10,000System health and capability updates
channels8,000Connector status and message queue depth
config15,000Configuration and secret metadata
browser10,000Headless session heartbeats
Sources: apps/web/src/console/useConsoleAppState.tsx#43-73, apps/web/src/console/sections/OperationsSection.tsx#49-122.

System Integration

The console state bridges the gap between the React UI and the Rust backend’s internal structures. Diagram: Code Entity Mapping

Data Flow for Usage Aggregates

Usage data (tokens, latency, costs) is processed on the backend and returned as structured envelopes. The useUsageDomain hook manages the windowing (24h, 7d, etc.) and pushes these filters to the API apps/web/src/console/sections/UsageSection.tsx#167-188.
  1. Request: useUsageDomain calls api.getUsageSummary with a time window apps/web/src/console/hooks/useUsageDomain.ts#22-36.
  2. Processing: The daemon aggregates metrics from the JournalStore.
  3. Response: Returns a UsageSummaryEnvelope containing UsageTotals and UsageTimelineBucket[] apps/web/src/consoleApi.ts#154-160.
  4. Rendering: The UsageSection uses WorkspaceMetricCard to display these values apps/web/src/console/sections/UsageSection.tsx#95-143.
Sources: apps/web/src/console/sections/UsageSection.tsx#34-143, apps/web/src/consoleApi.ts#154-192.