feat: Implement SQLite storage for CLI execution history

- Introduced a new SQLite-based storage backend for managing CLI execution history.
- Added `CliHistoryStore` class to handle conversation records and turns with efficient queries.
- Migrated existing JSON history files to the new SQLite format.
- Updated CLI executor to use asynchronous and synchronous methods for saving and loading conversations.
- Enhanced execution history retrieval with support for filtering by tool, status, and search terms.
- Added prompt concatenation utilities to build multi-turn prompts in various formats (plain, YAML, JSON).
- Implemented batch deletion of conversations and improved error handling for database operations.
This commit is contained in:
catlog22
2025-12-13 14:53:53 +08:00
parent 37417caca2
commit 029384c427
9 changed files with 2380 additions and 279 deletions

View File

@@ -8,7 +8,7 @@ import { createHash } from 'crypto';
import { scanSessions } from './session-scanner.js';
import { aggregateData } from './data-aggregator.js';
import { resolvePath, getRecentPaths, trackRecentPath, removeRecentPath, normalizePathForDisplay, getWorkflowDir } from '../utils/path-resolver.js';
import { getCliToolsStatus, getExecutionHistory, getExecutionDetail, getConversationDetail, deleteExecution, executeCliTool } from '../tools/cli-executor.js';
import { getCliToolsStatus, getExecutionHistory, getExecutionHistoryAsync, getExecutionDetail, getConversationDetail, deleteExecution, deleteExecutionAsync, batchDeleteExecutionsAsync, executeCliTool } from '../tools/cli-executor.js';
import { getAllManifests } from './manifest.js';
import { checkVenvStatus, bootstrapVenv, executeCodexLens, checkSemanticStatus, installSemantic } from '../tools/codex-lens.js';
import { listTools } from '../tools/index.js';
@@ -635,6 +635,27 @@ export async function startServer(options: ServerOptions = {}): Promise<http.Ser
return;
}
// API: CLI Settings
if (pathname === '/api/cli/settings' && req.method === 'POST') {
handlePostRequest(req, res, async (body) => {
const { storageBackend: backend } = body as { storageBackend?: string };
if (backend && (backend === 'sqlite' || backend === 'json')) {
// Import and set storage backend dynamically
try {
const { setStorageBackend } = await import('../tools/cli-executor.js');
setStorageBackend(backend as 'sqlite' | 'json');
return { success: true, storageBackend: backend };
} catch (err) {
return { success: false, error: (err as Error).message };
}
}
return { success: true, message: 'No changes' };
});
return;
}
// API: CLI Execution History
if (pathname === '/api/cli/history') {
const projectPath = url.searchParams.get('path') || initialPath;
@@ -686,6 +707,21 @@ export async function startServer(options: ServerOptions = {}): Promise<http.Ser
return;
}
// API: Batch Delete CLI Executions
if (pathname === '/api/cli/batch-delete' && req.method === 'POST') {
handlePostRequest(req, res, async (body) => {
const { path: projectPath, ids } = body;
if (!ids || !Array.isArray(ids) || ids.length === 0) {
return { error: 'ids array is required', status: 400 };
}
const basePath = projectPath || initialPath;
return await batchDeleteExecutionsAsync(basePath, ids);
});
return;
}
// API: Execute CLI Tool
if (pathname === '/api/cli/execute' && req.method === 'POST') {
handlePostRequest(req, res, async (body) => {