sync: features from private repo (2025-12-24)
Synced from ra-h private repo: - Collapsible chat panel (Cmd+\) - FolderViewOverlay with Kanban/Grid/List views - Updated agent prompts - Improved executor and quickAdd services - New views.ts types Files kept at OS versions (auth/backend deps): - SettingsModal, RAHChat, useSSEChat - Delegation tools and wiseRAHExecutor - openExternalUrl (no Tauri) Added stub: supabaseTokenRegistry.ts for compatibility
This commit is contained in:
@@ -8,7 +8,6 @@ import { calculateCost } from '@/services/analytics/pricing';
|
||||
import { UsageData } from '@/types/analytics';
|
||||
import { summarizeToolExecution } from '@/services/agents/toolResultUtils';
|
||||
import { edgeService } from '@/services/database/edges';
|
||||
import { RequestContext } from '@/services/context/requestContext';
|
||||
|
||||
interface CapsuleNodeJSON {
|
||||
id: number;
|
||||
@@ -121,11 +120,7 @@ export interface MiniRAHExecutionInput {
|
||||
export class MiniRAHExecutor {
|
||||
static async execute({ sessionId, task, context, expectedOutcome, traceId, parentChatId, workflowKey, workflowNodeId }: MiniRAHExecutionInput) {
|
||||
try {
|
||||
const requestContext = RequestContext.get();
|
||||
const delegateKey =
|
||||
requestContext.apiKeys?.openai ||
|
||||
process.env.RAH_DELEGATE_OPENAI_API_KEY ||
|
||||
process.env.OPENAI_API_KEY;
|
||||
const delegateKey = process.env.RAH_DELEGATE_OPENAI_API_KEY || process.env.OPENAI_API_KEY;
|
||||
if (!delegateKey) {
|
||||
throw new Error('RAH_DELEGATE_OPENAI_API_KEY (or OPENAI_API_KEY) is not set.');
|
||||
}
|
||||
|
||||
@@ -210,7 +210,6 @@ async function handleNoteQuickAdd(rawInput: string, task: string): Promise<strin
|
||||
body: JSON.stringify({
|
||||
title,
|
||||
content,
|
||||
dimensions: [],
|
||||
metadata: {
|
||||
source: 'quick-add-note',
|
||||
refined_at: new Date().toISOString(),
|
||||
@@ -307,7 +306,6 @@ async function handleChatTranscriptQuickAdd(rawInput: string, task: string): Pro
|
||||
title,
|
||||
content,
|
||||
chunk: transcript,
|
||||
dimensions: [],
|
||||
metadata,
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Stub for SupabaseTokenRegistry - not used in open source version
|
||||
* The private version uses this for backend API authentication.
|
||||
* In open source mode, all API calls go directly to OpenAI/Anthropic.
|
||||
*/
|
||||
export class SupabaseTokenRegistry {
|
||||
static async get(_key: string): Promise<string | null> {
|
||||
return null;
|
||||
}
|
||||
|
||||
static getLast(_key: string): string | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
static set(_key: string, _value: string): void {
|
||||
// No-op in OS version
|
||||
}
|
||||
|
||||
static delete(_key: string): void {
|
||||
// No-op in OS version
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,8 @@ export interface ContextBuilderOptions {
|
||||
const BASE_CONTEXT = `=== RA-H BASE CONTEXT ===
|
||||
- Nodes store content (title, content, dimensions, metadata, link, chunk)
|
||||
- Edges capture directed relationships between nodes
|
||||
- Dimensions organize nodes; locked dimensions (isPriority=true) auto-assign to new nodes
|
||||
- You can create and manage dimensions using dimension tools (createDimension, updateDimension, lockDimension, unlockDimension, deleteDimension)
|
||||
- When auto-context is enabled you'll see BACKGROUND CONTEXT with the 10 most-connected nodes (ID + title only)
|
||||
- Focused nodes show truncated content; use queryNodes, searchContentEmbeddings, or queryEdge when you need full detail
|
||||
- Node references must use [NODE:id:"title"] so the UI renders clickable labels
|
||||
|
||||
@@ -32,12 +32,6 @@ export class ApiKeyService {
|
||||
this.loadKeys();
|
||||
}
|
||||
|
||||
private notifyUpdate(): void {
|
||||
if (typeof window !== 'undefined') {
|
||||
window.dispatchEvent(new CustomEvent('api-keys:updated'));
|
||||
}
|
||||
}
|
||||
|
||||
// Load keys from localStorage
|
||||
private loadKeys(): void {
|
||||
try {
|
||||
@@ -81,7 +75,6 @@ export class ApiKeyService {
|
||||
if (this.validateOpenAiKey(key)) {
|
||||
this.keys.openai = key;
|
||||
this.saveKeys();
|
||||
this.notifyUpdate();
|
||||
} else {
|
||||
throw new Error('Invalid OpenAI API key format');
|
||||
}
|
||||
@@ -92,7 +85,6 @@ export class ApiKeyService {
|
||||
if (this.validateAnthropicKey(key)) {
|
||||
this.keys.anthropic = key;
|
||||
this.saveKeys();
|
||||
this.notifyUpdate();
|
||||
} else {
|
||||
throw new Error('Invalid Anthropic API key format');
|
||||
}
|
||||
@@ -103,14 +95,12 @@ export class ApiKeyService {
|
||||
delete this.keys.openai;
|
||||
this.saveKeys();
|
||||
this.status.openai = 'not-set';
|
||||
this.notifyUpdate();
|
||||
}
|
||||
|
||||
clearAnthropicKey(): void {
|
||||
delete this.keys.anthropic;
|
||||
this.saveKeys();
|
||||
this.status.anthropic = 'not-set';
|
||||
this.notifyUpdate();
|
||||
}
|
||||
|
||||
// Clear all keys
|
||||
@@ -121,7 +111,6 @@ export class ApiKeyService {
|
||||
openai: 'not-set',
|
||||
anthropic: 'not-set'
|
||||
};
|
||||
this.notifyUpdate();
|
||||
}
|
||||
|
||||
// Get masked key for display (show only last 4 characters)
|
||||
@@ -184,16 +173,26 @@ export class ApiKeyService {
|
||||
async testAnthropicConnection(key?: string): Promise<boolean> {
|
||||
const testKey = key || this.getAnthropicKey();
|
||||
if (!testKey) return false;
|
||||
|
||||
this.status.anthropic = 'testing';
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/local/test-anthropic', {
|
||||
// Simple test call to Anthropic API
|
||||
const response = await fetch('https://api.anthropic.com/v1/messages', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ apiKey: testKey }),
|
||||
headers: {
|
||||
'x-api-key': testKey,
|
||||
'Content-Type': 'application/json',
|
||||
'anthropic-version': '2023-06-01'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model: 'claude-3-haiku-20240307',
|
||||
max_tokens: 1,
|
||||
messages: [{ role: 'user', content: 'test' }]
|
||||
})
|
||||
});
|
||||
const data = await response.json();
|
||||
const isConnected = Boolean(data?.ok);
|
||||
|
||||
const isConnected = response.ok;
|
||||
this.status.anthropic = isConnected ? 'connected' : 'failed';
|
||||
return isConnected;
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user