Refactor SettingsDefaultsManager: Move to shared directory and update imports

- Moved SettingsDefaultsManager from worker/settings to shared directory.
- Updated all import paths across the codebase to reflect the new location.
- Removed early-settings.ts as its functionality is now handled by SettingsDefaultsManager.
- Adjusted logger and paths to utilize SettingsDefaultsManager for configuration values.
This commit is contained in:
Alex Newman
2025-12-09 15:29:17 -05:00
parent c3761a2204
commit 005a80c540
21 changed files with 205 additions and 275 deletions
+121
View File
@@ -0,0 +1,121 @@
/**
* SettingsDefaultsManager
*
* Single source of truth for all default configuration values.
* Provides methods to get defaults with optional environment variable overrides.
*/
import { readFileSync, existsSync } from 'fs';
import { join } from 'path';
import { homedir } from 'os';
import { DEFAULT_OBSERVATION_TYPES_STRING, DEFAULT_OBSERVATION_CONCEPTS_STRING } from '../constants/observation-metadata.js';
export interface SettingsDefaults {
CLAUDE_MEM_MODEL: string;
CLAUDE_MEM_CONTEXT_OBSERVATIONS: string;
CLAUDE_MEM_WORKER_PORT: string;
// System Configuration
CLAUDE_MEM_DATA_DIR: string;
CLAUDE_MEM_LOG_LEVEL: string;
CLAUDE_MEM_PYTHON_VERSION: string;
CLAUDE_CODE_PATH: string;
// Token Economics
CLAUDE_MEM_CONTEXT_SHOW_READ_TOKENS: string;
CLAUDE_MEM_CONTEXT_SHOW_WORK_TOKENS: string;
CLAUDE_MEM_CONTEXT_SHOW_SAVINGS_AMOUNT: string;
CLAUDE_MEM_CONTEXT_SHOW_SAVINGS_PERCENT: string;
// Observation Filtering
CLAUDE_MEM_CONTEXT_OBSERVATION_TYPES: string;
CLAUDE_MEM_CONTEXT_OBSERVATION_CONCEPTS: string;
// Display Configuration
CLAUDE_MEM_CONTEXT_FULL_COUNT: string;
CLAUDE_MEM_CONTEXT_FULL_FIELD: string;
CLAUDE_MEM_CONTEXT_SESSION_COUNT: string;
// Feature Toggles
CLAUDE_MEM_CONTEXT_SHOW_LAST_SUMMARY: string;
CLAUDE_MEM_CONTEXT_SHOW_LAST_MESSAGE: string;
}
export class SettingsDefaultsManager {
/**
* Default values for all settings
*/
private static readonly DEFAULTS: SettingsDefaults = {
CLAUDE_MEM_MODEL: 'claude-haiku-4-5',
CLAUDE_MEM_CONTEXT_OBSERVATIONS: '50',
CLAUDE_MEM_WORKER_PORT: '37777',
// System Configuration
CLAUDE_MEM_DATA_DIR: join(homedir(), '.claude-mem'),
CLAUDE_MEM_LOG_LEVEL: 'INFO',
CLAUDE_MEM_PYTHON_VERSION: '3.13',
CLAUDE_CODE_PATH: '', // Empty means auto-detect via 'which claude'
// Token Economics
CLAUDE_MEM_CONTEXT_SHOW_READ_TOKENS: 'true',
CLAUDE_MEM_CONTEXT_SHOW_WORK_TOKENS: 'true',
CLAUDE_MEM_CONTEXT_SHOW_SAVINGS_AMOUNT: 'true',
CLAUDE_MEM_CONTEXT_SHOW_SAVINGS_PERCENT: 'true',
// Observation Filtering
CLAUDE_MEM_CONTEXT_OBSERVATION_TYPES: DEFAULT_OBSERVATION_TYPES_STRING,
CLAUDE_MEM_CONTEXT_OBSERVATION_CONCEPTS: DEFAULT_OBSERVATION_CONCEPTS_STRING,
// Display Configuration
CLAUDE_MEM_CONTEXT_FULL_COUNT: '5',
CLAUDE_MEM_CONTEXT_FULL_FIELD: 'narrative',
CLAUDE_MEM_CONTEXT_SESSION_COUNT: '10',
// Feature Toggles
CLAUDE_MEM_CONTEXT_SHOW_LAST_SUMMARY: 'true',
CLAUDE_MEM_CONTEXT_SHOW_LAST_MESSAGE: 'false',
};
/**
* Get all defaults as an object
*/
static getAllDefaults(): SettingsDefaults {
return { ...this.DEFAULTS };
}
/**
* Get a default value from defaults (no environment variable override)
*/
static get(key: keyof SettingsDefaults): string {
return this.DEFAULTS[key];
}
/**
* Get an integer default value
*/
static getInt(key: keyof SettingsDefaults): number {
const value = this.get(key);
return parseInt(value, 10);
}
/**
* Get a boolean default value
*/
static getBool(key: keyof SettingsDefaults): boolean {
const value = this.get(key);
return value === 'true';
}
/**
* Load settings from file with fallback to defaults
* Returns merged settings with defaults as fallback
*/
static loadFromFile(settingsPath: string): SettingsDefaults {
if (!existsSync(settingsPath)) {
return this.getAllDefaults();
}
const settingsData = readFileSync(settingsPath, 'utf-8');
const settings = JSON.parse(settingsData);
// Merge file settings with defaults (flat schema, no env wrapper)
const result: SettingsDefaults = { ...this.DEFAULTS };
for (const key of Object.keys(this.DEFAULTS) as Array<keyof SettingsDefaults>) {
if (settings[key] !== undefined) {
result[key] = settings[key];
}
}
return result;
}
}
-32
View File
@@ -1,32 +0,0 @@
import { join } from 'path';
import { homedir } from 'os';
import { existsSync, readFileSync } from 'fs';
import { happy_path_error__with_fallback } from '../utils/silent-debug.js';
const SETTINGS_PATH = join(homedir(), '.claude-mem', 'settings.json');
interface EarlySettings {
CLAUDE_MEM_DATA_DIR?: string;
CLAUDE_MEM_LOG_LEVEL?: string;
CLAUDE_MEM_PYTHON_VERSION?: string;
CLAUDE_CODE_PATH?: string;
}
/**
* Load settings for early-stage modules (paths, logger)
* Falls back to env vars, then defaults
*/
export function loadEarlySetting(key: keyof EarlySettings, defaultValue: string): string {
// Priority: settings.json > env var > default
try {
if (existsSync(SETTINGS_PATH)) {
const data = JSON.parse(readFileSync(SETTINGS_PATH, 'utf-8'));
const fileValue = data.env?.[key];
if (fileValue !== undefined) return fileValue;
}
} catch (error) {
happy_path_error__with_fallback('Failed to load settings file', { error, settingsPath: SETTINGS_PATH, key });
}
return process.env[key] || defaultValue;
}
+2 -2
View File
@@ -3,7 +3,7 @@ import { homedir } from 'os';
import { existsSync, mkdirSync } from 'fs';
import { execSync } from 'child_process';
import { fileURLToPath } from 'url';
import { loadEarlySetting } from './early-settings.js';
import { SettingsDefaultsManager } from './SettingsDefaultsManager.js';
// Get __dirname that works in both ESM (hooks) and CJS (worker) contexts
function getDirname(): string {
@@ -23,7 +23,7 @@ const _dirname = getDirname();
*/
// Base directories
export const DATA_DIR = loadEarlySetting('CLAUDE_MEM_DATA_DIR', join(homedir(), '.claude-mem'));
export const DATA_DIR = SettingsDefaultsManager.get('CLAUDE_MEM_DATA_DIR');
// Note: CLAUDE_CONFIG_DIR is a Claude Code setting, not claude-mem, so leave as env var
export const CLAUDE_CONFIG_DIR = process.env.CLAUDE_CONFIG_DIR || join(homedir(), '.claude');
+1 -1
View File
@@ -2,7 +2,7 @@ import path from "path";
import { existsSync } from "fs";
import { homedir } from "os";
import { spawnSync } from "child_process";
import { SettingsDefaultsManager } from "../services/worker/settings/SettingsDefaultsManager.js";
import { SettingsDefaultsManager } from "./SettingsDefaultsManager.js";
import { logger } from "../utils/logger.js";
import { HOOK_TIMEOUTS, getTimeout } from "./hook-constants.js";