specmem-hardwicksoftware 3.7.8 → 3.7.10
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.
|
@@ -189,20 +189,50 @@ export class EmbeddingServerManager extends EventEmitter {
|
|
|
189
189
|
logger.info({ count: runningServers.length, pids: runningServers.map(s => s.pid) },
|
|
190
190
|
'[EmbeddingServerManager] FIX 1B: Found existing embedding server processes, checking health');
|
|
191
191
|
// Test if any existing process is healthy via socket
|
|
192
|
+
// CRITICAL FIX: Retry health check up to 15s to give freshly-spawned servers time to warm up
|
|
193
|
+
// This prevents MCP bootstrap from killing servers that init just spawned
|
|
192
194
|
if (existsSync(this.socketPath)) {
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
195
|
+
for (let attempt = 0; attempt < 6; attempt++) {
|
|
196
|
+
const healthResult = await this.healthCheck();
|
|
197
|
+
if (healthResult.success) {
|
|
198
|
+
logger.info({
|
|
199
|
+
pids: runningServers.map(s => s.pid),
|
|
200
|
+
responseTimeMs: healthResult.responseTimeMs,
|
|
201
|
+
attempt,
|
|
202
|
+
}, '[EmbeddingServerManager] FIX 1B: Existing server is healthy - reusing instead of spawning new');
|
|
203
|
+
this.isRunning = true;
|
|
204
|
+
this.startTime = Date.now();
|
|
205
|
+
this.consecutiveFailures = 0;
|
|
206
|
+
return true;
|
|
207
|
+
}
|
|
208
|
+
if (attempt < 5) {
|
|
209
|
+
logger.debug({ attempt }, '[EmbeddingServerManager] FIX 1B: Health check failed, waiting 3s before retry...');
|
|
210
|
+
await this.sleep(3000);
|
|
211
|
+
// Re-check socket still exists
|
|
212
|
+
if (!existsSync(this.socketPath)) break;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
} else {
|
|
216
|
+
// Socket doesn't exist yet but processes are running - wait for socket to appear
|
|
217
|
+
logger.debug('[EmbeddingServerManager] FIX 1B: No socket yet, waiting up to 15s for server to create it');
|
|
218
|
+
for (let i = 0; i < 15; i++) {
|
|
219
|
+
await this.sleep(1000);
|
|
220
|
+
if (existsSync(this.socketPath)) {
|
|
221
|
+
const healthResult = await this.healthCheck();
|
|
222
|
+
if (healthResult.success) {
|
|
223
|
+
logger.info({
|
|
224
|
+
pids: runningServers.map(s => s.pid),
|
|
225
|
+
responseTimeMs: healthResult.responseTimeMs,
|
|
226
|
+
}, '[EmbeddingServerManager] FIX 1B: Server became healthy after waiting - reusing');
|
|
227
|
+
this.isRunning = true;
|
|
228
|
+
this.startTime = Date.now();
|
|
229
|
+
this.consecutiveFailures = 0;
|
|
230
|
+
return true;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
203
233
|
}
|
|
204
234
|
}
|
|
205
|
-
// Existing processes found but unhealthy - kill only THIS project's before starting fresh
|
|
235
|
+
// Existing processes found but unhealthy after retries - kill only THIS project's before starting fresh
|
|
206
236
|
// PROJECT ISOLATION: Filter to only processes belonging to this project
|
|
207
237
|
const thisProjectServers = runningServers.filter(s => this._isProcessForThisProject(s.pid));
|
|
208
238
|
logger.warn({ count: thisProjectServers.length, totalFound: runningServers.length },
|
|
@@ -1422,7 +1452,7 @@ export class EmbeddingServerManager extends EventEmitter {
|
|
|
1422
1452
|
// CRITICAL FIX: Also search for PID files in ANY project path
|
|
1423
1453
|
// This catches project-specific socket directories like /newServer/specmem/sockets/
|
|
1424
1454
|
try {
|
|
1425
|
-
const allProjectPids = execSync(`find / -path "*/specmem/sockets/embedding.pid" -o -path "*/.specmem/*/sockets/embedding.pid" 2>/dev/null | xargs cat 2>/dev/null || true`, { encoding: 'utf8', timeout: 5000 }).trim();
|
|
1455
|
+
const allProjectPids = execSync(`find /home /root /opt /srv /var /tmp -maxdepth 6 -path "*/specmem/sockets/embedding.pid" -o -path "*/.specmem/*/sockets/embedding.pid" 2>/dev/null | xargs cat 2>/dev/null || true`, { encoding: 'utf8', timeout: 5000 }).trim();
|
|
1426
1456
|
for (const line of allProjectPids.split('\n')) {
|
|
1427
1457
|
if (!line.trim())
|
|
1428
1458
|
continue;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "specmem-hardwicksoftware",
|
|
3
|
-
"version": "3.7.
|
|
3
|
+
"version": "3.7.10",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Persistent memory system for coding sessions - semantic search with pgvector, token compression, team coordination, file watching. Needs root: installs system-wide hooks, manages docker/PostgreSQL, writes global configs, handles screen sessions. justcalljon.pro",
|
|
6
6
|
"main": "dist/index.js",
|
package/scripts/specmem-init.cjs
CHANGED
|
@@ -3514,6 +3514,46 @@ async function indexCodebase(projectPath, ui, embeddingResult) {
|
|
|
3514
3514
|
return results;
|
|
3515
3515
|
}
|
|
3516
3516
|
|
|
3517
|
+
// AUTO-CREATE codebase_files table if it doesn't exist
|
|
3518
|
+
// CRITICAL: Init must not depend on MCP migrations having run first
|
|
3519
|
+
try {
|
|
3520
|
+
await pool.query(`CREATE EXTENSION IF NOT EXISTS "uuid-ossp"`);
|
|
3521
|
+
await pool.query(`CREATE EXTENSION IF NOT EXISTS "vector"`);
|
|
3522
|
+
await pool.query(`
|
|
3523
|
+
CREATE TABLE IF NOT EXISTS codebase_files (
|
|
3524
|
+
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
3525
|
+
file_path TEXT NOT NULL,
|
|
3526
|
+
absolute_path TEXT NOT NULL,
|
|
3527
|
+
file_name VARCHAR(255) NOT NULL,
|
|
3528
|
+
extension VARCHAR(50),
|
|
3529
|
+
language_id VARCHAR(50) NOT NULL DEFAULT 'unknown',
|
|
3530
|
+
language_name VARCHAR(100) NOT NULL DEFAULT 'Unknown',
|
|
3531
|
+
language_type VARCHAR(50) NOT NULL DEFAULT 'data',
|
|
3532
|
+
content TEXT NOT NULL,
|
|
3533
|
+
content_hash VARCHAR(64),
|
|
3534
|
+
size_bytes INTEGER NOT NULL DEFAULT 0,
|
|
3535
|
+
line_count INTEGER NOT NULL DEFAULT 0,
|
|
3536
|
+
char_count INTEGER NOT NULL DEFAULT 0,
|
|
3537
|
+
last_modified TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
3538
|
+
chunk_index INTEGER,
|
|
3539
|
+
total_chunks INTEGER,
|
|
3540
|
+
original_file_id UUID,
|
|
3541
|
+
embedding vector(384),
|
|
3542
|
+
project_path TEXT DEFAULT '/',
|
|
3543
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
3544
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
3545
|
+
CONSTRAINT content_not_empty CHECK (length(content) > 0)
|
|
3546
|
+
)
|
|
3547
|
+
`);
|
|
3548
|
+
await pool.query(`CREATE INDEX IF NOT EXISTS idx_codebase_files_content_hash ON codebase_files(content_hash)`);
|
|
3549
|
+
await pool.query(`CREATE INDEX IF NOT EXISTS idx_codebase_files_path ON codebase_files(file_path)`);
|
|
3550
|
+
await pool.query(`CREATE INDEX IF NOT EXISTS idx_codebase_files_project_path_file ON codebase_files(file_path, project_path)`);
|
|
3551
|
+
await pool.query(`CREATE INDEX IF NOT EXISTS idx_codebase_files_project_path_hash ON codebase_files(project_path, content_hash)`);
|
|
3552
|
+
initLog('[CODEBASE] Table codebase_files ensured');
|
|
3553
|
+
} catch (e) {
|
|
3554
|
+
initLog(`[CODEBASE] Table ensure warning: ${e.message}`);
|
|
3555
|
+
}
|
|
3556
|
+
|
|
3517
3557
|
// Load existing hashes to skip unchanged files ONLY if they have embeddings
|
|
3518
3558
|
// CRITICAL: Files without embeddings need to be re-indexed even if content matches!
|
|
3519
3559
|
ui.setStatus('Checking existing index...');
|