Pi chat agent UI template on Svelte/SvelteKit, ready for plugging with knowledge and tools.
  • TypeScript 71.3%
  • Svelte 21.5%
  • Just 4.3%
  • JavaScript 2.3%
  • HTML 0.6%
Find a file
2026-06-17 21:49:26 +07:00
src add phase 2 with some tests 2026-06-17 21:49:26 +07:00
static init 2026-06-17 17:34:21 +07:00
.gitignore add phase 1 with test 2026-06-17 19:05:47 +07:00
.npmrc init 2026-06-17 17:34:21 +07:00
.prettierignore init 2026-06-17 17:34:21 +07:00
.prettierrc init 2026-06-17 17:34:21 +07:00
bun.lock add phase 1 with test 2026-06-17 19:05:47 +07:00
eslint.config.js init 2026-06-17 17:34:21 +07:00
justfile add phase 1 with test 2026-06-17 19:05:47 +07:00
package.json add phase 1 with test 2026-06-17 19:05:47 +07:00
README.md add phase 2 with some tests 2026-06-17 21:49:26 +07:00
tsconfig.json init 2026-06-17 17:34:21 +07:00
vite.config.ts init 2026-06-17 17:34:21 +07:00

barechat

A web chat UI that connects to @earendil-works/pi-agent-core Agent backend — a modern web alternative to the @earendil-works/pi-tui terminal experience.

Architecture

  • SvelteKit (app shell + API routes)
  • SSE (server→client event stream)
  • JSONL (server-side session persistence)
  • pi-agent-core (Agent runtime, model inference)

Each SSE connection owns one Agent. Sessions are permanent threads with JSONL history replay on reconnect.

Project Structure

src/
├── lib/
│   ├── agent/
│   │   ├── manager.ts    # Session CRUD, JSONL read/write, listSessions()
│   │   ├── run.ts        # Agent init, prompt handling, SSE event forwarding
│   │   └── types.ts      # SSEEvent interface
│   ├── components/
│   │   └── SessionSidebar.svelte  # Session list sidebar
│   ├── stores/
│   │   ├── sessions.ts       # LocalStorage-backed session list
│   │   ├── currentSession.ts # Active session store
│   │   └── events.ts         # SSE event state store
│   └── vitest-examples/  # SvelteKit scaffold examples
├── routes/
│   ├── +layout.svelte    # App layout (favicon, Svelte head)
│   ├── +page.svelte      # Chat page (placeholder — Phase 3)
│   └── api/sessions/
│       ├── +server.ts         # POST create, DELETE
│       └── [sessionId]/
│           ├── +server.ts     # DELETE (moved from parent)
│           ├── prompt/
│           │   └── +server.ts # POST prompt
│           └── sse/
│               └── +server.ts # GET SSE stream
├── test/
│   ├── index.ts              # Barrel export
│   ├── fixtures/
│   │   ├── messages.ts       # userMessage(), fullAssistantMessage(), toolResultMessage()
│   │   ├── messages.test.ts  # 4 tests — message builders
│   │   ├── jsonl.ts          # readJsonl(), writeJsonl(), appendJsonl()
│   │   ├── jsonl.test.ts     # 2 tests — JSONL roundtrip
│   │   ├── session.ts        # createTestSession(), deleteTestSession(), listTestSessions()
│   │   └── session.test.ts   # 5 tests — session CRUD
│   ├── mock-agent.ts         # FakeAgent — event emitter for unit tests
│   ├── mock-agent.test.ts    # 5 tests — lifecycle, subscribe, abort
│   ├── sse.ts                # collectSSEEvents(), extractEventTypes()
│   └── sse.test.ts           # 2 tests — SSE collection + event extraction
└── app.d.ts / app.html

API Endpoints

Method Endpoint Description
POST /api/sessions Create session → { sessionId, createdAt } (201)
DELETE /api/sessions/:sessionId Delete session → { deleted: true } (200)
GET /api/sessions/:sessionId/sse Open SSE stream (replay history + live events)
POST /api/sessions/:sessionId/prompt Send prompt → { accepted: true } (202)

