mirror of
https://github.com/thedotmack/claude-mem
synced 2026-04-25 17:15:04 +02:00
Deletes files and symbols with zero importers or self-declared deprecation.
No behavior change — structural cleanup only.
Removed:
- hook-response.ts, utils/bun-path.ts (zero importers)
- cli/handlers/user-message.ts (not wired in hooks.json)
- services/Context.ts + context-generator.ts (deprecated stubs)
- sqlite/migrations.ts (645 lines, pre-SDK schema, unused)
- DatabaseManager singleton + getDatabase + initializeDatabase
- 6 sqlite re-export shells (Observations/Sessions/Summaries/Prompts/Timeline/Import)
- worker/search/{strategies,filters}/ dirs (dead via unused SearchOrchestrator)
- SearchOrchestrator, TimelineBuilder, ResultFormatter
- TimelineService.formatTimeline (137 lines, unused)
- ProcessManager.cleanupOrphanedProcesses + createSignalHandler
- Duplicate php: key in smart-file-read/parser.ts
Rewired:
- SearchRoutes dynamic imports (services/Context → services/context)
- CorpusBuilder: SearchOrchestrator → SearchManager.search({format:'json'})
- build-hooks.js entry: context-generator.ts → services/context/index.ts
- scripts/ imports for moved transcript-parser.ts
Moved:
- utils/transcript-parser.ts → scripts/transcript-parser.ts (only callers)
Skipped (plan was wrong):
- consecutiveRestarts: live backoff math at SessionRoutes.ts:348
- AgentFormatter stubs: wired to HeaderRenderer with passing tests
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
199 lines
7.2 KiB
TypeScript
199 lines
7.2 KiB
TypeScript
/**
|
|
* Session module tests
|
|
* Tests modular session functions with in-memory database
|
|
*
|
|
* Sources:
|
|
* - API patterns from src/services/sqlite/sessions/create.ts
|
|
* - API patterns from src/services/sqlite/sessions/get.ts
|
|
* - Test pattern from tests/session_store.test.ts
|
|
*/
|
|
|
|
import { describe, it, expect, beforeEach, afterEach } from 'bun:test';
|
|
import { ClaudeMemDatabase } from '../../src/services/sqlite/Database.js';
|
|
import {
|
|
createSDKSession,
|
|
getSessionById,
|
|
updateMemorySessionId,
|
|
} from '../../src/services/sqlite/index.js';
|
|
import type { Database } from 'bun:sqlite';
|
|
|
|
describe('Sessions Module', () => {
|
|
let db: Database;
|
|
|
|
beforeEach(() => {
|
|
db = new ClaudeMemDatabase(':memory:').db;
|
|
});
|
|
|
|
afterEach(() => {
|
|
db.close();
|
|
});
|
|
|
|
describe('createSDKSession', () => {
|
|
it('should create a new session and return numeric ID', () => {
|
|
const contentSessionId = 'content-session-123';
|
|
const project = 'test-project';
|
|
const userPrompt = 'Initial user prompt';
|
|
|
|
const sessionId = createSDKSession(db, contentSessionId, project, userPrompt);
|
|
|
|
expect(typeof sessionId).toBe('number');
|
|
expect(sessionId).toBeGreaterThan(0);
|
|
});
|
|
|
|
it('should be idempotent - return same ID for same content_session_id', () => {
|
|
const contentSessionId = 'content-session-456';
|
|
const project = 'test-project';
|
|
const userPrompt = 'Initial user prompt';
|
|
|
|
const sessionId1 = createSDKSession(db, contentSessionId, project, userPrompt);
|
|
const sessionId2 = createSDKSession(db, contentSessionId, project, 'Different prompt');
|
|
|
|
expect(sessionId1).toBe(sessionId2);
|
|
});
|
|
|
|
it('should create different sessions for different content_session_ids', () => {
|
|
const sessionId1 = createSDKSession(db, 'session-a', 'project', 'prompt');
|
|
const sessionId2 = createSDKSession(db, 'session-b', 'project', 'prompt');
|
|
|
|
expect(sessionId1).not.toBe(sessionId2);
|
|
});
|
|
});
|
|
|
|
describe('getSessionById', () => {
|
|
it('should retrieve session by ID', () => {
|
|
const contentSessionId = 'content-session-get';
|
|
const project = 'test-project';
|
|
const userPrompt = 'Test prompt';
|
|
|
|
const sessionId = createSDKSession(db, contentSessionId, project, userPrompt);
|
|
const session = getSessionById(db, sessionId);
|
|
|
|
expect(session).not.toBeNull();
|
|
expect(session?.id).toBe(sessionId);
|
|
expect(session?.content_session_id).toBe(contentSessionId);
|
|
expect(session?.project).toBe(project);
|
|
expect(session?.user_prompt).toBe(userPrompt);
|
|
// memory_session_id should be null initially (set via updateMemorySessionId)
|
|
expect(session?.memory_session_id).toBeNull();
|
|
});
|
|
|
|
it('should return null for non-existent session', () => {
|
|
const session = getSessionById(db, 99999);
|
|
|
|
expect(session).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe('custom_title', () => {
|
|
it('should store custom_title when provided at creation', () => {
|
|
const sessionId = createSDKSession(db, 'session-title-1', 'project', 'prompt', 'My Agent');
|
|
const session = getSessionById(db, sessionId);
|
|
|
|
expect(session?.custom_title).toBe('My Agent');
|
|
});
|
|
|
|
it('should default custom_title to null when not provided', () => {
|
|
const sessionId = createSDKSession(db, 'session-title-2', 'project', 'prompt');
|
|
const session = getSessionById(db, sessionId);
|
|
|
|
expect(session?.custom_title).toBeNull();
|
|
});
|
|
|
|
it('should backfill custom_title on idempotent call if not already set', () => {
|
|
const sessionId = createSDKSession(db, 'session-title-3', 'project', 'prompt');
|
|
let session = getSessionById(db, sessionId);
|
|
expect(session?.custom_title).toBeNull();
|
|
|
|
// Second call with custom_title should backfill
|
|
createSDKSession(db, 'session-title-3', 'project', 'prompt', 'Backfilled Title');
|
|
session = getSessionById(db, sessionId);
|
|
expect(session?.custom_title).toBe('Backfilled Title');
|
|
});
|
|
|
|
it('should not overwrite existing custom_title on idempotent call', () => {
|
|
const sessionId = createSDKSession(db, 'session-title-4', 'project', 'prompt', 'Original');
|
|
let session = getSessionById(db, sessionId);
|
|
expect(session?.custom_title).toBe('Original');
|
|
|
|
// Second call should NOT overwrite
|
|
createSDKSession(db, 'session-title-4', 'project', 'prompt', 'Attempted Override');
|
|
session = getSessionById(db, sessionId);
|
|
expect(session?.custom_title).toBe('Original');
|
|
});
|
|
|
|
it('should handle empty string custom_title as no title', () => {
|
|
const sessionId = createSDKSession(db, 'session-title-5', 'project', 'prompt', '');
|
|
const session = getSessionById(db, sessionId);
|
|
|
|
// Empty string becomes null via the || null conversion
|
|
expect(session?.custom_title).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe('platform_source', () => {
|
|
it('should default new sessions to claude when platformSource is omitted', () => {
|
|
const sessionId = createSDKSession(db, 'session-platform-1', 'project', 'prompt');
|
|
const session = getSessionById(db, sessionId);
|
|
|
|
expect(session?.platform_source).toBe('claude');
|
|
});
|
|
|
|
it('should preserve a non-default platform_source for legacy callers that omit platformSource', () => {
|
|
const sessionId = createSDKSession(db, 'session-platform-2', 'project', 'prompt', undefined, 'codex');
|
|
let session = getSessionById(db, sessionId);
|
|
expect(session?.platform_source).toBe('codex');
|
|
|
|
createSDKSession(db, 'session-platform-2', 'project', 'prompt');
|
|
session = getSessionById(db, sessionId);
|
|
expect(session?.platform_source).toBe('codex');
|
|
});
|
|
|
|
it('should reject explicit platform_source conflicts for the same session', () => {
|
|
createSDKSession(db, 'session-platform-3', 'project', 'prompt', undefined, 'codex');
|
|
|
|
expect(() => createSDKSession(
|
|
db,
|
|
'session-platform-3',
|
|
'project',
|
|
'prompt',
|
|
undefined,
|
|
'claude'
|
|
)).toThrow(/Platform source conflict/);
|
|
});
|
|
});
|
|
|
|
describe('updateMemorySessionId', () => {
|
|
it('should update memory_session_id for existing session', () => {
|
|
const contentSessionId = 'content-session-update';
|
|
const project = 'test-project';
|
|
const userPrompt = 'Test prompt';
|
|
const memorySessionId = 'memory-session-abc123';
|
|
|
|
const sessionId = createSDKSession(db, contentSessionId, project, userPrompt);
|
|
|
|
// Verify memory_session_id is null initially
|
|
let session = getSessionById(db, sessionId);
|
|
expect(session?.memory_session_id).toBeNull();
|
|
|
|
// Update memory session ID
|
|
updateMemorySessionId(db, sessionId, memorySessionId);
|
|
|
|
// Verify update
|
|
session = getSessionById(db, sessionId);
|
|
expect(session?.memory_session_id).toBe(memorySessionId);
|
|
});
|
|
|
|
it('should allow updating to different memory_session_id', () => {
|
|
const sessionId = createSDKSession(db, 'session-x', 'project', 'prompt');
|
|
|
|
updateMemorySessionId(db, sessionId, 'memory-1');
|
|
let session = getSessionById(db, sessionId);
|
|
expect(session?.memory_session_id).toBe('memory-1');
|
|
|
|
updateMemorySessionId(db, sessionId, 'memory-2');
|
|
session = getSessionById(db, sessionId);
|
|
expect(session?.memory_session_id).toBe('memory-2');
|
|
});
|
|
});
|
|
});
|