fix: use platform-aware local defaults
- Route app DB and sqlite-vec defaults through shared platform helpers - Mirror platform DB defaults in the standalone MCP package - Fix Windows setup npm spawning and remove macOS-only env defaults
This commit is contained in:
+4
-3
@@ -6,9 +6,10 @@
|
|||||||
# Get one at: https://platform.openai.com/api-keys
|
# Get one at: https://platform.openai.com/api-keys
|
||||||
OPENAI_API_KEY=
|
OPENAI_API_KEY=
|
||||||
|
|
||||||
# Database path (defaults work for most users)
|
# Database/vector paths are auto-detected for macOS, Windows, and Linux.
|
||||||
# SQLITE_DB_PATH=~/Library/Application Support/RA-H/db/rah.sqlite
|
# Override only if you intentionally want a custom location.
|
||||||
SQLITE_VEC_EXTENSION_PATH=./vendor/sqlite-extensions/vec0.dylib
|
# SQLITE_DB_PATH=/absolute/path/to/rah.sqlite
|
||||||
|
# SQLITE_VEC_EXTENSION_PATH=/absolute/path/to/vec0.<dylib|dll|so>
|
||||||
|
|
||||||
# App config (no changes needed)
|
# App config (no changes needed)
|
||||||
NODE_ENV=development
|
NODE_ENV=development
|
||||||
|
|||||||
@@ -50,13 +50,13 @@ Restart Claude fully. If you need to freeze behavior for debugging, pin an exact
|
|||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
- Node.js 18-22 LTS recommended
|
- Node.js 18-22 LTS recommended
|
||||||
- a RA-H database at `~/Library/Application Support/RA-H/db/rah.sqlite`, created by `setup`, `init-db`, or the app
|
- a RA-H database at the platform default path, created by `setup`, `init-db`, or the app
|
||||||
|
|
||||||
## Environment Variables
|
## Environment Variables
|
||||||
|
|
||||||
| Variable | Default | Description |
|
| Variable | Default | Description |
|
||||||
|----------|---------|-------------|
|
|----------|---------|-------------|
|
||||||
| `RAH_DB_PATH` | `~/Library/Application Support/RA-H/db/rah.sqlite` | Database path |
|
| `RAH_DB_PATH` | Platform default app-data path | Database path |
|
||||||
|
|
||||||
For demos or isolated installs:
|
For demos or isolated installs:
|
||||||
|
|
||||||
|
|||||||
@@ -7,24 +7,32 @@ const os = require('node:os');
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the database path.
|
* Get the database path.
|
||||||
* Priority: RAH_DB_PATH env var > default app data location
|
* Priority: RAH_DB_PATH env var > SQLITE_DB_PATH env var > platform app data location
|
||||||
*/
|
*/
|
||||||
function getDatabasePath() {
|
function getDefaultDbPath() {
|
||||||
if (process.env.RAH_DB_PATH) {
|
const homeDir = os.homedir() || process.env.HOME || '~';
|
||||||
return process.env.RAH_DB_PATH;
|
|
||||||
|
if (process.platform === 'win32') {
|
||||||
|
const appData = process.env.APPDATA || path.join(homeDir, 'AppData', 'Roaming');
|
||||||
|
return path.join(appData, 'RA-H', 'db', 'rah.sqlite');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.platform === 'darwin') {
|
||||||
|
return path.join(homeDir, 'Library', 'Application Support', 'RA-H', 'db', 'rah.sqlite');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default: ~/Library/Application Support/RA-H/db/rah.sqlite
|
|
||||||
return path.join(
|
return path.join(
|
||||||
os.homedir(),
|
process.env.XDG_DATA_HOME || path.join(homeDir, '.local', 'share'),
|
||||||
'Library',
|
|
||||||
'Application Support',
|
|
||||||
'RA-H',
|
'RA-H',
|
||||||
'db',
|
'db',
|
||||||
'rah.sqlite'
|
'rah.sqlite'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getDatabasePath() {
|
||||||
|
return process.env.RAH_DB_PATH || process.env.SQLITE_DB_PATH || getDefaultDbPath();
|
||||||
|
}
|
||||||
|
|
||||||
let db = null;
|
let db = null;
|
||||||
|
|
||||||
function getExistingColumnNames(db, tableName) {
|
function getExistingColumnNames(db, tableName) {
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ Start with product orientation and goal discovery first.
|
|||||||
Only bring up setup details if the user actually needs them:
|
Only bring up setup details if the user actually needs them:
|
||||||
|
|
||||||
1. If they are on local/BYO-key mode, point them to Settings → API Keys.
|
1. If they are on local/BYO-key mode, point them to Settings → API Keys.
|
||||||
2. If they ask about the database location, tell them the default macOS path is `~/Library/Application Support/RA-H/db/rah.sqlite`.
|
2. If they ask about the database location, tell them RA-H uses the platform default: macOS `~/Library/Application Support/RA-H/db/rah.sqlite`, Windows `%APPDATA%/RA-H/db/rah.sqlite`, Linux `~/.local/share/RA-H/db/rah.sqlite`.
|
||||||
3. If API keys are relevant, explain them plainly:
|
3. If API keys are relevant, explain them plainly:
|
||||||
- **OpenAI** — powers embeddings, semantic retrieval, and extraction-related AI work.
|
- **OpenAI** — powers embeddings, semantic retrieval, and extraction-related AI work.
|
||||||
- **Anthropic** — mainly relevant for compatible runtime paths and local/dev setups.
|
- **Anthropic** — mainly relevant for compatible runtime paths and local/dev setups.
|
||||||
|
|||||||
@@ -6,8 +6,14 @@ function run(command, args) {
|
|||||||
const result = spawnSync(command, args, {
|
const result = spawnSync(command, args, {
|
||||||
stdio: 'inherit',
|
stdio: 'inherit',
|
||||||
env: process.env,
|
env: process.env,
|
||||||
|
shell: process.platform === 'win32',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (result.error) {
|
||||||
|
console.error(`[setup-local] Failed to run ${command}: ${result.error.message}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
if (result.status !== 0) {
|
if (result.status !== 0) {
|
||||||
process.exit(result.status || 1);
|
process.exit(result.status || 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ Start with product orientation and goal discovery first.
|
|||||||
Only bring up setup details if the user actually needs them:
|
Only bring up setup details if the user actually needs them:
|
||||||
|
|
||||||
1. If they are on local/BYO-key mode, point them to Settings → API Keys.
|
1. If they are on local/BYO-key mode, point them to Settings → API Keys.
|
||||||
2. If they ask about the database location, tell them the default macOS path is `~/Library/Application Support/RA-H/db/rah.sqlite`.
|
2. If they ask about the database location, tell them RA-H uses the platform default: macOS `~/Library/Application Support/RA-H/db/rah.sqlite`, Windows `%APPDATA%/RA-H/db/rah.sqlite`, Linux `~/.local/share/RA-H/db/rah.sqlite`.
|
||||||
3. If API keys are relevant, explain them plainly:
|
3. If API keys are relevant, explain them plainly:
|
||||||
- **OpenAI** — powers embeddings, semantic retrieval, and extraction-related AI work.
|
- **OpenAI** — powers embeddings, semantic retrieval, and extraction-related AI work.
|
||||||
- **Anthropic** — mainly relevant for compatible runtime paths and local/dev setups.
|
- **Anthropic** — mainly relevant for compatible runtime paths and local/dev setups.
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import Database from 'better-sqlite3';
|
|||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { DatabaseError } from '@/types/database';
|
import { DatabaseError } from '@/types/database';
|
||||||
|
import { getDatabasePath, getVecExtensionPath } from '@/services/database/sqlite-runtime';
|
||||||
|
|
||||||
export interface SQLiteConfig {
|
export interface SQLiteConfig {
|
||||||
dbPath: string;
|
dbPath: string;
|
||||||
@@ -115,17 +116,9 @@ class SQLiteClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private getSQLiteConfig(): SQLiteConfig {
|
private getSQLiteConfig(): SQLiteConfig {
|
||||||
const dbPath = process.env.SQLITE_DB_PATH || path.join(
|
|
||||||
process.env.HOME || '~',
|
|
||||||
'Library/Application Support/RA-H/db/rah.sqlite'
|
|
||||||
);
|
|
||||||
|
|
||||||
const vecExtensionPath = process.env.SQLITE_VEC_EXTENSION_PATH ||
|
|
||||||
'./vendor/sqlite-extensions/vec0.dylib';
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
dbPath,
|
dbPath: getDatabasePath(),
|
||||||
vecExtensionPath
|
vecExtensionPath: getVecExtensionPath()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import Database from 'better-sqlite3';
|
import Database from 'better-sqlite3';
|
||||||
import path from 'path';
|
import {
|
||||||
import os from 'os';
|
getDatabasePath as getRuntimeDatabasePath,
|
||||||
import { getDbVectorCapability as getVectorCapability } from '@/services/database/sqlite-runtime';
|
getDbVectorCapability as getVectorCapability,
|
||||||
|
getVecExtensionPath as getRuntimeVecExtensionPath
|
||||||
|
} from '@/services/database/sqlite-runtime';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize a float array to binary format for vec0 storage
|
* Serialize a float array to binary format for vec0 storage
|
||||||
@@ -35,27 +37,14 @@ export function deserializeFloat32Vector(blob: Buffer): number[] {
|
|||||||
* Get SQLite database path from environment or default location
|
* Get SQLite database path from environment or default location
|
||||||
*/
|
*/
|
||||||
export function getDatabasePath(): string {
|
export function getDatabasePath(): string {
|
||||||
const envPath = process.env.SQLITE_DB_PATH;
|
return getRuntimeDatabasePath();
|
||||||
if (envPath) {
|
|
||||||
return envPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Default path: ~/Library/Application Support/RA-H/db/rah.sqlite
|
|
||||||
const homeDir = os.homedir();
|
|
||||||
return path.join(homeDir, 'Library', 'Application Support', 'RA-H', 'db', 'rah.sqlite');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get vec extension path from environment or default location
|
* Get vec extension path from environment or default location
|
||||||
*/
|
*/
|
||||||
export function getVecExtensionPath(): string {
|
export function getVecExtensionPath(): string {
|
||||||
const envPath = process.env.SQLITE_VEC_EXTENSION_PATH;
|
return getRuntimeVecExtensionPath();
|
||||||
if (envPath) {
|
|
||||||
return envPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Default path relative to project root
|
|
||||||
return path.join(process.cwd(), 'vendor', 'sqlite-extensions', 'vec0.dylib');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -2,18 +2,10 @@ import { tool } from 'ai';
|
|||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { exec } from 'child_process';
|
import { exec } from 'child_process';
|
||||||
import { promisify } from 'util';
|
import { promisify } from 'util';
|
||||||
import path from 'path';
|
import { getDatabasePath } from '@/services/database/sqlite-runtime';
|
||||||
|
|
||||||
const execAsync = promisify(exec);
|
const execAsync = promisify(exec);
|
||||||
|
|
||||||
// Get database path (same logic as sqlite-client.ts)
|
|
||||||
function getDatabasePath(): string {
|
|
||||||
return process.env.SQLITE_DB_PATH || path.join(
|
|
||||||
process.env.HOME || '~',
|
|
||||||
'Library/Application Support/RA-H/db/rah.sqlite'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Security: Only allow SELECT statements
|
// Security: Only allow SELECT statements
|
||||||
function isReadOnlyQuery(sql: string): boolean {
|
function isReadOnlyQuery(sql: string): boolean {
|
||||||
const normalized = sql.trim().toLowerCase();
|
const normalized = sql.trim().toLowerCase();
|
||||||
|
|||||||
Reference in New Issue
Block a user