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
- Base URL: Initialized with a base path (e.g.,
/console/v1) to target the daemon’s console API surface apps/web/src/console/useConsoleAppState.tsx#166-166. - CSRF Protection: The client automatically injects the
x-palyra-csrf-tokenheader into mutating HTTP requests (POST, PUT, DELETE) once a session is established apps/web/src/consoleApi.test.ts#44-90. - Authentication: Supports standard login flows and a specialized “Desktop Handoff” mechanism where a short-lived token from the Palyra Desktop app is exchanged for a full browser session apps/web/src/console/useConsoleAppState.tsx#110-124.
NDJSON Streaming
For chat interactions, the client implementsrunChatStream, 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 theConsoleApiClient 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:- Check Handoff: It looks for a
desktop_handoff_tokenin the URL query parameters apps/web/src/console/useConsoleAppState.tsx#134-144. - 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. - 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.
- Auth Fallback: If no session is found after retries, it transitions from
bootingto theConsoleAuthScreenapps/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:useOverviewDomain: Aggregates high-level system status and capability catalogs apps/web/src/console/useConsoleAppState.tsx#25-25.useAuthDomain: Manages OAuth profiles and identity provider status apps/web/src/console/useConsoleAppState.tsx#22-22.useBrowserDomain: Controls headless browser sessions and snapshots apps/web/src/console/useConsoleAppState.tsx#23-23.useUsageDomain: Handles token tracking, cost estimation, and timeline aggregation apps/web/src/console/hooks/useUsageDomain.ts#1-22.useInventoryDomain: Manages device pairing, trust states, and node inventory apps/web/src/console/hooks/useInventoryDomain.ts#1-13.
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 definedAUTO_REFRESH_SECTION_TTL_MS apps/web/src/console/useConsoleAppState.tsx#43-55.
| Section | TTL (ms) | Purpose |
|---|---|---|
overview | 10,000 | System health and capability updates |
channels | 8,000 | Connector status and message queue depth |
config | 15,000 | Configuration and secret metadata |
browser | 10,000 | Headless session heartbeats |
System Integration
The console state bridges the gap between the React UI and the Rust backend’s internal structures. Diagram: Code Entity MappingData Flow for Usage Aggregates
Usage data (tokens, latency, costs) is processed on the backend and returned as structured envelopes. TheuseUsageDomain hook manages the windowing (24h, 7d, etc.) and pushes these filters to the API apps/web/src/console/sections/UsageSection.tsx#167-188.
- Request:
useUsageDomaincallsapi.getUsageSummarywith a time window apps/web/src/console/hooks/useUsageDomain.ts#22-36. - Processing: The daemon aggregates metrics from the
JournalStore. - Response: Returns a
UsageSummaryEnvelopecontainingUsageTotalsandUsageTimelineBucket[]apps/web/src/consoleApi.ts#154-160. - Rendering: The
UsageSectionusesWorkspaceMetricCardto display these values apps/web/src/console/sections/UsageSection.tsx#95-143.