Files
claude-mem/src/shared/paths.ts
T
Alex Newman 309e8a7139 Implement hybrid search: Chroma semantic + SQLite temporal
Core implementation:
- Added Chroma MCP client integration to search-server.ts
- Implemented queryChroma() helper with Python dict parsing
- Added VECTOR_DB_DIR constant to paths.ts
- Added SessionStore.getObservationsByIds() method

Search handlers updated:
- search_observations: Semantic-first with 90-day temporal filter
- find_by_concept/type/file: Metadata-first, semantic-enhanced ranking
- All handlers fall back to FTS5 if Chroma unavailable

Technical details:
- Direct MCP client usage (no abstractions)
- Regex parsing of Chroma Python dict responses
- Semantic ranking preserved in final results
- Graceful degradation to FTS5-only search

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-31 23:00:04 -04:00

134 lines
3.5 KiB
TypeScript

import { join, dirname, basename, sep } from 'path';
import { homedir } from 'os';
import { existsSync, mkdirSync } from 'fs';
import { execSync } from 'child_process';
import { fileURLToPath } from 'url';
// Get __dirname that works in both ESM (hooks) and CJS (worker) contexts
function getDirname(): string {
// CJS context - __dirname exists
if (typeof __dirname !== 'undefined') {
return __dirname;
}
// ESM context - use import.meta.url
return dirname(fileURLToPath(import.meta.url));
}
const _dirname = getDirname();
/**
* Simple path configuration for claude-mem
* Standard paths based on Claude Code conventions
*/
// Base directories
export const DATA_DIR = process.env.CLAUDE_MEM_DATA_DIR || join(homedir(), '.claude-mem');
export const CLAUDE_CONFIG_DIR = process.env.CLAUDE_CONFIG_DIR || join(homedir(), '.claude');
// Data subdirectories
export const ARCHIVES_DIR = join(DATA_DIR, 'archives');
export const LOGS_DIR = join(DATA_DIR, 'logs');
export const TRASH_DIR = join(DATA_DIR, 'trash');
export const BACKUPS_DIR = join(DATA_DIR, 'backups');
export const USER_SETTINGS_PATH = join(DATA_DIR, 'settings.json');
export const DB_PATH = join(DATA_DIR, 'claude-mem.db');
export const VECTOR_DB_DIR = join(DATA_DIR, 'vector-db');
// Claude integration paths
export const CLAUDE_SETTINGS_PATH = join(CLAUDE_CONFIG_DIR, 'settings.json');
export const CLAUDE_COMMANDS_DIR = join(CLAUDE_CONFIG_DIR, 'commands');
export const CLAUDE_MD_PATH = join(CLAUDE_CONFIG_DIR, 'CLAUDE.md');
/**
* Get project-specific archive directory
*/
export function getProjectArchiveDir(projectName: string): string {
return join(ARCHIVES_DIR, projectName);
}
/**
* Get worker socket path for a session
*/
export function getWorkerSocketPath(sessionId: number): string {
return join(DATA_DIR, `worker-${sessionId}.sock`);
}
/**
* Ensure a directory exists
*/
export function ensureDir(dirPath: string): void {
mkdirSync(dirPath, { recursive: true });
}
/**
* Ensure all data directories exist
*/
export function ensureAllDataDirs(): void {
ensureDir(DATA_DIR);
ensureDir(ARCHIVES_DIR);
ensureDir(LOGS_DIR);
ensureDir(TRASH_DIR);
ensureDir(BACKUPS_DIR);
}
/**
* Ensure all Claude integration directories exist
*/
export function ensureAllClaudeDirs(): void {
ensureDir(CLAUDE_CONFIG_DIR);
ensureDir(CLAUDE_COMMANDS_DIR);
}
/**
* Get current project name from git root or cwd
*/
export function getCurrentProjectName(): string {
try {
const gitRoot = execSync('git rev-parse --show-toplevel', {
cwd: process.cwd(),
encoding: 'utf8',
stdio: ['pipe', 'pipe', 'ignore']
}).trim();
return basename(gitRoot);
} catch {
return basename(process.cwd());
}
}
/**
* Find package root directory
*
* Works because bundled hooks are in plugin/scripts/,
* so package root is always two levels up
*/
export function getPackageRoot(): string {
return join(_dirname, '..', '..');
}
/**
* Find commands directory in the installed package
*/
export function getPackageCommandsDir(): string {
const packageRoot = getPackageRoot();
const commandsDir = join(packageRoot, 'commands');
if (!existsSync(join(commandsDir, 'save.md'))) {
throw new Error('Package commands directory missing required files');
}
return commandsDir;
}
/**
* Create a timestamped backup filename
*/
export function createBackupFilename(originalPath: string): string {
const timestamp = new Date()
.toISOString()
.replace(/[:.]/g, '-')
.replace('T', '_')
.slice(0, 19);
return `${originalPath}.backup.${timestamp}`;
}