@jungjaehoon/mama-server 1.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/package.json +53 -0
- package/src/mama/config-loader.js +218 -0
- package/src/mama/db-adapter/README.md +105 -0
- package/src/mama/db-adapter/base-adapter.js +91 -0
- package/src/mama/db-adapter/index.js +31 -0
- package/src/mama/db-adapter/sqlite-adapter.js +342 -0
- package/src/mama/db-adapter/statement.js +127 -0
- package/src/mama/db-manager.js +584 -0
- package/src/mama/debug-logger.js +78 -0
- package/src/mama/decision-formatter.js +1180 -0
- package/src/mama/decision-tracker.js +565 -0
- package/src/mama/embedding-cache.js +221 -0
- package/src/mama/embeddings.js +265 -0
- package/src/mama/hook-metrics.js +403 -0
- package/src/mama/mama-api.js +913 -0
- package/src/mama/memory-inject.js +243 -0
- package/src/mama/memory-store.js +89 -0
- package/src/mama/ollama-client.js +387 -0
- package/src/mama/outcome-tracker.js +349 -0
- package/src/mama/query-intent.js +236 -0
- package/src/mama/relevance-scorer.js +283 -0
- package/src/mama/time-formatter.js +82 -0
- package/src/mama/transparency-banner.js +301 -0
- package/src/server.js +290 -0
- package/src/tools/checkpoint-tools.js +76 -0
- package/src/tools/index.js +54 -0
- package/src/tools/list-decisions.js +76 -0
- package/src/tools/recall-decision.js +75 -0
- package/src/tools/save-decision.js +113 -0
- package/src/tools/suggest-decision.js +84 -0
- package/src/tools/update-outcome.js +128 -0
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@jungjaehoon/mama-server",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "MAMA MCP Server - Memory-Augmented MCP Assistant for Claude Code & Desktop",
|
|
5
|
+
"main": "src/server.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"mama-server": "src/server.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"start": "node src/server.js",
|
|
11
|
+
"test": "vitest run",
|
|
12
|
+
"test:watch": "vitest watch",
|
|
13
|
+
"clean": "rm -rf dist node_modules"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"mcp-server",
|
|
17
|
+
"model-context-protocol",
|
|
18
|
+
"claude",
|
|
19
|
+
"memory-assistant",
|
|
20
|
+
"decision-tracking",
|
|
21
|
+
"semantic-search",
|
|
22
|
+
"embeddings"
|
|
23
|
+
],
|
|
24
|
+
"author": "SpineLift Team",
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "https://github.com/jungjaehoon/MAMA.git",
|
|
29
|
+
"directory": "packages/mcp-server"
|
|
30
|
+
},
|
|
31
|
+
"bugs": {
|
|
32
|
+
"url": "https://github.com/jungjaehoon/MAMA/issues"
|
|
33
|
+
},
|
|
34
|
+
"homepage": "https://github.com/jungjaehoon/MAMA#readme",
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=18.0.0"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@modelcontextprotocol/sdk": "^1.0.1",
|
|
40
|
+
"@huggingface/transformers": "^3.0.0",
|
|
41
|
+
"better-sqlite3": "^11.0.0",
|
|
42
|
+
"sqlite-vec": "^0.1.0"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"vitest": "^1.0.0",
|
|
46
|
+
"@types/better-sqlite3": "^7.6.0"
|
|
47
|
+
},
|
|
48
|
+
"files": [
|
|
49
|
+
"src/**/*.js",
|
|
50
|
+
"README.md",
|
|
51
|
+
"LICENSE"
|
|
52
|
+
]
|
|
53
|
+
}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MAMA Configuration Loader
|
|
3
|
+
*
|
|
4
|
+
* Story M1.4: Configurable embedding model selection
|
|
5
|
+
* Priority: P1 (Core Feature)
|
|
6
|
+
*
|
|
7
|
+
* Loads user configuration from ~/.mama/config.json with sensible defaults.
|
|
8
|
+
* Supports:
|
|
9
|
+
* - Model selection (default: multilingual-e5-small)
|
|
10
|
+
* - Embedding dimensions
|
|
11
|
+
* - Cache directory configuration
|
|
12
|
+
*
|
|
13
|
+
* @module config-loader
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const fs = require('fs');
|
|
17
|
+
const path = require('path');
|
|
18
|
+
const os = require('os');
|
|
19
|
+
const { info, warn, error: logError } = require('./debug-logger');
|
|
20
|
+
|
|
21
|
+
// Default configuration
|
|
22
|
+
const DEFAULT_CONFIG = {
|
|
23
|
+
modelName: 'Xenova/multilingual-e5-small',
|
|
24
|
+
embeddingDim: 384,
|
|
25
|
+
cacheDir: path.join(os.homedir(), '.cache', 'huggingface', 'transformers'),
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// Config file path
|
|
29
|
+
const CONFIG_DIR = path.join(os.homedir(), '.mama');
|
|
30
|
+
const CONFIG_PATH = path.join(CONFIG_DIR, 'config.json');
|
|
31
|
+
|
|
32
|
+
// Cached configuration
|
|
33
|
+
let cachedConfig = null;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Ensure config directory exists
|
|
37
|
+
* @returns {void}
|
|
38
|
+
*/
|
|
39
|
+
function ensureConfigDir() {
|
|
40
|
+
if (!fs.existsSync(CONFIG_DIR)) {
|
|
41
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
42
|
+
info(`[config] Created config directory: ${CONFIG_DIR}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Create default config file if it doesn't exist
|
|
48
|
+
* @returns {void}
|
|
49
|
+
*/
|
|
50
|
+
function ensureConfigFile() {
|
|
51
|
+
if (!fs.existsSync(CONFIG_PATH)) {
|
|
52
|
+
ensureConfigDir();
|
|
53
|
+
fs.writeFileSync(CONFIG_PATH, JSON.stringify(DEFAULT_CONFIG, null, 2), 'utf8');
|
|
54
|
+
info(`[config] Created default config file: ${CONFIG_PATH}`);
|
|
55
|
+
info(`[config] Model: ${DEFAULT_CONFIG.modelName} (${DEFAULT_CONFIG.embeddingDim}-dim)`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Load MAMA configuration from ~/.mama/config.json
|
|
61
|
+
*
|
|
62
|
+
* Story M1.4 AC #1: Config parser loads ~/.mama/config.json
|
|
63
|
+
*
|
|
64
|
+
* @param {boolean} reload - Force reload from disk (default: false)
|
|
65
|
+
* @returns {Object} Configuration object with modelName, embeddingDim, cacheDir
|
|
66
|
+
*/
|
|
67
|
+
function loadConfig(reload = false) {
|
|
68
|
+
// Return cached config if available and not forcing reload
|
|
69
|
+
if (cachedConfig && !reload) {
|
|
70
|
+
return cachedConfig;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
// Ensure config file exists
|
|
75
|
+
ensureConfigFile();
|
|
76
|
+
|
|
77
|
+
// Read and parse config file
|
|
78
|
+
const configData = fs.readFileSync(CONFIG_PATH, 'utf8');
|
|
79
|
+
const userConfig = JSON.parse(configData);
|
|
80
|
+
|
|
81
|
+
// Merge with defaults (user config overrides)
|
|
82
|
+
const config = {
|
|
83
|
+
...DEFAULT_CONFIG,
|
|
84
|
+
...userConfig,
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// Validate configuration
|
|
88
|
+
if (!config.modelName || typeof config.modelName !== 'string') {
|
|
89
|
+
warn('[config] Invalid modelName, using default:', DEFAULT_CONFIG.modelName);
|
|
90
|
+
config.modelName = DEFAULT_CONFIG.modelName;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (!Number.isInteger(config.embeddingDim) || config.embeddingDim <= 0) {
|
|
94
|
+
warn('[config] Invalid embeddingDim, using default:', DEFAULT_CONFIG.embeddingDim);
|
|
95
|
+
config.embeddingDim = DEFAULT_CONFIG.embeddingDim;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (!config.cacheDir || typeof config.cacheDir !== 'string') {
|
|
99
|
+
warn('[config] Invalid cacheDir, using default:', DEFAULT_CONFIG.cacheDir);
|
|
100
|
+
config.cacheDir = DEFAULT_CONFIG.cacheDir;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Cache the loaded config
|
|
104
|
+
cachedConfig = config;
|
|
105
|
+
|
|
106
|
+
// Log loaded configuration
|
|
107
|
+
if (reload) {
|
|
108
|
+
info(`[config] Configuration reloaded from ${CONFIG_PATH}`);
|
|
109
|
+
info(`[config] Model: ${config.modelName} (${config.embeddingDim}-dim)`);
|
|
110
|
+
info(`[config] Cache: ${config.cacheDir}`);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return config;
|
|
114
|
+
} catch (error) {
|
|
115
|
+
logError(`[config] Failed to load config file: ${error.message}`);
|
|
116
|
+
logError('[config] Using default configuration');
|
|
117
|
+
|
|
118
|
+
// Cache defaults on error
|
|
119
|
+
cachedConfig = { ...DEFAULT_CONFIG };
|
|
120
|
+
return cachedConfig;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Get current model name
|
|
126
|
+
* @returns {string} Current model name
|
|
127
|
+
*/
|
|
128
|
+
function getModelName() {
|
|
129
|
+
const config = loadConfig();
|
|
130
|
+
return config.modelName;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Get current embedding dimension
|
|
135
|
+
* @returns {number} Current embedding dimension
|
|
136
|
+
*/
|
|
137
|
+
function getEmbeddingDim() {
|
|
138
|
+
const config = loadConfig();
|
|
139
|
+
return config.embeddingDim;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Get current cache directory
|
|
144
|
+
* @returns {string} Current cache directory
|
|
145
|
+
*/
|
|
146
|
+
function getCacheDir() {
|
|
147
|
+
const config = loadConfig();
|
|
148
|
+
return config.cacheDir;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Update configuration and save to file
|
|
153
|
+
*
|
|
154
|
+
* Story M1.4 AC #3: Changing model via config triggers informative log + resets caches
|
|
155
|
+
*
|
|
156
|
+
* @param {Object} updates - Configuration updates
|
|
157
|
+
* @param {string} updates.modelName - New model name
|
|
158
|
+
* @param {number} updates.embeddingDim - New embedding dimension
|
|
159
|
+
* @param {string} updates.cacheDir - New cache directory
|
|
160
|
+
* @returns {boolean} Success status
|
|
161
|
+
*/
|
|
162
|
+
function updateConfig(updates) {
|
|
163
|
+
try {
|
|
164
|
+
ensureConfigFile();
|
|
165
|
+
|
|
166
|
+
// Load current config
|
|
167
|
+
const currentConfig = loadConfig();
|
|
168
|
+
|
|
169
|
+
// Check if model is changing
|
|
170
|
+
const modelChanged = updates.modelName && updates.modelName !== currentConfig.modelName;
|
|
171
|
+
const dimChanged = updates.embeddingDim && updates.embeddingDim !== currentConfig.embeddingDim;
|
|
172
|
+
|
|
173
|
+
// Merge updates
|
|
174
|
+
const newConfig = {
|
|
175
|
+
...currentConfig,
|
|
176
|
+
...updates,
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
// Save to file
|
|
180
|
+
fs.writeFileSync(CONFIG_PATH, JSON.stringify(newConfig, null, 2), 'utf8');
|
|
181
|
+
|
|
182
|
+
// Update cache
|
|
183
|
+
cachedConfig = newConfig;
|
|
184
|
+
|
|
185
|
+
// Story M1.4 AC #3: Informative log when model changes
|
|
186
|
+
if (modelChanged || dimChanged) {
|
|
187
|
+
info('[config] ⚠️ Embedding model configuration changed');
|
|
188
|
+
info(`[config] Old: ${currentConfig.modelName} (${currentConfig.embeddingDim}-dim)`);
|
|
189
|
+
info(`[config] New: ${newConfig.modelName} (${newConfig.embeddingDim}-dim)`);
|
|
190
|
+
info('[config] ⚡ Model cache will be reset on next embedding generation');
|
|
191
|
+
info('[config] ⚡ Existing embeddings in database remain unchanged');
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
info(`[config] Configuration saved to ${CONFIG_PATH}`);
|
|
195
|
+
return true;
|
|
196
|
+
} catch (error) {
|
|
197
|
+
logError(`[config] Failed to update config: ${error.message}`);
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Get config file path
|
|
204
|
+
* @returns {string} Config file path
|
|
205
|
+
*/
|
|
206
|
+
function getConfigPath() {
|
|
207
|
+
return CONFIG_PATH;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
module.exports = {
|
|
211
|
+
loadConfig,
|
|
212
|
+
getModelName,
|
|
213
|
+
getEmbeddingDim,
|
|
214
|
+
getCacheDir,
|
|
215
|
+
updateConfig,
|
|
216
|
+
getConfigPath,
|
|
217
|
+
DEFAULT_CONFIG,
|
|
218
|
+
};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Database Adapter Layer
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Abstraction layer for MAMA database to support both SQLite (development/testing) and PostgreSQL (production on Railway).
|
|
6
|
+
|
|
7
|
+
## Architecture
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
mama-api.js
|
|
11
|
+
↓
|
|
12
|
+
memory-store.js (business logic)
|
|
13
|
+
↓
|
|
14
|
+
DatabaseAdapter (interface)
|
|
15
|
+
↓
|
|
16
|
+
├── SQLiteAdapter (better-sqlite3 + sqlite-vss)
|
|
17
|
+
└── PostgreSQLAdapter (pg + pgvector)
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Decision Rationale
|
|
21
|
+
|
|
22
|
+
**Topic**: mama_db_adapter_pattern
|
|
23
|
+
**Decision**: Abstract database layer with driver-specific implementations
|
|
24
|
+
**Reasoning**:
|
|
25
|
+
1. **Environment Flexibility**: SQLite for local/testing, PostgreSQL for production
|
|
26
|
+
2. **Zero Breaking Changes**: Existing memory-store.js API remains unchanged
|
|
27
|
+
3. **Vector Search Portability**: sqlite-vss → pgvector migration path
|
|
28
|
+
4. **Testing Simplicity**: Fast SQLite tests, production PostgreSQL validation
|
|
29
|
+
|
|
30
|
+
## Adapter Interface
|
|
31
|
+
|
|
32
|
+
All adapters must implement:
|
|
33
|
+
|
|
34
|
+
```javascript
|
|
35
|
+
class DatabaseAdapter {
|
|
36
|
+
// Connection
|
|
37
|
+
connect(config) → db
|
|
38
|
+
disconnect()
|
|
39
|
+
isConnected() → boolean
|
|
40
|
+
|
|
41
|
+
// Prepared Statements
|
|
42
|
+
prepare(sql) → Statement
|
|
43
|
+
exec(sql)
|
|
44
|
+
transaction(fn) → result
|
|
45
|
+
|
|
46
|
+
// Vector Search
|
|
47
|
+
vectorSearch(embedding, limit) → results
|
|
48
|
+
insertEmbedding(rowid, embedding)
|
|
49
|
+
|
|
50
|
+
// Utility
|
|
51
|
+
getLastInsertRowid() → number
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Implementation Files
|
|
56
|
+
|
|
57
|
+
- `index.js` - Factory + environment detection
|
|
58
|
+
- `sqlite-adapter.js` - SQLite implementation (current behavior)
|
|
59
|
+
- `postgresql-adapter.js` - PostgreSQL implementation
|
|
60
|
+
- `statement.js` - Statement wrapper (unified interface)
|
|
61
|
+
|
|
62
|
+
## Environment Variable
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
# Default: SQLite
|
|
66
|
+
MAMA_DB_PATH=~/.mama/memories.db
|
|
67
|
+
|
|
68
|
+
# PostgreSQL (Railway)
|
|
69
|
+
MAMA_DATABASE_URL=postgresql://user:pass@host:5432/mama_db
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**Detection Logic**:
|
|
73
|
+
- If `MAMA_DATABASE_URL` set → PostgreSQL
|
|
74
|
+
- Else → SQLite with `MAMA_DB_PATH`
|
|
75
|
+
|
|
76
|
+
## Migration Strategy
|
|
77
|
+
|
|
78
|
+
### Phase 1: Adapter Layer (Current)
|
|
79
|
+
1. Create adapter interface
|
|
80
|
+
2. Extract SQLite logic to SQLiteAdapter
|
|
81
|
+
3. Update memory-store.js to use adapter
|
|
82
|
+
|
|
83
|
+
### Phase 2: PostgreSQL Support
|
|
84
|
+
1. Implement PostgreSQLAdapter
|
|
85
|
+
2. Convert migration SQL files
|
|
86
|
+
3. Add pgvector support
|
|
87
|
+
|
|
88
|
+
### Phase 3: Testing
|
|
89
|
+
1. Run existing tests with SQLite
|
|
90
|
+
2. Add PostgreSQL integration tests
|
|
91
|
+
3. Validate on Railway
|
|
92
|
+
|
|
93
|
+
## Performance Requirements
|
|
94
|
+
|
|
95
|
+
- Prepared statement caching
|
|
96
|
+
- Connection pooling (PostgreSQL only)
|
|
97
|
+
- Transaction batching support
|
|
98
|
+
- Vector search < 100ms (p95)
|
|
99
|
+
|
|
100
|
+
## Backward Compatibility
|
|
101
|
+
|
|
102
|
+
✅ Existing code works without changes
|
|
103
|
+
✅ SQLite remains default for development
|
|
104
|
+
✅ Environment variable controls database type
|
|
105
|
+
✅ No API changes to memory-store.js
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base Database Adapter Interface
|
|
3
|
+
* All adapters must implement these methods
|
|
4
|
+
*/
|
|
5
|
+
class DatabaseAdapter {
|
|
6
|
+
/**
|
|
7
|
+
* Connect to database
|
|
8
|
+
* @returns {Object} Database connection
|
|
9
|
+
*/
|
|
10
|
+
connect() {
|
|
11
|
+
throw new Error('connect() must be implemented by subclass');
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Disconnect from database
|
|
16
|
+
*/
|
|
17
|
+
disconnect() {
|
|
18
|
+
throw new Error('disconnect() must be implemented by subclass');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Check if connected
|
|
23
|
+
* @returns {boolean} Connection status
|
|
24
|
+
*/
|
|
25
|
+
isConnected() {
|
|
26
|
+
throw new Error('isConnected() must be implemented by subclass');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Prepare a SQL statement
|
|
31
|
+
* @param {string} sql - SQL query
|
|
32
|
+
* @returns {Statement} Prepared statement
|
|
33
|
+
*/
|
|
34
|
+
prepare(sql) {
|
|
35
|
+
throw new Error('prepare() must be implemented by subclass');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Execute raw SQL
|
|
40
|
+
* @param {string} sql - SQL to execute
|
|
41
|
+
*/
|
|
42
|
+
exec(sql) {
|
|
43
|
+
throw new Error('exec() must be implemented by subclass');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Execute function in transaction
|
|
48
|
+
* @param {Function} fn - Function to execute
|
|
49
|
+
* @returns {*} Function return value
|
|
50
|
+
*/
|
|
51
|
+
transaction(fn) {
|
|
52
|
+
throw new Error('transaction() must be implemented by subclass');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Vector similarity search
|
|
57
|
+
* @param {number[]} embedding - Query embedding (384-dim)
|
|
58
|
+
* @param {number} limit - Max results
|
|
59
|
+
* @returns {Array<Object>} Search results with distance
|
|
60
|
+
*/
|
|
61
|
+
vectorSearch(embedding, limit) {
|
|
62
|
+
throw new Error('vectorSearch() must be implemented by subclass');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Insert vector embedding
|
|
67
|
+
* @param {number} rowid - Decision rowid
|
|
68
|
+
* @param {number[]} embedding - Embedding vector
|
|
69
|
+
*/
|
|
70
|
+
insertEmbedding(rowid, embedding) {
|
|
71
|
+
throw new Error('insertEmbedding() must be implemented by subclass');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Get last inserted row ID
|
|
76
|
+
* @returns {number} Last rowid
|
|
77
|
+
*/
|
|
78
|
+
getLastInsertRowid() {
|
|
79
|
+
throw new Error('getLastInsertRowid() must be implemented by subclass');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Run migrations
|
|
84
|
+
* @param {string} migrationsDir - Path to migrations directory
|
|
85
|
+
*/
|
|
86
|
+
runMigrations(migrationsDir) {
|
|
87
|
+
throw new Error('runMigrations() must be implemented by subclass');
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
module.exports = { DatabaseAdapter };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Database Adapter Factory (SQLite-only)
|
|
3
|
+
*
|
|
4
|
+
* MAMA Plugin uses SQLite exclusively for local storage.
|
|
5
|
+
* PostgreSQL support is only available in the legacy mcp-server.
|
|
6
|
+
*
|
|
7
|
+
* @module db-adapter
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const { info } = require('../debug-logger');
|
|
11
|
+
const SQLiteAdapter = require('./sqlite-adapter');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Create SQLite database adapter
|
|
15
|
+
*
|
|
16
|
+
* @param {Object} config - Database configuration
|
|
17
|
+
* @param {string} [config.dbPath] - SQLite file path (overrides env)
|
|
18
|
+
* @returns {DatabaseAdapter} Configured SQLite adapter instance
|
|
19
|
+
*/
|
|
20
|
+
function createAdapter(config = {}) {
|
|
21
|
+
info('[db-adapter] Using SQLite adapter (plugin mode)');
|
|
22
|
+
const dbPath = config.dbPath || process.env.MAMA_DB_PATH;
|
|
23
|
+
return new SQLiteAdapter({ dbPath });
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const { DatabaseAdapter } = require('./base-adapter');
|
|
27
|
+
|
|
28
|
+
module.exports = {
|
|
29
|
+
createAdapter,
|
|
30
|
+
DatabaseAdapter,
|
|
31
|
+
};
|