persyst-mcp 2.2.4 → 2.2.5
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/README.md +39 -0
- package/bin/export.js +116 -0
- package/bin/import.js +160 -0
- package/hooks/persyst-hook.js +9 -10
- package/index.js +11 -1
- package/package.json +13 -3
- package/src/database.js +6 -4
- package/src/events.js +19 -0
- package/src/extractor-heuristic.js +502 -324
- package/src/sdk.d.ts +175 -0
- package/src/sdk.js +217 -0
- package/src/search.js +92 -2
- package/src/server.js +723 -183
- package/src/tools.js +11 -3
- package/src/watcher.js +27 -12
package/src/tools.js
CHANGED
|
@@ -48,6 +48,7 @@ import { searchHybrid, getOptimizedContext, consolidateMemories } from './search
|
|
|
48
48
|
import { getRecentCommits } from './git.js';
|
|
49
49
|
import { verifyChainIntegrity } from './attestation.js';
|
|
50
50
|
import { searchCache } from './cache.js';
|
|
51
|
+
import { memoryEventBus } from './events.js';
|
|
51
52
|
|
|
52
53
|
// ============================================================
|
|
53
54
|
// CONSTANTS
|
|
@@ -152,6 +153,9 @@ export async function addMemoryInternal({ content, importance = 1.0, agent_id, s
|
|
|
152
153
|
// Feature 1: Invalidate search cache on write
|
|
153
154
|
searchCache.invalidate();
|
|
154
155
|
|
|
156
|
+
// Broadcast to SSE subscribers (HTTP gateway + SSE clients)
|
|
157
|
+
memoryEventBus.emit('memory_added', { id, content, namespace, source: normalizedAgentId || 'manual' });
|
|
158
|
+
|
|
155
159
|
// Feature 2: Contradiction Detection
|
|
156
160
|
let contradictions = [];
|
|
157
161
|
try {
|
|
@@ -403,6 +407,9 @@ export function registerTools(server) {
|
|
|
403
407
|
// Feature 1: Invalidate search cache on write
|
|
404
408
|
searchCache.invalidate();
|
|
405
409
|
|
|
410
|
+
// Broadcast deletion to SSE subscribers
|
|
411
|
+
memoryEventBus.emit('memory_deleted', { id });
|
|
412
|
+
|
|
406
413
|
return text({ success: true, id, message: `Memory #${id} deleted` });
|
|
407
414
|
} catch (err) {
|
|
408
415
|
return text({ error: err.message });
|
|
@@ -778,12 +785,13 @@ export function registerTools(server) {
|
|
|
778
785
|
query: z.string().describe('The search query context'),
|
|
779
786
|
max_tokens: z.number().default(4000).describe('Token budget for LLM context compression (default: 4000)'),
|
|
780
787
|
agent_id: z.string().optional().describe('Agent ID requesting context — filters to this agent\'s namespace + shared'),
|
|
781
|
-
session_id: z.string().optional().describe('Session ID')
|
|
788
|
+
session_id: z.string().optional().describe('Session ID'),
|
|
789
|
+
intent: z.string().optional().describe('The active task intent / category (e.g. debugging, ui_styling, database_management)')
|
|
782
790
|
},
|
|
783
|
-
async ({ query, max_tokens, agent_id, session_id }) => {
|
|
791
|
+
async ({ query, max_tokens, agent_id, session_id, intent }) => {
|
|
784
792
|
try {
|
|
785
793
|
const namespace = agent_id || null;
|
|
786
|
-
const contextData = await getOptimizedContext(query, max_tokens, agent_id, session_id, namespace);
|
|
794
|
+
const contextData = await getOptimizedContext(query, max_tokens, agent_id, session_id, namespace, intent);
|
|
787
795
|
return text(contextData);
|
|
788
796
|
} catch (err) {
|
|
789
797
|
return text({ error: err.message });
|
package/src/watcher.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
import { join, resolve } from 'path';
|
|
10
10
|
import { homedir } from 'os';
|
|
11
|
-
import { existsSync, readFileSync, writeFileSync, readdirSync, statSync } from 'fs';
|
|
11
|
+
import { existsSync, readFileSync, writeFileSync, readdirSync, statSync, openSync, readSync, closeSync } from 'fs';
|
|
12
12
|
import {
|
|
13
13
|
getWatchPosition,
|
|
14
14
|
upsertWatchPosition,
|
|
@@ -20,6 +20,7 @@ import { generateEmbedding } from './embeddings.js';
|
|
|
20
20
|
import { extractHeuristic } from './extractor-heuristic.js';
|
|
21
21
|
import { searchHybrid } from './search.js';
|
|
22
22
|
import { searchCache } from './cache.js';
|
|
23
|
+
import { memoryEventBus } from './events.js';
|
|
23
24
|
|
|
24
25
|
// Config path: ~/.persyst/config.json
|
|
25
26
|
const CONFIG_FILE = join(homedir(), '.persyst', 'config.json');
|
|
@@ -86,10 +87,19 @@ async function processJsonlFile(filePath) {
|
|
|
86
87
|
|
|
87
88
|
if (stat.size <= lastPos) return;
|
|
88
89
|
|
|
89
|
-
// Read only new content appended to the file
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
90
|
+
// Read only new content appended to the file (Bug C fix)
|
|
91
|
+
const length = stat.size - lastPos;
|
|
92
|
+
let text = '';
|
|
93
|
+
if (length > 0) {
|
|
94
|
+
const newContentBuffer = Buffer.alloc(length);
|
|
95
|
+
const fd = openSync(filePath, 'r');
|
|
96
|
+
try {
|
|
97
|
+
readSync(fd, newContentBuffer, 0, length, lastPos);
|
|
98
|
+
} finally {
|
|
99
|
+
closeSync(fd);
|
|
100
|
+
}
|
|
101
|
+
text = newContentBuffer.toString('utf8');
|
|
102
|
+
}
|
|
93
103
|
|
|
94
104
|
const lines = text.split('\n');
|
|
95
105
|
let addedCount = 0;
|
|
@@ -116,16 +126,16 @@ async function processJsonlFile(filePath) {
|
|
|
116
126
|
|
|
117
127
|
const facts = extractHeuristic(cleanText);
|
|
118
128
|
for (const fact of facts) {
|
|
119
|
-
// Verify against exact duplicate
|
|
120
|
-
if (memoryExists(fact.content)) continue;
|
|
129
|
+
// Verify against exact duplicate (Bug A fix: check namespace 'shared')
|
|
130
|
+
if (memoryExists(fact.content, 'shared')) continue;
|
|
121
131
|
|
|
122
|
-
// Verify against semantic similarity
|
|
123
|
-
const similar = await searchHybrid(fact.content, 1);
|
|
132
|
+
// Verify against semantic similarity (Bug B fix: check namespace 'shared')
|
|
133
|
+
const similar = await searchHybrid(fact.content, 1, null, null, 'shared');
|
|
124
134
|
if (similar.length > 0 && parseFloat(similar[0].similarity) >= DEDUP_THRESHOLD) {
|
|
125
135
|
continue;
|
|
126
136
|
}
|
|
127
137
|
|
|
128
|
-
// Insert memory with provenance
|
|
138
|
+
// Insert memory with provenance (written to 'shared' by default)
|
|
129
139
|
const id = insertMemory(fact.content, fact.confidence, {
|
|
130
140
|
source_type: 'agent',
|
|
131
141
|
source_id: record.source === 'MODEL' ? 'antigravity-worker' : 'user-dialogue',
|
|
@@ -136,6 +146,7 @@ async function processJsonlFile(filePath) {
|
|
|
136
146
|
insertVector(id, embedding);
|
|
137
147
|
addedCount++;
|
|
138
148
|
console.error(`[persyst-watcher] Auto-extracted fact: "${fact.content}" (Memory #${id})`);
|
|
149
|
+
memoryEventBus.emit('memory_added', { id, content: fact.content, namespace: 'shared', source: 'watcher-antigravity' });
|
|
139
150
|
}
|
|
140
151
|
}
|
|
141
152
|
}
|
|
@@ -181,13 +192,16 @@ async function processJsonFile(filePath) {
|
|
|
181
192
|
if (msg.role === 'user' || msg.role === 'assistant') {
|
|
182
193
|
const facts = extractHeuristic(msg.content);
|
|
183
194
|
for (const fact of facts) {
|
|
184
|
-
|
|
195
|
+
// Verify against exact duplicate (Bug A fix: check namespace 'shared')
|
|
196
|
+
if (memoryExists(fact.content, 'shared')) continue;
|
|
185
197
|
|
|
186
|
-
|
|
198
|
+
// Verify against semantic similarity (Bug B fix: check namespace 'shared')
|
|
199
|
+
const similar = await searchHybrid(fact.content, 1, null, null, 'shared');
|
|
187
200
|
if (similar.length > 0 && parseFloat(similar[0].similarity) >= DEDUP_THRESHOLD) {
|
|
188
201
|
continue;
|
|
189
202
|
}
|
|
190
203
|
|
|
204
|
+
// Insert memory with provenance (written to 'shared' by default)
|
|
191
205
|
const id = insertMemory(fact.content, fact.confidence, {
|
|
192
206
|
source_type: 'agent',
|
|
193
207
|
source_id: msg.role === 'assistant' ? 'roo-worker' : 'user-dialogue',
|
|
@@ -198,6 +212,7 @@ async function processJsonFile(filePath) {
|
|
|
198
212
|
insertVector(id, embedding);
|
|
199
213
|
addedCount++;
|
|
200
214
|
console.error(`[persyst-watcher] Auto-extracted fact: "${fact.content}" (Memory #${id})`);
|
|
215
|
+
memoryEventBus.emit('memory_added', { id, content: fact.content, namespace: 'shared', source: 'watcher-roo' });
|
|
201
216
|
}
|
|
202
217
|
}
|
|
203
218
|
}
|