@jungjaehoon/mama-core 1.1.4 → 1.1.5

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.
@@ -53,7 +53,7 @@ export interface DecisionRecord {
53
53
  refined_from?: string | string[] | null;
54
54
  created_at: number;
55
55
  updated_at?: number;
56
- edges?: unknown[];
56
+ edges?: DecisionEdgeRow[];
57
57
  }
58
58
  export interface OutcomeData {
59
59
  outcome?: string | null;
@@ -68,17 +68,40 @@ export interface VectorSearchParams {
68
68
  threshold?: number;
69
69
  timeWindow?: number;
70
70
  }
71
+ export interface DecisionEdgeRow {
72
+ from_id: string;
73
+ to_id: string;
74
+ relationship: string;
75
+ reason?: string | null;
76
+ weight?: number;
77
+ created_at?: number;
78
+ created_by?: string;
79
+ approved_by_user?: number | null;
80
+ decision_id?: string | null;
81
+ evidence?: string | null;
82
+ }
83
+ export interface SemanticEdgeItem {
84
+ from_id: string;
85
+ to_id: string;
86
+ relationship: string;
87
+ reason?: string;
88
+ topic: string;
89
+ decision: string;
90
+ confidence?: number;
91
+ created_at?: string;
92
+ approved_by_user?: number | null;
93
+ }
71
94
  export interface SemanticEdges {
72
- refines: unknown[];
73
- refined_by: unknown[];
74
- contradicts: unknown[];
75
- contradicted_by: unknown[];
76
- builds_on: unknown[];
77
- built_on_by: unknown[];
78
- debates: unknown[];
79
- debated_by: unknown[];
80
- synthesizes: unknown[];
81
- synthesized_by: unknown[];
95
+ refines: SemanticEdgeItem[];
96
+ refined_by: SemanticEdgeItem[];
97
+ contradicts: SemanticEdgeItem[];
98
+ contradicted_by: SemanticEdgeItem[];
99
+ builds_on: SemanticEdgeItem[];
100
+ built_on_by: SemanticEdgeItem[];
101
+ debates: SemanticEdgeItem[];
102
+ debated_by: SemanticEdgeItem[];
103
+ synthesizes: SemanticEdgeItem[];
104
+ synthesized_by: SemanticEdgeItem[];
82
105
  }
83
106
  /**
84
107
  * Initialize SQLite database adapter and connect
@@ -20,9 +20,17 @@ import type { Server as HTTPServer } from 'http';
20
20
  /**
21
21
  * Message router interface
22
22
  */
23
+ interface StreamCallbacks {
24
+ onDelta?: (text: string) => void;
25
+ onToolUse?: (toolName: string, input: Record<string, unknown>) => void;
26
+ onToolComplete?: (toolName: string, toolUseId: string, isError: boolean) => void;
27
+ onFinal?: (response: unknown) => void;
28
+ onError?: (error: Error) => void;
29
+ }
23
30
  interface MessageRouter {
24
31
  process(message: NormalizedMessage, options?: {
25
32
  onQueued?: () => void;
33
+ onStream?: StreamCallbacks;
26
34
  }): Promise<RouterResult>;
27
35
  }
28
36
  /**
@@ -218,6 +218,8 @@ async function handleClientMessage(clientId, message, clientInfo, messageRouter,
218
218
  }
219
219
  }, 10000); // Every 10 seconds
220
220
  let result;
221
+ let deltasSent = false;
222
+ let toolIndex = 0;
221
223
  try {
222
224
  // Build contentBlocks from attachments (files are pre-compressed by upload-handler)
223
225
  let contentBlocks = undefined;
@@ -303,18 +305,33 @@ async function handleClientMessage(clientId, message, clientInfo, messageRouter,
303
305
  }
304
306
  logger.info(`Message queued for ${clientId} (session busy)`);
305
307
  },
308
+ onStream: {
309
+ onDelta: (text) => {
310
+ deltasSent = true;
311
+ safeSend(clientInfo.ws, JSON.stringify({ type: 'stream', content: text }));
312
+ },
313
+ onToolUse: (tool, input) => {
314
+ const idx = toolIndex++;
315
+ safeSend(clientInfo.ws, JSON.stringify({ type: 'tool_use', tool, index: idx, input }));
316
+ },
317
+ onToolComplete: (tool, _toolUseId, isError) => {
318
+ safeSend(clientInfo.ws, JSON.stringify({ type: 'tool_complete', tool, index: toolIndex - 1, isError }));
319
+ },
320
+ },
306
321
  });
307
322
  }
308
323
  finally {
309
324
  clearInterval(keepAliveInterval);
310
325
  }
311
- // Send response as stream (for Chat tab compatibility)
312
- safeSend(clientInfo.ws, JSON.stringify({
313
- type: 'stream',
314
- content: result.response,
315
- sessionId: result.sessionId,
316
- }));
317
- // Send stream end
326
+ // Only send full response if no deltas were streamed (Codex fallback)
327
+ if (!deltasSent) {
328
+ safeSend(clientInfo.ws, JSON.stringify({
329
+ type: 'stream',
330
+ content: result.response,
331
+ sessionId: result.sessionId,
332
+ }));
333
+ }
334
+ // Always send stream end
318
335
  safeSend(clientInfo.ws, JSON.stringify({
319
336
  type: 'stream_end',
320
337
  sessionId: result.sessionId,
package/dist/index.d.ts CHANGED
@@ -10,7 +10,7 @@
10
10
  export { generateEmbedding, generateEnhancedEmbedding, generateBatchEmbeddings, cosineSimilarity, embeddingCache, EMBEDDING_DIM, MODEL_NAME, } from './embeddings.js';
11
11
  export { EmbeddingCache } from './embedding-cache.js';
12
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';
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 SemanticEdgeItem, type DecisionInput, } from './db-manager.js';
14
14
  export { createAdapter, DatabaseAdapter, SQLiteAdapter, type AdapterConfig, type Statement, type VectorSearchResult, type RunResult, } from './db-adapter/index.js';
15
15
  export { getSessionDecisions, incrementUsageSuccess, incrementUsageFailure, getDecisionById, traverseDecisionChain, DB_PATH, DB_DIR, LEGACY_DB_PATH, DEFAULT_DB_PATH, } from './memory-store.js';
16
16
  import mama from './mama-api.js';
@@ -172,6 +172,9 @@ export interface LoadCheckpointResult {
172
172
  * Outcome badge map type
173
173
  */
174
174
  export type OutcomeBadgeMap = Record<string, string | null>;
175
+ /**
176
+ * Raw semantic edge from database
177
+ */
175
178
  /**
176
179
  * Recall options
177
180
  */
@@ -412,7 +415,51 @@ declare function save({ topic, decision, reasoning, confidence, type, outcome, f
412
415
  * const markdown = await mama.recall('auth_strategy', { format: 'markdown' });
413
416
  * // → "📋 Decision History: auth_strategy\n━━━━━━━━..."
414
417
  */
415
- declare function recall(topic: string, options?: RecallOptions): Promise<unknown>;
418
+ interface RecallEdgeRef {
419
+ to_topic?: string;
420
+ to_decision?: string;
421
+ to_id?: string;
422
+ from_topic?: string;
423
+ from_decision?: string;
424
+ from_id?: string;
425
+ reason?: string | null;
426
+ confidence?: number;
427
+ created_at?: string | number;
428
+ }
429
+ interface RecallGraphResult {
430
+ topic: string;
431
+ supersedes_chain: Array<{
432
+ id: string;
433
+ decision: string;
434
+ reasoning?: string | null;
435
+ confidence?: number;
436
+ outcome?: string | null;
437
+ failure_reason?: string | null;
438
+ created_at: number;
439
+ updated_at?: number;
440
+ superseded_by?: string | null;
441
+ supersedes?: string | null;
442
+ }>;
443
+ semantic_edges: {
444
+ refines: RecallEdgeRef[];
445
+ refined_by: RecallEdgeRef[];
446
+ contradicts: RecallEdgeRef[];
447
+ contradicted_by: RecallEdgeRef[];
448
+ };
449
+ meta: {
450
+ count: number;
451
+ latest_id?: string;
452
+ has_supersedes_chain: boolean;
453
+ has_semantic_edges: boolean;
454
+ semantic_edges_count: {
455
+ refines: number;
456
+ refined_by: number;
457
+ contradicts: number;
458
+ contradicted_by: number;
459
+ };
460
+ };
461
+ }
462
+ declare function recall(topic: string, options?: RecallOptions): Promise<string | RecallGraphResult>;
416
463
  /**
417
464
  * Update outcome of a decision
418
465
  *
@@ -505,13 +552,21 @@ declare function saveCheckpoint(summary: string, openFiles?: string[], nextSteps
505
552
  *
506
553
  * @returns {Promise<Object|null>} Latest checkpoint or null
507
554
  */
555
+ interface ConversationMessage {
556
+ role: string;
557
+ content: string | Array<{
558
+ type: string;
559
+ text?: string;
560
+ [key: string]: unknown;
561
+ }>;
562
+ }
508
563
  interface CheckpointRow {
509
564
  id?: number;
510
565
  timestamp?: number;
511
566
  summary?: string;
512
567
  open_files?: string | string[];
513
568
  next_steps?: string;
514
- recent_conversation?: string | unknown[];
569
+ recent_conversation?: string | ConversationMessage[];
515
570
  status?: string;
516
571
  }
517
572
  declare function loadCheckpoint(): Promise<CheckpointRow | null>;
package/dist/mama-api.js CHANGED
@@ -347,26 +347,6 @@ async function _getReasoningGraphInfo(topic, currentId) {
347
347
  };
348
348
  }
349
349
  }
350
- /**
351
- * Recall decisions by topic
352
- *
353
- * DEFAULT: Returns JSON object with decisions and edges (LLM-first design)
354
- * OPTIONAL: Returns Markdown string if format='markdown' (for human display)
355
- *
356
- * @param {string} topic - Decision topic to recall
357
- * @param {Object} [options] - Options
358
- * @param {string} [options.format='json'] - Output format: 'json' (default) or 'markdown'
359
- * @returns {Promise<Object|string>} Decision history as JSON or Markdown
360
- *
361
- * @example
362
- * // LLM usage (default)
363
- * const data = await mama.recall('auth_strategy');
364
- * // → { topic, decisions: [...], edges: [...], meta: {...} }
365
- *
366
- * // Human display
367
- * const markdown = await mama.recall('auth_strategy', { format: 'markdown' });
368
- * // → "📋 Decision History: auth_strategy\n━━━━━━━━..."
369
- */
370
350
  async function recall(topic, options = {}) {
371
351
  if (!topic || typeof topic !== 'string') {
372
352
  throw new Error('mama.recall() requires topic (string)');
@@ -382,18 +362,22 @@ async function recall(topic, options = {}) {
382
362
  topic,
383
363
  supersedes_chain: [],
384
364
  semantic_edges: { refines: [], refined_by: [], contradicts: [], contradicted_by: [] },
385
- meta: { count: 0 },
365
+ meta: {
366
+ count: 0,
367
+ has_supersedes_chain: false,
368
+ has_semantic_edges: false,
369
+ semantic_edges_count: { refines: 0, refined_by: 0, contradicts: 0, contradicted_by: 0 },
370
+ },
386
371
  };
387
372
  }
388
373
  // Query semantic edges for all decisions
389
374
  const decisionIds = decisions.map((d) => d.id);
390
- const rawEdgesResult = await (0, memory_store_js_1.querySemanticEdges)(decisionIds);
391
- const rawEdges = (rawEdgesResult || {});
375
+ const rawEdges = await (0, memory_store_js_1.querySemanticEdges)(decisionIds);
392
376
  const semanticEdges = {
393
- refines: (rawEdges.refines || []),
394
- refined_by: (rawEdges.refined_by || []),
395
- contradicts: (rawEdges.contradicts || []),
396
- contradicted_by: (rawEdges.contradicted_by || []),
377
+ refines: rawEdges.refines || [],
378
+ refined_by: rawEdges.refined_by || [],
379
+ contradicts: rawEdges.contradicts || [],
380
+ contradicted_by: rawEdges.contradicted_by || [],
397
381
  };
398
382
  // Markdown format (for human display)
399
383
  if (format === 'markdown') {
@@ -566,7 +550,6 @@ async function expandWithGraph(candidates) {
566
550
  synthesized_by: rawEdges.synthesized_by || [],
567
551
  };
568
552
  // Helper to add edge to graph
569
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- dynamic property access with idField
570
553
  const addEdge = (edge, idField, source, rank, simFactor) => {
571
554
  const id = edge[idField];
572
555
  if (!graphEnhanced.has(id)) {
@@ -698,8 +681,10 @@ async function suggest(userQuestion, options = {}) {
698
681
  let results = [];
699
682
  let searchMethod = 'vector';
700
683
  try {
701
- // Check if vectorSearch prepared statement exists
702
- (0, memory_store_js_1.getPreparedStmt)('vectorSearch');
684
+ // Check if vector search is available (sqlite-vec loaded)
685
+ if (!(0, memory_store_js_1.getAdapter)().vectorSearchEnabled) {
686
+ throw new Error('Vector search not available');
687
+ }
703
688
  // Generate query embedding
704
689
  const queryEmbedding = await (0, embeddings_js_1.generateEmbedding)(userQuestion);
705
690
  // Adaptive threshold (shorter queries need higher confidence)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jungjaehoon/mama-core",
3
- "version": "1.1.4",
3
+ "version": "1.1.5",
4
4
  "description": "MAMA Core - Shared modules for Memory-Augmented MCP Assistant",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",