@nxuss/lemma 1.11.0 → 1.14.0
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 +98 -821
- package/dist/cjs/cli/lemma-proxy.d.ts.map +1 -1
- package/dist/cjs/cli/lemma-proxy.js +14 -0
- package/dist/cjs/cli/lemma-proxy.js.map +1 -1
- package/dist/cjs/infra/mcp-tools.d.ts +7 -0
- package/dist/cjs/infra/mcp-tools.d.ts.map +1 -1
- package/dist/cjs/infra/mcp-tools.js +22 -0
- package/dist/cjs/infra/mcp-tools.js.map +1 -1
- package/dist/cjs/mcp/index.js +35 -7
- package/dist/cjs/mcp/index.js.map +1 -1
- package/dist/cjs/mcp/prompts.d.ts +1 -0
- package/dist/cjs/mcp/prompts.d.ts.map +1 -1
- package/dist/cjs/mcp/prompts.js +98 -0
- package/dist/cjs/mcp/prompts.js.map +1 -1
- package/dist/cjs/mcp/resources.d.ts +2 -0
- package/dist/cjs/mcp/resources.d.ts.map +1 -1
- package/dist/cjs/mcp/resources.js +26 -0
- package/dist/cjs/mcp/resources.js.map +1 -1
- package/dist/cjs/mcp/tasks.d.ts +20 -0
- package/dist/cjs/mcp/tasks.d.ts.map +1 -0
- package/dist/cjs/mcp/tasks.js +71 -0
- package/dist/cjs/mcp/tasks.js.map +1 -0
- package/dist/cjs/mcp/tool-profiles.d.ts.map +1 -1
- package/dist/cjs/mcp/tool-profiles.js +29 -50
- package/dist/cjs/mcp/tool-profiles.js.map +1 -1
- package/dist/cjs/mcp/tools.d.ts.map +1 -1
- package/dist/cjs/mcp/tools.js +575 -93
- package/dist/cjs/mcp/tools.js.map +1 -1
- package/dist/cjs/proxy/Gatekeeper.d.ts +29 -0
- package/dist/cjs/proxy/Gatekeeper.d.ts.map +1 -1
- package/dist/cjs/proxy/Gatekeeper.js +122 -1
- package/dist/cjs/proxy/Gatekeeper.js.map +1 -1
- package/dist/cjs/subconscious/TheBrainV2.d.ts +50 -1
- package/dist/cjs/subconscious/TheBrainV2.d.ts.map +1 -1
- package/dist/cjs/subconscious/TheBrainV2.js +149 -8
- package/dist/cjs/subconscious/TheBrainV2.js.map +1 -1
- package/dist/cjs/utils/PatchMatcher.d.ts +1 -0
- package/dist/cjs/utils/PatchMatcher.d.ts.map +1 -1
- package/dist/cjs/utils/PatchMatcher.js +4 -4
- package/dist/cjs/utils/PatchMatcher.js.map +1 -1
- package/dist/esm/cli/lemma-proxy.d.ts.map +1 -1
- package/dist/esm/cli/lemma-proxy.js +14 -0
- package/dist/esm/cli/lemma-proxy.js.map +1 -1
- package/dist/esm/infra/mcp-tools.d.ts +7 -0
- package/dist/esm/infra/mcp-tools.d.ts.map +1 -1
- package/dist/esm/infra/mcp-tools.js +22 -0
- package/dist/esm/infra/mcp-tools.js.map +1 -1
- package/dist/esm/mcp/index.js +37 -9
- package/dist/esm/mcp/index.js.map +1 -1
- package/dist/esm/mcp/prompts.d.ts +1 -0
- package/dist/esm/mcp/prompts.d.ts.map +1 -1
- package/dist/esm/mcp/prompts.js +95 -1
- package/dist/esm/mcp/prompts.js.map +1 -1
- package/dist/esm/mcp/resources.d.ts +2 -0
- package/dist/esm/mcp/resources.d.ts.map +1 -1
- package/dist/esm/mcp/resources.js +27 -2
- package/dist/esm/mcp/resources.js.map +1 -1
- package/dist/esm/mcp/tasks.d.ts +20 -0
- package/dist/esm/mcp/tasks.d.ts.map +1 -0
- package/dist/esm/mcp/tasks.js +66 -0
- package/dist/esm/mcp/tasks.js.map +1 -0
- package/dist/esm/mcp/tool-profiles.d.ts.map +1 -1
- package/dist/esm/mcp/tool-profiles.js +29 -50
- package/dist/esm/mcp/tool-profiles.js.map +1 -1
- package/dist/esm/mcp/tools.d.ts.map +1 -1
- package/dist/esm/mcp/tools.js +577 -95
- package/dist/esm/mcp/tools.js.map +1 -1
- package/dist/esm/proxy/Gatekeeper.d.ts +29 -0
- package/dist/esm/proxy/Gatekeeper.d.ts.map +1 -1
- package/dist/esm/proxy/Gatekeeper.js +120 -0
- package/dist/esm/proxy/Gatekeeper.js.map +1 -1
- package/dist/esm/subconscious/TheBrainV2.d.ts +50 -1
- package/dist/esm/subconscious/TheBrainV2.d.ts.map +1 -1
- package/dist/esm/subconscious/TheBrainV2.js +149 -8
- package/dist/esm/subconscious/TheBrainV2.js.map +1 -1
- package/dist/esm/utils/PatchMatcher.d.ts +1 -0
- package/dist/esm/utils/PatchMatcher.d.ts.map +1 -1
- package/dist/esm/utils/PatchMatcher.js +4 -4
- package/dist/esm/utils/PatchMatcher.js.map +1 -1
- package/package.json +2 -2
|
@@ -17,6 +17,18 @@ export interface GatekeeperStatus {
|
|
|
17
17
|
isPro: boolean;
|
|
18
18
|
licenseKey: string | null;
|
|
19
19
|
}
|
|
20
|
+
export type InferenceMode = 'cloud' | 'hybrid' | 'airgapped';
|
|
21
|
+
export interface EgressDecision {
|
|
22
|
+
allowed: boolean;
|
|
23
|
+
mode: InferenceMode;
|
|
24
|
+
host: string;
|
|
25
|
+
reason: string;
|
|
26
|
+
}
|
|
27
|
+
export declare class EgressBlockedError extends Error {
|
|
28
|
+
readonly decision: EgressDecision;
|
|
29
|
+
code: "EGRESS_BLOCKED";
|
|
30
|
+
constructor(decision: EgressDecision);
|
|
31
|
+
}
|
|
20
32
|
export interface CacheBackend {
|
|
21
33
|
set(key: string, input: string, data: any, ttl: number): Promise<void>;
|
|
22
34
|
findSimilar(input: string, threshold: number): Promise<{
|
|
@@ -32,7 +44,24 @@ export declare class Gatekeeper extends EventEmitter {
|
|
|
32
44
|
private memBackend;
|
|
33
45
|
private semBackend;
|
|
34
46
|
private semInitialized;
|
|
47
|
+
private inferenceMode;
|
|
48
|
+
private allowedEndpoints;
|
|
35
49
|
constructor(keyManager: KeyManager);
|
|
50
|
+
private loadInferencePolicy;
|
|
51
|
+
getInferenceStatus(): {
|
|
52
|
+
mode: InferenceMode;
|
|
53
|
+
allowedEndpoints: string[];
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Central egress decision. Called once per outbound provider request from
|
|
57
|
+
* lemma-proxy.ts — no call site talks to a provider without going through this.
|
|
58
|
+
*/
|
|
59
|
+
checkEgress(urlOrHost: string): EgressDecision;
|
|
60
|
+
/**
|
|
61
|
+
* Throws EgressBlockedError on denial, and emits 'egress-blocked' so callers
|
|
62
|
+
* (e.g. the audit/token_receipt log) can record the attempt for compliance.
|
|
63
|
+
*/
|
|
64
|
+
assertEgressAllowed(urlOrHost: string): void;
|
|
36
65
|
getBackend(): Promise<CacheBackend>;
|
|
37
66
|
getMode(): CacheMode;
|
|
38
67
|
getStatus(): GatekeeperStatus;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Gatekeeper.d.ts","sourceRoot":"","sources":["../../../src/proxy/Gatekeeper.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,KAAK,CAAC;AAE3C,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,SAAS,CAAC;IAChB,eAAe,EAAE,OAAO,CAAC;IACzB,KAAK,EAAE,OAAO,CAAC;IACf,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,GAAG,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IACjG,IAAI,IAAI,MAAM,CAAC;IACf,KAAK,IAAI,IAAI,CAAC;CACf;AAED,qBAAa,UAAW,SAAQ,YAAY;IAC1C,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,QAAQ,CAA0B;IAC1C,OAAO,CAAC,UAAU,CAA6B;IAC/C,OAAO,CAAC,UAAU,CAA6B;IAC/C,OAAO,CAAC,cAAc,CAAS;
|
|
1
|
+
{"version":3,"file":"Gatekeeper.d.ts","sourceRoot":"","sources":["../../../src/proxy/Gatekeeper.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,KAAK,CAAC;AAE3C,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,SAAS,CAAC;IAChB,eAAe,EAAE,OAAO,CAAC;IACzB,KAAK,EAAE,OAAO,CAAC;IACf,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAmBD,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,QAAQ,GAAG,WAAW,CAAC;AAE7D,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,aAAa,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,kBAAmB,SAAQ,KAAK;aAEf,QAAQ,EAAE,cAAc;IADpD,IAAI,EAAG,gBAAgB,CAAU;gBACL,QAAQ,EAAE,cAAc;CAOrD;AA0CD,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,GAAG,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IACjG,IAAI,IAAI,MAAM,CAAC;IACf,KAAK,IAAI,IAAI,CAAC;CACf;AAED,qBAAa,UAAW,SAAQ,YAAY;IAC1C,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,QAAQ,CAA0B;IAC1C,OAAO,CAAC,UAAU,CAA6B;IAC/C,OAAO,CAAC,UAAU,CAA6B;IAC/C,OAAO,CAAC,cAAc,CAAS;IAE/B,OAAO,CAAC,aAAa,CAA0B;IAC/C,OAAO,CAAC,gBAAgB,CAA0B;gBAEtC,UAAU,EAAE,UAAU;IAMlC,OAAO,CAAC,mBAAmB;IAsB3B,kBAAkB;;;;IAOlB;;;OAGG;IACH,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc;IAgC9C;;;OAGG;IACH,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAStC,UAAU,IAAI,OAAO,CAAC,YAAY,CAAC;IAazC,OAAO,IAAI,SAAS;IAIpB,SAAS,IAAI,gBAAgB;IAK7B,MAAM,IAAI,IAAI;IAKd,OAAO,CAAC,gBAAgB;YAKV,kBAAkB;CAejC"}
|
|
@@ -9,6 +9,57 @@
|
|
|
9
9
|
* Emits 'mode-changed' when the effective tier switches.
|
|
10
10
|
*/
|
|
11
11
|
import { EventEmitter } from 'events';
|
|
12
|
+
export class EgressBlockedError extends Error {
|
|
13
|
+
constructor(decision) {
|
|
14
|
+
super(`[Gatekeeper] Blocked outbound request to "${decision.host}" ` +
|
|
15
|
+
`(LEMMA_INFERENCE_MODE=${decision.mode}): ${decision.reason}`);
|
|
16
|
+
this.decision = decision;
|
|
17
|
+
this.code = 'EGRESS_BLOCKED';
|
|
18
|
+
this.name = 'EgressBlockedError';
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
// Public LLM provider hosts we recognize by default. Not exhaustive — enterprises
|
|
22
|
+
// extend this via LEMMA_ALLOWED_ENDPOINTS (allow) rather than us maintaining a
|
|
23
|
+
// perfect blocklist (deny-lists always miss something; this list only needs to
|
|
24
|
+
// cover the hosts Lemma itself dials directly, see lemma-proxy.ts callUpstream).
|
|
25
|
+
const KNOWN_PUBLIC_LLM_HOSTS = [
|
|
26
|
+
'api.openai.com',
|
|
27
|
+
'api.anthropic.com',
|
|
28
|
+
'generativelanguage.googleapis.com',
|
|
29
|
+
'api.mistral.ai',
|
|
30
|
+
'api.cohere.ai',
|
|
31
|
+
];
|
|
32
|
+
function parseAllowedEndpoints(raw) {
|
|
33
|
+
if (!raw)
|
|
34
|
+
return new Set();
|
|
35
|
+
return new Set(raw.split(',').map(h => h.trim().toLowerCase()).filter(Boolean));
|
|
36
|
+
}
|
|
37
|
+
function hostOf(urlOrHost) {
|
|
38
|
+
try {
|
|
39
|
+
return new URL(urlOrHost).hostname.toLowerCase();
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
// Already a bare hostname (e.g. from a config value, not a full URL)
|
|
43
|
+
return urlOrHost.toLowerCase().replace(/:\d+$/, '');
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function isPrivateHost(host) {
|
|
47
|
+
if (host === 'localhost' || host === '127.0.0.1' || host === '::1')
|
|
48
|
+
return true;
|
|
49
|
+
if (host.endsWith('.local') || host.endsWith('.internal'))
|
|
50
|
+
return true;
|
|
51
|
+
const m = host.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/);
|
|
52
|
+
if (!m)
|
|
53
|
+
return false;
|
|
54
|
+
const [a, b] = [parseInt(m[1], 10), parseInt(m[2], 10)];
|
|
55
|
+
if (a === 10)
|
|
56
|
+
return true; // 10.0.0.0/8
|
|
57
|
+
if (a === 172 && b >= 16 && b <= 31)
|
|
58
|
+
return true; // 172.16.0.0/12
|
|
59
|
+
if (a === 192 && b === 168)
|
|
60
|
+
return true; // 192.168.0.0/16
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
12
63
|
export class Gatekeeper extends EventEmitter {
|
|
13
64
|
constructor(keyManager) {
|
|
14
65
|
super();
|
|
@@ -16,7 +67,75 @@ export class Gatekeeper extends EventEmitter {
|
|
|
16
67
|
this.memBackend = null;
|
|
17
68
|
this.semBackend = null;
|
|
18
69
|
this.semInitialized = false;
|
|
70
|
+
this.inferenceMode = 'cloud';
|
|
71
|
+
this.allowedEndpoints = new Set();
|
|
19
72
|
this.keyManager = keyManager;
|
|
73
|
+
this.loadInferencePolicy();
|
|
74
|
+
}
|
|
75
|
+
loadInferencePolicy() {
|
|
76
|
+
const envValue = process.env.LEMMA_INFERENCE_MODE;
|
|
77
|
+
const raw = (envValue || 'cloud').toLowerCase();
|
|
78
|
+
this.allowedEndpoints = parseAllowedEndpoints(process.env.LEMMA_ALLOWED_ENDPOINTS);
|
|
79
|
+
if (raw === 'cloud' || raw === 'hybrid' || raw === 'airgapped') {
|
|
80
|
+
this.inferenceMode = raw;
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
// LEMMA_INFERENCE_MODE was set to something we don't recognize (typo, stale
|
|
84
|
+
// value, etc). Unset defaults to "cloud" for backward compatibility, but a
|
|
85
|
+
// *garbled* value must not silently fall back to the unrestricted mode — that
|
|
86
|
+
// would let a typo quietly disable the one thing enterprises deploy this for.
|
|
87
|
+
// Fail closed to the strictest mode instead.
|
|
88
|
+
this.inferenceMode = 'airgapped';
|
|
89
|
+
console.error(`[Gatekeeper] Unknown LEMMA_INFERENCE_MODE="${envValue}". Failing closed to "airgapped" ` +
|
|
90
|
+
`(only private hosts + LEMMA_ALLOWED_ENDPOINTS) until this is fixed to one of: cloud, hybrid, airgapped.`);
|
|
91
|
+
}
|
|
92
|
+
getInferenceStatus() {
|
|
93
|
+
return {
|
|
94
|
+
mode: this.inferenceMode,
|
|
95
|
+
allowedEndpoints: Array.from(this.allowedEndpoints),
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Central egress decision. Called once per outbound provider request from
|
|
100
|
+
* lemma-proxy.ts — no call site talks to a provider without going through this.
|
|
101
|
+
*/
|
|
102
|
+
checkEgress(urlOrHost) {
|
|
103
|
+
const host = hostOf(urlOrHost);
|
|
104
|
+
const mode = this.inferenceMode;
|
|
105
|
+
if (mode === 'cloud') {
|
|
106
|
+
return { allowed: true, mode, host, reason: 'LEMMA_INFERENCE_MODE=cloud (unrestricted)' };
|
|
107
|
+
}
|
|
108
|
+
if (this.allowedEndpoints.has(host)) {
|
|
109
|
+
return { allowed: true, mode, host, reason: 'host is in LEMMA_ALLOWED_ENDPOINTS' };
|
|
110
|
+
}
|
|
111
|
+
if (isPrivateHost(host)) {
|
|
112
|
+
return { allowed: true, mode, host, reason: 'private/local host' };
|
|
113
|
+
}
|
|
114
|
+
if (mode === 'hybrid' && !KNOWN_PUBLIC_LLM_HOSTS.includes(host)) {
|
|
115
|
+
// hybrid only blocks recognized public LLM providers; unknown hosts (e.g. a
|
|
116
|
+
// customer's own SaaS endpoint) pass through unless they opt into airgapped.
|
|
117
|
+
return { allowed: true, mode, host, reason: 'not a recognized public LLM provider host' };
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
allowed: false,
|
|
121
|
+
mode,
|
|
122
|
+
host,
|
|
123
|
+
reason: mode === 'airgapped'
|
|
124
|
+
? 'airgapped mode blocks all non-private hosts not in LEMMA_ALLOWED_ENDPOINTS'
|
|
125
|
+
: 'hybrid mode blocks known public LLM provider hosts not in LEMMA_ALLOWED_ENDPOINTS',
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Throws EgressBlockedError on denial, and emits 'egress-blocked' so callers
|
|
130
|
+
* (e.g. the audit/token_receipt log) can record the attempt for compliance.
|
|
131
|
+
*/
|
|
132
|
+
assertEgressAllowed(urlOrHost) {
|
|
133
|
+
const decision = this.checkEgress(urlOrHost);
|
|
134
|
+
if (!decision.allowed) {
|
|
135
|
+
this.emit('egress-blocked', { ...decision, timestamp: Date.now() });
|
|
136
|
+
console.warn(`[Gatekeeper] BLOCKED egress to ${decision.host} (mode=${decision.mode}): ${decision.reason}`);
|
|
137
|
+
throw new EgressBlockedError(decision);
|
|
138
|
+
}
|
|
20
139
|
}
|
|
21
140
|
async getBackend() {
|
|
22
141
|
const mode = this.getMode();
|
|
@@ -39,6 +158,7 @@ export class Gatekeeper extends EventEmitter {
|
|
|
39
158
|
}
|
|
40
159
|
reload() {
|
|
41
160
|
this.keyManager.reload();
|
|
161
|
+
this.loadInferencePolicy();
|
|
42
162
|
}
|
|
43
163
|
getMemoryBackend() {
|
|
44
164
|
if (!this.memBackend)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Gatekeeper.js","sourceRoot":"","sources":["../../../src/proxy/Gatekeeper.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Gatekeeper.js","sourceRoot":"","sources":["../../../src/proxy/Gatekeeper.ts"],"names":[],"mappings":"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"}
|
|
@@ -38,6 +38,12 @@ export interface BrainEntry {
|
|
|
38
38
|
* fix — the Brain can only ever suggest reuse, never warn "we already tried this."
|
|
39
39
|
*/
|
|
40
40
|
outcome?: 'confirmed' | 'failed';
|
|
41
|
+
/**
|
|
42
|
+
* Free-text domain tag (e.g. "auth", "billing") lifted from cognitive_map's current
|
|
43
|
+
* context at store time. Absent means untagged — those entries stay visible to every
|
|
44
|
+
* domain-scoped search rather than disappearing, same rationale as projectId above.
|
|
45
|
+
*/
|
|
46
|
+
domain?: string;
|
|
41
47
|
/**
|
|
42
48
|
* Absolute-path::symbolName -> sha256 of just that symbol's extracted source (via
|
|
43
49
|
* SymbolSurgicalContext), not the whole file. When a file has an entry here, freshness
|
|
@@ -55,6 +61,12 @@ export interface BrainEntry {
|
|
|
55
61
|
* still trustworthy instead of discarding (or blindly trusting) the whole thing.
|
|
56
62
|
*/
|
|
57
63
|
claims?: Claim[];
|
|
64
|
+
/**
|
|
65
|
+
* Count of explicit "this memory led me astray" signals via downvote(). Distinct from
|
|
66
|
+
* hits: hits means "this surfaced and looked relevant enough to reuse," demerits means
|
|
67
|
+
* "reuse turned out to be wrong." Absent/0 means never downvoted.
|
|
68
|
+
*/
|
|
69
|
+
demerits?: number;
|
|
58
70
|
}
|
|
59
71
|
export interface Claim {
|
|
60
72
|
id: string;
|
|
@@ -89,6 +101,7 @@ export interface BrainSearchResult {
|
|
|
89
101
|
staleFiles?: string[];
|
|
90
102
|
outcome?: 'confirmed' | 'failed';
|
|
91
103
|
claims?: ClaimFreshness[];
|
|
104
|
+
domain?: string;
|
|
92
105
|
}
|
|
93
106
|
export interface BrainSearchOptions {
|
|
94
107
|
/**
|
|
@@ -99,6 +112,8 @@ export interface BrainSearchOptions {
|
|
|
99
112
|
countStats?: boolean;
|
|
100
113
|
/** Prefer memories from this project. See the scoping note in search(). */
|
|
101
114
|
projectId?: string;
|
|
115
|
+
/** Prefer memories tagged with this domain. Same soft-fallback rule as projectId. */
|
|
116
|
+
domain?: string;
|
|
102
117
|
}
|
|
103
118
|
export interface BrainStats {
|
|
104
119
|
totalEntries: number;
|
|
@@ -156,11 +171,33 @@ export declare class TheBrainV2 {
|
|
|
156
171
|
* Store a query+response pair in the brain.
|
|
157
172
|
* Returns false if detected as duplicate (>= dupThreshold similarity).
|
|
158
173
|
*/
|
|
159
|
-
store(query: string, response: string, provider?: string, dupThreshold?: number, filePaths?: string[], projectId?: string, outcome?: 'confirmed' | 'failed', symbolRefs?: SymbolRef[], claimInputs?: ClaimInput[]): {
|
|
174
|
+
store(query: string, response: string, provider?: string, dupThreshold?: number, filePaths?: string[], projectId?: string, outcome?: 'confirmed' | 'failed', symbolRefs?: SymbolRef[], claimInputs?: ClaimInput[], domain?: string): {
|
|
160
175
|
stored: boolean;
|
|
161
176
|
reason: string;
|
|
162
177
|
duplicate?: BrainSearchResult;
|
|
178
|
+
conflicts?: Array<{
|
|
179
|
+
id: string;
|
|
180
|
+
query: string;
|
|
181
|
+
outcome: 'confirmed' | 'failed';
|
|
182
|
+
}>;
|
|
163
183
|
};
|
|
184
|
+
/**
|
|
185
|
+
* Hard cap on entry count. Past this, the inverted index keeps growing and old, unused
|
|
186
|
+
* entries dilute every future BM25 IDF calculation (more docs sharing a term → lower
|
|
187
|
+
* signal) without ever being asked for again. Evicting keeps ranking quality from
|
|
188
|
+
* degrading as the Brain accumulates months of memories.
|
|
189
|
+
*/
|
|
190
|
+
private static readonly MAX_ENTRIES;
|
|
191
|
+
/** How many entries to evict per pass once over MAX_ENTRIES — batched, not one-at-a-time. */
|
|
192
|
+
private static readonly EVICT_BATCH;
|
|
193
|
+
/**
|
|
194
|
+
* Evict the lowest-value entries once the Brain is over capacity. Value = hits (proven
|
|
195
|
+
* usefulness) with a mild recency tiebreak — never based on similarity to any one query,
|
|
196
|
+
* since an entry unrelated to today's search may still be exactly what tomorrow's needs.
|
|
197
|
+
* Failed-outcome entries are cheap to keep (they're short, deliberate warnings) so they're
|
|
198
|
+
* evicted last among equally-unused entries rather than first.
|
|
199
|
+
*/
|
|
200
|
+
private evictIfOverCapacity;
|
|
164
201
|
/**
|
|
165
202
|
* Search brain using BM25 + Jaccard re-ranking.
|
|
166
203
|
* Returns results with similarity scores normalized to 0-1.
|
|
@@ -180,6 +217,18 @@ export declare class TheBrainV2 {
|
|
|
180
217
|
similarity: number;
|
|
181
218
|
existing?: BrainSearchResult;
|
|
182
219
|
};
|
|
220
|
+
/**
|
|
221
|
+
* Record that a specific memory turned out NOT to help — the caller acted on it and it
|
|
222
|
+
* was wrong, misleading, or irrelevant despite ranking well. Unlike `outcome: 'failed'`
|
|
223
|
+
* (set at store time, about the underlying approach), this is set after the fact, about
|
|
224
|
+
* the memory's usefulness as a search result. Lowers future ranking and eviction priority
|
|
225
|
+
* without deleting the entry — a bad-fit-today memory may still be exactly right for a
|
|
226
|
+
* differently-phrased query tomorrow.
|
|
227
|
+
*/
|
|
228
|
+
downvote(id: string): {
|
|
229
|
+
ok: boolean;
|
|
230
|
+
message: string;
|
|
231
|
+
};
|
|
183
232
|
getStats(): BrainStats;
|
|
184
233
|
clear(): void;
|
|
185
234
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TheBrainV2.d.ts","sourceRoot":"","sources":["../../../src/subconscious/TheBrainV2.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAUH,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAInB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,WAAW,GAAG,QAAQ,CAAC;IACjC;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"TheBrainV2.d.ts","sourceRoot":"","sources":["../../../src/subconscious/TheBrainV2.ts"],"names":[],"mappings":"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"}
|
|
@@ -129,7 +129,37 @@ export function tokenize(text) {
|
|
|
129
129
|
// the same index bucket. Purely additive: old entries that predate this still match on
|
|
130
130
|
// their original terms exactly as before, they just don't get the extra recall.
|
|
131
131
|
const stems = terms.map(stem).filter(s => s !== undefined);
|
|
132
|
-
|
|
132
|
+
// 7. Add a shared cluster tag for known dev-vocabulary synonyms (bilingual) so "jwt
|
|
133
|
+
// expiration" and "token timeout" land on a common term without needing embeddings.
|
|
134
|
+
// Purely additive, same rationale as stems — never replaces the surface form, so it
|
|
135
|
+
// can only add recall, never hide an existing exact match.
|
|
136
|
+
const synonymTags = terms
|
|
137
|
+
.map(t => SYNONYM_CLUSTERS.get(t))
|
|
138
|
+
.filter((c) => c !== undefined);
|
|
139
|
+
return [...new Set([...terms, ...bigrams, ...stems, ...synonymTags])];
|
|
140
|
+
}
|
|
141
|
+
// Groups of interchangeable dev-vocabulary terms (bilingual). Each member maps to a shared
|
|
142
|
+
// `syn_<canonical>` token so any two synonyms in the same group become a shared index bucket
|
|
143
|
+
// — a cheap substitute for embeddings when the gap is "different word, same concept" rather
|
|
144
|
+
// than true paraphrase. Keep groups small and unambiguous; a bad merge can only add a false
|
|
145
|
+
// candidate (never hide a real exact match), but it does dilute BM25 signal if overused.
|
|
146
|
+
const SYNONYM_GROUPS = [
|
|
147
|
+
['jwt', 'token', 'session', 'auth', 'login', 'autenticacion', 'sesion', 'autenticar'],
|
|
148
|
+
['timeout', 'expiration', 'expiry', 'vencimiento', 'caducidad', 'expirar', 'vencer'],
|
|
149
|
+
['bug', 'error', 'fallo', 'falla', 'issue', 'defect', 'defecto'],
|
|
150
|
+
['fix', 'patch', 'solucion', 'solucionar', 'arreglar', 'corregir', 'hotfix'],
|
|
151
|
+
['delete', 'remove', 'eliminar', 'borrar', 'quitar'],
|
|
152
|
+
['config', 'configuration', 'configuracion', 'settings', 'ajustes'],
|
|
153
|
+
['deploy', 'deployment', 'despliegue', 'desplegar', 'release'],
|
|
154
|
+
['crash', 'exception', 'excepcion', 'throw', 'falla'],
|
|
155
|
+
['slow', 'lento', 'lentitud', 'latency', 'latencia', 'performance', 'rendimiento'],
|
|
156
|
+
['test', 'tests', 'testing', 'prueba', 'pruebas', 'spec'],
|
|
157
|
+
];
|
|
158
|
+
const SYNONYM_CLUSTERS = new Map();
|
|
159
|
+
for (const group of SYNONYM_GROUPS) {
|
|
160
|
+
const canonical = `syn_${group[0]}`;
|
|
161
|
+
for (const member of group)
|
|
162
|
+
SYNONYM_CLUSTERS.set(member, canonical);
|
|
133
163
|
}
|
|
134
164
|
// Suffix-stripping rules, longest/most-specific match first. Additive expansion only —
|
|
135
165
|
// this is not a correctness-critical stemmer, so mild over-stemming (merging two distinct
|
|
@@ -470,7 +500,7 @@ export class TheBrainV2 {
|
|
|
470
500
|
* Store a query+response pair in the brain.
|
|
471
501
|
* Returns false if detected as duplicate (>= dupThreshold similarity).
|
|
472
502
|
*/
|
|
473
|
-
store(query, response, provider = 'generic', dupThreshold = 0.92, filePaths, projectId = deriveProjectId(), outcome, symbolRefs, claimInputs) {
|
|
503
|
+
store(query, response, provider = 'generic', dupThreshold = 0.92, filePaths, projectId = deriveProjectId(), outcome, symbolRefs, claimInputs, domain) {
|
|
474
504
|
// Quick bloom check
|
|
475
505
|
const queryKey = query.trim().toLowerCase().substring(0, 200);
|
|
476
506
|
if (this.bloom.has(queryKey)) {
|
|
@@ -484,6 +514,28 @@ export class TheBrainV2 {
|
|
|
484
514
|
};
|
|
485
515
|
}
|
|
486
516
|
}
|
|
517
|
+
// Conflict check: another entry about the exact same symbol, with the opposite
|
|
518
|
+
// outcome, is worth flagging before this one is even written — two memories about one
|
|
519
|
+
// function disagreeing on whether an approach works is a trap for whoever searches next.
|
|
520
|
+
// Not a block, just a warning: the newer entry may legitimately supersede the older one.
|
|
521
|
+
let conflicts;
|
|
522
|
+
if (symbolRefs && symbolRefs.length > 0) {
|
|
523
|
+
const newKeys = new Set(symbolRefs.map((r) => `${path.resolve(r.filePath)}::${r.symbolName}`));
|
|
524
|
+
const newOutcome = outcome === 'failed' ? 'failed' : 'confirmed';
|
|
525
|
+
const found = [];
|
|
526
|
+
for (const existingEntry of this.entries.values()) {
|
|
527
|
+
if (!existingEntry.symbolHashes)
|
|
528
|
+
continue;
|
|
529
|
+
const existingOutcome = existingEntry.outcome === 'failed' ? 'failed' : 'confirmed';
|
|
530
|
+
if (existingOutcome === newOutcome)
|
|
531
|
+
continue;
|
|
532
|
+
const sharesSymbol = Object.keys(existingEntry.symbolHashes).some((k) => newKeys.has(k));
|
|
533
|
+
if (sharesSymbol)
|
|
534
|
+
found.push({ id: existingEntry.id, query: existingEntry.query, outcome: existingOutcome });
|
|
535
|
+
}
|
|
536
|
+
if (found.length > 0)
|
|
537
|
+
conflicts = found;
|
|
538
|
+
}
|
|
487
539
|
const terms = tokenize(query + ' ' + response);
|
|
488
540
|
const termFreq = termFrequencies(terms);
|
|
489
541
|
const id = crypto
|
|
@@ -506,6 +558,7 @@ export class TheBrainV2 {
|
|
|
506
558
|
outcome,
|
|
507
559
|
symbolHashes: symbolRefs && symbolRefs.length > 0 ? hashSymbolsForFreshness(symbolRefs) : undefined,
|
|
508
560
|
claims: claimInputs && claimInputs.length > 0 ? buildClaims(claimInputs) : undefined,
|
|
561
|
+
domain,
|
|
509
562
|
};
|
|
510
563
|
this.entries.set(id, entry);
|
|
511
564
|
// Update inverted index
|
|
@@ -518,8 +571,46 @@ export class TheBrainV2 {
|
|
|
518
571
|
// Update bloom
|
|
519
572
|
this.bloom.add(queryKey);
|
|
520
573
|
this.recalcAvgDocLength();
|
|
574
|
+
this.evictIfOverCapacity();
|
|
521
575
|
this.scheduleSave();
|
|
522
|
-
return { stored: true, reason: 'Stored successfully' };
|
|
576
|
+
return { stored: true, reason: 'Stored successfully', conflicts };
|
|
577
|
+
}
|
|
578
|
+
/**
|
|
579
|
+
* Evict the lowest-value entries once the Brain is over capacity. Value = hits (proven
|
|
580
|
+
* usefulness) with a mild recency tiebreak — never based on similarity to any one query,
|
|
581
|
+
* since an entry unrelated to today's search may still be exactly what tomorrow's needs.
|
|
582
|
+
* Failed-outcome entries are cheap to keep (they're short, deliberate warnings) so they're
|
|
583
|
+
* evicted last among equally-unused entries rather than first.
|
|
584
|
+
*/
|
|
585
|
+
evictIfOverCapacity() {
|
|
586
|
+
if (this.entries.size <= TheBrainV2.MAX_ENTRIES)
|
|
587
|
+
return;
|
|
588
|
+
const ranked = Array.from(this.entries.values()).sort((a, b) => {
|
|
589
|
+
// Net value = hits minus twice the demerits — a downvoted entry is worse than a
|
|
590
|
+
// merely-unused one, so it should be first out even if it has a few stale hits.
|
|
591
|
+
const aValue = a.hits - (a.demerits || 0) * 2;
|
|
592
|
+
const bValue = b.hits - (b.demerits || 0) * 2;
|
|
593
|
+
const aFailed = a.outcome === 'failed' ? 1 : 0;
|
|
594
|
+
const bFailed = b.outcome === 'failed' ? 1 : 0;
|
|
595
|
+
if (aValue !== bValue)
|
|
596
|
+
return aValue - bValue; // lower net value evicted first
|
|
597
|
+
if (aFailed !== bFailed)
|
|
598
|
+
return bFailed - aFailed; // confirmed evicted before failed, when tied on value
|
|
599
|
+
return new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime(); // older evicted first
|
|
600
|
+
});
|
|
601
|
+
const toEvict = ranked.slice(0, TheBrainV2.EVICT_BATCH);
|
|
602
|
+
for (const entry of toEvict) {
|
|
603
|
+
this.entries.delete(entry.id);
|
|
604
|
+
for (const term of entry.terms) {
|
|
605
|
+
const ids = this.invertedIndex.get(term);
|
|
606
|
+
if (!ids)
|
|
607
|
+
continue;
|
|
608
|
+
ids.delete(entry.id);
|
|
609
|
+
if (ids.size === 0)
|
|
610
|
+
this.invertedIndex.delete(term);
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
this.recalcAvgDocLength();
|
|
523
614
|
}
|
|
524
615
|
// ─── Search ───────────────────────────────────────────────────────────────
|
|
525
616
|
/**
|
|
@@ -594,11 +685,33 @@ export class TheBrainV2 {
|
|
|
594
685
|
}
|
|
595
686
|
// 4. Normalize BM25 to 0-1 range
|
|
596
687
|
const maxBm25 = Math.max(...scored.map(s => s.bm25), 1);
|
|
597
|
-
// 5. Combined score: 70% BM25 + 30% Jaccard
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
688
|
+
// 5. Combined score: 70% BM25 + 30% Jaccard, then adjust for signals BM25/Jaccard can't
|
|
689
|
+
// see on their own: a memory's own track record. Small and additive by design — none of
|
|
690
|
+
// these can turn an unrelated result into a top hit, they only reorder among already-
|
|
691
|
+
// relevant candidates.
|
|
692
|
+
const combined = scored.map(s => {
|
|
693
|
+
let similarity = (s.bm25 / maxBm25) * 0.7 + s.jaccard * 0.3;
|
|
694
|
+
// Popularity prior: entries other searches actually reused are more likely to be
|
|
695
|
+
// reused again. Log-scaled and capped at +0.08 so a handful of hits can't outrank a
|
|
696
|
+
// much better textual match.
|
|
697
|
+
similarity += Math.min(Math.log2(s.entry.hits + 1) * 0.02, 0.08);
|
|
698
|
+
// A documented dead end ranking above a working fix is actively harmful — it reads as
|
|
699
|
+
// a suggestion even with the "STALE"/"FAILED" label attached downstream. Demote, don't
|
|
700
|
+
// hide: the warning is still worth surfacing, just not first.
|
|
701
|
+
if (s.entry.outcome === 'failed')
|
|
702
|
+
similarity -= 0.15;
|
|
703
|
+
// Soft domain preference (see projectId scoping above for why this stays soft): an
|
|
704
|
+
// entry tagged with the requested domain is more likely relevant, but an untagged or
|
|
705
|
+
// cross-domain entry may still be the right answer.
|
|
706
|
+
if (options.domain && s.entry.domain === options.domain)
|
|
707
|
+
similarity += 0.05;
|
|
708
|
+
// Explicit negative feedback from downvote() — a caller saying "this was wrong" is a
|
|
709
|
+
// stronger, more deliberate signal than the absence of hits, so it outweighs the
|
|
710
|
+
// popularity prior above rather than just canceling it out.
|
|
711
|
+
if (s.entry.demerits)
|
|
712
|
+
similarity -= Math.min(s.entry.demerits * 0.06, 0.25);
|
|
713
|
+
return { entry: s.entry, similarity: Math.max(0, similarity) };
|
|
714
|
+
});
|
|
602
715
|
// 6. Sort and filter
|
|
603
716
|
combined.sort((a, b) => b.similarity - a.similarity);
|
|
604
717
|
const results = combined
|
|
@@ -618,6 +731,7 @@ export class TheBrainV2 {
|
|
|
618
731
|
...(fresh ? {} : { staleFiles }),
|
|
619
732
|
...(r.entry.outcome ? { outcome: r.entry.outcome } : {}),
|
|
620
733
|
...(claims && claims.length > 0 ? { claims } : {}),
|
|
734
|
+
...(r.entry.domain ? { domain: r.entry.domain } : {}),
|
|
621
735
|
};
|
|
622
736
|
});
|
|
623
737
|
// 7. Update hit counters — only for searches a caller actually asked a question with.
|
|
@@ -671,6 +785,23 @@ export class TheBrainV2 {
|
|
|
671
785
|
}
|
|
672
786
|
return { isDuplicate: false, similarity: sim };
|
|
673
787
|
}
|
|
788
|
+
// ─── Feedback ─────────────────────────────────────────────────────────────
|
|
789
|
+
/**
|
|
790
|
+
* Record that a specific memory turned out NOT to help — the caller acted on it and it
|
|
791
|
+
* was wrong, misleading, or irrelevant despite ranking well. Unlike `outcome: 'failed'`
|
|
792
|
+
* (set at store time, about the underlying approach), this is set after the fact, about
|
|
793
|
+
* the memory's usefulness as a search result. Lowers future ranking and eviction priority
|
|
794
|
+
* without deleting the entry — a bad-fit-today memory may still be exactly right for a
|
|
795
|
+
* differently-phrased query tomorrow.
|
|
796
|
+
*/
|
|
797
|
+
downvote(id) {
|
|
798
|
+
const entry = this.entries.get(id);
|
|
799
|
+
if (!entry)
|
|
800
|
+
return { ok: false, message: `No entry with id "${id}" in the Brain.` };
|
|
801
|
+
entry.demerits = (entry.demerits || 0) + 1;
|
|
802
|
+
this.scheduleSave();
|
|
803
|
+
return { ok: true, message: `Recorded negative feedback on entry "${id}" (demerits: ${entry.demerits}). It will rank lower and be evicted sooner.` };
|
|
804
|
+
}
|
|
674
805
|
// ─── Stats ────────────────────────────────────────────────────────────────
|
|
675
806
|
getStats() {
|
|
676
807
|
return {
|
|
@@ -700,6 +831,16 @@ export class TheBrainV2 {
|
|
|
700
831
|
catch { /* ignore */ }
|
|
701
832
|
}
|
|
702
833
|
}
|
|
834
|
+
// ─── Capacity / Pruning ─────────────────────────────────────────────────────
|
|
835
|
+
/**
|
|
836
|
+
* Hard cap on entry count. Past this, the inverted index keeps growing and old, unused
|
|
837
|
+
* entries dilute every future BM25 IDF calculation (more docs sharing a term → lower
|
|
838
|
+
* signal) without ever being asked for again. Evicting keeps ranking quality from
|
|
839
|
+
* degrading as the Brain accumulates months of memories.
|
|
840
|
+
*/
|
|
841
|
+
TheBrainV2.MAX_ENTRIES = 8000;
|
|
842
|
+
/** How many entries to evict per pass once over MAX_ENTRIES — batched, not one-at-a-time. */
|
|
843
|
+
TheBrainV2.EVICT_BATCH = 500;
|
|
703
844
|
// ─── Global singleton ────────────────────────────────────────────────────────
|
|
704
845
|
let _brain = null;
|
|
705
846
|
export function getBrain() {
|