specmem-hardwicksoftware 3.7.14 → 3.7.16
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.
- package/dist/commands/promptCommands.js +2 -2
- package/dist/config/configSync.js +4 -3
- package/dist/init/claudeConfigInjector.js +2 -2
- package/dist/mcp/embeddingServerManager.js +20 -0
- package/dist/utils/processHealthCheck.js +7 -2
- package/mcp-proxy.cjs +5 -1
- package/package.json +1 -1
- package/scripts/specmem-init.cjs +2 -2
|
@@ -174,8 +174,8 @@ export class PromptCommands {
|
|
|
174
174
|
category VARCHAR(100) DEFAULT 'general',
|
|
175
175
|
tags TEXT[] DEFAULT '{}',
|
|
176
176
|
variables TEXT[] DEFAULT '{}',
|
|
177
|
-
--
|
|
178
|
-
embedding vector,
|
|
177
|
+
-- Dimension must be specified for ivfflat index
|
|
178
|
+
embedding vector(384),
|
|
179
179
|
usage_count INTEGER DEFAULT 0,
|
|
180
180
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
181
181
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
@@ -155,8 +155,9 @@ function syncConfigJson() {
|
|
|
155
155
|
needsFix = true;
|
|
156
156
|
}
|
|
157
157
|
// Check args - should point to bootstrap.cjs
|
|
158
|
-
const expectedArgs = [
|
|
159
|
-
|
|
158
|
+
const expectedArgs = [BOOTSTRAP_PATH];
|
|
159
|
+
// Support both old format (with --max-old-space-size) and new format (just path)
|
|
160
|
+
const actualEntryPoint = existing.args?.find(a => a.includes('bootstrap.cjs') || a.includes('mcp-proxy.cjs'));
|
|
160
161
|
if (actualEntryPoint !== BOOTSTRAP_PATH) {
|
|
161
162
|
mismatches.push({
|
|
162
163
|
file: 'config.json',
|
|
@@ -185,7 +186,7 @@ function syncConfigJson() {
|
|
|
185
186
|
// Fix config.json
|
|
186
187
|
config.mcpServers['specmem'] = {
|
|
187
188
|
command: 'node',
|
|
188
|
-
args: [
|
|
189
|
+
args: [BOOTSTRAP_PATH],
|
|
189
190
|
env: {
|
|
190
191
|
HOME: os.homedir(),
|
|
191
192
|
// Project-local configuration - ${cwd} is expanded by Code per-invocation
|
|
@@ -242,7 +242,7 @@ function configureMcpServer() {
|
|
|
242
242
|
// CRITICAL: ${PWD} is expanded at MCP server startup to current working directory
|
|
243
243
|
const specmemConfig = {
|
|
244
244
|
command: 'node',
|
|
245
|
-
args: [
|
|
245
|
+
args: [BOOTSTRAP_PATH],
|
|
246
246
|
env: {
|
|
247
247
|
// Core paths - ${PWD} gives us project isolation (dynamic per-directory)
|
|
248
248
|
HOME: HOME_DIR,
|
|
@@ -348,7 +348,7 @@ function fixProjectMcpConfigs() {
|
|
|
348
348
|
// Don't clobber other MCP servers - only add specmem
|
|
349
349
|
config.mcpServers.specmem = {
|
|
350
350
|
command: 'node',
|
|
351
|
-
args: [
|
|
351
|
+
args: [BOOTSTRAP_PATH],
|
|
352
352
|
env: {
|
|
353
353
|
HOME: HOME_DIR,
|
|
354
354
|
SPECMEM_PROJECT_PATH: '${PWD}',
|
|
@@ -1661,6 +1661,20 @@ export class EmbeddingServerManager extends EventEmitter {
|
|
|
1661
1661
|
}, '[EmbeddingServerManager] SAFETY CHECK: Process command line does not match this project - skipping kill');
|
|
1662
1662
|
continue;
|
|
1663
1663
|
}
|
|
1664
|
+
// CRITICAL FIX: Never kill --service mode processes based on age
|
|
1665
|
+
// Service mode is meant to run indefinitely
|
|
1666
|
+
const isServiceMode = commandLine.includes('--service');
|
|
1667
|
+
if (isServiceMode) {
|
|
1668
|
+
logger.info({
|
|
1669
|
+
pid,
|
|
1670
|
+
ageHours: ageHours?.toFixed(2) || 'unknown',
|
|
1671
|
+
socketPath: this.socketPath,
|
|
1672
|
+
}, '[EmbeddingServerManager] Orphaned --service process found - KEEPING (service mode runs indefinitely)');
|
|
1673
|
+
// Adopt it instead of killing
|
|
1674
|
+
this.isRunning = true;
|
|
1675
|
+
this.process = { pid };
|
|
1676
|
+
continue;
|
|
1677
|
+
}
|
|
1664
1678
|
// Only kill if older than max age
|
|
1665
1679
|
if (ageHours !== null && ageHours <= this.config.maxProcessAgeHours) {
|
|
1666
1680
|
logger.info({
|
|
@@ -1819,6 +1833,12 @@ export class EmbeddingServerManager extends EventEmitter {
|
|
|
1819
1833
|
statusMessage: healthInfo.statusMessage,
|
|
1820
1834
|
}, '[EmbeddingServerManager] Checked PID file process');
|
|
1821
1835
|
if (healthInfo.processExists) {
|
|
1836
|
+
// Respect recommended action — don't kill healthy/service processes
|
|
1837
|
+
if (healthInfo.recommendedAction === 'keep') {
|
|
1838
|
+
logger.info({ pid: healthInfo.pid, status: healthInfo.statusMessage },
|
|
1839
|
+
'[EmbeddingServerManager] killByPidFile: Process is healthy/service - keeping');
|
|
1840
|
+
return;
|
|
1841
|
+
}
|
|
1822
1842
|
await this.killProcessWithHealthInfo(healthInfo);
|
|
1823
1843
|
}
|
|
1824
1844
|
else {
|
|
@@ -119,7 +119,10 @@ export function checkProcessHealth(config) {
|
|
|
119
119
|
// Step 4: Determine if stale
|
|
120
120
|
// Use actual process age if available, otherwise fall back to PID file age
|
|
121
121
|
const effectiveAgeHours = processAgeHours !== null ? processAgeHours : pidFileAgeHours;
|
|
122
|
-
|
|
122
|
+
// CRITICAL FIX: --service mode processes are meant to run indefinitely
|
|
123
|
+
// They should NEVER be considered stale based on age alone
|
|
124
|
+
const isServiceMode = commandLine && commandLine.includes('--service');
|
|
125
|
+
const isStale = isServiceMode ? false : effectiveAgeHours > maxAgeHours;
|
|
123
126
|
// Step 5: Determine recommended action
|
|
124
127
|
let recommendedAction = 'keep';
|
|
125
128
|
let statusMessage = '';
|
|
@@ -137,7 +140,9 @@ export function checkProcessHealth(config) {
|
|
|
137
140
|
}
|
|
138
141
|
else {
|
|
139
142
|
recommendedAction = 'keep';
|
|
140
|
-
statusMessage =
|
|
143
|
+
statusMessage = isServiceMode
|
|
144
|
+
? `Process ${pid} is healthy service-mode (${effectiveAgeHours.toFixed(2)}h old, age check bypassed)`
|
|
145
|
+
: `Process ${pid} is healthy (${effectiveAgeHours.toFixed(2)}h old)`;
|
|
141
146
|
}
|
|
142
147
|
logger.info({
|
|
143
148
|
pid,
|
package/mcp-proxy.cjs
CHANGED
|
@@ -155,7 +155,11 @@ function spawnServer() {
|
|
|
155
155
|
|
|
156
156
|
log(`Spawning server: node ${BOOTSTRAP_PATH} ${args.join(' ')}`);
|
|
157
157
|
|
|
158
|
-
|
|
158
|
+
// CRITICAL: Do NOT hardcode --max-old-space-size here
|
|
159
|
+
// The proxy's own heap limit is set by Claude config args (e.g. --max-old-space-size=250)
|
|
160
|
+
// but the child bootstrap needs MORE memory for all its initialization
|
|
161
|
+
const heapLimit = process.env.SPECMEM_MAX_HEAP_MB || '512';
|
|
162
|
+
child = spawn('node', [`--max-old-space-size=${heapLimit}`, BOOTSTRAP_PATH, ...args], {
|
|
159
163
|
env,
|
|
160
164
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
161
165
|
cwd: process.env.SPECMEM_PROJECT_PATH || process.cwd()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "specmem-hardwicksoftware",
|
|
3
|
-
"version": "3.7.
|
|
3
|
+
"version": "3.7.16",
|
|
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
|
@@ -6519,7 +6519,6 @@ async function runAutoSetup(projectPath) {
|
|
|
6519
6519
|
type: "stdio",
|
|
6520
6520
|
command: "node",
|
|
6521
6521
|
args: [
|
|
6522
|
-
"--max-old-space-size=250",
|
|
6523
6522
|
mcpEntry
|
|
6524
6523
|
],
|
|
6525
6524
|
env: {
|
|
@@ -6531,7 +6530,8 @@ async function runAutoSetup(projectPath) {
|
|
|
6531
6530
|
SPECMEM_DB_PORT: "5432",
|
|
6532
6531
|
SPECMEM_DB_NAME: "specmem_westayunprofessional",
|
|
6533
6532
|
SPECMEM_DB_USER: "specmem_westayunprofessional",
|
|
6534
|
-
SPECMEM_DB_PASSWORD: "specmem_westayunprofessional"
|
|
6533
|
+
SPECMEM_DB_PASSWORD: "specmem_westayunprofessional",
|
|
6534
|
+
SPECMEM_MAX_HEAP_MB: "512"
|
|
6535
6535
|
}
|
|
6536
6536
|
};
|
|
6537
6537
|
claudeJson.projects[projectPath].hasTrustDialogAccepted = true;
|