diff --git a/README.md b/README.md index 582feb7..f3be215 100644 --- a/README.md +++ b/README.md @@ -9,13 +9,13 @@ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ``` -**TL;DR:** Clone this repository and you'll have a local SQLite database on your computer. External AI agents can read and write nodes in it. The app owns chunking and embedding from node source. +**TL;DR:** Clone this repository and you get a local SQLite knowledge graph plus a UI and standalone MCP server. External agents can read and write the graph, while the app owns chunking and embedding from node source. [](https://youtu.be/IA02YB8mInM?si=WoWpNE9QZEKEukvZ) > **Cross-platform local runtime:** macOS works out of the box. Windows and Linux are now being hardened for the core local/web app flow, but semantic/vector search still depends on either sqlite-vec for your platform or a later Qdrant setup. -**Full documentation:** [ra-h.app/docs/open-source](https://ra-h.app/docs/open-source) +**Docs start here:** [docs/README.md](./docs/README.md) --- @@ -23,10 +23,18 @@ 1. **Stores knowledge locally** — Notes, bookmarks, ideas, research in a SQLite database on your machine 2. **Provides a UI** — Browse, search, and organize your nodes at `localhost:3000` -3. **Exposes an MCP server** — Claude Code, Cursor, or any MCP client can query and add to your knowledge base +3. **Exposes an MCP server** — Claude Code and other MCP clients can query and add to your knowledge base Your data stays on your machine. Nothing is sent anywhere unless you configure an API key. +Current contract: +- no runtime `dimensions` +- optional `contexts` +- node quality comes from `title`, `description`, `source`, `metadata`, and explicit `edges` +- direct node lookup first for specific-node intent +- broader retrieval only when graph context would help +- standalone MCP writes node data, but the app owns chunking and embeddings + --- ## Requirements @@ -50,6 +58,11 @@ npm run dev Open [localhost:3000](http://localhost:3000). Done. +Full install details: +- [docs/README.md](./docs/README.md) +- [docs/8_mcp.md](./docs/8_mcp.md) +- [docs/10_full-local.md](./docs/10_full-local.md) + --- ## OpenAI API Key @@ -103,7 +116,7 @@ Restart Claude Code fully (**Cmd+Q on Mac**, not just closing the window). If you publish a newer MCP release and want clients to use it immediately, bump the pinned version here and restart the client. Do not rely on plain `npx ra-h-mcp-server` always refreshing instantly. -**Verify it worked:** Ask Claude "Do you have RA-H tools available?" — you should see tools like `createNode`, `queryNodes`, and `readSkill`. +**Verify it worked:** Ask Claude `Do you have RA-H tools available?` You should see tools like `queryNodes`, `retrieveQueryContext`, `createNode`, and `readSkill`. **For contributors** testing local changes, use the local path instead: ```json @@ -117,7 +130,7 @@ If you publish a newer MCP release and want clients to use it immediately, bump } ``` -**What happens:** Once connected, Claude should use `queryNodes` for specific existing-node lookup, `retrieveQueryContext` when broader graph context would help, and `getContext` only for orientation. It proactively captures knowledge. When a new insight, decision, person, or reference surfaces, it should propose a specific node with a strong title, description, source, and metadata. Context is optional and should only be set when the primary scope is obvious. The MCP server stores source on the node. The app later turns that source into chunks and embeddings. +**What happens:** Once connected, the agent should use `queryNodes` for specific existing-node lookup, `retrieveQueryContext` when broader graph context would help, and `getContext` only for orientation. It should search before creating, keep context optional by default, and propose durable writeback selectively instead of pestering. The MCP server stores source on the node. The app later turns that source into chunks and embeddings. Available tools: @@ -171,7 +184,7 @@ JOIN nodes n2 ON e.to_node_id = n2.id LIMIT 10; ``` -See [ra-h.app/docs/open-source](https://ra-h.app/docs/open-source) for full schema documentation. +See [docs/2_schema.md](./docs/2_schema.md) and [docs/8_mcp.md](./docs/8_mcp.md) for the current contract. --- @@ -228,6 +241,6 @@ Without sqlite-vec: ## Community - **Discord:** [discord.gg/3cpQj6Jtc9](https://discord.gg/3cpQj6Jtc9) — ask questions, share your setup, get help -- **Full docs:** [ra-h.app/docs/open-source](https://ra-h.app/docs/open-source) +- **Repo docs:** [docs/README.md](./docs/README.md) - **Issues:** [github.com/bradwmorris/ra-h_os/issues](https://github.com/bradwmorris/ra-h_os/issues) - **License:** MIT diff --git a/app/api/health/route.ts b/app/api/health/route.ts index 85e96e2..5edddd4 100644 --- a/app/api/health/route.ts +++ b/app/api/health/route.ts @@ -5,7 +5,7 @@ import { NextResponse } from 'next/server'; import { checkDatabaseHealth } from '@/services/database'; -import { hasValidOpenAiKey } from '@/services/storage/apiKeys'; +import { hasPreferredOpenAiKey } from '@/services/storage/openaiKeyServer'; export const runtime = 'nodejs'; @@ -17,7 +17,7 @@ export async function GET() { status: dbHealth.connected ? 'ok' : 'degraded', database: dbHealth.connected ? 'connected' : 'disconnected', vectorSearch: dbHealth.vectorExtension ? 'enabled' : 'disabled', - aiFeatures: hasValidOpenAiKey() ? 'enabled' : 'disabled (no API key)', + aiFeatures: hasPreferredOpenAiKey() ? 'enabled' : 'disabled (no API key)', timestamp: new Date().toISOString(), }; diff --git a/app/api/settings/openai-key/route.ts b/app/api/settings/openai-key/route.ts new file mode 100644 index 0000000..386b3a8 --- /dev/null +++ b/app/api/settings/openai-key/route.ts @@ -0,0 +1,75 @@ +import { NextRequest, NextResponse } from 'next/server'; +import { + getEnvLocalPath, + isValidOpenAiKey, + maskOpenAiKey, + readStoredOpenAiKey, + writeOpenAiKeyToEnvLocal, +} from '@/services/storage/envLocalServer'; + +export const runtime = 'nodejs'; + +function buildResponse(key: string | null) { + const configured = isValidOpenAiKey(key); + return { + configured, + maskedKey: configured ? maskOpenAiKey(key) : null, + envPath: getEnvLocalPath(), + }; +} + +export async function GET() { + try { + const storedKey = await readStoredOpenAiKey(); + return NextResponse.json(buildResponse(storedKey)); + } catch (error) { + return NextResponse.json( + { + configured: false, + error: error instanceof Error ? error.message : 'Failed to read .env.local', + }, + { status: 500 } + ); + } +} + +export async function POST(request: NextRequest) { + try { + const body = await request.json(); + const key = typeof body?.key === 'string' ? body.key.trim() : ''; + + if (!isValidOpenAiKey(key)) { + return NextResponse.json( + { error: 'Invalid OpenAI API key format.' }, + { status: 400 } + ); + } + + await writeOpenAiKeyToEnvLocal(key); + process.env.OPENAI_API_KEY = key; + + return NextResponse.json(buildResponse(key)); + } catch (error) { + return NextResponse.json( + { + error: error instanceof Error ? error.message : 'Failed to save OpenAI API key', + }, + { status: 500 } + ); + } +} + +export async function DELETE() { + try { + await writeOpenAiKeyToEnvLocal(null); + delete process.env.OPENAI_API_KEY; + return NextResponse.json(buildResponse(null)); + } catch (error) { + return NextResponse.json( + { + error: error instanceof Error ? error.message : 'Failed to remove OpenAI API key', + }, + { status: 500 } + ); + } +} diff --git a/apps/mcp-server-standalone/README.md b/apps/mcp-server-standalone/README.md index f563599..325dc02 100644 --- a/apps/mcp-server-standalone/README.md +++ b/apps/mcp-server-standalone/README.md @@ -1,6 +1,6 @@ # RA-H MCP Server -Connect Claude Code and Claude Desktop to your RA-H knowledge base. Direct SQLite access to an existing RA-H database. +Connect Claude Code and Claude Desktop to your RA-H knowledge base. This package talks directly to an existing RA-H SQLite database. ## Install @@ -10,6 +10,11 @@ npx --yes ra-h-mcp-server@2.1.2 Run RA-H once first so the database exists, then use the MCP server from any client. +Important contract: +- pinned package version recommended +- standalone MCP reads and writes node data directly +- standalone MCP does not own chunking, embeddings, or live schema migration on an existing DB + ## Configure Claude Code / Claude Desktop Add to your Claude config (`~/.claude.json` or Claude Desktop settings): @@ -25,68 +30,63 @@ Add to your Claude config (`~/.claude.json` or Claude Desktop settings): } ``` -Restart Claude. Done. +Restart Claude fully. Done. If you publish a newer MCP release and need this client to pick it up immediately, bump the pinned version here and restart Claude. Do not assume plain `npx ra-h-mcp-server` always refreshes instantly. ## Requirements -- Node.js 18+ -- An existing RA-H database at `~/Library/Application Support/RA-H/db/rah.sqlite` -- Run the RA-H app at least once before using the standalone MCP server +- Node.js 18-22 LTS recommended +- an existing RA-H database at `~/Library/Application Support/RA-H/db/rah.sqlite` +- run the RA-H app at least once before using the standalone MCP server ## Environment Variables | Variable | Default | Description | |----------|---------|-------------| -| `RAH_DB_PATH` | ~/Library/Application Support/RA-H/db/rah.sqlite | Database path | +| `RAH_DB_PATH` | `~/Library/Application Support/RA-H/db/rah.sqlite` | Database path | -## What to Expect +## What To Expect -Once connected, Claude will: -- **Use `queryNodes` for explicit node lookup** when the user is trying to find a specific existing thing -- **Use `retrieveQueryContext` when graph context is helpful** for a broader task, question, or request -- **Use `getContext` only for orientation** when high-level graph state would actually help -- **Treat context as optional by default** — normal node creation and updates should omit context unless the user explicitly wants one; when context is intentionally provided, use `context_name` -- **Proactively capture knowledge** — when a new insight, decision, person, or reference surfaces, it proposes a specific node (title, description, optional context) so you can approve with minimal friction -- **Treat edges as proposal-first** — it should suggest likely relationships briefly, then create them only after you explicitly confirm -- **Read skills for complex tasks** — skills are editable and shared across internal + external agents -- **Search before creating** to avoid duplicates +Once connected, the agent should: +- use `queryNodes` for explicit node lookup when the user is trying to find a specific existing thing +- use `retrieveQueryContext` when graph context is helpful for a broader task, question, or request +- use `getContext` only for orientation when high-level graph state would actually help +- treat context as optional by default +- search before creating to avoid duplicates +- propose likely edges first, then create them only after explicit confirmation +- read skills for more complex tasks ## Source Processing -- The standalone MCP server stores source text on the node. -- It does **not** split source into chunks or generate embeddings itself. -- The RA-H app owns chunking and embedding when the app is running. -- If the app is closed, writes still land in `nodes.source`, and the app processes them later. +- the standalone MCP server stores source text on the node +- it does **not** split source into chunks or generate embeddings itself +- the RA-H app owns chunking and embedding when the app is running +- if the app is closed, writes still land in `nodes.source`, and the app processes them later ## Recommended Agent Memory Line If you use external agents through this MCP server, you may add one short instruction line to your agent memory file (`AGENTS.md`, `CLAUDE.md`, etc.) as optional reinforcement: ```md -Retrieve relevant context from RA-H before substantive work, and only suggest writing durable context back when it is clearly valuable and the user can confirm yes. -``` - -Keep the writeback prompt brief. A good pattern is: - -```md -Add "X" as a node? +Retrieve relevant RA-H context before substantive work, search before creating, and keep durable writeback prompts brief and confirmation-gated. ``` RA-H should still work well without this line. The MCP tools, server instructions, skills, and docs are meant to carry the core behavior on their own. +Do not create contradictory instruction files. Prefer one short reinforcement line over a pile of overlapping guidance. + ## Available Tools | Tool | Description | |------|-------------| -| `getContext` | Get graph overview — stats, contexts, recent activity | +| `getContext` | Get graph overview - stats, contexts, recent activity | | `retrieveQueryContext` | Pull relevant graph context for a broader current-turn task | | `createNode` | Create a new node | | `writeContext` | Save one confirmed durable context node after explicit user approval | | `queryNodes` | Search nodes by keyword | | `queryContexts` | List or inspect contexts | -| `getNodesById` | Load nodes by ID (includes chunk + metadata) | +| `getNodesById` | Load nodes by ID | | `updateNode` | Update an existing node | | `createEdge` | Create a confirmed connection between nodes | | `updateEdge` | Update an edge explanation after explicit confirmation | @@ -95,18 +95,14 @@ RA-H should still work well without this line. The MCP tools, server instruction | `readSkill` | Read a skill by name | | `writeSkill` | Create or update a skill | | `deleteSkill` | Delete a skill | -| `searchContentEmbeddings` | Search through source content (transcripts, books, articles) | -| `sqliteQuery` | Execute read-only SQL queries (SELECT/WITH/PRAGMA) | +| `searchContentEmbeddings` | Search through source content | +| `sqliteQuery` | Execute read-only SQL queries (`SELECT` / `WITH` / `PRAGMA`) | + +Verification tip: +- after config changes, fully restart the client and confirm you can see tools like `queryNodes`, `retrieveQueryContext`, and `createNode` ## Node Metadata Contract -## Context Rule - -- Creating a node never requires context. -- Normal node lookup and update flows should omit context unless the user explicitly asks for it. -- If context is intentionally provided, prefer `context_name`. -- Numeric `context_id` is treated as an internal implementation detail rather than a normal agent-facing field. - When `createNode` or `updateNode` includes metadata, prefer the canonical shape: ```json @@ -120,39 +116,45 @@ When `createNode` or `updateNode` includes metadata, prefer the canonical shape: ``` Rules: - - `source_metadata` is for small factual source-specific fields only - metadata updates merge with the existing object; they do not replace the full blob - use `captured_by = "human"` for direct user creation and user-requested agent capture - reserve `captured_by = "agent"` for autonomous/background creation only +## Context Rule + +- creating a node never requires context +- normal node lookup and update flows should omit context unless the user explicitly asks for it +- if context is intentionally provided, prefer `context_name` +- numeric `context_id` is treated as an internal implementation detail rather than a normal agent-facing field + ## Writeback Rule -- Do not ask to save every moderately useful point from the conversation. -- Only suggest a save when the context is unusually durable and valuable. -- Keep the ask terse and concrete, for example: `Add "X" as a node?` -- Never call `writeContext` unless the user has explicitly said yes. +- do not ask to save every moderately useful point from the conversation +- only suggest a save when the context is unusually durable and valuable +- keep the ask terse and concrete, for example: `Add "X" as a node?` +- never call `writeContext` unless the user has explicitly said yes ## Edge Rule -- External agents should propose likely edge candidates first. -- `createEdge` is the execution tool after explicit user confirmation. -- Agent-driven edge creation should always include a clear explanation sentence. +- external agents should propose likely edge candidates first +- `createEdge` is the execution tool after explicit user confirmation +- agent-driven edge creation should always include a clear explanation sentence ## Skills -Skills are detailed instruction sets that teach agents how to work with your knowledge base. The default seeded skills are editable and shared by internal + external agents. +Skills are editable and shared across internal and external agents. Skills are stored at `~/Library/Application Support/RA-H/skills/` and shared with the main app. ## What's NOT Included This is a lightweight CRUD server. Advanced features are handled by the main app: - -- Embedding generation +- embedding generation - AI-powered edge inference -- Content extraction (URL, YouTube, PDF) -- Real-time SSE events +- content extraction (URL, YouTube, PDF) +- real-time SSE events +- automatic chunking or embedding while the app is closed ## Testing diff --git a/docs/0_overview.md b/docs/0_overview.md index 5382c79..0e8a6a3 100644 --- a/docs/0_overview.md +++ b/docs/0_overview.md @@ -1,8 +1,8 @@ -# RA-OS Overview +# RA-H OS Overview ## What is RA-OS? -RA-OS is a minimal knowledge graph UI with MCP server integration. It provides a local-first knowledge management system designed to be extended by external AI agents via the Model Context Protocol. +RA-H OS is the open-source local graph surface of RA-H. It gives you the graph, UI, and MCP path without the private Mac-app-only packaging and subscription surfaces. **Open Source:** [github.com/bradwmorris/ra-h_os](https://github.com/bradwmorris/ra-h_os) @@ -10,9 +10,9 @@ RA-OS is a minimal knowledge graph UI with MCP server integration. It provides a **Local-first** — Your knowledge network belongs to you. Everything runs locally in a SQLite database you control. -**Agent-agnostic** — No built-in AI chat. Instead, RA-OS exposes an MCP server that any AI agent (Claude Code, custom agents) can connect to. +**External-agent friendly** — The open-source path is designed to work well with external MCP clients. The graph contract should not depend on prompt hacks or old taxonomy assumptions. -**Simple & focused** — A compact multi-pane UI for browsing and editing your knowledge graph. No bloat. +**Simple & focused** — The open-source surface keeps the graph, UI, and MCP contract. It does not try to mirror every private-app surface. ## Tech Stack @@ -23,7 +23,7 @@ RA-OS is a minimal knowledge graph UI with MCP server integration. It provides a ## What's Included -- Multi-pane UI for nodes, contexts, map, table, and focus work +- Multi-pane UI for feed, contexts, map, table, node focus, and skills - Node/Edge CRUD with optional contexts - Full-text and semantic search - MCP server with graph and skill tools @@ -34,25 +34,18 @@ RA-OS is a minimal knowledge graph UI with MCP server integration. It provides a ## What's NOT Included -- Chat interface (use external agents via MCP) +- Private-app-only built-in assistant experience - Voice features -- Built-in AI agents - Auth/subscription system - Desktop packaging -## Two-Panel Layout +## Current Doctrine -``` -┌─────────────┬─────────────────────────┐ -│ NODES │ FOCUS │ -│ Panel │ Panel │ -│ │ │ -│ • Search │ • Node content │ -│ • Filters │ • Connections │ -│ • List │ • Context + metadata │ -│ │ │ -└─────────────┴─────────────────────────┘ -``` +- no runtime `dimensions` +- optional `contexts` +- node quality driven by `title`, `description`, `source`, `metadata`, and `edges` +- direct lookup first, broader retrieval when useful +- app-owned chunking and embeddings from `nodes.source` ## MCP Integration @@ -81,4 +74,5 @@ Core tools include: `queryNodes`, `retrieveQueryContext`, `createNode`, `writeCo | [Tools & Skills](./4_tools-and-guides.md) | Available MCP tools, skill system | | [UI](./6_ui.md) | Component structure, panels, views | | [MCP](./8_mcp.md) | External agent connector setup | +| [Full Local](./10_full-local.md) | Supported local path and community patterns | | [Troubleshooting](./TROUBLESHOOTING.md) | Common issues and fixes | diff --git a/docs/10_full-local.md b/docs/10_full-local.md new file mode 100644 index 0000000..e0dfa86 --- /dev/null +++ b/docs/10_full-local.md @@ -0,0 +1,102 @@ +# Fully Local / Community Patterns + +This page is for users who want to stay as local as possible without pretending every local-first stack is equally supported. + +## 1. What "Fully Local" Means In RA-H Terms + +In RA-H terms, "fully local" usually means: +- your graph lives in local SQLite +- the UI runs locally +- your MCP server runs locally +- you avoid shipping graph data to hosted backends where possible + +That does not automatically mean every part of the stack is equally local. Model choice, embeddings, and alternate vector backends change that. + +## 2. The Supported Baseline Local Stack + +Supported core path: +- RA-H OS app +- local SQLite DB +- standard standalone MCP server +- documented repo install flow +- hosted model APIs if you choose them + +This is the path the core docs and troubleshooting are written for. + +## 3. Where Local-First Starts Getting Experimental + +Local-first gets more experimental when you change: +- model provider +- embedding provider +- vector backend +- deployment target +- chat/agent client beyond the documented MCP path + +That does not make those setups bad. It just changes the support boundary. + +## 4. Community Pattern: Local Models + RA-H MCP + +Reasonable community pattern: +- keep RA-H OS local +- keep SQLite local +- connect a local-model-capable client to RA-H through MCP + +Honest caveat: +- tool-calling quality depends heavily on the model/runtime +- smaller local models may perform materially worse than stronger hosted tool-use models +- "fully local" can reduce privacy concerns and improve offline control, but it can also degrade reliability + +## 5. Community Pattern: AnythingLLM As Alternate Local Chat / Agent Surface + +Based on current public docs: +- AnythingLLM has MCP compatibility +- AnythingLLM supports local-model paths +- Intelligent Tool Selection exists and may matter for local-model performance + +This makes it a plausible alternate local chat/agent surface for RA-H MCP. + +Caveat: +- MCP support alone does not guarantee strong tool use +- weaker local models can still underperform badly even with a solid MCP integration + +References: +- https://docs.anythingllm.com/mcp-compatibility/overview +- https://docs.anythingllm.com/agent/intelligent-tool-selection + +## 6. Community Pattern: Qdrant Add-On For Vector-Heavy Or `sqlite-vec`-Hostile Environments + +Qdrant is a plausible local or self-hosted vector backend when: +- `sqlite-vec` is weak on the target platform +- storage/runtime constraints make the default vector path awkward +- you are intentionally running a more custom environment + +Important boundary: +- this is not a bundled official RA-H core dependency +- the Nathan Maine repo is a community add-on example, not the default install story + +References: +- https://qdrant.tech/documentation/quickstart/ +- https://github.com/NathanMaine/rah-qdrant-integration + +## 7. Honest Tradeoffs + +- more local privacy can be better +- offline control can be better +- maintenance burden is usually higher +- tool quality can get worse fast with weaker local models +- troubleshooting becomes more user-owned as you move away from the baseline path + +## 8. Support Boundary + +Supported core path: +- repo install flow +- SQLite +- documented standalone MCP setup + +Reasonable community pattern: +- alternate local-model or alternate local chat surface that still respects the MCP contract + +Experimental / user-owned: +- custom vector backend swaps +- unsupported runtime targets +- heavily modified inference stacks diff --git a/docs/2_schema.md b/docs/2_schema.md index 4ef7083..f3f2bfe 100644 --- a/docs/2_schema.md +++ b/docs/2_schema.md @@ -49,7 +49,21 @@ - `nodes_fts` indexes title, description, and source for full-text lookup. - `chunks_fts` indexes chunk text. -- Vector tables store node and chunk embeddings. +- `vec_nodes` stores node-level vectors. +- `vec_chunks` stores chunk-level vectors. + +Full-text search and vector search are separate surfaces: +- FTS uses `nodes_fts` / `chunks_fts` +- semantic/vector retrieval uses `vec_nodes` / `vec_chunks` +- retrieval may combine them, but docs should not blur them into one surface + +## Embedding Lifecycle + +- `nodes.source` is the canonical long-form field for chunking and chunk embeddings. +- changing `nodes.source` should return the node to the app-owned chunk pipeline +- standalone MCP can write `nodes.source`, but it does not directly create chunks or vector rows +- node-level embeddings and chunk embeddings are separate runtime surfaces +- integrity/degraded-mode behavior matters enough that docs should describe these surfaces honestly ## Important Constraints diff --git a/docs/4_tools-and-guides.md b/docs/4_tools-and-guides.md index 59b03da..3be4c0d 100644 --- a/docs/4_tools-and-guides.md +++ b/docs/4_tools-and-guides.md @@ -1,50 +1,56 @@ # Tools & Skills -> MCP tools for graph operations and skills for procedural guidance. +MCP tools are the graph contract. Skills are the reusable procedural layer that teaches agents how to use that contract well. -**How it works:** External agents call MCP tools to read and write your graph. Contexts are optional soft organization only; node quality should come from clear nodes and explicit edges. +## Live MCP Tools ---- - -## MCP Tools - -RA-OS exposes these core standalone MCP tools: - -### Context + Graph +### Read | Tool | Description | |------|-------------| -| `getContext` | Graph overview: stats, contexts, hub nodes, recent activity, skills | -| `retrieveQueryContext` | Pull relevant graph context for a broader current-turn task | -| `queryNodes` | Find specific existing nodes by title, description, or source | +| `getContext` | Graph overview for orientation | +| `queryNodes` | Direct node lookup by title, description, or source | +| `retrieveQueryContext` | Broader current-turn retrieval when graph grounding helps | | `getNodesById` | Fetch full nodes by ID | -| `createNode` | Create a node | -| `writeContext` | Save one confirmed durable context node after explicit user approval | -| `updateNode` | Update a node while preserving context by default | -| `createEdge` | Create a confirmed edge between nodes | -| `queryEdge` | Query edges | -| `updateEdge` | Update an edge explanation after explicit confirmation | -| `queryContexts` | List contexts and optional attached nodes | +| `queryEdge` | Inspect existing edges | +| `queryContexts` | List/search contexts | +| `searchContentEmbeddings` | Search source chunks/transcripts | +| `sqliteQuery` | Read-only SQL (`SELECT`, `WITH`, `PRAGMA`) | -### Skills + Search +### Write + +| Tool | Description | +|------|-------------| +| `createNode` | Create a node after duplicate/update checks | +| `updateNode` | Update a node while preserving context by default | +| `writeContext` | Save one confirmed durable context node | +| `createEdge` | Create a confirmed edge | +| `updateEdge` | Correct an edge after explicit confirmation | + +### Skills | Tool | Description | |------|-------------| | `listSkills` | List available skills | | `readSkill` | Read one skill | -| `writeSkill` | Create/update a skill | +| `writeSkill` | Create or update a skill | | `deleteSkill` | Delete a skill | -| `searchContentEmbeddings` | Search source chunks/transcripts | -| `sqliteQuery` | Read-only SQL (`SELECT`, `WITH`, `PRAGMA`) | ---- +## Behavior Rules + +- search before creating +- use `queryNodes` first for specific-node intent +- use `retrieveQueryContext` only when broader grounding would help +- leave context blank by default +- if context is intentionally provided, prefer `context_name` +- `writeContext`, `createEdge`, and `updateEdge` are confirmation-gated +- judge graph quality by node quality and explicit edges, not taxonomy completeness ## Skills -Skills are markdown instructions stored locally and shared across internal + external agents. - -### Default seeded skills +Skills are markdown instructions stored locally and shared across internal and external agents. +Default seeded skills: - `db-operations` - `create-skill` - `audit` @@ -54,12 +60,9 @@ Skills are markdown instructions stored locally and shared across internal + ext - `calibration` - `connect` -### Storage - -- Live skills: `~/Library/Application Support/RA-H/skills/` -- Bundled defaults: `src/config/skills/` - ---- +Storage: +- live skills: `~/Library/Application Support/RA-H/skills/` +- bundled defaults: `src/config/skills/` ## API Routes @@ -70,13 +73,12 @@ Skills are markdown instructions stored locally and shared across internal + ext | `/api/guides` | GET | Compatibility alias to skills | | `/api/guides/[name]` | GET/PUT/DELETE | Compatibility alias to skills | ---- - ## Key Files | File | Purpose | |------|---------| -| `apps/mcp-server-standalone/` | Standalone MCP server (recommended) | +| `apps/mcp-server-standalone/` | Standalone MCP server | +| `src/tools/infrastructure/registry.ts` | Live tool registry | | `src/services/skills/skillService.ts` | Skills runtime service | | `src/config/skills/*.md` | Bundled default skills | | `src/components/panes/SkillsPane.tsx` | Skills pane UI | diff --git a/docs/5_logging-and-evals.md b/docs/5_logging-and-evals.md index 33e2d87..7a3e181 100644 --- a/docs/5_logging-and-evals.md +++ b/docs/5_logging-and-evals.md @@ -108,9 +108,11 @@ LIMIT 100 - 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 +**Model pricing (current defaults):** +- GPT-5.4 Mini: $0.75/1M input, $0.075/1M cached input, $4.50/1M output +- GPT-5.4: $2.50/1M input, $0.25/1M cached input, $15.00/1M output +- GPT-5 Mini: $0.25/1M input, $0.025/1M cached input, $2.00/1M output +- GPT-5: $1.25/1M input, $0.125/1M cached 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 diff --git a/docs/6_ui.md b/docs/6_ui.md index d64879a..34d69c4 100644 --- a/docs/6_ui.md +++ b/docs/6_ui.md @@ -1,5 +1,13 @@ # UI Surfaces +## Workspace Model + +RA-H OS follows the current pane model: +- explicit `1 / 2 / 3` visible panes +- chat anchored to the right edge of the active workspace +- node tabs only in node panes +- singleton non-node panes + ## Main Views - `Feed` for recent and sortable node browsing @@ -12,12 +20,12 @@ ## UI Contract After The Migration - The app no longer exposes a dimensions pane. -- Feed and table filtering are context-aware and no longer dimension-based. +- Feed and table filtering are not dimension-based. - Persisted pane layout should only hydrate valid pane types: `views`, `node`, `contexts`, `map`, `table`, `skills`. - Contexts are shown as a secondary organizational aid, not as a hard requirement for capture. ## Focus And Capture -- Capture must succeed when both context and dimensions are omitted. +- Capture must succeed when context is omitted. - Focus surfaces should emphasize title, description, source, metadata, and edges. - Node cards may show context when present, but should not depend on it for meaning. diff --git a/docs/8_mcp.md b/docs/8_mcp.md index 6ee61cc..0450920 100644 --- a/docs/8_mcp.md +++ b/docs/8_mcp.md @@ -1,6 +1,94 @@ # MCP Surface -RA-H exposes MCP tools for direct graph work against the local database or app API. +This is the full practical setup page for the standalone open-source MCP path. + +## 1. What MCP Gives You In RA-H OS + +MCP lets an external agent: +- search your existing graph +- ground a broader task in relevant graph context +- create or update nodes +- propose and confirm edges +- read and write shared skills + +The graph contract is: +- no runtime `dimensions` +- optional `contexts` +- direct lookup first +- broader retrieval only when useful +- confirmation-gated durable writeback and edge changes + +## 2. Choose Your Assistant / Client + +Best-supported path: +- Claude Code +- Claude Desktop + +Also reasonable: +- Cursor and similar MCP-capable coding assistants + +Prefer a client that: +- supports local stdio MCP servers well +- reliably restarts after config changes +- lets you pin one package version in config + +## 3. Install The Standalone MCP Server + +Requirements: +- Node.js 18-22 LTS recommended +- existing RA-H DB created by running the app once +- pinned package version in client config + +Package: + +```bash +npx --yes ra-h-mcp-server@2.1.2 +``` + +If `better-sqlite3` fails to load: +- use Node 18-22 LTS +- rebuild native modules if you are developing locally + +## 4. Configure The Assistant With A Pinned Version + +Claude config example: + +```json +{ + "mcpServers": { + "ra-h": { + "command": "npx", + "args": ["--yes", "ra-h-mcp-server@2.1.2"] + } + } +} +``` + +Contributor local-path example: + +```json +{ + "mcpServers": { + "ra-h": { + "command": "node", + "args": ["/absolute/path/to/ra-h_os/apps/mcp-server-standalone/index.js"] + } + } +} +``` + +## 5. Restart And Verify The Tools Are Available + +After editing config: +- fully restart the client +- do not trust a soft window close +- ask the assistant whether RA-H tools are available + +Healthy verification usually means you can see tools like: +- `queryNodes` +- `retrieveQueryContext` +- `createNode` +- `readSkill` ## Core MCP Contract @@ -11,8 +99,8 @@ RA-H exposes MCP tools for direct graph work against the local database or app A - If context is intentionally provided, prefer `context_name`. - `context_id` is an internal implementation detail, not the normal agent-facing field. - `writeContext` writes one confirmed durable context node and must never be called before explicit user approval. -- `createEdge` is a post-confirmation execution tool. Agents should propose likely edges first and only write them after the user explicitly confirms. -- `updateEdge` is also a post-confirmation execution tool. Agents should only correct an edge after the user explicitly confirms the corrected relationship. +- `createEdge` is a post-confirmation execution tool. +- `updateEdge` is also post-confirmation only. - `queryNodes` searches title, description, and source, with optional context filters. - `dimensions` are removed from the MCP contract. @@ -39,18 +127,61 @@ Write: - `writeSkill` - `deleteSkill` -## Tool Behavior +## 6. How The Agent Should Behave With RA-H -- Always search before creating. -- If the user is trying to find a specific existing node, use `queryNodes` first. -- If the user is asking a broader question that would benefit from graph context, use `retrieveQueryContext`. -- Optional user memory reinforcement can help, but the MCP tools, instructions, skills, and docs should be enough for the core retrieval and writeback contract to work. -- Prefer explicit context assignment only when the user clearly wants it and a real context is already known. -- Use `context_name` when context is intentionally provided. -- Do not assume the agent needs to think about context during normal node creation, lookup, or update flows. -- Do not assume the server will infer a best-fit context. -- If the user explicitly asked to save or update something and the target artifact is clear, the agent can write after duplicate/update checks. -- If the agent is only suggesting a save, it should propose the node first and wait for confirmation. -- When obvious relationships appear, propose candidate edges briefly rather than writing them automatically. -- Judge graph quality by node quality and edges, not taxonomy completeness. -- Keep writeback prompts terse and selective. The goal is not to ask constantly whether every useful sentence should be saved. +- always search before creating +- use `queryNodes` first for specific-node intent +- use `retrieveQueryContext` when broader graph grounding would help +- keep context optional by default +- use `context_name` only when context is intentionally provided +- do not assume the server will infer a best-fit context +- if the user explicitly asked to save or update something and the target artifact is clear, the agent can write after duplicate/update checks +- if the agent is only suggesting a save, it should propose the node first and wait for confirmation +- when obvious relationships appear, propose candidate edges briefly rather than writing them automatically +- keep writeback prompts terse and selective + +Do not assume MCP node creation immediately produces chunks or embeddings. The canonical contract is: +- write node data first +- app-owned pipeline later creates chunks, FTS rows, and vectors + +## 7. Optional Memory-File Reinforcement + +Important distinction: +- `CLAUDE.md` is an assistant-native memory/instruction file for Claude Code +- `AGENTS.md` is a repo-local instruction file many teams already use +- other clients may have their own memory or instruction surfaces + +Rules: +- the MCP/tool/docs contract should work without user prompt surgery +- optional reinforcement can still improve consistency +- do not create contradictory instruction files + +Short recommended reinforcement pattern: + +```md +Retrieve relevant RA-H context before substantive work, search before creating, and keep durable writeback prompts brief and confirmation-gated. +``` + +## 8. Troubleshooting And Common Failure Cases + +`Tools not found` +- fully restart the client +- verify the config path is the one your client actually uses +- run the pinned package manually once + +`Database not found` +- run the RA-H app once first so the DB exists +- confirm `RAH_DB_PATH` if using a custom path + +`Node writes land but embeddings/chunks are missing` +- this is usually expected when the app is closed +- standalone MCP writes node data first +- the app later processes pending `nodes.source` work + +`Native module load failure` +- use Node 18-22 LTS +- rebuild `better-sqlite3` if needed for local development + +`Version drift` +- pin the package version in client config +- bump the pinned version intentionally when testing a new release diff --git a/docs/9_open-source.md b/docs/9_open-source.md index 4b0f538..41f9801 100644 --- a/docs/9_open-source.md +++ b/docs/9_open-source.md @@ -1,12 +1,43 @@ # Open Source Surface -The open-source RA-H surface should match the main app contract: +The open-source RA-H surface should match the main app contract where product behavior is shared: - no runtime `dimensions` model, - optional soft `contexts`, - no automatic context assignment on write, - node quality driven by title, description, source, metadata, and edges. +## What RA-H OS Includes + +- local SQLite graph +- local UI +- standalone MCP server +- shared skills system +- BYO API key path + +## What RA-H OS Does Not Promise + +- every private-app surface +- private subscription/auth behavior +- official support for every local model stack or vector backend someone can wire up +- a guarantee that every community setup is first-class supported + +## Support Boundary + +Supported core path: +- RA-H OS app +- local SQLite +- standard standalone MCP server +- documented repo install flow + +Reasonable community pattern: +- local model or alternate MCP-capable chat surface layered on top of the documented contract + +Experimental / user-owned: +- custom vector backends +- unsupported deployment targets +- aggressive local-model substitutions that degrade tool quality + ## Important App Routes - `app/api/nodes/` diff --git a/docs/README.md b/docs/README.md index 8c8458d..654c0bc 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,4 +1,4 @@ -# RA-OS Documentation +# RA-H OS Documentation ``` ██████╗ █████╗ ██╗ ██╗ @@ -13,28 +13,31 @@ | Doc | Description | |-----|-------------| -| [Overview](./0_overview.md) | What is RA-OS, design philosophy | -| [Schema](./2_schema.md) | Database schema, node/edge structure | -| [Tools & Skills](./4_tools-and-guides.md) | MCP tools, skill system | -| [Logging & Evals](./5_logging-and-evals.md) | Debugging, evaluation framework | -| [UI](./6_ui.md) | 2-panel layout, components, views | -| [MCP](./8_mcp.md) | Connect Claude Code and external agents | -| [About](./9_open-source.md) | What's included, contributing | +| [Overview](./0_overview.md) | What RA-H OS is and what contract it shares with the main app | +| [Schema](./2_schema.md) | Current SQLite contract | +| [Tools & Skills](./4_tools-and-guides.md) | MCP tools and skill system | +| [Logging & Evals](./5_logging-and-evals.md) | Logs, evals, and debugging surfaces | +| [UI](./6_ui.md) | Current pane and focus model | +| [MCP](./8_mcp.md) | Full standalone MCP install and behavior guide | +| [Open Source](./9_open-source.md) | Scope, support boundary, contributor reality | +| [Full Local](./10_full-local.md) | Supported local path vs community patterns | | [Troubleshooting](./TROUBLESHOOTING.md) | Common issues and fixes | -| [Development](./development/process.md) | Dev workflow and PR checklist | -| [Docs Process](./development/docs-process.md) | How to maintain docs | -## Getting Started +## Start Here + +If you just want RA-H OS working: +1. Read [../README.md](../README.md) +2. Follow [MCP](./8_mcp.md) if you want external-agent access +3. Read [Full Local](./10_full-local.md) if you want a more local-first or community setup + +## Local App Quick Start ```bash -# Clone git clone https://github.com/bradwmorris/ra-h_os.git cd ra-h_os - -# Install npm install - -# Run +npm rebuild better-sqlite3 +npm run bootstrap:local npm run dev ``` @@ -57,7 +60,7 @@ Add to your `~/.claude.json`: If you publish a newer MCP release and need clients to use it immediately, bump the pinned version here and restart the client. Do not assume plain `npx ra-h-mcp-server` always refreshes instantly. -Run RA-H once first so the database exists. The standalone MCP server can write nodes without the app running, but the app owns chunking and embedding from node source. See [MCP docs](./8_mcp.md) for alternatives. +Run RA-H once first so the database exists. The standalone MCP server can write nodes without the app running, but the app owns chunking and embedding from node source. See [MCP docs](./8_mcp.md) for the full install, verify, memory-file, and troubleshooting path. ## Questions? diff --git a/instrumentation.ts b/instrumentation.ts index 9493d31..27c9f94 100644 --- a/instrumentation.ts +++ b/instrumentation.ts @@ -1,7 +1,6 @@ -import { startAutoEmbedRecovery } from '@/services/embedding/autoEmbedQueue'; - export async function register() { if (process.env.NEXT_RUNTIME === 'nodejs') { + const { startAutoEmbedRecovery } = await import('@/services/embedding/autoEmbedQueue'); startAutoEmbedRecovery(); } } diff --git a/src/components/onboarding/FirstRunModal.tsx b/src/components/onboarding/FirstRunModal.tsx index 82b4c5d..7315cba 100644 --- a/src/components/onboarding/FirstRunModal.tsx +++ b/src/components/onboarding/FirstRunModal.tsx @@ -28,13 +28,13 @@ export default function FirstRunModal() {
To use AI features (embeddings, auto-descriptions, smart tagging),
- add your OpenAI API key to .env.local:
+ add your OpenAI API key in Settings → API Keys or directly in .env.local:
OPENAI_API_KEY=sk-your-key-here
- Then restart the app. Average cost for heavy use is less than $0.10/day.
+ Settings writes to .env.local for you. Average cost for heavy use is less than $0.10/day.
- Add your key to .env.local in the project root:
+ Save your key here to write it into {envPath}.
+ You can still edit the file directly if you prefer.
OPENAI_API_KEY=sk-your-key-here
- Restart the app after changing the key. + + setKeyInput(e.target.value)} + placeholder={status === 'configured' ? 'Paste a new key to replace the current one' : 'sk-...'} + style={inputStyle} + autoCapitalize="off" + autoCorrect="off" + spellCheck={false} + /> +
+ Current key: {maskedKey}
+
+ {message} +
+ )} + {error && ( ++ {error} +
+ )} ++ This open-source build uses your own local key only. No Railway key path is used here.