klypix-mcp 1.67.0 → 1.67.1
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/package.json +2 -2
- package/src/brain-semantic.mjs +50 -4
- package/src/semantic-memory.mjs +55 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "klypix-mcp",
|
|
3
|
-
"version": "1.67.
|
|
3
|
+
"version": "1.67.1",
|
|
4
4
|
"description": "Shared project brain and MCP coordination server for multi-agent coding.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"bench": "node bin/klypix-mcp.mjs bench",
|
|
84
84
|
"test:bench": "node test/bench.mjs",
|
|
85
85
|
"pretest": "node test/publish-workflow.mjs",
|
|
86
|
-
"test": "node test/publish-verdict.mjs && node test/remote-client.mjs && node test/project-graph.mjs && node test/project-map-cli.mjs && node test/mcp-auto-update.mjs && node test/mcp-supervisor.mjs && node test/runtime-inspector.mjs && node test/codex-hooks.mjs && node test/request-identity.mjs && node test/session-identity-core.mjs && node test/agent-presence.mjs && node test/message-delivery-v3.mjs && node test/claude-message-delivery-v3.mjs && node test/result-reconcile.mjs && node test/evidence-publication-gate.mjs && node test/release-evidence-cli.mjs && node test/intent-guard.mjs && node test/git-capture-install.mjs && node test/brain-history.mjs && node test/brain-graveyard.mjs && node test/archived-visibility.mjs && node test/finding-routing.mjs && node test/finding-routing-hook.mjs && node test/presence-relay.mjs && node test/install-version.mjs && node test/context-gateway.mjs && node test/conformance.mjs && node test/brain-doctor.mjs && node test/version-currency.mjs && node test/ship-capture.mjs && node test/lane-message.mjs && node test/brain-quality.mjs && node test/brain-connect-orphans.mjs && node test/brief-and-recall.mjs && node test/layout-cluster.mjs && node test/brain-ask.mjs && node test/field-report-2026-07-04.mjs && node test/autoprop.mjs && node test/overlay-recency-2026-07-12.mjs && node test/brain-challenge.mjs && node test/brain-lens.mjs && node test/brain-kind.mjs && node test/rule-drafts.mjs && node test/claim-engine.mjs && node test/skill-staleness.mjs && node test/canvas-view.mjs && node test/status-completeness.mjs && node test/semantic-gate.mjs && node test/memory-runtime.mjs && node test/semantic-cache.mjs && node test/decay-status.mjs && node test/decay-hook.mjs && node test/evidence-anchors.mjs && node test/presence-visibility.mjs && node test/merge-brains.mjs && node test/concurrent-writes.mjs && node test/lock-interop.mjs && node test/a2a-smoke.mjs && node test/cli-args.mjs && node test/format-guard.mjs && node test/git-tools.mjs && node test/uninstall.mjs",
|
|
86
|
+
"test": "node test/publish-verdict.mjs && node test/remote-client.mjs && node test/project-graph.mjs && node test/project-map-cli.mjs && node test/mcp-auto-update.mjs && node test/mcp-supervisor.mjs && node test/runtime-inspector.mjs && node test/codex-hooks.mjs && node test/request-identity.mjs && node test/session-identity-core.mjs && node test/agent-presence.mjs && node test/message-delivery-v3.mjs && node test/claude-message-delivery-v3.mjs && node test/result-reconcile.mjs && node test/evidence-publication-gate.mjs && node test/release-evidence-cli.mjs && node test/intent-guard.mjs && node test/git-capture-install.mjs && node test/brain-history.mjs && node test/brain-graveyard.mjs && node test/archived-visibility.mjs && node test/finding-routing.mjs && node test/finding-routing-hook.mjs && node test/presence-relay.mjs && node test/install-version.mjs && node test/context-gateway.mjs && node test/conformance.mjs && node test/brain-doctor.mjs && node test/version-currency.mjs && node test/ship-capture.mjs && node test/lane-message.mjs && node test/brain-quality.mjs && node test/brain-connect-orphans.mjs && node test/brief-and-recall.mjs && node test/layout-cluster.mjs && node test/brain-ask.mjs && node test/field-report-2026-07-04.mjs && node test/autoprop.mjs && node test/overlay-recency-2026-07-12.mjs && node test/brain-challenge.mjs && node test/brain-lens.mjs && node test/brain-kind.mjs && node test/rule-drafts.mjs && node test/claim-engine.mjs && node test/skill-staleness.mjs && node test/canvas-view.mjs && node test/status-completeness.mjs && node test/semantic-security.mjs && node test/semantic-gate.mjs && node test/memory-runtime.mjs && node test/semantic-cache.mjs && node test/decay-status.mjs && node test/decay-hook.mjs && node test/evidence-anchors.mjs && node test/presence-visibility.mjs && node test/merge-brains.mjs && node test/concurrent-writes.mjs && node test/lock-interop.mjs && node test/a2a-smoke.mjs && node test/cli-args.mjs && node test/format-guard.mjs && node test/git-tools.mjs && node test/uninstall.mjs",
|
|
87
87
|
"test:memory": "node test/memory-runtime.mjs",
|
|
88
88
|
"test:memory:soak": "node --expose-gc test/memory-soak.mjs",
|
|
89
89
|
"runtime": "node bin/klypix-runtime.mjs"
|
package/src/brain-semantic.mjs
CHANGED
|
@@ -18,6 +18,7 @@ import fs from 'fs';
|
|
|
18
18
|
import path from 'path';
|
|
19
19
|
import os from 'os';
|
|
20
20
|
import crypto from 'crypto';
|
|
21
|
+
import { createRequire } from 'module';
|
|
21
22
|
|
|
22
23
|
const PB_DIR = path.join(os.homedir(), '.claude', 'project-brain');
|
|
23
24
|
const EMB_DIR = path.join(PB_DIR, 'embeddings');
|
|
@@ -29,6 +30,46 @@ export const HOOK_EMBEDDING_MODEL_ID = 'Xenova/bge-small-en-v1.5';
|
|
|
29
30
|
export const HOOK_EMBEDDING_QUERY_PREFIX = 'Represent this sentence for searching relevant passages: ';
|
|
30
31
|
export const HOOK_EMBEDDING_POOLING = 'cls';
|
|
31
32
|
export const HOOK_EMBEDDING_CACHE_KEY = `${HOOK_EMBEDDING_MODEL_ID}|q8|${HOOK_EMBEDDING_POOLING}|query-instruction-v1`;
|
|
33
|
+
const MIN_SAFE_SHARP_VERSION = [0, 35, 3];
|
|
34
|
+
|
|
35
|
+
function findPackageManifest(entryPath, expectedName) {
|
|
36
|
+
let dir = path.dirname(entryPath);
|
|
37
|
+
while (dir !== path.dirname(dir)) {
|
|
38
|
+
try {
|
|
39
|
+
const manifestPath = path.join(dir, 'package.json');
|
|
40
|
+
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
|
|
41
|
+
if (manifest?.name === expectedName) return { manifestPath, manifest };
|
|
42
|
+
} catch { /* keep walking */ }
|
|
43
|
+
dir = path.dirname(dir);
|
|
44
|
+
}
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function isSafeSharpVersion(version) {
|
|
49
|
+
const parts = String(version || '').split('.').slice(0, 3).map(Number);
|
|
50
|
+
if (parts.length !== 3 || parts.some(part => !Number.isInteger(part) || part < 0)) return false;
|
|
51
|
+
for (let i = 0; i < MIN_SAFE_SHARP_VERSION.length; i++) {
|
|
52
|
+
if (parts[i] !== MIN_SAFE_SHARP_VERSION[i]) return parts[i] > MIN_SAFE_SHARP_VERSION[i];
|
|
53
|
+
}
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function semanticRuntimeEntryIfSafe(transformersEntry) {
|
|
58
|
+
try {
|
|
59
|
+
const transformers = findPackageManifest(transformersEntry, '@huggingface/transformers');
|
|
60
|
+
if (!transformers) return null;
|
|
61
|
+
const sharpEntry = createRequire(transformers.manifestPath).resolve('sharp');
|
|
62
|
+
const sharp = findPackageManifest(sharpEntry, 'sharp');
|
|
63
|
+
return sharp && isSafeSharpVersion(sharp.manifest.version) ? transformersEntry : null;
|
|
64
|
+
} catch { return null; }
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function ambientTransformersEntryIfSafe() {
|
|
68
|
+
try {
|
|
69
|
+
const entry = createRequire(import.meta.url).resolve('@huggingface/transformers');
|
|
70
|
+
return semanticRuntimeEntryIfSafe(entry);
|
|
71
|
+
} catch { return null; }
|
|
72
|
+
}
|
|
32
73
|
|
|
33
74
|
// Memoized within THIS process only (a one-shot hook run) — across prompts it
|
|
34
75
|
// reloads cold, which is exactly why we only pay it on a lexical miss.
|
|
@@ -37,15 +78,20 @@ function getEmbedder() {
|
|
|
37
78
|
if (_embedder !== undefined) return _embedder;
|
|
38
79
|
_embedder = (async () => {
|
|
39
80
|
let t;
|
|
40
|
-
|
|
41
|
-
|
|
81
|
+
const ambientEntry = ambientTransformersEntryIfSafe();
|
|
82
|
+
if (ambientEntry) {
|
|
83
|
+
try { t = await import('@huggingface/transformers'); } catch { /* try owned runtime */ }
|
|
84
|
+
}
|
|
85
|
+
if (!t) {
|
|
42
86
|
const base = path.join(PB_DIR, 'semantic', 'node_modules', '@huggingface', 'transformers', 'dist');
|
|
43
87
|
let last;
|
|
44
88
|
for (const f of ['transformers.node.mjs', 'transformers.mjs']) {
|
|
45
|
-
|
|
89
|
+
const entry = path.join(base, f);
|
|
90
|
+
if (!semanticRuntimeEntryIfSafe(entry)) continue;
|
|
91
|
+
try { t = await import(new URL('file:///' + entry.replace(/\\/g, '/')).href); last = null; break; }
|
|
46
92
|
catch (e) { last = e; }
|
|
47
93
|
}
|
|
48
|
-
if (!t) throw last;
|
|
94
|
+
if (!t) throw last || new Error('semantic runtime rejected: sharp must be >=0.35.3');
|
|
49
95
|
}
|
|
50
96
|
t.env.cacheDir = path.join(PB_DIR, 'hf-cache');
|
|
51
97
|
return await t.pipeline('feature-extraction', HOOK_EMBEDDING_MODEL_ID, { dtype: 'q8' });
|
package/src/semantic-memory.mjs
CHANGED
|
@@ -13,6 +13,7 @@ import { createRequire } from 'module';
|
|
|
13
13
|
const PB_DIR = path.join(os.homedir(), '.claude', 'project-brain');
|
|
14
14
|
const EMB_DIR = path.join(PB_DIR, 'embeddings');
|
|
15
15
|
const sha1 = (s) => crypto.createHash('sha1').update(String(s)).digest('hex');
|
|
16
|
+
const MIN_SAFE_SHARP_VERSION = [0, 35, 3];
|
|
16
17
|
export const EMBEDDING_MODEL_ID = 'Xenova/bge-small-en-v1.5';
|
|
17
18
|
export const EMBEDDING_QUERY_PREFIX = 'Represent this sentence for searching relevant passages: ';
|
|
18
19
|
export const EMBEDDING_POOLING = 'cls';
|
|
@@ -236,16 +237,59 @@ function disposeTensorTree(value, seen = new Set()) {
|
|
|
236
237
|
for (const item of Object.values(value)) disposeTensorTree(item, seen);
|
|
237
238
|
}
|
|
238
239
|
|
|
240
|
+
function findPackageManifest(entryPath, expectedName) {
|
|
241
|
+
let dir = path.dirname(entryPath);
|
|
242
|
+
while (dir !== path.dirname(dir)) {
|
|
243
|
+
try {
|
|
244
|
+
const manifestPath = path.join(dir, 'package.json');
|
|
245
|
+
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
|
|
246
|
+
if (manifest?.name === expectedName) return { manifestPath, manifest };
|
|
247
|
+
} catch { /* keep walking */ }
|
|
248
|
+
dir = path.dirname(dir);
|
|
249
|
+
}
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function isSafeSharpVersion(version) {
|
|
254
|
+
const parts = String(version || '').split('.').slice(0, 3).map(Number);
|
|
255
|
+
if (parts.length !== 3 || parts.some(part => !Number.isInteger(part) || part < 0)) return false;
|
|
256
|
+
for (let i = 0; i < MIN_SAFE_SHARP_VERSION.length; i++) {
|
|
257
|
+
if (parts[i] !== MIN_SAFE_SHARP_VERSION[i]) return parts[i] > MIN_SAFE_SHARP_VERSION[i];
|
|
258
|
+
}
|
|
259
|
+
return true;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export function semanticRuntimeEntryIfSafe(transformersEntry) {
|
|
263
|
+
try {
|
|
264
|
+
const transformers = findPackageManifest(transformersEntry, '@huggingface/transformers');
|
|
265
|
+
if (!transformers) return null;
|
|
266
|
+
const sharpEntry = createRequire(transformers.manifestPath).resolve('sharp');
|
|
267
|
+
const sharp = findPackageManifest(sharpEntry, 'sharp');
|
|
268
|
+
return sharp && isSafeSharpVersion(sharp.manifest.version) ? transformersEntry : null;
|
|
269
|
+
} catch { return null; }
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function ambientTransformersEntryIfSafe() {
|
|
273
|
+
try {
|
|
274
|
+
const entry = createRequire(import.meta.url).resolve('@huggingface/transformers');
|
|
275
|
+
return semanticRuntimeEntryIfSafe(entry);
|
|
276
|
+
} catch { return null; }
|
|
277
|
+
}
|
|
278
|
+
|
|
239
279
|
async function loadTransformers() {
|
|
240
|
-
|
|
241
|
-
|
|
280
|
+
if (ambientTransformersEntryIfSafe()) {
|
|
281
|
+
try { return await import('@huggingface/transformers'); } catch { /* try owned runtime */ }
|
|
282
|
+
}
|
|
283
|
+
{
|
|
242
284
|
const base = path.join(PB_DIR, 'semantic', 'node_modules', '@huggingface', 'transformers', 'dist');
|
|
243
285
|
let lastErr;
|
|
244
286
|
for (const f of ['transformers.node.mjs', 'transformers.mjs']) {
|
|
245
|
-
|
|
287
|
+
const entry = path.join(base, f);
|
|
288
|
+
if (!semanticRuntimeEntryIfSafe(entry)) continue;
|
|
289
|
+
try { return await import(new URL('file:///' + entry.replace(/\\/g, '/')).href); }
|
|
246
290
|
catch (error) { lastErr = error; }
|
|
247
291
|
}
|
|
248
|
-
throw lastErr;
|
|
292
|
+
throw lastErr || new Error('semantic runtime rejected: sharp must be >=0.35.3');
|
|
249
293
|
}
|
|
250
294
|
}
|
|
251
295
|
|
|
@@ -267,13 +311,15 @@ export function semanticRuntimeInstalled() {
|
|
|
267
311
|
if (runtimeInstalledCache !== null) return runtimeInstalledCache;
|
|
268
312
|
let found = false;
|
|
269
313
|
try {
|
|
270
|
-
createRequire(import.meta.url).resolve('@huggingface/transformers');
|
|
271
|
-
found =
|
|
314
|
+
const entry = createRequire(import.meta.url).resolve('@huggingface/transformers');
|
|
315
|
+
found = Boolean(semanticRuntimeEntryIfSafe(entry));
|
|
272
316
|
} catch {
|
|
317
|
+
// Fall through to the owned runtime below.
|
|
318
|
+
}
|
|
319
|
+
if (!found) {
|
|
273
320
|
const base = path.join(PB_DIR, 'semantic', 'node_modules', '@huggingface', 'transformers', 'dist');
|
|
274
|
-
found = ['transformers.node.mjs', 'transformers.mjs']
|
|
275
|
-
|
|
276
|
-
});
|
|
321
|
+
found = ['transformers.node.mjs', 'transformers.mjs']
|
|
322
|
+
.some(f => Boolean(semanticRuntimeEntryIfSafe(path.join(base, f))));
|
|
277
323
|
}
|
|
278
324
|
runtimeInstalledCache = found;
|
|
279
325
|
return found;
|