claude-memory-agent 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +107 -0
- package/README.md +200 -0
- package/agent_card.py +512 -0
- package/bin/cli.js +181 -0
- package/bin/postinstall.js +216 -0
- package/config.py +104 -0
- package/dashboard.html +2689 -0
- package/hooks/README.md +196 -0
- package/hooks/__pycache__/auto-detect-response.cpython-312.pyc +0 -0
- package/hooks/__pycache__/auto_capture.cpython-312.pyc +0 -0
- package/hooks/__pycache__/session_end.cpython-312.pyc +0 -0
- package/hooks/__pycache__/session_start.cpython-312.pyc +0 -0
- package/hooks/auto-detect-response.py +348 -0
- package/hooks/auto_capture.py +255 -0
- package/hooks/detect-correction.py +173 -0
- package/hooks/grounding-hook.py +348 -0
- package/hooks/log-tool-use.py +234 -0
- package/hooks/log-user-request.py +208 -0
- package/hooks/pre-tool-decision.py +218 -0
- package/hooks/problem-detector.py +343 -0
- package/hooks/session_end.py +192 -0
- package/hooks/session_start.py +227 -0
- package/install.py +887 -0
- package/main.py +2859 -0
- package/manager.py +997 -0
- package/package.json +55 -0
- package/requirements.txt +8 -0
- package/run_server.py +136 -0
- package/services/__init__.py +50 -0
- package/services/__pycache__/__init__.cpython-312.pyc +0 -0
- package/services/__pycache__/agent_registry.cpython-312.pyc +0 -0
- package/services/__pycache__/auth.cpython-312.pyc +0 -0
- package/services/__pycache__/auto_inject.cpython-312.pyc +0 -0
- package/services/__pycache__/claude_md_sync.cpython-312.pyc +0 -0
- package/services/__pycache__/cleanup.cpython-312.pyc +0 -0
- package/services/__pycache__/compaction_flush.cpython-312.pyc +0 -0
- package/services/__pycache__/confidence.cpython-312.pyc +0 -0
- package/services/__pycache__/daily_log.cpython-312.pyc +0 -0
- package/services/__pycache__/database.cpython-312.pyc +0 -0
- package/services/__pycache__/embeddings.cpython-312.pyc +0 -0
- package/services/__pycache__/insights.cpython-312.pyc +0 -0
- package/services/__pycache__/llm_analyzer.cpython-312.pyc +0 -0
- package/services/__pycache__/memory_md_sync.cpython-312.pyc +0 -0
- package/services/__pycache__/retry_queue.cpython-312.pyc +0 -0
- package/services/__pycache__/timeline.cpython-312.pyc +0 -0
- package/services/__pycache__/vector_index.cpython-312.pyc +0 -0
- package/services/__pycache__/websocket.cpython-312.pyc +0 -0
- package/services/agent_registry.py +753 -0
- package/services/auth.py +331 -0
- package/services/auto_inject.py +250 -0
- package/services/claude_md_sync.py +275 -0
- package/services/cleanup.py +667 -0
- package/services/compaction_flush.py +447 -0
- package/services/confidence.py +301 -0
- package/services/daily_log.py +333 -0
- package/services/database.py +2485 -0
- package/services/embeddings.py +358 -0
- package/services/insights.py +632 -0
- package/services/llm_analyzer.py +595 -0
- package/services/memory_md_sync.py +409 -0
- package/services/retry_queue.py +453 -0
- package/services/timeline.py +579 -0
- package/services/vector_index.py +398 -0
- package/services/websocket.py +257 -0
- package/skills/__init__.py +6 -0
- package/skills/__pycache__/__init__.cpython-312.pyc +0 -0
- package/skills/__pycache__/admin.cpython-312.pyc +0 -0
- package/skills/__pycache__/checkpoint.cpython-312.pyc +0 -0
- package/skills/__pycache__/claude_md.cpython-312.pyc +0 -0
- package/skills/__pycache__/cleanup.cpython-312.pyc +0 -0
- package/skills/__pycache__/grounding.cpython-312.pyc +0 -0
- package/skills/__pycache__/insights.cpython-312.pyc +0 -0
- package/skills/__pycache__/natural_language.cpython-312.pyc +0 -0
- package/skills/__pycache__/retrieve.cpython-312.pyc +0 -0
- package/skills/__pycache__/search.cpython-312.pyc +0 -0
- package/skills/__pycache__/state.cpython-312.pyc +0 -0
- package/skills/__pycache__/store.cpython-312.pyc +0 -0
- package/skills/__pycache__/summarize.cpython-312.pyc +0 -0
- package/skills/__pycache__/timeline.cpython-312.pyc +0 -0
- package/skills/__pycache__/verification.cpython-312.pyc +0 -0
- package/skills/admin.py +469 -0
- package/skills/checkpoint.py +198 -0
- package/skills/claude_md.py +363 -0
- package/skills/cleanup.py +241 -0
- package/skills/grounding.py +801 -0
- package/skills/insights.py +231 -0
- package/skills/natural_language.py +277 -0
- package/skills/retrieve.py +67 -0
- package/skills/search.py +213 -0
- package/skills/state.py +182 -0
- package/skills/store.py +179 -0
- package/skills/summarize.py +588 -0
- package/skills/timeline.py +387 -0
- package/skills/verification.py +391 -0
- package/start_daemon.py +155 -0
- package/test_automation.py +221 -0
- package/test_complete.py +338 -0
- package/test_full.py +322 -0
- package/update_system.py +817 -0
- package/verify_db.py +134 -0
package/bin/cli.js
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Claude Memory Agent CLI
|
|
5
|
+
*
|
|
6
|
+
* This is the npm entry point that wraps the Python CLI.
|
|
7
|
+
* Usage:
|
|
8
|
+
* claude-memory-agent install - Run installation wizard
|
|
9
|
+
* claude-memory-agent start - Start the agent
|
|
10
|
+
* claude-memory-agent stop - Stop the agent
|
|
11
|
+
* claude-memory-agent status - Check status
|
|
12
|
+
* claude-memory-agent dashboard - Open dashboard
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const { spawn, execSync } = require('child_process');
|
|
16
|
+
const path = require('path');
|
|
17
|
+
const fs = require('fs');
|
|
18
|
+
|
|
19
|
+
const AGENT_DIR = path.dirname(__dirname);
|
|
20
|
+
const args = process.argv.slice(2);
|
|
21
|
+
const command = args[0] || 'help';
|
|
22
|
+
|
|
23
|
+
// Check Python availability
|
|
24
|
+
function getPython() {
|
|
25
|
+
const pythonCommands = ['python3', 'python', 'py'];
|
|
26
|
+
|
|
27
|
+
for (const cmd of pythonCommands) {
|
|
28
|
+
try {
|
|
29
|
+
const result = execSync(`${cmd} --version`, {
|
|
30
|
+
encoding: 'utf8',
|
|
31
|
+
stdio: ['pipe', 'pipe', 'pipe']
|
|
32
|
+
});
|
|
33
|
+
if (result.includes('Python 3')) {
|
|
34
|
+
return cmd;
|
|
35
|
+
}
|
|
36
|
+
} catch (e) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Check if Python dependencies are installed
|
|
44
|
+
function checkDependencies(python) {
|
|
45
|
+
try {
|
|
46
|
+
execSync(`${python} -c "import fastapi, uvicorn, dotenv"`, {
|
|
47
|
+
cwd: AGENT_DIR,
|
|
48
|
+
stdio: ['pipe', 'pipe', 'pipe']
|
|
49
|
+
});
|
|
50
|
+
return true;
|
|
51
|
+
} catch (e) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Install Python dependencies
|
|
57
|
+
function installDependencies(python) {
|
|
58
|
+
console.log('Installing Python dependencies...');
|
|
59
|
+
try {
|
|
60
|
+
execSync(`${python} -m pip install -r requirements.txt -q`, {
|
|
61
|
+
cwd: AGENT_DIR,
|
|
62
|
+
stdio: 'inherit'
|
|
63
|
+
});
|
|
64
|
+
return true;
|
|
65
|
+
} catch (e) {
|
|
66
|
+
console.error('Failed to install dependencies:', e.message);
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Run Python script
|
|
72
|
+
function runPython(script, scriptArgs = []) {
|
|
73
|
+
const python = getPython();
|
|
74
|
+
|
|
75
|
+
if (!python) {
|
|
76
|
+
console.error('Error: Python 3 is required but not found.');
|
|
77
|
+
console.error('Please install Python 3.9+ from https://python.org/');
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const proc = spawn(python, [script, ...scriptArgs], {
|
|
82
|
+
cwd: AGENT_DIR,
|
|
83
|
+
stdio: 'inherit',
|
|
84
|
+
shell: process.platform === 'win32'
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
proc.on('close', (code) => {
|
|
88
|
+
process.exit(code || 0);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
proc.on('error', (err) => {
|
|
92
|
+
console.error('Failed to start:', err.message);
|
|
93
|
+
process.exit(1);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Print help
|
|
98
|
+
function printHelp() {
|
|
99
|
+
console.log(`
|
|
100
|
+
Claude Memory Agent v2.0.0
|
|
101
|
+
Persistent semantic memory for Claude Code sessions
|
|
102
|
+
|
|
103
|
+
USAGE:
|
|
104
|
+
claude-memory-agent <command> [options]
|
|
105
|
+
|
|
106
|
+
COMMANDS:
|
|
107
|
+
install Run the installation wizard
|
|
108
|
+
start Start the memory agent in background
|
|
109
|
+
stop Stop the running agent
|
|
110
|
+
status Check if agent is running
|
|
111
|
+
dashboard Open the web dashboard
|
|
112
|
+
logs Show recent log output
|
|
113
|
+
help Show this help message
|
|
114
|
+
|
|
115
|
+
QUICK START:
|
|
116
|
+
1. claude-memory-agent install # Configure everything
|
|
117
|
+
2. claude-memory-agent start # Start the agent
|
|
118
|
+
3. claude-memory-agent dashboard # Open web UI
|
|
119
|
+
|
|
120
|
+
REQUIREMENTS:
|
|
121
|
+
- Python 3.9+
|
|
122
|
+
- Ollama with nomic-embed-text model (for embeddings)
|
|
123
|
+
- Claude Code (for full integration)
|
|
124
|
+
|
|
125
|
+
For more info: https://github.com/yourusername/claude-memory-agent
|
|
126
|
+
`);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Main
|
|
130
|
+
function main() {
|
|
131
|
+
switch (command) {
|
|
132
|
+
case 'install':
|
|
133
|
+
case 'setup':
|
|
134
|
+
runPython('install.py', args.slice(1));
|
|
135
|
+
break;
|
|
136
|
+
|
|
137
|
+
case 'start':
|
|
138
|
+
runPython('memory-agent', ['start', ...args.slice(1)]);
|
|
139
|
+
break;
|
|
140
|
+
|
|
141
|
+
case 'stop':
|
|
142
|
+
runPython('memory-agent', ['stop', ...args.slice(1)]);
|
|
143
|
+
break;
|
|
144
|
+
|
|
145
|
+
case 'status':
|
|
146
|
+
runPython('memory-agent', ['status', ...args.slice(1)]);
|
|
147
|
+
break;
|
|
148
|
+
|
|
149
|
+
case 'dashboard':
|
|
150
|
+
runPython('memory-agent', ['dashboard', ...args.slice(1)]);
|
|
151
|
+
break;
|
|
152
|
+
|
|
153
|
+
case 'logs':
|
|
154
|
+
runPython('memory-agent', ['logs', ...args.slice(1)]);
|
|
155
|
+
break;
|
|
156
|
+
|
|
157
|
+
case 'run':
|
|
158
|
+
case 'server':
|
|
159
|
+
// Run directly (not in background)
|
|
160
|
+
runPython('main.py', args.slice(1));
|
|
161
|
+
break;
|
|
162
|
+
|
|
163
|
+
case 'help':
|
|
164
|
+
case '--help':
|
|
165
|
+
case '-h':
|
|
166
|
+
printHelp();
|
|
167
|
+
break;
|
|
168
|
+
|
|
169
|
+
case '--version':
|
|
170
|
+
case '-v':
|
|
171
|
+
console.log('claude-memory-agent v2.0.0');
|
|
172
|
+
break;
|
|
173
|
+
|
|
174
|
+
default:
|
|
175
|
+
console.error(`Unknown command: ${command}`);
|
|
176
|
+
console.error('Run "claude-memory-agent help" for usage.');
|
|
177
|
+
process.exit(1);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
main();
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Post-installation script for Claude Memory Agent
|
|
5
|
+
*
|
|
6
|
+
* This runs automatically after npm install to:
|
|
7
|
+
* 1. Check Python availability
|
|
8
|
+
* 2. Install Python dependencies
|
|
9
|
+
* 3. Run the configuration wizard (if interactive)
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const { execSync, spawn } = require('child_process');
|
|
13
|
+
const path = require('path');
|
|
14
|
+
const fs = require('fs');
|
|
15
|
+
const readline = require('readline');
|
|
16
|
+
|
|
17
|
+
const AGENT_DIR = path.dirname(__dirname);
|
|
18
|
+
|
|
19
|
+
// Colors for terminal output
|
|
20
|
+
const colors = {
|
|
21
|
+
reset: '\x1b[0m',
|
|
22
|
+
green: '\x1b[32m',
|
|
23
|
+
yellow: '\x1b[33m',
|
|
24
|
+
red: '\x1b[31m',
|
|
25
|
+
cyan: '\x1b[36m',
|
|
26
|
+
bold: '\x1b[1m'
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
function log(msg) {
|
|
30
|
+
console.log(msg);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function success(msg) {
|
|
34
|
+
console.log(`${colors.green}✓${colors.reset} ${msg}`);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function warn(msg) {
|
|
38
|
+
console.log(`${colors.yellow}!${colors.reset} ${msg}`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function error(msg) {
|
|
42
|
+
console.log(`${colors.red}✗${colors.reset} ${msg}`);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function header(msg) {
|
|
46
|
+
console.log(`\n${colors.bold}${colors.cyan}${msg}${colors.reset}\n`);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Check Python availability
|
|
50
|
+
function getPython() {
|
|
51
|
+
const pythonCommands = ['python3', 'python', 'py'];
|
|
52
|
+
|
|
53
|
+
for (const cmd of pythonCommands) {
|
|
54
|
+
try {
|
|
55
|
+
const result = execSync(`${cmd} --version`, {
|
|
56
|
+
encoding: 'utf8',
|
|
57
|
+
stdio: ['pipe', 'pipe', 'pipe']
|
|
58
|
+
});
|
|
59
|
+
const match = result.match(/Python (\d+)\.(\d+)/);
|
|
60
|
+
if (match) {
|
|
61
|
+
const major = parseInt(match[1]);
|
|
62
|
+
const minor = parseInt(match[2]);
|
|
63
|
+
if (major >= 3 && minor >= 9) {
|
|
64
|
+
return { cmd, version: result.trim() };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
} catch (e) {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Check if Ollama is running
|
|
75
|
+
function checkOllama() {
|
|
76
|
+
try {
|
|
77
|
+
const http = require('http');
|
|
78
|
+
return new Promise((resolve) => {
|
|
79
|
+
const req = http.get('http://localhost:11434/api/tags', { timeout: 2000 }, (res) => {
|
|
80
|
+
resolve(res.statusCode === 200);
|
|
81
|
+
});
|
|
82
|
+
req.on('error', () => resolve(false));
|
|
83
|
+
req.on('timeout', () => {
|
|
84
|
+
req.destroy();
|
|
85
|
+
resolve(false);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
} catch (e) {
|
|
89
|
+
return Promise.resolve(false);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Install Python dependencies
|
|
94
|
+
function installPythonDeps(python) {
|
|
95
|
+
const requirementsPath = path.join(AGENT_DIR, 'requirements.txt');
|
|
96
|
+
|
|
97
|
+
if (!fs.existsSync(requirementsPath)) {
|
|
98
|
+
warn('requirements.txt not found, skipping Python dependencies');
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
log('Installing Python dependencies...');
|
|
103
|
+
try {
|
|
104
|
+
execSync(`${python} -m pip install -r requirements.txt -q --disable-pip-version-check`, {
|
|
105
|
+
cwd: AGENT_DIR,
|
|
106
|
+
stdio: ['pipe', 'pipe', 'pipe']
|
|
107
|
+
});
|
|
108
|
+
success('Python dependencies installed');
|
|
109
|
+
return true;
|
|
110
|
+
} catch (e) {
|
|
111
|
+
error('Failed to install Python dependencies');
|
|
112
|
+
console.log(' Run manually: pip install -r requirements.txt');
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Create .env file if it doesn't exist
|
|
118
|
+
function createEnvFile() {
|
|
119
|
+
const envPath = path.join(AGENT_DIR, '.env');
|
|
120
|
+
const examplePath = path.join(AGENT_DIR, '.env.example');
|
|
121
|
+
|
|
122
|
+
if (fs.existsSync(envPath)) {
|
|
123
|
+
success('.env file already exists');
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Create basic .env
|
|
128
|
+
const envContent = `# Claude Memory Agent Configuration
|
|
129
|
+
# Generated during npm install
|
|
130
|
+
|
|
131
|
+
# Server
|
|
132
|
+
PORT=8102
|
|
133
|
+
HOST=0.0.0.0
|
|
134
|
+
MEMORY_AGENT_URL=http://localhost:8102
|
|
135
|
+
|
|
136
|
+
# Ollama
|
|
137
|
+
OLLAMA_HOST=http://localhost:11434
|
|
138
|
+
EMBEDDING_MODEL=nomic-embed-text
|
|
139
|
+
|
|
140
|
+
# Database (relative to agent directory)
|
|
141
|
+
DATABASE_PATH=${path.join(AGENT_DIR, 'memories.db').replace(/\\/g, '/')}
|
|
142
|
+
|
|
143
|
+
# Logging
|
|
144
|
+
LOG_LEVEL=INFO
|
|
145
|
+
`;
|
|
146
|
+
|
|
147
|
+
try {
|
|
148
|
+
fs.writeFileSync(envPath, envContent);
|
|
149
|
+
success('Created .env configuration file');
|
|
150
|
+
return true;
|
|
151
|
+
} catch (e) {
|
|
152
|
+
warn('Could not create .env file');
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Main installation
|
|
158
|
+
async function main() {
|
|
159
|
+
header('Claude Memory Agent - Post-Installation Setup');
|
|
160
|
+
|
|
161
|
+
// Check Python
|
|
162
|
+
log('Checking Python...');
|
|
163
|
+
const python = getPython();
|
|
164
|
+
if (!python) {
|
|
165
|
+
error('Python 3.9+ is required but not found');
|
|
166
|
+
console.log('\n Please install Python from https://python.org/');
|
|
167
|
+
console.log(' Then run: claude-memory-agent install\n');
|
|
168
|
+
process.exit(1);
|
|
169
|
+
}
|
|
170
|
+
success(`Found ${python.version}`);
|
|
171
|
+
|
|
172
|
+
// Install Python dependencies
|
|
173
|
+
installPythonDeps(python.cmd);
|
|
174
|
+
|
|
175
|
+
// Create .env file
|
|
176
|
+
createEnvFile();
|
|
177
|
+
|
|
178
|
+
// Check Ollama (non-blocking)
|
|
179
|
+
log('Checking Ollama...');
|
|
180
|
+
const ollamaRunning = await checkOllama();
|
|
181
|
+
if (ollamaRunning) {
|
|
182
|
+
success('Ollama is running');
|
|
183
|
+
} else {
|
|
184
|
+
warn('Ollama not detected - embeddings require Ollama');
|
|
185
|
+
console.log(' Install from: https://ollama.ai/');
|
|
186
|
+
console.log(' Then run: ollama pull nomic-embed-text');
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Print next steps
|
|
190
|
+
header('Installation Complete!');
|
|
191
|
+
console.log('Next steps:');
|
|
192
|
+
console.log('');
|
|
193
|
+
console.log(' 1. Run the setup wizard:');
|
|
194
|
+
console.log(' claude-memory-agent install');
|
|
195
|
+
console.log('');
|
|
196
|
+
console.log(' 2. Start the agent:');
|
|
197
|
+
console.log(' claude-memory-agent start');
|
|
198
|
+
console.log('');
|
|
199
|
+
console.log(' 3. Open the dashboard:');
|
|
200
|
+
console.log(' claude-memory-agent dashboard');
|
|
201
|
+
console.log('');
|
|
202
|
+
|
|
203
|
+
if (!ollamaRunning) {
|
|
204
|
+
console.log(' For embeddings, install and start Ollama:');
|
|
205
|
+
console.log(' ollama pull nomic-embed-text');
|
|
206
|
+
console.log(' ollama serve');
|
|
207
|
+
console.log('');
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Run if not in CI/CD environment
|
|
212
|
+
if (!process.env.CI && !process.env.npm_config_ignore_scripts) {
|
|
213
|
+
main().catch(console.error);
|
|
214
|
+
} else {
|
|
215
|
+
console.log('Skipping post-install in CI environment');
|
|
216
|
+
}
|
package/config.py
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Centralized configuration for Claude Memory Agent.
|
|
3
|
+
|
|
4
|
+
All configuration is loaded from environment variables with sensible defaults.
|
|
5
|
+
Use .env file for local overrides (not committed to git).
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
from config import config
|
|
9
|
+
print(config.PORT)
|
|
10
|
+
print(config.MEMORY_AGENT_URL)
|
|
11
|
+
"""
|
|
12
|
+
import os
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from typing import Optional
|
|
15
|
+
from dotenv import load_dotenv
|
|
16
|
+
|
|
17
|
+
# Load .env from agent directory
|
|
18
|
+
AGENT_DIR = Path(__file__).parent.resolve()
|
|
19
|
+
load_dotenv(AGENT_DIR / ".env")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class Config:
|
|
23
|
+
"""Configuration singleton with environment variable loading."""
|
|
24
|
+
|
|
25
|
+
def __init__(self):
|
|
26
|
+
# Paths (auto-detected from script location)
|
|
27
|
+
self.AGENT_DIR = AGENT_DIR
|
|
28
|
+
self.DATABASE_PATH = Path(os.getenv(
|
|
29
|
+
"DATABASE_PATH",
|
|
30
|
+
str(AGENT_DIR / "memories.db")
|
|
31
|
+
))
|
|
32
|
+
self.INDEX_DIR = Path(os.getenv(
|
|
33
|
+
"INDEX_DIR",
|
|
34
|
+
str(AGENT_DIR / "indexes")
|
|
35
|
+
))
|
|
36
|
+
self.LOG_FILE = AGENT_DIR / "memory-agent.log"
|
|
37
|
+
self.LOCK_FILE = AGENT_DIR / "memory-agent.lock"
|
|
38
|
+
self.PID_FILE = AGENT_DIR / "memory-agent.pid"
|
|
39
|
+
|
|
40
|
+
# Server configuration
|
|
41
|
+
self.HOST = os.getenv("HOST", "0.0.0.0")
|
|
42
|
+
self.PORT = int(os.getenv("PORT", "8102"))
|
|
43
|
+
self.MEMORY_AGENT_URL = os.getenv(
|
|
44
|
+
"MEMORY_AGENT_URL",
|
|
45
|
+
f"http://localhost:{self.PORT}"
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
# Ollama / Embeddings
|
|
49
|
+
self.OLLAMA_HOST = os.getenv("OLLAMA_HOST", "http://localhost:11434")
|
|
50
|
+
self.EMBEDDING_MODEL = os.getenv("EMBEDDING_MODEL", "nomic-embed-text")
|
|
51
|
+
self.EMBEDDING_DIM = int(os.getenv("EMBEDDING_DIM", "768"))
|
|
52
|
+
self.OLLAMA_HEALTH_TIMEOUT = float(os.getenv("OLLAMA_HEALTH_TIMEOUT", "2.0"))
|
|
53
|
+
self.OLLAMA_HEALTH_CACHE_TTL = float(os.getenv("OLLAMA_HEALTH_CACHE_TTL", "30.0"))
|
|
54
|
+
|
|
55
|
+
# Database
|
|
56
|
+
self.USE_VECTOR_INDEX = os.getenv("USE_VECTOR_INDEX", "true").lower() == "true"
|
|
57
|
+
self.DB_POOL_SIZE = int(os.getenv("DB_POOL_SIZE", "5"))
|
|
58
|
+
self.DB_TIMEOUT = float(os.getenv("DB_TIMEOUT", "30.0"))
|
|
59
|
+
self.DB_MAX_RETRIES = int(os.getenv("DB_MAX_RETRIES", "3"))
|
|
60
|
+
self.DB_RETRY_BASE_DELAY = float(os.getenv("DB_RETRY_BASE_DELAY", "0.1"))
|
|
61
|
+
|
|
62
|
+
# Authentication
|
|
63
|
+
self.AUTH_ENABLED = os.getenv("AUTH_ENABLED", "false").lower() == "true"
|
|
64
|
+
self.AUTH_KEY_FILE = Path(os.getenv(
|
|
65
|
+
"AUTH_KEY_FILE",
|
|
66
|
+
str(Path.home() / ".claude" / "memory-agent-keys.json")
|
|
67
|
+
))
|
|
68
|
+
self.AUTH_RATE_LIMIT = int(os.getenv("AUTH_RATE_LIMIT", "100"))
|
|
69
|
+
self.AUTH_RATE_WINDOW = int(os.getenv("AUTH_RATE_WINDOW", "60"))
|
|
70
|
+
|
|
71
|
+
# Logging
|
|
72
|
+
self.LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO")
|
|
73
|
+
|
|
74
|
+
# Hook timeouts
|
|
75
|
+
self.API_TIMEOUT = int(os.getenv("API_TIMEOUT", "30"))
|
|
76
|
+
|
|
77
|
+
def get_health_url(self) -> str:
|
|
78
|
+
"""Get the health check URL."""
|
|
79
|
+
return f"{self.MEMORY_AGENT_URL}/health"
|
|
80
|
+
|
|
81
|
+
def get_dashboard_url(self) -> str:
|
|
82
|
+
"""Get the dashboard URL."""
|
|
83
|
+
return f"{self.MEMORY_AGENT_URL}/dashboard"
|
|
84
|
+
|
|
85
|
+
def to_dict(self) -> dict:
|
|
86
|
+
"""Export configuration as dictionary (for debugging)."""
|
|
87
|
+
return {
|
|
88
|
+
key: str(value) if isinstance(value, Path) else value
|
|
89
|
+
for key, value in vars(self).items()
|
|
90
|
+
if not key.startswith("_")
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
# Singleton instance
|
|
95
|
+
config = Config()
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
# Convenience exports for backwards compatibility
|
|
99
|
+
PORT = config.PORT
|
|
100
|
+
HOST = config.HOST
|
|
101
|
+
MEMORY_AGENT_URL = config.MEMORY_AGENT_URL
|
|
102
|
+
OLLAMA_HOST = config.OLLAMA_HOST
|
|
103
|
+
EMBEDDING_MODEL = config.EMBEDDING_MODEL
|
|
104
|
+
DATABASE_PATH = config.DATABASE_PATH
|