Files
DivaCode/plan.md

256 lines
9.7 KiB
Markdown

# DivaCode — AI Being Platform Action Plan
**Language:** Go
**Inference:** llama.cpp (HTTP server), OpenAI-compatible API planned
**Inspiration:** OpenHer, Agent Diva, nanobot
---
## Current Status (2026-06-10)
**Builds:** yes
**Runs:** yes (requires llama.cpp on :8080)
**Known issues:**
- Prompt template is raw text — model dumps reasoning/self-correction meta-text instead of just the response
- No chat template configurability (ChatML, Llama 3 instruct, etc.)
- TUI is basic (no streaming, no word-wrap polish)
- Memory store uses keyword `LIKE` search, not real embeddings
- OpenAI-compatible adapter not yet built
- Matrix adapter is a stub
---
## Architecture Overview
```
User
├── TUI (Bubble Tea)
└── Matrix (future)
┌─────┴──────────────────────────────┐
│ Core Agent Loop │
│ (internal/agent/) │
└─────┬──────────────────────────────┘
┌─────┴──────────────────────────────┐
│ Companion Layer │
│ (internal/companion/) │
│ ├─ Personality (5 bounded traits) │
│ ├─ Relationship (familiarity,trust)│
│ ├─ Reflection (diary,observations)│
│ ├─ Mood (6 states + energy) │
│ └─ Prompt Composer (dynamic ctx) │
└─────┬──────────────────────────────┘
┌─────┴──────────────────────────────┐
│ Memory Layer │
│ (internal/memory/) │
│ ├─ RAG store (keywords → vectors) │
│ └─ Self-memory (promises,strats) │
└─────┬──────────────────────────────┘
┌─────┴──────────────────────────────┐
│ Inference (internal/llama/) │
│ ├─ llama.cpp HTTP client │
│ └─ OpenAI-compatible (planned) │
└────────────────────────────────────┘
Skills / Tools:
├─ web_fetch
├─ web_search (stub)
└─ MCP protocol (future)
```
---
## Phase 0 — Foundation & Scaffolding
**Status: COMPLETE**
- [x] Go module: `git.db123.ir/db123/divacode`
- [x] Project structure per Holy Code Bible conventions
- [x] `internal/config/` — std lib `os.Getenv` only
- [x] `internal/storage/``modernc.org/sqlite` (pure Go, no CGO), auto-creates `data/` dir
- [x] `internal/llama/client.go` — HTTP client for `POST /completion`, `POST /embedding`, `GET /health`
- [x] `.env.example`, `Makefile`, `.gitignore`, `Dockerfile`, `docker-compose.yml`
- [x] `AGENTS.md` with architecture, commands, conventions
---
## Phase 1 — Core Agent Loop
**Status: COMPLETE** (minor issues remain)
- [x] `internal/agent/agent.go` — message → memory search → prompt → llama → save → respond
- [x] `internal/agent/scheduler.go` — tick every 15m, check mood/diary/auto-message
- [x] `cmd/divad/main.go` — wires everything: config, DB, llama, TUI, scheduler, Matrix, API
- [x] Conversation persistence to SQLite (`conversations`, `messages` tables)
- [x] Bubble Tea TUI with viewport + input bar
- [ ] Prompt template is wrong — uses raw headers, no chat format. Model outputs meta-text
- [ ] No token tracking — context window grows unbounded
- [ ] TUI doesn't stream tokens (waits for full completion)
---
## Phase 2 — Prompt Templating & Format Fix
**Goal:** Fix the model output. Swap raw prompt text for a configurable chat template so the model only returns the assistant response.
- [ ] `internal/llama/template.go` — chat template formatter:
- ChatML (`<|im_start|>system...<|im_end|>`)
- Llama 3 instruct (`<|begin_of_text|><|start_header_id|>system<|end_header_id|>`)
- Configurable via env `CHAT_TEMPLATE=chatml` (default)
- [ ] Refactor `companion/promptbuilder.go` to output structured segments, then let template.go wrap them
- [ ] Strip system prompt of raw formatting — let the template handle structure
- [ ] Test: "hi" produces just "Hello!" not paragraphs of self-correction
---
## Phase 3 — Long-Term Memory (RAG)
**Goal:** Embedding-based retrieval so the agent recalls across sessions.
- [ ] `internal/memory/embed.go` — call llama.cpp `POST /embedding` to get vectors
- [ ] `internal/memory/store.go` — upgrade `Search()` from keyword `LIKE` to cosine similarity
- [ ] Store embeddings as BLOB in `memories` table
- [ ] Temporal decay — older memories scored lower
- [ ] Importance scoring — "remember this" / emotional content boosts score
- [ ] **Test:** Store info, restart, ask about stored info → recall
---
## Phase 4 — OpenAI-Compatible Adapter
**Goal:** Swap inference to any OpenAI-compatible API (OpenAI, vLLM, Ollama, etc.).
- [ ] `internal/llama/provider.go` — interface:
```go
type Provider interface {
Complete(ctx, *Request) (*Response, error)
Embed(ctx, string) ([]float64, error)
Health() error
}
```
- [ ] Rename `internal/llama/` → `internal/inference/`
- [ ] `llama.go` — implements Provider (existing code)
- [ ] `openai.go` — implements Provider via OpenAI-compatible REST API
- [ ] Config: `INFERENCE_PROVIDER=llama|openai`, `OPENAI_API_KEY`, `OPENAI_BASE_URL`
- [ ] **Test:** Both providers produce same interface, switchable via env
---
## Phase 5 — Episodic Diary & Reflection
**Status: CODE DONE** — needs integration into the scheduled pipeline.
- [x] `internal/companion/reflection.go` — `GenerateDiary`, `RecentObservations`, `AddObservation`
- [x] `diary_entries` table with date, summary, mood, topics, observations
- [x] `observations` table with confidence, category, applied flag
- [ ] Connect scheduler's diary trigger to actual LLM-generated summaries (currently writes stub text)
- [ ] Reflection → Personality update pipeline:
- Observations accumulate → periodic analysis → bounded trait drift
- Max 0.5% change/day, max 5%/month
---
## Phase 6 — MCP Tools & Integrations
**Status: PARTIAL**
- [x] `internal/tools/registry.go` — register/list/execute tools
- [x] `internal/tools/builtin.go` — `web_fetch`, `web_search` (stub)
- [ ] MCP protocol client (`internal/tools/mcp.go`) — stdio/TCP, list tools, execute, parse results
- [ ] Tool call loop in agent: LLM decides → agent executes → result appended → LLM finalizes
- [ ] Plugins: Obsidian vault, Gitea, Actual Budget
---
## Phase 7 — Matrix Integration
**Status: STUB**
- [x] `internal/channel/matrix.go` — config + start stub
- [ ] Full Matrix bot with `mautrix-go`:
- Listen for invitations, join rooms
- Handle DMs with typing indicators
- Bot identity: `@diva:homeserver.tld`
- [ ] Sync TUI and Matrix state
- [ ] **Test:** Send DM, verify response, verify cross-session memory
---
## Phase 8 — Self-Memory & Identity
**Status: CODE DONE**
- [x] `internal/memory/self_memory.go` — promises, strategies
- [x] `agent_promises` table (id, promise, context, fulfilled, deadline)
- [x] `agent_strategies` table (id, situation, strategy, outcome)
- [ ] Wire into Prompt Composer: "You promised to X" context
- [ ] **Test:** "What did you promise me?" → recall
---
## Phase 9 — Safety Guardrails & Identity Stability
**Goal:** Prevent personality drift, maintain core safety.
- [ ] `internal/companion/safety.go` — core identity (stable) vs state (dynamic)
- [ ] Personality safety: bounded traits, safety overrides personality, no tool access changes
- [ ] Prompt injection protection: user input wrapped in delimiters, strict template sections
---
## Phase 10 — Polish: Streaming TUI, Token Tracking, Observability
**Goal:** Production-quality UX.
- [ ] Token streaming in TUI (char-by-char from llama.cpp SSE or chunked response)
- [ ] Context window manager — track tokens, sliding window when full, auto-summarize old messages
- [ ] `POST /v1/chat` streaming via SSE in API mode
- [ ] Prometheus metrics (`GET /metrics`)
- [ ] Graceful shutdown — drain in-flight requests, save state
---
## Phase 11 — Future Enhancements (Optional)
- [ ] Voice: whisper.cpp (STT) + piper/XTTS (TTS)
- [ ] VRM/Live2D avatar rendering
- [ ] Multi-user with per-user relationship tracking
- [ ] Multi-room Matrix
- [ ] Plugin system
- [ ] WebUI dashboard
- [ ] Home Assistant integration
---
## Database Schema (15 tables across 2 DBs)
`divacode.db`:
- `conversations`, `messages`, `context_state`, `memories`
`companion.db`:
- `personality_traits`, `relationship_metrics`, `shared_topics`, `inside_jokes`
- `diary_entries`, `observations`
- `agent_promises`, `agent_strategies`
---
## Key Principles
1. **Smallest loop first** — get message → memory → llm → response working before adding complexity
2. **Personality is data, not prompt text** — traits in SQLite, composed dynamically
3. **Memory ≠ Personality** — factual memory separate from relationship/emotional state
4. **Slow evolution** — max 0.5% trait change/day, 5%/month
5. **Core Identity stable** — never allow personality to override safety rules
6. **Diary before reflection** — nightly diary is the emotional continuity layer
7. **Autonomous messaging** — scheduler makes it feel alive, not the LLM
8. **No config libs** — std lib `os.Getenv` only
9. **No HTTP routers** — std lib `net/http` only
10. **Error wrapping** — `fmt.Errorf("context: %w", err)`, never discard