SSE Event Types

Event Payload
agent_start {}
turn_start {}
message_start { message, type? }
message_update { contentIndex, delta, type: "text_delta"|"thinking_delta" }
message_end { message }
tool_execution_start { toolCallId, toolName, args }
tool_execution_end { toolCallId, toolName, result, isError }
turn_end { message, toolResults }
agent_end { messages }
error { errorMessage }

Environment Variables

Variable Required Default Description
SYSTEM_PROMPT Yes System prompt for the Agent
MODEL Yes provider/modelId (e.g. anthropic/claude-sonnet-4-20250514)
OPENAI_BASE_URL conditional Base URL for OpenAI-compatible endpoints
OPENAI_API_KEY conditional API key for OpenAI-compatible endpoints
SESSION_DIR No ./data/sessions Directory for JSONL session files

The MODEL variable supports either provider/modelId format or a bare model ID (defaults to openai provider). When using OpenAI-compatible endpoints (vLLM, Ollama, etc.), set OPENAI_BASE_URL and OPENAI_API_KEY.

Development

Prerequisites

  • bun or Node.js 20+
  • just (optional, for convenience commands)

Quick Start

# Install dependencies
just install-deps        # or: bun install

# Copy and configure environment
cp .env.local .env        # edit with your MODEL, OPENAI_BASE_URL, etc.

# Run tests
just test

# Start dev server
just dev

Commands

Command Description
just dev Start Vite dev server
just build Build for production
just preview Preview production build
just lint Prettier check + ESLint
just format / just fmt Format with Prettier
just check Full type check (svelte-check)
just check-watch Type check in watch mode
just test Server tests (unit + integration)
just test-all All tests including Playwright client tests
just sync Regenerate SvelteKit generated files
just ci lint + check + test

Implementation Status

Phase 1: Backend Foundation

  • Session CRUD (create, delete, list) with uuidv7 IDs
  • JSONL read/write persistence
  • Agent initialization & prompt handling
  • SSE event streaming (fine-grained, live)
  • JSONL replay on reconnect
  • Agent polling loop (detects prompts between runs)
  • Full end-to-end curl tested

Phase 2: Frontend Skeleton

  • src/lib/stores/sessions.ts — LocalStorage-backed session list
  • src/lib/stores/currentSession.ts — active session store
  • src/lib/stores/events.ts — SSE event state store
  • SessionSidebar.svelte — session list with create/delete
  • +layout.svelte — sidebar + chat area layout
  • +page.svelte — wire up session creation & SSE connection
  • Added GET /api/sessions endpoint for listing sessions

📋 Phase 3: Chat UI Components

  • InputBox.svelte — auto-growing textarea (Enter=send)
  • MessageList.svelte — renders message array
  • MessageBubble.svelte — individual message rendering
  • ThinkingBlock.svelte — collapsible thinking
  • ToolBlock.svelte — collapsible tool execution
  • ErrorBlock.svelte — inline error display
  • MarkdownContent.sveltemarked + highlight.js renderer

📋 Phase 4: Integration & Polish

  • Replay logic (SSE history → UI build)
  • Reconnect flow (session ID → SSE → replay)
  • Loading states during prompt execution
  • Message timestamps
  • Style polish (colors, spacing, transitions)
  • Error handling (network, agent, SSE disconnect)
  • Mobile responsive layout

Test Module

The src/test/ module provides utilities for backend testing:

  • Message fixtures: userMessage(), fullAssistantMessage(), toolResultMessage()
  • JSONL helpers: readJsonl(), writeJsonl(), appendJsonl()
  • Session fixtures: createTestSession(), deleteTestSession(), listTestSessions(), clearTestSessions() (uses isolated data/sessions-test/ directory)
  • SSE collector: collectSSEEvents() — captures SSE events from a URL
  • FakeAgent: lightweight mock Agent for unit tests — emits events, supports prompt(), subscribe(), abort()

19 tests passing across fixtures, mock agent, and SSE utilities.