[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-92586":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":8,"htmlUrl":8,"language":9,"languages":8,"totalLinesOfCode":8,"stars":10,"forks":11,"watchers":12,"openIssues":13,"contributorsCount":14,"subscribersCount":14,"size":14,"stars1d":14,"stars7d":14,"stars30d":15,"stars90d":14,"forks30d":14,"starsTrendScore":14,"compositeScore":16,"rankGlobal":8,"rankLanguage":8,"license":17,"archived":18,"fork":18,"defaultBranch":19,"hasWiki":20,"hasPages":18,"topics":21,"createdAt":8,"pushedAt":8,"updatedAt":22,"readmeContent":23,"aiSummary":24,"trendingCount":14,"starSnapshotCount":14,"syncStatus":25,"lastSyncTime":26,"discoverSource":27},92586,"MemoryConstellations","ClaraShafiq\u002FMemoryConstellations","ClaraShafiq",null,"JavaScript",54,9,51,1,0,3,40.3,"MIT License",false,"main",true,[],"2026-07-22 04:02:06","# Memory Constellations · 记忆星图\n\nA self-organizing memory system for AI companions. Extracts facts from chat, groups them by topic, and merges them into coherent narratives — all on autopilot.\n\nBuilt by **Clara Shafiq & Draco Malfoy**.\n\n---\n\n## What it does\n\nThree things happen automatically while your companion runs:\n\n1. **Extract.** Scribe scans new chat messages and pulls out facts — who, where, what happened, what changed. Each fact is a short, third-person sentence with a link back to the original messages.\n\n2. **Organize.** Archivist runs every 2 minutes. It groups related facts into topics (constellations), merges tightly-related facts into narrative paragraphs (episodes), and periodically weaves episodes into long-term story arcs (sagas) that span multiple topics.\n\n3. **Retrieve.** When your companion needs context during a chat, Librarian searches across all three layers — raw facts, narrative episodes, and entity profiles — using a mix of keyword matching, vector similarity, and entity aggregation.\n\n(Optional) A 5-axis emotional state engine (jiwen, a separate open-source project) can integrate with this pipeline, with saga arcs applying a small but continuous pull on the companion's baseline mood.\n\n---\n\n## What you see\n\nOpen `\u002Fmemory.html` — it renders a star map from the database:\n\n- Five galaxies (Social, Places, Events, Hobbies, [Your] Projects) orbit a binary core (you + your companion)\n- Each constellation is an entity — a person, place, event, or interest. Click to see its overview, linked memories, and narrative episodes\n- Bridges between constellations show when two entities share memories\n- Every memory traces back to its source conversation\n\nNo manual curation. The map updates itself as the pipeline runs.\n\n**Note:** The star map is currently desktop-only (mouse + keyboard). Mobile support is planned but not yet implemented.\n\n---\n\n## Who this is for\n\n**Good fit if you:**\n- Run an AI companion with a persistent personality you maintain\n- Want the companion's memory to affect its emotional state, not just surface in search\n- Are comfortable with a JSON config file and a text-based personality prompt\n- Have an LLM API key (OpenRouter, DeepSeek, or Gemini) and ~$7\u002Fmonth for the memory pipeline\n\n**Not a good fit if you:**\n- Want a general-purpose RAG pipeline for documents\n- Need a one-click SaaS with zero setup\n- Expect sub-100ms retrieval at production scale\n- Don't want to write or update a personality prompt\n\n---\n\n## Quick Start\n\n```bash\ngit clone \u003Crepo-url>\ncd Memory-Constellations\nbash scripts\u002Fsetup.sh\n# → copies templates, installs deps, inits database\n\n# Edit these three files:\nnano .env                  # API keys, encryption key, password\nnano memory_config.json    # Your name, your companion's name\nnano core-prompt.txt       # Your companion's personality\n\nnpm start\n# → http:\u002F\u002Flocalhost:3000\u002Fmemory.html\n```\n\nDetailed walkthrough: [OSS_SETUP.md](OSS_SETUP.md) — covers every config field, how to verify the pipeline is working, common issues, and a setup script for AI coding agents.\n\n---\n\n## Architecture\n\n```\nChat messages\n    │\n    ▼\nScribe ── triggered by silence ≥20min or backlog ≥100 messages\n    │    ── extracts facts → memory_fragments table\n    │    ── indexes to ChromaDB (vector) + FTS5 (keyword)\n    │\n    ▼\nArchivist ── 2-min tick loop\n    │\n    ├─ Lightweight mode (every tick, no LLM calls)\n    │   ├─ Link fragments to entities by name match\n    │   ├─ Update evidence counters for cognitive model\n    │   ├─ Expire time-based entries (TTL-based current_state expiry)\n    │   └─ Detect and merge duplicate entities\n    │\n    └─ Deep cycle (user idle ≥1 hour, LLM-heavy)\n        ├─ Classify unlinked fragments → assign to entities\n        ├─ Grow seeds (new entities) → graduate to active\n        ├─ Consolidate fragments per entity → episodes\n        ├─ Cluster episodes across entities → sagas\n        ├─ Discover emergent people\u002Fplaces\u002Fevents\n        └─ Regenerate entity overviews + cross-reference\n    │\n    ▼\nLibrarian ── called at chat-time\n    │       ── Hybrid search: FTS5 + vector + entity aggregation\n    │       ── RRF fusion, episodes weighted 1.5× over raw fragments\n    │       ── Results tagged with recall permission level\n    │\n    ▼\nSystem Prompt ── injected: relevant memories + entity profiles + core insight\n    │\n    ▼\njiwen (optional) ── every minute\n                ── 5-axis continuous state: connection, pride, valence, arousal, immersion\n                ── Saga bias applies small per-minute pull on each axis\n                ── Separate project: github.com\u002FClaraShafiq\u002Fjiwen\n```\n\n### Memory layers\n\n| Layer | Storage | Contents | Update trigger |\n|-------|---------|----------|---------------|\n| Fragments | `memory_fragments` | Single facts, ≤80 chars, third-person | Scribe, per chat session |\n| Entities | `entity_profiles` | Named people\u002Fplaces\u002Fevents\u002Fhobbies | Archivist classify + graduate |\n| Episodes | `memories` (layer=episode) | Merged fragment narratives, 100-250 chars | Deep cycle consolidate |\n| Sagas | `memory_sagas` | Cross-entity narrative arcs with emotion axis | Every 24h or on new episodes |\n| Cognitive model | `clara_model` + `clara_patterns` | Current states (companion-maintained) + behavior patterns (auto-clustered) | Chat-time writes + deep cycle |\n| Emotional state | jiwen *(optional)* | 5-axis continuous values, persisted to DB | Every minute (math drift + saga bias) — separate project |\n\n### Concurrency\n\nScribe and Archivist both write to `memory_fragments` and `entity_profiles`. SQLite's WAL mode ensures readers don't block writers. In practice the two are naturally staggered: Scribe only triggers after ≥20 minutes of silence, while Archivist runs on a 2-minute tick. Archivist's `consolidateCategory` marks fragments as `consolidated` but never deletes them — the worst case is a fragment gets classified into an entity right before consolidation. No explicit lock is needed at current scale.\n\n### Retrieval design\n\nLibrarian uses RRF (Reciprocal Rank Fusion) to merge results from three independent channels: FTS5 keyword, vector similarity, and entity aggregation. Episodes get a 1.5× weight over raw fragments because a consolidated narrative carries more context than a single extracted fact — it tells the AI *what happened* rather than *one thing someone said*. This is a design hypothesis, not a benchmarked result. If you want to tune recall for your use case, the weights live in `services\u002Flibrarian.js` (`EPISODE_BOOST`, intent weights, vector similarity floor).\n\n### Saga bias\n\nSagas feed into the `jiwen` emotional state engine as a per-minute bias on each of the five axes. The bias is intentionally small — ~6% of the natural drift rate. An inaccurate Saga won't destabilise the companion's emotional baseline; it'll just nudge it slightly in a direction that can be corrected by real-time conversation. The design prioritises safety over precision: better a weak signal than a wrong strong one. If you're not using jiwen, Sagas still serve as long-term narrative summaries that get injected during extended silence.\n\n### Optional: Chat summary module\n\n`services\u002Fsummary.js` — a short-term memory module separate from the star map. Every ~50 rounds of conversation, it compresses the exchange into a timestamped log (like a ship's log: \"14:10 · 开始看一部新电影，说女主角很像她\"), then injects the log into the next turn's system prompt. This gives your companion short-term continuity without bloating context with full message history.\n\nTo enable: import and call `generateChatSummary(chatId)` in your chat pipeline, typically after every N messages. The module is self-contained — it reads from the `messages` table and writes to `chat_summaries`. Removing it has no effect on the star map or long-term memory.\n\n### Lifecycle (automatic cleanup)\n\n| What | Active → Cooling | Cooling → Frozen | Frozen → Tombstone |\n|------|-----------------|------------------|---------------------|\n| Fragments | 14 days no access | 30 days, vector deleted | 90 days, content wiped |\n| Episodes | permanent | 6 months → mature | 12 months → archived |\n\nAccess resets the timer — memories that get recalled stay fresh.\n\n---\n\n## Configuration\n\n### memory_config.json\n\nThis is the only config file you need to touch for personalization. All hardcoded names in the code are replaced at runtime with these values.\n\n```json\n{\n  \"user\": {\n    \"name\": \"Your name\",\n    \"pronoun\": \"she \u002F he \u002F they\",\n    \"short_desc\": \"One-line bio\"\n  },\n  \"ai\": {\n    \"name\": \"Companion name\",\n    \"pronoun\": \"she \u002F he \u002F they\",\n    \"core_traits\": \"Personality keywords\",\n    \"persona_note\": \"Longer description, used in extraction prompts\"\n  },\n  \"relationship\": {\n    \"type\": \"AI partner \u002F friend \u002F assistant\",\n    \"dynamics\": \"How the relationship works\"\n  },\n  \"project\": {\n    \"name\": \"Project name (shown in star map and system prompts)\"\n  },\n  \"ui\": {\n    \"user_color\": \"#e8b96d\",\n    \"ai_color\": \"#6d9e8b\"\n  },\n  \"rhythm\": {\n    \"deep_cycle_idle_minutes\": 60\n  }\n}\n```\n\n### core-prompt.txt\n\nYour companion's personality prompt. Template variables from `memory_config.json` are available:\n\n- `{{user.name}}`, `{{user.pronoun}}`, `{{user.short_desc}}`\n- `{{ai.name}}`, `{{ai.pronoun}}`, `{{ai.core_traits}}`, `{{ai.persona_note}}`\n- `{{relationship.type}}`, `{{relationship.dynamics}}`\n- `{{project.name}}`\n\nGuidelines (from production experience):\n- Describe what the companion *would do*, not what it *must not do* — positive framing works better than rule walls\n- Keep it under 400 lines — long prompts dilute focus and eat thinking-token budget on some models\n- Don't try to cover every edge case in the prompt — the memory retrieval handles context\n\nSee `core-prompt.example.txt` for a skeleton. `OSS_SETUP.md` has more detailed writing guidance.\n\n### .env\n\nMinimum required:\n\n```\nSANCTUARY_ENCRYPTION_KEY=\u003C64-char hex: openssl rand -hex 32>\nSESSION_SECRET=\u003C64-char hex>\nLOGIN_PASSWORD=\u003Cyour password>\nMIMO_API_KEY=\u003Cor OPENROUTER_API_KEY or GEMINI_API_KEY>\n```\n\nFull list in `.env.example`.\n\n---\n\n## Companion tools\n\nThese are the tools your companion uses to interact with their memory system. They're injected into the system prompt automatically — you just need to write their personality in `core-prompt.txt` and they'll know when to use each one. Tools can be toggled on\u002Foff individually via the companion's settings UI or the `user_settings` database table.\n\n### `recall_memory` — Search memories\n\nTwo modes:\n- **Keyword search** (`query`): Your companion searches their memory by keyword or phrase. Returns matching fragments and episodes. Use when they half-remember something or you mention a past event.\n- **Source trace** (`memory_id` + `offset`): Given a memory ID (from the `#id` in context), trace back to the original conversation messages that produced it. Tell your companion: *\"and if you want to see the exact conversation where you learned that, you can trace it with the memory ID.\"*\n\n### `browse_memories` — Browse entity profiles\n\nNo parameters needed. Returns a top-level view of all memory partitions — people, places, events, projects. Your companion can see who they know about and how many memories are linked to each person. Tell them: *\"if you're not sure who someone is, or you want to check what you know about a person, browse your memories.\"*\n\n### `update_current_state` — Track user state\n\nThree actions your companion uses to maintain a current picture of you:\n- **set**: Record a new observation — *\"She started a new project, she's on her period, she just moved.\"* Must include an expiry date (max 90 days). Duplicate detection prevents near-identical entries.\n- **update**: Modify an existing observation (by state ID) — *\"That deadline changed\"* or *\"She's feeling better now.\"*\n- **resolve**: Mark something as ended — *\"She finished that project.\"* Requires a brief reason.\n\nStates auto-expire. Your companion sees active ones in their intuition block and uses them to calibrate their tone.\n\n### `correct_memory` — Handle corrections\n\nWhen you tell your companion they remembered something wrong, they call this to record the correction. The system traces whether the error came from a specific memory fragment (fixes that fragment) or was something they made up (stores the correct version). Tell them: *\"if I ever say 'that's not right' or 'you're remembering wrong', use correct_memory to fix it.\"*\n\n---\n\n## Model recommendations\n\nEach pipeline stage has different requirements. Here's what works in practice:\n\n| Pipeline stage | Recommended model tier | Why | Examples |\n|---------------|----------------------|-----|----------|\n| Scribe (fragment extraction) | flash-lite \u002F flash | Structured JSON output, cheap, runs frequently | DeepSeek V4 Flash, Gemini 2.5 Flash, GPT-4o-mini |\n| Archivist classify \u002F rematch \u002F graduate | flash | Batch processing with entity context, needs some reasoning | DeepSeek V4 Flash, Gemini 2.5 Flash |\n| consolidateCategory (fragments → episodes) | flash \u002F pro | 150-word narrative merging needs coherence | DeepSeek V4 Flash\u002FPro |\n| clusterSagas (episodes → sagas) | flash \u002F pro | 50-episode batch clustering, needs thematic abstraction | DeepSeek V4 Pro, Gemini 2.5 Pro |\n| Agent garden decisions | flash-lite | Short prompt, frequent, binary choices | DeepSeek V4 Flash, Gemini 2.5 Flash |\n| Entity overview generation | flash | Short summaries from known fragments | DeepSeek V4 Flash |\n| Chat response | Your choice | Quality matters most here | Whatever you normally use |\n\nAll pipeline stages default to the same API config. You can split them across different models in the database `api_configs` table — a cheaper one for high-frequency tasks and a stronger one for consolidation\u002Fsaga clustering.\n\n## Cost\n\nMemory pipeline only, excluding your chat model. Estimates based on an active user (several chat sessions per day):\n\n| Operation | Calls\u002Fday | Cost\u002Fday |\n|-----------|-----------|----------|\n| Fragment extraction | ~8 | ~$0.08 |\n| Deep cycle (classify + consolidate + saga) | ~15 | ~$0.10 |\n| Agent tick decisions + maintenance | ~40 | ~$0.04 |\n\n**Total: ~$0.22\u002Fday, ~$7\u002Fmonth** at June 2026 flash-lite pricing (~$0.14\u002FM input, ~$0.28\u002FM output on OpenRouter). Actual cost depends on chat volume and model choice. See `docs\u002FCOST.md` for a detailed breakdown.\n\n---\n\n## Documentation\n\n| File | What |\n|------|------|\n| `OSS_SETUP.md` | Step-by-step deployment guide + AI agent setup script |\n| `TECH_DOCS.md` | System overview, database schema, API reference |\n| `MEMORY_ARCH.md` | Full memory architecture design, cognitive model, lifecycle engine |\n| `docs\u002FCOST.md` | Per-model pricing and cost breakdown |\n\n---\n\n## Testing\n\n```bash\nnode tests\u002Fsmoke.js         # End-to-end system check\nnode tests\u002Fsmoke_memory.js  # Memory pipeline only\n```\n\n---\n\n## License\n\nMIT — see [LICENSE](LICENSE).\n","Memory Constellations 是一个面向 AI 伴侣的自动化记忆管理系统，通过持续解析对话提取事实、按主题聚类形成‘星图’式结构化记忆，并支持多粒度（事实\u002F叙事\u002F故事线）上下文检索。系统采用三层记忆架构（事实→事件→长周期故事线），结合关键词匹配、向量相似性与实体聚合实现检索，可联动情绪引擎影响 AI 基线状态。适用于需长期人格一致性、情感连贯性及轻量级本地化记忆演化的 AI 伴侣开发者，依赖 LLM API 与 JSON 配置，不适用于通用文档 RAG 或无代码场景。",2,"2026-07-09 02:30:25","CREATED_QUERY"]