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
+128
View File
@@ -0,0 +1,128 @@
export interface UsageData {
inputTokens: number;
outputTokens: number;
totalTokens: number;
cacheWriteTokens?: number;
cacheReadTokens?: number;
cacheHit?: boolean;
cacheSavingsPct?: number;
estimatedCostUsd: number;
modelUsed: string;
provider: 'anthropic' | 'openai';
toolsUsed?: string[];
toolCallsCount?: number;
traceId?: string;
parentChatId?: number;
workflowKey?: string;
workflowNodeId?: number;
capsuleVersion?: number;
contextSourcesUsed?: number[];
validationStatus?: 'ok' | 'failed';
validationMessage?: string;
fallbackAction?: string;
mode?: 'easy' | 'hard';
}
export interface EnhancedChatMetadata {
timestamp: string;
session_id: string;
current_view: 'nodes' | 'memory';
open_tab_count: number;
has_focused_node: boolean;
message_count: number;
input_tokens?: number;
output_tokens?: number;
total_tokens?: number;
cache_write_tokens?: number;
cache_read_tokens?: number;
cache_hit?: boolean;
cache_savings_pct?: number;
estimated_cost_usd?: number;
model_used?: string;
provider?: 'anthropic' | 'openai';
tools_used?: string[];
tool_calls_count?: number;
trace_id?: string;
parent_chat_id?: number;
voice_tts_chars?: number;
voice_tts_cost_usd?: number;
voice_tts_chars_total?: number;
voice_tts_cost_usd_total?: number;
voice_request_id?: string;
voice_tts_request_count?: number;
voice_usage?: Array<{
request_id: string;
message_id?: string | null;
chars: number;
cost_usd: number;
voice?: string;
model?: string;
duration_ms?: number | null;
logged_at?: string;
}>;
}
export interface CostReport {
periodStart: string;
periodEnd: string;
totalCostUsd: number;
totalChats: number;
totalTokens: number;
inputTokens: number;
outputTokens: number;
cacheReadTokens: number;
cacheWriteTokens: number;
cacheHitRate: number;
cacheSavingsUsd: number;
avgCostPerChat: number;
avgTokensPerChat: number;
costByAgent: {
[agentName: string]: {
costUsd: number;
chats: number;
tokens: number;
};
};
costByModel: {
[modelId: string]: {
costUsd: number;
chats: number;
tokens: number;
};
};
}
export interface TraceCostSummary {
traceId: string;
totalCostUsd: number;
chatCount: number;
orchestratorCost: number;
executorCost: number;
plannerCost: number;
totalTokens: number;
interactions: Array<{
chatId: number;
agentName: string;
costUsd: number;
tokens: number;
createdAt: string;
}>;
}
export interface ModelPricing {
provider: 'anthropic' | 'openai';
inputPer1M: number;
outputPer1M: number;
cacheWritePer1M?: number;
cacheReadPer1M?: number;
}
export interface CacheEffectiveness {
totalRequests: number;
cacheHits: number;
cacheMisses: number;
hitRate: number;
totalCacheSavingsUsd: number;
avgSavingsPerHit: number;
totalTokensSaved: number;
}
+173
View File
@@ -0,0 +1,173 @@
// New Node-based type system replacing rigid Item categorization
export interface Node {
id: number;
title: string;
description?: string;
content?: string; // Consolidated content from description + abstract + notes
link?: string;
type?: string;
dimensions: string[]; // Flexible dimensions replacing type + stage + segment + tags
embedding?: Buffer; // Node-level embedding (BLOB data)
chunk?: string;
metadata?: any; // Flexible metadata storage from extras + chunk_status + sub_type
created_at: string;
updated_at: string;
is_pinned?: number; // Legacy pin flag (read-only, slated for removal)
edge_count?: number; // Derived count of edges, included in some queries
// Optional embedding fields (restored from migration)
embedding_updated_at?: string;
embedding_text?: string;
chunk_status?: 'not_chunked' | 'chunking' | 'chunked' | 'error' | null;
}
// Legacy Item interface - DEPRECATED, use Node instead
// Kept temporarily for migration compatibility
export interface Item extends Node {
// Legacy fields for backwards compatibility during transition
description?: string;
abstract?: string;
type?: string;
legacyType?: string[];
stage?: string;
segment?: string[];
tags?: string[];
sub_type?: any;
notes?: any;
extras?: any;
score?: number;
content_embedding?: number[];
embedding_updated_at?: string;
chunk_status?: 'not_chunked' | 'chunking' | 'chunked' | 'error';
chunk_updated_at?: string;
}
export interface Chunk {
id: number;
node_id: number; // Updated from item_id to node_id
chunk_idx?: number;
text: string;
embedding?: number[];
embedding_type: string;
metadata?: any; // Updated from extras to metadata
created_at: string;
}
export interface Edge {
id: number;
from_node_id: number;
to_node_id: number;
context?: any;
source: 'user' | 'ai_similarity' | 'helper_name';
created_at: string;
}
export interface Chat {
id: number;
user_message?: string;
assistant_message?: string;
thread_id: string;
focused_node_id?: number; // Updated from focused_item_id
metadata?: any;
embedding?: number[]; // Renamed from content_embedding
created_at: string;
}
export interface SessionContext {
id: number;
session_id: string;
focused_node_id: number; // Updated from focused_item_id
context_data: any;
created_at: string;
last_accessed: string;
expires_at: string;
}
export interface SessionCache {
id: number;
session_id: string;
cache_key: string;
cache_data: any;
expires_at: string;
created_at: string;
}
// New NodeFilters interface replacing rigid ItemFilters
export interface NodeFilters {
dimensions?: string[]; // Filter by dimensions (replaces stage/type filtering)
search?: string; // Text search in title/content
limit?: number;
offset?: number;
sortBy?: 'updated' | 'edges'; // Sort by updated_at or edge count
}
// Legacy filters - DEPRECATED, use NodeFilters instead
export interface ItemFilters extends NodeFilters {
stage?: string;
type?: string;
tags?: string[];
}
export interface ChunkData {
node_id: number; // Updated from item_id
chunk_idx?: number;
text: string;
embedding?: number[];
embedding_type: string;
metadata?: any; // Updated from extras
}
export interface EdgeData {
from_node_id: number;
to_node_id: number;
context?: any;
source: 'user' | 'ai_similarity' | 'helper_name';
}
export interface ChatData {
user_message?: string;
assistant_message?: string;
thread_id: string;
focused_node_id?: number; // Updated from focused_item_id
metadata?: any;
embedding?: number[]; // Renamed from content_embedding
}
export interface CachedContext {
sessionId: string;
focusedNodeId: number; // Updated from focusedItemId
contextData: any;
expiresAt: string;
}
// New NodeConnection interface
export interface NodeConnection {
id: number;
connected_node: Node; // Updated from connected_item
edge: Edge;
}
// Legacy connection - DEPRECATED, use NodeConnection instead
export interface ItemConnection {
id: number;
connected_item: Item;
edge: Edge;
}
export interface DatabaseConfig {
host: string;
port: number;
database: string;
user: string;
password: string;
ssl?: boolean;
connectionTimeoutMillis?: number;
idleTimeoutMillis?: number;
max?: number;
}
export interface DatabaseError {
message: string;
code?: string;
details?: any;
}
+22
View File
@@ -0,0 +1,22 @@
export interface MemoryContext {
insights: {
user_patterns: string[];
preferences: string[];
common_queries: string[];
knowledge_domains: string[];
};
context: string;
}
export interface HelperConfig {
name: string;
display_name: string;
description: string;
system_prompt: string;
component_key: string;
available_tools: string[];
enabled: boolean;
created_at: string;
updated_at: string;
memory?: MemoryContext;
}
+19
View File
@@ -0,0 +1,19 @@
export interface LogEntry {
id: number;
ts: string;
table_name: string;
action: string;
row_id: number;
summary: string | null;
snapshot_json: string | null;
enriched_summary: string | null;
}
export interface LogsResponse {
logs: LogEntry[];
page: number;
limit: number;
threadId?: string;
traceId?: string;
table?: string;
}
+26
View File
@@ -0,0 +1,26 @@
declare module 'pdf-parse' {
interface PDFInfo {
Title?: string;
Author?: string;
Creator?: string;
Producer?: string;
CreationDate?: string;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[key: string]: any;
}
interface PDFData {
numpages: number;
numrender: number;
info: PDFInfo;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
metadata: any;
text: string;
version: string;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function pdf(dataBuffer: Buffer, options?: any): Promise<PDFData>;
export = pdf;
}
+25
View File
@@ -0,0 +1,25 @@
/**
* Types for Anthropic prompt caching
* https://docs.claude.com/en/docs/build-with-claude/prompt-caching
*/
export type CacheControl = { type: 'ephemeral' };
export interface CacheableBlock {
type: 'text';
text: string;
cache_control?: CacheControl;
}
export interface SystemPromptResult {
blocks: CacheableBlock[];
cacheHit: boolean;
}
export interface CacheStats {
cacheCreationInputTokens: number;
cacheReadInputTokens: number;
inputTokens: number;
outputTokens: number;
savingsPercentage: number;
}