@pcircle/memesh 4.0.1 → 4.0.2
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 +36 -30
- package/dashboard/dist/index.html +2 -2
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +17 -7
- package/dist/core/config.js.map +1 -1
- package/dist/core/embedder.d.ts +2 -0
- package/dist/core/embedder.d.ts.map +1 -1
- package/dist/core/embedder.js +51 -8
- package/dist/core/embedder.js.map +1 -1
- package/dist/core/operations.d.ts.map +1 -1
- package/dist/core/operations.js +26 -8
- package/dist/core/operations.js.map +1 -1
- package/dist/core/serializer.d.ts.map +1 -1
- package/dist/core/serializer.js +24 -0
- package/dist/core/serializer.js.map +1 -1
- package/dist/knowledge-graph.d.ts +3 -0
- package/dist/knowledge-graph.d.ts.map +1 -1
- package/dist/knowledge-graph.js +28 -3
- package/dist/knowledge-graph.js.map +1 -1
- package/dist/transports/cli/cli.js +5 -2
- package/dist/transports/cli/cli.js.map +1 -1
- package/dist/transports/http/server.d.ts +3 -1
- package/dist/transports/http/server.d.ts.map +1 -1
- package/dist/transports/http/server.js +21 -2
- package/dist/transports/http/server.js.map +1 -1
- package/package.json +5 -6
- package/plugin.json +1 -1
- package/scripts/hooks/_shared.js +62 -0
- package/scripts/hooks/pre-edit-recall.js +22 -15
- package/scripts/hooks/session-start.js +30 -21
- package/scripts/hooks/session-summary.js +4 -5
- package/skills/memesh/SKILL.md +8 -0
|
@@ -2,13 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
import { createRequire } from 'module';
|
|
4
4
|
import { homedir } from 'os';
|
|
5
|
-
import { join, basename } from 'path';
|
|
6
|
-
import { existsSync,
|
|
7
|
-
import { dirname } from 'path';
|
|
5
|
+
import { dirname, join, basename } from 'path';
|
|
6
|
+
import { existsSync, unlinkSync } from 'fs';
|
|
8
7
|
import { fileURLToPath } from 'url';
|
|
8
|
+
import {
|
|
9
|
+
buildReferenceContext,
|
|
10
|
+
ensurePrivateDir,
|
|
11
|
+
getMemeshDir,
|
|
12
|
+
isTrustedForAutoContext,
|
|
13
|
+
writePrivateJson,
|
|
14
|
+
} from './_shared.js';
|
|
9
15
|
|
|
10
16
|
const require = createRequire(import.meta.url);
|
|
11
17
|
|
|
18
|
+
const dbPath = process.env.MEMESH_DB_PATH || join(homedir(), '.memesh', 'knowledge-graph.db');
|
|
19
|
+
const memeshDir = getMemeshDir(process.env);
|
|
20
|
+
const throttlePath = join(memeshDir, 'session-recalled-files.json');
|
|
21
|
+
|
|
12
22
|
let input = '';
|
|
13
23
|
process.stdin.setEncoding('utf8');
|
|
14
24
|
process.stdin.on('data', (chunk) => { input += chunk; });
|
|
@@ -19,7 +29,6 @@ process.stdin.on('end', async () => {
|
|
|
19
29
|
|
|
20
30
|
// Clear pre-edit recall throttle from previous session
|
|
21
31
|
try {
|
|
22
|
-
const throttlePath = join(homedir(), '.memesh', 'session-recalled-files.json');
|
|
23
32
|
if (existsSync(throttlePath)) {
|
|
24
33
|
unlinkSync(throttlePath);
|
|
25
34
|
}
|
|
@@ -27,8 +36,6 @@ process.stdin.on('end', async () => {
|
|
|
27
36
|
// Non-critical
|
|
28
37
|
}
|
|
29
38
|
|
|
30
|
-
// Find database
|
|
31
|
-
const dbPath = process.env.MEMESH_DB_PATH || join(homedir(), '.memesh', 'knowledge-graph.db');
|
|
32
39
|
if (!existsSync(dbPath)) {
|
|
33
40
|
output('MeMesh: No database found. Memories will be created as you work.');
|
|
34
41
|
return;
|
|
@@ -85,14 +92,16 @@ process.stdin.on('end', async () => {
|
|
|
85
92
|
// Query project-specific top-N entities by relevance score
|
|
86
93
|
const projectTag = `project:${projectName}`;
|
|
87
94
|
const projectEntities = db.prepare(`
|
|
88
|
-
SELECT DISTINCT e.id, e.name, e.type, e.created_at
|
|
95
|
+
SELECT DISTINCT e.id, e.name, e.type, e.created_at, e.metadata
|
|
89
96
|
FROM entities e
|
|
90
97
|
JOIN tags t ON t.entity_id = e.id
|
|
91
98
|
WHERE t.tag = ?
|
|
92
99
|
${statusFilter}
|
|
93
100
|
${scoringOrderBy}
|
|
94
101
|
LIMIT ?
|
|
95
|
-
`).all(projectTag, sessionLimit)
|
|
102
|
+
`).all(projectTag, sessionLimit * 3)
|
|
103
|
+
.filter(entity => isTrustedForAutoContext(entity.metadata))
|
|
104
|
+
.slice(0, sessionLimit);
|
|
96
105
|
|
|
97
106
|
// Fetch the first observation for each entity (for concise summary)
|
|
98
107
|
const getFirstObservation = db.prepare(
|
|
@@ -101,12 +110,14 @@ process.stdin.on('end', async () => {
|
|
|
101
110
|
|
|
102
111
|
// Query global recent/top entities (exclude project-tagged ones for this project)
|
|
103
112
|
const recentEntities = db.prepare(`
|
|
104
|
-
SELECT id, name, type, created_at
|
|
113
|
+
SELECT id, name, type, created_at, metadata
|
|
105
114
|
FROM entities
|
|
106
115
|
${recentStatusFilter}
|
|
107
116
|
${recentScoringOrderBy}
|
|
108
|
-
LIMIT
|
|
109
|
-
`).all()
|
|
117
|
+
LIMIT 15
|
|
118
|
+
`).all()
|
|
119
|
+
.filter(entity => isTrustedForAutoContext(entity.metadata))
|
|
120
|
+
.slice(0, 5);
|
|
110
121
|
|
|
111
122
|
// Format entity as concise bullet: "• name (type): first observation (truncated)"
|
|
112
123
|
function formatEntity(entity) {
|
|
@@ -144,7 +155,7 @@ process.stdin.on('end', async () => {
|
|
|
144
155
|
// --- Proactive lesson warnings ---
|
|
145
156
|
try {
|
|
146
157
|
const lessonEntities = db.prepare(`
|
|
147
|
-
SELECT DISTINCT e.id, e.name, e.confidence
|
|
158
|
+
SELECT DISTINCT e.id, e.name, e.confidence, e.metadata
|
|
148
159
|
FROM entities e
|
|
149
160
|
JOIN tags t ON t.entity_id = e.id
|
|
150
161
|
WHERE e.type = 'lesson_learned'
|
|
@@ -152,8 +163,8 @@ process.stdin.on('end', async () => {
|
|
|
152
163
|
AND t.tag = ?
|
|
153
164
|
ORDER BY CASE WHEN e.confidence IS NULL THEN 0.5 ELSE e.confidence END DESC,
|
|
154
165
|
CASE WHEN e.access_count IS NULL THEN 0 ELSE e.access_count END DESC
|
|
155
|
-
LIMIT
|
|
156
|
-
`).all(projectTag);
|
|
166
|
+
LIMIT 15
|
|
167
|
+
`).all(projectTag).filter(entity => isTrustedForAutoContext(entity.metadata));
|
|
157
168
|
|
|
158
169
|
if (lessonEntities.length > 0) {
|
|
159
170
|
memorySummary += '\n\n⚠️ Known lessons for this project:\n';
|
|
@@ -188,23 +199,21 @@ process.stdin.on('end', async () => {
|
|
|
188
199
|
});
|
|
189
200
|
|
|
190
201
|
if (allInjected.length > 0) {
|
|
191
|
-
const memeshDir = join(homedir(), '.memesh');
|
|
192
202
|
const sessionsDir = join(memeshDir, 'sessions');
|
|
193
|
-
|
|
203
|
+
ensurePrivateDir(sessionsDir);
|
|
194
204
|
|
|
195
205
|
// FIX: Use session-scoped file with unique ID (pid + timestamp)
|
|
196
206
|
const sessionId = `${process.pid}-${Date.now()}`;
|
|
197
|
-
|
|
207
|
+
writePrivateJson(
|
|
198
208
|
join(sessionsDir, `${sessionId}.json`),
|
|
199
|
-
|
|
209
|
+
{
|
|
200
210
|
injectedAt: new Date().toISOString(),
|
|
201
211
|
project: projectName,
|
|
202
212
|
entityIds: allInjected.map(e => e.id),
|
|
203
213
|
entityNames: allInjected.map(e => e.name),
|
|
204
214
|
// FIX: Save injected context text to exclude from hit detection
|
|
205
215
|
injectedContext: memorySummary,
|
|
206
|
-
}
|
|
207
|
-
'utf8'
|
|
216
|
+
}
|
|
208
217
|
);
|
|
209
218
|
|
|
210
219
|
// Clean up old session files (>24h)
|
|
@@ -229,7 +238,7 @@ process.stdin.on('end', async () => {
|
|
|
229
238
|
suppressOutput: true,
|
|
230
239
|
hookSpecificOutput: {
|
|
231
240
|
hookEventName: 'SessionStart',
|
|
232
|
-
additionalContext: memorySummary,
|
|
241
|
+
additionalContext: buildReferenceContext(memorySummary.split('\n')),
|
|
233
242
|
},
|
|
234
243
|
};
|
|
235
244
|
console.log(JSON.stringify(hookOutput));
|
|
@@ -7,8 +7,9 @@
|
|
|
7
7
|
import { createRequire } from 'module';
|
|
8
8
|
import { homedir } from 'os';
|
|
9
9
|
import { join, basename, dirname } from 'path';
|
|
10
|
-
import { existsSync, mkdirSync, readFileSync
|
|
10
|
+
import { existsSync, mkdirSync, readFileSync } from 'fs';
|
|
11
11
|
import { fileURLToPath } from 'url';
|
|
12
|
+
import { getMemeshDir } from './_shared.js';
|
|
12
13
|
|
|
13
14
|
const require = createRequire(import.meta.url);
|
|
14
15
|
|
|
@@ -152,9 +153,7 @@ process.stdin.on('end', async () => {
|
|
|
152
153
|
|
|
153
154
|
// Open DB
|
|
154
155
|
const dbPath = process.env.MEMESH_DB_PATH || join(homedir(), '.memesh', 'knowledge-graph.db');
|
|
155
|
-
const dbDir = process.env
|
|
156
|
-
? join(process.env.MEMESH_DB_PATH, '..')
|
|
157
|
-
: join(homedir(), '.memesh');
|
|
156
|
+
const dbDir = getMemeshDir(process.env);
|
|
158
157
|
if (!existsSync(dbDir)) mkdirSync(dbDir, { recursive: true });
|
|
159
158
|
|
|
160
159
|
const Database = require('better-sqlite3');
|
|
@@ -244,7 +243,7 @@ process.stdin.on('end', async () => {
|
|
|
244
243
|
// their names appear in the transcript, update hits/misses.
|
|
245
244
|
try {
|
|
246
245
|
// FIX: Find the most recent session file for this project (within last hour)
|
|
247
|
-
const sessionsDir = join(
|
|
246
|
+
const sessionsDir = join(getMemeshDir(process.env), 'sessions');
|
|
248
247
|
let injectedData = null;
|
|
249
248
|
|
|
250
249
|
if (existsSync(sessionsDir)) {
|
package/skills/memesh/SKILL.md
CHANGED
|
@@ -116,6 +116,14 @@ memesh status # version, search level, embeddings
|
|
|
116
116
|
memesh config list # current configuration
|
|
117
117
|
```
|
|
118
118
|
|
|
119
|
+
### Regenerate embeddings after provider change
|
|
120
|
+
```bash
|
|
121
|
+
memesh reindex # rebuild all embeddings
|
|
122
|
+
memesh reindex --namespace personal # reindex only one namespace
|
|
123
|
+
memesh reindex --json # structured progress output
|
|
124
|
+
```
|
|
125
|
+
Use this when you change embedding provider (e.g., Ollama → OpenAI) or dimension. The database auto-drops old embeddings on provider change, but you need to run `reindex` to regenerate them for existing memories.
|
|
126
|
+
|
|
119
127
|
## MCP-Only Features
|
|
120
128
|
|
|
121
129
|
These require MCP tools or the HTTP API (`memesh serve` + REST calls):
|