266c746d50
* Refactor worker version checks and increase timeout settings - Updated the default hook timeout from 5000ms to 120000ms for improved stability. - Modified the worker version check to log a warning instead of restarting the worker on version mismatch. - Removed legacy PM2 cleanup and worker start logic, simplifying the ensureWorkerRunning function. - Enhanced polling mechanism for worker readiness with increased retries and reduced interval. * feat: implement worker queue polling to ensure processing completion before proceeding * refactor: change worker command from start to restart in hooks configuration * refactor: remove session management complexity - Simplify createSDKSession to pure INSERT OR IGNORE - Remove auto-create logic from storeObservation/storeSummary - Delete 11 unused session management methods - Derive prompt_number from user_prompts count - Keep sdk_sessions table schema unchanged for compatibility * refactor: simplify session management by removing unused methods and auto-creation logic * Refactor session prompt number retrieval in SessionRoutes - Updated the method of obtaining the prompt number from the session. - Replaced `store.getPromptCounter(sessionDbId)` with `store.getPromptNumberFromUserPrompts(claudeSessionId)` for better clarity and accuracy. - Adjusted the logic for incrementing the prompt number to derive it from the user prompts count instead of directly incrementing a counter. * refactor: replace getPromptCounter with getPromptNumberFromUserPrompts in SessionManager Phase 7 of session management simplification. Updates SessionManager to derive prompt numbers from user_prompts table count instead of using the deprecated prompt_counter column. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * refactor: simplify SessionCompletionHandler to use direct SQL query Phase 8: Remove call to findActiveSDKSession() and replace with direct database query in SessionCompletionHandler.completeByClaudeId(). This removes dependency on the deleted findActiveSDKSession() method and simplifies the code by using a straightforward SELECT query. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * refactor: remove markSessionCompleted call from SDKAgent - Delete call to markSessionCompleted() in SDKAgent.ts - Session status is no longer tracked or updated - Part of phase 9: simplifying session management 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * refactor: remove markSessionComplete method (Phase 10) - Deleted markSessionComplete() method from DatabaseManager - Removed markSessionComplete call from SessionCompletionHandler - Session completion status no longer tracked in database - Part of session management simplification effort 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * refactor: replace deleted updateSDKSessionId calls in import script (Phase 11) - Replace updateSDKSessionId() calls with direct SQL UPDATE statements - Method was deleted in Phase 3 as part of session management simplification - Import script now uses direct database access consistently 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * test: add validation for SQL updates in sdk_sessions table * refactor: enhance worker-cli to support manual and automated runs * Remove cleanup hook and associated session completion logic - Deleted the cleanup-hook implementation from the hooks directory. - Removed the session completion endpoint that was used by the cleanup hook. - Updated the SessionCompletionHandler to eliminate the completeByClaudeId method and its dependencies. - Adjusted the SessionRoutes to reflect the removal of the session completion route. * fix: update worker-cli command to use bun for consistency * feat: Implement timestamp fix for observations and enhance processing logic - Added `earliestPendingTimestamp` to `ActiveSession` to track the original timestamp of the earliest pending message. - Updated `SDKAgent` to capture and utilize the earliest pending timestamp during response processing. - Modified `SessionManager` to track the earliest timestamp when yielding messages. - Created scripts for fixing corrupted timestamps, validating fixes, and investigating timestamp issues. - Verified that all corrupted observations have been repaired and logic for future processing is sound. - Ensured orphan processing can be safely re-enabled after validation. * feat: Enhance SessionStore to support custom database paths and add timestamp fields for observations and summaries * Refactor pending queue processing and add management endpoints - Disabled automatic recovery of orphaned queues on startup; users must now use the new /api/pending-queue/process endpoint. - Updated processOrphanedQueues method to processPendingQueues with improved session handling and return detailed results. - Added new API endpoints for managing pending queues: GET /api/pending-queue and POST /api/pending-queue/process. - Introduced a new script (check-pending-queue.ts) for checking and processing pending observation queues interactively or automatically. - Enhanced logging and error handling for better monitoring of session processing. * updated agent sdk * feat: Add manual recovery guide and queue management endpoints to documentation --------- Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
114 lines
3.0 KiB
TypeScript
114 lines
3.0 KiB
TypeScript
/**
|
|
* DatabaseManager: Single long-lived database connection
|
|
*
|
|
* Responsibility:
|
|
* - Manage single database connection for worker lifetime
|
|
* - Provide centralized access to SessionStore and SessionSearch
|
|
* - High-level database operations
|
|
* - ChromaSync integration
|
|
*/
|
|
|
|
import { SessionStore } from '../sqlite/SessionStore.js';
|
|
import { SessionSearch } from '../sqlite/SessionSearch.js';
|
|
import { ChromaSync } from '../sync/ChromaSync.js';
|
|
import { logger } from '../../utils/logger.js';
|
|
import type { DBSession } from '../worker-types.js';
|
|
|
|
export class DatabaseManager {
|
|
private sessionStore: SessionStore | null = null;
|
|
private sessionSearch: SessionSearch | null = null;
|
|
private chromaSync: ChromaSync | null = null;
|
|
|
|
/**
|
|
* Initialize database connection (once, stays open)
|
|
*/
|
|
async initialize(): Promise<void> {
|
|
// Open database connection (ONCE)
|
|
this.sessionStore = new SessionStore();
|
|
this.sessionSearch = new SessionSearch();
|
|
|
|
// Initialize ChromaSync
|
|
this.chromaSync = new ChromaSync('claude-mem');
|
|
|
|
// Start background backfill (fire-and-forget)
|
|
this.chromaSync.ensureBackfilled().catch(error => {
|
|
logger.error('DB', 'Chroma backfill failed (non-fatal)', {}, error);
|
|
});
|
|
|
|
logger.info('DB', 'Database initialized');
|
|
}
|
|
|
|
/**
|
|
* Close database connection and cleanup all resources
|
|
*/
|
|
async close(): Promise<void> {
|
|
// Close ChromaSync first (terminates uvx/python processes)
|
|
if (this.chromaSync) {
|
|
await this.chromaSync.close();
|
|
this.chromaSync = null;
|
|
}
|
|
|
|
if (this.sessionStore) {
|
|
this.sessionStore.close();
|
|
this.sessionStore = null;
|
|
}
|
|
if (this.sessionSearch) {
|
|
this.sessionSearch.close();
|
|
this.sessionSearch = null;
|
|
}
|
|
logger.info('DB', 'Database closed');
|
|
}
|
|
|
|
/**
|
|
* Get SessionStore instance (throws if not initialized)
|
|
*/
|
|
getSessionStore(): SessionStore {
|
|
if (!this.sessionStore) {
|
|
throw new Error('Database not initialized');
|
|
}
|
|
return this.sessionStore;
|
|
}
|
|
|
|
/**
|
|
* Get SessionSearch instance (throws if not initialized)
|
|
*/
|
|
getSessionSearch(): SessionSearch {
|
|
if (!this.sessionSearch) {
|
|
throw new Error('Database not initialized');
|
|
}
|
|
return this.sessionSearch;
|
|
}
|
|
|
|
/**
|
|
* Get ChromaSync instance (throws if not initialized)
|
|
*/
|
|
getChromaSync(): ChromaSync {
|
|
if (!this.chromaSync) {
|
|
throw new Error('ChromaSync not initialized');
|
|
}
|
|
return this.chromaSync;
|
|
}
|
|
|
|
// REMOVED: cleanupOrphanedSessions - violates "EVERYTHING SHOULD SAVE ALWAYS"
|
|
// Worker restarts don't make sessions orphaned. Sessions are managed by hooks
|
|
// and exist independently of worker state.
|
|
|
|
/**
|
|
* Get session by ID (throws if not found)
|
|
*/
|
|
getSessionById(sessionDbId: number): {
|
|
id: number;
|
|
claude_session_id: string;
|
|
sdk_session_id: string | null;
|
|
project: string;
|
|
user_prompt: string;
|
|
} {
|
|
const session = this.getSessionStore().getSessionById(sessionDbId);
|
|
if (!session) {
|
|
throw new Error(`Session ${sessionDbId} not found`);
|
|
}
|
|
return session;
|
|
}
|
|
|
|
}
|