0cbcbd970a
* Initial plan * Add .catch() handlers to Chroma sync operations to prevent worker crashes Co-authored-by: thedotmack <683968+thedotmack@users.noreply.github.com> * Add .catch() handler to syncUserPrompt to prevent crashes Co-authored-by: thedotmack <683968+thedotmack@users.noreply.github.com> * Update mem-search plugin with new features and improvements --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: thedotmack <683968+thedotmack@users.noreply.github.com> Co-authored-by: Alex Newman <thedotmack@gmail.com>
Worker Service Architecture
Overview
The Worker Service is an Express HTTP server that handles all claude-mem operations. It runs on port 37777 (configurable via CLAUDE_MEM_WORKER_PORT) and is managed by PM2.
Request Flow
Hook (plugin/scripts/*-hook.js)
→ HTTP Request to Worker (localhost:37777)
→ Route Handler (http/routes/*.ts)
→ MCP Server Tool (for search) OR Service Layer (for session/data)
→ Database (SQLite3 + Chroma vector DB)
Directory Structure
src/services/worker/
├── README.md # This file
├── WorkerService.ts # Slim orchestrator (~150 lines)
├── http/ # HTTP layer
│ ├── middleware.ts # Shared middleware (logging, CORS, etc.)
│ └── routes/ # Route handlers organized by feature area
│ ├── SessionRoutes.ts # Session lifecycle (init, observations, summarize, complete)
│ ├── DataRoutes.ts # Data retrieval (get observations, summaries, prompts, stats)
│ ├── SearchRoutes.ts # Search/MCP proxy (all search endpoints)
│ ├── SettingsRoutes.ts # Settings, MCP toggle, branch switching
│ └── ViewerRoutes.ts # Health check, viewer UI, SSE stream
└── services/ # Business logic services (existing, NO CHANGES in Phase 1)
├── DatabaseManager.ts # SQLite connection management
├── SessionManager.ts # Session state tracking
├── SDKAgent.ts # Claude Agent SDK for observations/summaries
├── SSEBroadcaster.ts # Server-Sent Events for real-time updates
├── PaginationHelper.ts # Query pagination utilities
├── SettingsManager.ts # User settings CRUD
└── BranchManager.ts # Git branch operations
Route Organization
ViewerRoutes.ts
GET /health- Health check endpointGET /- Serve viewer UI (React app)GET /stream- SSE stream for real-time updates
SessionRoutes.ts
Session lifecycle operations (use service layer directly):
POST /sessions/init- Initialize new sessionPOST /sessions/:sessionId/observations- Add tool usage observationsPOST /sessions/:sessionId/summarize- Trigger session summaryGET /sessions/:sessionId/status- Get session statusDELETE /sessions/:sessionId- Delete sessionPOST /sessions/:sessionId/complete- Mark session completePOST /sessions/claude-id/:claudeId/observations- Add observations by claude_idPOST /sessions/claude-id/:claudeId/summarize- Summarize by claude_idPOST /sessions/claude-id/:claudeId/complete- Complete by claude_id
DataRoutes.ts
Data retrieval operations (use service layer directly):
GET /observations- List observations (paginated)GET /summaries- List session summaries (paginated)GET /prompts- List user prompts (paginated)GET /observations/:id- Get observation by IDGET /sessions/:sessionId- Get session by IDGET /prompts/:id- Get prompt by IDGET /stats- Get database statisticsGET /projects- List all projectsGET /processing- Get processing statusPOST /processing- Set processing status
SearchRoutes.ts
All search operations (proxy to MCP server):
GET /search- Unified search (observations + sessions + prompts)GET /timeline- Unified timeline contextGET /decisions- Decision-type observationsGET /changes- Change-related observationsGET /how-it-works- How-it-works explanationsGET /search/observations- Search observationsGET /search/sessions- Search sessionsGET /search/prompts- Search promptsGET /search/by-concept- Find by concept tagGET /search/by-file- Find by file pathGET /search/by-type- Find by observation typeGET /search/recent-context- Get recent contextGET /search/context-timeline- Get context timelineGET /context/preview- Preview contextGET /context/inject- Inject contextGET /search/timeline-by-query- Timeline by search queryGET /search/help- Search help
SettingsRoutes.ts
Settings and configuration (use service layer directly):
GET /settings- Get user settingsPOST /settings- Update user settingsGET /mcp/status- Get MCP server statusPOST /mcp/toggle- Toggle MCP server on/offGET /branch/status- Get git branch infoPOST /branch/switch- Switch git branchPOST /branch/update- Pull branch updates
Current State (Phase 1)
Phase 1 is a pure code reorganization with ZERO functional changes:
- Extract route handlers from WorkerService.ts monolith
- Organize into logical route classes
- Keep all existing behavior identical
MCP vs Direct DB Split (inherited, not changed in Phase 1):
- Search operations → MCP server (mem-search)
- Session/data operations → Direct DB access via service layer
Future Phase 2
Phase 2 will unify the architecture:
- Expand MCP server to handle ALL operations (not just search)
- Convert all route handlers to proxy through MCP
- Move database logic from service layer into MCP tools
- Result: Worker becomes pure HTTP → MCP proxy for maximum portability
This separation allows the worker to be deployed anywhere (as a CLI tool, cloud service, etc.) without carrying database dependencies.
Adding New Endpoints
- Choose the appropriate route file based on the endpoint's purpose
- Add the route handler method to the class
- Register the route in the
setupRoutes()method - Import any needed services in the constructor
- Follow the existing patterns for error handling and logging
Example:
// In DataRoutes.ts
private async handleGetFoo(req: Request, res: Response): Promise<void> {
try {
const result = await this.dbManager.getFoo();
res.json(result);
} catch (error) {
logger.failure('WORKER', 'Get foo failed', {}, error as Error);
res.status(500).json({ error: (error as Error).message });
}
}
// Register in setupRoutes()
app.get('/foo', this.handleGetFoo.bind(this));
Key Design Principles
- Progressive Disclosure: Navigate from high-level (WorkerService.ts) to specific routes to implementation details
- Single Responsibility: Each route class handles one feature area
- Dependency Injection: Route classes receive only the services they need
- Consistent Error Handling: All handlers use try/catch with logger.failure()
- Bound Methods: All route handlers use
.bind(this)to preserve context