Aller au contenu

@maiaos/client-core

Platform-neutral client use cases for Maia OS: Effect services that sit between a client's renderer and @maiaos/sdk, so every client reads Maia Node state and sends requests the same way.

Pre-release. Maia publishes canary builds to npm only, and latest follows the newest one (earlier nightly builds are historical). They are not release-qualified, and Maia has no stable release (D-202). Nothing in this package is a stability promise: entry points, names and shapes can change in any build.

Two Maia clients share it. The Expo client, @maiaos/client (Desktop and mobile), uses it today. The maia CLI will use it for its terminal dashboard (D-161, planned; the CLI does not use it yet).

Requirements

Node.js 24.22.1, and a Maia Node to talk to through @maiaos/sdk, which installs with this package.

Install

pnpm add @maiaos/client-core@canary   # or an exact version

Usage

import { makeNodeStatusClientService } from "@maiaos/client-core/node-status";
import { validateVoiceProposal } from "@maiaos/client-core/single-session";
import { makeTerminalClientService } from "@maiaos/client-core/terminal";
import { makeWorkspaceScopeService } from "@maiaos/client-core/workspace-scope";

Each factory returns an Effect service that the renderer composes with a platform transport; React components only render its state.

The package owns client-side validation, deadlines, cancellation, recovery of uncertain requests and projections of Node state. It owns no transport, credentials, native API, Node lifecycle or durable state: the SDK is the protocol client and Maia Node is the authority.

Entry pointResponsibility
bootThe Desktop boot sequence: lifecycle status, one start, then status reads until the host reports a ready Node
navigationRoute names, the ?q=&state=&page= list query, parent routes and the one pagination model
node-statusOne truthful, point-in-time Node status projection
workspace-scopeThe one active Workspace scope, loaded from and replaced only by Node
single-sessionVoice setup, Node-provided orchestrator context and local proposals
terminal, terminal-unavailableLive terminal client and its explicit unavailable state
interaction, interaction-viewRecord-only questions and answers, with recovery of unknown outcomes
presentationBounded Workspace, Project and Session list reads
cockpitWork cockpit per Node and a combined view: one bounded index, one change feed, attention, lists, launcher search, single or bulk Session creation over the SDK batch and first-run onboarding
session-viewFocused Session detail: live items over session.attach, recent turns, summary, diff and a send, interrupt and wait composer
commandsThe keyboard command registry: stable IDs, Desktop and terminal keymaps, rebinding, conflicts and reserved chords
node-registryThe local and registered remote Nodes a client addresses: connecting, ready, stale or unreachable (with ssh's reason, or auth when the Node rejects the credential)
session-attachThe SDK's Session attach reducer, re-exported unchanged
dictationComposer dictation state: listening, partial text at the caret, cancel, language
  • Deadlines and uncertainty. Every request gets a unique message ID from the package IdGenerator (Effect Random by default) and a 5.5-second client deadline. A timed-out query is retryable; a timed-out mutation is outcome_unknown and is reconciled with its original command ID, never retried as a new one. Each request carries deadlineAt, that deadline as an instant on Clock.monotonicTimeNanos (never wall-clock time), for a requester that retries to stop before it. A client that must bound its reads in flight provides ReadAdmission; a read waits for its permit before its deadline starts, and a mutation never waits.
  • Freshness. Each Node's cockpit keeps the time of its last successful read and one whole-Node load in flight. A failed load retries, after 2 s and doubling to 30 s, until the Node answers; a reload a person asks for runs once; the change feed resubscribes on the same backoff. A copy is stale when its latest whole-Node read failed and partial until the Node first answers or while it caps a read. The combined view stays ready once any Node answers.
  • Routing. The combined view labels each Project and Session with its Node, and nodeIdOf is the one lookup an action asks. It returns that Node, or a NodeRouteError when the combined view holds no such target (unknown) or two Nodes' indexes hold the same ID (ambiguous). A repeated Workspace, Project or Session ID keeps the first Node's record and marks the view truncated, and no action targets a repeated Project or Session. One Node's own view routes every target to that Node, since its bounded index can lack a Session the Node holds.
  • Fail closed. Token, Workspace, orchestrator and relay services are unavailable by default. A proposal or preview is never evidence of delivery; only an exact Node preview enables explicit confirmation.
  • No hidden authority. Browsing owns no execution focus or mutation authority, and errors carry only bounded reason codes, never credentials or request envelopes.

Status

Source candidate. Its terminal, voice, interaction and cockpit services are not release-qualified. The cockpit follows today's observe.events feed; the planned R1 aggregate subscription, view store and reconnect policy will replace its index load here; see the client architecture.

  • Bulk creation. A preview fixes every target, task and command ID and carries a digest; one confirmation runs it once, within its expiry. Each item reports its receipts or the Node's refusal (for example saturated when an account has no free slot). A retry replays the same commands and request bodies, so the Node answers the original results. The Run ledger (S19) joins as a second CreationDispatch.
  • Onboarding. makeOnboarding reads vendor accounts from Connection records, scans native sessions as metadata (titles only when a person turns them on), registers repositories, and runs adoption as a preview, then one confirmation request per item, each opening the Desktop native sheet. A declined or uncertain confirmation stops the batch; confirming again resends the same preview IDs. One-click use of signed-in CLIs waits for connection.detect (CliDetection placeholder).
  • Timeline seam. session-view reads final turn text through a TimelineSource; the S12b reduceSessionAttach source plugs in there.

Imported from Maia OS docs at a2175bb