跳到主内容
Spark
中文

Architecture

Surface UIs, protocol, server, engine, session files — five layers top to bottom.

Architecture

Five layers: surface UIs / protocol / server / engine / session files.

apps/*Four surface UIs (Web · Desktop · CLI · Mobile)
@spark/protocol27-event vocabulary · zod schemas · Transport
apps/serverFastify · SSE · binds to 127.0.0.1 only
@spark/engineInputQueue → RunLoop → ToolPipeline
sessions/*.jsonldurable append-only · fully replayable

↓ data flow: user input → engine → events → UI

Event model

27 events form the full vocabulary (24 durable / 3 live-only), each carrying three attributes:

durable
24 types. Persisted to JSONL, replayable to rebuild the UI
live
3 delta types. Never persisted, gone after a reconnect
surface
2 types. The model-visible surface — always in model history

The two "projections" differ: each surface folds the event stream into UI state with the same applyEvent reducer, while the engine-side Projector projects model context (surface events → LlmMessage). The protocol layer is runtime code, not type definitions. New events follow the new-event-type flow: type definition → zod schema → classification → reducer unit test → engine emit → doc sync.

Four surfaces

Shared @spark/protocol, platform specifics adapted per surface.

  • Web

    The primary interactive surface, full feature coverage

    React 19 · Vite 7 · Tailwind CSS v4

  • Desktop

    Local shell, system integration and shortcuts

    Electron sidecar · embedded server

  • CLI

    Terminal-native experience, keyboard only

    Ink 7 · Node.js 24

  • Mobile

    Session viewing and light interaction on mobile

    Expo + RN · Taro 4 mini app

Data location

Session data persists as append-only JSONL on the local filesystem — no external database.

bash
# Session data location (packages/engine/src/session/store.ts)
~/.spark/sessions/<cwd-munged>-<sha1-8>/<ISO-timestamp>_<sessionId>.jsonl

# Format: append-only JSONL
# Line 0 is the header (sparkVersion / cwd / createdAt / model)
# Each following line is one event envelope, seq == file line number
# Append-only, never rewritten — the full decision chain is preserved
# Replay = reduce line by line from the top → rebuild the full UI state