fix: Windows platform improvements — re-enable Chroma, fix DB race, simplify env isolation
1. ProcessManager: Migrate spawnDaemon() from WMIC to PowerShell Start-Process - WMIC deprecated in Windows 11, PowerShell inherits env vars properly - Use -WindowStyle Hidden to prevent console popups - Fix redundant backslash escaping in PowerShell $_ variables 2. ChromaSync: Re-enable vector search on Windows - Remove overly defensive platform check that disabled all semantic search - Worker daemon starts with -WindowStyle Hidden; child processes inherit - MCP SDK's StdioClientTransport uses shell:false, no new console created 3. worker-service: Unified DB-ready gate middleware - Replace single-endpoint /api/sessions/init wait with global middleware - Hold all DB-dependent requests until database is initialized (30s timeout) - Whitelist static assets, /health, and viewer page for immediate response - Separate dbReadyPromise (DB only) from initializationComplete (full init) - Fixes "Database not initialized" errors on /stream, /summarize, /init 4. EnvManager: Switch from allowlist to blocklist for subprocess env - Only strip ANTHROPIC_API_KEY to prevent Issue #733 billing hijack - Pass through all other vars (ANTHROPIC_AUTH_TOKEN, ANTHROPIC_BASE_URL, etc.) - Simpler, less fragile than maintaining an exhaustive system vars allowlist
This commit is contained in:
+29
-42
@@ -18,33 +18,15 @@ import { logger } from '../utils/logger.js';
|
||||
const DATA_DIR = join(homedir(), '.claude-mem');
|
||||
export const ENV_FILE_PATH = join(DATA_DIR, '.env');
|
||||
|
||||
// Essential system environment variables that subprocesses need to function
|
||||
const ESSENTIAL_SYSTEM_VARS = [
|
||||
'PATH',
|
||||
'HOME',
|
||||
'USER',
|
||||
'SHELL',
|
||||
'TMPDIR',
|
||||
'TMP',
|
||||
'TEMP',
|
||||
'LANG',
|
||||
'LC_ALL',
|
||||
'LC_CTYPE',
|
||||
// Node.js specific
|
||||
'NODE_ENV',
|
||||
'NODE_PATH',
|
||||
// Platform specific
|
||||
'SYSTEMROOT', // Windows
|
||||
'WINDIR', // Windows
|
||||
'PROGRAMFILES', // Windows
|
||||
'APPDATA', // Windows
|
||||
'LOCALAPPDATA', // Windows
|
||||
'XDG_RUNTIME_DIR', // Linux
|
||||
'XDG_CONFIG_HOME', // Linux
|
||||
'XDG_DATA_HOME', // Linux
|
||||
// Claude Code specific (not credentials)
|
||||
'CLAUDE_CONFIG_DIR',
|
||||
'CLAUDE_CODE_DEBUG_LOGS_DIR',
|
||||
// Environment variables to STRIP from subprocess environment (blocklist approach)
|
||||
// Only ANTHROPIC_API_KEY is stripped because it's the specific variable that causes
|
||||
// Issue #733: project .env files set ANTHROPIC_API_KEY which the SDK auto-discovers,
|
||||
// causing memory operations to bill personal API accounts instead of CLI subscription.
|
||||
//
|
||||
// All other env vars (ANTHROPIC_AUTH_TOKEN, ANTHROPIC_BASE_URL, system vars, etc.)
|
||||
// are passed through to avoid breaking CLI authentication, proxies, and platform features.
|
||||
const BLOCKED_ENV_VARS = [
|
||||
'ANTHROPIC_API_KEY', // Issue #733: Prevent auto-discovery from project .env files
|
||||
];
|
||||
|
||||
// Credential keys that claude-mem manages
|
||||
@@ -191,39 +173,44 @@ export function saveClaudeMemEnv(env: ClaudeMemEnv): void {
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a clean, isolated environment for spawning SDK subprocesses
|
||||
* Build a clean environment for spawning SDK subprocesses
|
||||
*
|
||||
* This is the key function that prevents Issue #733:
|
||||
* - Includes only essential system variables (PATH, HOME, etc.)
|
||||
* - Adds credentials ONLY from claude-mem's .env file
|
||||
* - Does NOT inherit random ANTHROPIC_API_KEY from user's shell
|
||||
* Uses a BLOCKLIST approach: inherits the full process environment but strips
|
||||
* only ANTHROPIC_API_KEY to prevent Issue #733 (accidental billing from project .env files).
|
||||
*
|
||||
* @param includeCredentials - Whether to include API keys (default: true)
|
||||
* All other variables pass through, including:
|
||||
* - ANTHROPIC_AUTH_TOKEN (CLI subscription auth)
|
||||
* - ANTHROPIC_BASE_URL (custom proxy endpoints)
|
||||
* - Platform-specific vars (USERPROFILE, XDG_*, etc.)
|
||||
*
|
||||
* If claude-mem has an explicit ANTHROPIC_API_KEY in ~/.claude-mem/.env, it's re-injected
|
||||
* after stripping, so the managed credential takes precedence over any ambient value.
|
||||
*
|
||||
* @param includeCredentials - Whether to include API keys from ~/.claude-mem/.env (default: true)
|
||||
*/
|
||||
export function buildIsolatedEnv(includeCredentials: boolean = true): Record<string, string> {
|
||||
// 1. Start with full process environment
|
||||
const isolatedEnv: Record<string, string> = {};
|
||||
|
||||
// 1. Copy essential system variables from current process
|
||||
for (const key of ESSENTIAL_SYSTEM_VARS) {
|
||||
const value = process.env[key];
|
||||
if (value !== undefined) {
|
||||
for (const [key, value] of Object.entries(process.env)) {
|
||||
if (value !== undefined && !BLOCKED_ENV_VARS.includes(key)) {
|
||||
isolatedEnv[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Add SDK entrypoint marker
|
||||
// 2. Override SDK entrypoint marker
|
||||
isolatedEnv.CLAUDE_CODE_ENTRYPOINT = 'sdk-ts';
|
||||
|
||||
// 3. Add credentials from claude-mem's .env file (NOT from process.env)
|
||||
// 3. Re-inject managed credentials from claude-mem's .env file
|
||||
if (includeCredentials) {
|
||||
const credentials = loadClaudeMemEnv();
|
||||
|
||||
// Only add ANTHROPIC_API_KEY if explicitly configured in claude-mem
|
||||
// If not configured, CLI billing will be used (via pathToClaudeCodeExecutable)
|
||||
// If not configured, CLI billing will be used (via ANTHROPIC_AUTH_TOKEN passthrough)
|
||||
if (credentials.ANTHROPIC_API_KEY) {
|
||||
isolatedEnv.ANTHROPIC_API_KEY = credentials.ANTHROPIC_API_KEY;
|
||||
}
|
||||
// Note: GEMINI_API_KEY and OPENROUTER_API_KEY are handled by their respective agents
|
||||
// Note: GEMINI_API_KEY and OPENROUTER_API_KEY pass through from process.env,
|
||||
// but claude-mem's .env takes precedence if configured
|
||||
if (credentials.GEMINI_API_KEY) {
|
||||
isolatedEnv.GEMINI_API_KEY = credentials.GEMINI_API_KEY;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user