@jungjaehoon/mama-core 1.1.2 → 1.1.3
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/dist/config-loader.d.ts +61 -0
- package/dist/config-loader.js +187 -0
- package/dist/db-adapter/base-adapter.d.ts +76 -0
- package/dist/db-adapter/base-adapter.js +11 -0
- package/dist/db-adapter/index.d.ts +24 -0
- package/dist/db-adapter/index.js +29 -0
- package/dist/db-adapter/sqlite-adapter.d.ts +73 -0
- package/dist/db-adapter/sqlite-adapter.js +330 -0
- package/dist/db-adapter/statement.d.ts +119 -0
- package/dist/db-adapter/statement.js +113 -0
- package/dist/db-manager.d.ts +252 -0
- package/dist/db-manager.js +622 -0
- package/dist/debug-logger.d.ts +32 -0
- package/dist/debug-logger.js +83 -0
- package/dist/decision-formatter.d.ts +172 -0
- package/dist/decision-formatter.js +894 -0
- package/dist/decision-tracker.d.ts +218 -0
- package/dist/decision-tracker.js +531 -0
- package/dist/embedding-cache.d.ts +83 -0
- package/dist/embedding-cache.js +182 -0
- package/dist/embedding-client.d.ts +43 -0
- package/dist/embedding-client.js +132 -0
- package/dist/embedding-server/index.d.ts +65 -0
- package/dist/embedding-server/index.js +397 -0
- package/dist/embedding-server/mobile/auth.d.ts +53 -0
- package/dist/embedding-server/mobile/auth.js +140 -0
- package/dist/embedding-server/mobile/daemon.d.ts +128 -0
- package/dist/embedding-server/mobile/daemon.js +303 -0
- package/dist/embedding-server/mobile/output-parser.d.ts +115 -0
- package/dist/embedding-server/mobile/output-parser.js +241 -0
- package/dist/embedding-server/mobile/session-api.d.ts +57 -0
- package/dist/embedding-server/mobile/session-api.js +261 -0
- package/dist/embedding-server/mobile/session-manager.d.ts +135 -0
- package/dist/embedding-server/mobile/session-manager.js +333 -0
- package/dist/embedding-server/mobile/websocket-handler.d.ts +127 -0
- package/dist/embedding-server/mobile/websocket-handler.js +435 -0
- package/dist/embeddings.d.ts +75 -0
- package/dist/embeddings.js +262 -0
- package/dist/errors.d.ts +131 -0
- package/dist/errors.js +225 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.js +193 -0
- package/dist/mama-api.d.ts +954 -0
- package/dist/mama-api.js +2210 -0
- package/dist/memory-inject.d.ts +24 -0
- package/dist/memory-inject.js +116 -0
- package/dist/memory-store.d.ts +103 -0
- package/dist/memory-store.js +129 -0
- package/dist/notification-manager.d.ts +7 -0
- package/dist/notification-manager.js +12 -0
- package/dist/ollama-client.d.ts +51 -0
- package/dist/ollama-client.js +308 -0
- package/dist/outcome-tracker.d.ts +165 -0
- package/dist/outcome-tracker.js +315 -0
- package/dist/progress-indicator.d.ts +48 -0
- package/dist/progress-indicator.js +82 -0
- package/dist/query-intent.d.ts +27 -0
- package/dist/query-intent.js +144 -0
- package/dist/relevance-scorer.d.ts +124 -0
- package/dist/relevance-scorer.js +243 -0
- package/dist/test-utils.d.ts +66 -0
- package/dist/test-utils.js +166 -0
- package/dist/tier-validator.d.ts +55 -0
- package/dist/tier-validator.js +216 -0
- package/dist/time-formatter.d.ts +25 -0
- package/dist/time-formatter.js +93 -0
- package/package.json +3 -2
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* MAMA (Memory-Augmented MCP Architecture) - Embedding Generation
|
|
4
|
+
*
|
|
5
|
+
* Story M1.4: Configurable embedding model selection
|
|
6
|
+
* Generates embeddings using configurable model (default: multilingual-e5-small)
|
|
7
|
+
* Supports: Korean-English cross-lingual similarity, enhanced metadata
|
|
8
|
+
*
|
|
9
|
+
* @module embeddings
|
|
10
|
+
* @version 1.1
|
|
11
|
+
* @date 2025-11-20
|
|
12
|
+
*/
|
|
13
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.getEmbeddingDim = exports.getModelName = exports.loadConfig = exports.MODEL_NAME = exports.EMBEDDING_DIM = exports.embeddingCache = void 0;
|
|
18
|
+
exports.generateEmbedding = generateEmbedding;
|
|
19
|
+
exports.generateEnhancedEmbedding = generateEnhancedEmbedding;
|
|
20
|
+
exports.generateBatchEmbeddings = generateBatchEmbeddings;
|
|
21
|
+
exports.cosineSimilarity = cosineSimilarity;
|
|
22
|
+
const os_1 = __importDefault(require("os"));
|
|
23
|
+
const path_1 = __importDefault(require("path"));
|
|
24
|
+
const debug_logger_js_1 = require("./debug-logger.js");
|
|
25
|
+
const progress_indicator_js_1 = require("./progress-indicator.js");
|
|
26
|
+
const embedding_cache_js_1 = require("./embedding-cache.js");
|
|
27
|
+
Object.defineProperty(exports, "embeddingCache", { enumerable: true, get: function () { return embedding_cache_js_1.embeddingCache; } });
|
|
28
|
+
const config_loader_js_1 = require("./config-loader.js");
|
|
29
|
+
Object.defineProperty(exports, "loadConfig", { enumerable: true, get: function () { return config_loader_js_1.loadConfig; } });
|
|
30
|
+
Object.defineProperty(exports, "getModelName", { enumerable: true, get: function () { return config_loader_js_1.getModelName; } });
|
|
31
|
+
Object.defineProperty(exports, "getEmbeddingDim", { enumerable: true, get: function () { return config_loader_js_1.getEmbeddingDim; } });
|
|
32
|
+
// Shared cache directory (not in node_modules)
|
|
33
|
+
const DEFAULT_CACHE_DIR = path_1.default.join(os_1.default.homedir(), '.cache', 'huggingface', 'transformers');
|
|
34
|
+
// Singleton pattern for model loading
|
|
35
|
+
let embeddingPipeline = null;
|
|
36
|
+
let currentModelName = null;
|
|
37
|
+
let modelLoadFailed = false; // Cache load failures to avoid repeated slow retries
|
|
38
|
+
/**
|
|
39
|
+
* Load embedding model (configurable)
|
|
40
|
+
*
|
|
41
|
+
* Story M1.4 AC #2: Transformers.js singleton initialization
|
|
42
|
+
* Story M1.4 AC #3: Changing model via config triggers informative log + resets caches
|
|
43
|
+
*
|
|
44
|
+
* @returns Embedding pipeline
|
|
45
|
+
*/
|
|
46
|
+
async function loadModel() {
|
|
47
|
+
const modelName = (0, config_loader_js_1.getModelName)();
|
|
48
|
+
// Check if model has changed (Story M1.4 AC #3)
|
|
49
|
+
if (embeddingPipeline && currentModelName && currentModelName !== modelName) {
|
|
50
|
+
(0, debug_logger_js_1.info)('[MAMA] ⚠️ Embedding model changed - resetting pipeline');
|
|
51
|
+
(0, debug_logger_js_1.info)(`[MAMA] Old model: ${currentModelName}`);
|
|
52
|
+
(0, debug_logger_js_1.info)(`[MAMA] New model: ${modelName}`);
|
|
53
|
+
// Reset pipeline and cache
|
|
54
|
+
embeddingPipeline = null;
|
|
55
|
+
currentModelName = null;
|
|
56
|
+
embedding_cache_js_1.embeddingCache.clear();
|
|
57
|
+
(0, debug_logger_js_1.info)('[MAMA] ⚡ Model cache cleared');
|
|
58
|
+
}
|
|
59
|
+
// Fail fast if a previous load attempt already failed (avoid repeated slow retries)
|
|
60
|
+
if (modelLoadFailed) {
|
|
61
|
+
throw new Error('Embedding model previously failed to load — skipping retry');
|
|
62
|
+
}
|
|
63
|
+
// Load model if not already loaded
|
|
64
|
+
if (!embeddingPipeline) {
|
|
65
|
+
(0, progress_indicator_js_1.logLoading)(`Loading embedding model: ${modelName}...`);
|
|
66
|
+
const startTime = Date.now();
|
|
67
|
+
try {
|
|
68
|
+
// Dynamic import for ES Module compatibility (Railway deployment)
|
|
69
|
+
const transformers = await import('@huggingface/transformers');
|
|
70
|
+
const { pipeline, env } = transformers;
|
|
71
|
+
// Set shared cache directory (not in node_modules)
|
|
72
|
+
// This prevents re-downloading models on every npm install
|
|
73
|
+
const cacheDir = process.env.HF_HOME || process.env.TRANSFORMERS_CACHE || DEFAULT_CACHE_DIR;
|
|
74
|
+
env.cacheDir = cacheDir;
|
|
75
|
+
(0, debug_logger_js_1.info)(`[MAMA] Model cache directory: ${cacheDir}`);
|
|
76
|
+
embeddingPipeline = (await pipeline('feature-extraction', modelName));
|
|
77
|
+
currentModelName = modelName;
|
|
78
|
+
const loadTime = Date.now() - startTime;
|
|
79
|
+
const config = (0, config_loader_js_1.loadConfig)();
|
|
80
|
+
(0, progress_indicator_js_1.logComplete)(`Embedding model ready (${loadTime}ms, ${config.embeddingDim}-dim)`);
|
|
81
|
+
}
|
|
82
|
+
catch (loadErr) {
|
|
83
|
+
modelLoadFailed = true;
|
|
84
|
+
throw loadErr;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return embeddingPipeline;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Generate embedding vector from text
|
|
91
|
+
*
|
|
92
|
+
* Story M1.4 AC #1: Uses configurable embeddingDim from config
|
|
93
|
+
* Target: < 30ms latency
|
|
94
|
+
*
|
|
95
|
+
* @param text - Input text to embed
|
|
96
|
+
* @returns Embedding vector (dimension from config)
|
|
97
|
+
* @throws Error if text is empty or embedding fails
|
|
98
|
+
*/
|
|
99
|
+
async function generateEmbedding(text) {
|
|
100
|
+
if (!text || text.trim().length === 0) {
|
|
101
|
+
throw new Error('Text cannot be empty');
|
|
102
|
+
}
|
|
103
|
+
// Task 2: Check cache first (AC #3)
|
|
104
|
+
const cached = embedding_cache_js_1.embeddingCache.get(text);
|
|
105
|
+
if (cached) {
|
|
106
|
+
return cached;
|
|
107
|
+
}
|
|
108
|
+
const startTime = Date.now();
|
|
109
|
+
try {
|
|
110
|
+
const model = await loadModel();
|
|
111
|
+
const expectedDim = (0, config_loader_js_1.getEmbeddingDim)();
|
|
112
|
+
// Generate embedding
|
|
113
|
+
const output = await model(text, {
|
|
114
|
+
pooling: 'mean', // Mean pooling over tokens
|
|
115
|
+
normalize: true, // L2 normalization
|
|
116
|
+
});
|
|
117
|
+
// Extract Float32Array
|
|
118
|
+
const embedding = output.data;
|
|
119
|
+
// Verify dimensions match config
|
|
120
|
+
if (embedding.length !== expectedDim) {
|
|
121
|
+
throw new Error(`Expected ${expectedDim}-dim, got ${embedding.length}-dim`);
|
|
122
|
+
}
|
|
123
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
124
|
+
const _latency = Date.now() - startTime;
|
|
125
|
+
// Task 2: Store in cache (AC #3)
|
|
126
|
+
embedding_cache_js_1.embeddingCache.set(text, embedding);
|
|
127
|
+
return embedding;
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
131
|
+
throw new Error(`Failed to generate embedding: ${message}`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Generate enhanced embedding with content + metadata
|
|
136
|
+
*
|
|
137
|
+
* Task 3.4: Implement enhanced embedding format
|
|
138
|
+
* Inspired by A-mem: Content + Metadata for richer semantic representation
|
|
139
|
+
*
|
|
140
|
+
* @param decision - Decision object
|
|
141
|
+
* @returns 384-dim enhanced embedding
|
|
142
|
+
*/
|
|
143
|
+
async function generateEnhancedEmbedding(decision) {
|
|
144
|
+
// Construct enriched text representation with narrative fields (Story 2.2)
|
|
145
|
+
const parts = [
|
|
146
|
+
`Topic: ${decision.topic}`,
|
|
147
|
+
`Decision: ${decision.decision}`,
|
|
148
|
+
`Reasoning: ${decision.reasoning || 'N/A'}`,
|
|
149
|
+
`Outcome: ${decision.outcome || 'ONGOING'}`,
|
|
150
|
+
`Confidence: ${decision.confidence !== undefined ? decision.confidence : 0.5}`,
|
|
151
|
+
`User Involvement: ${decision.user_involvement || 'N/A'}`,
|
|
152
|
+
];
|
|
153
|
+
// Add narrative fields if present (Story 2.2: Narrative-Based Search)
|
|
154
|
+
if (decision.evidence) {
|
|
155
|
+
const evidenceText = Array.isArray(decision.evidence)
|
|
156
|
+
? decision.evidence.join('; ')
|
|
157
|
+
: typeof decision.evidence === 'string'
|
|
158
|
+
? decision.evidence
|
|
159
|
+
: JSON.stringify(decision.evidence);
|
|
160
|
+
parts.push(`Evidence: ${evidenceText}`);
|
|
161
|
+
}
|
|
162
|
+
if (decision.alternatives) {
|
|
163
|
+
const alternativesText = Array.isArray(decision.alternatives)
|
|
164
|
+
? decision.alternatives.join('; ')
|
|
165
|
+
: typeof decision.alternatives === 'string'
|
|
166
|
+
? decision.alternatives
|
|
167
|
+
: JSON.stringify(decision.alternatives);
|
|
168
|
+
parts.push(`Alternatives: ${alternativesText}`);
|
|
169
|
+
}
|
|
170
|
+
if (decision.risks) {
|
|
171
|
+
parts.push(`Risks: ${decision.risks}`);
|
|
172
|
+
}
|
|
173
|
+
const enrichedText = parts.join('\n').trim();
|
|
174
|
+
return generateEmbedding(enrichedText);
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Batch generate embeddings (optimized)
|
|
178
|
+
*
|
|
179
|
+
* Task 1: Implement Batch Embedding Generation
|
|
180
|
+
* AC #3: Target - 30ms for 10 embeddings (vs 300ms sequential)
|
|
181
|
+
*
|
|
182
|
+
* Strategy: Use native transformer batch processing for parallel inference
|
|
183
|
+
*
|
|
184
|
+
* @param texts - Array of texts to embed (max 10 per batch)
|
|
185
|
+
* @returns Array of embeddings
|
|
186
|
+
*/
|
|
187
|
+
async function generateBatchEmbeddings(texts) {
|
|
188
|
+
if (!Array.isArray(texts) || texts.length === 0) {
|
|
189
|
+
throw new Error('Texts must be a non-empty array');
|
|
190
|
+
}
|
|
191
|
+
// Validate all texts
|
|
192
|
+
for (const text of texts) {
|
|
193
|
+
if (!text || text.trim().length === 0) {
|
|
194
|
+
throw new Error('All texts must be non-empty');
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
const startTime = Date.now();
|
|
198
|
+
try {
|
|
199
|
+
const model = await loadModel();
|
|
200
|
+
const expectedDim = (0, config_loader_js_1.getEmbeddingDim)();
|
|
201
|
+
// Native batch processing - single model forward pass
|
|
202
|
+
// This is significantly faster than sequential calls
|
|
203
|
+
const outputs = await model(texts, {
|
|
204
|
+
pooling: 'mean',
|
|
205
|
+
normalize: true,
|
|
206
|
+
});
|
|
207
|
+
// Extract embeddings from batch output
|
|
208
|
+
const embeddings = [];
|
|
209
|
+
const batchSize = texts.length;
|
|
210
|
+
for (let i = 0; i < batchSize; i++) {
|
|
211
|
+
// Each embedding is expectedDim consecutive elements
|
|
212
|
+
const start = i * expectedDim;
|
|
213
|
+
const end = start + expectedDim;
|
|
214
|
+
const embedding = outputs.data.slice(start, end);
|
|
215
|
+
// Verify dimensions
|
|
216
|
+
if (embedding.length !== expectedDim) {
|
|
217
|
+
throw new Error(`Expected ${expectedDim}-dim, got ${embedding.length}-dim at index ${i}`);
|
|
218
|
+
}
|
|
219
|
+
embeddings.push(embedding);
|
|
220
|
+
}
|
|
221
|
+
const latency = Date.now() - startTime;
|
|
222
|
+
const avgLatency = latency / batchSize;
|
|
223
|
+
// Log for performance tracking
|
|
224
|
+
if (process.env.MAMA_DEBUG) {
|
|
225
|
+
(0, debug_logger_js_1.info)(`[MAMA] Batch(${batchSize}) embeddings: ${latency}ms total (${avgLatency.toFixed(1)}ms avg)`);
|
|
226
|
+
}
|
|
227
|
+
return embeddings;
|
|
228
|
+
}
|
|
229
|
+
catch (error) {
|
|
230
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
231
|
+
throw new Error(`Failed to generate batch embeddings: ${message}`);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Calculate cosine similarity between two embeddings
|
|
236
|
+
*
|
|
237
|
+
* Utility for testing and validation
|
|
238
|
+
*
|
|
239
|
+
* @param embA - First embedding
|
|
240
|
+
* @param embB - Second embedding
|
|
241
|
+
* @returns Cosine similarity (0-1)
|
|
242
|
+
*/
|
|
243
|
+
function cosineSimilarity(embA, embB) {
|
|
244
|
+
if (embA.length !== embB.length) {
|
|
245
|
+
throw new Error('Embeddings must have same dimension');
|
|
246
|
+
}
|
|
247
|
+
let dotProduct = 0;
|
|
248
|
+
let normA = 0;
|
|
249
|
+
let normB = 0;
|
|
250
|
+
for (let i = 0; i < embA.length; i++) {
|
|
251
|
+
dotProduct += embA[i] * embB[i];
|
|
252
|
+
normA += embA[i] * embA[i];
|
|
253
|
+
normB += embB[i] * embB[i];
|
|
254
|
+
}
|
|
255
|
+
const similarity = dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
|
|
256
|
+
return similarity;
|
|
257
|
+
}
|
|
258
|
+
// Static snapshots of config values at module load time (Story M1.4)
|
|
259
|
+
// Note: These are evaluated once at import time. Use getEmbeddingDim()/getModelName() for runtime values.
|
|
260
|
+
exports.EMBEDDING_DIM = (0, config_loader_js_1.getEmbeddingDim)();
|
|
261
|
+
exports.MODEL_NAME = (0, config_loader_js_1.getModelName)();
|
|
262
|
+
//# sourceMappingURL=embeddings.js.map
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MAMA Error Classes - Typed Error Handling
|
|
3
|
+
*
|
|
4
|
+
* Story 8.3: Typed Error Classes
|
|
5
|
+
* Provides consistent error handling across MCP tools and core modules
|
|
6
|
+
*
|
|
7
|
+
* Error codes follow MCP standard response format:
|
|
8
|
+
* {error: {code: 'ERROR_CODE', message: '...', details: {}}}
|
|
9
|
+
*
|
|
10
|
+
* @module errors
|
|
11
|
+
* @version 1.0
|
|
12
|
+
*/
|
|
13
|
+
export interface ErrorDetails {
|
|
14
|
+
[key: string]: unknown;
|
|
15
|
+
}
|
|
16
|
+
export interface ErrorResponse {
|
|
17
|
+
error: {
|
|
18
|
+
code: string;
|
|
19
|
+
message: string;
|
|
20
|
+
details: ErrorDetails;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export interface ErrorJSON {
|
|
24
|
+
name: string;
|
|
25
|
+
code: string;
|
|
26
|
+
message: string;
|
|
27
|
+
details: ErrorDetails;
|
|
28
|
+
timestamp: string;
|
|
29
|
+
stack?: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Base error class for all MAMA errors
|
|
33
|
+
*/
|
|
34
|
+
export declare class MAMAError extends Error {
|
|
35
|
+
code: string;
|
|
36
|
+
details: ErrorDetails;
|
|
37
|
+
timestamp: string;
|
|
38
|
+
constructor(message: string, code?: string, details?: ErrorDetails);
|
|
39
|
+
/**
|
|
40
|
+
* Convert to MCP-compatible error response format
|
|
41
|
+
*/
|
|
42
|
+
toResponse(): ErrorResponse;
|
|
43
|
+
/**
|
|
44
|
+
* Convert to JSON for logging
|
|
45
|
+
*/
|
|
46
|
+
toJSON(): ErrorJSON;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Error thrown when a decision is not found
|
|
50
|
+
*/
|
|
51
|
+
export declare class NotFoundError extends MAMAError {
|
|
52
|
+
constructor(resourceType: string, identifier: string, details?: ErrorDetails);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Error thrown when input validation fails
|
|
56
|
+
*/
|
|
57
|
+
export declare class ValidationError extends MAMAError {
|
|
58
|
+
field: string;
|
|
59
|
+
constructor(field: string, message: string, received?: unknown, details?: ErrorDetails);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Error thrown when database operations fail
|
|
63
|
+
*/
|
|
64
|
+
export declare class DatabaseError extends MAMAError {
|
|
65
|
+
operation: string;
|
|
66
|
+
constructor(operation: string, message: string, details?: ErrorDetails);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Error thrown when embedding generation fails
|
|
70
|
+
*/
|
|
71
|
+
export declare class EmbeddingError extends MAMAError {
|
|
72
|
+
constructor(message: string, details?: ErrorDetails);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Error thrown when configuration is invalid
|
|
76
|
+
*/
|
|
77
|
+
export declare class ConfigurationError extends MAMAError {
|
|
78
|
+
configKey: string;
|
|
79
|
+
constructor(configKey: string, message: string, details?: ErrorDetails);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Error thrown when a link operation fails
|
|
83
|
+
*/
|
|
84
|
+
export declare class LinkError extends MAMAError {
|
|
85
|
+
operation: string;
|
|
86
|
+
constructor(operation: string, message: string, details?: ErrorDetails);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Error thrown when rate limit is exceeded
|
|
90
|
+
*/
|
|
91
|
+
export declare class RateLimitError extends MAMAError {
|
|
92
|
+
retryAfterMs: number;
|
|
93
|
+
constructor(operation: string, retryAfterMs: number, details?: ErrorDetails);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Error thrown when operation times out
|
|
97
|
+
*/
|
|
98
|
+
export declare class TimeoutError extends MAMAError {
|
|
99
|
+
timeoutMs: number;
|
|
100
|
+
constructor(operation: string, timeoutMs: number, details?: ErrorDetails);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Error codes enum for reference
|
|
104
|
+
*/
|
|
105
|
+
export declare const ErrorCodes: {
|
|
106
|
+
readonly DECISION_NOT_FOUND: "DECISION_NOT_FOUND";
|
|
107
|
+
readonly CHECKPOINT_NOT_FOUND: "CHECKPOINT_NOT_FOUND";
|
|
108
|
+
readonly LINK_NOT_FOUND: "LINK_NOT_FOUND";
|
|
109
|
+
readonly INVALID_INPUT: "INVALID_INPUT";
|
|
110
|
+
readonly MISSING_REQUIRED_FIELD: "MISSING_REQUIRED_FIELD";
|
|
111
|
+
readonly INVALID_FORMAT: "INVALID_FORMAT";
|
|
112
|
+
readonly DATABASE_ERROR: "DATABASE_ERROR";
|
|
113
|
+
readonly CONNECTION_FAILED: "CONNECTION_FAILED";
|
|
114
|
+
readonly QUERY_FAILED: "QUERY_FAILED";
|
|
115
|
+
readonly EMBEDDING_ERROR: "EMBEDDING_ERROR";
|
|
116
|
+
readonly CONFIG_ERROR: "CONFIG_ERROR";
|
|
117
|
+
readonly LINK_ERROR: "LINK_ERROR";
|
|
118
|
+
readonly RATE_LIMITED: "RATE_LIMITED";
|
|
119
|
+
readonly TIMEOUT: "TIMEOUT";
|
|
120
|
+
readonly INTERNAL_ERROR: "INTERNAL_ERROR";
|
|
121
|
+
};
|
|
122
|
+
export type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];
|
|
123
|
+
/**
|
|
124
|
+
* Helper function to wrap unknown errors
|
|
125
|
+
*/
|
|
126
|
+
export declare function wrapError(error: unknown, context?: string): MAMAError;
|
|
127
|
+
/**
|
|
128
|
+
* Helper function to check if an error is a MAMA error
|
|
129
|
+
*/
|
|
130
|
+
export declare function isMAMAError(error: unknown): error is MAMAError;
|
|
131
|
+
//# sourceMappingURL=errors.d.ts.map
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* MAMA Error Classes - Typed Error Handling
|
|
4
|
+
*
|
|
5
|
+
* Story 8.3: Typed Error Classes
|
|
6
|
+
* Provides consistent error handling across MCP tools and core modules
|
|
7
|
+
*
|
|
8
|
+
* Error codes follow MCP standard response format:
|
|
9
|
+
* {error: {code: 'ERROR_CODE', message: '...', details: {}}}
|
|
10
|
+
*
|
|
11
|
+
* @module errors
|
|
12
|
+
* @version 1.0
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.ErrorCodes = exports.TimeoutError = exports.RateLimitError = exports.LinkError = exports.ConfigurationError = exports.EmbeddingError = exports.DatabaseError = exports.ValidationError = exports.NotFoundError = exports.MAMAError = void 0;
|
|
16
|
+
exports.wrapError = wrapError;
|
|
17
|
+
exports.isMAMAError = isMAMAError;
|
|
18
|
+
/**
|
|
19
|
+
* Base error class for all MAMA errors
|
|
20
|
+
*/
|
|
21
|
+
class MAMAError extends Error {
|
|
22
|
+
code;
|
|
23
|
+
details;
|
|
24
|
+
timestamp;
|
|
25
|
+
constructor(message, code = 'MAMA_ERROR', details = {}) {
|
|
26
|
+
super(message);
|
|
27
|
+
this.name = 'MAMAError';
|
|
28
|
+
this.code = code;
|
|
29
|
+
this.details = details;
|
|
30
|
+
this.timestamp = new Date().toISOString();
|
|
31
|
+
// Capture stack trace
|
|
32
|
+
if (Error.captureStackTrace) {
|
|
33
|
+
Error.captureStackTrace(this, this.constructor);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Convert to MCP-compatible error response format
|
|
38
|
+
*/
|
|
39
|
+
toResponse() {
|
|
40
|
+
return {
|
|
41
|
+
error: {
|
|
42
|
+
code: this.code,
|
|
43
|
+
message: this.message,
|
|
44
|
+
details: this.details,
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Convert to JSON for logging
|
|
50
|
+
*/
|
|
51
|
+
toJSON() {
|
|
52
|
+
return {
|
|
53
|
+
name: this.name,
|
|
54
|
+
code: this.code,
|
|
55
|
+
message: this.message,
|
|
56
|
+
details: this.details,
|
|
57
|
+
timestamp: this.timestamp,
|
|
58
|
+
stack: this.stack,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
exports.MAMAError = MAMAError;
|
|
63
|
+
/**
|
|
64
|
+
* Error thrown when a decision is not found
|
|
65
|
+
*/
|
|
66
|
+
class NotFoundError extends MAMAError {
|
|
67
|
+
constructor(resourceType, identifier, details = {}) {
|
|
68
|
+
super(`${resourceType} not found: ${identifier}`, `${resourceType.toUpperCase()}_NOT_FOUND`, {
|
|
69
|
+
resourceType,
|
|
70
|
+
identifier,
|
|
71
|
+
...details,
|
|
72
|
+
});
|
|
73
|
+
this.name = 'NotFoundError';
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
exports.NotFoundError = NotFoundError;
|
|
77
|
+
/**
|
|
78
|
+
* Error thrown when input validation fails
|
|
79
|
+
*/
|
|
80
|
+
class ValidationError extends MAMAError {
|
|
81
|
+
field;
|
|
82
|
+
constructor(field, message, received, details = {}) {
|
|
83
|
+
super(`Validation failed for '${field}': ${message}`, 'INVALID_INPUT', {
|
|
84
|
+
field,
|
|
85
|
+
received: received !== undefined ? String(received).substring(0, 100) : undefined,
|
|
86
|
+
...details,
|
|
87
|
+
});
|
|
88
|
+
this.name = 'ValidationError';
|
|
89
|
+
this.field = field;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
exports.ValidationError = ValidationError;
|
|
93
|
+
/**
|
|
94
|
+
* Error thrown when database operations fail
|
|
95
|
+
*/
|
|
96
|
+
class DatabaseError extends MAMAError {
|
|
97
|
+
operation;
|
|
98
|
+
constructor(operation, message, details = {}) {
|
|
99
|
+
super(`Database ${operation} failed: ${message}`, 'DATABASE_ERROR', {
|
|
100
|
+
operation,
|
|
101
|
+
...details,
|
|
102
|
+
});
|
|
103
|
+
this.name = 'DatabaseError';
|
|
104
|
+
this.operation = operation;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
exports.DatabaseError = DatabaseError;
|
|
108
|
+
/**
|
|
109
|
+
* Error thrown when embedding generation fails
|
|
110
|
+
*/
|
|
111
|
+
class EmbeddingError extends MAMAError {
|
|
112
|
+
constructor(message, details = {}) {
|
|
113
|
+
super(`Embedding generation failed: ${message}`, 'EMBEDDING_ERROR', details);
|
|
114
|
+
this.name = 'EmbeddingError';
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
exports.EmbeddingError = EmbeddingError;
|
|
118
|
+
/**
|
|
119
|
+
* Error thrown when configuration is invalid
|
|
120
|
+
*/
|
|
121
|
+
class ConfigurationError extends MAMAError {
|
|
122
|
+
configKey;
|
|
123
|
+
constructor(configKey, message, details = {}) {
|
|
124
|
+
super(`Configuration error for '${configKey}': ${message}`, 'CONFIG_ERROR', {
|
|
125
|
+
configKey,
|
|
126
|
+
...details,
|
|
127
|
+
});
|
|
128
|
+
this.name = 'ConfigurationError';
|
|
129
|
+
this.configKey = configKey;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
exports.ConfigurationError = ConfigurationError;
|
|
133
|
+
/**
|
|
134
|
+
* Error thrown when a link operation fails
|
|
135
|
+
*/
|
|
136
|
+
class LinkError extends MAMAError {
|
|
137
|
+
operation;
|
|
138
|
+
constructor(operation, message, details = {}) {
|
|
139
|
+
super(`Link ${operation} failed: ${message}`, 'LINK_ERROR', {
|
|
140
|
+
operation,
|
|
141
|
+
...details,
|
|
142
|
+
});
|
|
143
|
+
this.name = 'LinkError';
|
|
144
|
+
this.operation = operation;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
exports.LinkError = LinkError;
|
|
148
|
+
/**
|
|
149
|
+
* Error thrown when rate limit is exceeded
|
|
150
|
+
*/
|
|
151
|
+
class RateLimitError extends MAMAError {
|
|
152
|
+
retryAfterMs;
|
|
153
|
+
constructor(operation, retryAfterMs, details = {}) {
|
|
154
|
+
super(`Rate limit exceeded for ${operation}. Retry after ${retryAfterMs}ms`, 'RATE_LIMITED', {
|
|
155
|
+
operation,
|
|
156
|
+
retryAfterMs,
|
|
157
|
+
...details,
|
|
158
|
+
});
|
|
159
|
+
this.name = 'RateLimitError';
|
|
160
|
+
this.retryAfterMs = retryAfterMs;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
exports.RateLimitError = RateLimitError;
|
|
164
|
+
/**
|
|
165
|
+
* Error thrown when operation times out
|
|
166
|
+
*/
|
|
167
|
+
class TimeoutError extends MAMAError {
|
|
168
|
+
timeoutMs;
|
|
169
|
+
constructor(operation, timeoutMs, details = {}) {
|
|
170
|
+
super(`Operation '${operation}' timed out after ${timeoutMs}ms`, 'TIMEOUT', {
|
|
171
|
+
operation,
|
|
172
|
+
timeoutMs,
|
|
173
|
+
...details,
|
|
174
|
+
});
|
|
175
|
+
this.name = 'TimeoutError';
|
|
176
|
+
this.timeoutMs = timeoutMs;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
exports.TimeoutError = TimeoutError;
|
|
180
|
+
/**
|
|
181
|
+
* Error codes enum for reference
|
|
182
|
+
*/
|
|
183
|
+
exports.ErrorCodes = {
|
|
184
|
+
// Resource errors
|
|
185
|
+
DECISION_NOT_FOUND: 'DECISION_NOT_FOUND',
|
|
186
|
+
CHECKPOINT_NOT_FOUND: 'CHECKPOINT_NOT_FOUND',
|
|
187
|
+
LINK_NOT_FOUND: 'LINK_NOT_FOUND',
|
|
188
|
+
// Validation errors
|
|
189
|
+
INVALID_INPUT: 'INVALID_INPUT',
|
|
190
|
+
MISSING_REQUIRED_FIELD: 'MISSING_REQUIRED_FIELD',
|
|
191
|
+
INVALID_FORMAT: 'INVALID_FORMAT',
|
|
192
|
+
// Database errors
|
|
193
|
+
DATABASE_ERROR: 'DATABASE_ERROR',
|
|
194
|
+
CONNECTION_FAILED: 'CONNECTION_FAILED',
|
|
195
|
+
QUERY_FAILED: 'QUERY_FAILED',
|
|
196
|
+
// Processing errors
|
|
197
|
+
EMBEDDING_ERROR: 'EMBEDDING_ERROR',
|
|
198
|
+
CONFIG_ERROR: 'CONFIG_ERROR',
|
|
199
|
+
LINK_ERROR: 'LINK_ERROR',
|
|
200
|
+
// Operational errors
|
|
201
|
+
RATE_LIMITED: 'RATE_LIMITED',
|
|
202
|
+
TIMEOUT: 'TIMEOUT',
|
|
203
|
+
INTERNAL_ERROR: 'INTERNAL_ERROR',
|
|
204
|
+
};
|
|
205
|
+
/**
|
|
206
|
+
* Helper function to wrap unknown errors
|
|
207
|
+
*/
|
|
208
|
+
function wrapError(error, context = 'Unknown operation') {
|
|
209
|
+
if (error instanceof MAMAError) {
|
|
210
|
+
return error;
|
|
211
|
+
}
|
|
212
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
213
|
+
const stack = error instanceof Error ? error.stack : undefined;
|
|
214
|
+
return new MAMAError(`${context}: ${message}`, 'INTERNAL_ERROR', {
|
|
215
|
+
originalError: message,
|
|
216
|
+
originalStack: stack,
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Helper function to check if an error is a MAMA error
|
|
221
|
+
*/
|
|
222
|
+
function isMAMAError(error) {
|
|
223
|
+
return error instanceof MAMAError;
|
|
224
|
+
}
|
|
225
|
+
//# sourceMappingURL=errors.js.map
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MAMA Core - Main exports
|
|
3
|
+
*
|
|
4
|
+
* Shared modules for Memory-Augmented MCP Assistant.
|
|
5
|
+
* Used by mcp-server, claude-code-plugin, and standalone packages.
|
|
6
|
+
*
|
|
7
|
+
* @module mama-core
|
|
8
|
+
* @version 1.0.0
|
|
9
|
+
*/
|
|
10
|
+
export { generateEmbedding, generateEnhancedEmbedding, generateBatchEmbeddings, cosineSimilarity, embeddingCache, EMBEDDING_DIM, MODEL_NAME, } from './embeddings.js';
|
|
11
|
+
export { EmbeddingCache } from './embedding-cache.js';
|
|
12
|
+
export { getEmbeddingFromServer, getServerStatus, isServerRunning, getServerPort, DEFAULT_PORT, HOST, TIMEOUT_MS, type ServerStatus, } from './embedding-client.js';
|
|
13
|
+
export { initDB, getDB, getAdapter, closeDB, insertEmbedding, vectorSearch, queryVectorSearch, insertDecisionWithEmbedding, queryDecisionGraph, querySemanticEdges, updateDecisionOutcome, getPreparedStmt, getDbPath, type DatabaseAdapter as DBManagerAdapter, type PreparedStatement, type DecisionRecord, type OutcomeData, type VectorSearchParams, type SemanticEdges, type DecisionInput, } from './db-manager.js';
|
|
14
|
+
export { createAdapter, DatabaseAdapter, SQLiteAdapter, type AdapterConfig, type Statement, type VectorSearchResult, type RunResult, } from './db-adapter/index.js';
|
|
15
|
+
export { getSessionDecisions, incrementUsageSuccess, incrementUsageFailure, getDecisionById, traverseDecisionChain, DB_PATH, DB_DIR, LEGACY_DB_PATH, DEFAULT_DB_PATH, } from './memory-store.js';
|
|
16
|
+
import mama from './mama-api.js';
|
|
17
|
+
export { mama };
|
|
18
|
+
export { loadConfig, getModelName, getEmbeddingDim, getCacheDir, updateConfig, getConfigPath, DEFAULT_CONFIG, type MAMAConfig, type ConfigUpdates, } from './config-loader.js';
|
|
19
|
+
export { calculateRelevance, selectTopDecisions, formatTopNContext, testRelevanceScoring, type DecisionWithEmbedding, type QueryContext, type FormattedContext, type TestResult, } from './relevance-scorer.js';
|
|
20
|
+
export { learnDecision, generateDecisionId, getPreviousDecision, createEdge, createSupersedesEdge, markSuperseded, calculateCombinedConfidence, detectRefinement, parseReasoningForRelationships, createEdgesFromReasoning, getSupersededChainDepth, updateConfidence, VALID_EDGE_TYPES, type EdgeType, type DecisionDetection, type ToolExecution, type SessionContext, type LearnDecisionResult, type ParsedRelationship, type EvidenceItem, } from './decision-tracker.js';
|
|
21
|
+
export { validateTier, checkNodeVersion, checkSQLite, checkEmbeddings, checkDatabase, getTierDescription, getTierBanner, type TierValidation, type CheckResult, type NamedCheckResult, } from './tier-validator.js';
|
|
22
|
+
export { logProgress, logComplete, logFailed, logError, logInfo, logLoading, logSearching, } from './progress-indicator.js';
|
|
23
|
+
export { debug, info, warn, error, DebugLogger } from './debug-logger.js';
|
|
24
|
+
export { formatTimeAgo } from './time-formatter.js';
|
|
25
|
+
export { MAMAError, NotFoundError, ValidationError, DatabaseError, EmbeddingError, ConfigurationError, LinkError, RateLimitError, TimeoutError, ErrorCodes, wrapError, isMAMAError, type ErrorDetails, type ErrorResponse, type ErrorJSON, type ErrorCode, } from './errors.js';
|
|
26
|
+
export { formatContext, formatLegacyContext, formatRecall, formatList, formatTeaser, formatInstantAnswer, formatTrustContext, ensureTokenBudget, estimateTokens, extractQuickAnswer, extractCodeExample, type DecisionForFormat, type TrustContext, type SemanticEdges as FormatterSemanticEdges, type FormatOptions, } from './decision-formatter.js';
|
|
27
|
+
export { analyzeOutcome, matchesFailureIndicators, matchesSuccessIndicators, matchesPartialIndicators, extractFailureReason, getRecentDecision, calculateDurationDays, getEvidenceImpact, markOutcome, onUserPromptSubmit, FAILURE_INDICATORS, SUCCESS_INDICATORS, PARTIAL_INDICATORS, RECENT_WINDOW_MS, type HookContext, type OutcomeType, } from './outcome-tracker.js';
|
|
28
|
+
export { injectDecisionContext } from './memory-inject.js';
|
|
29
|
+
export { analyzeIntent, extractTopicKeywords, type IntentResult, type AnalyzeOptions, } from './query-intent.js';
|
|
30
|
+
export { generate, analyzeDecision, analyzeQueryIntent, isAvailable, listModels, DEFAULT_MODEL, FALLBACK_MODEL, type GenerateOptions, type DecisionAnalysisResult, type QueryIntentResult, } from './ollama-client.js';
|
|
31
|
+
export { notifyInsight } from './notification-manager.js';
|
|
32
|
+
//# sourceMappingURL=index.d.ts.map
|