Initial commit: RA-H Open Source Edition

Local-first knowledge management system with BYO API keys.

Features:
- 3-panel UI (Nodes | Focus | Helpers)
- SQLite + sqlite-vec for vector search
- Agent system (Easy/Hard mode orchestrators)
- Content extraction (YouTube, PDF, web)
- Integrate workflow for connection discovery
- Dimension system with auto-assignment

Tech stack:
- Next.js 15 + TypeScript + Tailwind CSS
- Anthropic (Claude) + OpenAI (GPT) via Vercel AI SDK

Setup:
  npm install && npm rebuild better-sqlite3
  scripts/dev/bootstrap-local.sh
  npm run dev

MIT License
This commit is contained in:
“BeeRad”
2025-12-15 16:14:28 +11:00
commit 733d1c3407
226 changed files with 46231 additions and 0 deletions
+28
View File
@@ -0,0 +1,28 @@
# RA-H Overview
## What is RA-H?
RA-H is a flexible knowledge management system designed for researchers. It learns how you think and helps connect ideas across your knowledge base.
For more information, visit [ra-h.app](https://ra-h.app)
## Design Philosophy
**Non-prescriptive & emergent** - The system doesn't force you into folders or predefined categories. Organization emerges naturally from your actual content. The structure adapts to how you think, not the other way around.
**Everything is connected** - Every piece of knowledge can potentially connect to any other. Connections aren't just links - they carry context, explanation, and meaning.
**Local-first** - Your knowledge network belongs to you, not a platform. Your thinking, research, and connections all belong to you in a portable format you control.
## Tech Stack
- **Frontend:** Next.js 15, TypeScript, Tailwind CSS
- **Database:** SQLite + sqlite-vec (vector search)
- **AI:** Anthropic Claude + OpenAI GPT via Vercel AI SDK
- **Deployment:** Currently beta web bundle, Mac app coming soon
## Current Status
- **Version:** Beta (private distribution)
- **Platform:** Web-based (Next.js server)
- **Roadmap:** Native Mac application with user data migration
+106
View File
@@ -0,0 +1,106 @@
# System Architecture
## Overview
RA-H uses a multi-agent architecture with three specialized AI agents that collaborate to manage your knowledge base. The system is built around **nodes** (knowledge items), **edges** (relationships), and **dimensions** (categories).
## Core Concepts
### Nodes
Knowledge items stored in the database (papers, ideas, people, projects, videos, tweets, etc). Each node has:
- **Title** and **content**
- **Dimensions** (multi-tag categorization)
- **Metadata** (structured JSON)
- **Embeddings** (for semantic search)
- **Links** (for external sources)
### Edges
Directed relationships between nodes. Edges capture how nodes connect ("relates to", "inspired by", etc).
### Dimensions
Multi-select categorization tags. Nodes can have multiple dimensions. Some dimensions can be marked as "priority" for focused context.
## Agent Architecture
### Orchestrator Agents (Easy/Hard Mode)
**ra-h-easy (Easy Mode - Default)**
- **Model:** GPT-5 Mini (`openai/gpt-5-mini`)
- **Purpose:** Fast, low-latency orchestration for everyday tasks
- **Caching:** OpenAI implicit caching
- **Reasoning:** `reasoning_effort: light` for speed
**ra-h (Hard Mode)**
- **Model:** Claude Sonnet 4.5 (`anthropic/claude-sonnet-4.5`)
- **Purpose:** Deep reasoning for complex tasks
- **Caching:** Anthropic explicit prompt caching
- **Reasoning:** Stronger analytical capabilities
**Tools Available:**
- `queryNodes`, `queryEdge`, `searchContentEmbeddings`
- `webSearch`, `think`
- `executeWorkflow` (delegates to wise-rah)
- `createNode`, `updateNode`, `createEdge`, `updateEdge`
- `youtubeExtract`, `websiteExtract`, `paperExtract`
**Mode Switching:**
Users toggle via UI (⚡ Easy / 🔥 Hard). Choice persists in localStorage. **Seamless mid-conversation switching** - context maintained across mode changes.
### Wise RA-H (Workflow Executor)
**wise-rah**
- **Model:** GPT-5 (`openai/gpt-5`)
- **Purpose:** Executes predefined workflows (integrate, deep analysis)
- **Direct write access:** Calls `updateNode` directly (no delegation)
- **Context isolation:** Returns summaries only to orchestrator
**Tools Available:**
- `queryNodes`, `getNodesById`, `queryEdge`, `searchContentEmbeddings`
- `webSearch`, `think`
- `updateNode` (append-only, enforced at tool level)
**Key Workflows:**
- **Integrate:** Database-wide connection discovery (5-step: plan → ground → search → contextualize → append)
### Mini RA-H (Delegate Workers)
**mini-rah**
- **Model:** GPT-4o Mini (`openai/gpt-4o-mini`)
- **Purpose:** Spawned for write operations, extraction, batch tasks
- **Execution:** Isolated context, returns summaries only
**Tools Available:**
- All read tools + `createNode`, `updateNode`, `createEdge`, `updateEdge`
- Extraction tools (`youtubeExtract`, `websiteExtract`, `paperExtract`)
## Prompt Caching
**Anthropic (Claude):**
- Explicit cache control blocks in system prompts
- Caches tool definitions, workflows, base context
**OpenAI (GPT-5/4o):**
- Implicit caching based on prefix matching
- Optimized prompts for cache reuse
- `reasoning_effort` parameter for speed/quality tradeoff
## Context Hygiene
**Orchestrator:**
- Maintains full conversation history
- Sees pinned nodes + focused node
- Delegates isolation ensures clean context
**Workers (wise-rah/mini-rah):**
- Execute in isolated sessions
- Return structured summaries only
- Do NOT pollute orchestrator context with tool execution details
## UI Integration
Users interact with a single interface that automatically routes requests to the appropriate agent based on:
- **Mode selection** (Easy/Hard)
- **Workflow triggers** (executeWorkflow → wise-rah)
- **Delegation needs** (mini-rah spawned in background)
All agents share the same **pinned context** (up to 10 nodes) plus the **focused node** for consistent knowledge access.
+254
View File
@@ -0,0 +1,254 @@
# Database Schema
## Why SQLite?
RA-H uses **SQLite** for local-first data ownership. Your knowledge stays on your machine - no cloud dependencies. SQLite provides:
- **Zero configuration** - single file database
- **sqlite-vec extension** - fast vector similarity search
- **Full-text search (FTS5)** - Google-like text search
- **Relational integrity** - foreign keys, triggers, transactions
- **Portability** - database file migrates with Mac app
**Database Location:** `~/Library/Application Support/RA-H/db/rah.sqlite`
## Two-Layer Embedding Architecture
RA-H uses **two types of embeddings** for different search needs:
### 1. Node-Level Embeddings
- **Storage:** `nodes.embedding` column (BLOB)
- **Purpose:** Semantic search for nodes (legacy memory pipeline used this too)
- **Model:** `text-embedding-3-small` (1536 dimensions)
- **Used by:** Search/agent tools (legacy memory pipeline has been removed)
### 2. Chunk-Level Embeddings
- **Storage:** `chunks` table (text) → `vec_chunks` virtual table (embeddings)
- **Purpose:** Detailed content search within long documents
- **Model:** `text-embedding-3-small` (1536 dimensions)
- **Used by:** `searchContentEmbeddings` tool
## Core Tables
### nodes
Primary knowledge storage. Each row is a discrete knowledge item.
**Columns:**
- `id` (INTEGER PK) - Unique identifier
- `title` (TEXT) - Node title
- `content` (TEXT) - Full content
- `type` (TEXT) - Node type (memory, paper, idea, person, etc)
- `link` (TEXT) - External source URL (only for source nodes, not derived ideas)
- `description` (TEXT) - Brief summary
- `metadata` (TEXT) - JSON metadata
- `chunk` (TEXT) - Source text for chunking
- `chunk_status` (TEXT) - Chunking status (not_chunked, chunked)
- `embedding` (BLOB) - Node-level embedding vector
- `embedding_text` (TEXT) - Text that was embedded
- `embedding_updated_at` (TEXT) - Embedding timestamp
- `is_pinned` (INTEGER) - Legacy pin flag (kept for migration; not surfaced in UI)
- `created_at`, `updated_at` (TEXT) - Timestamps
**Indexes:**
- `idx_nodes_type` - Fast type filtering
- `idx_nodes_pinned` - Legacy partial index (no longer recreated, safe to drop later)
**FTS:**
- `nodes_fts` - Full-text search on title + content
### edges
Directed relationships between nodes (knowledge graph).
**Columns:**
- `id` (INTEGER PK)
- `from_node_id` (INTEGER FK → nodes.id)
- `to_node_id` (INTEGER FK → nodes.id)
- `source` (TEXT) - How edge was created (e.g., "user", "agent")
- `context` (TEXT) - Relationship context/description
- `user_feedback` (INTEGER) - User rating
- `created_at` (TEXT)
**Indexes:**
- `idx_edges_from` - Fast "outgoing edges" queries
- `idx_edges_to` - Fast "incoming edges" queries
### chunks
Long-form content split into searchable pieces.
**Columns:**
- `id` (INTEGER PK)
- `node_id` (INTEGER FK → nodes.id)
- `chunk_idx` (INTEGER) - Sequence number
- `text` (TEXT) - Chunk content
- `embedding_type` (TEXT) - Model used
- `metadata` (TEXT) - JSON metadata
- `created_at` (TEXT)
**Indexes:**
- `idx_chunks_by_node` - Fast node→chunks lookup
- `idx_chunks_by_node_idx` - Ordered retrieval
**FTS:**
- `chunks_fts` - Full-text search within chunks
### dimensions
Master list of categorization tags.
**Columns:**
- `name` (TEXT PK) - Dimension name
- `is_priority` (INTEGER) - Priority dimension flag
- `updated_at` (TEXT)
### node_dimensions
Many-to-many junction table (nodes ↔ dimensions).
**Columns:**
- `node_id` (INTEGER FK → nodes.id)
- `dimension` (TEXT FK → dimensions.name)
- Primary key: `(node_id, dimension)`
**Indexes:**
- `idx_dim_by_dimension` - Fast "all nodes in dimension X"
- `idx_dim_by_node` - Fast "all dimensions for node X"
### chats
Conversation history with token/cost tracking.
**Columns:**
- `id` (INTEGER PK)
- `chat_type` (TEXT) - Conversation type
- `helper_name` (TEXT) - Agent key (ra-h, ra-h-easy, mini-rah, wise-rah)
- `agent_type` (TEXT) - Role category (orchestrator, executor, planner)
- `delegation_id` (INTEGER FK)
- `user_message` (TEXT)
- `assistant_message` (TEXT)
- `thread_id` (TEXT) - Conversation thread
- `focused_node_id` (INTEGER FK → nodes.id)
- `metadata` (TEXT) - JSON with token counts, costs, traces
- `created_at` (TEXT)
**Indexes:**
- `idx_chats_thread` - Fast thread retrieval
### agent_delegations
Task queue for mini-rah workers.
**Columns:**
- `id` (INTEGER PK)
- `session_id` (TEXT UNIQUE) - Delegation identifier
- `agent_type` (TEXT) - Delegate type (default: 'mini')
- `task` (TEXT) - Task description
- `context` (TEXT) - Execution context
- `expected_outcome` (TEXT)
- `status` (TEXT) - queued, in_progress, completed, failed
- `summary` (TEXT) - Result summary
- `created_at`, `updated_at` (TEXT)
### chat_memory_state
Checkpoint tracker for memory pipeline.
**Columns:**
- `thread_id` (TEXT PK)
- `helper_name` (TEXT) - Agent that owns the thread
- `last_processed_chat_id` (INTEGER) - Last chat processed
- `last_processed_at` (TEXT)
**Indexes:**
- `idx_chat_memory_thread` - Fast state lookup
### logs
Activity audit trail (auto-pruned to last 10k).
**Columns:**
- `id` (INTEGER PK)
- `ts` (TEXT) - Timestamp
- `table_name` (TEXT) - Affected table
- `action` (TEXT) - INSERT, UPDATE, DELETE
- `row_id` (INTEGER) - Affected row
- `summary` (TEXT) - Human-readable summary
- `snapshot_json` (TEXT) - Row snapshot
- `enriched_summary` (TEXT) - Enriched log entry
**Indexes:**
- `idx_logs_ts` - Chronological queries
- `idx_logs_table_ts` - Per-table chronological
- `idx_logs_table_row` - Per-row history
- `idx_logs_enriched` - Enriched-only filtering
## Vector Tables (Auto-Created)
### vec_nodes
Virtual table for node-level vector search (sqlite-vec).
```sql
VIRTUAL TABLE USING vec0(
node_id INTEGER PRIMARY KEY,
embedding FLOAT[1536]
)
```
**Supporting tables (auto-generated):**
- `vec_nodes_info`, `vec_nodes_chunks`, `vec_nodes_rowids`, `vec_nodes_vector_chunks00`
### vec_chunks
Virtual table for chunk-level vector search.
```sql
VIRTUAL TABLE USING vec0(
chunk_id INTEGER PRIMARY KEY,
embedding FLOAT[1536]
)
```
**Supporting tables (auto-generated):**
- `vec_chunks_info`, `vec_chunks_chunks`, `vec_chunks_rowids`, `vec_chunks_vector_chunks00`
**Note:** Vec tables are NOT pre-seeded in distribution. They auto-create on first app startup via `ensureVectorTables()` in `sqlite-client.ts:45`.
## Views
### nodes_v
Nodes with dimensions aggregated as JSON array.
```sql
SELECT
n.id, n.title, n.content, n.link, n.metadata, n.chunk,
n.created_at, n.updated_at,
COALESCE(JSON_GROUP_ARRAY(d.dimension), '[]') AS dimensions_json
FROM nodes n
LEFT JOIN node_dimensions d ON d.node_id = n.id
```
### logs_v
Enriched logs with related data (node titles, edge titles, chat previews).
## Triggers
**Logging triggers:**
- `trg_nodes_ai` / `trg_nodes_au` - Log node inserts/updates
- `trg_edges_ai` / `trg_edges_au` - Log edge inserts/updates
- `trg_chats_ai` - Log chat inserts (with token/cost/trace metadata)
**Maintenance triggers:**
- `trg_edges_update_nodes_on_insert` - Touch node timestamps on edge creation
- `trg_logs_prune` - Keep last 10,000 log rows
## Schema Version
**schema_version table:**
- Tracks database migrations
- Current: v1.0 (frozen for Mac app release)
```sql
CREATE TABLE schema_version (
version INTEGER PRIMARY KEY,
applied_at TEXT DEFAULT CURRENT_TIMESTAMP,
description TEXT
);
```
## Seed Database
**Location:** `/dist/resources/rah_seed.sqlite`
**Purpose:** Ships with Mac app for new users
**Contents:** Clean schema, no data, no vec tables (auto-created on first run)
**Size:** ~128KB
+148
View File
@@ -0,0 +1,148 @@
# Context & Memory
## Context Builder
The context builder assembles the information each agent sees during conversations. It creates **cacheable blocks** (for Anthropic) and structured context for all agents.
### Context Structure
Every agent receives:
**1. Base Context**
- How nodes, edges, and dimensions work
- Node reference format: `[NODE:id:"title"]`
- If auto-context is enabled, BACKGROUND CONTEXT explains that the 10 most-connected nodes will be listed later
- Pronouns like "this conversation/paper/video" refer to focused node
**2. Agent Instructions**
- Agent-specific system prompt (ra-h, ra-h-easy, wise-rah, mini-rah)
- Role-specific behavior guidelines
- Execution approach and response style
**3. Tool Definitions**
- Role-specific tools (orchestrator/executor/planner)
- Each tool's description and parameters
- Usage guidelines
**4. Workflow Definitions** (orchestrators only)
- Available workflows (integrate, etc.)
- Workflow descriptions and triggers
- Only shown to ra-h and ra-h-easy
**5. Background Context (auto-context hubs)** (orchestrators only)
- Optional block controlled by `~/Library/Application Support/RA-H/config/settings.json`
- Lists the 10 nodes with the highest edge counts (ID + title + edge count)
- Reminds agents to call `queryNodes`/`getNodesById` for full content
- Ordered by edge count, then most recently updated to break ties
**6. Focused Nodes**
- Primary focused node (active tab)
- Additional focused nodes (other open tabs)
- 25-word content previews
- Chunk status and embedding availability
- Link information
### Context Caching
**Anthropic (Claude):**
- Explicit cache control blocks (`cache_control: {type: 'ephemeral'}`)
- Caches base context, instructions, tools, workflows, background context
- Focused nodes NOT cached (changes frequently)
**OpenAI (GPT):**
- Implicit caching based on prefix matching
- Same block structure for consistency
- No explicit cache control markers needed
### Truncation Strategy
- **Background context:** IDs + titles only to keep the block lightweight
- **Focused nodes:** 25-word previews
- **Full content access:** Agents use `queryNodes`, `getNodesById`, `searchContentEmbeddings` for complete content
- **Chunk status indicator:** Shows if embeddings are available (avoid re-extraction)
## Memory System (Legacy)
The automatic memory pipeline has been removed. Existing memory nodes remain in the database for archival purposes, but no new ones are created and they are excluded from auto-context. The old files (`src/services/memory/**`) have been deleted along with the `ENABLE_CHAT_MEMORY_PIPELINE` toggle. Future improvements should store long-term knowledge as normal nodes with explicit dimensions rather than a background pipeline.
6. Update checkpoint in `chat_memory_state`
**Location:**
- Pipeline: `/src/services/memory/synthesis/chatMemoryPipeline.ts`
- Trigger: `/src/services/chat/middleware.ts:168-178`
- Extraction: `/src/services/memory/synthesis/llmSynthesis.ts`
### Memory Node Structure
```typescript
{
type: 'memory',
title: 'Insight on [subject]',
description: 'Multi-line list of facts',
content: 'Second-person statements combined',
metadata: {
category: 'identity' | 'interests' | 'models' | 'preferences' | 'relationships',
subject_type: 'person' | 'project' | 'concept' | 'resource' | 'organization' | 'workflow',
source_thread: string,
source_helper: string,
importance: 'low' | 'medium' | 'high',
focused_node_titles: string[],
canonical_key: string | null,
subject: string
}
}
```
### Memory Categories
- **identity** - Who you are, your roles, background
- **interests** - What you're curious about, learning, exploring
- **models** - How you think, mental frameworks, approaches
- **preferences** - What you like/dislike, priorities, values
- **relationships** - Connections to people, projects, concepts
### Subject Types
Memory extraction classifies subjects into these types:
- **person** - Individual people (yourself or collaborators)
- **project** - Projects, products, or initiatives
- **concept** - Ideas, theories, mental models, beliefs
- **resource** - Tools, articles, books, references
- **organization** - Companies, institutions, communities
- **workflow** - Processes, systems, methodologies
### Importance Levels
Each memory fact is classified by importance:
- **high** - Explicitly marked as priority, main project, strong belief ("is crucial", "must")
- **medium** - Normal statements and observations (default)
- **low** - Tentative, uncertain, or exploratory statements
## Auto-Context Toggle
Auto-context replaces manual pinning. When enabled, BACKGROUND CONTEXT includes the 10 nodes with the highest edge counts.
**How it works:**
1. Settings UI exposes a toggle inside the Context tab.
2. The toggle writes to `~/Library/Application Support/RA-H/config/settings.json`.
3. Context builder and workflows read that file on each request (missing file defaults to `false`).
4. When enabled, the following query runs once per request:
```sql
SELECT n.id,
n.title,
COUNT(DISTINCT e.id) AS edge_count,
n.updated_at
FROM nodes n
LEFT JOIN edges e ON (e.from_node_id = n.id OR e.to_node_id = n.id)
WHERE n.type IS NULL OR n.type != 'memory'
GROUP BY n.id
ORDER BY edge_count DESC, n.updated_at DESC
LIMIT 10;
```
**Notes:**
- Only orchestrators (ra-h / ra-h-easy) see the block.
- Titles + edge counts are shown; agents must call `queryNodes`/`getNodesById` for content.
- Users who previously pinned nodes are auto-migrated to `autoContextEnabled: true` the first time the toggle helper runs and sees legacy pins.
+174
View File
@@ -0,0 +1,174 @@
# Tools & Workflows
## Tool Architecture
Tools are organized into three categories with role-based access control.
### Core Tools (All Agents)
Read-only graph operations available to orchestrators, executors, and planners:
- **queryNodes** - Search nodes by title/content/dimensions
- **getNodesById** - Retrieve full node data by ID array
- **queryEdge** - Inspect existing edges between nodes
- **searchContentEmbeddings** - Semantic search across chunk embeddings
### Orchestration Tools (Orchestrators Only)
Workflow and delegation tools for ra-h and ra-h-easy:
- **webSearch** - External web search via Tavily
- **think** - Internal reasoning/planning (logged to metadata)
- **executeWorkflow** - Delegate to wise-rah for predefined workflows
- **delegateToMiniRAH** - Spawn mini-rah worker for tasks (deprecated in favor of direct execution)
- **delegateToWiseRAH** - Delegate to wise-rah (now replaced by executeWorkflow)
### Execution Tools (Workers + Orchestrators)
Write operations and extraction - available to mini-rah, wise-rah, and orchestrators:
- **createNode** - Create new knowledge nodes
- **updateNode** - Append content to existing nodes (append-only enforced at tool level)
- **createEdge** - Create relationships between nodes
- **updateEdge** - Modify edge metadata
- **youtubeExtract** - Extract transcripts from YouTube videos
- **websiteExtract** - Extract content from web pages
- **paperExtract** - Extract text from PDF papers
## Tool Access by Agent
### ra-h / ra-h-easy (Orchestrators)
**Tools:** Core + Orchestration + Execution (minus delegation helpers)
- Direct write access (createNode, updateNode, createEdge, updateEdge)
- Extraction tools (youtube, website, paper)
- Workflow execution (executeWorkflow)
- External search (webSearch)
### wise-rah (Planner)
**Tools:** Core + webSearch + think + updateNode
- **Direct write access** via updateNode (append-only)
- **NO delegation** - executes workflows autonomously
- Database-wide search capabilities
- Minimal tool set for focused workflow execution
### mini-rah (Executor)
**Tools:** Core + Execution + webSearch + think
- All read tools
- All write tools (createNode, updateNode, createEdge, updateEdge)
- All extraction tools
- **NO delegation** - leaf workers only
## Tool Registry
**Location:** `/src/tools/infrastructure/registry.ts`
**Structure:**
```typescript
TOOL_SETS = {
core: { queryNodes, getNodesById, queryEdge, searchContentEmbeddings },
orchestration: { webSearch, think, delegateToMiniRAH, executeWorkflow, ... },
execution: { createNode, updateNode, createEdge, updateEdge, youtubeExtract, websiteExtract, paperExtract }
}
```
**Role mappings:**
- `ORCHESTRATOR_TOOL_NAMES` - Core + webSearch + think + executeWorkflow + Execution
- `EXECUTOR_TOOL_NAMES` - Core + Execution + webSearch + think (no delegation)
- `PLANNER_TOOL_NAMES` - Core + webSearch + think + updateNode
## Workflows
**Location:** `/src/services/workflows/registry.ts`
Workflows are **code-first** - defined in registry, not database. Users cannot create custom workflows.
### Integrate Workflow
**Key:** `integrate`
**Executor:** wise-rah (planner role)
**Purpose:** Database-wide connection discovery for focused node
**Cost:** ~$0.18/execution (GPT-5, 18 tool calls max)
**Process (5 steps):**
1. **Plan** - Call `think` to outline approach
2. **Ground** - Identify node type, extract entities (names, projects, concepts), summarize core insight
3. **Search** - Database-wide search using extracted entities
- Obvious connections: queryNodes for specific names/projects/techniques
- Thematic connections: searchContentEmbeddings for shared concepts
- Finds 3-8 strong connections (not 20 weak ones)
4. **Contextualize** - Brief 1-2 sentence relevance to pinned context
5. **Append** - Call updateNode ONCE with Integration Analysis section
**Output format:**
```markdown
## Integration Analysis
[2-3 sentences: what this node is, why it matters, core insight]
**Database Connections:**
- [NODE:123:"Title"] — [why: authorship/shared concept/dependency/contradiction]
- [NODE:456:"Title"] — [why: ...]
- [continue for 3-8 connections]
**Relevance:** [1-2 sentences connecting to user's pinned context]
```
**Key features:**
- **Database-first search** - Ignores pinned context during search (step 3), uses it only for relevance explanation (step 4)
- **Entity extraction** - Grounding step identifies searchable entities before searching
- **Append-only** - updateNode enforced at tool level (cannot overwrite)
- **Single update** - Calls updateNode EXACTLY once per workflow
- **Works for any node type** - Adapts to person/project/paper/idea/video/tweet/technique
**Invocation:**
```typescript
// User: "run integrate workflow"
// Orchestrator calls: executeWorkflow({ workflow_key: 'integrate' })
// System delegates to wise-rah with workflow instructions
```
## Workflow Registry
**Definition:**
```typescript
{
id: 1,
key: 'integrate',
displayName: 'Integrate',
description: 'Deep analysis and connection-building for focused node',
instructions: INTEGRATE_WORKFLOW_INSTRUCTIONS,
enabled: true,
requiresFocusedNode: true,
primaryActor: 'oracle',
expectedOutcome: 'Focused node updated with insights; 3-5 high-value edges created'
}
```
**Adding new workflows:**
1. Create instructions file in `/src/config/workflows/[name].ts`
2. Add workflow definition to `WorkflowRegistry.WORKFLOWS`
3. Immediately available to orchestrators (no database changes needed)
## Tool Execution Flow
**Orchestrator conversation:**
1. User sends message → ra-h/ra-h-easy
2. Agent calls tools directly (createNode, queryNodes, etc.)
3. Agent synthesizes response from tool results
4. Response includes [NODE:id:"title"] references for UI rendering
**Workflow execution:**
1. User: "run integrate workflow"
2. ra-h/ra-h-easy calls `executeWorkflow({ workflow_key: 'integrate' })`
3. System spawns wise-rah session with workflow instructions
4. wise-rah executes 5-step process autonomously
5. wise-rah returns summary to orchestrator
6. Orchestrator shows summary to user
**Delegation (legacy, rarely used):**
1. Orchestrator calls `delegateToMiniRAH({ task, context, expected_outcome })`
2. System creates agent_delegations row (status: 'queued')
3. Mini-rah spawned in isolated session
4. Mini-rah executes task, returns structured summary
5. Summary shown in delegation tab (persists until manually closed)
+152
View File
@@ -0,0 +1,152 @@
# Logging & Evals
## Logging System
RA-H uses a **trigger-based logging system** that automatically captures all database activity in the `logs` table.
### What Gets Logged
**Automatically logged via triggers:**
- **Node operations** - Create, update (via `trg_nodes_ai`, `trg_nodes_au`)
- **Edge operations** - Create, update (via `trg_edges_ai`, `trg_edges_au`)
- **Chat operations** - All conversations with token/cost metadata (via `trg_chats_ai`)
**Log structure:**
```typescript
{
id: number,
ts: timestamp,
table_name: 'nodes' | 'edges' | 'chats',
action: 'INSERT' | 'UPDATE',
row_id: number,
summary: string, // Human-readable description
snapshot_json: string, // Full row data as JSON
enriched_summary: string | null // Enhanced log entry
}
```
### Chat Metadata
Every chat log includes detailed execution metadata:
```typescript
metadata: {
// Token tracking
prompt_tokens: number,
completion_tokens: number,
reasoning_tokens: number,
total_tokens: number,
// Cost tracking
cost: number, // USD cost for this chat
// Tool usage
tools_used: string[], // Array of tool names called
// Workflow tracking
is_workflow: boolean,
workflow_key?: string,
workflow_node_id?: number,
// Model parameters
reasoning_effort?: 'low' | 'medium' | 'high',
// Execution trace
trace?: {
session_id: string,
parent_session_id?: string,
execution_time_ms: number
}
}
```
### Auto-Pruning
**Trigger:** `trg_logs_prune`
**Behavior:** Keeps last 10,000 log entries
**Runs:** After every INSERT to logs table
This prevents infinite database growth while preserving recent activity history.
### Enriched Logs View
**View:** `logs_v`
**Purpose:** Joins log entries with related data for readable activity feed
**Enrichment:**
- Node logs → show node title
- Edge logs → show from/to node titles
- Chat logs → show agent name, user/assistant message previews
## Settings Panel Visibility
**Location:** Settings → Logs tab
**Features:**
- **Real-time activity feed** - Shows last 100 log entries
- **Table filtering** - Filter by nodes/edges/chats
- **Action filtering** - Filter by INSERT/UPDATE
- **Detailed view** - Click to see full snapshot_json
- **Token/cost visibility** - Chat logs show usage and costs
- **Tool usage** - See which tools were called per chat
**Query:**
```sql
SELECT * FROM logs_v
ORDER BY ts DESC
LIMIT 100
```
## Cost Tracking
**Automatic cost calculation:**
- Every chat records token counts from LLM response
- Cost computed using model-specific pricing
- Stored in `chats.metadata.cost` (USD)
- Aggregated in Settings → Analytics
**Model pricing (as of v1.0):**
- GPT-5 Mini: $0.10/1M input, $0.40/1M output
- GPT-5: $2.50/1M input, $10.00/1M output
- GPT-4o Mini: $0.15/1M input, $0.60/1M output
- Claude Sonnet 4.5: $3.00/1M input, $15.00/1M output
**Typical costs:**
- Easy mode chat: $0.01-0.03
- Hard mode chat: $0.03-0.10
- Integrate workflow: ~$0.18
- Deep analysis: ~$0.33
## Token Analytics
**Settings → Analytics panel shows:**
- Total tokens used (all time)
- Total cost (USD)
- Breakdown by agent (ra-h, ra-h-easy, mini-rah, wise-rah)
- Breakdown by conversation thread
- Average cost per chat
**Query:**
```sql
SELECT
helper_name,
COUNT(*) as chat_count,
SUM(JSON_EXTRACT(metadata, '$.total_tokens')) as total_tokens,
SUM(JSON_EXTRACT(metadata, '$.cost')) as total_cost
FROM chats
WHERE metadata IS NOT NULL
GROUP BY helper_name
```
## Evaluation (Future)
**Planned features:**
- Edge quality ratings (user feedback via `edges.user_feedback`)
- Memory node relevance scoring
- Workflow success metrics
- Connection discovery quality
**Current state:**
- Infrastructure exists (`edges.user_feedback` column)
- UI not yet implemented
- Manual evaluation via logs table queries
+169
View File
@@ -0,0 +1,169 @@
# User Interface
## 3-Panel Layout
RA-H uses a fixed 3-panel desktop layout optimized for knowledge work.
### Left Panel: Nodes
**Purpose:** Browse and manage your knowledge base
**Features:**
- **Search bar** - Cmd+K global search modal
- **Dimension filters** - Multi-select dimension tags
- **Node list** - Scrollable list of filtered nodes
- **Quick actions** - Pin/unpin, delete, open in focus
**Node display:**
- Title + description preview
- Dimension tags
- Last updated timestamp
- Pin indicator
### Middle Panel: Focus
**Purpose:** Active workspace for current node(s)
**Tabbed interface:**
- **Primary tab** - Main focused node
- **Additional tabs** - Related nodes opened from conversations
- **Tab controls** - Close, reorder, switch
**Node detail view:**
- Full title and content
- Metadata (created, updated, type, link)
- Dimension tags (editable)
- Edge list (incoming/outgoing connections)
- Quick Add bar (bottom) - Create related nodes
**Content rendering:**
- Markdown support
- `[NODE:id:"title"]` auto-links to clickable node references
- Syntax highlighting for code blocks
- YouTube embeds (if link present)
### Right Panel: Helpers
**Purpose:** AI conversation interface
**Tabbed interface:**
- **ra-h tab** - Main orchestrator conversation
- **Delegation tabs** - Background worker tasks (mini-rah)
- **Tab lifecycle** - Manual close only (persist until user closes)
**Conversation view:**
- Message history (user + assistant)
- Tool call visibility (collapsed by default)
- Token/cost tracking per message
- Node references auto-linked
**Input controls:**
- Text input with Shift+Enter for multiline
- Submit button
- Mode toggle (⚡ Easy / 🔥 Hard)
- Thread reset button
**Mode switching:**
- Easy mode: GPT-5 Mini (fast, cheap)
- Hard mode: Claude Sonnet 4.5 (deep reasoning)
- Seamless mid-conversation switching
- localStorage persists user choice
## Settings Panel
**Access:** Settings icon (top-right)
**Tabs:**
1. **General** - App info, version, data location
2. **Agents** - View agent configurations (ra-h, ra-h-easy, mini-rah, wise-rah)
3. **Workflows** - Available workflows (integrate)
4. **Logs** - Activity feed (last 100 entries)
5. **Analytics** - Token usage and cost breakdown
6. **API Keys** - Configure Anthropic/OpenAI/Tavily keys (beta ships with embedded keys)
**Logs view:**
- Table/action filtering
- Timestamp, table, action, summary
- Detailed JSON snapshot on click
- Real-time updates
**Analytics view:**
- Total tokens used
- Total cost (USD)
- Breakdown by agent
- Breakdown by thread
- Average cost per chat
## Search (Cmd+K)
**Trigger:** Cmd+K keyboard shortcut
**4-tier relevance ranking:**
1. **Exact title match** - Highest priority
2. **Title substring** - High priority
3. **FTS content match** - Medium priority
4. **Semantic embedding** - Fallback for conceptual matches
**Features:**
- Type-ahead search
- Instant results (no search button)
- Click to open node in Focus panel
- Recent searches preserved (session only)
**UI:**
- Modal overlay
- Search input
- Results list (grouped by relevance tier)
- Keyboard navigation (arrow keys, Enter to select)
## Quick Add
**Location:** Bottom of Focus panel
**Purpose:** Rapidly create nodes related to current focus
**Flow:**
1. User types title in Quick Add input
2. Presses Enter
3. System creates node via `createNode` tool
4. Auto-creates edge from focused node to new node
5. New node opens in adjacent tab
**Features:**
- Single-field input (title only)
- Inherit dimensions from focused node
- Automatic edge creation with source='quick_add'
- Real-time feedback (loading state, success confirmation)
## Node References
**Format:** `[NODE:id:"title"]`
**Rendering:**
- Clickable labels in chat messages
- Clickable labels in node content
- Hover tooltip with node preview
- Click → open node in Focus panel
**Usage:**
- Agents automatically use this format
- Middleware converts to clickable UI elements
- Enables knowledge graph navigation from conversations
## Delegation Tabs
**Purpose:** Show background worker task progress
**Lifecycle:**
- Created when mini-rah delegated
- Persist until manually closed (no auto-cleanup)
- Show task, status, summary, result
- Tool calls visible (collapsed)
**Status indicators:**
- queued - Task waiting
- in_progress - Worker executing
- completed - Success
- failed - Error with details
**Close behavior:**
- Manual close only (X button)
- DELETE request to `/api/rah/delegations/[sessionId]`
- Permanent deletion from database
+45
View File
@@ -0,0 +1,45 @@
# RA-H MCP Connector Setup
The desktop app now ships with a local Model Context Protocol (MCP) server so any MCPcompatible assistant (Claude, ChatGPT, Gemini, Codex, etc.) can read/write your RA-H graph. Everything runs on `127.0.0.1` and never leaves your Mac.
## Quick Start
1. Launch the RA-H desktop app (it boots the Next.js sidecar + MCP bridge automatically).
2. Open **Settings → External Agents** inside RA-H and copy the connector URL (example: `http://127.0.0.1:44145/mcp`).
3. In Claude, ChatGPT, or any other assistant:
- open the MCP/connectors panel,
- choose **Add connector → HTTP**,
- paste the copied URL and name it “RA-H”.
4. Talk naturally. Examples:
- “Summarize this chat and add it to RA-H under Strategy + Q1 Execution.”
- “Search RA-H for what I already wrote about Apollo launch delays.”
The assistant calls two tools behind the scenes:
| Tool | Description |
| --- | --- |
| `rah_add_node` | Adds a new entry (title/content/dimensions) to the local SQLite graph and triggers the auto-embed queue. |
| `rah_search_nodes` | Searches existing nodes (title/content/dimensions) before deciding whether to create something new. |
## Guardrails
- The MCP server only binds to `127.0.0.1` and is meant for **your** agents. Do not expose it beyond your machine.
- Anything the assistant writes is immediately persisted to `~/Library/Application Support/RA-H/db/rah.sqlite`. Review the RA-H activity panel if something looks off.
- Disable the connector by setting `RAH_ENABLE_MCP=false` before launching the app (UI toggle coming soon).
- The `/status` endpoint returns health info if you need diagnostics: `curl http://127.0.0.1:44145/status`.
### Claude Desktop (STDIO Connector)
Claudes configuration window expects STDIO-based servers. To let Claude start a connector directly, point it at:
```
node /Users/<you>/Desktop/dev/ra-h/apps/mcp-server/stdio-server.js
```
This script speaks MCP over stdin/stdout (no HTTP listener), so Claude can manage it through `claude_desktop_config.json` or the “Add MCP Server” CLI flow. Keep the main RA-H app running so the STDIO bridge can call `http://127.0.0.1:3000/api/nodes`.
## Development Notes
- Implementation lives in `apps/mcp-server/server.js` (HTTP transport + tool definitions). It proxies through the existing `/api/nodes/*` routes, so validation + auto-embed behavior stays consistent.
- The Mac sidecar (`apps/mac/scripts/sidecar-launcher.js`) bootstraps the MCP server and keeps `~/Library/Application Support/RA-H/config/mcp-status.json` updated for the Settings panel/API.
- To run the server standalone (for MCP Inspector, etc.): `node apps/mcp-server/server.js` (requires the Next.js sidecar to be running so the API endpoints respond).
+9
View File
@@ -0,0 +1,9 @@
# RA-H BYO-Key Plan (Future Work)
The production repo remains private and powers the packaged Mac app. A separate, minimal open-source project will be created later for users who want to run RA-H with their own API keys. That future repo will include:
1. Basic three-panel UI
2. Local SQLite storage
3. Simple Settings → API Keys experience (no Supabase/subscription backend)
No active work is happening in this repo toward that goal right now. Track progress in `docs/development/prd-private-repo-reset.md`.