Skip to content

Architecture

Hypar is a single Nuxt 3 application: Vue 3 on the client, Nitro (h3) server routes on the same port, Prisma 7 + PostgreSQL for persistence, and the Vercel AI SDK for agent interactions via Ollama.

There is no separate API repo and no CORS split — the UI calls relative /api/* routes.


High-level diagram

┌─────────────────────────────────────────────────────────────┐
│                     Browser (Vue 3)                        │
│  pages/*  components/*  Pinia stores                       │
└──────────────────────────┬────────────────────────────────┘
                           │ same origin
┌──────────────────────────▼────────────────────────────────┐
│                  Nitro server (Nuxt)                      │
│  server/api/embryos/*  — CRUD + agent SSE                 │
│  GET /api/health       — db check                         │
│  server/utils/*        — prisma, session, logger, agent   │
└───────────────┬───────────────────────┬───────────────────┘
                │                       │
                ▼                       ▼
          PostgreSQL 16           Ollama (local or cloud)
                                  via OpenAI-compatible API

Domain: Embryo

The data model centers on the Embryo — a unit of knowledge with a lifecycle.

ModelPurpose
EmbryoThe idea. Immutable seed, state, optional fossil fields.
EmbryoEventAppend-only audit: state changes, tensions, agent questions, replies.
TensionAn open question attached to an embryo. Raised by user or agent.
ConnectionA typed directed link: REINFORCES, CONTRADICTS, EXTENDS, RESURRECTS.
AgentNoteHITL pending work: question, connection, path, or fossil proposal.

States: LATENT → GERMINATING → GROWING → MATURE → FOSSIL

No delete. Fossilization preserves the idea, the reason it died, and its full event history.

User transitions are free jumps among living states (including backward). The only automatic advance is first successful agent turn on LATENTGERMINATING. Fossils reject further PATCH and agent calls (409).


Agent integration

POST /api/embryos/[id]/agent streams SSE { type: chunk | done | error }. On done the payload includes question, move, and optional connections, paths, fossil. The client maps those onto ai-elements-nuxt primitives (AiMessage, AiConfirmation, AiQueue, canvas). See ai-elements surfaces.

The agent's spoken turn is constrained: exactly one challenging question. Stance follows lifecycle (define → probe → generate paths → select the simplest). Path and fossil proposals are additive fields, not a second question. No summaries, no validation, no preamble, no named methodology in the question.

Context the agent actually receives:

  • The current embryo (seed, state, unresolved tensions, recent dialogue)
  • Up to 15 other living embryos and 5 fossils
  • Outgoing connection targets already linked from this embryo

Agent-detected links are stored as unconfirmed Connection rows (detectedBy: AGENT) plus a HITL note. Accept confirms; dismiss deletes the unconfirmed row. The graph draws dashed inferred edges.


HTTP surface (embryos)

RouteRole
GET/POST /api/embryosList (own) / create LATENT
GET/PATCH /api/embryos/:idDetail / actions (transition, tensions, connect, reply, accept path/fossil, dismiss note)
POST /api/embryos/:id/agentSSE collaborator turn (optional { model })
POST /api/embryos/:id/fossilizeClose with a required reason
GET /api/llm/modelsOllama tags for the settings selector
GET /api/health{ status, checks.db, ts } — unauthenticated, used by Compose

All embryo and LLM routes call requireSessionUserId. Ownership is userId on every query.


Layer responsibilities

LayerPathResponsibility
UIpages/, components/embryo/, components/garden/Garden, detail, collaborator, graph, pending queue, auth, admin stubs, settings (model selector).
Methodutils/embryo-method.tsStance, fossil kinds, copy.
APIserver/api/embryos/**CRUD, transitions, fossilization, agent SSE.
Storestores/embryos.tsPinia store with computed views (byState, alive).
Dataprisma/schema.prismaEmbryo domain + better-auth models.

Deployment

  • Development: pnpm dev + local PostgreSQL + Ollama (local or cloud)
  • Docker: docker compose --profile full runs app + Postgres + Ollama
  • Production: see Production deployment

Next

MIT License